mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-10-29 08:13:44 +01:00
Rewrote X11 code
This commit is contained in:
+32
-14
@@ -68,12 +68,26 @@ else(VULKAN_FOUND)
|
||||
message(WARNING "Package vulkan not found. Building without support.")
|
||||
endif(VULKAN_FOUND)
|
||||
|
||||
pkg_check_modules (X11 x11)
|
||||
if(X11_FOUND)
|
||||
add_compile_definitions(FF_HAVE_X11=1)
|
||||
else(X11_FOUND)
|
||||
message(WARNING "Package x11 not found. Building without support.")
|
||||
endif(X11_FOUND)
|
||||
pkg_check_modules (WAYLAND wayland-client)
|
||||
if(WAYLAND_FOUND)
|
||||
add_compile_definitions(FF_HAVE_WAYLAND=1)
|
||||
else(WAYLAND_FOUND)
|
||||
message(WARNING "Package wayland-client not found. Building without support.")
|
||||
endif(WAYLAND_FOUND)
|
||||
|
||||
pkg_check_modules (XCB_RANDR xcb-randr)
|
||||
if(XCB_RANDR_FOUND)
|
||||
add_compile_definitions(FF_HAVE_XCB_RANDR=1)
|
||||
else(XCB_RANDR_FOUND)
|
||||
message(WARNING "Package xcb-randr not found. Building without support.")
|
||||
endif(XCB_RANDR_FOUND)
|
||||
|
||||
pkg_check_modules (XCB xcb)
|
||||
if(XCB_FOUND)
|
||||
add_compile_definitions(FF_HAVE_XCB=1)
|
||||
else(XCB_FOUND)
|
||||
message(WARNING "Package xcb not found. Building without support.")
|
||||
endif(XCB_FOUND)
|
||||
|
||||
pkg_check_modules (XRANDR xrandr)
|
||||
if(XRANDR_FOUND)
|
||||
@@ -82,12 +96,12 @@ else(XRANDR_FOUND)
|
||||
message(WARNING "Package xrandr not found. Building without support.")
|
||||
endif(XRANDR_FOUND)
|
||||
|
||||
pkg_check_modules (WAYLAND wayland-client)
|
||||
if(WAYLAND_FOUND)
|
||||
add_compile_definitions(FF_HAVE_WAYLAND=1)
|
||||
else(WAYLAND_FOUND)
|
||||
message(WARNING "Package wayland-client not found. Building without support.")
|
||||
endif(WAYLAND_FOUND)
|
||||
pkg_check_modules (X11 x11)
|
||||
if(X11_FOUND)
|
||||
add_compile_definitions(FF_HAVE_X11=1)
|
||||
else(X11_FOUND)
|
||||
message(WARNING "Package x11 not found. Building without support.")
|
||||
endif(X11_FOUND)
|
||||
|
||||
pkg_check_modules (GIO gio-2.0)
|
||||
if(GIO_FOUND)
|
||||
@@ -121,9 +135,12 @@ include_directories(
|
||||
${PROJECT_BINARY_DIR}
|
||||
${PROJECT_SOURCE_DIR}/src
|
||||
${LIBPCI_INCLUDE_DIRS}
|
||||
${X11_INCLUDE_DIRS}
|
||||
${XRANDR_INCLUDE_DIRS}
|
||||
${VULKAN_INCLUDE_DIRS}
|
||||
${WAYLAND_INCLUDE_DIRS}
|
||||
${XCB_RANDR_INCLUDE_DIRS}
|
||||
${XCB_INCLUDE_DIRS}
|
||||
${XRANDR_INCLUDE_DIRS}
|
||||
${X11_INCLUDE_DIRS}
|
||||
${GIO_INCLUDE_DIRS}
|
||||
${DCONF_INCLUDE_DIRS}
|
||||
${XFCONF_INCLUDE_DIRS}
|
||||
@@ -151,6 +168,7 @@ set(SRCS
|
||||
src/detection/terminalShell.c
|
||||
src/detection/displayserver/displayServer.c
|
||||
src/detection/displayserver/wayland.c
|
||||
src/detection/displayserver/xcb.c
|
||||
src/detection/displayserver/xlib.c
|
||||
src/detection/displayserver/wmde.c
|
||||
src/modules/break.c
|
||||
|
||||
@@ -20,9 +20,11 @@ In order to run properly on every machine, fastfetch dynamically loads needed li
|
||||
The following libraries are used if present:
|
||||
* [`libpci`](https://github.com/pciutils/pciutils): GPU output.
|
||||
* [`libvulkan`](https://www.vulkan.org/): Fallback for GPU output.
|
||||
* [`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): Needed for resolution output
|
||||
* [`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr): Needed for appending refresh rate to resolution output.
|
||||
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance in wayland sessions.
|
||||
* [`libxcb-randr`](https://xcb.freedesktop.org/),
|
||||
[`libXrandr`](https://gitlab.freedesktop.org/xorg/lib/libxrandr),
|
||||
[`libxcb`](https://xcb.freedesktop.org/),
|
||||
[`libX11`](https://gitlab.freedesktop.org/xorg/lib/libx11): At least one of them sould be present in X11 sessions for better resolution detection and faster WM detection. The `*randr` ones provide multi monitor support. The `libxcb*` ones usually have better performance.
|
||||
* [`libwayland-client`](https://wayland.freedesktop.org/): Better resolution performance and output in wayland sessions. Supports different refresh rates per monitor.
|
||||
* [`libGIO`](https://developer.gnome.org/gio/unstable/): Needed for values that are only stored GSettings.
|
||||
* [`libDConf`](https://developer.gnome.org/dconf/unstable/): Needed for values that are only stored in DConf + Fallback for GSettings.
|
||||
* [`libXFConf`](https://gitlab.xfce.org/xfce/xfconf): Needed for XFWM theme and XFCE Terminal font.
|
||||
|
||||
+4
-2
@@ -196,11 +196,13 @@ __fastfetch_completion()
|
||||
local FF_OPTIONS_PATH=(
|
||||
"--lib-PCI"
|
||||
"--lib-vulkan"
|
||||
"--lib-X11"
|
||||
"--lib-wayland"
|
||||
"--lib-xcb-randr"
|
||||
"--lib-xcb"
|
||||
"--lib-Xrandr"
|
||||
"--lib-X11"
|
||||
"--lib-gio"
|
||||
"--lib-DConf"
|
||||
"--lib-wayland"
|
||||
"--lib-XFConf"
|
||||
"--lib-RPM"
|
||||
"--battery-dir"
|
||||
|
||||
+4
-2
@@ -174,11 +174,13 @@ static void defaultConfig(FFinstance* instance)
|
||||
|
||||
ffStrbufInitA(&instance->config.libPCI, 0);
|
||||
ffStrbufInitA(&instance->config.libVulkan, 0);
|
||||
ffStrbufInitA(&instance->config.libX11, 0);
|
||||
ffStrbufInitA(&instance->config.libWayland, 0);
|
||||
ffStrbufInitA(&instance->config.libXcbRandr, 0);
|
||||
ffStrbufInitA(&instance->config.libXcb, 0);
|
||||
ffStrbufInitA(&instance->config.libXrandr, 0);
|
||||
ffStrbufInitA(&instance->config.libX11, 0);
|
||||
ffStrbufInitA(&instance->config.libGIO, 0);
|
||||
ffStrbufInitA(&instance->config.libDConf, 0);
|
||||
ffStrbufInitA(&instance->config.libWayland, 0);
|
||||
ffStrbufInitA(&instance->config.libXFConf, 0);
|
||||
ffStrbufInitA(&instance->config.librpm, 0);
|
||||
|
||||
|
||||
+4
-2
@@ -185,10 +185,12 @@
|
||||
# Must be a valid path to a library.
|
||||
#--lib-PCI /usr/lib/libpci.so
|
||||
#--lib-vulkan /usr/lib/libvulkan.so
|
||||
#--lib-X11 /usr/lib/libX11.so
|
||||
#--lib-wayland /usr/lib/libwayland-client.so
|
||||
#--lib-xcb-randr /usr/lib/libxcb-randr.so
|
||||
#--lib-xcb /usr/lib/libxcb.so
|
||||
#--lib-Xrandr /usr/lib/libXrandr.so
|
||||
#--lib-X11 /usr/lib/libX11.so
|
||||
#--lib-gio /usr/lib/libgio-2.0.so
|
||||
#--lib-DConf /usr/lib/libdconf.so
|
||||
#--lib-wayland /usr/lib/libwayland-client.so
|
||||
#--lib-XFConf /usr/lib/libxfconf-0.so
|
||||
#--lib-rpm /usr/lib/librpm.so
|
||||
|
||||
+4
-2
@@ -92,11 +92,13 @@ Key options: Provide a custom key for an output
|
||||
Library options: Set the path of a library to load
|
||||
--lib-PCI <path>
|
||||
--lib-vulkan <path>
|
||||
--lib-X11 <path>
|
||||
--lib-wayland <path>
|
||||
--lib-xcb-randr <path>
|
||||
--lib-xcb <path>
|
||||
--lib-Xrandr <path>
|
||||
--lib-X11 <path>
|
||||
--lib-gio <path>
|
||||
--lib-DConf <path>
|
||||
--lib-wayland <path>
|
||||
--lib-XFConf <path>
|
||||
--lib-RPM <path>
|
||||
|
||||
|
||||
@@ -20,6 +20,19 @@ uint32_t ffdsParseRefreshRate(int32_t refreshRate)
|
||||
return (uint32_t) refreshRate;
|
||||
}
|
||||
|
||||
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate)
|
||||
{
|
||||
if(width == 0 || height == 0)
|
||||
return false;
|
||||
|
||||
FFResolutionResult* resolution = ffListAdd(&result->resolutions);
|
||||
resolution->width = width;
|
||||
resolution->height = height;
|
||||
resolution->refreshRate = refreshRate;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void parseDRM(FFDisplayServerResult* result)
|
||||
{
|
||||
const char* drmDirPath = "/sys/class/drm/";
|
||||
@@ -94,9 +107,15 @@ const FFDisplayServerResult* ffConnectDisplayServer(const FFinstance* instance)
|
||||
//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)
|
||||
ffdsConnectXcbRandr(instance, &result);
|
||||
|
||||
if(result.resolutions.length == 0)
|
||||
ffdsConnectXrandr(instance, &result);
|
||||
|
||||
if(result.resolutions.length == 0)
|
||||
ffdsConnectXcb(instance, &result);
|
||||
|
||||
if(result.resolutions.length == 0)
|
||||
ffdsConnectXlib(instance, &result);
|
||||
|
||||
|
||||
@@ -10,8 +10,13 @@
|
||||
#define FF_DISPLAYSERVER_PROTOCOL_TTY "TTY"
|
||||
|
||||
uint32_t ffdsParseRefreshRate(int32_t refreshRate);
|
||||
bool ffdsAppendResolution(FFDisplayServerResult* result, uint32_t width, uint32_t height, uint32_t refreshRate);
|
||||
|
||||
void ffdsConnectWayland(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result);
|
||||
|
||||
|
||||
@@ -0,0 +1,389 @@
|
||||
#include "displayServer.h"
|
||||
|
||||
#ifdef FF_HAVE_XCB
|
||||
#include <xcb/xcb.h>
|
||||
#include <string.h>
|
||||
|
||||
typedef struct XcbPropertyData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(xcb_intern_atom)
|
||||
FF_LIBRARY_SYMBOL(xcb_intern_atom_reply)
|
||||
FF_LIBRARY_SYMBOL(xcb_get_property)
|
||||
FF_LIBRARY_SYMBOL(xcb_get_property_reply)
|
||||
FF_LIBRARY_SYMBOL(xcb_get_property_value)
|
||||
FF_LIBRARY_SYMBOL(xcb_get_property_value_length)
|
||||
} XcbPropertyData;
|
||||
|
||||
static bool xcbInitPropertyData(void* libraryHandle, XcbPropertyData* propertyData)
|
||||
{
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_intern_atom, xcb_intern_atom, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_intern_atom_reply, xcb_intern_atom_reply, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_get_property, xcb_get_property, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_get_property_reply, xcb_get_property_reply, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_get_property_value, xcb_get_property_value, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffxcb_get_property_value_length, xcb_get_property_value_length, false)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void* xcbGetProperty(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t window, const char* request)
|
||||
{
|
||||
xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(connection, true, (uint16_t) strlen(request), request);
|
||||
xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(connection, requestAtomCookie, NULL);
|
||||
if(requestAtomReply == NULL)
|
||||
return NULL;
|
||||
|
||||
xcb_get_property_cookie_t propertyCookie = data->ffxcb_get_property(connection, false, window, requestAtomReply->atom, XCB_ATOM_ANY, 0, 64);
|
||||
|
||||
free(requestAtomReply);
|
||||
|
||||
xcb_get_property_reply_t* propertyReply = data->ffxcb_get_property_reply(connection, propertyCookie, NULL);
|
||||
if(propertyReply == NULL)
|
||||
return NULL;
|
||||
|
||||
int length = data->ffxcb_get_property_value_length(propertyReply);
|
||||
if(length <= 0)
|
||||
{
|
||||
free(propertyReply);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//Why are xcb property strings not null terminated???
|
||||
void* replyValue = malloc((size_t) (length + 1));
|
||||
memcpy(replyValue, data->ffxcb_get_property_value(propertyReply), (size_t) length);
|
||||
((char*) replyValue)[length] = '\0';
|
||||
|
||||
free(propertyReply);
|
||||
|
||||
return replyValue;
|
||||
}
|
||||
|
||||
static void xcbDetectWMfromEWMH(XcbPropertyData* data, xcb_connection_t* connection, xcb_window_t rootWindow, FFDisplayServerResult* result)
|
||||
{
|
||||
if(result->wmProcessName.length > 0)
|
||||
return;
|
||||
|
||||
xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, connection, rootWindow, "_NET_SUPPORTING_WM_CHECK");
|
||||
if(wmWindow == NULL)
|
||||
return;
|
||||
|
||||
char* wmName = (char*) xcbGetProperty(data, connection, *wmWindow, "_NET_WM_NAME");
|
||||
if(wmName == NULL)
|
||||
wmName = (char*) xcbGetProperty(data, connection, *wmWindow, "WM_NAME");
|
||||
|
||||
free(wmWindow);
|
||||
|
||||
if(wmName == NULL)
|
||||
return;
|
||||
|
||||
if(*wmName == '\0')
|
||||
{
|
||||
free(wmName);
|
||||
return;
|
||||
}
|
||||
|
||||
ffStrbufSetS(&result->wmProcessName, wmName);
|
||||
|
||||
free(wmName);
|
||||
}
|
||||
|
||||
void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(xcb, "libxcb.so", instance->config.libXcb,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_connect,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_get_setup,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_setup_roots_iterator,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_screen_next,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcb, xcb_disconnect,)
|
||||
|
||||
XcbPropertyData propertyData;
|
||||
bool propertyDataInitialized = xcbInitPropertyData(xcb, &propertyData);
|
||||
|
||||
xcb_connection_t* connection = ffxcb_connect(NULL, NULL);
|
||||
if(connection == NULL)
|
||||
{
|
||||
dlclose(xcb);
|
||||
return;
|
||||
}
|
||||
|
||||
xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(connection));
|
||||
|
||||
if(iterator.rem > 0 && propertyDataInitialized)
|
||||
xcbDetectWMfromEWMH(&propertyData, connection, iterator.data->root, result);
|
||||
|
||||
while(iterator.rem > 0)
|
||||
{
|
||||
ffdsAppendResolution(
|
||||
result,
|
||||
(uint32_t) iterator.data->width_in_pixels,
|
||||
(uint32_t) iterator.data->height_in_pixels,
|
||||
0
|
||||
);
|
||||
ffxcb_screen_next(&iterator);
|
||||
}
|
||||
|
||||
ffxcb_disconnect(connection);
|
||||
dlclose(xcb);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void ffdsConnectXcb(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
//Do nothing. There are other implementations coming
|
||||
FF_UNUSED(instance, result)
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FF_HAVE_XCB_RANDR
|
||||
#include <xcb/randr.h>
|
||||
|
||||
typedef struct XcbRandrData
|
||||
{
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_reply)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_modes_iterator)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_info)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_info_reply)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_mode_info_next)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_monitors)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_monitors_reply)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_monitors_monitors_iterator)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_monitor_info_next)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_monitor_info_outputs_length)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_monitor_info_outputs)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_output_next)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_output_info)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_output_info_reply)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_crtc_info)
|
||||
FF_LIBRARY_SYMBOL(xcb_randr_get_crtc_info_reply)
|
||||
|
||||
//init once
|
||||
xcb_connection_t* connection;
|
||||
FFDisplayServerResult* result;
|
||||
|
||||
//init per screen
|
||||
uint32_t defaultRefreshRate;
|
||||
xcb_randr_get_screen_resources_reply_t* screenResources;
|
||||
} XcbRandrData;
|
||||
|
||||
static bool xcbRandrHandleModeInfo(XcbRandrData* data, xcb_randr_mode_info_t* modeInfo)
|
||||
{
|
||||
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
|
||||
modeInfo->dot_clock / (modeInfo->htotal * modeInfo->vtotal)
|
||||
));
|
||||
|
||||
return ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) modeInfo->width,
|
||||
(uint32_t) modeInfo->height,
|
||||
refreshRate == 0 ? data->defaultRefreshRate : refreshRate
|
||||
);
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleMode(XcbRandrData* data, xcb_randr_mode_t mode)
|
||||
{
|
||||
//We do the check here, because we want the best fallback resolution if this call failed
|
||||
if(data->screenResources == NULL)
|
||||
return false;
|
||||
|
||||
xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_modes_iterator(data->screenResources);
|
||||
|
||||
while(modesIterator.rem > 0)
|
||||
{
|
||||
if(modesIterator.data->id == mode)
|
||||
return xcbRandrHandleModeInfo(data, modesIterator.data);
|
||||
|
||||
data->ffxcb_randr_mode_info_next(&modesIterator);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleCrtc(XcbRandrData* data, xcb_randr_crtc_t crtc)
|
||||
{
|
||||
xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, crtc, XCB_CURRENT_TIME);
|
||||
xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL);
|
||||
if(crtcInfoReply == NULL)
|
||||
return false;
|
||||
|
||||
bool res = xcbRandrHandleMode(data, crtcInfoReply->mode);
|
||||
|
||||
free(crtcInfoReply);
|
||||
|
||||
return res ? true : ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) crtcInfoReply->width,
|
||||
(uint32_t) crtcInfoReply->height,
|
||||
data->defaultRefreshRate
|
||||
);
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output)
|
||||
{
|
||||
xcb_randr_get_output_info_cookie_t outputInfoCookie = data->ffxcb_randr_get_output_info(data->connection, output, XCB_CURRENT_TIME);
|
||||
xcb_randr_get_output_info_reply_t* outputInfoReply = data->ffxcb_randr_get_output_info_reply(data->connection, outputInfoCookie, NULL);
|
||||
if(outputInfoReply == NULL)
|
||||
return false;
|
||||
|
||||
bool res = xcbRandrHandleCrtc(data, outputInfoReply->crtc);
|
||||
|
||||
free(outputInfoReply);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* monitor)
|
||||
{
|
||||
//for some reasons, we have to construct this our self
|
||||
xcb_randr_output_iterator_t outputIterator = {
|
||||
.index = 0,
|
||||
.data = data->ffxcb_randr_monitor_info_outputs(monitor),
|
||||
.rem = data->ffxcb_randr_monitor_info_outputs_length(monitor)
|
||||
};
|
||||
|
||||
bool foundOutput = false;
|
||||
|
||||
while(outputIterator.rem > 0)
|
||||
{
|
||||
if(xcbRandrHandleOutput(data, *outputIterator.data))
|
||||
foundOutput = true;
|
||||
data->ffxcb_randr_output_next(&outputIterator);
|
||||
};
|
||||
|
||||
return foundOutput ? true : ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) monitor->width,
|
||||
(uint32_t) monitor->height,
|
||||
data->defaultRefreshRate
|
||||
);
|
||||
}
|
||||
|
||||
static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
|
||||
{
|
||||
xcb_randr_get_monitors_cookie_t monitorsCookie = data->ffxcb_randr_get_monitors(data->connection, screen->root, true);
|
||||
xcb_randr_get_monitors_reply_t* monitorsReply = data->ffxcb_randr_get_monitors_reply(data->connection, monitorsCookie, NULL);
|
||||
if(monitorsReply == NULL)
|
||||
return false;
|
||||
|
||||
xcb_randr_monitor_info_iterator_t monitorInfoIterator = data->ffxcb_randr_get_monitors_monitors_iterator(monitorsReply);
|
||||
|
||||
bool foundMonitor = false;
|
||||
|
||||
while(monitorInfoIterator.rem > 0)
|
||||
{
|
||||
if(xcbRandrHandleMonitor(data, monitorInfoIterator.data))
|
||||
foundMonitor = true;
|
||||
data->ffxcb_randr_monitor_info_next(&monitorInfoIterator);
|
||||
}
|
||||
|
||||
free(monitorsReply);
|
||||
|
||||
return foundMonitor;
|
||||
}
|
||||
|
||||
static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
|
||||
{
|
||||
//Init screen info. This is used to get the default refresh rate. If this fails, default refresh rate is simply 0.
|
||||
xcb_randr_get_screen_info_cookie_t screenInfoCookie = data->ffxcb_randr_get_screen_info(data->connection, screen->root);
|
||||
xcb_randr_get_screen_info_reply_t* screenInfoReply = data->ffxcb_randr_get_screen_info_reply(data->connection, screenInfoCookie, NULL);
|
||||
|
||||
if(screenInfoReply != NULL)
|
||||
{
|
||||
data->defaultRefreshRate = screenInfoReply->rate;
|
||||
free(screenInfoReply);
|
||||
}
|
||||
else
|
||||
data->defaultRefreshRate = 0;
|
||||
|
||||
//Init screen resources. They are used to iterate over all modes. xcbRandrHandleMode checks for " == NULL", to fail as late as possible.
|
||||
xcb_randr_get_screen_resources_cookie_t screenResourcesCookie = data->ffxcb_randr_get_screen_resources(data->connection, screen->root);
|
||||
data->screenResources = data->ffxcb_randr_get_screen_resources_reply(data->connection, screenResourcesCookie, NULL);
|
||||
|
||||
//With all the initialisation done, start the detection
|
||||
bool ret = xcbRandrHandleMonitors(data, screen);
|
||||
|
||||
free(data->screenResources);
|
||||
|
||||
if(ret)
|
||||
return;
|
||||
|
||||
//If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation
|
||||
ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) screen->width_in_pixels,
|
||||
(uint32_t) screen->height_in_pixels,
|
||||
data->defaultRefreshRate
|
||||
);
|
||||
}
|
||||
|
||||
void ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
FF_LIBRARY_LOAD(xcbRandr, "libxcb-randr.so", instance->config.libXcbRandr,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_connect,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_get_setup,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_setup_roots_iterator,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_screen_next,)
|
||||
FF_LIBRARY_LOAD_SYMBOL(xcbRandr, xcb_disconnect,)
|
||||
|
||||
XcbRandrData data;
|
||||
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_resources, xcb_randr_get_screen_resources,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_resources_reply, xcb_randr_get_screen_resources_reply,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_resources_modes_iterator, xcb_randr_get_screen_resources_modes_iterator,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_info, xcb_randr_get_screen_info,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_screen_info_reply, xcb_randr_get_screen_info_reply,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_mode_info_next, xcb_randr_mode_info_next,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_monitors, xcb_randr_get_monitors,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_monitors_reply, xcb_randr_get_monitors_reply,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_monitors_monitors_iterator, xcb_randr_get_monitors_monitors_iterator,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_monitor_info_next, xcb_randr_monitor_info_next,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_monitor_info_outputs_length, xcb_randr_monitor_info_outputs_length,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_monitor_info_outputs, xcb_randr_monitor_info_outputs,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_output_next, xcb_randr_output_next,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_output_info, xcb_randr_get_output_info,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_output_info_reply, xcb_randr_get_output_info_reply,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_crtc_info, xcb_randr_get_crtc_info,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xcbRandr, data.ffxcb_randr_get_crtc_info_reply, xcb_randr_get_crtc_info_reply,)
|
||||
|
||||
XcbPropertyData propertyData;
|
||||
bool propertyDataInitialized = xcbInitPropertyData(xcbRandr, &propertyData);
|
||||
|
||||
data.connection = ffxcb_connect(NULL, NULL);
|
||||
if(data.connection == NULL)
|
||||
{
|
||||
dlclose(xcbRandr);
|
||||
return;
|
||||
}
|
||||
|
||||
data.result = result;
|
||||
|
||||
xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(data.connection));
|
||||
|
||||
if(iterator.rem > 0 && propertyDataInitialized)
|
||||
xcbDetectWMfromEWMH(&propertyData, data.connection, iterator.data->root, result);
|
||||
|
||||
while(iterator.rem > 0)
|
||||
{
|
||||
xcbRandrHandleScreen(&data, iterator.data);
|
||||
ffxcb_screen_next(&iterator);
|
||||
}
|
||||
|
||||
ffxcb_disconnect(data.connection);
|
||||
dlclose(xcbRandr);
|
||||
|
||||
//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 ffdsConnectXcbRandr(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
{
|
||||
//Do nothing. There are other implementations coming
|
||||
FF_UNUSED(instance, result)
|
||||
}
|
||||
|
||||
#endif
|
||||
+111
-122
@@ -9,6 +9,14 @@ typedef struct X11PropertyData
|
||||
FF_LIBRARY_SYMBOL(XGetWindowProperty)
|
||||
} X11PropertyData;
|
||||
|
||||
static bool x11InitPropertyData(void* libraryHandle, X11PropertyData* propertyData)
|
||||
{
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffXInternAtom, XInternAtom, false)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(libraryHandle, propertyData->ffXGetWindowProperty, XGetWindowProperty, false)
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Window window, const char* request)
|
||||
{
|
||||
Atom requestAtom = data->ffXInternAtom(display, request, False);
|
||||
@@ -19,20 +27,7 @@ static unsigned char* x11GetProperty(X11PropertyData* data, Display* display, Wi
|
||||
unsigned long unused;
|
||||
unsigned char* result = NULL;
|
||||
|
||||
data->ffXGetWindowProperty(
|
||||
display,
|
||||
window,
|
||||
requestAtom,
|
||||
0,
|
||||
64,
|
||||
False,
|
||||
AnyPropertyType,
|
||||
&actualType,
|
||||
(int*) &unused,
|
||||
&unused,
|
||||
&unused,
|
||||
&result
|
||||
);
|
||||
data->ffXGetWindowProperty(display, window, requestAtom, 0, 64, False, AnyPropertyType, &actualType, (int*) &unused, &unused, &unused, &result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -42,40 +37,17 @@ static void x11DetectWMFromEWMH(X11PropertyData* data, Display* display, FFDispl
|
||||
if(result->wmProcessName.length > 0)
|
||||
return;
|
||||
|
||||
Window root = DefaultRootWindow(display);
|
||||
if(root == None)
|
||||
Window* wmWindow = (Window*) x11GetProperty(data, display, DefaultRootWindow(display), "_NET_SUPPORTING_WM_CHECK");
|
||||
if(wmWindow == NULL)
|
||||
return;
|
||||
|
||||
unsigned char* wmWindowID = x11GetProperty(data, display, root, "_NET_SUPPORTING_WM_CHECK");
|
||||
if(wmWindowID == NULL)
|
||||
return;
|
||||
|
||||
Window wmWindow = *(Window*) wmWindowID;
|
||||
if(wmWindow == None)
|
||||
return;
|
||||
|
||||
unsigned char* wmName = x11GetProperty(data, display, wmWindow, "_NET_WM_NAME");
|
||||
if(wmName == NULL)
|
||||
wmName = x11GetProperty(data, display, wmWindow, "WM_NAME");
|
||||
const char* wmName = (const char*) x11GetProperty(data, display, *wmWindow, "_NET_WM_NAME");
|
||||
if(wmName == NULL)
|
||||
wmName = (const char*) x11GetProperty(data, display, *wmWindow, "WM_NAME");
|
||||
if(wmName == NULL || *wmName == '\0')
|
||||
return;
|
||||
|
||||
const char* wmNameString = (const char*) wmName;
|
||||
if(*wmNameString == '\0')
|
||||
return;
|
||||
|
||||
ffStrbufSetS(&result->wmProcessName, wmNameString);
|
||||
}
|
||||
|
||||
static void x11AddScreenAsResult(FFlist* results, Screen* screen, uint32_t refreshRate)
|
||||
{
|
||||
if(WidthOfScreen(screen) == 0 || HeightOfScreen(screen) == 0)
|
||||
return;
|
||||
|
||||
FFResolutionResult* result = ffListAdd(results);
|
||||
result->width = (uint32_t) WidthOfScreen(screen);
|
||||
result->height = (uint32_t) HeightOfScreen(screen);
|
||||
result->refreshRate = refreshRate;
|
||||
ffStrbufSetS(&result->wmProcessName, wmName);
|
||||
}
|
||||
|
||||
void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
@@ -85,8 +57,7 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
FF_LIBRARY_LOAD_SYMBOL(x11, XCloseDisplay,)
|
||||
|
||||
X11PropertyData propertyData;
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(x11, propertyData.ffXInternAtom, XInternAtom,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(x11, propertyData.ffXGetWindowProperty, XGetWindowProperty,)
|
||||
bool propertyDataInitialized = x11InitPropertyData(x11, &propertyData);
|
||||
|
||||
Display* display = ffXOpenDisplay(x11);
|
||||
if(display == NULL)
|
||||
@@ -95,10 +66,19 @@ void ffdsConnectXlib(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
return;
|
||||
}
|
||||
|
||||
for(int i = 0; i < ScreenCount(display); i++)
|
||||
x11AddScreenAsResult(&result->resolutions, ScreenOfDisplay(display, i), 0);
|
||||
if(propertyDataInitialized && ScreenCount(display) > 0)
|
||||
x11DetectWMFromEWMH(&propertyData, display, result);
|
||||
|
||||
x11DetectWMFromEWMH(&propertyData, display, result);
|
||||
for(int i = 0; i < ScreenCount(display); i++)
|
||||
{
|
||||
Screen* screen = ScreenOfDisplay(display, i);
|
||||
ffdsAppendResolution(
|
||||
result,
|
||||
(uint32_t) screen->width,
|
||||
(uint32_t) screen->height,
|
||||
0
|
||||
);
|
||||
}
|
||||
|
||||
ffXCloseDisplay(display);
|
||||
dlclose(x11);
|
||||
@@ -138,101 +118,115 @@ typedef struct XrandrData
|
||||
|
||||
//Init once
|
||||
Display* display;
|
||||
FFlist* results;
|
||||
FFDisplayServerResult* result;
|
||||
|
||||
//Init per screen
|
||||
uint32_t defaultRefreshRate;
|
||||
XRRScreenResources* screenResources;
|
||||
} XrandrData;
|
||||
|
||||
static XRRModeInfo* xrandrGetModeInfo(XRRScreenResources* screenResources, RRMode mode)
|
||||
static bool xrandrHandleModeInfo(XrandrData* data, XRRModeInfo* modeInfo)
|
||||
{
|
||||
for(int i = 0; i < screenResources->nmode; i++)
|
||||
{
|
||||
if(screenResources->modes[i].id == mode)
|
||||
return &screenResources->modes[i];
|
||||
}
|
||||
return NULL;
|
||||
uint32_t refreshRate = ffdsParseRefreshRate((int32_t) (
|
||||
modeInfo->dotClock / (modeInfo->hTotal * modeInfo->vTotal)
|
||||
));
|
||||
|
||||
return ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) modeInfo->width,
|
||||
(uint32_t) modeInfo->height,
|
||||
refreshRate == 0 ? data->defaultRefreshRate : refreshRate
|
||||
);
|
||||
}
|
||||
|
||||
static bool xrandrHandleOutputInfo(XrandrData* data, XRROutputInfo* outputInfo)
|
||||
static bool xrandrHandleMode(XrandrData* data, RRMode mode)
|
||||
{
|
||||
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, outputInfo->crtc);
|
||||
for(int i = 0; i < data->screenResources->nmode; i++)
|
||||
{
|
||||
if(data->screenResources->modes[i].id == mode)
|
||||
return xrandrHandleModeInfo(data, &data->screenResources->modes[i]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool xrandrHandleCrtc(XrandrData* data, RRCrtc crtc)
|
||||
{
|
||||
//We do the check here, because we want the best fallback resolution if this call failed
|
||||
if(data->screenResources == NULL)
|
||||
return false;
|
||||
|
||||
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, data->screenResources, 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;
|
||||
bool res = xrandrHandleMode(data, crtcInfo->mode);
|
||||
|
||||
data->ffXRRFreeCrtcInfo(crtcInfo);
|
||||
|
||||
return true;
|
||||
return res ? true : ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) crtcInfo->width,
|
||||
(uint32_t) crtcInfo->height,
|
||||
data->defaultRefreshRate
|
||||
);
|
||||
}
|
||||
|
||||
static bool xrandrHandleMonitorFallback(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
static bool xrandrHandleOutput(XrandrData* data, RROutput output)
|
||||
{
|
||||
if(monitorInfo->width == 0 || monitorInfo->height == 0)
|
||||
XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, data->screenResources, output);
|
||||
if(outputInfo == NULL)
|
||||
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;
|
||||
bool res = xrandrHandleCrtc(data, outputInfo->crtc);
|
||||
|
||||
data->ffXRRFreeOutputInfo(outputInfo);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo)
|
||||
{
|
||||
bool foundMode = false;
|
||||
bool foundOutput = 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(xrandrHandleOutput(data, monitorInfo->outputs[i]))
|
||||
foundOutput = true;
|
||||
}
|
||||
|
||||
if(!foundMode)
|
||||
return xrandrHandleMonitorFallback(data, monitorInfo);
|
||||
|
||||
return true;
|
||||
return foundOutput ? true : ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) monitorInfo->width,
|
||||
(uint32_t) monitorInfo->height,
|
||||
data->defaultRefreshRate
|
||||
);
|
||||
}
|
||||
|
||||
static inline bool xrandrLoopMonitors(XrandrData* data, XRRMonitorInfo* monitorInfos, int numberOfMonitors, bool(*monitorFunc)(XrandrData* data, XRRMonitorInfo* monitorInfo))
|
||||
static bool xrandrHandleMonitors(XrandrData* data, Screen* screen)
|
||||
{
|
||||
bool foundAMonitor = false;
|
||||
int numberOfMonitors;
|
||||
XRRMonitorInfo* monitorInfos = data->ffXRRGetMonitors(data->display, RootWindowOfScreen(screen), True, &numberOfMonitors);
|
||||
if(monitorInfos == NULL)
|
||||
return false;
|
||||
|
||||
bool foundAMonitor;
|
||||
|
||||
for(int i = 0; i < numberOfMonitors; i++)
|
||||
{
|
||||
if(monitorFunc(data, &monitorInfos[i]))
|
||||
if(xrandrHandleMonitor(data, &monitorInfos[i]))
|
||||
foundAMonitor = true;
|
||||
}
|
||||
|
||||
data->ffXRRFreeMonitors(monitorInfos);
|
||||
|
||||
return foundAMonitor;
|
||||
}
|
||||
|
||||
static void xrandrHandleScreen(XrandrData* data, Screen* screen)
|
||||
{
|
||||
Window window = RootWindowOfScreen(screen);
|
||||
//Init screen configuration. This is used to get the default refresh rate. If this fails, default refresh rate is simply 0.
|
||||
XRRScreenConfiguration* screenConfiguration = data->ffXRRGetScreenInfo(data->display, RootWindowOfScreen(screen));
|
||||
|
||||
XRRScreenConfiguration* screenConfiguration = data->ffXRRGetScreenInfo(data->display, window);
|
||||
if(screenConfiguration != NULL)
|
||||
{
|
||||
data->defaultRefreshRate = (uint32_t) data->ffXRRConfigCurrentRate(screenConfiguration);
|
||||
@@ -241,28 +235,23 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
|
||||
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;
|
||||
}
|
||||
//Init screen resources
|
||||
data->screenResources = data->ffXRRGetScreenResources(data->display, RootWindowOfScreen(screen));
|
||||
|
||||
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);
|
||||
bool ret = xrandrHandleMonitors(data, screen);
|
||||
|
||||
data->ffXRRFreeScreenResources(data->screenResources);
|
||||
data->ffXRRFreeMonitors(monitorInfos);
|
||||
|
||||
if(ret)
|
||||
return;
|
||||
|
||||
//Fallback to screen
|
||||
ffdsAppendResolution(
|
||||
data->result,
|
||||
(uint32_t) WidthOfScreen(screen),
|
||||
(uint32_t) HeightOfScreen(screen),
|
||||
data->defaultRefreshRate
|
||||
);
|
||||
}
|
||||
|
||||
void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result)
|
||||
@@ -287,8 +276,7 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, data.ffXRRFreeScreenConfigInfo, XRRFreeScreenConfigInfo,);
|
||||
|
||||
X11PropertyData propertyData;
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, propertyData.ffXInternAtom, XInternAtom,)
|
||||
FF_LIBRARY_LOAD_SYMBOL_ADRESS(xrandr, propertyData.ffXGetWindowProperty, XGetWindowProperty,)
|
||||
bool propertyDataInitialized = x11InitPropertyData(xrandr, &propertyData);
|
||||
|
||||
data.display = ffXOpenDisplay(NULL);
|
||||
if(data.display == NULL)
|
||||
@@ -297,13 +285,14 @@ void ffdsConnectXrandr(const FFinstance* instance, FFDisplayServerResult* result
|
||||
return;
|
||||
}
|
||||
|
||||
data.results = &result->resolutions;
|
||||
if(propertyDataInitialized && ScreenCount(data.display) > 0)
|
||||
x11DetectWMFromEWMH(&propertyData, data.display, result);
|
||||
|
||||
data.result = result;
|
||||
|
||||
for(int i = 0; i < ScreenCount(data.display); i++)
|
||||
xrandrHandleScreen(&data, ScreenOfDisplay(data.display, i));
|
||||
|
||||
x11DetectWMFromEWMH(&propertyData, data.display, result);
|
||||
|
||||
ffXCloseDisplay(data.display);
|
||||
dlclose(xrandr);
|
||||
|
||||
|
||||
+18
-8
@@ -354,14 +354,20 @@ static inline void listSupportedFeatures()
|
||||
#ifdef FF_HAVE_VULKAN
|
||||
"vulkan\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_X11
|
||||
"x11\n"
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
"wayland\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XCB_RANDR
|
||||
"xcb-randr\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XCB
|
||||
"xcb\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_XRANDR
|
||||
"xrandr\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_WAYLAND
|
||||
"wayland\n"
|
||||
#ifdef FF_HAVE_X11
|
||||
"x11\n"
|
||||
#endif
|
||||
#ifdef FF_HAVE_GIO
|
||||
"gio\n"
|
||||
@@ -826,16 +832,20 @@ static void parseOption(FFinstance* instance, FFdata* data, const char* key, con
|
||||
optionParseString(key, value, &instance->config.libPCI);
|
||||
else if(strcasecmp(key, "--lib-vulkan") == 0)
|
||||
optionParseString(key, value, &instance->config.libVulkan);
|
||||
else if(strcasecmp(key, "--lib-X11") == 0)
|
||||
optionParseString(key, value, &instance->config.libX11);
|
||||
else if(strcasecmp(key, "--lib-wayland") == 0)
|
||||
optionParseString(key, value, &instance->config.libWayland);
|
||||
else if(strcasecmp(key, "--lib-xcb-randr") == 0)
|
||||
optionCheckString(key, value, &instance->config.libXcbRandr);
|
||||
else if(strcasecmp(key, "--lib-xcb") == 0)
|
||||
optionParseString(key, value, &instance->config.libXcb);
|
||||
else if(strcasecmp(key, "--lib-Xrandr") == 0)
|
||||
optionParseString(key, value, &instance->config.libXrandr);
|
||||
else if(strcasecmp(key, "--lib-X11") == 0)
|
||||
optionParseString(key, value, &instance->config.libX11);
|
||||
else if(strcasecmp(key, "--lib-gio") == 0)
|
||||
optionParseString(key, value, &instance->config.libGIO);
|
||||
else if(strcasecmp(key, "--lib-DConf") == 0)
|
||||
optionParseString(key, value, &instance->config.libDConf);
|
||||
else if(strcasecmp(key, "--lib-wayland") == 0)
|
||||
optionParseString(key, value, &instance->config.libWayland);
|
||||
else if(strcasecmp(key, "--lib-XFConf") == 0)
|
||||
optionParseString(key, value, &instance->config.libXFConf);
|
||||
else if(strcasecmp(key, "--lib-rpm") == 0)
|
||||
|
||||
+4
-2
@@ -108,9 +108,11 @@ typedef struct FFconfig
|
||||
|
||||
FFstrbuf libPCI;
|
||||
FFstrbuf libVulkan;
|
||||
FFstrbuf libX11;
|
||||
FFstrbuf libXrandr;
|
||||
FFstrbuf libWayland;
|
||||
FFstrbuf libXcbRandr;
|
||||
FFstrbuf libXcb;
|
||||
FFstrbuf libXrandr;
|
||||
FFstrbuf libX11;
|
||||
FFstrbuf libGIO;
|
||||
FFstrbuf libDConf;
|
||||
FFstrbuf libXFConf;
|
||||
|
||||
Reference in New Issue
Block a user