mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-30 00:37:23 +01:00
Unified WM / DE / Resolution detection
This commit is contained in:
+4
-1
@@ -148,8 +148,11 @@ set(SRCS
|
||||
src/common/settings.c
|
||||
src/detection/plasma.c
|
||||
src/detection/gtk.c
|
||||
src/detection/wmde.c
|
||||
src/detection/terminalShell.c
|
||||
src/detection/displayserver/displayServer.c
|
||||
src/detection/displayserver/wayland.c
|
||||
src/detection/displayserver/xlib.c
|
||||
src/detection/displayserver/wmde.c
|
||||
src/modules/break.c
|
||||
src/modules/custom.c
|
||||
src/modules/title.c
|
||||
|
||||
+4
-4
@@ -341,7 +341,7 @@ bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer)
|
||||
return ffParsePropFileValues(filename, 1, (FFpropquery[]){{start, buffer}});
|
||||
}
|
||||
|
||||
bool ffParsePropFileHomeValues(FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
|
||||
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
|
||||
{
|
||||
FFstrbuf absolutePath;
|
||||
ffStrbufInitA(&absolutePath, 64);
|
||||
@@ -356,12 +356,12 @@ bool ffParsePropFileHomeValues(FFinstance* instance, const char* relativeFile, u
|
||||
return result;
|
||||
}
|
||||
|
||||
bool ffParsePropFileHome(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||
{
|
||||
return ffParsePropFileHomeValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
|
||||
}
|
||||
|
||||
bool ffParsePropFileConfigValues(FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
|
||||
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries)
|
||||
{
|
||||
bool foundAFile = false;
|
||||
|
||||
@@ -397,7 +397,7 @@ bool ffParsePropFileConfigValues(FFinstance* instance, const char* relativeFile,
|
||||
return foundAFile;
|
||||
}
|
||||
|
||||
bool ffParsePropFileConfig(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer)
|
||||
{
|
||||
return ffParsePropFileConfigValues(instance, relativeFile, 1, (FFpropquery[]){{start, buffer}});
|
||||
}
|
||||
|
||||
@@ -26,9 +26,9 @@ static inline void* detectGTK4ThreadMain(void* instance)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void* detectWMDEThreadMain(void* instance)
|
||||
static inline void* connectDisplayServerThreadMain(void* instance)
|
||||
{
|
||||
ffDetectWMDE((FFinstance*)instance);
|
||||
ffConnectDisplayServer((FFinstance*)instance);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@@ -40,9 +40,9 @@ static inline void* detectTerminalShellThreadMain(void* instance)
|
||||
|
||||
static inline void* startThreadsThreadMain(void* instance)
|
||||
{
|
||||
pthread_t wmdeThread;
|
||||
pthread_create(&wmdeThread, NULL, detectWMDEThreadMain, instance);
|
||||
pthread_detach(wmdeThread);
|
||||
pthread_t dsThread;
|
||||
pthread_create(&dsThread, NULL, connectDisplayServerThreadMain, instance);
|
||||
pthread_detach(dsThread);
|
||||
|
||||
pthread_t gtk2Thread;
|
||||
pthread_create(>k2Thread, NULL, detectGTK2ThreadMain, instance);
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
#include "displayServer.h"
|
||||
#include <pthread.h>
|
||||
#include <dirent.h>
|
||||
|
||||
uint32_t ffdsParseRefreshRate(int32_t refreshRate)
|
||||
{
|
||||
if(refreshRate <= 0)
|
||||
return 0;
|
||||
|
||||
int remainder = refreshRate % 5;
|
||||
if(remainder >= 3)
|
||||
refreshRate += (5 - remainder);
|
||||
else
|
||||
refreshRate -= remainder;
|
||||
|
||||
//All other typicall refresh rates are dividable by 5
|
||||
if(refreshRate == 145)
|
||||
refreshRate = 144;
|
||||
|
||||
return (uint32_t) refreshRate;
|
||||
}
|
||||
|
||||
static void parseDRM(FFDisplayServerResult* result)
|
||||
{
|
||||
const char* drmDirPath = "/sys/class/drm/";
|
||||
|
||||
DIR* dirp = opendir(drmDirPath);
|
||||
if(dirp == NULL)
|
||||
return;
|
||||
|
||||
FFstrbuf drmDir;
|
||||
ffStrbufInitA(&drmDir, 64);
|
||||
ffStrbufAppendS(&drmDir, drmDirPath);
|
||||
|
||||
uint32_t drmDirLength = drmDir.length;
|
||||
|
||||
struct dirent* entry;
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
ffStrbufAppendS(&drmDir, entry->d_name);
|
||||
ffStrbufAppendS(&drmDir, "/modes");
|
||||
|
||||
FILE* modeFile = fopen(drmDir.chars, "r");
|
||||
if(modeFile == NULL)
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
|
||||
resolution->width = 0;
|
||||
resolution->height = 0;
|
||||
resolution->refreshRate = 0;
|
||||
|
||||
int scanned = fscanf(modeFile, "%ix%i", &resolution->width, &resolution->height);
|
||||
if(scanned < 2 || resolution->width == 0 || resolution->height == 0)
|
||||
--result->resolutions.length;
|
||||
|
||||
fclose(modeFile);
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
ffStrbufDestroy(&drmDir);
|
||||
}
|
||||
|
||||
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance)
|
||||
{
|
||||
static FFDisplayServerResult result;
|
||||
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static bool init = false;
|
||||
pthread_mutex_lock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
ffStrbufInit(&result.wmProcessName);
|
||||
ffStrbufInit(&result.wmPrettyName);
|
||||
ffStrbufInit(&result.wmProtocolName);
|
||||
ffStrbufInit(&result.deProcessName);
|
||||
ffStrbufInit(&result.dePrettyName);
|
||||
ffStrbufInit(&result.deVersion);
|
||||
ffListInitA(&result.resolutions, sizeof(FFResolutionResult), 4);
|
||||
|
||||
//We try wayland as our prefered display server, as it supports the most features.
|
||||
//This method can't detect the name of our WM / DE
|
||||
ffdsConnectWayland(instance, &result);
|
||||
|
||||
//Try the x11 libs, from most feature rich to least.
|
||||
//We use the resolution list to detect if a connection is needed.
|
||||
//They respect wmProtocolName, and only detect resolution if it is set.
|
||||
|
||||
if(result.resolutions.length == 0)
|
||||
ffdsConnectXrandr(instance, &result);
|
||||
|
||||
if(result.resolutions.length == 0)
|
||||
ffdsConnectXlib(instance, &result);
|
||||
|
||||
//This resolution detection method is display server independent.
|
||||
//Use it if all connections failed
|
||||
if(result.resolutions.length == 0)
|
||||
parseDRM(&result);
|
||||
|
||||
//This fills in missing information about WM / DE by using env vars and iterating processes
|
||||
ffdsDetectWMDE(instance, &result);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef FASTFETCH_INCLUDED_DISPLAYSERVER
|
||||
#define FASTFETCH_INCLUDED_DISPLAYSERVER
|
||||
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_WAYLAND "Wayland"
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_X11 "X11"
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_TTY "TTY"
|
||||
|
||||
uint32_t ffdsParseRefreshRate(int32_t refreshRate);
|
||||
|
||||
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
void ffdsDetectWMDE(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,166 @@
|
||||
#include "displayServer.h"
|
||||
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
#include <wayland-client.h>
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct WaylandData
|
||||
{
|
||||
const FFinstance* instance;
|
||||
FFlist* results;
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_add_listener)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_destroy)
|
||||
const struct wl_interface* ffwl_output_interface;
|
||||
struct wl_output_listener output_listener;
|
||||
} WaylandData;
|
||||
|
||||
static void waylandGlobalRemoveListener(void* data, struct wl_registry* wl_registry, uint32_t name){
|
||||
FF_UNUSED(data, wl_registry, name);
|
||||
}
|
||||
|
||||
static void waylandOutputGeometryListener(void* data, struct wl_output* wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform)
|
||||
{
|
||||
FF_UNUSED(data, wl_output, x, y, physical_width, physical_height, subpixel, make, model, transform);
|
||||
}
|
||||
|
||||
static void waylandOutputDoneListener(void* data, struct wl_output* wl_output)
|
||||
{
|
||||
FF_UNUSED(data, wl_output);
|
||||
}
|
||||
|
||||
static void waylandOutputScaleListener(void* data, struct wl_output* wl_output, int32_t factor)
|
||||
{
|
||||
FF_UNUSED(data, wl_output, factor);
|
||||
}
|
||||
|
||||
static void waylandOutputModeListener(void* data, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
|
||||
{
|
||||
if(!(flags & WL_OUTPUT_MODE_CURRENT))
|
||||
return;
|
||||
|
||||
WaylandData* wldata = (WaylandData*) data;
|
||||
|
||||
wldata->ffwl_proxy_destroy((struct wl_proxy*) output);
|
||||
|
||||
if(width <= 0 || height <= 0)
|
||||
return;
|
||||
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
FFResolutionResult* result = ffListAdd(wldata->results);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
result->width = (uint32_t) width;
|
||||
result->height = (uint32_t) height;
|
||||
result->refreshRate = ffdsParseRefreshRate(refreshRate / 1000);
|
||||
}
|
||||
|
||||
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
|
||||
{
|
||||
if(strcmp(interface, "wl_output") == 0)
|
||||
{
|
||||
WaylandData* wldata = (WaylandData*) data;
|
||||
|
||||
struct wl_output* output = (struct wl_output*) wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy *) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
|
||||
if(output == NULL)
|
||||
return;
|
||||
|
||||
wldata->ffwl_proxy_add_listener((struct wl_proxy*) output, (void(**)(void)) &wldata->output_listener, data);
|
||||
}
|
||||
}
|
||||
|
||||
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
if(getenv("XDG_RUNTIME_DIR") == NULL)
|
||||
return;
|
||||
|
||||
FF_LIBRARY_LOAD(wayland, "libwayland-client.so", instance->config.libWayland,);
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_dispatch,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_roundtrip,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface,)
|
||||
|
||||
WaylandData data;
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_marshal_constructor_versioned, wl_proxy_marshal_constructor_versioned,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_add_listener, wl_proxy_add_listener,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_output_interface, wl_output_interface,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_destroy, wl_proxy_destroy,)
|
||||
|
||||
struct wl_display* display = ffwl_display_connect(NULL);
|
||||
if(display == NULL)
|
||||
{
|
||||
dlclose(wayland);
|
||||
return;
|
||||
}
|
||||
|
||||
struct wl_registry* registry = (struct wl_registry*) ffwl_proxy_marshal_constructor((struct wl_proxy*) display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
|
||||
if(registry == NULL)
|
||||
{
|
||||
ffwl_display_disconnect(display);
|
||||
dlclose(wayland);
|
||||
return;
|
||||
}
|
||||
|
||||
data.instance = instance;
|
||||
data.results = &result->resolutions;
|
||||
|
||||
struct wl_registry_listener regestry_listener;
|
||||
regestry_listener.global = waylandGlobalAddListener;
|
||||
regestry_listener.global_remove = waylandGlobalRemoveListener;
|
||||
|
||||
data.output_listener.geometry = waylandOutputGeometryListener;
|
||||
data.output_listener.mode = waylandOutputModeListener;
|
||||
data.output_listener.done = waylandOutputDoneListener;
|
||||
data.output_listener.scale = waylandOutputScaleListener;
|
||||
|
||||
data.ffwl_proxy_add_listener((struct wl_proxy*) registry, (void(**)(void)) ®estry_listener, &data);
|
||||
ffwl_display_dispatch(display);
|
||||
ffwl_display_roundtrip(display);
|
||||
|
||||
data.ffwl_proxy_destroy((struct wl_proxy*) registry);
|
||||
ffwl_display_disconnect(display);
|
||||
dlclose(wayland);
|
||||
|
||||
//We successfully connected to wayland and detected the resolution.
|
||||
//So we can set set the session type to wayland.
|
||||
//This is used as an indicator that we are running wayland by the x11 backends.
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
FF_UNUSED(instance);
|
||||
|
||||
//We try to detect wayland already here, so the x11 methods only to resolution detection.
|
||||
|
||||
//Wayland requires this to be set
|
||||
if(getenv("XDG_RUNTIME_DIR") == NULL)
|
||||
return;
|
||||
|
||||
const char* xdgSessionType = getenv("XDG_SESSION_TYPE");
|
||||
|
||||
//If XDG_SESSION_TYPE is set, and doesn't contain "wayland", we are probably not running in a wayland session.
|
||||
if(xdgSessionType != NULL && strcasecmp(xdgSessionType, "wayland") != 0)
|
||||
return;
|
||||
|
||||
//If XDG_SESSION_TYPE is not set, check if WAYLAND_DISPLAY is set.
|
||||
//If not, there is no indicator for a wayland session
|
||||
if(xdgSessionType == NULL && getenv("WAYLAND_DISPLAY") == NULL)
|
||||
return;
|
||||
|
||||
//We are probably running a wayland compositor at this point, but fastfetch was compiled without the required library.
|
||||
//Set the protocol name and use DRM for resolution detection.
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_WAYLAND);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,351 @@
|
||||
#include "displayServer.h"
|
||||
#include <dirent.h>
|
||||
#include <string.h>
|
||||
|
||||
static const char* parseEnv()
|
||||
{
|
||||
const char* env;
|
||||
|
||||
env = getenv("XDG_CURRENT_DESKTOP");
|
||||
if(env != NULL && *env != '\0')
|
||||
return env;
|
||||
|
||||
env = getenv("XDG_SESSION_DESKTOP");
|
||||
if(env != NULL && *env != '\0')
|
||||
return env;
|
||||
|
||||
env = getenv("CURRENT_DESKTOP");
|
||||
if(env != NULL && *env != '\0')
|
||||
return env;
|
||||
|
||||
env = getenv("SESSION_DESKTOP");
|
||||
if(env != NULL && *env != '\0')
|
||||
return env;
|
||||
|
||||
env = getenv("DESKTOP_SESSION");
|
||||
if(env != NULL && *env != '\0')
|
||||
return env;
|
||||
|
||||
if(getenv("KDE_FULL_SESSION") != NULL || getenv("KDE_SESSION_UID") != NULL || getenv("KDE_SESSION_VERSION") != NULL)
|
||||
return "KDE";
|
||||
|
||||
if(getenv("GNOME_DESKTOP_SESSION_ID") != NULL)
|
||||
return "Gnome";
|
||||
|
||||
if(getenv("MATE_DESKTOP_SESSION_ID") != NULL)
|
||||
return "Mate";
|
||||
|
||||
if(getenv("TDE_FULL_SESSION") != NULL)
|
||||
return "Trinity";
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* processName)
|
||||
{
|
||||
if(processName == NULL || *processName == '\0')
|
||||
return;
|
||||
|
||||
if(strcasecmp(processName, "kwin_wayland") == 0 || strcasecmp(processName, "kwin_x11") == 0 || strcasecmp(processName, "kwin") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "KWin");
|
||||
else if(strcasecmp(processName, "sway") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Sway");
|
||||
else if(strcasecmp(processName, "weston") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Weston");
|
||||
else if(strcasecmp(processName, "wayfire") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Wayfire");
|
||||
else if(strcasecmp(processName, "openbox") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Openbox");
|
||||
else if(strcasecmp(processName, "xfwm4") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Xfwm4");
|
||||
else if(strcasecmp(processName, "Marco") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Marco");
|
||||
else if(strcasecmp(processName, "gnome-session-binary") == 0 || strcasecmp(processName, "Mutter") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Mutter");
|
||||
else if(strcasecmp(processName, "cinnamon-session") == 0 || strcasecmp(processName, "Muffin") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Muffin");
|
||||
else if( // WMs where the pretty name matches the process name
|
||||
strcasecmp(processName, "dwm") == 0
|
||||
) ffStrbufSetS(&result->wmPrettyName, processName);
|
||||
|
||||
if(result->wmPrettyName.length > 0 && result->wmProcessName.length == 0)
|
||||
ffStrbufSetS(&result->wmProcessName, processName);
|
||||
}
|
||||
|
||||
static void applyBetterWM(FFDisplayServerResult* result, const char* processName)
|
||||
{
|
||||
if(processName == NULL || *processName == '\0')
|
||||
return;
|
||||
|
||||
//If it is a known wm, this will set the pretty name
|
||||
applyPrettyNameIfWM(result, processName);
|
||||
|
||||
//If it isn't a known wm, we have to set the process name our self
|
||||
ffStrbufSetS(&result->wmProcessName, processName);
|
||||
|
||||
//If it isn't a known wm, set the pretty name to the process name
|
||||
if(result->wmPrettyName.length == 0)
|
||||
ffStrbufAppend(&result->wmPrettyName, &result->wmProcessName);
|
||||
}
|
||||
|
||||
static void getKDE(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "plasmashell");
|
||||
ffStrbufSetS(&result->dePrettyName, "KDE Plasma");
|
||||
ffParsePropFile("/usr/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
applyBetterWM(result, getenv("KDEWM"));
|
||||
}
|
||||
|
||||
static void getGnome(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "gnome-shell");
|
||||
ffStrbufSetS(&result->dePrettyName, "GNOME");
|
||||
ffParsePropFile("/usr/share/gnome-shell/org.gnome.Extensions", "version :", &result->deVersion);
|
||||
}
|
||||
|
||||
static void getCinnamon(FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "cinnamon");
|
||||
ffStrbufSetS(&result->dePrettyName, "Cinnamon");
|
||||
ffParsePropFile("/usr/share/applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
|
||||
}
|
||||
|
||||
static void getMate(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "mate-session");
|
||||
ffStrbufSetS(&result->dePrettyName, "MATE");
|
||||
|
||||
FFstrbuf major;
|
||||
ffStrbufInit(&major);
|
||||
|
||||
FFstrbuf minor;
|
||||
ffStrbufInit(&minor);
|
||||
|
||||
FFstrbuf micro;
|
||||
ffStrbufInit(µ);
|
||||
|
||||
ffParsePropFileValues("/usr/share/mate-about/mate-version.xml", 3, (FFpropquery[]) {
|
||||
{"<platform>", &major},
|
||||
{"<minor>", &minor},
|
||||
{"<micro>", µ}
|
||||
});
|
||||
|
||||
ffParseSemver(&result->deVersion, &major, &minor, µ);
|
||||
|
||||
ffStrbufDestroy(&major);
|
||||
ffStrbufDestroy(&minor);
|
||||
ffStrbufDestroy(µ);
|
||||
|
||||
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
|
||||
{
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"mate-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
|
||||
ffStrbufTrim(&result->deVersion, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getXFCE4(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "xfce4-session");
|
||||
ffStrbufSetS(&result->dePrettyName, "Xfce4");
|
||||
ffParsePropFile("/usr/share/gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
|
||||
{
|
||||
//This is somewhat slow
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"xfce4-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrBeforeFirstC(&result->deVersion, '(');
|
||||
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
|
||||
ffStrbufTrim(&result->deVersion, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getLXQt(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "lxqt-session");
|
||||
ffStrbufSetS(&result->dePrettyName, "LXQt");
|
||||
ffParsePropFile("/usr/lib/pkgconfig/lxqt.pc", "Version:", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFile("/usr/share/cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFile("/usr/share/cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
|
||||
{
|
||||
//This is really, really, really slow. Thank you, LXQt developers
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"lxqt-session",
|
||||
"-v",
|
||||
NULL
|
||||
});
|
||||
|
||||
result->deVersion.length = 0; //don't set '\0' byte
|
||||
ffGetPropValueFromLines(result->deVersion.chars , "liblxqt", &result->deVersion);
|
||||
}
|
||||
|
||||
FFstrbuf wmProcessNameBuffer;
|
||||
ffStrbufInit(&wmProcessNameBuffer);
|
||||
|
||||
ffParsePropFileConfig(instance, "lxqt/session.conf", "window_manager =", &wmProcessNameBuffer);
|
||||
applyBetterWM(result, wmProcessNameBuffer.chars);
|
||||
|
||||
ffStrbufDestroy(&wmProcessNameBuffer);
|
||||
}
|
||||
|
||||
static void applyPrettyNameIfDE(const FFinstance* instance, FFDisplayServerResult* result, const char* name)
|
||||
{
|
||||
if(name == NULL || *name == '\0')
|
||||
return;
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "KDE") == 0 ||
|
||||
strcasecmp(name, "plasma") == 0 ||
|
||||
strcasecmp(name, "plasmashell") == 0 ||
|
||||
strcasecmp(name, "plasmawayland") == 0
|
||||
) getKDE(result);
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "Gnome") == 0 ||
|
||||
strcasecmp(name, "ubuntu:GNOME") == 0 ||
|
||||
strcasecmp(name, "ubuntu") == 0 ||
|
||||
strcasecmp(name, "gnome-shell") == 0
|
||||
) getGnome(result);
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "X-Cinnamon") == 0 ||
|
||||
strcasecmp(name, "Cinnamon") == 0
|
||||
) getCinnamon(result);
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "XFCE") == 0 ||
|
||||
strcasecmp(name, "X-XFCE") == 0 ||
|
||||
strcasecmp(name, "XFCE4") == 0 ||
|
||||
strcasecmp(name, "X-XFCE4") == 0 ||
|
||||
strcasecmp(name, "xfce4-session") == 0
|
||||
) getXFCE4(instance, result);
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "MATE") == 0 ||
|
||||
strcasecmp(name, "X-MATE") == 0 ||
|
||||
strcasecmp(name, "mate-session") == 0
|
||||
) getMate(instance, result);
|
||||
|
||||
else if(
|
||||
strcasecmp(name, "LXQt") == 0 ||
|
||||
strcasecmp(name, "X-LXQT") == 0 ||
|
||||
strcasecmp(name, "lxqt-session") == 0
|
||||
) getLXQt(instance, result);
|
||||
}
|
||||
|
||||
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
|
||||
{
|
||||
//This is only called if all connection attempts to a display server failed
|
||||
//We don't need to check for wayland here, as the wayland code will always set the protocol name to wayland
|
||||
|
||||
const char* env = getenv("XDG_SESSION_TYPE");
|
||||
if(env != NULL && *env != '\0')
|
||||
{
|
||||
if(strcasecmp(env, "x11") == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
|
||||
else if(strcasecmp(env, "tty") == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY);
|
||||
else
|
||||
ffStrbufSetS(&result->wmProtocolName, env);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
env = getenv("TERM");
|
||||
if(env != NULL && *env != '\0')
|
||||
{
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_TTY);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void getFromProcDir(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
DIR* proc = opendir("/proc");
|
||||
if(proc == NULL)
|
||||
return;
|
||||
|
||||
FFstrbuf procPath;
|
||||
ffStrbufInitA(&procPath, 64);
|
||||
ffStrbufAppendS(&procPath, "/proc/");
|
||||
|
||||
uint32_t procPathLength = procPath.length;
|
||||
|
||||
FFstrbuf processName;
|
||||
ffStrbufInitA(&processName, 256); //Some processes have large command lines (looking at you chrome)
|
||||
|
||||
struct dirent* dirent;
|
||||
while((dirent = readdir(proc)) != NULL)
|
||||
{
|
||||
if(dirent->d_type != DT_DIR || dirent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&procPath, dirent->d_name);
|
||||
ffStrbufAppendS(&procPath, "/cmdline");
|
||||
ffGetFileContent(procPath.chars, &processName);
|
||||
ffStrbufSubstrBeforeFirstC(&processName, '\0'); //Trim the arguments
|
||||
ffStrbufSubstrAfterLastC(&processName, '/');
|
||||
ffStrbufSubstrBefore(&procPath, procPathLength);
|
||||
|
||||
if(result->dePrettyName.length == 0)
|
||||
applyPrettyNameIfDE(instance, result, processName.chars);
|
||||
|
||||
if(result->wmPrettyName.length == 0)
|
||||
applyPrettyNameIfWM(result, processName.chars);
|
||||
|
||||
if(result->deProcessName.length > 0 && result->wmPrettyName.length > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(proc);
|
||||
|
||||
ffStrbufDestroy(&processName);
|
||||
ffStrbufDestroy(&procPath);
|
||||
}
|
||||
|
||||
void ffdsDetectWMDE(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
//If all connections failed, use the environment variables to detect protocol name
|
||||
if(result->wmProtocolName.length == 0)
|
||||
getWMProtocolNameFromEnv(result);
|
||||
|
||||
const char* env = parseEnv();
|
||||
|
||||
//Connecting to a display server only gives WM results, not DE results.
|
||||
//If we find it in the environment, use that.
|
||||
applyPrettyNameIfDE(instance, result, env);
|
||||
|
||||
//If WM was found by connection to the sever, and DE in the environment, we can return.
|
||||
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
|
||||
return;
|
||||
|
||||
//If WM is not set, prefer the environment variable over process names,
|
||||
//to avoid matching processes from different users.
|
||||
if(result->wmPrettyName.length == 0)
|
||||
applyPrettyNameIfWM(result, env);
|
||||
|
||||
//Get missing WM / DE from processes.
|
||||
getFromProcDir(instance, result);
|
||||
|
||||
//Fallback for unknown WMs and DEs. This will falsely detect DEs as WMs if they (and their used WM) are unknown
|
||||
if(result->wmPrettyName.length == 0 && result->dePrettyName.length == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmProcessName, env);
|
||||
ffStrbufSetS(&result->wmPrettyName, env);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
#include "displayServer.h"
|
||||
|
||||
#ifdef FF_HAVE_X11
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
static void x11AddScreenAsResult(FFlist* results, Screen* screen, uint32_t refreshRate)
|
||||
{
|
||||
if(WidthOfScreen(screen) == 0 || HeightOfScreen(screen) == 0)
|
||||
return;
|
||||
|
||||
FFResolutionResult* result = ffListAdd(results);
|
||||
result->width = (uint32_t) WidthOfScreen(screen);
|
||||
result->height = (uint32_t) HeightOfScreen(screen);
|
||||
result->refreshRate = refreshRate;
|
||||
}
|
||||
|
||||
void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(x11, "libX11.so", instance->config.libX11,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(x11, XOpenDisplay,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(x11, XCloseDisplay,)
|
||||
|
||||
Display* display = ffXOpenDisplay(x11);
|
||||
if(display == NULL)
|
||||
{
|
||||
dlclose(x11);
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < ScreenCount(display); i++)
|
||||
x11AddScreenAsResult(&result->resolutions, ScreenOfDisplay(display, i), 0);
|
||||
|
||||
ffXCloseDisplay(display);
|
||||
dlclose(x11);
|
||||
|
||||
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
|
||||
if(result->wmProtocolName.length == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
//Do nothing. WM / DE detection will use environment vars to detect as much as possible.
|
||||
FF_UNUSED(instance, result);
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_X11
|
||||
|
||||
#ifdef FF_HAVE_XRANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
||||
typedef struct XrandrData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(XRRGetScreenInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRConfigCurrentConfiguration)
|
||||
FF_LIBRARY_SYMBOL(XRRConfigCurrentRate)
|
||||
FF_LIBRARY_SYMBOL(XRRGetMonitors)
|
||||
FF_LIBRARY_SYMBOL(XRRGetScreenResources)
|
||||
FF_LIBRARY_SYMBOL(XRRGetOutputInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRGetCrtcInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeCrtcInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeOutputInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeScreenResources)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeMonitors)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeScreenConfigInfo)
|
||||
|
||||
//Init once
|
||||
Display* display;
|
||||
FFlist* results;
|
||||
|
||||
//Init per screen
|
||||
uint32_t defaultRefreshRate;
|
||||
XRRScreenResources* screenResources;
|
||||
} XrandrData;
|
||||
|
||||
static XRRModeInfo* xrandrGetModeInfo(XRRScreenResources* screenResources, RRMode mode)
|
||||
{
|
||||
for(int i = 0; i < screenResources->nmode; i++)
|
||||
{
|
||||
if(screenResources->modes[i].id == mode)
|
||||
return &screenResources->modes[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool xrandrHandleOutputInfo(XrandrData* data, XRROutputInfo* outputInfo)
|
||||
{
|
||||
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, outputInfo->crtc);
|
||||
if(crtcInfo == NULL)
|
||||
return false;
|
||||
|
||||
XRRModeInfo* modeInfo = xrandrGetModeInfo(data->screenResources, crtcInfo->mode);
|
||||
if(modeInfo == NULL || modeInfo->width == 0 || modeInfo->height == 0)
|
||||
{
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
FFResolutionResult* result = ffListAdd(data->results);
|
||||
result->width = modeInfo->width;
|
||||
result->height = modeInfo->height;
|
||||
result->refreshRate = ffdsParseRefreshRate((int32_t) (modeInfo->dotClock / (modeInfo->hTotal * modeInfo->vTotal)));
|
||||
|
||||
if(result->refreshRate == 0)
|
||||
result->refreshRate = data->defaultRefreshRate;
|
||||
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool xrandrHandleMonitorFallback(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
{
|
||||
if(monitorInfo->width == 0 || monitorInfo->height == 0)
|
||||
return false;
|
||||
|
||||
FFResolutionResult* result = ffListAdd(data->results);
|
||||
result->width = (uint32_t) monitorInfo->width;
|
||||
result->height = (uint32_t) monitorInfo->height;
|
||||
result->refreshRate = (uint32_t) data->defaultRefreshRate;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
{
|
||||
bool foundMode = false;
|
||||
|
||||
for(int i = 0; i < monitorInfo->noutput; i++)
|
||||
{
|
||||
XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, monitorInfo->outputs[i]);
|
||||
if(outputInfo == NULL)
|
||||
continue;
|
||||
|
||||
if(xrandrHandleOutputInfo(data, outputInfo))
|
||||
foundMode = true;
|
||||
|
||||
data->ffXRRFreeOutputInfo(outputInfo);
|
||||
}
|
||||
|
||||
if(!foundMode)
|
||||
return xrandrHandleMonitorFallback(data, monitorInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool xrandrLoopMonitors(XrandrData* data, XRRMonitorInfo* monitorInfos, int numberOfMonitors, bool(*monitorFunc)(XrandrData* data, XRRMonitorInfo* monitorInfo))
|
||||
{
|
||||
bool foundAMonitor = false;
|
||||
|
||||
for(int i = 0; i < numberOfMonitors; i++)
|
||||
{
|
||||
if(monitorFunc(data, &monitorInfos[i]))
|
||||
foundAMonitor = true;
|
||||
}
|
||||
|
||||
return foundAMonitor;
|
||||
}
|
||||
|
||||
static void xrandrHandleScreen(XrandrData* data, Screen* screen)
|
||||
{
|
||||
Window window = RootWindowOfScreen(screen);
|
||||
|
||||
XRRScreenConfiguration* screenConfiguration = data->ffXRRGetScreenInfo(data->display, window);
|
||||
if(screenConfiguration != NULL)
|
||||
{
|
||||
data->defaultRefreshRate = (uint32_t) data->ffXRRConfigCurrentRate(screenConfiguration);
|
||||
data->ffXRRFreeScreenConfigInfo(screenConfiguration);
|
||||
}
|
||||
else
|
||||
data->defaultRefreshRate = 0;
|
||||
|
||||
int numberOfMonitors;
|
||||
XRRMonitorInfo* monitorInfos = data->ffXRRGetMonitors(data->display, window, True, &numberOfMonitors);
|
||||
if(monitorInfos == NULL)
|
||||
{
|
||||
x11AddScreenAsResult(data->results, screen, data->defaultRefreshRate);
|
||||
return;
|
||||
}
|
||||
|
||||
data->screenResources = data->ffXRRGetScreenResources(data->display, window);
|
||||
|
||||
bool foundAMonitor;
|
||||
|
||||
if(data->screenResources != NULL)
|
||||
foundAMonitor = xrandrLoopMonitors(data, monitorInfos, numberOfMonitors, xrandrHandleMonitor);
|
||||
else
|
||||
foundAMonitor = xrandrLoopMonitors(data, monitorInfos, numberOfMonitors, xrandrHandleMonitorFallback);
|
||||
|
||||
if(!foundAMonitor)
|
||||
x11AddScreenAsResult(data->results, screen, data->defaultRefreshRate);
|
||||
|
||||
data->ffXRRFreeScreenResources(data->screenResources);
|
||||
data->ffXRRFreeMonitors(monitorInfos);
|
||||
}
|
||||
|
||||
void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(xrandr, "libXrandr.so", instance->config.libXrandr,);
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(xrandr, XOpenDisplay,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xrandr, XCloseDisplay,)
|
||||
|
||||
XrandrData data;
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetScreenInfo, XRRGetScreenInfo,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRConfigCurrentRate, XRRConfigCurrentRate,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetMonitors, XRRGetMonitors,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetScreenResources, XRRGetScreenResources,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetOutputInfo, XRRGetOutputInfo,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetCrtcInfo, XRRGetCrtcInfo,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeCrtcInfo, XRRFreeCrtcInfo,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeOutputInfo, XRRFreeOutputInfo,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeScreenResources, XRRFreeScreenResources,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeMonitors, XRRFreeMonitors,);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeScreenConfigInfo, XRRFreeScreenConfigInfo,);
|
||||
|
||||
data.display = ffXOpenDisplay(NULL);
|
||||
if(data.display == NULL)
|
||||
{
|
||||
dlclose(xrandr);
|
||||
return;
|
||||
}
|
||||
|
||||
data.results = &result->resolutions;
|
||||
|
||||
for(int i = 0; i < ScreenCount(data.display); i++)
|
||||
xrandrHandleScreen(&data, ScreenOfDisplay(data.display, i));
|
||||
|
||||
ffXCloseDisplay(data.display);
|
||||
dlclose(xrandr);
|
||||
|
||||
//If wayland hasn't set this, connection failed for it. So we are running only a X Server, not XWayland.
|
||||
if(result->wmProtocolName.length == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, FF_DISPLAYSERVER_PROTOCOL_X11);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
//Do nothing here. There are more x11 implementaions to come.
|
||||
FF_UNUSED(instance, result);
|
||||
}
|
||||
|
||||
#endif // FF_HAVE_XRANDR
|
||||
+1
-1
@@ -51,7 +51,7 @@ static void detectGTKFromDConf(FFinstance* instance, FFGTKResult* result)
|
||||
|
||||
init = true;
|
||||
|
||||
const FFWMDEResult* wmde = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0)
|
||||
{
|
||||
|
||||
@@ -85,7 +85,7 @@ const FFPlasmaResult* ffDetectPlasma(FFinstance* instance)
|
||||
ffStrbufInit(&result.icons);
|
||||
ffStrbufInit(&result.font);
|
||||
|
||||
const FFWMDEResult* wmde = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
if(ffStrbufIgnCaseCompS(&wmde->deProcessName, "plasmashell") != 0)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
@@ -1,414 +0,0 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
|
||||
typedef enum ProtocolHint
|
||||
{
|
||||
FF_PROTOCOL_HINT_UNKNOWN = 0,
|
||||
FF_PROTOCOL_HINT_X11,
|
||||
FF_PROTOCOL_HINT_WAYLAND
|
||||
} ProtocolHint;
|
||||
|
||||
static void getSessionDesktop(FFWMDEResult* result)
|
||||
{
|
||||
result->sessionDesktop = getenv("XDG_CURRENT_DESKTOP");
|
||||
if(result->sessionDesktop != NULL && *result->sessionDesktop != '\0')
|
||||
return;
|
||||
|
||||
result->sessionDesktop = getenv("XDG_SESSION_DESKTOP");
|
||||
if(result->sessionDesktop != NULL && *result->sessionDesktop != '\0')
|
||||
return;
|
||||
|
||||
result->sessionDesktop = getenv("CURRENT_DESKTOP");
|
||||
if(result->sessionDesktop != NULL && *result->sessionDesktop != '\0')
|
||||
return;
|
||||
|
||||
result->sessionDesktop = getenv("SESSION_DESKTOP");
|
||||
if(result->sessionDesktop != NULL && *result->sessionDesktop != '\0')
|
||||
return;
|
||||
|
||||
char* env;
|
||||
|
||||
env = getenv("DESKTOP_SESSION");
|
||||
if(env != NULL && *env != '\0')
|
||||
{
|
||||
if(strcasecmp(env, "plasma") == 0)
|
||||
result->sessionDesktop = "KDE";
|
||||
else
|
||||
result->sessionDesktop = env;
|
||||
return;
|
||||
}
|
||||
|
||||
env = getenv("GNOME_DESKTOP_SESSION_ID");
|
||||
if(env != NULL)
|
||||
{
|
||||
result->sessionDesktop = "Gnome";
|
||||
return;
|
||||
}
|
||||
|
||||
env = getenv("MATE_DESKTOP_SESSION_ID");
|
||||
if(env != NULL)
|
||||
{
|
||||
result->sessionDesktop = "Mate";
|
||||
return;
|
||||
}
|
||||
|
||||
env = getenv("TDE_FULL_SESSION");
|
||||
if(env != NULL)
|
||||
{
|
||||
result->sessionDesktop = "Trinity";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void applyPrettyNameIfWM(FFWMDEResult* result, const char* processName, ProtocolHint* protocolHint)
|
||||
{
|
||||
if(processName == NULL || *processName == '\0')
|
||||
return;
|
||||
|
||||
if(strcasecmp(processName, "kwin_wayland") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmPrettyName, "KWin");
|
||||
*protocolHint = FF_PROTOCOL_HINT_WAYLAND;
|
||||
}
|
||||
else if(strcasecmp(processName, "kwin_x11") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmPrettyName, "KWin");
|
||||
*protocolHint = FF_PROTOCOL_HINT_X11;
|
||||
}
|
||||
else if(strcasecmp(processName, "sway") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmPrettyName, "Sway");
|
||||
*protocolHint = FF_PROTOCOL_HINT_WAYLAND;
|
||||
}
|
||||
else if(strcasecmp(processName, "weston") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmPrettyName, "Weston");
|
||||
*protocolHint = FF_PROTOCOL_HINT_WAYLAND;
|
||||
}
|
||||
else if(strcasecmp(processName, "wayfire") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmPrettyName, "Wayfire");
|
||||
*protocolHint = FF_PROTOCOL_HINT_WAYLAND;
|
||||
}
|
||||
else if(strcasecmp(processName, "openbox") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmPrettyName, "Openbox");
|
||||
*protocolHint = FF_PROTOCOL_HINT_X11;
|
||||
}
|
||||
else if(strcasecmp(processName, "xfwm4") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmPrettyName, "Xfwm4");
|
||||
*protocolHint = FF_PROTOCOL_HINT_X11;
|
||||
}
|
||||
else if(strcasecmp(processName, "Marco") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmPrettyName, "Marco");
|
||||
*protocolHint = FF_PROTOCOL_HINT_X11;
|
||||
}
|
||||
else if(strcasecmp(processName, "dwm") == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmPrettyName, "dwm");
|
||||
*protocolHint = FF_PROTOCOL_HINT_X11;
|
||||
}
|
||||
else if(strcasecmp(processName, "gnome-session-binary") == 0 || strcasecmp(processName, "Mutter") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Mutter");
|
||||
else if(strcasecmp(processName, "cinnamon-session") == 0 || strcasecmp(processName, "Muffin") == 0)
|
||||
ffStrbufSetS(&result->wmPrettyName, "Muffin");
|
||||
|
||||
if(result->wmPrettyName.length > 0 && result->wmProcessName.length == 0)
|
||||
ffStrbufSetS(&result->wmProcessName, processName);
|
||||
}
|
||||
|
||||
static void applyBetterWM(FFWMDEResult* result, const char* processName, ProtocolHint* protocolHint)
|
||||
{
|
||||
if(processName == NULL || *processName == '\0')
|
||||
return;
|
||||
|
||||
ffStrbufSetS(&result->wmProcessName, processName);
|
||||
applyPrettyNameIfWM(result, processName, protocolHint);
|
||||
if(result->wmPrettyName.length == 0)
|
||||
ffStrbufAppend(&result->wmPrettyName, &result->wmProcessName);
|
||||
}
|
||||
|
||||
static void getKDE(FFWMDEResult* result, ProtocolHint* protocolHint)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "plasmashell");
|
||||
ffStrbufSetS(&result->dePrettyName, "KDE Plasma");
|
||||
ffParsePropFile("/usr/share/xsessions/plasma.desktop", "X-KDE-PluginInfo-Version =", &result->deVersion);
|
||||
applyBetterWM(result, getenv("KDEWM"), protocolHint);
|
||||
}
|
||||
|
||||
static void getGnome(FFWMDEResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "gnome-shell");
|
||||
ffStrbufSetS(&result->dePrettyName, "GNOME");
|
||||
ffParsePropFile("/usr/share/gnome-shell/org.gnome.Extensions", "version :", &result->deVersion);
|
||||
}
|
||||
|
||||
static void getCinnamon(FFWMDEResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "cinnamon");
|
||||
ffStrbufSetS(&result->dePrettyName, "Cinnamon");
|
||||
ffParsePropFile("/usr/share/applications/cinnamon.desktop", "X-GNOME-Bugzilla-Version =", &result->deVersion);
|
||||
}
|
||||
|
||||
static void getMate(FFinstance* instance, FFWMDEResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "mate-session");
|
||||
ffStrbufSetS(&result->dePrettyName, "MATE");
|
||||
|
||||
FFstrbuf major; ffStrbufInit(&major);
|
||||
FFstrbuf minor; ffStrbufInit(&minor);
|
||||
FFstrbuf micro; ffStrbufInit(µ);
|
||||
|
||||
ffParsePropFileValues("/usr/share/mate-about/mate-version.xml", 3, (FFpropquery[]) {
|
||||
{"<platform>", &major},
|
||||
{"<minor>", &minor},
|
||||
{"<micro>", µ}
|
||||
});
|
||||
|
||||
ffParseSemver(&result->deVersion, &major, &minor, µ);
|
||||
|
||||
ffStrbufDestroy(&major);
|
||||
ffStrbufDestroy(&minor);
|
||||
ffStrbufDestroy(µ);
|
||||
|
||||
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
|
||||
{
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"mate-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
|
||||
ffStrbufTrim(&result->deVersion, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getXFCE4(FFinstance* instance, FFWMDEResult* result)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "xfce4-session");
|
||||
ffStrbufSetS(&result->dePrettyName, "Xfce4");
|
||||
ffParsePropFile("/usr/share/gtk-doc/html/libxfce4ui/index.html", "<div><p class=\"releaseinfo\">Version", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
|
||||
{
|
||||
//This is somewhat slow
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"xfce4-session",
|
||||
"--version",
|
||||
NULL
|
||||
});
|
||||
|
||||
ffStrbufSubstrBeforeFirstC(&result->deVersion, '(');
|
||||
ffStrbufSubstrAfterFirstC(&result->deVersion, ' ');
|
||||
ffStrbufTrim(&result->deVersion, ' ');
|
||||
}
|
||||
}
|
||||
|
||||
static void getLXQt(FFinstance* instance, FFWMDEResult* result, ProtocolHint* protocolHint)
|
||||
{
|
||||
ffStrbufSetS(&result->deProcessName, "lxqt-session");
|
||||
ffStrbufSetS(&result->dePrettyName, "LXQt");
|
||||
ffParsePropFile("/usr/lib/pkgconfig/lxqt.pc", "Version:", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFile("/usr/share/cmake/lxqt/lxqt-config.cmake", "set ( LXQT_VERSION", &result->deVersion);
|
||||
if(result->deVersion.length == 0)
|
||||
ffParsePropFile("/usr/share/cmake/lxqt/lxqt-config-version.cmake", "set ( PACKAGE_VERSION", &result->deVersion);
|
||||
|
||||
if(result->deVersion.length == 0 && instance->config.allowSlowOperations)
|
||||
{
|
||||
//This is really, really, really slow. Thank you, LXQt developers
|
||||
ffProcessAppendStdOut(&result->deVersion, (char* const[]){
|
||||
"lxqt-session",
|
||||
"-v",
|
||||
NULL
|
||||
});
|
||||
|
||||
result->deVersion.length = 0; //don't set '\0' byte
|
||||
ffGetPropValueFromLines(result->deVersion.chars , "liblxqt", &result->deVersion);
|
||||
}
|
||||
|
||||
FFstrbuf wmProcessNameBuffer;
|
||||
ffStrbufInit(&wmProcessNameBuffer);
|
||||
|
||||
ffParsePropFileConfig(instance, "lxqt/session.conf", "window_manager =", &wmProcessNameBuffer);
|
||||
applyBetterWM(result, wmProcessNameBuffer.chars, protocolHint);
|
||||
|
||||
ffStrbufDestroy(&wmProcessNameBuffer);
|
||||
}
|
||||
|
||||
static void applyPrettyNameIfDE(FFinstance* instance, FFWMDEResult* result, const char* name, ProtocolHint* protocolHint)
|
||||
{
|
||||
if(name == NULL || *name == '\0')
|
||||
return;
|
||||
|
||||
if(strcasecmp(name, "KDE") == 0 || strcasecmp(name, "plasma") == 0 || strcasecmp(name, "plasmashell") == 0)
|
||||
getKDE(result, protocolHint);
|
||||
else if(strcasecmp(name, "Gnome") == 0 || strcasecmp(name, "ubuntu:GNOME") == 0 || strcasecmp(name, "ubuntu") == 0 || strcasecmp(name, "gnome-shell") == 0)
|
||||
getGnome(result);
|
||||
else if(strcasecmp(name, "X-Cinnamon") == 0 || strcasecmp(name, "Cinnamon") == 0)
|
||||
getCinnamon(result);
|
||||
else if(strcasecmp(name, "XFCE") == 0 || strcasecmp(name, "X-XFCE") == 0 || strcasecmp(name, "XFCE4") == 0 || strcasecmp(name, "X-XFCE4") == 0 || strcasecmp(name, "xfce4-session") == 0)
|
||||
getXFCE4(instance, result);
|
||||
else if(strcasecmp(name, "MATE") == 0 || strcasecmp(name, "X-MATE") == 0 || strcasecmp(name, "mate-session") == 0)
|
||||
getMate(instance, result);
|
||||
else if(strcasecmp(name, "LXQt") == 0 || strcasecmp(name, "X-LXQT") == 0 || strcasecmp(name, "lxqt-session") == 0)
|
||||
getLXQt(instance, result, protocolHint);
|
||||
}
|
||||
|
||||
static void getSessionTypeFromHint(FFWMDEResult* result, ProtocolHint protocolHint)
|
||||
{
|
||||
if(
|
||||
result->wmProtocolName.length > 0 ||
|
||||
protocolHint == FF_PROTOCOL_HINT_UNKNOWN
|
||||
) return;
|
||||
|
||||
if(protocolHint == FF_PROTOCOL_HINT_WAYLAND)
|
||||
ffStrbufSetS(&result->wmProtocolName, "Wayland");
|
||||
else if(protocolHint == FF_PROTOCOL_HINT_X11)
|
||||
ffStrbufSetS(&result->wmProtocolName, "X11");
|
||||
}
|
||||
|
||||
static void getSessionTypeFromEnv(FFWMDEResult* result)
|
||||
{
|
||||
const char* env = getenv("XDG_SESSION_TYPE");
|
||||
if(env != NULL && *env != '\0')
|
||||
{
|
||||
if(strcasecmp(env, "wayland") == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, "Wayland");
|
||||
else if(strcasecmp(env, "x11") == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, "X11");
|
||||
else if(strcasecmp(env, "tty") == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, "TTY");
|
||||
else if(strcasecmp(env, "mir") == 0)
|
||||
ffStrbufSetS(&result->wmProtocolName, "Mir");
|
||||
else
|
||||
ffStrbufSetS(&result->wmProtocolName, env);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
env = getenv("WAYLAND_DISPLAY");
|
||||
if(env != NULL && *env != '\0')
|
||||
{
|
||||
ffStrbufSetS(&result->wmProtocolName, "Wayland");
|
||||
return;
|
||||
}
|
||||
|
||||
env = getenv("TERM");
|
||||
if(env != NULL && *env != '\0')
|
||||
{
|
||||
ffStrbufSetS(&result->wmProtocolName, "TTY");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void getFromProcDir(FFinstance* instance, FFWMDEResult* result, ProtocolHint* protocolHint)
|
||||
{
|
||||
DIR* proc = opendir("/proc");
|
||||
if(proc == NULL)
|
||||
return;
|
||||
|
||||
FFstrbuf procPath;
|
||||
ffStrbufInitA(&procPath, 64);
|
||||
ffStrbufAppendS(&procPath, "/proc/");
|
||||
|
||||
uint32_t procPathLength = procPath.length;
|
||||
|
||||
FFstrbuf processName;
|
||||
ffStrbufInitA(&processName, 256); //Some processes have large command lines (looking at you chrome)
|
||||
|
||||
struct dirent* dirent;
|
||||
while((dirent = readdir(proc)) != NULL)
|
||||
{
|
||||
if(dirent->d_type != DT_DIR || dirent->d_name[0] == '.')
|
||||
continue;
|
||||
|
||||
ffStrbufAppendS(&procPath, dirent->d_name);
|
||||
ffStrbufAppendS(&procPath, "/cmdline");
|
||||
ffGetFileContent(procPath.chars, &processName);
|
||||
ffStrbufSubstrBeforeFirstC(&processName, '\0'); //Trim the arguments
|
||||
ffStrbufSubstrAfterLastC(&processName, '/');
|
||||
ffStrbufSubstrBefore(&procPath, procPathLength);
|
||||
|
||||
if(result->dePrettyName.length == 0)
|
||||
applyPrettyNameIfDE(instance, result, processName.chars, protocolHint);
|
||||
|
||||
if(result->wmPrettyName.length == 0)
|
||||
applyPrettyNameIfWM(result, processName.chars, protocolHint);
|
||||
|
||||
if(result->deProcessName.length > 0 && result->wmPrettyName.length > 0)
|
||||
break;
|
||||
}
|
||||
|
||||
closedir(proc);
|
||||
|
||||
ffStrbufDestroy(&processName);
|
||||
ffStrbufDestroy(&procPath);
|
||||
}
|
||||
|
||||
void getWMDE(FFinstance* instance, FFWMDEResult* result)
|
||||
{
|
||||
ProtocolHint protocolHint;
|
||||
|
||||
//If sessionDesktop is a known DE, set it. Some DEs even have config files which tell us the WM, so we can return very fast in this case
|
||||
applyPrettyNameIfDE(instance, result, result->sessionDesktop, &protocolHint);
|
||||
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
|
||||
{
|
||||
getSessionTypeFromHint(result, protocolHint);
|
||||
return;
|
||||
}
|
||||
|
||||
//If sessionDesktop is a known WM, set it.
|
||||
applyPrettyNameIfWM(result, result->sessionDesktop, &protocolHint);
|
||||
|
||||
//Search for missing DE / WM in processes
|
||||
getFromProcDir(instance, result, &protocolHint);
|
||||
|
||||
//Fallback for unknown WMs and DEs. This will falsely detect DEs as WMs if they (and their used WM) are unknown
|
||||
if(result->wmPrettyName.length == 0 && result->dePrettyName.length == 0)
|
||||
{
|
||||
ffStrbufSetS(&result->wmProcessName, result->sessionDesktop);
|
||||
ffStrbufSetS(&result->wmPrettyName, result->sessionDesktop);
|
||||
}
|
||||
|
||||
getSessionTypeFromHint(result, protocolHint);
|
||||
}
|
||||
|
||||
const FFWMDEResult* ffDetectWMDE(FFinstance* instance)
|
||||
{
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
static FFWMDEResult result;
|
||||
static bool init = false;
|
||||
pthread_mutex_lock(&mutex);
|
||||
if(init)
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
init = true;
|
||||
|
||||
ffStrbufInit(&result.wmProcessName);
|
||||
ffStrbufInit(&result.wmPrettyName);
|
||||
ffStrbufInit(&result.wmProtocolName);
|
||||
ffStrbufInit(&result.deProcessName);
|
||||
ffStrbufInit(&result.dePrettyName);
|
||||
ffStrbufInit(&result.deVersion);
|
||||
|
||||
getSessionDesktop(&result);
|
||||
getSessionTypeFromEnv(&result);
|
||||
|
||||
//Don't run anyting when on TTY. This prevents us to catch process from other users in at least that case.
|
||||
if(ffStrbufIgnCaseCompS(&result.wmProtocolName, "TTY") != 0)
|
||||
getWMDE(instance, &result);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
return &result;
|
||||
}
|
||||
+2
-4
@@ -129,8 +129,7 @@ static inline void printCommandHelp(const char* command)
|
||||
}
|
||||
else if(strcasecmp(command, "de-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("de", "{3} {4}", 4,
|
||||
"Session desktop",
|
||||
constructAndPrintCommandHelpFormat("de", "{2} {3}", 3,
|
||||
"DE process name",
|
||||
"DE pretty name",
|
||||
"DE version"
|
||||
@@ -138,8 +137,7 @@ static inline void printCommandHelp(const char* command)
|
||||
}
|
||||
else if(strcasecmp(command, "wm-format") == 0)
|
||||
{
|
||||
constructAndPrintCommandHelpFormat("wm", "{3} ({4})", 4,
|
||||
"Session desktop",
|
||||
constructAndPrintCommandHelpFormat("wm", "{2} ({3})", 3,
|
||||
"WM process name",
|
||||
"WM pretty name",
|
||||
"WM protocol name"
|
||||
|
||||
+16
-9
@@ -203,16 +203,23 @@ typedef struct FFTerminalShellResult
|
||||
FFstrbuf userShellVersion;
|
||||
} FFTerminalShellResult;
|
||||
|
||||
typedef struct FFWMDEResult
|
||||
typedef struct FFResolutionResult
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t refreshRate;
|
||||
} FFResolutionResult;
|
||||
|
||||
typedef struct FFDisplayServerResult
|
||||
{
|
||||
const char* sessionDesktop;
|
||||
FFstrbuf wmProcessName;
|
||||
FFstrbuf wmPrettyName;
|
||||
FFstrbuf wmProtocolName;
|
||||
FFstrbuf deProcessName;
|
||||
FFstrbuf dePrettyName;
|
||||
FFstrbuf deVersion;
|
||||
} FFWMDEResult;
|
||||
FFlist resolutions; //List of FFResolutionResult
|
||||
} FFDisplayServerResult;
|
||||
|
||||
typedef enum FFformatargtype
|
||||
{
|
||||
@@ -342,10 +349,10 @@ void ffPrintColor(const FFstrbuf* colorValue);
|
||||
// The last occurence of start in the first file will be the one used
|
||||
bool ffParsePropFileValues(const char* filename, uint32_t numQueries, FFpropquery* queries);
|
||||
bool ffParsePropFile(const char* filename, const char* start, FFstrbuf* buffer);
|
||||
bool ffParsePropFileHomeValues(FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
|
||||
bool ffParsePropFileHome(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
|
||||
bool ffParsePropFileConfigValues(FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
|
||||
bool ffParsePropFileConfig(FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
|
||||
bool ffParsePropFileHomeValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
|
||||
bool ffParsePropFileHome(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
|
||||
bool ffParsePropFileConfigValues(const FFinstance* instance, const char* relativeFile, uint32_t numQueries, FFpropquery* queries);
|
||||
bool ffParsePropFileConfig(const FFinstance* instance, const char* relativeFile, const char* start, FFstrbuf* buffer);
|
||||
|
||||
//common/processing.c
|
||||
void ffProcessAppendStdOut(FFstrbuf* buffer, char* const argv[]);
|
||||
@@ -397,8 +404,8 @@ const FFGTKResult* ffDetectGTK2(FFinstance* instance);
|
||||
const FFGTKResult* ffDetectGTK4(FFinstance* instance);
|
||||
const FFGTKResult* ffDetectGTK3(FFinstance* instance);
|
||||
|
||||
//detection/wmde.c
|
||||
const FFWMDEResult* ffDetectWMDE(FFinstance* instance);
|
||||
//detection/displayServer.c
|
||||
const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance);
|
||||
|
||||
//detection/terminalShell.c
|
||||
const FFTerminalShellResult* ffDetectTerminalShell(FFinstance* instance);
|
||||
|
||||
@@ -175,7 +175,7 @@ static bool printCursorFromEnv(FFinstance* instance)
|
||||
|
||||
void ffPrintCursor(FFinstance* instance)
|
||||
{
|
||||
const FFWMDEResult* wmde = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
|
||||
{
|
||||
|
||||
+2
-3
@@ -3,11 +3,11 @@
|
||||
#include <string.h>
|
||||
|
||||
#define FF_DE_MODULE_NAME "DE"
|
||||
#define FF_DE_NUM_FORMAT_ARGS 4
|
||||
#define FF_DE_NUM_FORMAT_ARGS 3
|
||||
|
||||
void ffPrintDesktopEnvironment(FFinstance* instance)
|
||||
{
|
||||
const FFWMDEResult* result = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* result = ffConnectDisplayServer(instance);
|
||||
|
||||
if(result->dePrettyName.length == 0)
|
||||
{
|
||||
@@ -32,7 +32,6 @@ void ffPrintDesktopEnvironment(FFinstance* instance)
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, FF_DE_MODULE_NAME, 0, &instance->config.deKey, &instance->config.deFormat, NULL, FF_DE_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result->sessionDesktop},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->deProcessName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->dePrettyName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->deVersion}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
void ffPrintFont(FFinstance* instance)
|
||||
{
|
||||
const FFWMDEResult* wmde = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
|
||||
{
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
void ffPrintIcons(FFinstance* instance)
|
||||
{
|
||||
const FFWMDEResult* wmde = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
|
||||
{
|
||||
|
||||
+7
-485
@@ -1,25 +1,16 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define FF_RESOLUTION_MODULE_NAME "Resolution"
|
||||
#define FF_RESOLUTION_NUM_FORMAT_ARGS 3
|
||||
|
||||
typedef struct ResolutionResult
|
||||
void ffPrintResolution(FFinstance* instance)
|
||||
{
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t refreshRate;
|
||||
} ResolutionResult;
|
||||
const FFDisplayServerResult* dsResult = ffConnectDisplayServer(instance);
|
||||
|
||||
static bool printResolutionResultList(FFinstance* instance, FFlist* results)
|
||||
{
|
||||
for(uint32_t i = 0; i < results->length; i++)
|
||||
for(uint32_t i = 0; i < dsResult->resolutions.length; i++)
|
||||
{
|
||||
ResolutionResult* result = ffListGet(results, i);
|
||||
uint8_t moduleIndex = results->length == 1 ? 0 : (uint8_t) i + 1;
|
||||
FFResolutionResult* result = ffListGet(&dsResult->resolutions, i);
|
||||
uint8_t moduleIndex = dsResult->resolutions.length == 1 ? 0 : (uint8_t) i + 1;
|
||||
|
||||
if(instance->config.resolutionFormat.length == 0)
|
||||
{
|
||||
@@ -41,475 +32,6 @@ static bool printResolutionResultList(FFinstance* instance, FFlist* results)
|
||||
}
|
||||
}
|
||||
|
||||
bool res = results->length > 0;
|
||||
ffListDestroy(results);
|
||||
return res;
|
||||
}
|
||||
|
||||
static void printResolutionDRMBackend(FFinstance* instance)
|
||||
{
|
||||
const char* drmDirPath = "/sys/class/drm/";
|
||||
|
||||
DIR* dirp = opendir(drmDirPath);
|
||||
if(dirp == NULL)
|
||||
{
|
||||
ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS, "Couldn't connect to a display server or open %s", drmDirPath);
|
||||
return;
|
||||
}
|
||||
|
||||
FFstrbuf drmDir;
|
||||
ffStrbufInitA(&drmDir, 64);
|
||||
ffStrbufAppendS(&drmDir, drmDirPath);
|
||||
|
||||
uint32_t drmDirLength = drmDir.length;
|
||||
|
||||
FFlist modes;
|
||||
ffListInitA(&modes, sizeof(ResolutionResult), 4);
|
||||
|
||||
struct dirent* entry;
|
||||
|
||||
while((entry = readdir(dirp)) != NULL)
|
||||
{
|
||||
ffStrbufAppendS(&drmDir, entry->d_name);
|
||||
ffStrbufAppendS(&drmDir, "/modes");
|
||||
|
||||
FILE* modeFile = fopen(drmDir.chars, "r");
|
||||
if(modeFile == NULL)
|
||||
{
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
continue;
|
||||
}
|
||||
|
||||
ResolutionResult* result = ffListAdd(&modes);
|
||||
result->width = 0;
|
||||
result->height = 0;
|
||||
result->refreshRate = 0;
|
||||
|
||||
int scanned = fscanf(modeFile, "%ix%i", &result->width, &result->height);
|
||||
if(scanned < 2 || result->width == 0 || result->height == 0)
|
||||
--modes.length;
|
||||
|
||||
fclose(modeFile);
|
||||
ffStrbufSubstrBefore(&drmDir, drmDirLength);
|
||||
}
|
||||
|
||||
closedir(dirp);
|
||||
ffStrbufDestroy(&drmDir);
|
||||
|
||||
if(modes.length == 0)
|
||||
{
|
||||
ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS, "Couldn't connect to a display server or find a resolution in %s", drmDirPath);
|
||||
ffListDestroy(&modes);
|
||||
return;
|
||||
}
|
||||
|
||||
printResolutionResultList(instance, &modes);
|
||||
}
|
||||
|
||||
#if defined(FF_HAVE_XRANDR) || defined(FF_HAVE_WAYLAND)
|
||||
|
||||
static uint32_t parseRefreshRate(int32_t refreshRate)
|
||||
{
|
||||
if(refreshRate <= 0)
|
||||
return 0;
|
||||
|
||||
int remainder = refreshRate % 5;
|
||||
if(remainder >= 3)
|
||||
refreshRate += (5 - remainder);
|
||||
else
|
||||
refreshRate -= remainder;
|
||||
|
||||
//All other typicall refresh rates are dividable by 5
|
||||
if(refreshRate == 145)
|
||||
refreshRate = 144;
|
||||
|
||||
return (uint32_t) refreshRate;
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_XRANDR || FF_HAVE_WAYLAND
|
||||
|
||||
#ifdef FF_HAVE_X11
|
||||
#include <X11/Xlib.h>
|
||||
|
||||
static void x11AddScreenAsResult(FFlist* results, Screen* screen, uint32_t refreshRate)
|
||||
{
|
||||
if(WidthOfScreen(screen) == 0 || HeightOfScreen(screen) == 0)
|
||||
return;
|
||||
|
||||
ResolutionResult* result = ffListAdd(results);
|
||||
result->width = (uint32_t) WidthOfScreen(screen);
|
||||
result->height = (uint32_t) HeightOfScreen(screen);
|
||||
result->refreshRate = refreshRate;
|
||||
}
|
||||
|
||||
static bool printResolutionX11Backend(FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_LOAD(x11, "libX11.so", instance->config.libX11, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(x11, XOpenDisplay, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(x11, XCloseDisplay, false)
|
||||
|
||||
Display* display = ffXOpenDisplay(x11);
|
||||
if(display == NULL)
|
||||
{
|
||||
dlclose(x11);
|
||||
return false;
|
||||
}
|
||||
|
||||
FFlist results;
|
||||
ffListInitA(&results, sizeof(ResolutionResult), 4);
|
||||
|
||||
for(int i = 0; i < ScreenCount(display); i++)
|
||||
x11AddScreenAsResult(&results, ScreenOfDisplay(display, i), 0);
|
||||
|
||||
ffXCloseDisplay(display);
|
||||
dlclose(x11);
|
||||
|
||||
return printResolutionResultList(instance, &results);
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_X11
|
||||
|
||||
#ifdef FF_HAVE_XRANDR
|
||||
#include <X11/extensions/Xrandr.h>
|
||||
|
||||
typedef struct XrandrData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(XRRGetScreenInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRConfigCurrentConfiguration)
|
||||
FF_LIBRARY_SYMBOL(XRRConfigCurrentRate)
|
||||
FF_LIBRARY_SYMBOL(XRRGetMonitors)
|
||||
FF_LIBRARY_SYMBOL(XRRGetScreenResources)
|
||||
FF_LIBRARY_SYMBOL(XRRGetOutputInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRGetCrtcInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeCrtcInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeOutputInfo)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeScreenResources)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeMonitors)
|
||||
FF_LIBRARY_SYMBOL(XRRFreeScreenConfigInfo)
|
||||
|
||||
//Init once
|
||||
Display* display;
|
||||
FFlist results;
|
||||
|
||||
//Init per screen
|
||||
uint32_t defaultRefreshRate;
|
||||
XRRScreenResources* screenResources;
|
||||
} XrandrData;
|
||||
|
||||
static XRRModeInfo* xrandrGetModeInfo(XRRScreenResources* screenResources, RRMode mode)
|
||||
{
|
||||
for(int i = 0; i < screenResources->nmode; i++)
|
||||
{
|
||||
if(screenResources->modes[i].id == mode)
|
||||
return &screenResources->modes[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static bool xrandrHandleOutputInfo(XrandrData* data, XRROutputInfo* outputInfo)
|
||||
{
|
||||
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, outputInfo->crtc);
|
||||
if(crtcInfo == NULL)
|
||||
return false;
|
||||
|
||||
XRRModeInfo* modeInfo = xrandrGetModeInfo(data->screenResources, crtcInfo->mode);
|
||||
if(modeInfo == NULL || modeInfo->width == 0 || modeInfo->height == 0)
|
||||
{
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
return false;
|
||||
}
|
||||
|
||||
ResolutionResult* result = ffListAdd(&data->results);
|
||||
result->width = modeInfo->width;
|
||||
result->height = modeInfo->height;
|
||||
result->refreshRate = parseRefreshRate((int32_t) (modeInfo->dotClock / (modeInfo->hTotal * modeInfo->vTotal)));
|
||||
|
||||
if(result->refreshRate == 0)
|
||||
result->refreshRate = data->defaultRefreshRate;
|
||||
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool xrandrHandleMonitorFallback(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
{
|
||||
if(monitorInfo->width == 0 || monitorInfo->height == 0)
|
||||
return false;
|
||||
|
||||
ResolutionResult* result = ffListAdd(&data->results);
|
||||
result->width = (uint32_t) monitorInfo->width;
|
||||
result->height = (uint32_t) monitorInfo->height;
|
||||
result->refreshRate = (uint32_t) data->defaultRefreshRate;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
{
|
||||
bool foundMode = false;
|
||||
|
||||
for(int i = 0; i < monitorInfo->noutput; i++)
|
||||
{
|
||||
XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, monitorInfo->outputs[i]);
|
||||
if(outputInfo == NULL)
|
||||
continue;
|
||||
|
||||
if(xrandrHandleOutputInfo(data, outputInfo))
|
||||
foundMode = true;
|
||||
|
||||
data->ffXRRFreeOutputInfo(outputInfo);
|
||||
}
|
||||
|
||||
if(!foundMode)
|
||||
return xrandrHandleMonitorFallback(data, monitorInfo);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline bool xrandrLoopMonitors(XrandrData* data, XRRMonitorInfo* monitorInfos, int numberOfMonitors, bool(*monitorFunc)(XrandrData* data, XRRMonitorInfo* monitorInfo))
|
||||
{
|
||||
bool foundAMonitor = false;
|
||||
|
||||
for(int i = 0; i < numberOfMonitors; i++)
|
||||
{
|
||||
if(monitorFunc(data, &monitorInfos[i]))
|
||||
foundAMonitor = true;
|
||||
}
|
||||
|
||||
return foundAMonitor;
|
||||
}
|
||||
|
||||
static void xrandrHandleScreen(XrandrData* data, Screen* screen)
|
||||
{
|
||||
Window window = RootWindowOfScreen(screen);
|
||||
|
||||
XRRScreenConfiguration* screenConfiguration = data->ffXRRGetScreenInfo(data->display, window);
|
||||
if(screenConfiguration != NULL)
|
||||
{
|
||||
data->defaultRefreshRate = (uint32_t) data->ffXRRConfigCurrentRate(screenConfiguration);
|
||||
data->ffXRRFreeScreenConfigInfo(screenConfiguration);
|
||||
}
|
||||
else
|
||||
data->defaultRefreshRate = 0;
|
||||
|
||||
int numberOfMonitors;
|
||||
XRRMonitorInfo* monitorInfos = data->ffXRRGetMonitors(data->display, window, True, &numberOfMonitors);
|
||||
if(monitorInfos == NULL)
|
||||
{
|
||||
x11AddScreenAsResult(&data->results, screen, data->defaultRefreshRate);
|
||||
return;
|
||||
}
|
||||
|
||||
data->screenResources = data->ffXRRGetScreenResources(data->display, window);
|
||||
|
||||
bool foundAMonitor;
|
||||
|
||||
if(data->screenResources != NULL)
|
||||
foundAMonitor = xrandrLoopMonitors(data, monitorInfos, numberOfMonitors, xrandrHandleMonitor);
|
||||
else
|
||||
foundAMonitor = xrandrLoopMonitors(data, monitorInfos, numberOfMonitors, xrandrHandleMonitorFallback);
|
||||
|
||||
if(!foundAMonitor)
|
||||
x11AddScreenAsResult(&data->results, screen, data->defaultRefreshRate);
|
||||
|
||||
data->ffXRRFreeScreenResources(data->screenResources);
|
||||
data->ffXRRFreeMonitors(monitorInfos);
|
||||
}
|
||||
|
||||
static bool printResolutionXrandrBackend(FFinstance* instance)
|
||||
{
|
||||
FF_LIBRARY_LOAD(xrandr, "libXrandr.so", instance->config.libXrandr, false);
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(xrandr, XOpenDisplay, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xrandr, XCloseDisplay, false)
|
||||
|
||||
XrandrData data;
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetScreenInfo, XRRGetScreenInfo, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRConfigCurrentRate, XRRConfigCurrentRate, false);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetMonitors, XRRGetMonitors, false);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetScreenResources, XRRGetScreenResources, false);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetOutputInfo, XRRGetOutputInfo, false);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRGetCrtcInfo, XRRGetCrtcInfo, false);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeCrtcInfo, XRRFreeCrtcInfo, false);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeOutputInfo, XRRFreeOutputInfo, false);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeScreenResources, XRRFreeScreenResources, false);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeMonitors, XRRFreeMonitors, false);
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeScreenConfigInfo, XRRFreeScreenConfigInfo, false);
|
||||
|
||||
data.display = ffXOpenDisplay(NULL);
|
||||
if(data.display == NULL)
|
||||
{
|
||||
dlclose(xrandr);
|
||||
return false;
|
||||
}
|
||||
|
||||
ffListInitA(&data.results, sizeof(ResolutionResult), 4);
|
||||
|
||||
for(int i = 0; i < ScreenCount(data.display); i++)
|
||||
xrandrHandleScreen(&data, ScreenOfDisplay(data.display, i));
|
||||
|
||||
ffXCloseDisplay(data.display);
|
||||
dlclose(xrandr);
|
||||
|
||||
return printResolutionResultList(instance, &data.results);
|
||||
}
|
||||
#endif // FF_HAVE_XRANDR
|
||||
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
#include <wayland-client.h>
|
||||
|
||||
typedef struct WaylandData
|
||||
{
|
||||
FFinstance* instance;
|
||||
FFlist results;
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_add_listener)
|
||||
FF_LIBRARY_SYMBOL(wl_proxy_destroy)
|
||||
const struct wl_interface* ffwl_output_interface;
|
||||
struct wl_output_listener output_listener;
|
||||
} WaylandData;
|
||||
|
||||
static void waylandGlobalRemoveListener(void* data, struct wl_registry* wl_registry, uint32_t name){
|
||||
FF_UNUSED(data, wl_registry, name);
|
||||
return;
|
||||
}
|
||||
|
||||
static void waylandOutputGeometryListener(void* data, struct wl_output* wl_output, int32_t x, int32_t y, int32_t physical_width, int32_t physical_height, int32_t subpixel, const char* make, const char* model, int32_t transform)
|
||||
{
|
||||
FF_UNUSED(data, wl_output, x, y, physical_width, physical_height, subpixel, make, model, transform);
|
||||
return;
|
||||
}
|
||||
|
||||
static void waylandOutputDoneListener(void* data, struct wl_output* wl_output)
|
||||
{
|
||||
FF_UNUSED(data, wl_output);
|
||||
return;
|
||||
}
|
||||
|
||||
static void waylandOutputScaleListener(void* data, struct wl_output* wl_output, int32_t factor)
|
||||
{
|
||||
FF_UNUSED(data, wl_output, factor);
|
||||
return;
|
||||
}
|
||||
|
||||
static void waylandOutputModeListener(void* data, struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
|
||||
{
|
||||
if(!(flags & WL_OUTPUT_MODE_CURRENT))
|
||||
return;
|
||||
|
||||
WaylandData* wldata = (WaylandData*) data;
|
||||
|
||||
wldata->ffwl_proxy_destroy((struct wl_proxy*) output);
|
||||
|
||||
if(width <= 0 || height <= 0)
|
||||
return;
|
||||
|
||||
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
ResolutionResult* result = ffListAdd(&wldata->results);
|
||||
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
result->width = (uint32_t) width;
|
||||
result->height = (uint32_t) height;
|
||||
result->refreshRate = parseRefreshRate(refreshRate / 1000);
|
||||
}
|
||||
|
||||
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
|
||||
{
|
||||
if(strcmp(interface, "wl_output") == 0)
|
||||
{
|
||||
WaylandData* wldata = (WaylandData*) data;
|
||||
|
||||
struct wl_output* output = (struct wl_output*) wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy *) registry, WL_REGISTRY_BIND, wldata->ffwl_output_interface, version, name, wldata->ffwl_output_interface->name, version, NULL);
|
||||
if(output == NULL)
|
||||
return;
|
||||
|
||||
wldata->ffwl_proxy_add_listener((struct wl_proxy*) output, (void(**)(void)) &wldata->output_listener, data);
|
||||
}
|
||||
}
|
||||
|
||||
static bool printResolutionWaylandBackend(FFinstance* instance)
|
||||
{
|
||||
if(getenv("XDG_RUNTIME_DIR") == NULL)
|
||||
return false;
|
||||
|
||||
const char* sessionType = getenv("XDG_SESSION_TYPE");
|
||||
if(sessionType != NULL && strcasecmp(sessionType, "wayland") != 0)
|
||||
return false;
|
||||
|
||||
FF_LIBRARY_LOAD(wayland, "libwayland-client.so", instance->config.libWayland, false);
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_connect, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_dispatch, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_roundtrip, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_proxy_marshal_constructor, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_display_disconnect, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL(wayland, wl_registry_interface, false)
|
||||
|
||||
WaylandData data;
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_marshal_constructor_versioned, wl_proxy_marshal_constructor_versioned, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_add_listener, wl_proxy_add_listener, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_output_interface, wl_output_interface, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(wayland, data.ffwl_proxy_destroy, wl_proxy_destroy, false)
|
||||
|
||||
struct wl_display* display = ffwl_display_connect(NULL);
|
||||
if(display == NULL)
|
||||
{
|
||||
dlclose(wayland);
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wl_registry* registry = (struct wl_registry*) ffwl_proxy_marshal_constructor((struct wl_proxy*) display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
|
||||
if(registry == NULL)
|
||||
{
|
||||
ffwl_display_disconnect(display);
|
||||
dlclose(wayland);
|
||||
return false;
|
||||
}
|
||||
|
||||
data.instance = instance;
|
||||
ffListInitA(&data.results, sizeof(ResolutionResult), 4);
|
||||
|
||||
struct wl_registry_listener regestry_listener;
|
||||
regestry_listener.global = waylandGlobalAddListener;
|
||||
regestry_listener.global_remove = waylandGlobalRemoveListener;
|
||||
|
||||
data.output_listener.geometry = waylandOutputGeometryListener;
|
||||
data.output_listener.mode = waylandOutputModeListener;
|
||||
data.output_listener.done = waylandOutputDoneListener;
|
||||
data.output_listener.scale = waylandOutputScaleListener;
|
||||
|
||||
data.ffwl_proxy_add_listener((struct wl_proxy*) registry, (void(**)(void)) ®estry_listener, &data);
|
||||
ffwl_display_dispatch(display);
|
||||
ffwl_display_roundtrip(display);
|
||||
|
||||
data.ffwl_proxy_destroy((struct wl_proxy*) registry);
|
||||
ffwl_display_disconnect(display);
|
||||
dlclose(wayland);
|
||||
|
||||
return printResolutionResultList(instance, &data.results);
|
||||
}
|
||||
|
||||
#endif //FF_HAVE_WAYLAND
|
||||
|
||||
void ffPrintResolution(FFinstance* instance)
|
||||
{
|
||||
if(
|
||||
#if FF_HAVE_WAYLAND
|
||||
printResolutionWaylandBackend(instance) ||
|
||||
#endif
|
||||
#if FF_HAVE_XRANDR
|
||||
printResolutionXrandrBackend(instance) ||
|
||||
#endif
|
||||
#if FF_HAVE_X11
|
||||
printResolutionX11Backend(instance) ||
|
||||
#endif
|
||||
false
|
||||
) return;
|
||||
|
||||
printResolutionDRMBackend(instance);
|
||||
if(dsResult->resolutions.length == 0)
|
||||
ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS, "Couldn't detect resolution");
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ static void printTerminalFont(FFinstance* instance, const char* raw, FFfont* fon
|
||||
|
||||
static const char* getSystemMonospaceFont(FFinstance* instance)
|
||||
{
|
||||
const FFWMDEResult* wmde = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->dePrettyName, "Cinnamon") == 0)
|
||||
{
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@
|
||||
|
||||
void ffPrintTheme(FFinstance* instance)
|
||||
{
|
||||
const FFWMDEResult* wmde = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* wmde = ffConnectDisplayServer(instance);
|
||||
|
||||
if(ffStrbufIgnCaseCompS(&wmde->wmProtocolName, "TTY") == 0)
|
||||
{
|
||||
|
||||
+3
-4
@@ -1,11 +1,11 @@
|
||||
#include "fastfetch.h"
|
||||
|
||||
#define FF_WM_MODULE_NAME "WM"
|
||||
#define FF_WM_NUM_FORMAT_ARGS 4
|
||||
#define FF_WM_NUM_FORMAT_ARGS 3
|
||||
|
||||
void ffPrintWM(FFinstance* instance)
|
||||
{
|
||||
const FFWMDEResult* result = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* result = ffConnectDisplayServer(instance);
|
||||
|
||||
if(result->wmPrettyName.length == 0)
|
||||
{
|
||||
@@ -15,7 +15,7 @@ void ffPrintWM(FFinstance* instance)
|
||||
|
||||
if(instance->config.wmFormat.length == 0)
|
||||
{
|
||||
ffPrintLogoAndKey(instance, "WM", 0, &instance->config.wmKey);
|
||||
ffPrintLogoAndKey(instance, FF_WM_MODULE_NAME, 0, &instance->config.wmKey);
|
||||
|
||||
if(result->wmPrettyName.length == 0 && result->wmProcessName.length == 0)
|
||||
{
|
||||
@@ -41,7 +41,6 @@ void ffPrintWM(FFinstance* instance)
|
||||
else
|
||||
{
|
||||
ffPrintFormatString(instance, FF_WM_MODULE_NAME, 0, &instance->config.wmKey, &instance->config.wmFormat, NULL, FF_WM_NUM_FORMAT_ARGS, (FFformatarg[]){
|
||||
{FF_FORMAT_ARG_TYPE_STRING, result->sessionDesktop},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->wmProcessName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->wmPrettyName},
|
||||
{FF_FORMAT_ARG_TYPE_STRBUF, &result->wmProtocolName}
|
||||
|
||||
@@ -223,7 +223,7 @@ static void printOpenbox(FFinstance* instance, const FFstrbuf* dePrettyName)
|
||||
|
||||
void ffPrintWMTheme(FFinstance* instance)
|
||||
{
|
||||
const FFWMDEResult* result = ffDetectWMDE(instance);
|
||||
const FFDisplayServerResult* result = ffConnectDisplayServer(instance);
|
||||
|
||||
if(result->wmPrettyName.length == 0)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user