diff --git a/CMakeLists.txt b/CMakeLists.txt index f59d76886..f6e2c0384 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -101,8 +101,6 @@ set(SRCS src/modules/packages.c src/modules/shell.c src/modules/resolution.c - src/modules/resolution_x11.c - src/modules/resolution_wayland.c src/modules/de.c src/modules/wm.c src/modules/wmtheme.c diff --git a/src/modules/resolution.c b/src/modules/resolution.c index 061a3411b..29abadcef 100644 --- a/src/modules/resolution.c +++ b/src/modules/resolution.c @@ -1,6 +1,25 @@ -#include "resolution.h" +#include "fastfetch.h" -void ffPrintResolutionValue(FFinstance* instance, uint8_t moduleIndex, FFcache* cache, int width, int height, int refreshRate) +#include +#include +#include +#include +#include + +#define FF_RESOLUTION_MODULE_NAME "Resolution" +#define FF_RESOLUTION_NUM_FORMAT_ARGS 3 + +#define FF_LIBRARY_LOAD(libraryNameUser, libraryNameDefault) dlopen(libraryNameUser.length == 0 ? libraryNameDefault : libraryNameUser.chars, RTLD_LAZY); \ + if(dlerror() != NULL) \ + return false; + +#define FF_LIBRARY_LOAD_SYMBOL(library, symbolName) dlsym(library, symbolName); \ + if(dlerror() != NULL) { \ + dlclose(library); \ + return false; \ + } + +static void printResolution(FFinstance* instance, uint8_t moduleIndex, FFcache* cache, int width, int height, int refreshRate) { FFstrbuf value; ffStrbufInitA(&value, 32); @@ -16,16 +35,399 @@ void ffPrintResolutionValue(FFinstance* instance, uint8_t moduleIndex, FFcache* }); } +typedef struct DRMData +{ + int width; + int height; +} DRMData; + +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(DRMData), 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; + } + + DRMData* data = ffListAdd(&modes); + data->width = 0; + data->height = 0; + fscanf(modeFile, "%ix%i", &data->width, &data->height); + + if(data->width == 0 || data->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; + } + + FFcache cache; + ffCacheOpenWrite(instance, FF_RESOLUTION_MODULE_NAME, &cache); + + for(uint32_t i = 0; i < modes.length; i++) + { + DRMData* data = ffListGet(&modes, i); + printResolution(instance, modes.length == 1 ? 0 : i + 1, &cache, data->width, data->height, 0); + } + + ffCacheClose(&cache); + + ffListDestroy(&modes); +} + +static Display* xOpenDisplay(void* library) +{ + Display*(*ffXOpenDisplay)(const char*) = dlsym(library, "XOpenDisplay"); + if(dlerror() != NULL) + return NULL; + + Display* display = ffXOpenDisplay(NULL); + if(display == NULL) + return NULL; + + return display; +} + +static void xCloseDisplay(void* library, Display* display) +{ + int(*ffXCloseDisplay)(Display*) = dlsym(library, "XCloseDisplay"); + if(dlerror() != NULL) + ffXCloseDisplay(display); +} + +static bool printResolutionX11Backend(FFinstance* instance) +{ + void* x11 = FF_LIBRARY_LOAD(instance->config.libX11, "libX11.so"); + + Display* display = xOpenDisplay(instance); + if(display == NULL) + { + dlclose(x11); + return false; + } + + int screenCount = ScreenCount(display); + if(screenCount < 1) + { + xCloseDisplay(x11, display); + dlclose(x11); + return false; + } + + FFcache cache; + ffCacheOpenWrite(instance, FF_RESOLUTION_MODULE_NAME, &cache); + + for(int i = 0; i < screenCount; i++) + { + Screen* screen = ScreenOfDisplay(display, i); + uint8_t moduleIndex = screenCount == 1 ? 0 : i + 1; + printResolution(instance, moduleIndex, &cache, WidthOfScreen(screen), HeightOfScreen(screen), 0); + } + + ffCacheClose(&cache); + + xCloseDisplay(x11, display); + dlclose(x11); + + return true; +} + +static int xrandrGetCurrentRate(void* xrandr, Display* display) +{ + XRRScreenConfiguration*(*ffXRRGetScreenInfo)(Display*, Window) = dlsym(xrandr, "XRRGetScreenInfo"); + if(dlerror() != NULL) + return 0; + + short(*ffXRRConfigCurrentRate)(XRRScreenConfiguration*) = dlsym(xrandr, "XRRConfigCurrentRate"); + if(dlerror() != NULL) + return 0; + + + XRRScreenConfiguration* xrrscreenconf = ffXRRGetScreenInfo(display, DefaultRootWindow(display)); + if(dlerror() != NULL) + return 0; + + short currentRate = ffXRRConfigCurrentRate(xrrscreenconf); + + void(*ffXRRFreeScreenConfigInfo)(XRRScreenConfiguration*) = dlsym(xrandr, "XRRFreeScreenConfigInfo"); + if(dlerror() != NULL) + ffXRRFreeScreenConfigInfo(xrrscreenconf); + + return (int) currentRate; +} + +static bool printResolutionXrandrBackend(FFinstance* instance) +{ + void* xrandr = FF_LIBRARY_LOAD(instance->config.libXrandr, "libXrandr.so"); + + XRRMonitorInfo*(*ffXRRGetMonitors)(Display*, Window, Bool, int*) = FF_LIBRARY_LOAD_SYMBOL(xrandr, "XRRGetMonitors"); + + Display* display = xOpenDisplay(instance); + if(display == NULL) + { + dlclose(xrandr); + return false; + } + + int numberOfMonitors; + XRRMonitorInfo* monitors = ffXRRGetMonitors(display, DefaultRootWindow(display), False, &numberOfMonitors); + if(monitors == NULL) + { + xCloseDisplay(xrandr, display); + dlclose(xrandr); + return false; + } + + if(numberOfMonitors < 1) + { + xCloseDisplay(xrandr, display); + dlclose(xrandr); + return false; + } + + int refreshRate = xrandrGetCurrentRate(xrandr, display); + + FFcache cache; + ffCacheOpenWrite(instance, FF_RESOLUTION_MODULE_NAME, &cache); + + for(int i = 0; i < numberOfMonitors; i++) + { + uint8_t moduleIndex = numberOfMonitors == 1 ? 0 : i + 1; + printResolution(instance, moduleIndex, &cache, monitors[i].width, monitors[i].height, refreshRate); + } + + ffCacheClose(&cache); + + void(*ffXRRFreeMonitors)(XRRMonitorInfo*) = dlsym(xrandr, "XRRFreeMonitors"); + if(dlerror() != NULL) + ffXRRFreeMonitors(monitors); + + xCloseDisplay(xrandr, display); + dlclose(xrandr); + + return true; +} + +typedef struct WaylandData +{ + FFinstance* instance; + void* wayland; + FFcache cache; + struct wl_proxy*(*ffwl_proxy_marshal_constructor_versioned)(struct wl_proxy*, uint32_t, const struct wl_interface*, uint32_t, ...); + int(*ffwl_proxy_add_listener)(struct wl_proxy*, void (**)(void), void *data); + void(*ffwl_proxy_destroy)(struct wl_proxy*); + const struct wl_interface* ffwl_output_interface; + struct wl_output_listener output_listener; + int8_t moduleCounter; + int8_t numModules; +} WaylandData; + +static void waylandGlobalRemoveListener(void* data, struct wl_registry* wl_registry, uint32_t name){ + UNUSED(data); + UNUSED(wl_registry); + UNUSED(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) +{ + UNUSED(data); + UNUSED(wl_output); + UNUSED(x); + UNUSED(y); + UNUSED(physical_width); + UNUSED(physical_height); + UNUSED(subpixel); + UNUSED(make); + UNUSED(model); + UNUSED(transform); +} + +static void waylandOutputDoneListener(void* data, struct wl_output* wl_output) +{ + UNUSED(data); + UNUSED(wl_output); +} + +static void waylandOutputScaleListener(void* data, struct wl_output* wl_output, int32_t factor) +{ + UNUSED(data); + UNUSED(wl_output); + UNUSED(factor); +} + +static int parseRefreshRate(int32_t refreshRate) +{ + if(refreshRate <= 0) + return 0; + + refreshRate /= 1000; //to Hz + + 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 refreshRate; +} + +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->moduleCounter; + printResolution(wldata->instance, wldata->numModules == 1 ? 0 : wldata->moduleCounter, &wldata->cache, width, height, parseRefreshRate(refreshRate)); + + if(wldata->ffwl_proxy_destroy != NULL) + wldata->ffwl_proxy_destroy((struct wl_proxy*) output); +} + +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->numModules; + wldata->ffwl_proxy_add_listener((struct wl_proxy*) output, (void(**)(void)) &wldata->output_listener, data); + } +} + +static inline void waylandDisplayDisconnect(void* wayland, struct wl_display* display) +{ + void(*ffwl_display_disconnect)(struct wl_display*) = dlsym(wayland, "wl_display_disconnect"); + if(dlerror() != NULL) + ffwl_display_disconnect(display); +} + +static bool printResolutionWaylandBackend(FFinstance* instance) +{ + const char* sessionType = getenv("XDG_SESSION_TYPE"); + if(sessionType != NULL && strcasecmp(sessionType, "wayland") != 0) + return false; + + void* wayland = FF_LIBRARY_LOAD(instance->config.libWayland, "libwayland-client.so"); + + WaylandData data; + data.instance = instance; + data.wayland = wayland; + data.moduleCounter = 0; + data.numModules = 0; + + struct wl_display*(*ffwl_display_connect)(const char*) = FF_LIBRARY_LOAD_SYMBOL(wayland, "wl_display_connect"); + int(*ffwl_display_dispatch)(struct wl_display*) = FF_LIBRARY_LOAD_SYMBOL(wayland, "wl_display_dispatch"); + void(*ffwl_display_roundtrip)(struct wl_display*) = FF_LIBRARY_LOAD_SYMBOL(wayland, "wl_display_roundtrip"); + struct wl_proxy*(*ffwl_proxy_marshal_constructor)(struct wl_proxy*, uint32_t, const struct wl_interface*, ...) = FF_LIBRARY_LOAD_SYMBOL(wayland, "wl_proxy_marshal_constructor"); + data.ffwl_proxy_marshal_constructor_versioned = FF_LIBRARY_LOAD_SYMBOL(wayland, "wl_proxy_marshal_constructor_versioned"); + data.ffwl_proxy_add_listener = FF_LIBRARY_LOAD_SYMBOL(wayland, "wl_proxy_add_listener"); + const struct wl_interface* ffwl_registry_interface = FF_LIBRARY_LOAD_SYMBOL(wayland, "wl_registry_interface"); + data.ffwl_output_interface = FF_LIBRARY_LOAD_SYMBOL(wayland, "wl_output_interface"); + + data.ffwl_proxy_destroy = dlsym(wayland, "wl_proxy_destroy"); + //We check for NULL before each call because this is just used for cleanup and not actually needed + if(dlerror() != NULL) + data.ffwl_proxy_destroy = NULL; + + 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) + { + waylandDisplayDisconnect(wayland, display); + dlclose(wayland); + return false; + } + + 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; + + ffCacheOpenWrite(instance, FF_RESOLUTION_MODULE_NAME, &data.cache); + + data.ffwl_proxy_add_listener((struct wl_proxy*) registry, (void(**)(void)) ®estry_listener, &data); + ffwl_display_dispatch(display); + ffwl_display_roundtrip(display); + + ffCacheClose(&data.cache); + + if(data.ffwl_proxy_destroy != NULL) + data.ffwl_proxy_destroy((struct wl_proxy*) registry); + + waylandDisplayDisconnect(wayland, display); + dlclose(wayland); + + return data.numModules > 0; +} + void ffPrintResolution(FFinstance* instance) { - if(ffPrintFromCache(instance, FF_RESOLUTION_MODULE_NAME, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS)) - return; + if( + ffPrintFromCache(instance, FF_RESOLUTION_MODULE_NAME, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS) || + printResolutionWaylandBackend(instance) || + printResolutionXrandrBackend(instance) || + printResolutionX11Backend(instance) + ) return; - if(ffPrintResolutionWaylandBackend(instance)) - return; - - if(ffPrintResolutionXrandrBackend(instance)) - return; - - ffPrintResolutionX11Backend(instance); + printResolutionDRMBackend(instance); } + +#undef FF_LIBRARY_LOAD +#undef FF_LIBRARY_LOAD_SYMBOL diff --git a/src/modules/resolution.h b/src/modules/resolution.h deleted file mode 100644 index 0d4ffc646..000000000 --- a/src/modules/resolution.h +++ /dev/null @@ -1,14 +0,0 @@ -#include "fastfetch.h" - -#define FF_RESOLUTION_MODULE_NAME "Resolution" -#define FF_RESOLUTION_NUM_FORMAT_ARGS 3 - -//modules/resolution.c -void ffPrintResolutionValue(FFinstance* instance, uint8_t moduleIndex, FFcache* cache, int width, int height, int refreshRate); - -//modules/resolution_wayland.c -bool ffPrintResolutionWaylandBackend(FFinstance* instance); - -//modules/resolution_x11.c -bool ffPrintResolutionXrandrBackend(FFinstance* instance); -void ffPrintResolutionX11Backend(FFinstance* instance); diff --git a/src/modules/resolution_wayland.c b/src/modules/resolution_wayland.c deleted file mode 100644 index 7fc1f5853..000000000 --- a/src/modules/resolution_wayland.c +++ /dev/null @@ -1,225 +0,0 @@ -#include "resolution.h" - -#include -#include -#include - -typedef struct WaylandData -{ - FFinstance* instance; - void* wayland; - FFcache cache; - struct wl_proxy*(*ffwl_proxy_marshal_constructor_versioned)(struct wl_proxy*, uint32_t, const struct wl_interface*, uint32_t, ...); - int(*ffwl_proxy_add_listener)(struct wl_proxy*, void (**)(void), void *data); - void(*ffwl_proxy_destroy)(struct wl_proxy*); - const struct wl_interface* ffwl_output_interface; - struct wl_output_listener output_listener; - int8_t moduleCounter; - int8_t numModules; -} WaylandData; - -static void waylandGlobalRemoveListener(void* data, struct wl_registry* wl_registry, uint32_t name){ - UNUSED(data); - UNUSED(wl_registry); - UNUSED(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) -{ - UNUSED(data); - UNUSED(wl_output); - UNUSED(x); - UNUSED(y); - UNUSED(physical_width); - UNUSED(physical_height); - UNUSED(subpixel); - UNUSED(make); - UNUSED(model); - UNUSED(transform); -} - -static void waylandOutputDoneListener(void* data, struct wl_output* wl_output) -{ - UNUSED(data); - UNUSED(wl_output); -} - -static void waylandOutputScaleListener(void* data, struct wl_output* wl_output, int32_t factor) -{ - UNUSED(data); - UNUSED(wl_output); - UNUSED(factor); -} - -static int parseRefreshRate(int32_t refreshRate) -{ - if(refreshRate <= 0) - return 0; - - refreshRate /= 1000; //to Hz - - 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 refreshRate; -} - -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->moduleCounter; - ffPrintResolutionValue(wldata->instance, wldata->numModules == 1 ? 0 : wldata->moduleCounter, &wldata->cache, width, height, parseRefreshRate(refreshRate)); - - if(wldata->ffwl_proxy_destroy != NULL) - wldata->ffwl_proxy_destroy((struct wl_proxy*) output); -} - -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->numModules; - wldata->ffwl_proxy_add_listener((struct wl_proxy*) output, (void(**)(void)) &wldata->output_listener, data); - } -} - -static inline void waylandDisplayDisconnect(void* wayland, struct wl_display* display) -{ - void(*ffwl_display_disconnect)(struct wl_display*) = dlsym(wayland, "wl_display_disconnect"); - if(ffwl_display_disconnect != NULL) - ffwl_display_disconnect(display); -} - -bool ffPrintResolutionWaylandBackend(FFinstance* instance) -{ - const char* sessionType = getenv("XDG_SESSION_TYPE"); - if(sessionType != NULL && strcasecmp(sessionType, "wayland") != 0) - return false; - - void* wayland = dlopen(instance->config.libWayland.length == 0 ? "libwayland-client.so" : instance->config.libWayland.chars, RTLD_LAZY); - if(wayland == NULL) - return false; - - WaylandData data; - data.instance = instance; - data.wayland = wayland; - data.moduleCounter = 0; - data.numModules = 0; - - struct wl_display*(*ffwl_display_connect)(const char*) = dlsym(wayland, "wl_display_connect"); - if(ffwl_display_connect == NULL) - { - dlclose(wayland); - return false; - } - - int(*ffwl_display_dispatch)(struct wl_display*) = dlsym(wayland, "wl_display_dispatch"); - if(ffwl_display_dispatch == NULL) - { - dlclose(wayland); - return false; - } - - void(*ffwl_display_roundtrip)(struct wl_display*) = dlsym(wayland, "wl_display_roundtrip"); - if(ffwl_display_roundtrip == NULL) - { - dlclose(wayland); - return false; - } - - struct wl_proxy*(*ffwl_proxy_marshal_constructor)(struct wl_proxy*, uint32_t, const struct wl_interface*, ...) = dlsym(wayland, "wl_proxy_marshal_constructor"); - if(ffwl_proxy_marshal_constructor == NULL) - { - dlclose(wayland); - return false; - } - - data.ffwl_proxy_marshal_constructor_versioned = dlsym(wayland, "wl_proxy_marshal_constructor_versioned"); - if(data.ffwl_proxy_marshal_constructor_versioned == NULL) - { - dlclose(wayland); - return false; - } - - data.ffwl_proxy_add_listener = dlsym(wayland, "wl_proxy_add_listener"); - if(data.ffwl_proxy_add_listener == NULL) - { - dlclose(wayland); - return false; - } - - const struct wl_interface* ffwl_registry_interface = dlsym(wayland, "wl_registry_interface"); - if(ffwl_registry_interface == NULL) - { - dlclose(wayland); - return false; - } - - data.ffwl_output_interface = dlsym(wayland, "wl_output_interface"); - if(data.ffwl_output_interface == NULL) - { - dlclose(wayland); - return false; - } - - data.ffwl_proxy_destroy = dlsym(wayland, "wl_proxy_destroy"); - //We check for NULL before each call because this is just used for cleanup and not actually needed - - 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) - { - waylandDisplayDisconnect(wayland, display); - dlclose(wayland); - return false; - } - - 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; - - ffCacheOpenWrite(instance, FF_RESOLUTION_MODULE_NAME, &data.cache); - - data.ffwl_proxy_add_listener((struct wl_proxy*) registry, (void(**)(void)) ®estry_listener, &data); - ffwl_display_dispatch(display); - ffwl_display_roundtrip(display); - - ffCacheClose(&data.cache); - - if(data.ffwl_proxy_destroy != NULL) - data.ffwl_proxy_destroy((struct wl_proxy*) registry); - - waylandDisplayDisconnect(wayland, display); - dlclose(wayland); - - return data.numModules > 0; -} diff --git a/src/modules/resolution_x11.c b/src/modules/resolution_x11.c deleted file mode 100644 index 28ca0cd02..000000000 --- a/src/modules/resolution_x11.c +++ /dev/null @@ -1,153 +0,0 @@ -#include "resolution.h" - -#include -#include - -static Display* xOpenDisplay(FFinstance* instance, void* library, bool printErrors) -{ - Display*(*ffXOpenDisplay)(const char*) = dlsym(library, "XOpenDisplay"); - if(ffXOpenDisplay == NULL) - { - dlclose(library); - if(printErrors) - ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS, "dlsym(library, \"XOpenDisplay\") == NULL"); - return NULL; - } - - Display* display = ffXOpenDisplay(NULL); - if(display == NULL) - { - dlclose(library); - if(printErrors) - ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS, "ffXOpenDisplay(NULL) == NULL"); - return NULL; - } - - return display; -} - -static void xCloseDisplay(void* library, Display* display) -{ - int(*ffXCloseDisplay)(Display*) = dlsym(library, "XCloseDisplay"); - if(ffXCloseDisplay != NULL) - ffXCloseDisplay(display); -} - -void ffPrintResolutionX11Backend(FFinstance* instance) -{ - const char* libX11Name = instance->config.libX11.length == 0 ? "libX11.so" : instance->config.libX11.chars; - void* x11 = dlopen(libX11Name, RTLD_LAZY); - if(x11 == NULL) - { - ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS, "dlopen(\"%s\", RTLD_LAZY) == NULL", libX11Name); - return; - } - - Display* display = xOpenDisplay(instance, x11, true); - if(display == NULL) - return; - - int screenCount = ScreenCount(display); - if(screenCount < 1) - { - xCloseDisplay(x11, display); - dlclose(x11); - ffPrintError(instance, FF_RESOLUTION_MODULE_NAME, 0, &instance->config.resolutionKey, &instance->config.resolutionFormat, FF_RESOLUTION_NUM_FORMAT_ARGS, "ScreenCount(display) < 1: %i", screenCount); - return; - } - - FFcache cache; - ffCacheOpenWrite(instance, FF_RESOLUTION_MODULE_NAME, &cache); - - for(int i = 0; i < screenCount; i++) - { - Screen* screen = ScreenOfDisplay(display, i); - uint8_t moduleIndex = screenCount == 1 ? 0 : i + 1; - ffPrintResolutionValue(instance, moduleIndex, &cache, WidthOfScreen(screen), HeightOfScreen(screen), 0); - } - - ffCacheClose(&cache); - - xCloseDisplay(x11, display); - dlclose(x11); -} - -static int xrandrGetCurrentRate(void* xrandr, Display* display) -{ - XRRScreenConfiguration*(*ffXRRGetScreenInfo)(Display*, Window) = dlsym(xrandr, "XRRGetScreenInfo"); - if(ffXRRGetScreenInfo == NULL) - return 0; - - short(*ffXRRConfigCurrentRate)(XRRScreenConfiguration*) = dlsym(xrandr, "XRRConfigCurrentRate"); - if(ffXRRConfigCurrentRate == NULL) - return 0; - - - XRRScreenConfiguration* xrrscreenconf = ffXRRGetScreenInfo(display, DefaultRootWindow(display)); - if(xrrscreenconf == NULL) - return 0; - - short currentRate = ffXRRConfigCurrentRate(xrrscreenconf); - - void(*ffXRRFreeScreenConfigInfo)(XRRScreenConfiguration*) = dlsym(xrandr, "XRRFreeScreenConfigInfo"); - if(ffXRRFreeScreenConfigInfo != NULL) - ffXRRFreeScreenConfigInfo(xrrscreenconf); - - return (int) currentRate; -} - -bool ffPrintResolutionXrandrBackend(FFinstance* instance) -{ - void* xrandr = dlopen(instance->config.libXrandr.length == 0 ? "libXrandr.so" : instance->config.libXrandr.chars, RTLD_LAZY); - if(xrandr == NULL) - return false; - - XRRMonitorInfo*(*ffXRRGetMonitors)(Display*, Window, Bool, int*) = dlsym(xrandr, "XRRGetMonitors"); - if(ffXRRGetMonitors == NULL) - { - dlclose(xrandr); - return false; - } - - Display* display = xOpenDisplay(instance, xrandr, false); - if(display == NULL) - return false; - - int numberOfMonitors; - XRRMonitorInfo* monitors = ffXRRGetMonitors(display, DefaultRootWindow(display), False, &numberOfMonitors); - if(monitors == NULL) - { - xCloseDisplay(xrandr, display); - dlclose(xrandr); - return false; - } - - if(numberOfMonitors < 1) - { - xCloseDisplay(xrandr, display); - dlclose(xrandr); - return false; - } - - int refreshRate = xrandrGetCurrentRate(xrandr, display); - - FFcache cache; - ffCacheOpenWrite(instance, FF_RESOLUTION_MODULE_NAME, &cache); - - for(int i = 0; i < numberOfMonitors; i++) - { - uint8_t moduleIndex = numberOfMonitors == 1 ? 0 : i + 1; - ffPrintResolutionValue(instance, moduleIndex, &cache, monitors[i].width, monitors[i].height, refreshRate); - } - - ffCacheClose(&cache); - - void(*ffXRRFreeMonitors)(XRRMonitorInfo*) = dlsym(xrandr, "XRRFreeMonitors"); - if(ffXRRFreeMonitors != NULL) - ffXRRFreeMonitors(monitors); - - xCloseDisplay(xrandr, display); - dlclose(xrandr); - - return true; -}