From 6496dcd7d05da1e851830a416370a01268f7c245 Mon Sep 17 00:00:00 2001 From: Carter Li Date: Tue, 13 Jan 2026 09:24:27 +0800 Subject: [PATCH] DisplayServer (Linux): refactors property handling in xcb and xlib --- src/detection/displayserver/linux/xcb.c | 200 +++++++++++------------ src/detection/displayserver/linux/xlib.c | 80 ++++----- 2 files changed, 122 insertions(+), 158 deletions(-) diff --git a/src/detection/displayserver/linux/xcb.c b/src/detection/displayserver/linux/xcb.c index 3cc8a9953..7d24448b5 100644 --- a/src/detection/displayserver/linux/xcb.c +++ b/src/detection/displayserver/linux/xcb.c @@ -13,103 +13,6 @@ #include #include -typedef struct XcbPropertyData -{ - FF_LIBRARY_SYMBOL(xcb_intern_atom) - FF_LIBRARY_SYMBOL(xcb_intern_atom_reply) - FF_LIBRARY_SYMBOL(xcb_get_property) - 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_name_length) - FF_LIBRARY_SYMBOL(xcb_get_atom_name_reply) - FF_LIBRARY_SYMBOL(xcb_get_setup) - FF_LIBRARY_SYMBOL(xcb_setup_vendor) - FF_LIBRARY_SYMBOL(xcb_setup_vendor_length) -} XcbPropertyData; - -static bool xcbInitPropertyData(FF_MAYBE_UNUSED void* libraryHandle, XcbPropertyData* propertyData) -{ - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_intern_atom, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_intern_atom_reply, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_property, false) - 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_name_length, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_atom_name_reply, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_get_setup, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_setup_vendor, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, xcb_setup_vendor_length, false) - - return true; -} - -static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t window, const char* request) -{ - xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(connection, true, (uint16_t) strlen(request), request); - FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(connection, requestAtomCookie, NULL); - if(requestAtomReply == NULL) - return NULL; - - xcb_get_property_cookie_t propertyCookie = data->ffxcb_get_property(connection, false, window, requestAtomReply->atom, XCB_ATOM_ANY, 0, 8 * 1024); - - FF_AUTO_FREE xcb_get_property_reply_t* propertyReply = data->ffxcb_get_property_reply(connection, propertyCookie, NULL); - if(propertyReply == NULL) - return NULL; - - int length = data->ffxcb_get_property_value_length(propertyReply); - if(length <= 0) - return NULL; - - //Why are xcb property strings not null terminated??? - void* replyValue = malloc((size_t)length + 1); - memcpy(replyValue, data->ffxcb_get_property_value(propertyReply), (size_t) length); - ((char*) replyValue)[length] = '\0'; - - return replyValue; -} - -static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t rootWindow, FFDisplayServerResult* result) -{ - if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0) - return; - - FF_AUTO_FREE xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, connection, rootWindow, "_NET_SUPPORTING_WM_CHECK"); - if(wmWindow == NULL) - return; - - FF_AUTO_FREE char* wmName = (char*) xcbGetProperty(data, connection, *wmWindow, "WM_NAME"); - if(!ffStrSet(wmName)) - wmName = (char*) xcbGetProperty(data, connection, *wmWindow, "_NET_WM_NAME"); - - if(!ffStrSet(wmName)) - return; - - ffStrbufSetS(&result->wmProcessName, wmName); -} - -static void xcbFetchServerVendor(XcbPropertyData* data, xcb_connection_t* connection, FFDisplayServerResult* result) -{ - const xcb_setup_t* setup = data->ffxcb_get_setup(connection); - - int length = data->ffxcb_setup_vendor_length(setup); - if(length <= 0) - return; - - FF_STRBUF_AUTO_DESTROY serverVendor = ffStrbufCreateNS((uint32_t) length, data->ffxcb_setup_vendor(setup)); - - if (!ffStrbufEqualS(&serverVendor, "The X.Org Foundation")) // Original - { - ffStrbufDestroy(&result->wmProtocolName); - ffStrbufInitMove(&result->wmProtocolName, &serverVendor); - } -} - typedef struct XcbRandrData { FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_current) @@ -131,15 +34,86 @@ typedef struct XcbRandrData FF_LIBRARY_SYMBOL(xcb_randr_get_output_property_reply) FF_LIBRARY_SYMBOL(xcb_randr_get_output_property_data) FF_LIBRARY_SYMBOL(xcb_randr_get_output_property_data_length) + FF_LIBRARY_SYMBOL(xcb_intern_atom) FF_LIBRARY_SYMBOL(xcb_intern_atom_reply) + FF_LIBRARY_SYMBOL(xcb_get_property) + 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_name_length) + FF_LIBRARY_SYMBOL(xcb_get_atom_name_reply) + FF_LIBRARY_SYMBOL(xcb_get_setup) + FF_LIBRARY_SYMBOL(xcb_setup_vendor) + FF_LIBRARY_SYMBOL(xcb_setup_vendor_length) //init once xcb_connection_t* connection; FFDisplayServerResult* result; - XcbPropertyData propData; } XcbRandrData; +static void* xcbGetProperty(XcbRandrData* data, xcb_window_t window, const char* request) +{ + xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(data->connection, true, (uint16_t) strlen(request), request); + FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(data->connection, requestAtomCookie, NULL); + if(requestAtomReply == NULL) + return NULL; + + xcb_get_property_cookie_t propertyCookie = data->ffxcb_get_property(data->connection, false, window, requestAtomReply->atom, XCB_ATOM_ANY, 0, 8 * 1024); + FF_AUTO_FREE xcb_get_property_reply_t* propertyReply = data->ffxcb_get_property_reply(data->connection, propertyCookie, NULL); + if(propertyReply == NULL) + return NULL; + + int length = data->ffxcb_get_property_value_length(propertyReply); + if(length <= 0) + return NULL; + + //Why are xcb property strings not null terminated??? + void* replyValue = malloc((size_t)length + 1); + memcpy(replyValue, data->ffxcb_get_property_value(propertyReply), (size_t) length); + ((char*) replyValue)[length] = '\0'; + + return replyValue; +} + +static void xcbDetectWMfromEWMH(XcbRandrData* data, xcb_window_t rootWindow, FFDisplayServerResult* result) +{ + if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0) + return; + + FF_AUTO_FREE xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, rootWindow, "_NET_SUPPORTING_WM_CHECK"); + if(wmWindow == NULL) + return; + + FF_AUTO_FREE char* wmName = (char*) xcbGetProperty(data, *wmWindow, "WM_NAME"); + if(!ffStrSet(wmName)) + wmName = (char*) xcbGetProperty(data, *wmWindow, "_NET_WM_NAME"); + + if(!ffStrSet(wmName)) + return; + + ffStrbufSetS(&result->wmProcessName, wmName); +} + +static void xcbFetchServerVendor(XcbRandrData* data, FFDisplayServerResult* result) +{ + const xcb_setup_t* setup = data->ffxcb_get_setup(data->connection); + + int length = data->ffxcb_setup_vendor_length(setup); + if(length <= 0) + return; + + FF_STRBUF_AUTO_DESTROY serverVendor = ffStrbufCreateNS((uint32_t) length, data->ffxcb_setup_vendor(setup)); + + if (!ffStrbufEqualS(&serverVendor, "The X.Org Foundation")) // Original + { + ffStrbufDestroy(&result->wmProtocolName); + ffStrbufInitMove(&result->wmProtocolName, &serverVendor); + } +} + static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary, FFDisplayType displayType, struct xcb_randr_get_screen_resources_current_reply_t* screenResources, uint8_t bitDepth, double scaleFactor) { xcb_randr_get_output_info_cookie_t outputInfoCookie = data->ffxcb_randr_get_output_info(data->connection, output, XCB_CURRENT_TIME); @@ -251,14 +225,14 @@ 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( + FF_AUTO_FREE xcb_get_atom_name_reply_t* nameReply = data->ffxcb_get_atom_name_reply( data->connection, - data->propData.ffxcb_get_atom_name(data->connection, monitor->name), + data->ffxcb_get_atom_name(data->connection, monitor->name), NULL ); FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateNS( - (uint32_t) data->propData.ffxcb_get_atom_name_name_length(nameReply), - data->propData.ffxcb_get_atom_name_name(nameReply) + (uint32_t) data->ffxcb_get_atom_name_name_length(nameReply), + data->ffxcb_get_atom_name_name(nameReply) ); const FFDisplayType displayType = ffdsGetDisplayType(name.chars); @@ -306,7 +280,7 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen) FF_AUTO_FREE struct xcb_randr_get_screen_resources_current_reply_t* screenResources = data->ffxcb_randr_get_screen_resources_current_reply(data->connection, screenResourcesCookie, NULL); double scaleFactor = 1; - FF_AUTO_FREE const char* resourceManager = xcbGetProperty(&data->propData, data->connection, screen->root, "RESOURCE_MANAGER"); + FF_AUTO_FREE const char* resourceManager = xcbGetProperty(data, screen->root, "RESOURCE_MANAGER"); if (resourceManager) { FF_STRBUF_AUTO_DESTROY dpi = ffStrbufCreate(); @@ -369,6 +343,18 @@ const char* ffdsConnectXcbRandr(FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_intern_atom) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_intern_atom_reply) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_get_property) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_get_property_reply) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_get_property_value) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_get_property_value_length) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_get_atom_name) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_get_atom_name_name) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_get_atom_name_name_length) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_get_atom_name_reply) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_get_setup) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_setup_vendor) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_setup_vendor_length) + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_randr_get_screen_resources_current) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_randr_get_screen_resources_current_reply) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_randr_get_screen_resources_current_modes_iterator) @@ -389,8 +375,6 @@ const char* ffdsConnectXcbRandr(FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_randr_get_crtc_info) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_randr_get_crtc_info_reply) - bool propertyDataInitialized = xcbInitPropertyData(xcbRandr, &data.propData); - data.connection = ffxcb_connect(NULL, NULL); if(ffxcb_connection_has_error(data.connection) > 0) @@ -405,9 +389,9 @@ const char* ffdsConnectXcbRandr(FFDisplayServerResult* result) xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(data.connection)); - if(iterator.rem > 0 && propertyDataInitialized) { - xcbDetectWMfromEWMH(&data.propData, data.connection, iterator.data->root, result); - xcbFetchServerVendor(&data.propData, data.connection, result); + if(iterator.rem > 0) { + xcbDetectWMfromEWMH(&data, iterator.data->root, result); + xcbFetchServerVendor(&data, result); } diff --git a/src/detection/displayserver/linux/xlib.c b/src/detection/displayserver/linux/xlib.c index 6dd06bf17..9490b040d 100644 --- a/src/detection/displayserver/linux/xlib.c +++ b/src/detection/displayserver/linux/xlib.c @@ -10,25 +10,29 @@ #include #include -typedef struct X11PropertyData +typedef struct XrandrData { FF_LIBRARY_SYMBOL(XInternAtom) + FF_LIBRARY_SYMBOL(XGetAtomName); FF_LIBRARY_SYMBOL(XGetWindowProperty) FF_LIBRARY_SYMBOL(XServerVendor) - FF_LIBRARY_SYMBOL(XFree) -} X11PropertyData; + FF_LIBRARY_SYMBOL(XFree); + FF_LIBRARY_SYMBOL(XRRGetMonitors) + FF_LIBRARY_SYMBOL(XRRGetScreenResourcesCurrent) + FF_LIBRARY_SYMBOL(XRRGetOutputInfo) + FF_LIBRARY_SYMBOL(XRRGetOutputProperty) + FF_LIBRARY_SYMBOL(XRRGetCrtcInfo) + FF_LIBRARY_SYMBOL(XRRFreeCrtcInfo) + FF_LIBRARY_SYMBOL(XRRFreeOutputInfo) + FF_LIBRARY_SYMBOL(XRRFreeScreenResources) + FF_LIBRARY_SYMBOL(XRRFreeMonitors) -static bool x11InitPropertyData(FF_MAYBE_UNUSED void* libraryHandle, X11PropertyData* propertyData) -{ - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XInternAtom, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XGetWindowProperty, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XServerVendor, false) - FF_LIBRARY_LOAD_SYMBOL_PTR(libraryHandle, propertyData, XFree, false) + //Init once + Display* display; + FFDisplayServerResult* result; +} XrandrData; - return true; -} - -static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Window window, const char* request) +static unsigned char* x11GetProperty(XrandrData* data, Display* display, Window window, const char* request) { Atom requestAtom = data->ffXInternAtom(display, request, False); if(requestAtom == None) @@ -44,18 +48,18 @@ static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Wi return result; } -static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDisplayServerResult* result) +static void x11DetectWMFromEWMH(XrandrData* data, FFDisplayServerResult* result) { if(result->wmProcessName.length > 0 || ffStrbufCompS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND) == 0) return; - Window* wmWindow = (Window*) x11GetProperty(data, display, DefaultRootWindow(display), "_NET_SUPPORTING_WM_CHECK"); + Window* wmWindow = (Window*) x11GetProperty(data, data->display, DefaultRootWindow(data->display), "_NET_SUPPORTING_WM_CHECK"); if(wmWindow == NULL) return; - char* wmName = (char*) x11GetProperty(data, display, *wmWindow, "WM_NAME"); + char* wmName = (char*) x11GetProperty(data, data->display, *wmWindow, "WM_NAME"); if(!ffStrSet(wmName)) - wmName = (char*) x11GetProperty(data, display, *wmWindow, "_NET_WM_NAME"); + wmName = (char*) x11GetProperty(data, data->display, *wmWindow, "_NET_WM_NAME"); if(ffStrSet(wmName)) ffStrbufSetS(&result->wmProcessName, wmName); @@ -64,35 +68,13 @@ static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDispl data->ffXFree(wmWindow); } -static void x11FetchServerVendor(X11PropertyData* data, Display* display, FFDisplayServerResult* result) +static void x11FetchServerVendor(XrandrData* data, FFDisplayServerResult* result) { - const char* serverVendor = data->ffXServerVendor(display); - if (serverVendor && !ffStrEquals(serverVendor, "The X.Org Foundation")) { + const char* serverVendor = data->ffXServerVendor(data->display); + if (serverVendor && !ffStrEquals(serverVendor, "The X.Org Foundation")) ffStrbufSetS(&result->wmProtocolName, serverVendor); - } } -typedef struct XrandrData -{ - FF_LIBRARY_SYMBOL(XInternAtom) - FF_LIBRARY_SYMBOL(XGetAtomName); - FF_LIBRARY_SYMBOL(XFree); - FF_LIBRARY_SYMBOL(XRRGetMonitors) - FF_LIBRARY_SYMBOL(XRRGetScreenResourcesCurrent) - FF_LIBRARY_SYMBOL(XRRGetOutputInfo) - FF_LIBRARY_SYMBOL(XRRGetOutputProperty) - FF_LIBRARY_SYMBOL(XRRGetCrtcInfo) - FF_LIBRARY_SYMBOL(XRRFreeCrtcInfo) - FF_LIBRARY_SYMBOL(XRRFreeOutputInfo) - FF_LIBRARY_SYMBOL(XRRFreeScreenResources) - FF_LIBRARY_SYMBOL(XRRFreeMonitors) - - //Init once - Display* display; - FFDisplayServerResult* result; - X11PropertyData* propData; -} XrandrData; - static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength, XRRScreenResources* screenResources, uint8_t bitDepth, double scaleFactor) { //We do the check here, because we want the best fallback display if this call failed @@ -247,7 +229,7 @@ static bool xrandrHandleMonitors(XrandrData* data, Screen* screen) XRRScreenResources* screenResources = data->ffXRRGetScreenResourcesCurrent(data->display, RootWindowOfScreen(screen)); double scaleFactor = 1; - char* resourceManager = (char*) x11GetProperty(data->propData, data->display, screen->root, "RESOURCE_MANAGER"); + char* resourceManager = (char*) x11GetProperty(data, data->display, screen->root, "RESOURCE_MANAGER"); if (resourceManager) { FF_STRBUF_AUTO_DESTROY dpi = ffStrbufCreate(); @@ -307,6 +289,8 @@ const char* ffdsConnectXrandr(FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XInternAtom); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XGetAtomName); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XGetWindowProperty); + FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XServerVendor); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XFree); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetMonitors); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRGetScreenResourcesCurrent); @@ -318,17 +302,13 @@ const char* ffdsConnectXrandr(FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRFreeScreenResources); FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRFreeMonitors); - X11PropertyData propertyData; - bool propertyDataInitialized = x11InitPropertyData(xrandr, &propertyData); - data.propData = &propertyData; - data.display = ffXOpenDisplay(NULL); if(data.display == NULL) return "XOpenDisplay() failed"; - if(propertyDataInitialized && ScreenCount(data.display) > 0) { - x11DetectWMFromEWMH(&propertyData, data.display, result); - x11FetchServerVendor(&propertyData, data.display, result); + if(ScreenCount(data.display) > 0) { + x11DetectWMFromEWMH(&data, result); + x11FetchServerVendor(&data, result); } data.result = result;