diff --git a/README.md b/README.md index 88261be06..c9dc4730a 100644 --- a/README.md +++ b/README.md @@ -34,12 +34,12 @@ Arch, Artix, Manjaro, Garuda, Debian, Ubuntu, Void Unknown/unsupported logos will be replaced with a question mark when running fastfetch. ### Package managers: ``` -Pacman, Flatpak +Pacman, Flatpak, xbps ``` ### Window managers: ``` -Kwin, Openbox, Muffin, XFWM, Wayfire +KWin, Mutter, Muffin, Openbox, Muffin, XFWM, Sway, Wayfire, Weston ``` ### Window manager themes: diff --git a/src/modules/wm.c b/src/modules/wm.c index 8d14d9d6d..58a790699 100644 --- a/src/modules/wm.c +++ b/src/modules/wm.c @@ -7,6 +7,13 @@ #define FF_WM_MODULE_NAME "WM" #define FF_WM_NUM_FORMAT_ARGS 3 +typedef enum ProtocolHint +{ + FF_WM_PROTOCOL_HINT_UNKNOWN, + FF_WM_PROTOCOL_HINT_X11, + FF_WM_PROTOCOL_HINT_WAYLAND +} ProtocolHint; + const char* ffGetSessionDesktop() { static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; @@ -14,6 +21,12 @@ const char* ffGetSessionDesktop() pthread_mutex_lock(&mutex); + if(sessionDesktop != NULL) + { + pthread_mutex_unlock(&mutex); + return sessionDesktop; + } + if(sessionDesktop == NULL) sessionDesktop = getenv("XDG_CURRENT_DESKTOP"); @@ -21,11 +34,55 @@ const char* ffGetSessionDesktop() sessionDesktop = getenv("XDG_SESSION_DESKTOP"); pthread_mutex_unlock(&mutex); - return sessionDesktop; } -static void getFromProcDir(FFWMResult* result) +static bool applyPrettyNameIfWM(FFWMResult* result, ProtocolHint* protocolHint) +{ + if(ffStrbufIgnCaseCompS(&result->processName, "kwin_wayland") == 0) + { + ffStrbufSetS(&result->prettyName, "KWin"); + *protocolHint = FF_WM_PROTOCOL_HINT_WAYLAND; + } + else if(ffStrbufIgnCaseCompS(&result->processName, "kwin_x11") == 0) + { + ffStrbufSetS(&result->prettyName, "KWin"); + *protocolHint = FF_WM_PROTOCOL_HINT_X11; + } + else if(ffStrbufIgnCaseCompS(&result->processName, "sway") == 0) + { + ffStrbufSetS(&result->prettyName, "Sway"); + *protocolHint = FF_WM_PROTOCOL_HINT_WAYLAND; + } + else if(ffStrbufIgnCaseCompS(&result->processName, "weston") == 0) + { + ffStrbufSetS(&result->prettyName, "Weston"); + *protocolHint = FF_WM_PROTOCOL_HINT_WAYLAND; + } + else if(ffStrbufIgnCaseCompS(&result->processName, "wayfire") == 0) + { + ffStrbufSetS(&result->prettyName, "Wayfire"); + *protocolHint = FF_WM_PROTOCOL_HINT_WAYLAND; + } + else if(ffStrbufIgnCaseCompS(&result->processName, "openbox") == 0) + { + ffStrbufSetS(&result->prettyName, "Openbox"); + *protocolHint = FF_WM_PROTOCOL_HINT_X11; + } + else if(ffStrbufIgnCaseCompS(&result->processName, "xfwm4") == 0) + { + ffStrbufSetS(&result->prettyName, "XFWM"); + *protocolHint = FF_WM_PROTOCOL_HINT_X11; + } + else if(ffStrbufIgnCaseCompS(&result->processName, "mutter") == 0) + ffStrbufSetS(&result->prettyName, "Mutter"); + else if(ffStrbufIgnCaseCompS(&result->processName, "cinnamon") == 0) + ffStrbufSetS(&result->prettyName, "Muffin"); + + return result->prettyName.length > 0; +} + +static inline void getFromProcDir(FFWMResult* result, ProtocolHint* protocolHint) { DIR* proc = opendir("/proc/"); if(proc == NULL) @@ -40,42 +97,37 @@ static void getFromProcDir(FFWMResult* result) char path[20]; sprintf(path, "/proc/%.8s/comm", dirent->d_name); - ffGetFileContent(path, &result->processName); - if(ffStrbufIgnCaseCompS(&result->processName, "kwin_wayland") == 0) - { - ffStrbufSetS(&result->prettyName, "KWin"); - ffStrbufSetS(&result->protocolName, "Wayland"); - } - else if(ffStrbufIgnCaseCompS(&result->processName, "kwin_x11") == 0) - { - ffStrbufSetS(&result->prettyName, "KWin"); - ffStrbufSetS(&result->protocolName, "X11"); - } - else if(ffStrbufIgnCaseCompS(&result->processName, "openbox") == 0) - ffStrbufSetS(&result->prettyName, "Openbox"); - else if(ffStrbufIgnCaseCompS(&result->processName, "cinnamon") == 0) - ffStrbufSetS(&result->prettyName, "Muffin"); - else if(ffStrbufIgnCaseCompS(&result->processName, "xfwm4") == 0) - ffStrbufSetS(&result->prettyName, "XFWM"); - else if(ffStrbufIgnCaseCompS(&result->processName, "wayfire") == 0) - ffStrbufSetS(&result->prettyName, "Wayfire"); - - if(result->prettyName.length > 0) + if(applyPrettyNameIfWM(result, protocolHint)) break; } + if(result->prettyName.length == 0) + ffStrbufClear(&result->processName); + closedir(proc); } -static void getSessionType(FFstrbuf* sessionType) +static void getSessionTypeFromProtocolHint(FFstrbuf* sessionType, ProtocolHint protocolHint) +{ + if(protocolHint == FF_WM_PROTOCOL_HINT_WAYLAND) + ffStrbufSetS(sessionType, "Wayland"); + else if(protocolHint == FF_WM_PROTOCOL_HINT_X11) + ffStrbufSetS(sessionType, "X11"); +} + +static inline void getSessionType(FFstrbuf* sessionType, ProtocolHint protocolHint) { const char* xdgSessionType = getenv("XDG_SESSION_TYPE"); - if (xdgSessionType == NULL) - return; - else if(strcasecmp(xdgSessionType, "wayland") == 0) + if (xdgSessionType == NULL) + { + getSessionTypeFromProtocolHint(sessionType, protocolHint); + return; + } + + if(strcasecmp(xdgSessionType, "wayland") == 0) ffStrbufSetS(sessionType, "Wayland"); else if(strcasecmp(xdgSessionType, "x11") == 0) ffStrbufSetS(sessionType, "X11"); @@ -85,6 +137,10 @@ static void getSessionType(FFstrbuf* sessionType) ffStrbufSetS(sessionType, "Mir"); else ffStrbufSetS(sessionType, xdgSessionType); + + // $XDG_SESSION_TYPE is empty + if(sessionType->length == 0) + getSessionTypeFromProtocolHint(sessionType, protocolHint); } const FFWMResult* ffDetectWM(FFinstance* instance) @@ -107,17 +163,23 @@ const FFWMResult* ffDetectWM(FFinstance* instance) ffStrbufInit(&result.protocolName); ffStrbufInit(&result.error); - getFromProcDir(&result); + ProtocolHint protocolHint = FF_WM_PROTOCOL_HINT_UNKNOWN; - if(result.prettyName.length == 0) + const char* sessionDesktop = ffGetSessionDesktop(); + + //If sessionDesktop env is a known WM, set it. Otherwise we might be running a DE, search /proc for known WMs + ffStrbufSetS(&result.processName, sessionDesktop); + if(!applyPrettyNameIfWM(&result, &protocolHint)) + getFromProcDir(&result, &protocolHint); + + //Fallback for unknown window managers. This will falsely detect DEs as WMs if their WM is unknown + if(result.prettyName.length == 0 && sessionDesktop != NULL) { - const char* sessionDesktop = ffGetSessionDesktop(); ffStrbufSetS(&result.processName, sessionDesktop); ffStrbufSetS(&result.prettyName, sessionDesktop); } - if(result.protocolName.length == 0) - getSessionType(&result.protocolName); + getSessionType(&result.protocolName, protocolHint); if(result.prettyName.length == 0 && result.protocolName.length == 0) {