From ecb1853d56f428c25f964c467a88b9b711fb194a Mon Sep 17 00:00:00 2001 From: Linus Dierheimer Date: Sun, 2 Jan 2022 18:42:58 +0100 Subject: [PATCH] Using EWMH to detect WM in X11 sessions --- src/detection/displayserver/wmde.c | 22 ++++++++- src/detection/displayserver/xlib.c | 76 ++++++++++++++++++++++++++++++ 2 files changed, 97 insertions(+), 1 deletion(-) diff --git a/src/detection/displayserver/wmde.c b/src/detection/displayserver/wmde.c index 71de49d67..0354d6c08 100644 --- a/src/detection/displayserver/wmde.c +++ b/src/detection/displayserver/wmde.c @@ -266,6 +266,13 @@ static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) return; } + env = getenv("DISPLAY"); + if(env != NULL && *env != '\0') + { + ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11); + return; + } + env = getenv("TERM"); if(env != NULL && *env != '\0') { @@ -308,7 +315,7 @@ static void getFromProcDir(const FFinstance* instance, FFDisplayServerResult* re if(result->wmPrettyName.length == 0) applyPrettyNameIfWM(result, processName.chars); - if(result->deProcessName.length > 0 && result->wmPrettyName.length > 0) + if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) break; } @@ -324,6 +331,19 @@ void ffdsDetectWMDE(const FFinstance* instance, FFDisplayServerResult* result) if(result->wmProtocolName.length == 0) getWMProtocolNameFromEnv(result); + //We don't want to detect anything in TTY + if(ffStrbufIgnCaseCompS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY) == 0) + return; + + //If we found the processName via display server, use it. + //This will set the pretty name if it is a known WM, otherwise the prettyName to the processName + if(result->wmProcessName.length > 0) + { + applyPrettyNameIfWM(result, result->wmProcessName.chars); + if(result->wmPrettyName.length == 0) + ffStrbufSet(&result->wmPrettyName, &result->wmProcessName); + } + const char* env = parseEnv(); //Connecting to a display server only gives WM results, not DE results. diff --git a/src/detection/displayserver/xlib.c b/src/detection/displayserver/xlib.c index 26b452c77..fbe2fb888 100644 --- a/src/detection/displayserver/xlib.c +++ b/src/detection/displayserver/xlib.c @@ -3,6 +3,70 @@ #ifdef FF_HAVE_X11 #include +typedef struct X11PropertyData +{ + FF_LIBRARY_SYMBOL(XInternAtom) + FF_LIBRARY_SYMBOL(XGetWindowProperty) +} X11PropertyData; + +static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Window window, const char* request) +{ + Atom requestAtom = data->ffXInternAtom(display, request, False); + if(requestAtom == None) + return NULL; + + Atom actualType; + unsigned long unused; + unsigned char* result = NULL; + + data->ffXGetWindowProperty( + display, + window, + requestAtom, + 0, + 64, + False, + AnyPropertyType, + &actualType, + (int*) &unused, + &unused, + &unused, + &result + ); + + return result; +} + +static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDisplayServerResult* result) +{ + if(result->wmProcessName.length > 0) + return; + + Window root = DefaultRootWindow(display); + if(root == None) + return; + + unsigned char* wmWindowID = x11GetProperty(data, display, root, "_NET_SUPPORTING_WM_CHECK"); + if(wmWindowID == NULL) + return; + + Window wmWindow = *(Window*) wmWindowID; + if(wmWindow == None) + return; + + unsigned char* wmName = x11GetProperty(data, display, wmWindow, "_NET_WM_NAME"); + if(wmName == NULL) + wmName = x11GetProperty(data, display, wmWindow, "WM_NAME"); + if(wmName == NULL) + return; + + const char* wmNameString = (const char*) wmName; + if(*wmNameString == '\0') + return; + + ffStrbufSetS(&result->wmProcessName, wmNameString); +} + static void x11AddScreenAsResult(FFlist* results, Screen* screen, uint32_t refreshRate) { if(WidthOfScreen(screen) == 0 || HeightOfScreen(screen) == 0) @@ -20,6 +84,10 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) FF_LIBRARY_LOAD_SYMBOL(x11, XOpenDisplay,) FF_LIBRARY_LOAD_SYMBOL(x11, XCloseDisplay,) + X11PropertyData propertyData; + FF_LIBRARY_LOAD_SYMBOL_ADRESS(x11, propertyData.ffXInternAtom, XInternAtom,) + FF_LIBRARY_LOAD_SYMBOL_ADRESS(x11, propertyData.ffXGetWindowProperty, XGetWindowProperty,) + Display* display = ffXOpenDisplay(x11); if(display == NULL) { @@ -30,6 +98,8 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result) for(int i = 0; i < ScreenCount(display); i++) x11AddScreenAsResult(&result->resolutions, ScreenOfDisplay(display, i), 0); + x11DetectWMFromEWMH(&propertyData, display, result); + ffXCloseDisplay(display); dlclose(x11); @@ -216,6 +286,10 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeMonitors, XRRFreeMonitors,); FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeScreenConfigInfo, XRRFreeScreenConfigInfo,); + X11PropertyData propertyData; + FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, propertyData.ffXInternAtom, XInternAtom,) + FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, propertyData.ffXGetWindowProperty, XGetWindowProperty,) + data.display = ffXOpenDisplay(NULL); if(data.display == NULL) { @@ -228,6 +302,8 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result for(int i = 0; i < ScreenCount(data.display); i++) xrandrHandleScreen(&data, ScreenOfDisplay(data.display, i)); + x11DetectWMFromEWMH(&propertyData, data.display, result); + ffXCloseDisplay(data.display); dlclose(xrandr);