From 59ec3ca69754aab6b0e79a11e01e7cda3a6500f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 16 Jun 2023 10:21:53 +0800 Subject: [PATCH] Display (X11): detect rotation and name --- src/detection/displayserver/linux/xcb.c | 67 ++++++++++++++++++------ src/detection/displayserver/linux/xlib.c | 50 +++++++++--------- 2 files changed, 77 insertions(+), 40 deletions(-) diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index c81bf46db..96ed13b40 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -1,4 +1,5 @@ #include "displayserver_linux.h" +#include "util/mallocHelper.h" #ifdef FF_HAVE_XCB #include "common/library.h" @@ -14,6 +15,9 @@ typedef struct XcbPropertyData FF_LIBRARY_SYMBOL(xcb_get_property_reply) FF_LIBRARY_SYMBOL(xcb_get_property_value) FF_LIBRARY_SYMBOL(xcb_get_property_value_length) + FF_LIBRARY_SYMBOL(xcb_get_atom_name) + FF_LIBRARY_SYMBOL(xcb_get_atom_name_name) + FF_LIBRARY_SYMBOL(xcb_get_atom_name_reply) } XcbPropertyData; static bool xcbInitPropertyData(void* libraryHandle, XcbPropertyData* propertyData) @@ -24,6 +28,9 @@ static bool xcbInitPropertyData(void* libraryHandle, XcbPropertyData* propertyDa FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_property_reply, false) FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_property_value, false) FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_property_value_length, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_atom_name, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_atom_name_name, false) + FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_atom_name_reply, false) return true; } @@ -164,17 +171,19 @@ typedef struct XcbRandrData FF_LIBRARY_SYMBOL(xcb_randr_get_output_info_reply) FF_LIBRARY_SYMBOL(xcb_randr_get_crtc_info) FF_LIBRARY_SYMBOL(xcb_randr_get_crtc_info_reply) + FF_LIBRARY_SYMBOL(xcb_get_atom_name) //init once xcb_connection_t* connection; FFDisplayServerResult* result; + XcbPropertyData propData; //init per screen uint32_t defaultRefreshRate; xcb_randr_get_screen_resources_reply_t* screenResources; } XcbRandrData; -static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo) +static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo, FFstrbuf* name, uint32_t rotation) { double refreshRate = (double) modeInfo->dot_clock / (double) (modeInfo->htotal * modeInfo->vtotal); @@ -185,13 +194,13 @@ static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* mo refreshRate == 0 ? data->defaultRefreshRate : refreshRate, (uint32_t) modeInfo->width, (uint32_t) modeInfo->height, - 0, - NULL, + rotation, + name, FF_DISPLAY_TYPE_UNKNOWN ); } -static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode) +static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode, FFstrbuf* name, uint32_t rotation) { //We do the check here, because we want the best fallback display if this call failed if(data->screenResources == NULL) @@ -202,7 +211,7 @@ static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode) while(modesIterator.rem > 0) { if(modesIterator.data->id == mode) - return xcbRandrHandleModeInfo(data, modesIterator.data); + return xcbRandrHandleModeInfo(data, modesIterator.data, name, rotation); data->ffxcb_randr_mode_info_next(&modesIterator); } @@ -210,14 +219,30 @@ static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode) return false; } -static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc) +static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc, FFstrbuf* name) { xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME); xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL); if(crtcInfoReply == NULL) return false; - bool res = xcbRandrHandleMode(data, crtcInfoReply->mode); + uint32_t rotation; + switch (crtcInfoReply->rotation) + { + case XCB_RANDR_ROTATION_ROTATE_90: + rotation = 90; + break; + case XCB_RANDR_ROTATION_ROTATE_180: + rotation = 180; + break; + case XCB_RANDR_ROTATION_ROTATE_270: + rotation = 270; + break; + default: + rotation = 0; + break; + } + bool res = xcbRandrHandleMode(data, crtcInfoReply->mode, name, rotation); res = res ? true : ffdsAppendDisplay( data->result, (uint32_t) crtcInfoReply->width, @@ -225,8 +250,8 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc) data->defaultRefreshRate, (uint32_t) crtcInfoReply->width, (uint32_t) crtcInfoReply->height, - 0, - NULL, + rotation, + name, FF_DISPLAY_TYPE_UNKNOWN ); @@ -234,14 +259,14 @@ static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc) return res; } -static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output) +static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name) { xcb_randr_get_output_info_cookie_t outputInfoCookie = data->ffxcb_randr_get_output_info(data->connection, output, XCB_CURRENT_TIME); xcb_randr_get_output_info_reply_t* outputInfoReply = data->ffxcb_randr_get_output_info_reply(data->connection, outputInfoCookie, NULL); if(outputInfoReply == NULL) return false; - bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc); + bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc, name); free(outputInfoReply); @@ -257,11 +282,22 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* .rem = data->ffxcb_randr_monitor_info_outputs_length(monitor) }; + FF_AUTO_FREE xcb_get_atom_name_reply_t* nameReply = data->propData.ffxcb_get_atom_name_reply( + data->connection, + data->propData.ffxcb_get_atom_name(data->connection, monitor->name), + NULL + ); + char* buf = data->propData.ffxcb_get_atom_name_name(nameReply); + FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(buf); + // name.chars = buf; + // name.allocated = (uint32_t) strlen(buf); + // name.length = name.allocated; + bool foundOutput = false; while(outputIterator.rem > 0) { - if(xcbRandrHandleOutput(data, *outputIterator.data)) + if(xcbRandrHandleOutput(data, *outputIterator.data, &name)) foundOutput = true; data->ffxcb_randr_output_next(&outputIterator); }; @@ -274,7 +310,7 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* (uint32_t) monitor->width, (uint32_t) monitor->height, 0, - NULL, + &name, FF_DISPLAY_TYPE_UNKNOWN ); } @@ -371,8 +407,7 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_crtc_info,) FF_LIBRARY_LOAD_SYMBOL_VAR(xcbRandr, data, xcb_randr_get_crtc_info_reply,) - XcbPropertyData propertyData; - bool propertyDataInitialized = xcbInitPropertyData(xcbRandr, &propertyData); + bool propertyDataInitialized = xcbInitPropertyData(xcbRandr, &data.propData); data.connection = ffxcb_connect(NULL, NULL); if(data.connection == NULL) @@ -383,7 +418,7 @@ void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* resu xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(data.connection)); if(iterator.rem > 0 && propertyDataInitialized) - xcbDetectWMfromEWMH(&propertyData, data.connection, iterator.data->root, result); + xcbDetectWMfromEWMH(&data.propData, data.connection, iterator.data->root, result); while(iterator.rem > 0) { diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 56a72ddf5..69b9f55a1 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -133,31 +133,17 @@ typedef struct XrandrData XRRScreenResources* screenResources; } XrandrData; -static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo) -{ - double refreshRate = (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal); - - return ffdsAppendDisplay( - data->result, - (uint32_t) modeInfo->width, - (uint32_t) modeInfo->height, - refreshRate == 0 ? data->defaultRefreshRate : refreshRate, - (uint32_t) modeInfo->width, - (uint32_t) modeInfo->height, - 0, - NULL, - FF_DISPLAY_TYPE_UNKNOWN - ); -} - -static bool xrandrHandleMode(XrandrData* data, RRMode mode) +static double xrandrHandleMode(XrandrData* data, RRMode mode) { for(int i = 0; i < data->screenResources->nmode; i++) { if(data->screenResources->modes[i].id == mode) - return xrandrHandleModeInfo(data, &data->screenResources->modes[i]); + { + XRRModeInfo* modeInfo = &data->screenResources->modes[i]; + return (double) modeInfo->dotClock / (double) (modeInfo->hTotal * modeInfo->vTotal); + } } - return false; + return data->defaultRefreshRate; } static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc) @@ -170,15 +156,31 @@ static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc) if(crtcInfo == NULL) return false; - bool res = xrandrHandleMode(data, crtcInfo->mode); - res = res ? true : ffdsAppendDisplay( + uint32_t rotation; + switch (crtcInfo->rotation) + { + case RR_Rotate_90: + rotation = 90; + break; + case RR_Rotate_180: + rotation = 180; + break; + case RR_Rotate_270: + rotation = 270; + break; + default: + rotation = 0; + break; + } + + bool res = ffdsAppendDisplay( data->result, (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, - data->defaultRefreshRate, + xrandrHandleMode(data, crtcInfo->mode), (uint32_t) crtcInfo->width, (uint32_t) crtcInfo->height, - 0, + rotation, NULL, FF_DISPLAY_TYPE_UNKNOWN );