Chore: run clang-format

```bash
find . -type f \( -name "*.c" -o -name "*.h" -o -name "*.cpp" -o -name "*.hpp" \) ! -path "src/3rdparty/*" -print0 | xargs -0 clang-format -i
```
This commit is contained in:
李通洲
2026-03-29 09:28:49 +08:00
parent cdd4cee968
commit e0eba8ce21
690 changed files with 28093 additions and 30062 deletions
+8 -8
View File
@@ -1,16 +1,16 @@
#include "displayserver_linux.h"
#include "common/stringUtils.h"
FFDisplayType ffdsGetDisplayType(const char* name)
{
if(ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-"))
FFDisplayType ffdsGetDisplayType(const char* name) {
if (ffStrStartsWith(name, "eDP-") || ffStrStartsWith(name, "LVDS-")) {
return FF_DISPLAY_TYPE_BUILTIN;
else if(ffStrStartsWith(name, "HDMI-") ||
ffStrStartsWith(name, "DP-") ||
ffStrStartsWith(name, "DisplayPort-") ||
ffStrStartsWith(name, "DVI-") ||
ffStrStartsWith(name, "VGA-"))
} else if (ffStrStartsWith(name, "HDMI-") ||
ffStrStartsWith(name, "DP-") ||
ffStrStartsWith(name, "DisplayPort-") ||
ffStrStartsWith(name, "DVI-") ||
ffStrStartsWith(name, "VGA-")) {
return FF_DISPLAY_TYPE_EXTERNAL;
}
return FF_DISPLAY_TYPE_UNKNOWN;
}
@@ -3,95 +3,89 @@
#include "common/stringUtils.h"
#ifdef __FreeBSD__
#include "common/settings.h"
# include "common/settings.h"
#endif
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result)
{
static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) {
const char* env = getenv("XDG_SESSION_TYPE");
if(env)
{
if(ffStrEqualsIgnCase(env, "wayland"))
if (env) {
if (ffStrEqualsIgnCase(env, "wayland")) {
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
else if(ffStrEqualsIgnCase(env, "x11") || ffStrEqualsIgnCase(env, "xorg"))
} else if (ffStrEqualsIgnCase(env, "x11") || ffStrEqualsIgnCase(env, "xorg")) {
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
else if(ffStrEqualsIgnCase(env, "tty"))
} else if (ffStrEqualsIgnCase(env, "tty")) {
ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
else
} else {
ffStrbufSetS(&result->wmProtocolName, env);
}
return;
}
if(getenv("WAYLAND_DISPLAY") != NULL || getenv("WAYLAND_SOCKET") != NULL)
{
if (getenv("WAYLAND_DISPLAY") != NULL || getenv("WAYLAND_SOCKET") != NULL) {
ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
return;
}
if(getenv("DISPLAY") != NULL) // XWayland also set this
if (getenv("DISPLAY") != NULL) // XWayland also set this
{
ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
return;
}
env = getenv("TERM");
if(ffStrSet(env) && ffStrEqualsIgnCase(env, "linux"))
{
if (ffStrSet(env) && ffStrEqualsIgnCase(env, "linux")) {
ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
return;
}
}
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds)
{
if (instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE)
{
//We try wayland as our preferred display server, as it supports the most features.
//This method can't detect the name of our WM / DE
void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) {
if (instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE) {
// We try wayland as our preferred display server, as it supports the most features.
// This method can't detect the name of our WM / DE
ffdsConnectWayland(ds);
//Try the x11 libs, from most feature rich to least.
//We use the display list to detect if a connection is needed.
//They respect wmProtocolName, and only detect display if it is set.
if(ds->displays.length == 0)
// Try the x11 libs, from most feature rich to least.
// We use the display list to detect if a connection is needed.
// They respect wmProtocolName, and only detect display if it is set.
if (ds->displays.length == 0) {
ffdsConnectXcbRandr(ds);
}
if(ds->displays.length == 0)
if (ds->displays.length == 0) {
ffdsConnectXrandr(ds);
}
}
//This display detection method is display server independent.
//Use it if all connections failed
if(ds->displays.length == 0)
// This display detection method is display server independent.
// Use it if all connections failed
if (ds->displays.length == 0) {
ffdsConnectDrm(ds);
}
#ifdef __FreeBSD__
if(ds->displays.length == 0)
{
#ifdef __FreeBSD__
if (ds->displays.length == 0) {
FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
if (ffSettingsGetFreeBSDKenv("screen.width", &buf))
{
if (ffSettingsGetFreeBSDKenv("screen.width", &buf)) {
uint32_t width = (uint32_t) ffStrbufToUInt(&buf, 0);
if (width)
{
if (width) {
ffStrbufClear(&buf);
if (ffSettingsGetFreeBSDKenv("screen.height", &buf))
{
if (ffSettingsGetFreeBSDKenv("screen.height", &buf)) {
uint32_t height = (uint32_t) ffStrbufToUInt(&buf, 0);
ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, 0, 0, NULL, FF_DISPLAY_TYPE_UNKNOWN, false, 0, 0, 0, "kenv");
}
}
}
}
#endif
#endif
if (ds->wmProtocolName.length == 0)
if (ds->wmProtocolName.length == 0) {
getWMProtocolNameFromEnv(ds);
}
if(!ffStrbufEqualS(&ds->wmProtocolName, FF_WM_PROTOCOL_TTY))
{
//This fills in missing information about WM / DE by using env vars and iterating processes
if (!ffStrbufEqualS(&ds->wmProtocolName, FF_WM_PROTOCOL_TTY)) {
// This fills in missing information about WM / DE by using env vars and iterating processes
ffdsDetectWMDE(ds);
}
}
+147 -165
View File
@@ -4,15 +4,15 @@
#include "common/stringUtils.h"
#ifdef __linux__
#include <dirent.h>
# include <dirent.h>
static const char* drmParseSysfs(FFDisplayServerResult* result)
{
static const char* drmParseSysfs(FFDisplayServerResult* result) {
const char* drmDirPath = "/sys/class/drm/";
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath);
if(dirp == NULL)
if (dirp == NULL) {
return "opendir(drmDirPath) failed";
}
FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64);
ffStrbufAppendS(&drmDir, drmDirPath);
@@ -20,10 +20,10 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
uint32_t drmDirLength = drmDir.length;
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
ffStrbufAppendS(&drmDir, entry->d_name);
uint32_t drmDirWithDnameLength = drmDir.length;
@@ -31,16 +31,16 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
char buf;
ffStrbufAppendS(&drmDir, "/enabled");
if (ffReadFileData(drmDir.chars, sizeof(buf), &buf) <= 0 || buf != 'e') {
/* read failed or enabled != "enabled" */
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/status");
buf = 'd';
ffReadFileData(drmDir.chars, sizeof(buf), &buf);
if (buf != 'c') {
/* read failed or status != "connected" */
ffStrbufSubstrBefore(&drmDir, drmDirLength);
continue;
}
/* read failed or enabled != "enabled" */
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/status");
buf = 'd';
ffReadFileData(drmDir.chars, sizeof(buf), &buf);
if (buf != 'c') {
/* read failed or status != "connected" */
ffStrbufSubstrBefore(&drmDir, drmDirLength);
continue;
}
}
unsigned width = 0, height = 0, physicalWidth = 0, physicalHeight = 0;
@@ -51,29 +51,26 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
ffStrbufAppendS(&drmDir, "/edid");
const char* plainName = entry->d_name;
if (ffStrStartsWith(plainName, "card"))
{
if (ffStrStartsWith(plainName, "card")) {
const char* tmp = strchr(plainName + strlen("card"), '-');
if (tmp) plainName = tmp + 1;
if (tmp) {
plainName = tmp + 1;
}
}
uint8_t edidData[512];
ssize_t edidLength = ffReadFileData(drmDir.chars, ARRAY_SIZE(edidData), edidData);
if(edidLength <= 0 || edidLength % 128 != 0)
{
if (edidLength <= 0 || edidLength % 128 != 0) {
edidLength = 0;
ffStrbufSubstrBefore(&drmDir, drmDirWithDnameLength);
ffStrbufAppendS(&drmDir, "/modes");
char modes[32];
if (ffReadFileData(drmDir.chars, ARRAY_SIZE(modes), modes) >= 3)
{
if (ffReadFileData(drmDir.chars, ARRAY_SIZE(modes), modes) >= 3) {
sscanf(modes, "%ux%u", &width, &height);
ffStrbufAppendS(&name, plainName);
}
}
else
{
} else {
ffEdidGetName(edidData, &name);
ffEdidGetPreferredResolutionAndRefreshRate(edidData, &width, &height, &refreshRate);
ffEdidGetPhysicalSize(edidData, &physicalWidth, &physicalHeight);
@@ -81,10 +78,12 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
FFDisplayResult* item = ffdsAppendDisplay(
result,
width, height,
width,
height,
refreshRate,
0,
0, 0,
0,
0,
0,
0,
&name,
@@ -93,10 +92,8 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
0,
physicalWidth,
physicalHeight,
"sysfs-drm"
);
if (item && edidLength)
{
"sysfs-drm");
if (item && edidLength) {
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
}
@@ -110,74 +107,72 @@ static const char* drmParseSysfs(FFDisplayServerResult* result)
#ifdef FF_HAVE_DRM
#include "common/library.h"
# include "common/library.h"
#include <xf86drm.h>
#include <xf86drmMode.h>
#include <fcntl.h>
# include <xf86drm.h>
# include <xf86drmMode.h>
# include <fcntl.h>
// https://gitlab.freedesktop.org/mesa/drm/-/blob/main/xf86drmMode.c#L1785
// It's not supported on Ubuntu 20.04
static inline const char* drmType2Name(uint32_t connector_type)
{
static inline const char* drmType2Name(uint32_t connector_type) {
/* Keep the strings in sync with the kernel's drm_connector_enum_list in
* drm_connector.c. */
switch (connector_type)
{
case DRM_MODE_CONNECTOR_Unknown:
return "Unknown";
case DRM_MODE_CONNECTOR_VGA:
return "VGA";
case DRM_MODE_CONNECTOR_DVII:
return "DVI-I";
case DRM_MODE_CONNECTOR_DVID:
return "DVI-D";
case DRM_MODE_CONNECTOR_DVIA:
return "DVI-A";
case DRM_MODE_CONNECTOR_Composite:
return "Composite";
case DRM_MODE_CONNECTOR_SVIDEO:
return "SVIDEO";
case DRM_MODE_CONNECTOR_LVDS:
return "LVDS";
case DRM_MODE_CONNECTOR_Component:
return "Component";
case DRM_MODE_CONNECTOR_9PinDIN:
return "DIN";
case DRM_MODE_CONNECTOR_DisplayPort:
return "DP";
case DRM_MODE_CONNECTOR_HDMIA:
return "HDMI-A";
case DRM_MODE_CONNECTOR_HDMIB:
return "HDMI-B";
case DRM_MODE_CONNECTOR_TV:
return "TV";
case DRM_MODE_CONNECTOR_eDP:
return "eDP";
case DRM_MODE_CONNECTOR_VIRTUAL:
return "Virtual";
case DRM_MODE_CONNECTOR_DSI:
return "DSI";
case DRM_MODE_CONNECTOR_DPI:
return "DPI";
case DRM_MODE_CONNECTOR_WRITEBACK:
return "Writeback";
case 19 /*DRM_MODE_CONNECTOR_SPI*/:
return "SPI";
case 20 /*DRM_MODE_CONNECTOR_USB*/:
return "USB";
default:
return "Unsupported";
switch (connector_type) {
case DRM_MODE_CONNECTOR_Unknown:
return "Unknown";
case DRM_MODE_CONNECTOR_VGA:
return "VGA";
case DRM_MODE_CONNECTOR_DVII:
return "DVI-I";
case DRM_MODE_CONNECTOR_DVID:
return "DVI-D";
case DRM_MODE_CONNECTOR_DVIA:
return "DVI-A";
case DRM_MODE_CONNECTOR_Composite:
return "Composite";
case DRM_MODE_CONNECTOR_SVIDEO:
return "SVIDEO";
case DRM_MODE_CONNECTOR_LVDS:
return "LVDS";
case DRM_MODE_CONNECTOR_Component:
return "Component";
case DRM_MODE_CONNECTOR_9PinDIN:
return "DIN";
case DRM_MODE_CONNECTOR_DisplayPort:
return "DP";
case DRM_MODE_CONNECTOR_HDMIA:
return "HDMI-A";
case DRM_MODE_CONNECTOR_HDMIB:
return "HDMI-B";
case DRM_MODE_CONNECTOR_TV:
return "TV";
case DRM_MODE_CONNECTOR_eDP:
return "eDP";
case DRM_MODE_CONNECTOR_VIRTUAL:
return "Virtual";
case DRM_MODE_CONNECTOR_DSI:
return "DSI";
case DRM_MODE_CONNECTOR_DPI:
return "DPI";
case DRM_MODE_CONNECTOR_WRITEBACK:
return "Writeback";
case 19 /*DRM_MODE_CONNECTOR_SPI*/:
return "SPI";
case 20 /*DRM_MODE_CONNECTOR_USB*/:
return "USB";
default:
return "Unsupported";
}
}
FF_MAYBE_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* edidData, ssize_t* edidLength)
{
FF_MAYBE_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t* edidData, ssize_t* edidLength) {
const char* drmDirPath = "/sys/class/drm/";
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath);
if(dirp == NULL)
if (dirp == NULL) {
return "opendir(drmDirPath) failed";
}
FF_STRBUF_AUTO_DESTROY drmDir = ffStrbufCreateA(64);
ffStrbufAppendS(&drmDir, drmDirPath);
@@ -185,10 +180,10 @@ FF_MAYBE_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t*
uint32_t drmDirLength = drmDir.length;
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
if(entry->d_name[0] == '.')
while ((entry = readdir(dirp)) != NULL) {
if (entry->d_name[0] == '.') {
continue;
}
ffStrbufAppendS(&drmDir, entry->d_name);
uint32_t drmDirWithDnameLength = drmDir.length;
@@ -197,8 +192,7 @@ FF_MAYBE_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t*
ffStrbufAppendS(&drmDir, "/connector_id");
ffReadFileData(drmDir.chars, ARRAY_SIZE(connectorId), connectorId);
if (strtoul(connectorId, NULL, 10) != connId)
{
if (strtoul(connectorId, NULL, 10) != connId) {
ffStrbufSubstrBefore(&drmDir, drmDirLength);
continue;
}
@@ -212,8 +206,7 @@ FF_MAYBE_UNUSED static const char* drmGetEdidByConnId(uint32_t connId, uint8_t*
return "Failed to match connector ID";
}
static const char* drmConnectLibdrm(FFDisplayServerResult* result)
{
static const char* drmConnectLibdrm(FFDisplayServerResult* result) {
FF_LIBRARY_LOAD_MESSAGE(libdrm, "libdrm" FF_LIBRARY_EXTENSION, 2)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmGetDevices)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(libdrm, drmModeGetResources)
@@ -234,64 +227,62 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
drmDevice* devices[64];
int nDevices = ffdrmGetDevices(devices, ARRAY_SIZE(devices));
if (nDevices <= 0)
if (nDevices <= 0) {
return "drmGetDevices() failed";
}
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreate();
for (int iDev = 0; iDev < nDevices; ++iDev)
{
for (int iDev = 0; iDev < nDevices; ++iDev) {
drmDevice* dev = devices[iDev];
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY)))
if (!(dev->available_nodes & (1 << DRM_NODE_PRIMARY))) {
continue;
}
const char* path = dev->nodes[DRM_NODE_PRIMARY];
#if __linux__
# if __linux__
ffStrbufSetF(&name, "/sys/class/drm/%s/device/power/runtime_status", strrchr(path, '/') + 1);
char buffer[8] = "";
if (ffReadFileData(name.chars, strlen("suspend"), buffer) > 0 && ffStrStartsWith(buffer, "suspend"))
if (ffReadFileData(name.chars, strlen("suspend"), buffer) > 0 && ffStrStartsWith(buffer, "suspend")) {
continue;
#endif
}
# endif
FF_AUTO_CLOSE_FD int primaryFd = open(path, O_RDWR | O_CLOEXEC);
if (primaryFd < 0)
if (primaryFd < 0) {
continue;
}
drmModeRes* res = ffdrmModeGetResources(primaryFd);
if (!res)
if (!res) {
continue;
}
for (int iConn = 0; iConn < res->count_connectors; ++iConn)
{
for (int iConn = 0; iConn < res->count_connectors; ++iConn) {
drmModeConnector* conn = ffdrmModeGetConnectorCurrent(primaryFd, res->connectors[iConn]);
if (!conn)
if (!conn) {
continue;
}
if (conn->connection != DRM_MODE_DISCONNECTED)
{
if (conn->connection != DRM_MODE_DISCONNECTED) {
drmModeEncoder* encoder = ffdrmModeGetEncoder(primaryFd, conn->encoder_id);
uint32_t width = 0, height = 0, refreshRate = 0;
uint8_t bitDepth = 0;
if (encoder)
{
if (encoder) {
drmModeCrtc* crtc = ffdrmModeGetCrtc(primaryFd, encoder->crtc_id);
if (crtc)
{
if (crtc) {
width = crtc->mode.hdisplay;
height = crtc->mode.vdisplay;
refreshRate = crtc->mode.vrefresh;
if (refreshRate == 0)
{
if (refreshRate == 0) {
// There are weird cases that we can't get the refresh rate from the CRTC but from the modes
for (int iMode = 0; iMode < conn->count_modes; ++iMode)
{
for (int iMode = 0; iMode < conn->count_modes; ++iMode) {
drmModeModeInfo* mode = &conn->modes[iMode];
if (mode->clock == crtc->mode.clock && mode->htotal == crtc->mode.htotal)
{
if (mode->clock == crtc->mode.clock && mode->htotal == crtc->mode.htotal) {
refreshRate = mode->vrefresh;
break;
}
@@ -299,8 +290,7 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
}
drmModeFBPtr fb = ffdrmModeGetFB(primaryFd, crtc->buffer_id);
if (fb)
{
if (fb) {
bitDepth = (uint8_t) (fb->depth / 3);
ffdrmModeFreeFB(fb);
}
@@ -313,12 +303,10 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
uint32_t preferredWidth = 0, preferredHeight = 0, preferredRefreshRate = 0;
for (int iMode = 0; iMode < conn->count_modes; ++iMode)
{
for (int iMode = 0; iMode < conn->count_modes; ++iMode) {
drmModeModeInfo* mode = &conn->modes[iMode];
if (mode->type & DRM_MODE_TYPE_PREFERRED)
{
if (mode->type & DRM_MODE_TYPE_PREFERRED) {
preferredWidth = mode->hdisplay;
preferredHeight = mode->vdisplay;
preferredRefreshRate = mode->vrefresh;
@@ -328,39 +316,35 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
// NVIDIA DRM driver seems incomplete and conn->encoder_id == 0
// Assume preferred resolution is used as what we do in drmParseSys
if (width == 0 || height == 0)
{
if (width == 0 || height == 0) {
width = preferredWidth;
height = preferredHeight;
refreshRate = preferredRefreshRate;
}
ffStrbufClear(&name);
uint16_t myear = 0, mweak = 0;
uint32_t serial = 0;
FFDisplayHdrStatus hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
for (int iProp = 0; iProp < conn->count_props; ++iProp)
{
drmModePropertyRes *prop = ffdrmModeGetProperty(primaryFd, conn->props[iProp]);
if (!prop)
for (int iProp = 0; iProp < conn->count_props; ++iProp) {
drmModePropertyRes* prop = ffdrmModeGetProperty(primaryFd, conn->props[iProp]);
if (!prop) {
continue;
}
uint32_t type = prop->flags & (DRM_MODE_PROP_LEGACY_TYPE | DRM_MODE_PROP_EXTENDED_TYPE);
if (type == DRM_MODE_PROP_BLOB && ffStrEquals(prop->name, "EDID"))
{
if (type == DRM_MODE_PROP_BLOB && ffStrEquals(prop->name, "EDID")) {
drmModePropertyBlobPtr blob = NULL;
if (prop->count_blobs > 0 && prop->blob_ids != NULL)
if (prop->count_blobs > 0 && prop->blob_ids != NULL) {
blob = ffdrmModeGetPropertyBlob(primaryFd, prop->blob_ids[0]);
else
} else {
blob = ffdrmModeGetPropertyBlob(primaryFd, (uint32_t) conn->prop_values[iProp]);
}
if (blob)
{
if (blob->length >= 128)
{
if (blob) {
if (blob->length >= 128) {
ffEdidGetName(blob->data, &name);
hdrStatus = ffEdidGetHdrCompatible(blob->data, blob->length) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(blob->data, &serial, &myear, &mweak);
@@ -372,50 +356,49 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
ffdrmModeFreeProperty(prop);
}
#if __linux__
if (name.length == 0)
{
# if __linux__
if (name.length == 0) {
uint8_t edidData[512];
ssize_t edidLength = 0;
drmGetEdidByConnId(conn->connector_id, edidData, &edidLength);
if (edidLength > 0 && edidLength % 128 == 0)
{
if (edidLength > 0 && edidLength % 128 == 0) {
ffEdidGetName(edidData, &name);
hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &serial, &myear, &mweak);
}
}
#endif
# endif
if (name.length == 0)
{
if (name.length == 0) {
const char* connectorTypeName = drmType2Name(conn->connector_type);
if (connectorTypeName == NULL)
if (connectorTypeName == NULL) {
connectorTypeName = "Unknown";
}
ffStrbufSetF(&name, "%s-%d", connectorTypeName, iConn + 1);
}
FFDisplayResult* item = ffdsAppendDisplay(result,
width, height,
width,
height,
refreshRate,
0,
preferredWidth, preferredHeight,
preferredWidth,
preferredHeight,
preferredRefreshRate,
0,
&name,
conn->connector_type == DRM_MODE_CONNECTOR_eDP || conn->connector_type == DRM_MODE_CONNECTOR_LVDS
? FF_DISPLAY_TYPE_BUILTIN
: conn->connector_type == DRM_MODE_CONNECTOR_HDMIA || conn->connector_type == DRM_MODE_CONNECTOR_HDMIB || conn->connector_type == DRM_MODE_CONNECTOR_DisplayPort
? FF_DISPLAY_TYPE_EXTERNAL : FF_DISPLAY_TYPE_UNKNOWN,
? FF_DISPLAY_TYPE_EXTERNAL
: FF_DISPLAY_TYPE_UNKNOWN,
false,
conn->connector_id,
conn->mmWidth,
conn->mmHeight,
"libdrm"
);
"libdrm");
if (item)
{
if (item) {
item->hdrStatus = hdrStatus;
item->serial = serial;
item->manufactureYear = myear;
@@ -437,19 +420,18 @@ static const char* drmConnectLibdrm(FFDisplayServerResult* result)
#endif
const char* ffdsConnectDrm(FF_MAYBE_UNUSED FFDisplayServerResult* result)
{
#ifdef FF_HAVE_DRM
if (instance.config.general.dsForceDrm != FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY)
{
if (drmConnectLibdrm(result) == NULL)
const char* ffdsConnectDrm(FF_MAYBE_UNUSED FFDisplayServerResult* result) {
#ifdef FF_HAVE_DRM
if (instance.config.general.dsForceDrm != FF_DS_FORCE_DRM_TYPE_SYSFS_ONLY) {
if (drmConnectLibdrm(result) == NULL) {
return NULL;
}
}
#endif
#endif
#ifdef __linux__
#ifdef __linux__
return drmParseSysfs(result);
#endif
#endif
return "fastfetch was compiled without drm support";
}
@@ -1,56 +1,49 @@
#ifdef FF_HAVE_WAYLAND
#include "wayland.h"
#include "common/stringUtils.h"
#include "xdg-output-unstable-v1-client-protocol.h"
# include "wayland.h"
# include "common/stringUtils.h"
# include "xdg-output-unstable-v1-client-protocol.h"
static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate)
{
static void waylandOutputModeListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, uint32_t flags, int32_t width, int32_t height, int32_t refreshRate) {
WaylandDisplay* display = data;
if (flags & WL_OUTPUT_MODE_CURRENT)
{
if (flags & WL_OUTPUT_MODE_CURRENT) {
display->width = width;
display->height = height;
display->refreshRate = refreshRate;
}
if (flags & WL_OUTPUT_MODE_PREFERRED)
{
if (flags & WL_OUTPUT_MODE_PREFERRED) {
display->preferredWidth = width;
display->preferredHeight = height;
display->preferredRefreshRate = refreshRate;
}
}
static void waylandOutputScaleListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, int32_t scale)
{
static void waylandOutputScaleListener(void* data, FF_MAYBE_UNUSED struct wl_output* output, int32_t scale) {
WaylandDisplay* display = data;
display->dpi = 96 * (uint32_t) scale;
}
static void waylandOutputGeometryListener(void *data,
FF_MAYBE_UNUSED struct wl_output *output,
static void waylandOutputGeometryListener(void* data,
FF_MAYBE_UNUSED struct wl_output* output,
FF_MAYBE_UNUSED int32_t x,
FF_MAYBE_UNUSED int32_t y,
int32_t physical_width,
int32_t physical_height,
FF_MAYBE_UNUSED int32_t subpixel,
FF_MAYBE_UNUSED const char *make,
FF_MAYBE_UNUSED const char *model,
int32_t transform)
{
FF_MAYBE_UNUSED const char* make,
FF_MAYBE_UNUSED const char* model,
int32_t transform) {
WaylandDisplay* display = data;
display->physicalWidth = physical_width;
display->physicalHeight = physical_height;
display->transform = (enum wl_output_transform) transform;
}
static void handleXdgLogicalSize(void *data, FF_MAYBE_UNUSED struct zxdg_output_v1 *_, int32_t width, FF_MAYBE_UNUSED int32_t height)
{
static void handleXdgLogicalSize(void* data, FF_MAYBE_UNUSED struct zxdg_output_v1* _, int32_t width, FF_MAYBE_UNUSED int32_t height) {
WaylandDisplay* display = data;
// Seems the values are only useful when ractional scale is enabled
if (width < display->width)
{
if (width < display->width) {
display->dpi = (uint32_t) (display->width * 96 / width);
}
}
@@ -58,17 +51,16 @@ static void handleXdgLogicalSize(void *data, FF_MAYBE_UNUSED struct zxdg_output_
// Dirty hack for #477
// The order of these callbacks MUST follow `struct wl_output_listener`
static void* outputListener[] = {
waylandOutputGeometryListener, // geometry
waylandOutputModeListener, // mode
stubListener, // done
waylandOutputScaleListener, // scale
ffWaylandOutputNameListener, // name
waylandOutputGeometryListener, // geometry
waylandOutputModeListener, // mode
stubListener, // done
waylandOutputScaleListener, // scale
ffWaylandOutputNameListener, // name
ffWaylandOutputDescriptionListener, // description
};
static_assert(
sizeof(outputListener) >= sizeof(struct wl_output_listener),
"sizeof(outputListener) is too small. Please report it to fastfetch github issue"
);
"sizeof(outputListener) is too small. Please report it to fastfetch github issue");
static struct zxdg_output_v1_listener zxdgOutputListener = {
.logical_position = (void*) stubListener,
@@ -78,11 +70,11 @@ static struct zxdg_output_v1_listener zxdgOutputListener = {
.description = (void*) ffWaylandOutputDescriptionListener,
};
const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
{
const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
struct wl_proxy* 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)
if (output == NULL) {
return "Failed to create wl_output";
}
WaylandDisplay display = {
.parent = wldata,
@@ -93,24 +85,20 @@ const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry*
.edidName = ffStrbufCreate(),
};
if (wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, &display) < 0)
{
if (wldata->ffwl_proxy_add_listener(output, (void (**)(void)) &outputListener, &display) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to add listener to wl_output";
}
if (wldata->ffwl_display_roundtrip(wldata->display) < 0)
{
if (wldata->ffwl_display_roundtrip(wldata->display) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to roundtrip wl_output";
}
if (wldata->zxdgOutputManager)
{
if (wldata->zxdgOutputManager) {
struct wl_proxy* zxdgOutput = wldata->ffwl_proxy_marshal_constructor_versioned(wldata->zxdgOutputManager, ZXDG_OUTPUT_MANAGER_V1_GET_XDG_OUTPUT, &zxdg_output_v1_interface, version, NULL, output);
if (zxdgOutput)
{
wldata->ffwl_proxy_add_listener(zxdgOutput, (void(**)(void)) &zxdgOutputListener, &display);
if (zxdgOutput) {
wldata->ffwl_proxy_add_listener(zxdgOutput, (void (**)(void)) &zxdgOutputListener, &display);
wldata->ffwl_display_roundtrip(wldata->display);
wldata->ffwl_proxy_destroy(zxdgOutput);
}
@@ -118,8 +106,9 @@ const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry*
wldata->ffwl_proxy_destroy(output);
if(display.width <= 0 || display.height <= 0)
if (display.width <= 0 || display.height <= 0) {
return "Failed to get display information from wl_output";
}
uint32_t rotation = ffWaylandHandleRotation(&display);
@@ -136,23 +125,22 @@ const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry*
? &display.edidName
// Try ignoring `eDP-1-unknown`, where `unknown` is localized
: display.description.length && !ffStrbufContain(&display.description, &display.name)
? &display.description
: &display.name,
? &display.description
: &display.name,
display.type,
false,
display.id,
(uint32_t) display.physicalWidth,
(uint32_t) display.physicalHeight,
"wayland-global"
);
if (item)
{
if (display.hdrSupported)
"wayland-global");
if (item) {
if (display.hdrSupported) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
else if (display.hdrInfoAvailable)
} else if (display.hdrInfoAvailable) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
else
} else {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
}
item->manufactureYear = display.myear;
item->manufactureWeek = display.mweek;
@@ -166,11 +154,11 @@ const char* ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry*
return NULL;
}
const char* ffWaylandHandleZxdgOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
{
const char* ffWaylandHandleZxdgOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
struct wl_proxy* manager = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &zxdg_output_manager_v1_interface, version, name, zxdg_output_manager_v1_interface.name, version, NULL);
if(manager == NULL)
if (manager == NULL) {
return "Failed to create zxdg_output_manager_v1";
}
wldata->zxdgOutputManager = manager;
File diff suppressed because it is too large Load Diff
@@ -12,105 +12,114 @@
* SPDX-License-Identifier: MIT-CMU
*/
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <wayland-util.h>
# include <stdbool.h>
# include <stdlib.h>
# include <stdint.h>
# include <wayland-util.h>
extern const struct wl_interface kde_output_device_mode_v2_interface;
extern const struct wl_interface kde_output_device_v2_interface;
static const struct wl_interface *kde_output_device_v2_types[] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&kde_output_device_v2_interface,
&kde_output_device_mode_v2_interface,
&kde_output_device_mode_v2_interface,
static const struct wl_interface* kde_output_device_v2_types[] = {
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
&kde_output_device_v2_interface,
&kde_output_device_mode_v2_interface,
&kde_output_device_mode_v2_interface,
};
static const struct wl_message kde_output_device_registry_v2_requests[] = {
{ "stop", "21", kde_output_device_v2_types + 0 },
{"stop", "21", kde_output_device_v2_types + 0},
};
static const struct wl_message kde_output_device_registry_v2_events[] = {
{ "finished", "21", kde_output_device_v2_types + 0 },
{ "output", "21n", kde_output_device_v2_types + 8 },
{"finished", "21", kde_output_device_v2_types + 0},
{"output", "21n", kde_output_device_v2_types + 8},
};
WL_EXPORT const struct wl_interface kde_output_device_registry_v2_interface = {
"kde_output_device_registry_v2", 21,
1, kde_output_device_registry_v2_requests,
2, kde_output_device_registry_v2_events,
"kde_output_device_registry_v2",
21,
1,
kde_output_device_registry_v2_requests,
2,
kde_output_device_registry_v2_events,
};
static const struct wl_message kde_output_device_v2_requests[] = {
{ "release", "21", kde_output_device_v2_types + 0 },
{"release", "21", kde_output_device_v2_types + 0},
};
static const struct wl_message kde_output_device_v2_events[] = {
{ "geometry", "iiiiissi", kde_output_device_v2_types + 0 },
{ "current_mode", "o", kde_output_device_v2_types + 9 },
{ "mode", "n", kde_output_device_v2_types + 10 },
{ "done", "", kde_output_device_v2_types + 0 },
{ "scale", "f", kde_output_device_v2_types + 0 },
{ "edid", "s", kde_output_device_v2_types + 0 },
{ "enabled", "i", kde_output_device_v2_types + 0 },
{ "uuid", "s", kde_output_device_v2_types + 0 },
{ "serial_number", "s", kde_output_device_v2_types + 0 },
{ "eisa_id", "s", kde_output_device_v2_types + 0 },
{ "capabilities", "u", kde_output_device_v2_types + 0 },
{ "overscan", "u", kde_output_device_v2_types + 0 },
{ "vrr_policy", "u", kde_output_device_v2_types + 0 },
{ "rgb_range", "u", kde_output_device_v2_types + 0 },
{ "name", "2s", kde_output_device_v2_types + 0 },
{ "high_dynamic_range", "3u", kde_output_device_v2_types + 0 },
{ "sdr_brightness", "3u", kde_output_device_v2_types + 0 },
{ "wide_color_gamut", "3u", kde_output_device_v2_types + 0 },
{ "auto_rotate_policy", "4u", kde_output_device_v2_types + 0 },
{ "icc_profile_path", "5s", kde_output_device_v2_types + 0 },
{ "brightness_metadata", "6uuu", kde_output_device_v2_types + 0 },
{ "brightness_overrides", "6iii", kde_output_device_v2_types + 0 },
{ "sdr_gamut_wideness", "6u", kde_output_device_v2_types + 0 },
{ "color_profile_source", "7u", kde_output_device_v2_types + 0 },
{ "brightness", "8u", kde_output_device_v2_types + 0 },
{ "color_power_tradeoff", "10u", kde_output_device_v2_types + 0 },
{ "dimming", "11u", kde_output_device_v2_types + 0 },
{ "replication_source", "13s", kde_output_device_v2_types + 0 },
{ "ddc_ci_allowed", "14u", kde_output_device_v2_types + 0 },
{ "max_bits_per_color", "15u", kde_output_device_v2_types + 0 },
{ "max_bits_per_color_range", "15uu", kde_output_device_v2_types + 0 },
{ "automatic_max_bits_per_color_limit", "15u", kde_output_device_v2_types + 0 },
{ "edr_policy", "16u", kde_output_device_v2_types + 0 },
{ "sharpness", "17u", kde_output_device_v2_types + 0 },
{ "priority", "18u", kde_output_device_v2_types + 0 },
{ "auto_brightness", "20u", kde_output_device_v2_types + 0 },
{ "removed", "21", kde_output_device_v2_types + 0 },
{"geometry", "iiiiissi", kde_output_device_v2_types + 0},
{"current_mode", "o", kde_output_device_v2_types + 9},
{"mode", "n", kde_output_device_v2_types + 10},
{"done", "", kde_output_device_v2_types + 0},
{"scale", "f", kde_output_device_v2_types + 0},
{"edid", "s", kde_output_device_v2_types + 0},
{"enabled", "i", kde_output_device_v2_types + 0},
{"uuid", "s", kde_output_device_v2_types + 0},
{"serial_number", "s", kde_output_device_v2_types + 0},
{"eisa_id", "s", kde_output_device_v2_types + 0},
{"capabilities", "u", kde_output_device_v2_types + 0},
{"overscan", "u", kde_output_device_v2_types + 0},
{"vrr_policy", "u", kde_output_device_v2_types + 0},
{"rgb_range", "u", kde_output_device_v2_types + 0},
{"name", "2s", kde_output_device_v2_types + 0},
{"high_dynamic_range", "3u", kde_output_device_v2_types + 0},
{"sdr_brightness", "3u", kde_output_device_v2_types + 0},
{"wide_color_gamut", "3u", kde_output_device_v2_types + 0},
{"auto_rotate_policy", "4u", kde_output_device_v2_types + 0},
{"icc_profile_path", "5s", kde_output_device_v2_types + 0},
{"brightness_metadata", "6uuu", kde_output_device_v2_types + 0},
{"brightness_overrides", "6iii", kde_output_device_v2_types + 0},
{"sdr_gamut_wideness", "6u", kde_output_device_v2_types + 0},
{"color_profile_source", "7u", kde_output_device_v2_types + 0},
{"brightness", "8u", kde_output_device_v2_types + 0},
{"color_power_tradeoff", "10u", kde_output_device_v2_types + 0},
{"dimming", "11u", kde_output_device_v2_types + 0},
{"replication_source", "13s", kde_output_device_v2_types + 0},
{"ddc_ci_allowed", "14u", kde_output_device_v2_types + 0},
{"max_bits_per_color", "15u", kde_output_device_v2_types + 0},
{"max_bits_per_color_range", "15uu", kde_output_device_v2_types + 0},
{"automatic_max_bits_per_color_limit", "15u", kde_output_device_v2_types + 0},
{"edr_policy", "16u", kde_output_device_v2_types + 0},
{"sharpness", "17u", kde_output_device_v2_types + 0},
{"priority", "18u", kde_output_device_v2_types + 0},
{"auto_brightness", "20u", kde_output_device_v2_types + 0},
{"removed", "21", kde_output_device_v2_types + 0},
};
WL_EXPORT const struct wl_interface kde_output_device_v2_interface = {
"kde_output_device_v2", 21,
1, kde_output_device_v2_requests,
37, kde_output_device_v2_events,
"kde_output_device_v2",
21,
1,
kde_output_device_v2_requests,
37,
kde_output_device_v2_events,
};
static const struct wl_message kde_output_device_mode_v2_events[] = {
{ "size", "ii", kde_output_device_v2_types + 0 },
{ "refresh", "i", kde_output_device_v2_types + 0 },
{ "preferred", "", kde_output_device_v2_types + 0 },
{ "removed", "", kde_output_device_v2_types + 0 },
{ "flags", "19u", kde_output_device_v2_types + 0 },
{"size", "ii", kde_output_device_v2_types + 0},
{"refresh", "i", kde_output_device_v2_types + 0},
{"preferred", "", kde_output_device_v2_types + 0},
{"removed", "", kde_output_device_v2_types + 0},
{"flags", "19u", kde_output_device_v2_types + 0},
};
WL_EXPORT const struct wl_interface kde_output_device_mode_v2_interface = {
"kde_output_device_mode_v2", 21,
0, NULL,
5, kde_output_device_mode_v2_events,
"kde_output_device_mode_v2",
21,
0,
NULL,
5,
kde_output_device_mode_v2_events,
};
#endif
@@ -7,7 +7,7 @@
#include <stddef.h>
#include "wayland-client.h"
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
@@ -26,7 +26,7 @@ extern "C" {
struct kde_output_order_v1;
#ifndef KDE_OUTPUT_ORDER_V1_INTERFACE
#define KDE_OUTPUT_ORDER_V1_INTERFACE
# define KDE_OUTPUT_ORDER_V1_INTERFACE
/**
* @page page_iface_kde_output_order_v1 kde_output_order_v1
* @section page_iface_kde_output_order_v1_desc Description
@@ -50,34 +50,35 @@ extern const struct wl_interface kde_output_order_v1_interface;
* @struct kde_output_order_v1_listener
*/
struct kde_output_order_v1_listener {
/**
* output name
*
* Specifies the output identified by their wl_output.name.
* @param output_name the name of the output
*/
void (*output)(void *data,
struct kde_output_order_v1 *kde_output_order_v1,
const char *output_name);
/**
* done
*
* Specifies that the output list is complete. On the next output
* event, a new list begins.
*/
void (*done)(void *data,
struct kde_output_order_v1 *kde_output_order_v1);
/**
* output name
*
* Specifies the output identified by their wl_output.name.
* @param output_name the name of the output
*/
void (*output)(void* data,
struct kde_output_order_v1* kde_output_order_v1,
const char* output_name);
/**
* done
*
* Specifies that the output list is complete. On the next output
* event, a new list begins.
*/
void (*done)(void* data,
struct kde_output_order_v1* kde_output_order_v1);
};
/**
* @ingroup iface_kde_output_order_v1
*/
static inline int
kde_output_order_v1_add_listener(struct kde_output_order_v1 *kde_output_order_v1,
const struct kde_output_order_v1_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) kde_output_order_v1,
(void (**)(void)) listener, data);
kde_output_order_v1_add_listener(struct kde_output_order_v1* kde_output_order_v1,
const struct kde_output_order_v1_listener* listener,
void* data) {
return wl_proxy_add_listener((struct wl_proxy*) kde_output_order_v1,
(void (**)(void)) listener,
data);
}
#define KDE_OUTPUT_ORDER_V1_DESTROY 0
@@ -126,7 +127,7 @@ kde_output_order_v1_add_listener(struct kde_output_order_v1 *kde_output_order_v1
// KDE_OUTPUT_ORDER_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) kde_output_order_v1), WL_MARSHAL_FLAG_DESTROY);
// }
#ifdef __cplusplus
#ifdef __cplusplus
}
#endif
@@ -8,28 +8,30 @@
* SPDX-License-Identifier: MIT-CMU
*/
#include <stdlib.h>
#include <stdint.h>
#include "wayland-util.h"
# include <stdlib.h>
# include <stdint.h>
# include "wayland-util.h"
static const struct wl_interface *kde_output_order_v1_types[] = {
NULL,
static const struct wl_interface* kde_output_order_v1_types[] = {
NULL,
};
static const struct wl_message kde_output_order_v1_requests[] = {
{ "destroy", "", kde_output_order_v1_types + 0 },
{"destroy", "", kde_output_order_v1_types + 0},
};
static const struct wl_message kde_output_order_v1_events[] = {
{ "output", "s", kde_output_order_v1_types + 0 },
{ "done", "", kde_output_order_v1_types + 0 },
{"output", "s", kde_output_order_v1_types + 0},
{"done", "", kde_output_order_v1_types + 0},
};
WL_EXPORT const struct wl_interface kde_output_order_v1_interface = {
"kde_output_order_v1", 1,
1, kde_output_order_v1_requests,
2, kde_output_order_v1_events,
"kde_output_order_v1",
1,
1,
kde_output_order_v1_requests,
2,
kde_output_order_v1_events,
};
#endif
@@ -1,13 +1,12 @@
#ifdef FF_HAVE_WAYLAND
#include "wayland.h"
#include "kde-output-device-v2-client-protocol.h"
#include "kde-output-order-v1-client-protocol.h"
#include "common/edidHelper.h"
#include "common/base64.h"
# include "wayland.h"
# include "kde-output-device-v2-client-protocol.h"
# include "kde-output-order-v1-client-protocol.h"
# include "common/edidHelper.h"
# include "common/base64.h"
typedef struct WaylandKdeMode
{
typedef struct WaylandKdeMode {
int32_t width;
int32_t height;
int32_t refreshRate;
@@ -15,21 +14,18 @@ typedef struct WaylandKdeMode
struct kde_output_device_mode_v2* pMode;
} WaylandKdeMode;
static void waylandKdeModeSizeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t width, int32_t height)
{
static void waylandKdeModeSizeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2* _, int32_t width, int32_t height) {
WaylandKdeMode* mode = (WaylandKdeMode*) data;
mode->width = width;
mode->height = height;
}
static void waylandKdeModeRefreshListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_, int32_t rate)
{
static void waylandKdeModeRefreshListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2* _, int32_t rate) {
WaylandKdeMode* mode = (WaylandKdeMode*) data;
mode->refreshRate = rate;
}
static void waylandKdeModePreferredListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2 *_)
{
static void waylandKdeModePreferredListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_mode_v2* _) {
WaylandKdeMode* mode = (WaylandKdeMode*) data;
mode->preferred = true;
}
@@ -42,88 +38,92 @@ static const struct kde_output_device_mode_v2_listener modeListener = {
.flags = (void*) stubListener,
};
static void waylandKdeModeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, struct kde_output_device_mode_v2 *mode)
{
static void waylandKdeModeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, struct kde_output_device_mode_v2* mode) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
if (!wldata->internal) return;
if (!wldata->internal) {
return;
}
WaylandKdeMode* newMode = ffListAdd((FFlist*) wldata->internal);
*newMode = (WaylandKdeMode) { .pMode = mode };
*newMode = (WaylandKdeMode) {.pMode = mode};
// Strangely, the listener is called only in this function, but not in `waylandKdeCurrentModeListener`
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy *) mode, (void (**)(void)) &modeListener, newMode);
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy*) mode, (void (**)(void)) &modeListener, newMode);
}
static void waylandKdeCurrentModeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2 *_, struct kde_output_device_mode_v2 *mode)
{
static void waylandKdeCurrentModeListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, struct kde_output_device_mode_v2* mode) {
// waylandKdeModeListener is always run before this
WaylandDisplay* wldata = (WaylandDisplay*) data;
if (!wldata->internal) return;
if (!wldata->internal) {
return;
}
int set = 0;
FF_LIST_FOR_EACH(WaylandKdeMode, m, *(FFlist*) wldata->internal)
{
if (m->pMode == mode)
{
FF_LIST_FOR_EACH (WaylandKdeMode, m, *(FFlist*) wldata->internal) {
if (m->pMode == mode) {
wldata->width = m->width;
wldata->height = m->height;
wldata->refreshRate = m->refreshRate;
if (++set == 2) break;
if (++set == 2) {
break;
}
}
if (m->preferred)
{
if (m->preferred) {
wldata->preferredWidth = m->width;
wldata->preferredHeight = m->height;
wldata->preferredRefreshRate = m->refreshRate;
if (++set == 2) break;
if (++set == 2) {
break;
}
}
}
}
static void waylandKdeScaleListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, wl_fixed_t scale)
{
static void waylandKdeScaleListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, wl_fixed_t scale) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
wldata->dpi = (uint32_t) scale * 3 / 8; // wl_fixed_to_double(scale) * 96;
}
static void waylandKdeEdidListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, const char* raw)
{
if (!*raw) return;
static void waylandKdeEdidListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, const char* raw) {
if (!*raw) {
return;
}
WaylandDisplay* wldata = (WaylandDisplay*) data;
FF_STRBUF_AUTO_DESTROY b64 = ffStrbufCreateStatic(raw);
FF_STRBUF_AUTO_DESTROY edid = ffBase64DecodeStrbuf(&b64);
if (edid.length < 128) return;
if (edid.length < 128) {
return;
}
ffEdidGetName((const uint8_t*) edid.chars, &wldata->edidName);
wldata->hdrSupported = ffEdidGetHdrCompatible((const uint8_t*) edid.chars, edid.length);
ffEdidGetSerialAndManufactureDate((const uint8_t*) edid.chars, &wldata->serial, &wldata->myear, &wldata->mweek);
wldata->hdrInfoAvailable = true;
}
static void waylandKdeEnabledListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, int32_t enabled)
{
static void waylandKdeEnabledListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* _, int32_t enabled) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
if (!enabled) wldata->internal = NULL;
if (!enabled) {
wldata->internal = NULL;
}
}
static void waylandKdeGeometryListener(void *data,
FF_MAYBE_UNUSED struct kde_output_device_v2 *kde_output_device_v2,
static void waylandKdeGeometryListener(void* data,
FF_MAYBE_UNUSED struct kde_output_device_v2* kde_output_device_v2,
FF_MAYBE_UNUSED int32_t x,
FF_MAYBE_UNUSED int32_t y,
int32_t physical_width,
int32_t physical_height,
FF_MAYBE_UNUSED int32_t subpixel,
FF_MAYBE_UNUSED const char *make,
FF_MAYBE_UNUSED const char *model,
int32_t transform)
{
FF_MAYBE_UNUSED const char* make,
FF_MAYBE_UNUSED const char* model,
int32_t transform) {
WaylandDisplay* display = data;
display->physicalWidth = physical_width;
display->physicalHeight = physical_height;
display->transform = (enum wl_output_transform) transform;
}
static void waylandKdeNameListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* kde_output_device_v2, const char *name)
{
static void waylandKdeNameListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* kde_output_device_v2, const char* name) {
WaylandDisplay* display = data;
display->type = ffdsGetDisplayType(name);
// As display->id is used as an internal identifier, we don't need it to be NUL terminated
@@ -132,14 +132,12 @@ static void waylandKdeNameListener(void* data, FF_MAYBE_UNUSED struct kde_output
ffStrbufAppendS(&display->name, name);
}
static void waylandKdeHdrListener(void *data, FF_MAYBE_UNUSED struct kde_output_device_v2 *kde_output_device_v2, uint32_t hdr_enabled)
{
static void waylandKdeHdrListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* kde_output_device_v2, uint32_t hdr_enabled) {
WaylandDisplay* display = data;
display->hdrEnabled = !!hdr_enabled;
}
static void waylandKdeMaxBitsPerColorListener(void *data, FF_MAYBE_UNUSED struct kde_output_device_v2 *kde_output_device_v2, uint32_t max_bpc)
{
static void waylandKdeMaxBitsPerColorListener(void* data, FF_MAYBE_UNUSED struct kde_output_device_v2* kde_output_device_v2, uint32_t max_bpc) {
WaylandDisplay* display = data;
display->bitDepth = (uint8_t) max_bpc;
}
@@ -184,11 +182,11 @@ static struct kde_output_device_v2_listener outputListener = {
.removed = (void*) stubListener,
};
const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
{
const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_device_v2_interface, version, name, kde_output_device_v2_interface.name, version, NULL);
if(output == NULL)
if (output == NULL) {
return "Failed to create kde_output_device_v2";
}
FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandKdeMode));
WaylandDisplay display = {
@@ -201,21 +199,20 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re
.internal = &modes,
};
if (wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, &display) < 0)
{
if (wldata->ffwl_proxy_add_listener(output, (void (**)(void)) &outputListener, &display) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to add listener to kde_output_device_v2";
}
if (wldata->ffwl_display_roundtrip(wldata->display) < 0)
{
if (wldata->ffwl_display_roundtrip(wldata->display) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to roundtrip kde_output_device_v2";
}
wldata->ffwl_proxy_destroy(output);
if(display.width <= 0 || display.height <= 0 || !display.internal)
if (display.width <= 0 || display.height <= 0 || !display.internal) {
return "Failed to get display information from kde_output_device_v2";
}
uint32_t rotation = ffWaylandHandleRotation(&display);
@@ -236,18 +233,17 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re
display.id,
(uint32_t) display.physicalWidth,
(uint32_t) display.physicalHeight,
"wayland-kde"
);
if (item)
{
if (display.hdrEnabled)
"wayland-kde");
if (item) {
if (display.hdrEnabled) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_ENABLED;
else if (display.hdrSupported)
} else if (display.hdrSupported) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
else if (display.hdrInfoAvailable)
} else if (display.hdrInfoAvailable) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
else
} else {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
}
item->manufactureYear = display.myear;
item->manufactureWeek = display.mweek;
@@ -262,32 +258,29 @@ const char* ffWaylandHandleKdeOutput(WaylandData* wldata, struct wl_registry* re
return NULL;
}
static void waylandKdeOutputOrderListener(void *data, FF_MAYBE_UNUSED struct kde_output_order_v1 *_, const char *output_name)
{
static void waylandKdeOutputOrderListener(void* data, FF_MAYBE_UNUSED struct kde_output_order_v1* _, const char* output_name) {
uint64_t* id = (uint64_t*) data;
if (*id == 0)
if (*id == 0) {
*id = ffWaylandGenerateIdFromName(output_name);
}
}
const char* ffWaylandHandleKdeOutputOrder(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
{
const char* ffWaylandHandleKdeOutputOrder(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &kde_output_order_v1_interface, version, name, kde_output_order_v1_interface.name, version, NULL);
if(output == NULL)
if (output == NULL) {
return "Failed to create kde_output_order_v1";
}
struct kde_output_order_v1_listener orderListener = {
.output = waylandKdeOutputOrderListener,
.done = (void*) stubListener,
};
if (wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &orderListener, &wldata->primaryDisplayId) < 0)
{
if (wldata->ffwl_proxy_add_listener(output, (void (**)(void)) &orderListener, &wldata->primaryDisplayId) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to add listener to kde_output_order_v1";
}
if (wldata->ffwl_display_roundtrip(wldata->display) < 0)
{
if (wldata->ffwl_display_roundtrip(wldata->display) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to roundtrip kde_output_order_v1";
}
@@ -8,131 +8,127 @@
#ifdef FF_HAVE_WAYLAND
#include <sys/socket.h>
# include <sys/socket.h>
#include "common/properties.h"
# include "common/properties.h"
#include "wayland.h"
#include "wlr-output-management-unstable-v1-client-protocol.h"
#include "kde-output-device-v2-client-protocol.h"
#include "kde-output-order-v1-client-protocol.h"
#include "xdg-output-unstable-v1-client-protocol.h"
# include "wayland.h"
# include "wlr-output-management-unstable-v1-client-protocol.h"
# include "kde-output-device-v2-client-protocol.h"
# include "kde-output-order-v1-client-protocol.h"
# include "xdg-output-unstable-v1-client-protocol.h"
#if __FreeBSD__
#include <sys/un.h>
#include <sys/ucred.h>
#include <sys/sysctl.h>
#endif
# if __FreeBSD__
# include <sys/un.h>
# include <sys/ucred.h>
# include <sys/sysctl.h>
# endif
static bool waylandDetectWM(int fd, FFDisplayServerResult* result)
{
#if __linux__ || __GNU__ || (__FreeBSD__ && !__DragonFly__)
static bool waylandDetectWM(int fd, FFDisplayServerResult* result) {
# if __linux__ || __GNU__ || (__FreeBSD__ && !__DragonFly__)
#if __linux__ || __GNU__
# if __linux__ || __GNU__
struct ucred ucred = {};
socklen_t len = sizeof(ucred);
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1 || ucred.pid <= 0)
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1 || ucred.pid <= 0) {
return false;
}
FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreate();
ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed.
if (!ffReadFileBuffer(procPath.chars, &result->wmProcessName))
ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); // We check the cmdline for the process name, because it is not trimmed.
if (!ffReadFileBuffer(procPath.chars, &result->wmProcessName)) {
return false;
#else
}
# else
struct xucred ucred = {};
socklen_t len = sizeof(ucred);
if (getsockopt(fd, AF_UNSPEC, LOCAL_PEERCRED, &ucred, &len) == -1 || ucred.cr_pid <= 0)
if (getsockopt(fd, AF_UNSPEC, LOCAL_PEERCRED, &ucred, &len) == -1 || ucred.cr_pid <= 0) {
return false;
}
size_t size = 4096;
ffStrbufEnsureFixedLengthFree(&result->wmProcessName, (uint32_t) size);
if(sysctl((int[]){CTL_KERN, KERN_PROC, KERN_PROC_ARGS, ucred.cr_pid}, 4, result->wmProcessName.chars, &size, NULL, 0 ) != 0)
if (sysctl((int[]) {CTL_KERN, KERN_PROC, KERN_PROC_ARGS, ucred.cr_pid}, 4, result->wmProcessName.chars, &size, NULL, 0) != 0) {
return false;
}
result->wmProcessName.length = (uint32_t) size - 1;
#endif
# endif
// #1135: wl-restart is a special case
const char* filename = strrchr(result->wmProcessName.chars, '/');
if (filename)
if (filename) {
filename++;
else
} else {
filename = result->wmProcessName.chars;
}
if (ffStrEquals(filename, "wl-restart"))
if (ffStrEquals(filename, "wl-restart")) {
ffStrbufSubstrAfterLastC(&result->wmProcessName, '\0');
}
ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments
ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path
ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); // Trim the arguments
ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); // Trim the path
return true;
#else
# else
FF_UNUSED(fd, result);
return false;
#endif
# endif
}
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version)
{
static void waylandGlobalAddListener(void* data, struct wl_registry* registry, uint32_t name, const char* interface, uint32_t version) {
WaylandData* wldata = data;
if((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL) && ffStrEquals(interface, wldata->ffwl_output_interface->name))
{
if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL) && ffStrEquals(interface, wldata->ffwl_output_interface->name)) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_GLOBAL;
if (ffWaylandHandleGlobalOutput(wldata, registry, name, version) != NULL)
if (ffWaylandHandleGlobalOutput(wldata, registry, name, version) != NULL) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_NONE;
}
else if((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_ZWLR) && ffStrEquals(interface, zwlr_output_manager_v1_interface.name))
{
}
} else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_ZWLR) && ffStrEquals(interface, zwlr_output_manager_v1_interface.name)) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_ZWLR;
if (ffWaylandHandleZwlrOutput(wldata, registry, name, version) != NULL)
if (ffWaylandHandleZwlrOutput(wldata, registry, name, version) != NULL) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_NONE;
}
else if((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_KDE) && ffStrEquals(interface, kde_output_device_v2_interface.name))
{
}
} else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_KDE) && ffStrEquals(interface, kde_output_device_v2_interface.name)) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_KDE;
if (ffWaylandHandleKdeOutput(wldata, registry, name, version) != NULL)
if (ffWaylandHandleKdeOutput(wldata, registry, name, version) != NULL) {
wldata->protocolType = FF_WAYLAND_PROTOCOL_TYPE_NONE;
}
else if(ffStrEquals(interface, kde_output_order_v1_interface.name))
{
}
} else if (ffStrEquals(interface, kde_output_order_v1_interface.name)) {
ffWaylandHandleKdeOutputOrder(wldata, registry, name, version);
}
else if((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE) && ffStrEquals(interface, zxdg_output_manager_v1_interface.name))
{
} else if ((wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_GLOBAL || wldata->protocolType == FF_WAYLAND_PROTOCOL_TYPE_NONE) && ffStrEquals(interface, zxdg_output_manager_v1_interface.name)) {
ffWaylandHandleZxdgOutput(wldata, registry, name, version);
}
}
static FF_MAYBE_UNUSED bool matchDrmConnector(const char* connName, WaylandDisplay* wldata)
{
static FF_MAYBE_UNUSED bool matchDrmConnector(const char* connName, WaylandDisplay* wldata) {
// https://wayland.freedesktop.org/docs/html/apa.html#protocol-spec-wl_output-event-name
// The doc says that "do not assume that the name is a reflection of an underlying DRM connector, X11 connection, etc."
// However I can't find a better method to get the edid data
const char* drmDirPath = "/sys/class/drm/";
FF_AUTO_CLOSE_DIR DIR* dirp = opendir(drmDirPath);
if(dirp == NULL)
if (dirp == NULL) {
return false;
}
struct dirent* entry;
while((entry = readdir(dirp)) != NULL)
{
while ((entry = readdir(dirp)) != NULL) {
const char* plainName = entry->d_name;
if (ffStrStartsWith(plainName, "card"))
{
if (ffStrStartsWith(plainName, "card")) {
const char* tmp = strchr(plainName + strlen("card"), '-');
if (tmp) plainName = tmp + 1;
if (tmp) {
plainName = tmp + 1;
}
}
if (ffStrEquals(plainName, connName))
{
if (ffStrEquals(plainName, connName)) {
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreateF("%s%s/edid", drmDirPath, entry->d_name);
uint8_t edidData[512];
ssize_t edidLength = ffReadFileData(path.chars, ARRAY_SIZE(edidData), edidData);
if (edidLength > 0 && edidLength % 128 == 0)
{
if (edidLength > 0 && edidLength % 128 == 0) {
ffEdidGetName(edidData, &wldata->edidName);
ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength);
ffEdidGetSerialAndManufactureDate(edidData, &wldata->serial, &wldata->myear, &wldata->mweek);
@@ -145,35 +141,39 @@ static FF_MAYBE_UNUSED bool matchDrmConnector(const char* connName, WaylandDispl
return false;
}
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name)
{
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char* name) {
WaylandDisplay* display = data;
if (display->id) return;
if (display->id) {
return;
}
display->type = ffdsGetDisplayType(name);
#if __linux__
if (!display->edidName.length)
# if __linux__
if (!display->edidName.length) {
matchDrmConnector(name, display);
#endif
}
# endif
display->id = ffWaylandGenerateIdFromName(name);
ffStrbufAppendS(&display->name, name);
}
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description)
{
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description) {
WaylandDisplay* display = data;
if (display->description.length) return;
if (display->description.length) {
return;
}
while (*description == ' ') ++description;
if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)"))
while (*description == ' ') {
++description;
}
if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)")) {
ffStrbufAppendS(&display->description, description);
}
}
uint32_t ffWaylandHandleRotation(WaylandDisplay* display)
{
uint32_t ffWaylandHandleRotation(WaylandDisplay* display) {
uint32_t rotation;
switch(display->transform)
{
switch (display->transform) {
case WL_OUTPUT_TRANSFORM_FLIPPED_90:
case WL_OUTPUT_TRANSFORM_90:
rotation = 90;
@@ -191,8 +191,7 @@ uint32_t ffWaylandHandleRotation(WaylandDisplay* display)
break;
}
switch(rotation)
{
switch (rotation) {
case 90:
case 270: {
int32_t temp = display->width;
@@ -210,10 +209,10 @@ uint32_t ffWaylandHandleRotation(WaylandDisplay* display)
return rotation;
}
const char* ffdsConnectWayland(FFDisplayServerResult* result)
{
if (getenv("XDG_RUNTIME_DIR") == NULL)
const char* ffdsConnectWayland(FFDisplayServerResult* result) {
if (getenv("XDG_RUNTIME_DIR") == NULL) {
return "Wayland requires $XDG_RUNTIME_DIR being set";
}
FF_LIBRARY_LOAD_MESSAGE(wayland, "libwayland-client" FF_LIBRARY_EXTENSION, 1)
@@ -232,14 +231,14 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(wayland, data, wl_output_interface)
data.display = ffwl_display_connect(NULL);
if(data.display == NULL)
if (data.display == NULL) {
return "wl_display_connect returned NULL";
}
waylandDetectWM(ffwl_display_get_fd(data.display), result);
struct wl_proxy* registry = ffwl_proxy_marshal_constructor((struct wl_proxy*) data.display, WL_DISPLAY_GET_REGISTRY, ffwl_registry_interface, NULL);
if(registry == NULL)
{
if (registry == NULL) {
ffwl_display_disconnect(data.display);
return "wl_display_get_registry returned NULL";
}
@@ -248,37 +247,34 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result)
struct wl_registry_listener registry_listener = {
.global = waylandGlobalAddListener,
.global_remove = (void*) stubListener
};
.global_remove = (void*) stubListener};
data.ffwl_proxy_add_listener(registry, (void(**)(void)) &registry_listener, &data);
data.ffwl_proxy_add_listener(registry, (void (**)(void)) &registry_listener, &data);
data.ffwl_display_roundtrip(data.display);
if (data.zxdgOutputManager)
if (data.zxdgOutputManager) {
data.ffwl_proxy_destroy(data.zxdgOutputManager);
}
data.ffwl_proxy_destroy(registry);
ffwl_display_disconnect(data.display);
if(data.primaryDisplayId == 0 && result->wmProcessName.length > 0)
{
if (data.primaryDisplayId == 0 && result->wmProcessName.length > 0) {
const char* fileName = ffStrbufEqualS(&result->wmProcessName, "gnome-shell")
? "monitors.xml"
: ffStrbufEqualS(&result->wmProcessName, "cinnamon")
? "cinnamon-monitors.xml"
: NULL;
if (fileName)
{
? "cinnamon-monitors.xml"
: NULL;
if (fileName) {
FF_STRBUF_AUTO_DESTROY monitorsXml = ffStrbufCreate();
FF_LIST_FOR_EACH(FFstrbuf, basePath, instance.state.platform.configDirs)
{
FF_LIST_FOR_EACH (FFstrbuf, basePath, instance.state.platform.configDirs) {
char path[1024];
snprintf(path, ARRAY_SIZE(path), "%s%s", basePath->chars, fileName);
if (ffReadFileBuffer(path, &monitorsXml))
if (ffReadFileBuffer(path, &monitorsXml)) {
break;
}
}
if (monitorsXml.length)
{
if (monitorsXml.length) {
// <monitors version="2">
// <configuration>
// <logicalmonitor>
@@ -303,14 +299,11 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result)
// </configuration>
// </monitors>
uint32_t start = ffStrbufFirstIndexS(&monitorsXml, "<primary>yes</primary>");
if (start < monitorsXml.length)
{
if (start < monitorsXml.length) {
start = ffStrbufNextIndexS(&monitorsXml, start, "<connector>");
if (start < monitorsXml.length)
{
if (start < monitorsXml.length) {
uint32_t end = ffStrbufNextIndexS(&monitorsXml, start, "</connector>");
if (end < monitorsXml.length)
{
if (end < monitorsXml.length) {
ffStrbufSubstrBefore(&monitorsXml, end);
const char* name = monitorsXml.chars + start + strlen("<connector>");
data.primaryDisplayId = ffWaylandGenerateIdFromName(name);
@@ -321,29 +314,25 @@ const char* ffdsConnectWayland(FFDisplayServerResult* result)
}
}
if(data.primaryDisplayId)
{
FF_LIST_FOR_EACH(FFDisplayResult, d, data.result->displays)
{
if(d->id == data.primaryDisplayId)
{
if (data.primaryDisplayId) {
FF_LIST_FOR_EACH (FFDisplayResult, d, data.result->displays) {
if (d->id == data.primaryDisplayId) {
d->primary = true;
break;
}
}
}
//We successfully connected to wayland and detected the display.
//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.
// We successfully connected to wayland and detected the display.
// 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.
ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
return NULL;
}
#else
const char* ffdsConnectWayland(FF_MAYBE_UNUSED FFDisplayServerResult* result)
{
const char* ffdsConnectWayland(FF_MAYBE_UNUSED FFDisplayServerResult* result) {
return "Fastfetch was compiled without Wayland support";
}
@@ -2,23 +2,21 @@
#ifdef FF_HAVE_WAYLAND
#include "common/library.h"
#include "common/stringUtils.h"
# include "common/library.h"
# include "common/stringUtils.h"
#include <wayland-client.h>
# include <wayland-client.h>
#include "../displayserver_linux.h"
# include "../displayserver_linux.h"
typedef enum __attribute__((__packed__)) WaylandProtocolType
{
typedef enum __attribute__((__packed__)) WaylandProtocolType {
FF_WAYLAND_PROTOCOL_TYPE_NONE,
FF_WAYLAND_PROTOCOL_TYPE_GLOBAL,
FF_WAYLAND_PROTOCOL_TYPE_ZWLR,
FF_WAYLAND_PROTOCOL_TYPE_KDE,
} WaylandProtocolType;
typedef struct WaylandData
{
typedef struct WaylandData {
FFDisplayServerResult* result;
FF_LIBRARY_SYMBOL(wl_proxy_marshal_constructor_versioned)
FF_LIBRARY_SYMBOL(wl_proxy_add_listener)
@@ -31,8 +29,7 @@ typedef struct WaylandData
struct wl_proxy* zxdgOutputManager;
} WaylandData;
typedef struct WaylandDisplay
{
typedef struct WaylandDisplay {
WaylandData* parent;
void* internal;
int32_t width;
@@ -59,23 +56,22 @@ typedef struct WaylandDisplay
uint8_t bitDepth;
} WaylandDisplay;
inline static void stubListener(void* data, ...)
{
inline static void stubListener(void* data, ...) {
(void) data;
}
inline static uint64_t ffWaylandGenerateIdFromName(const char* name)
{
inline static uint64_t ffWaylandGenerateIdFromName(const char* name) {
uint64_t id = 0;
size_t len = strlen(name);
if (len > sizeof(id))
if (len > sizeof(id)) {
memcpy(&id, name + (len - sizeof(id)), sizeof(id)); // copy the last 8 bytes
else if (len > 0)
} else if (len > 0) {
memcpy(&id, name, len);
}
return id;
}
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name);
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char* name);
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description);
// Modifies content of display. Don't call this function when calling ffdsAppendDisplay
uint32_t ffWaylandHandleRotation(WaylandDisplay* display);
@@ -27,135 +27,150 @@
* THIS SOFTWARE.
*/
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <wayland-util.h>
# include <stdbool.h>
# include <stdlib.h>
# include <stdint.h>
# include <wayland-util.h>
#ifndef __has_attribute
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
#endif
# ifndef __has_attribute
# define __has_attribute(x) 0 /* Compatibility with non-clang compilers. */
# endif
#if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
#define WL_PRIVATE __attribute__ ((visibility("hidden")))
#else
#define WL_PRIVATE
#endif
# if (__has_attribute(visibility) || defined(__GNUC__) && __GNUC__ >= 4)
# define WL_PRIVATE __attribute__((visibility("hidden")))
# else
# define WL_PRIVATE
# endif
extern const struct wl_interface zwlr_output_configuration_head_v1_interface;
extern const struct wl_interface zwlr_output_configuration_v1_interface;
extern const struct wl_interface zwlr_output_head_v1_interface;
extern const struct wl_interface zwlr_output_mode_v1_interface;
static const struct wl_interface *wlr_output_management_unstable_v1_types[] = {
NULL,
NULL,
NULL,
&zwlr_output_configuration_v1_interface,
NULL,
&zwlr_output_head_v1_interface,
&zwlr_output_mode_v1_interface,
&zwlr_output_mode_v1_interface,
&zwlr_output_configuration_head_v1_interface,
&zwlr_output_head_v1_interface,
&zwlr_output_head_v1_interface,
&zwlr_output_mode_v1_interface,
static const struct wl_interface* wlr_output_management_unstable_v1_types[] = {
NULL,
NULL,
NULL,
&zwlr_output_configuration_v1_interface,
NULL,
&zwlr_output_head_v1_interface,
&zwlr_output_mode_v1_interface,
&zwlr_output_mode_v1_interface,
&zwlr_output_configuration_head_v1_interface,
&zwlr_output_head_v1_interface,
&zwlr_output_head_v1_interface,
&zwlr_output_mode_v1_interface,
};
static const struct wl_message zwlr_output_manager_v1_requests[] = {
{ "create_configuration", "nu", wlr_output_management_unstable_v1_types + 3 },
{ "stop", "", wlr_output_management_unstable_v1_types + 0 },
{"create_configuration", "nu", wlr_output_management_unstable_v1_types + 3},
{"stop", "", wlr_output_management_unstable_v1_types + 0},
};
static const struct wl_message zwlr_output_manager_v1_events[] = {
{ "head", "n", wlr_output_management_unstable_v1_types + 5 },
{ "done", "u", wlr_output_management_unstable_v1_types + 0 },
{ "finished", "", wlr_output_management_unstable_v1_types + 0 },
{"head", "n", wlr_output_management_unstable_v1_types + 5},
{"done", "u", wlr_output_management_unstable_v1_types + 0},
{"finished", "", wlr_output_management_unstable_v1_types + 0},
};
WL_PRIVATE const struct wl_interface zwlr_output_manager_v1_interface = {
"zwlr_output_manager_v1", 4,
2, zwlr_output_manager_v1_requests,
3, zwlr_output_manager_v1_events,
"zwlr_output_manager_v1",
4,
2,
zwlr_output_manager_v1_requests,
3,
zwlr_output_manager_v1_events,
};
static const struct wl_message zwlr_output_head_v1_requests[] = {
{ "release", "3", wlr_output_management_unstable_v1_types + 0 },
{"release", "3", wlr_output_management_unstable_v1_types + 0},
};
static const struct wl_message zwlr_output_head_v1_events[] = {
{ "name", "s", wlr_output_management_unstable_v1_types + 0 },
{ "description", "s", wlr_output_management_unstable_v1_types + 0 },
{ "physical_size", "ii", wlr_output_management_unstable_v1_types + 0 },
{ "mode", "n", wlr_output_management_unstable_v1_types + 6 },
{ "enabled", "i", wlr_output_management_unstable_v1_types + 0 },
{ "current_mode", "o", wlr_output_management_unstable_v1_types + 7 },
{ "position", "ii", wlr_output_management_unstable_v1_types + 0 },
{ "transform", "i", wlr_output_management_unstable_v1_types + 0 },
{ "scale", "f", wlr_output_management_unstable_v1_types + 0 },
{ "finished", "", wlr_output_management_unstable_v1_types + 0 },
{ "make", "2s", wlr_output_management_unstable_v1_types + 0 },
{ "model", "2s", wlr_output_management_unstable_v1_types + 0 },
{ "serial_number", "2s", wlr_output_management_unstable_v1_types + 0 },
{ "adaptive_sync", "4u", wlr_output_management_unstable_v1_types + 0 },
{"name", "s", wlr_output_management_unstable_v1_types + 0},
{"description", "s", wlr_output_management_unstable_v1_types + 0},
{"physical_size", "ii", wlr_output_management_unstable_v1_types + 0},
{"mode", "n", wlr_output_management_unstable_v1_types + 6},
{"enabled", "i", wlr_output_management_unstable_v1_types + 0},
{"current_mode", "o", wlr_output_management_unstable_v1_types + 7},
{"position", "ii", wlr_output_management_unstable_v1_types + 0},
{"transform", "i", wlr_output_management_unstable_v1_types + 0},
{"scale", "f", wlr_output_management_unstable_v1_types + 0},
{"finished", "", wlr_output_management_unstable_v1_types + 0},
{"make", "2s", wlr_output_management_unstable_v1_types + 0},
{"model", "2s", wlr_output_management_unstable_v1_types + 0},
{"serial_number", "2s", wlr_output_management_unstable_v1_types + 0},
{"adaptive_sync", "4u", wlr_output_management_unstable_v1_types + 0},
};
WL_PRIVATE const struct wl_interface zwlr_output_head_v1_interface = {
"zwlr_output_head_v1", 4,
1, zwlr_output_head_v1_requests,
14, zwlr_output_head_v1_events,
"zwlr_output_head_v1",
4,
1,
zwlr_output_head_v1_requests,
14,
zwlr_output_head_v1_events,
};
static const struct wl_message zwlr_output_mode_v1_requests[] = {
{ "release", "3", wlr_output_management_unstable_v1_types + 0 },
{"release", "3", wlr_output_management_unstable_v1_types + 0},
};
static const struct wl_message zwlr_output_mode_v1_events[] = {
{ "size", "ii", wlr_output_management_unstable_v1_types + 0 },
{ "refresh", "i", wlr_output_management_unstable_v1_types + 0 },
{ "preferred", "", wlr_output_management_unstable_v1_types + 0 },
{ "finished", "", wlr_output_management_unstable_v1_types + 0 },
{"size", "ii", wlr_output_management_unstable_v1_types + 0},
{"refresh", "i", wlr_output_management_unstable_v1_types + 0},
{"preferred", "", wlr_output_management_unstable_v1_types + 0},
{"finished", "", wlr_output_management_unstable_v1_types + 0},
};
WL_PRIVATE const struct wl_interface zwlr_output_mode_v1_interface = {
"zwlr_output_mode_v1", 3,
1, zwlr_output_mode_v1_requests,
4, zwlr_output_mode_v1_events,
"zwlr_output_mode_v1",
3,
1,
zwlr_output_mode_v1_requests,
4,
zwlr_output_mode_v1_events,
};
static const struct wl_message zwlr_output_configuration_v1_requests[] = {
{ "enable_head", "no", wlr_output_management_unstable_v1_types + 8 },
{ "disable_head", "o", wlr_output_management_unstable_v1_types + 10 },
{ "apply", "", wlr_output_management_unstable_v1_types + 0 },
{ "test", "", wlr_output_management_unstable_v1_types + 0 },
{ "destroy", "", wlr_output_management_unstable_v1_types + 0 },
{"enable_head", "no", wlr_output_management_unstable_v1_types + 8},
{"disable_head", "o", wlr_output_management_unstable_v1_types + 10},
{"apply", "", wlr_output_management_unstable_v1_types + 0},
{"test", "", wlr_output_management_unstable_v1_types + 0},
{"destroy", "", wlr_output_management_unstable_v1_types + 0},
};
static const struct wl_message zwlr_output_configuration_v1_events[] = {
{ "succeeded", "", wlr_output_management_unstable_v1_types + 0 },
{ "failed", "", wlr_output_management_unstable_v1_types + 0 },
{ "cancelled", "", wlr_output_management_unstable_v1_types + 0 },
{"succeeded", "", wlr_output_management_unstable_v1_types + 0},
{"failed", "", wlr_output_management_unstable_v1_types + 0},
{"cancelled", "", wlr_output_management_unstable_v1_types + 0},
};
WL_PRIVATE const struct wl_interface zwlr_output_configuration_v1_interface = {
"zwlr_output_configuration_v1", 4,
5, zwlr_output_configuration_v1_requests,
3, zwlr_output_configuration_v1_events,
"zwlr_output_configuration_v1",
4,
5,
zwlr_output_configuration_v1_requests,
3,
zwlr_output_configuration_v1_events,
};
static const struct wl_message zwlr_output_configuration_head_v1_requests[] = {
{ "set_mode", "o", wlr_output_management_unstable_v1_types + 11 },
{ "set_custom_mode", "iii", wlr_output_management_unstable_v1_types + 0 },
{ "set_position", "ii", wlr_output_management_unstable_v1_types + 0 },
{ "set_transform", "i", wlr_output_management_unstable_v1_types + 0 },
{ "set_scale", "f", wlr_output_management_unstable_v1_types + 0 },
{ "set_adaptive_sync", "4u", wlr_output_management_unstable_v1_types + 0 },
{"set_mode", "o", wlr_output_management_unstable_v1_types + 11},
{"set_custom_mode", "iii", wlr_output_management_unstable_v1_types + 0},
{"set_position", "ii", wlr_output_management_unstable_v1_types + 0},
{"set_transform", "i", wlr_output_management_unstable_v1_types + 0},
{"set_scale", "f", wlr_output_management_unstable_v1_types + 0},
{"set_adaptive_sync", "4u", wlr_output_management_unstable_v1_types + 0},
};
WL_PRIVATE const struct wl_interface zwlr_output_configuration_head_v1_interface = {
"zwlr_output_configuration_head_v1", 4,
6, zwlr_output_configuration_head_v1_requests,
0, NULL,
"zwlr_output_configuration_head_v1",
4,
6,
zwlr_output_configuration_head_v1_requests,
0,
NULL,
};
#endif
@@ -7,7 +7,7 @@
#include <stddef.h>
#include <wayland-client.h>
#ifdef __cplusplus
#ifdef __cplusplus
extern "C" {
#endif
@@ -78,7 +78,7 @@ struct zxdg_output_manager_v1;
struct zxdg_output_v1;
#ifndef ZXDG_OUTPUT_MANAGER_V1_INTERFACE
#define ZXDG_OUTPUT_MANAGER_V1_INTERFACE
# define ZXDG_OUTPUT_MANAGER_V1_INTERFACE
/**
* @page page_iface_zxdg_output_manager_v1 zxdg_output_manager_v1
* @section page_iface_zxdg_output_manager_v1_desc Description
@@ -95,7 +95,7 @@ struct zxdg_output_v1;
extern const struct wl_interface zxdg_output_manager_v1_interface;
#endif
#ifndef ZXDG_OUTPUT_V1_INTERFACE
#define ZXDG_OUTPUT_V1_INTERFACE
# define ZXDG_OUTPUT_V1_INTERFACE
/**
* @page page_iface_zxdg_output_v1 zxdg_output_v1
* @section page_iface_zxdg_output_v1_desc Description
@@ -131,7 +131,6 @@ extern const struct wl_interface zxdg_output_v1_interface;
#define ZXDG_OUTPUT_MANAGER_V1_DESTROY 0
#define ZXDG_OUTPUT_MANAGER_V1_GET_XDG_OUTPUT 1
/**
* @ingroup iface_zxdg_output_manager_v1
*/
@@ -197,153 +196,154 @@ extern const struct wl_interface zxdg_output_v1_interface;
* @struct zxdg_output_v1_listener
*/
struct zxdg_output_v1_listener {
/**
* position of the output within the global compositor space
*
* The position event describes the location of the wl_output
* within the global compositor space.
*
* The logical_position event is sent after creating an xdg_output
* (see xdg_output_manager.get_xdg_output) and whenever the
* location of the output changes within the global compositor
* space.
* @param x x position within the global compositor space
* @param y y position within the global compositor space
*/
void (*logical_position)(void *data,
struct zxdg_output_v1 *zxdg_output_v1,
int32_t x,
int32_t y);
/**
* size of the output in the global compositor space
*
* The logical_size event describes the size of the output in the
* global compositor space.
*
* Most regular Wayland clients should not pay attention to the
* logical size and would rather rely on xdg_shell interfaces.
*
* Some clients such as Xwayland, however, need this to configure
* their surfaces in the global compositor space as the compositor
* may apply a different scale from what is advertised by the
* output scaling property (to achieve fractional scaling, for
* example).
*
* For example, for a wl_output mode 3840×2160 and a scale factor
* 2:
*
* - A compositor not scaling the monitor viewport in its
* compositing space will advertise a logical size of 3840×2160,
*
* - A compositor scaling the monitor viewport with scale factor 2
* will advertise a logical size of 1920×1080,
*
* - A compositor scaling the monitor viewport using a fractional
* scale of 1.5 will advertise a logical size of 2560×1440.
*
* For example, for a wl_output mode 1920×1080 and a 90 degree
* rotation, the compositor will advertise a logical size of
* 1080x1920.
*
* The logical_size event is sent after creating an xdg_output (see
* xdg_output_manager.get_xdg_output) and whenever the logical size
* of the output changes, either as a result of a change in the
* applied scale or because of a change in the corresponding output
* mode(see wl_output.mode) or transform (see wl_output.transform).
* @param width width in global compositor space
* @param height height in global compositor space
*/
void (*logical_size)(void *data,
struct zxdg_output_v1 *zxdg_output_v1,
int32_t width,
int32_t height);
/**
* all information about the output have been sent
*
* This event is sent after all other properties of an xdg_output
* have been sent.
*
* This allows changes to the xdg_output properties to be seen as
* atomic, even if they happen via multiple events.
*
* For objects version 3 onwards, this event is deprecated.
* Compositors are not required to send it anymore and must send
* wl_output.done instead.
*/
void (*done)(void *data,
struct zxdg_output_v1 *zxdg_output_v1);
/**
* name of this output
*
* Many compositors will assign names to their outputs, show them
* to the user, allow them to be configured by name, etc. The
* client may wish to know this name as well to offer the user
* similar behaviors.
*
* The naming convention is compositor defined, but limited to
* alphanumeric characters and dashes (-). Each name is unique
* among all wl_output globals, but if a wl_output global is
* destroyed the same name may be reused later. The names will also
* remain consistent across sessions with the same hardware and
* software configuration.
*
* Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc.
* However, do not assume that the name is a reflection of an
* underlying DRM connector, X11 connection, etc.
*
* The name event is sent after creating an xdg_output (see
* xdg_output_manager.get_xdg_output). This event is only sent once
* per xdg_output, and the name does not change over the lifetime
* of the wl_output global.
*
* This event is deprecated, instead clients should use
* wl_output.name. Compositors must still support this event.
* @param name output name
* @since 2
*/
void (*name)(void *data,
struct zxdg_output_v1 *zxdg_output_v1,
const char *name);
/**
* human-readable description of this output
*
* Many compositors can produce human-readable descriptions of
* their outputs. The client may wish to know this description as
* well, to communicate the user for various purposes.
*
* The description is a UTF-8 string with no convention defined for
* its contents. Examples might include 'Foocorp 11" Display' or
* 'Virtual X11 output via :1'.
*
* The description event is sent after creating an xdg_output (see
* xdg_output_manager.get_xdg_output) and whenever the description
* changes. The description is optional, and may not be sent at
* all.
*
* For objects of version 2 and lower, this event is only sent once
* per xdg_output, and the description does not change over the
* lifetime of the wl_output global.
*
* This event is deprecated, instead clients should use
* wl_output.description. Compositors must still support this
* event.
* @param description output description
* @since 2
*/
void (*description)(void *data,
struct zxdg_output_v1 *zxdg_output_v1,
const char *description);
/**
* position of the output within the global compositor space
*
* The position event describes the location of the wl_output
* within the global compositor space.
*
* The logical_position event is sent after creating an xdg_output
* (see xdg_output_manager.get_xdg_output) and whenever the
* location of the output changes within the global compositor
* space.
* @param x x position within the global compositor space
* @param y y position within the global compositor space
*/
void (*logical_position)(void* data,
struct zxdg_output_v1* zxdg_output_v1,
int32_t x,
int32_t y);
/**
* size of the output in the global compositor space
*
* The logical_size event describes the size of the output in the
* global compositor space.
*
* Most regular Wayland clients should not pay attention to the
* logical size and would rather rely on xdg_shell interfaces.
*
* Some clients such as Xwayland, however, need this to configure
* their surfaces in the global compositor space as the compositor
* may apply a different scale from what is advertised by the
* output scaling property (to achieve fractional scaling, for
* example).
*
* For example, for a wl_output mode 3840×2160 and a scale factor
* 2:
*
* - A compositor not scaling the monitor viewport in its
* compositing space will advertise a logical size of 3840×2160,
*
* - A compositor scaling the monitor viewport with scale factor 2
* will advertise a logical size of 1920×1080,
*
* - A compositor scaling the monitor viewport using a fractional
* scale of 1.5 will advertise a logical size of 2560×1440.
*
* For example, for a wl_output mode 1920×1080 and a 90 degree
* rotation, the compositor will advertise a logical size of
* 1080x1920.
*
* The logical_size event is sent after creating an xdg_output (see
* xdg_output_manager.get_xdg_output) and whenever the logical size
* of the output changes, either as a result of a change in the
* applied scale or because of a change in the corresponding output
* mode(see wl_output.mode) or transform (see wl_output.transform).
* @param width width in global compositor space
* @param height height in global compositor space
*/
void (*logical_size)(void* data,
struct zxdg_output_v1* zxdg_output_v1,
int32_t width,
int32_t height);
/**
* all information about the output have been sent
*
* This event is sent after all other properties of an xdg_output
* have been sent.
*
* This allows changes to the xdg_output properties to be seen as
* atomic, even if they happen via multiple events.
*
* For objects version 3 onwards, this event is deprecated.
* Compositors are not required to send it anymore and must send
* wl_output.done instead.
*/
void (*done)(void* data,
struct zxdg_output_v1* zxdg_output_v1);
/**
* name of this output
*
* Many compositors will assign names to their outputs, show them
* to the user, allow them to be configured by name, etc. The
* client may wish to know this name as well to offer the user
* similar behaviors.
*
* The naming convention is compositor defined, but limited to
* alphanumeric characters and dashes (-). Each name is unique
* among all wl_output globals, but if a wl_output global is
* destroyed the same name may be reused later. The names will also
* remain consistent across sessions with the same hardware and
* software configuration.
*
* Examples of names include 'HDMI-A-1', 'WL-1', 'X11-1', etc.
* However, do not assume that the name is a reflection of an
* underlying DRM connector, X11 connection, etc.
*
* The name event is sent after creating an xdg_output (see
* xdg_output_manager.get_xdg_output). This event is only sent once
* per xdg_output, and the name does not change over the lifetime
* of the wl_output global.
*
* This event is deprecated, instead clients should use
* wl_output.name. Compositors must still support this event.
* @param name output name
* @since 2
*/
void (*name)(void* data,
struct zxdg_output_v1* zxdg_output_v1,
const char* name);
/**
* human-readable description of this output
*
* Many compositors can produce human-readable descriptions of
* their outputs. The client may wish to know this description as
* well, to communicate the user for various purposes.
*
* The description is a UTF-8 string with no convention defined for
* its contents. Examples might include 'Foocorp 11" Display' or
* 'Virtual X11 output via :1'.
*
* The description event is sent after creating an xdg_output (see
* xdg_output_manager.get_xdg_output) and whenever the description
* changes. The description is optional, and may not be sent at
* all.
*
* For objects of version 2 and lower, this event is only sent once
* per xdg_output, and the description does not change over the
* lifetime of the wl_output global.
*
* This event is deprecated, instead clients should use
* wl_output.description. Compositors must still support this
* event.
* @param description output description
* @since 2
*/
void (*description)(void* data,
struct zxdg_output_v1* zxdg_output_v1,
const char* description);
};
/**
* @ingroup iface_zxdg_output_v1
*/
static inline int
zxdg_output_v1_add_listener(struct zxdg_output_v1 *zxdg_output_v1,
const struct zxdg_output_v1_listener *listener, void *data)
{
return wl_proxy_add_listener((struct wl_proxy *) zxdg_output_v1,
(void (**)(void)) listener, data);
zxdg_output_v1_add_listener(struct zxdg_output_v1* zxdg_output_v1,
const struct zxdg_output_v1_listener* listener,
void* data) {
return wl_proxy_add_listener((struct wl_proxy*) zxdg_output_v1,
(void (**)(void)) listener,
data);
}
#define ZXDG_OUTPUT_V1_DESTROY 0
@@ -407,7 +407,7 @@ zxdg_output_v1_add_listener(struct zxdg_output_v1 *zxdg_output_v1,
// ZXDG_OUTPUT_V1_DESTROY, NULL, wl_proxy_get_version((struct wl_proxy *) zxdg_output_v1), WL_MARSHAL_FLAG_DESTROY);
// }
#ifdef __cplusplus
#ifdef __cplusplus
}
#endif
@@ -24,47 +24,53 @@
* DEALINGS IN THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdint.h>
#include <wayland-util.h>
# include <stdlib.h>
# include <stdint.h>
# include <wayland-util.h>
extern const struct wl_interface wl_output_interface;
extern const struct wl_interface zxdg_output_v1_interface;
static const struct wl_interface *xdg_output_unstable_v1_types[] = {
NULL,
NULL,
&zxdg_output_v1_interface,
NULL, // &wl_output_interface,
static const struct wl_interface* xdg_output_unstable_v1_types[] = {
NULL,
NULL,
&zxdg_output_v1_interface,
NULL, // &wl_output_interface,
};
static const struct wl_message zxdg_output_manager_v1_requests[] = {
{ "destroy", "", xdg_output_unstable_v1_types + 0 },
{ "get_xdg_output", "no", xdg_output_unstable_v1_types + 2 },
{"destroy", "", xdg_output_unstable_v1_types + 0},
{"get_xdg_output", "no", xdg_output_unstable_v1_types + 2},
};
WL_EXPORT const struct wl_interface zxdg_output_manager_v1_interface = {
"zxdg_output_manager_v1", 3,
2, zxdg_output_manager_v1_requests,
0, NULL,
"zxdg_output_manager_v1",
3,
2,
zxdg_output_manager_v1_requests,
0,
NULL,
};
static const struct wl_message zxdg_output_v1_requests[] = {
{ "destroy", "", xdg_output_unstable_v1_types + 0 },
{"destroy", "", xdg_output_unstable_v1_types + 0},
};
static const struct wl_message zxdg_output_v1_events[] = {
{ "logical_position", "ii", xdg_output_unstable_v1_types + 0 },
{ "logical_size", "ii", xdg_output_unstable_v1_types + 0 },
{ "done", "", xdg_output_unstable_v1_types + 0 },
{ "name", "2s", xdg_output_unstable_v1_types + 0 },
{ "description", "2s", xdg_output_unstable_v1_types + 0 },
{"logical_position", "ii", xdg_output_unstable_v1_types + 0},
{"logical_size", "ii", xdg_output_unstable_v1_types + 0},
{"done", "", xdg_output_unstable_v1_types + 0},
{"name", "2s", xdg_output_unstable_v1_types + 0},
{"description", "2s", xdg_output_unstable_v1_types + 0},
};
WL_EXPORT const struct wl_interface zxdg_output_v1_interface = {
"zxdg_output_v1", 3,
1, zxdg_output_v1_requests,
5, zxdg_output_v1_events,
"zxdg_output_v1",
3,
1,
zxdg_output_v1_requests,
5,
zxdg_output_v1_events,
};
#endif
@@ -1,22 +1,19 @@
#ifdef FF_HAVE_WAYLAND
#include "wayland.h"
#include "wlr-output-management-unstable-v1-client-protocol.h"
# include "wayland.h"
# include "wlr-output-management-unstable-v1-client-protocol.h"
static void waylandZwlrTransformListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, int32_t transform)
{
static void waylandZwlrTransformListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, int32_t transform) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
wldata->transform = (enum wl_output_transform) transform;
}
static void waylandZwlrScaleListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, wl_fixed_t scale)
{
static void waylandZwlrScaleListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, wl_fixed_t scale) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
wldata->dpi = (uint32_t) scale * 3 / 8; // wl_fixed_to_double(scale) * 96;
}
typedef struct WaylandZwlrMode
{
typedef struct WaylandZwlrMode {
int32_t width;
int32_t height;
int32_t refreshRate;
@@ -24,21 +21,18 @@ typedef struct WaylandZwlrMode
struct zwlr_output_mode_v1* pMode;
} WaylandZwlrMode;
static void waylandZwlrModeSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t width, int32_t height)
{
static void waylandZwlrModeSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1* zwlr_output_mode_v1, int32_t width, int32_t height) {
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
mode->width = width;
mode->height = height;
}
static void waylandZwlrModeRefreshListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1, int32_t rate)
{
static void waylandZwlrModeRefreshListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1* zwlr_output_mode_v1, int32_t rate) {
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
mode->refreshRate = rate;
}
static void waylandZwlrModePreferredListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1 *zwlr_output_mode_v1)
{
static void waylandZwlrModePreferredListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_mode_v1* zwlr_output_mode_v1) {
WaylandZwlrMode* mode = (WaylandZwlrMode*) data;
mode->preferred = true;
}
@@ -50,55 +44,58 @@ static const struct zwlr_output_mode_v1_listener modeListener = {
.finished = (void*) stubListener,
};
static void waylandZwlrModeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, struct zwlr_output_mode_v1 *mode)
{
static void waylandZwlrModeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, struct zwlr_output_mode_v1* mode) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
if (!wldata->internal) return;
if (!wldata->internal) {
return;
}
WaylandZwlrMode* newMode = ffListAdd((FFlist*) wldata->internal);
*newMode = (WaylandZwlrMode) { .pMode = mode };
*newMode = (WaylandZwlrMode) {.pMode = mode};
// Strangely, the listener is called only in this function, but not in `waylandZwlrCurrentModeListener`
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy *) mode, (void (**)(void)) &modeListener, newMode);
wldata->parent->ffwl_proxy_add_listener((struct wl_proxy*) mode, (void (**)(void)) &modeListener, newMode);
}
static void waylandZwlrCurrentModeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, struct zwlr_output_mode_v1 *mode)
{
static void waylandZwlrCurrentModeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, struct zwlr_output_mode_v1* mode) {
// waylandZwlrModeListener is always run before this
WaylandDisplay* wldata = (WaylandDisplay*) data;
if (!wldata->internal) return;
if (!wldata->internal) {
return;
}
int set = 0;
FF_LIST_FOR_EACH(WaylandZwlrMode, m, *(FFlist*) wldata->internal)
{
if (m->pMode == mode)
{
FF_LIST_FOR_EACH (WaylandZwlrMode, m, *(FFlist*) wldata->internal) {
if (m->pMode == mode) {
wldata->width = m->width;
wldata->height = m->height;
wldata->refreshRate = m->refreshRate;
if (++set == 2) break;
if (++set == 2) {
break;
}
}
if (m->preferred)
{
if (m->preferred) {
wldata->preferredWidth = m->width;
wldata->preferredHeight = m->height;
wldata->preferredRefreshRate = m->refreshRate;
if (++set == 2) break;
if (++set == 2) {
break;
}
}
}
}
static void waylandZwlrPhysicalSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, int32_t width, int32_t height)
{
static void waylandZwlrPhysicalSizeListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, int32_t width, int32_t height) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
wldata->physicalWidth = width;
wldata->physicalHeight = height;
}
static void waylandZwlrEnabledListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1 *zwlr_output_head_v1, bool enabled)
{
static void waylandZwlrEnabledListener(void* data, FF_MAYBE_UNUSED struct zwlr_output_head_v1* zwlr_output_head_v1, bool enabled) {
WaylandDisplay* wldata = (WaylandDisplay*) data;
if (!enabled) wldata->internal = NULL;
if (!enabled) {
wldata->internal = NULL;
}
}
static const struct zwlr_output_head_v1_listener headListener = {
@@ -118,8 +115,7 @@ static const struct zwlr_output_head_v1_listener headListener = {
.adaptive_sync = (void*) stubListener,
};
static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output_manager_v1 *zwlr_output_manager_v1, struct zwlr_output_head_v1 *head)
{
static void waylandHandleZwlrHead(void* data, FF_MAYBE_UNUSED struct zwlr_output_manager_v1* zwlr_output_manager_v1, struct zwlr_output_head_v1* head) {
WaylandData* wldata = data;
FF_LIST_AUTO_DESTROY modes = ffListCreate(sizeof(WaylandZwlrMode));
@@ -133,11 +129,12 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
.internal = &modes,
};
wldata->ffwl_proxy_add_listener((struct wl_proxy*) head, (void(**)(void)) &headListener, &display);
wldata->ffwl_proxy_add_listener((struct wl_proxy*) head, (void (**)(void)) &headListener, &display);
wldata->ffwl_display_roundtrip(wldata->display);
if(display.width <= 0 || display.height <= 0 || !display.internal)
if (display.width <= 0 || display.height <= 0 || !display.internal) {
return;
}
uint32_t rotation = ffWaylandHandleRotation(&display);
@@ -153,23 +150,22 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
display.edidName.length
? &display.edidName
: display.description.length && !ffStrbufContain(&display.description, &display.name)
? &display.description
: &display.name,
? &display.description
: &display.name,
display.type,
false,
display.id,
(uint32_t) display.physicalWidth,
(uint32_t) display.physicalHeight,
"wayland-zwlr"
);
if (item)
{
if (display.hdrSupported)
"wayland-zwlr");
if (item) {
if (display.hdrSupported) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_SUPPORTED;
else if (display.hdrInfoAvailable)
} else if (display.hdrInfoAvailable) {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
else
} else {
item->hdrStatus = FF_DISPLAY_HDR_STATUS_UNKNOWN;
}
item->manufactureYear = display.myear;
item->manufactureWeek = display.mweek;
@@ -181,16 +177,17 @@ static void waylandHandleZwlrHead(void *data, FF_MAYBE_UNUSED struct zwlr_output
ffStrbufDestroy(&display.edidName);
// These must be released manually
FF_LIST_FOR_EACH(WaylandZwlrMode, m, modes)
FF_LIST_FOR_EACH (WaylandZwlrMode, m, modes) {
wldata->ffwl_proxy_destroy((void*) m->pMode);
}
wldata->ffwl_proxy_destroy((void*) head);
}
const char* ffWaylandHandleZwlrOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)
{
const char* ffWaylandHandleZwlrOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version) {
struct wl_proxy* output = wldata->ffwl_proxy_marshal_constructor_versioned((struct wl_proxy*) registry, WL_REGISTRY_BIND, &zwlr_output_manager_v1_interface, version, name, zwlr_output_manager_v1_interface.name, version, NULL);
if(output == NULL)
if (output == NULL) {
return "Failed to bind zwlr_output_manager_v1";
}
const struct zwlr_output_manager_v1_listener outputListener = {
.head = waylandHandleZwlrHead,
@@ -198,13 +195,11 @@ const char* ffWaylandHandleZwlrOutput(WaylandData* wldata, struct wl_registry* r
.finished = (void*) stubListener,
};
if (wldata->ffwl_proxy_add_listener(output, (void(**)(void)) &outputListener, wldata) < 0)
{
if (wldata->ffwl_proxy_add_listener(output, (void (**)(void)) &outputListener, wldata) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to add listener to zwlr_output_manager_v1";
}
if (wldata->ffwl_display_roundtrip(wldata->display) < 0)
{
if (wldata->ffwl_display_roundtrip(wldata->display) < 0) {
wldata->ffwl_proxy_destroy(output);
return "Failed to roundtrip display";
}
+205 -191
View File
@@ -9,319 +9,326 @@
#include <unistd.h>
#if __FreeBSD__
#include <sys/sysctl.h>
#include <sys/types.h>
#include <sys/user.h>
# include <sys/sysctl.h>
# include <sys/types.h>
# include <sys/user.h>
#elif __OpenBSD__
#include <sys/param.h>
#include <sys/sysctl.h>
#include <kvm.h>
# include <sys/param.h>
# include <sys/sysctl.h>
# include <kvm.h>
#elif __sun
#include <procfs.h>
# include <procfs.h>
#elif __NetBSD__
#include <sys/types.h>
#include <sys/sysctl.h>
# include <sys/types.h>
# include <sys/sysctl.h>
#endif
static const char* parseEnv(void)
{
static const char* parseEnv(void) {
const char* env;
env = getenv("XDG_CURRENT_DESKTOP");
if(ffStrSet(env))
if (ffStrSet(env)) {
return env;
}
env = getenv("XDG_SESSION_DESKTOP");
if(ffStrSet(env))
if (ffStrSet(env)) {
return env;
}
env = getenv("CURRENT_DESKTOP");
if(ffStrSet(env))
if (ffStrSet(env)) {
return env;
}
env = getenv("SESSION_DESKTOP");
if(ffStrSet(env))
if (ffStrSet(env)) {
return env;
}
env = getenv("DESKTOP_SESSION");
if(ffStrSet(env))
if (ffStrSet(env)) {
return env;
}
if(getenv("KDE_FULL_SESSION") != NULL || getenv("KDE_SESSION_UID") != NULL || getenv("KDE_SESSION_VERSION") != NULL)
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)
if (getenv("GNOME_DESKTOP_SESSION_ID") != NULL) {
return "GNOME";
}
if(getenv("MATE_DESKTOP_SESSION_ID") != NULL)
if (getenv("MATE_DESKTOP_SESSION_ID") != NULL) {
return "Mate";
}
if(getenv("TDE_FULL_SESSION") != NULL)
if (getenv("TDE_FULL_SESSION") != NULL) {
return "Trinity";
}
if(getenv("HYPRLAND_CMD") != NULL)
if (getenv("HYPRLAND_CMD") != NULL) {
return "Hyprland";
}
if(getenv("SWAYSOCK") != NULL)
if (getenv("SWAYSOCK") != NULL) {
return "Sway";
}
#if __linux__ && !__ANDROID__
if(
#if __linux__ && !__ANDROID__
if (
getenv("WAYLAND_DISPLAY") != NULL &&
ffPathExists("/mnt/wslg/", FF_PATHTYPE_DIRECTORY)
) return "WSLg";
#endif
ffPathExists("/mnt/wslg/", FF_PATHTYPE_DIRECTORY)) {
return "WSLg";
}
#endif
return NULL;
}
static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* name)
{
if(!ffStrSet(name))
static void applyPrettyNameIfWM(FFDisplayServerResult* result, const char* name) {
if (!ffStrSet(name)) {
return;
}
if(
if (
ffStrEqualsIgnCase(name, "kwin") ||
ffStrStartsWithIgnCase(name, "kwin_") ||
ffStrEndsWithIgnCase(name, "-kwin_wayland") ||
ffStrEndsWithIgnCase(name, "-kwin_x11")
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_KWIN);
else if(
ffStrEndsWithIgnCase(name, "-kwin_x11")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_KWIN);
} else if (
ffStrEqualsIgnCase(name, "gnome-shell") ||
ffStrEqualsIgnCase(name, "gnome shell") ||
ffStrEqualsIgnCase(name, "gnome-session-binary") ||
ffStrEqualsIgnCase(name, "Mutter")
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUTTER);
else if(
ffStrEqualsIgnCase(name, "Mutter")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUTTER);
} else if (
ffStrEqualsIgnCase(name, "cinnamon") ||
ffStrStartsWithIgnCase(name, "cinnamon-") ||
ffStrEqualsIgnCase(name, "Muffin") ||
ffStrEqualsIgnCase(name, "Mutter (Muffin)")
) ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUFFIN);
else if(ffStrEqualsIgnCase(name, "sway"))
ffStrEqualsIgnCase(name, "Mutter (Muffin)")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MUFFIN);
} else if (ffStrEqualsIgnCase(name, "sway")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_SWAY);
else if(ffStrEqualsIgnCase(name, "weston"))
} else if (ffStrEqualsIgnCase(name, "weston")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WESTON);
else if(ffStrEqualsIgnCase(name, "wayfire"))
} else if (ffStrEqualsIgnCase(name, "wayfire")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WAYFIRE);
else if(ffStrEqualsIgnCase(name, "openbox"))
} else if (ffStrEqualsIgnCase(name, "openbox")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_OPENBOX);
else if(ffStrEqualsIgnCase(name, "xfwm4"))
} else if (ffStrEqualsIgnCase(name, "xfwm4")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XFWM4);
else if(ffStrEqualsIgnCase(name, "Marco") ||
ffStrEqualsIgnCase(name, "Metacity (Marco)"))
} else if (ffStrEqualsIgnCase(name, "Marco") ||
ffStrEqualsIgnCase(name, "Metacity (Marco)")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_MARCO);
else if(ffStrEqualsIgnCase(name, "xmonad"))
} else if (ffStrEqualsIgnCase(name, "xmonad")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_XMONAD);
else if(ffStrEqualsIgnCase(name, "WSLg"))
} else if (ffStrEqualsIgnCase(name, "WSLg")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_WSLG);
else if(ffStrEqualsIgnCase(name, "dwm"))
} else if (ffStrEqualsIgnCase(name, "dwm")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_DWM);
else if(ffStrEqualsIgnCase(name, "bspwm"))
} else if (ffStrEqualsIgnCase(name, "bspwm")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_BSPWM);
else if(ffStrEqualsIgnCase(name, "tinywm"))
} else if (ffStrEqualsIgnCase(name, "tinywm")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_TINYWM);
else if(ffStrEqualsIgnCase(name, "qtile"))
} else if (ffStrEqualsIgnCase(name, "qtile")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_QTILE);
else if(ffStrEqualsIgnCase(name, "herbstluftwm"))
} else if (ffStrEqualsIgnCase(name, "herbstluftwm")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_HERBSTLUFTWM);
else if(ffStrEqualsIgnCase(name, "icewm"))
} else if (ffStrEqualsIgnCase(name, "icewm")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_ICEWM);
else if(ffStrEqualsIgnCase(name, "dtwm"))
} else if (ffStrEqualsIgnCase(name, "dtwm")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_DTWM);
else if(ffStrEqualsIgnCase(name, "fvwm"))
} else if (ffStrEqualsIgnCase(name, "fvwm")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_FVWM);
else if(ffStrEqualsIgnCase(name, "ctwm"))
} else if (ffStrEqualsIgnCase(name, "ctwm")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_CTWM);
else if(ffStrEqualsIgnCase(name, "hyprland"))
} else if (ffStrEqualsIgnCase(name, "hyprland")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_HYPRLAND);
else if(ffStrEqualsIgnCase(name, "ratpoison"))
} else if (ffStrEqualsIgnCase(name, "ratpoison")) {
ffStrbufSetS(&result->wmPrettyName, FF_WM_PRETTY_RATPOISON);
}
}
static void applyNameIfWM(FFDisplayServerResult* result, const char* processName)
{
static void applyNameIfWM(FFDisplayServerResult* result, const char* processName) {
applyPrettyNameIfWM(result, processName);
if(result->wmPrettyName.length > 0)
if (result->wmPrettyName.length > 0) {
ffStrbufSetS(&result->wmProcessName, processName);
}
}
static void applyBetterWM(FFDisplayServerResult* result, const char* processName)
{
if(!ffStrSet(processName))
static void applyBetterWM(FFDisplayServerResult* result, const char* processName) {
if (!ffStrSet(processName)) {
return;
}
ffStrbufSetS(&result->wmProcessName, processName);
//If it is a known wm, this will set the pretty name
// If it is a known wm, this will set the pretty name
applyPrettyNameIfWM(result, processName);
//If it isn't a known wm, set the pretty name to the process name
if(result->wmPrettyName.length == 0)
// 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 applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name)
{
if(!ffStrSet(name))
static void applyPrettyNameIfDE(FFDisplayServerResult* result, const char* name) {
if (!ffStrSet(name)) {
return;
}
else if(
else if (
ffStrEqualsIgnCase(name, "KDE") ||
ffStrEqualsIgnCase(name, "plasma") ||
ffStrEqualsIgnCase(name, "plasmashell") ||
ffStrEqualsIgnCase(name, "plasmawayland")
) {
ffStrEqualsIgnCase(name, "plasmawayland")) {
ffStrbufSetStatic(&result->deProcessName, "plasmashell");
ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_PLASMA);
applyBetterWM(result, getenv("KDEWM"));
}
else if(
else if (
ffStrEqualsIgnCase(name, "GNOME") ||
ffStrEqualsIgnCase(name, "ubuntu:GNOME") ||
ffStrEqualsIgnCase(name, "ubuntu") ||
ffStrEqualsIgnCase(name, "gnome-shell")
) {
ffStrEqualsIgnCase(name, "gnome-shell")) {
ffStrbufSetStatic(&result->deProcessName, "gnome-shell");
const char* sessionMode = getenv("GNOME_SHELL_SESSION_MODE");
if (sessionMode && ffStrEquals(sessionMode, "classic"))
if (sessionMode && ffStrEquals(sessionMode, "classic")) {
ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_GNOME_CLASSIC);
else
} else {
ffStrbufSetStatic(&result->dePrettyName, FF_DE_PRETTY_GNOME);
}
}
else if(
else if (
ffStrEqualsIgnCase(name, "X-Cinnamon") ||
ffStrEqualsIgnCase(name, "Cinnamon")
) {
ffStrEqualsIgnCase(name, "Cinnamon")) {
ffStrbufSetS(&result->deProcessName, "cinnamon");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CINNAMON);
}
else if(
else if (
ffStrEqualsIgnCase(name, "XFCE") ||
ffStrEqualsIgnCase(name, "X-XFCE") ||
ffStrEqualsIgnCase(name, "XFCE4") ||
ffStrEqualsIgnCase(name, "X-XFCE4") ||
ffStrEqualsIgnCase(name, "xfce4-session")
) {
ffStrEqualsIgnCase(name, "xfce4-session")) {
ffStrbufSetS(&result->deProcessName, "xfce4-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_XFCE4);
}
else if(
else if (
ffStrEqualsIgnCase(name, "MATE") ||
ffStrEqualsIgnCase(name, "X-MATE") ||
ffStrEqualsIgnCase(name, "mate-session")
) {
ffStrEqualsIgnCase(name, "mate-session")) {
ffStrbufSetS(&result->deProcessName, "mate-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_MATE);
}
else if(
else if (
ffStrEqualsIgnCase(name, "LXQt") ||
ffStrEqualsIgnCase(name, "X-LXQt") ||
ffStrEqualsIgnCase(name, "lxqt-session")
) {
ffStrEqualsIgnCase(name, "lxqt-session")) {
ffStrbufSetS(&result->deProcessName, "lxqt-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_LXQT);
if (result->wmProcessName.length == 0)
{
if (result->wmProcessName.length == 0) {
FF_STRBUF_AUTO_DESTROY wmProcessNameBuffer = ffStrbufCreate();
ffParsePropFileConfig("lxqt/session.conf", "window_manager =", &wmProcessNameBuffer);
applyBetterWM(result, wmProcessNameBuffer.chars);
}
}
else if(
else if (
ffStrEqualsIgnCase(name, "Budgie") ||
ffStrEqualsIgnCase(name, "X-Budgie") ||
ffStrEqualsIgnCase(name, "budgie-desktop") ||
ffStrEqualsIgnCase(name, "Budgie:GNOME")
) {
ffStrEqualsIgnCase(name, "Budgie:GNOME")) {
ffStrbufSetS(&result->deProcessName, "budgie-desktop");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_BUDGIE);
}
else if(
ffStrEqualsIgnCase(name, "dtsession")
) {
else if (
ffStrEqualsIgnCase(name, "dtsession")) {
ffStrbufSetS(&result->deProcessName, "dtsession");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_CDE);
}
else if(
ffStrEqualsIgnCase(name, "ukui-session")
) {
else if (
ffStrEqualsIgnCase(name, "ukui-session")) {
ffStrbufSetS(&result->deProcessName, "ukui-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_UKUI);
}
else if(
ffStrStartsWithIgnCase(name, "Unity:Unity")
) {
else if (
ffStrStartsWithIgnCase(name, "Unity:Unity")) {
ffStrbufSetS(&result->deProcessName, "unity-session");
ffStrbufSetS(&result->dePrettyName, FF_DE_PRETTY_UNITY);
}
}
static const char* getFromProcesses(FFDisplayServerResult* result)
{
static const char* getFromProcesses(FFDisplayServerResult* result) {
uint32_t userId = instance.state.platform.uid;
#if __FreeBSD__
#ifdef __DragonFly__
#define ki_comm kp_comm
#endif
# ifdef __DragonFly__
# define ki_comm kp_comm
# endif
int request[] = {CTL_KERN, KERN_PROC, KERN_PROC_UID, (int) userId};
size_t length = 0;
if(sysctl(request, ARRAY_SIZE(request), NULL, &length, NULL, 0) != 0)
if (sysctl(request, ARRAY_SIZE(request), NULL, &length, NULL, 0) != 0) {
return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, NULL) failed";
}
FF_AUTO_FREE struct kinfo_proc* procs = (struct kinfo_proc*) malloc(length);
if(sysctl(request, ARRAY_SIZE(request), procs, &length, NULL, 0) != 0)
if (sysctl(request, ARRAY_SIZE(request), procs, &length, NULL, 0) != 0) {
return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, procs) failed";
}
length /= sizeof(*procs);
for (struct kinfo_proc* proc = procs; proc < procs + length; ++proc)
{
if(result->dePrettyName.length == 0)
for (struct kinfo_proc* proc = procs; proc < procs + length; ++proc) {
if (result->dePrettyName.length == 0) {
applyPrettyNameIfDE(result, proc->ki_comm);
}
if(result->wmPrettyName.length == 0)
if (result->wmPrettyName.length == 0) {
applyNameIfWM(result, proc->ki_comm);
}
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) {
break;
}
}
#elif __OpenBSD__
kvm_t* kd = kvm_open(NULL, NULL, NULL, KVM_NO_FILES, NULL);
int count = 0;
const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_UID, (int) userId, sizeof(*proc), &count);
if (proc)
{
for (int i = 0; i < count; ++i)
{
if(result->dePrettyName.length == 0)
if (proc) {
for (int i = 0; i < count; ++i) {
if (result->dePrettyName.length == 0) {
applyPrettyNameIfDE(result, proc[i].p_comm);
}
if(result->wmPrettyName.length == 0)
if (result->wmPrettyName.length == 0) {
applyNameIfWM(result, proc[i].p_comm);
}
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) {
break;
}
}
}
kvm_close(kd);
#elif __sun
FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc");
if(procdir == NULL)
if (procdir == NULL) {
return "opendir(\"/proc\") failed";
}
FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreateA(64);
ffStrbufAppendS(&procPath, "/proc/");
@@ -329,35 +336,39 @@ static const char* getFromProcesses(FFDisplayServerResult* result)
uint32_t procPathLength = procPath.length;
struct dirent* dirent;
while((dirent = readdir(procdir)) != NULL)
{
if (!ffCharIsDigit(dirent->d_name[0]))
while ((dirent = readdir(procdir)) != NULL) {
if (!ffCharIsDigit(dirent->d_name[0])) {
continue;
}
ffStrbufAppendS(&procPath, dirent->d_name);
ffStrbufAppendS(&procPath, "/psinfo");
psinfo_t proc;
if (ffReadFileData(procPath.chars, sizeof(proc), &proc) == sizeof(proc))
{
if (ffReadFileData(procPath.chars, sizeof(proc), &proc) == sizeof(proc)) {
ffStrbufSubstrBefore(&procPath, procPathLength);
if (proc.pr_uid != userId)
if (proc.pr_uid != userId) {
continue;
}
if(result->dePrettyName.length == 0)
if (result->dePrettyName.length == 0) {
applyPrettyNameIfDE(result, proc.pr_fname);
}
if(result->wmPrettyName.length == 0)
if (result->wmPrettyName.length == 0) {
applyNameIfWM(result, proc.pr_fname);
}
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) {
break;
}
}
}
#elif __linux__ || __GNU__
FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc");
if(procdir == NULL)
if (procdir == NULL) {
return "opendir(\"/proc\") failed";
}
FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreateA(64);
ffStrbufAppendS(&procPath, "/proc/");
@@ -365,139 +376,142 @@ static const char* getFromProcesses(FFDisplayServerResult* result)
uint32_t procPathLength = procPath.length;
FF_STRBUF_AUTO_DESTROY loginuid = ffStrbufCreate();
FF_STRBUF_AUTO_DESTROY processName = ffStrbufCreateA(256); //Some processes have large command lines (looking at you chrome)
FF_STRBUF_AUTO_DESTROY processName = ffStrbufCreateA(256); // Some processes have large command lines (looking at you chrome)
struct dirent* dirent;
while((dirent = readdir(procdir)) != NULL)
{
//Match only folders starting with a number (the pid folders)
if(dirent->d_type != DT_DIR || !ffCharIsDigit(dirent->d_name[0]))
while ((dirent = readdir(procdir)) != NULL) {
// Match only folders starting with a number (the pid folders)
if (dirent->d_type != DT_DIR || !ffCharIsDigit(dirent->d_name[0])) {
continue;
}
ffStrbufAppendS(&procPath, dirent->d_name);
uint32_t procFolderPathLength = procPath.length;
//Don't check for processes not owned by the current user.
// Don't check for processes not owned by the current user.
ffStrbufAppendS(&procPath, "/loginuid");
ffReadFileBuffer(procPath.chars, &loginuid);
if(ffStrbufToUInt(&loginuid, (uint64_t) -1) != userId)
{
if (ffStrbufToUInt(&loginuid, (uint64_t) -1) != userId) {
ffStrbufSubstrBefore(&procPath, procPathLength);
continue;
}
ffStrbufSubstrBefore(&procPath, procFolderPathLength);
//We check the cmdline for the process name, because it is not trimmed.
// We check the cmdline for the process name, because it is not trimmed.
ffStrbufAppendS(&procPath, "/cmdline");
ffReadFileBuffer(procPath.chars, &processName);
ffStrbufTrimRightSpace(&processName);
ffStrbufSubstrBeforeFirstC(&processName, '\0'); //Trim the arguments
ffStrbufSubstrBeforeFirstC(&processName, '\0'); // Trim the arguments
ffStrbufSubstrAfterLastC(&processName, '/');
ffStrbufSubstrBefore(&procPath, procPathLength);
if(result->dePrettyName.length == 0)
if (result->dePrettyName.length == 0) {
applyPrettyNameIfDE(result, processName.chars);
}
if(result->wmPrettyName.length == 0)
if (result->wmPrettyName.length == 0) {
applyNameIfWM(result, processName.chars);
}
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) {
break;
}
}
#elif __NetBSD__
int request[] = {CTL_KERN, KERN_PROC2, KERN_PROC_UID, (int) userId, sizeof(struct kinfo_proc2), INT_MAX};
size_t size = 0;
if(sysctl(request, ARRAY_SIZE(request), NULL, &size, NULL, 0) != 0)
if (sysctl(request, ARRAY_SIZE(request), NULL, &size, NULL, 0) != 0) {
return "sysctl(KERN_PROC_UID, NULL) failed";
}
FF_AUTO_FREE struct kinfo_proc2* procs = malloc(size);
if(sysctl(request, ARRAY_SIZE(request), procs, &size, NULL, 0) != 0)
if (sysctl(request, ARRAY_SIZE(request), procs, &size, NULL, 0) != 0) {
return "sysctl(KERN_PROC_UID, procs) failed";
}
for(struct kinfo_proc2* proc = procs; proc < procs + (size / sizeof(struct kinfo_proc2)); proc++)
{
if(result->dePrettyName.length == 0)
for (struct kinfo_proc2* proc = procs; proc < procs + (size / sizeof(struct kinfo_proc2)); proc++) {
if (result->dePrettyName.length == 0) {
applyPrettyNameIfDE(result, proc->p_comm);
}
if(result->wmPrettyName.length == 0)
if (result->wmPrettyName.length == 0) {
applyNameIfWM(result, proc->p_comm);
}
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) {
break;
}
}
#endif
return NULL;
}
void ffdsDetectWMDE(FFDisplayServerResult* result)
{
#if __ANDROID__
if(ffStrbufIgnCaseEqualS(&result->wmProtocolName, FF_WM_PROTOCOL_SURFACEFLINGER))
void ffdsDetectWMDE(FFDisplayServerResult* result) {
#if __ANDROID__
if (ffStrbufIgnCaseEqualS(&result->wmProtocolName, FF_WM_PROTOCOL_SURFACEFLINGER)) {
return; // Only supported when connected to X11
#endif
}
#endif
const char* env = parseEnv();
if(result->wmProcessName.length > 0)
{
//If we found the processName via display server, use it.
//This will set the pretty name if it is a known WM, otherwise the prettyName to the processName
if (result->wmProcessName.length > 0) {
// If we found the processName via display server, use it.
// This will set the pretty name if it is a known WM, otherwise the prettyName to the processName
applyPrettyNameIfWM(result, result->wmProcessName.chars);
if(result->wmPrettyName.length == 0)
if (result->wmPrettyName.length == 0) {
ffStrbufSet(&result->wmPrettyName, &result->wmProcessName);
}
else
{
//if env is a known WM, use it
}
} else {
// if env is a known WM, use it
applyNameIfWM(result, env);
}
//Connecting to a display server only gives WM results, not DE results.
//If we find it in the environment, use that.
// Connecting to a display server only gives WM results, not DE results.
// If we find it in the environment, use that.
applyPrettyNameIfDE(result, env);
//If WM was found by connection to the sever, and DE in the environment, we can return
//This way we never call getFromProcDir(), which has slow initialization time
if(result->dePrettyName.length > 0 && result->wmPrettyName.length > 0)
// If WM was found by connection to the sever, and DE in the environment, we can return
// This way we never call getFromProcDir(), which has slow initialization time
if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) {
return;
}
//Get missing WM / DE from processes.
// Get missing WM / DE from processes.
getFromProcesses(result);
//Return if both wm and de are set, or if env doesn't contain anything
if(
// Return if both wm and de are set, or if env doesn't contain anything
if (
(result->wmPrettyName.length > 0 && result->dePrettyName.length > 0) ||
!ffStrSet(env)
) return;
!ffStrSet(env)) {
return;
}
//If nothing is set, use env as WM
else if(result->wmPrettyName.length == 0 && result->dePrettyName.length == 0)
{
// If nothing is set, use env as WM
else if (result->wmPrettyName.length == 0 && result->dePrettyName.length == 0) {
ffStrbufSetS(&result->wmProcessName, env);
ffStrbufSetS(&result->wmPrettyName, env);
}
//If only WM is not set, and DE doesn't equal env, use env as WM
else if(
// If only WM is not set, and DE doesn't equal env, use env as WM
else if (
result->wmPrettyName.length == 0 &&
ffStrbufIgnCaseCompS(&result->deProcessName, env) != 0 &&
ffStrbufIgnCaseCompS(&result->dePrettyName, env) != 0
) {
ffStrbufIgnCaseCompS(&result->dePrettyName, env) != 0) {
ffStrbufSetS(&result->wmProcessName, env);
ffStrbufSetS(&result->wmPrettyName, env);
}
//If only DE is not set, and WM doesn't equal env, use env as DE
else if(
// If only DE is not set, and WM doesn't equal env, use env as DE
else if (
result->dePrettyName.length == 0 &&
ffStrbufIgnCaseCompS(&result->wmProcessName, env) != 0 &&
ffStrbufIgnCaseCompS(&result->wmPrettyName, env) != 0
) {
ffStrbufIgnCaseCompS(&result->wmPrettyName, env) != 0) {
ffStrbufSetS(&result->deProcessName, env);
ffStrbufSetS(&result->dePrettyName, env);
}
+100 -112
View File
@@ -2,19 +2,18 @@
#ifdef FF_HAVE_XCB_RANDR
#include "common/library.h"
#include "common/properties.h"
#include "common/edidHelper.h"
#include "common/mallocHelper.h"
#include "common/stringUtils.h"
# include "common/library.h"
# include "common/properties.h"
# include "common/edidHelper.h"
# include "common/mallocHelper.h"
# include "common/stringUtils.h"
#include <stdlib.h>
#include <string.h>
#include <xcb/randr.h>
#include <xcb/xcb.h>
# include <stdlib.h>
# include <string.h>
# include <xcb/randr.h>
# include <xcb/xcb.h>
typedef struct XcbRandrData
{
typedef struct XcbRandrData {
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_current)
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_current_reply)
FF_LIBRARY_SYMBOL(xcb_randr_get_screen_resources_current_modes_iterator)
@@ -49,74 +48,77 @@ typedef struct XcbRandrData
FF_LIBRARY_SYMBOL(xcb_setup_vendor)
FF_LIBRARY_SYMBOL(xcb_setup_vendor_length)
//init once
// init once
xcb_connection_t* connection;
FFDisplayServerResult* result;
} XcbRandrData;
static void* xcbGetProperty(XcbRandrData* data, xcb_window_t window, const char* request)
{
static void* xcbGetProperty(XcbRandrData* data, xcb_window_t window, const char* request) {
xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(data->connection, true, (uint16_t) strlen(request), request);
FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(data->connection, requestAtomCookie, NULL);
if(requestAtomReply == NULL)
if (requestAtomReply == NULL) {
return NULL;
}
xcb_get_property_cookie_t propertyCookie = data->ffxcb_get_property(data->connection, false, window, requestAtomReply->atom, XCB_ATOM_ANY, 0, 8 * 1024);
FF_AUTO_FREE xcb_get_property_reply_t* propertyReply = data->ffxcb_get_property_reply(data->connection, propertyCookie, NULL);
if(propertyReply == NULL)
if (propertyReply == NULL) {
return NULL;
}
int length = data->ffxcb_get_property_value_length(propertyReply);
if(length <= 0)
if (length <= 0) {
return NULL;
}
//Why are xcb property strings not null terminated???
void* replyValue = malloc((size_t)length + 1);
// 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';
return replyValue;
}
static xcb_randr_get_output_property_reply_t* xcbRandrGetProperty(XcbRandrData* data, xcb_randr_output_t output, const char* name)
{
static xcb_randr_get_output_property_reply_t* xcbRandrGetProperty(XcbRandrData* data, xcb_randr_output_t output, const char* name) {
xcb_intern_atom_cookie_t requestAtomCookie = data->ffxcb_intern_atom(data->connection, true, (uint16_t) strlen(name), name);
FF_AUTO_FREE xcb_intern_atom_reply_t* requestAtomReply = data->ffxcb_intern_atom_reply(data->connection, requestAtomCookie, NULL);
if(requestAtomReply)
{
if (requestAtomReply) {
xcb_randr_get_output_property_cookie_t outputPropertyCookie = data->ffxcb_randr_get_output_property(data->connection, output, requestAtomReply->atom, XCB_GET_PROPERTY_TYPE_ANY, 0, 100, false, false);
return data->ffxcb_randr_get_output_property_reply(data->connection, outputPropertyCookie, NULL);
}
return NULL;
}
static void xcbDetectWMfromEWMH(XcbRandrData* data, xcb_window_t rootWindow, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0 || ffStrbufEqualS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND))
static void xcbDetectWMfromEWMH(XcbRandrData* data, xcb_window_t rootWindow, FFDisplayServerResult* result) {
if (result->wmProcessName.length > 0 || ffStrbufEqualS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND)) {
return;
}
FF_AUTO_FREE xcb_window_t* wmWindow = (xcb_window_t*) xcbGetProperty(data, rootWindow, "_NET_SUPPORTING_WM_CHECK");
if(wmWindow == NULL)
if (wmWindow == NULL) {
return;
}
FF_AUTO_FREE char* wmName = (char*) xcbGetProperty(data, *wmWindow, "WM_NAME");
if(!ffStrSet(wmName))
if (!ffStrSet(wmName)) {
wmName = (char*) xcbGetProperty(data, *wmWindow, "_NET_WM_NAME");
}
if(!ffStrSet(wmName))
if (!ffStrSet(wmName)) {
return;
}
ffStrbufSetS(&result->wmProcessName, wmName);
}
static void xcbFetchServerVendor(XcbRandrData* data, FFDisplayServerResult* result)
{
static void xcbFetchServerVendor(XcbRandrData* data, FFDisplayServerResult* result) {
const xcb_setup_t* setup = data->ffxcb_get_setup(data->connection);
int length = data->ffxcb_setup_vendor_length(setup);
if(length <= 0)
if (length <= 0) {
return;
}
FF_STRBUF_AUTO_DESTROY serverVendor = ffStrbufCreateNS((uint32_t) length, data->ffxcb_setup_vendor(setup));
@@ -127,49 +129,46 @@ static void xcbFetchServerVendor(XcbRandrData* data, FFDisplayServerResult* resu
}
}
static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary, FFDisplayType displayType, struct xcb_randr_get_screen_resources_current_reply_t* screenResources, uint8_t bitDepth, uint32_t dpi)
{
static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output, FFstrbuf* name, bool primary, FFDisplayType displayType, struct xcb_randr_get_screen_resources_current_reply_t* screenResources, uint8_t bitDepth, uint32_t dpi) {
xcb_randr_get_output_info_cookie_t outputInfoCookie = data->ffxcb_randr_get_output_info(data->connection, output, XCB_CURRENT_TIME);
FF_AUTO_FREE xcb_randr_get_output_info_reply_t* outputInfoReply = data->ffxcb_randr_get_output_info_reply(data->connection, outputInfoCookie, NULL);
if(outputInfoReply == NULL)
if (outputInfoReply == NULL) {
return false;
}
FF_AUTO_FREE xcb_randr_get_output_property_reply_t* edidReply = xcbRandrGetProperty(data, output, "EDID");
uint8_t* edidData = NULL;
uint32_t edidLength = 0;
if(edidReply)
{
if (edidReply) {
int len = data->ffxcb_randr_get_output_property_data_length(edidReply);
if(len >= 128)
{
if (len >= 128) {
edidData = data->ffxcb_randr_get_output_property_data(edidReply);
edidLength = (uint32_t) len;
}
}
if(edidData)
{
if (edidData) {
ffStrbufClear(name);
ffEdidGetName(edidData, name);
}
bool randrEmulation = false;
FF_AUTO_FREE xcb_randr_get_output_property_reply_t* randrEmulationReply = xcbRandrGetProperty(data, output, "RANDR Emulation");
if(randrEmulationReply)
{
if (randrEmulationReply) {
int len = data->ffxcb_randr_get_output_property_data_length(randrEmulationReply);
if(len >= 1)
if (len >= 1) {
randrEmulation = !!data->ffxcb_randr_get_output_property_data(randrEmulationReply)[0];
}
}
xcb_randr_get_crtc_info_cookie_t crtcInfoCookie = data->ffxcb_randr_get_crtc_info(data->connection, outputInfoReply->crtc, XCB_CURRENT_TIME);
FF_AUTO_FREE xcb_randr_get_crtc_info_reply_t* crtcInfoReply = data->ffxcb_randr_get_crtc_info_reply(data->connection, crtcInfoCookie, NULL);
if(crtcInfoReply == NULL)
if (crtcInfoReply == NULL) {
return false;
}
uint32_t rotation;
switch (crtcInfoReply->rotation)
{
switch (crtcInfoReply->rotation) {
case XCB_RANDR_ROTATION_ROTATE_90:
rotation = 90;
break;
@@ -187,17 +186,15 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output,
xcb_randr_mode_info_t* currentMode = NULL;
xcb_randr_mode_info_t* preferredMode = NULL;
if(screenResources)
{
if (screenResources) {
xcb_randr_mode_info_iterator_t modesIterator = data->ffxcb_randr_get_screen_resources_current_modes_iterator(screenResources);
if (outputInfoReply->num_preferred > 0)
if (outputInfoReply->num_preferred > 0) {
preferredMode = modesIterator.data;
}
while (modesIterator.rem > 0)
{
if (modesIterator.data->id == crtcInfoReply->mode)
{
while (modesIterator.rem > 0) {
if (modesIterator.data->id == crtcInfoReply->mode) {
currentMode = modesIterator.data;
break;
}
@@ -227,16 +224,13 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output,
: (currentMode ? "xcb-randr-mode" : "xcb-randr-crtc")
);
if (item)
{
if (edidData && edidLength >= 128)
{
if (item) {
if (edidData && edidLength >= 128) {
item->hdrStatus = ffEdidGetHdrCompatible(edidData, (uint32_t) edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
}
item->bitDepth = bitDepth;
if ((rotation == 90 || rotation == 180) && !randrEmulation)
{
if ((rotation == 90 || rotation == 180) && !randrEmulation) {
// In XWayland mode, width / height has been swapped out of box
uint32_t tmp = item->width;
item->width = item->height;
@@ -247,36 +241,34 @@ static bool xcbRandrHandleOutput(XcbRandrData* data, xcb_randr_output_t output,
return !!item;
}
static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* monitor, struct xcb_randr_get_screen_resources_current_reply_t* screenResources, uint8_t bitDepth, uint32_t dpi)
{
//for some reasons, we have to construct this our self
static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t* monitor, struct xcb_randr_get_screen_resources_current_reply_t* screenResources, uint8_t bitDepth, uint32_t dpi) {
// 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)
};
.rem = data->ffxcb_randr_monitor_info_outputs_length(monitor)};
FF_AUTO_FREE xcb_get_atom_name_reply_t* nameReply = data->ffxcb_get_atom_name_reply(
data->connection,
data->ffxcb_get_atom_name(data->connection, monitor->name),
NULL
);
NULL);
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateNS(
(uint32_t) data->ffxcb_get_atom_name_name_length(nameReply),
data->ffxcb_get_atom_name_name(nameReply)
);
data->ffxcb_get_atom_name_name(nameReply));
const FFDisplayType displayType = ffdsGetDisplayType(name.chars);
bool foundOutput = false;
while(outputIterator.rem > 0)
{
if(xcbRandrHandleOutput(data, *outputIterator.data, &name, monitor->primary, displayType, screenResources, bitDepth, dpi))
while (outputIterator.rem > 0) {
if (xcbRandrHandleOutput(data, *outputIterator.data, &name, monitor->primary, displayType, screenResources, bitDepth, dpi)) {
foundOutput = true;
}
data->ffxcb_randr_output_next(&outputIterator);
}
if (foundOutput) return true;
if (foundOutput) {
return true;
}
FFDisplayResult* display = ffdsAppendDisplay(
data->result,
@@ -284,7 +276,9 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
(uint32_t) monitor->height,
0,
dpi,
0, 0, 0,
0,
0,
0,
0,
&name,
displayType,
@@ -292,30 +286,31 @@ static bool xcbRandrHandleMonitor(XcbRandrData* data, xcb_randr_monitor_info_t*
0,
(uint32_t) monitor->width_in_millimeters,
(uint32_t) monitor->height_in_millimeters,
"xcb-randr-monitor"
);
if (display) display->bitDepth = bitDepth;
"xcb-randr-monitor");
if (display) {
display->bitDepth = bitDepth;
}
return !!display;
}
static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
{
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);
FF_AUTO_FREE xcb_randr_get_monitors_reply_t* monitorsReply = data->ffxcb_randr_get_monitors_reply(data->connection, monitorsCookie, NULL);
if(monitorsReply == NULL)
if (monitorsReply == NULL) {
return false;
}
//Init screen resources. They are used to iterate over all modes. xcbRandrHandleMode checks for " == NULL", to fail as late as possible.
// 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_current_cookie_t screenResourcesCookie = data->ffxcb_randr_get_screen_resources_current(data->connection, screen->root);
FF_AUTO_FREE struct xcb_randr_get_screen_resources_current_reply_t* screenResources = data->ffxcb_randr_get_screen_resources_current_reply(data->connection, screenResourcesCookie, NULL);
uint32_t dpi = 0;
FF_AUTO_FREE const char* resourceManager = xcbGetProperty(data, screen->root, "RESOURCE_MANAGER");
if (resourceManager)
{
if (resourceManager) {
FF_STRBUF_AUTO_DESTROY dpiStr = ffStrbufCreate();
if (ffParsePropLines(resourceManager, "Xft.dpi:", &dpiStr))
if (ffParsePropLines(resourceManager, "Xft.dpi:", &dpiStr)) {
dpi = (uint32_t) ffStrbufToUInt(&dpiStr, 96);
}
}
uint8_t bitDepth = (uint8_t) (screen->root_depth / 3);
@@ -323,30 +318,32 @@ static bool xcbRandrHandleMonitors(XcbRandrData* data, xcb_screen_t* screen)
bool foundMonitor = false;
while(monitorInfoIterator.rem > 0)
{
if(xcbRandrHandleMonitor(data, monitorInfoIterator.data, screenResources, bitDepth, dpi))
while (monitorInfoIterator.rem > 0) {
if (xcbRandrHandleMonitor(data, monitorInfoIterator.data, screenResources, bitDepth, dpi)) {
foundMonitor = true;
}
data->ffxcb_randr_monitor_info_next(&monitorInfoIterator);
}
return foundMonitor;
}
static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
{
//With all the initialisation done, start the detection
if(xcbRandrHandleMonitors(data, screen))
static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen) {
// With all the initialisation done, start the detection
if (xcbRandrHandleMonitors(data, screen)) {
return;
}
//If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation
// If detetction failed, fallback to screen = monitor, like in the libxcb.so implementation
ffdsAppendDisplay(
data->result,
(uint32_t) screen->width_in_pixels,
(uint32_t) screen->height_in_pixels,
0,
0,
0, 0, 0,
0,
0,
0,
0,
NULL,
FF_DISPLAY_TYPE_UNKNOWN,
@@ -354,12 +351,10 @@ static void xcbRandrHandleScreen(XcbRandrData* data, xcb_screen_t* screen)
(uint64_t) screen->root,
(uint32_t) screen->width_in_millimeters,
(uint32_t) screen->height_in_millimeters,
"xcb-randr-screen"
);
"xcb-randr-screen");
}
const char* ffdsConnectXcbRandr(FFDisplayServerResult* result)
{
const char* ffdsConnectXcbRandr(FFDisplayServerResult* result) {
FF_LIBRARY_LOAD_MESSAGE(xcbRandr, "libxcb-randr" FF_LIBRARY_EXTENSION, 1)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_connect)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xcbRandr, xcb_connection_has_error)
@@ -404,47 +399,40 @@ const char* ffdsConnectXcbRandr(FFDisplayServerResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_randr_get_crtc_info)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xcbRandr, data, xcb_randr_get_crtc_info_reply)
data.connection = ffxcb_connect(NULL, NULL);
if(ffxcb_connection_has_error(data.connection) > 0)
{
if (ffxcb_connection_has_error(data.connection) > 0) {
ffxcb_disconnect(data.connection);
return "xcb_connect() failed";
}
data.result = result;
xcb_screen_iterator_t iterator = ffxcb_setup_roots_iterator(ffxcb_get_setup(data.connection));
if(iterator.rem > 0) {
if (iterator.rem > 0) {
xcbDetectWMfromEWMH(&data, iterator.data->root, result);
xcbFetchServerVendor(&data, result);
}
while(iterator.rem > 0)
{
while (iterator.rem > 0) {
xcbRandrHandleScreen(&data, iterator.data);
ffxcb_screen_next(&iterator);
}
ffxcb_disconnect(data.connection);
//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)
// 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_WM_PROTOCOL_X11);
}
return NULL;
}
#else
const char* ffdsConnectXcbRandr(FFDisplayServerResult* result)
{
//Do nothing. There are other implementations coming
const char* ffdsConnectXcbRandr(FFDisplayServerResult* result) {
// Do nothing. There are other implementations coming
FF_UNUSED(result)
return "Fastfetch was compiled without libxcb-randr support";
}
+97 -96
View File
@@ -2,16 +2,15 @@
#ifdef FF_HAVE_XRANDR
#include "common/library.h"
#include "common/properties.h"
#include "common/edidHelper.h"
#include "common/stringUtils.h"
# include "common/library.h"
# include "common/properties.h"
# include "common/edidHelper.h"
# include "common/stringUtils.h"
#include <X11/extensions/Xrandr.h>
#include <X11/Xlib.h>
# include <X11/extensions/Xrandr.h>
# include <X11/Xlib.h>
typedef struct XrandrData
{
typedef struct XrandrData {
FF_LIBRARY_SYMBOL(XInternAtom)
FF_LIBRARY_SYMBOL(XGetAtomName)
FF_LIBRARY_SYMBOL(XGetWindowProperty)
@@ -27,45 +26,43 @@ typedef struct XrandrData
FF_LIBRARY_SYMBOL(XRRFreeScreenResources)
FF_LIBRARY_SYMBOL(XRRFreeMonitors)
//Init once
// Init once
Display* display;
FFDisplayServerResult* result;
} XrandrData;
static unsigned char* x11GetProperty(XrandrData* data, Display* display, Window window, const char* request)
{
static unsigned char* x11GetProperty(XrandrData* data, Display* display, Window window, const char* request) {
Atom requestAtom = data->ffXInternAtom(display, request, False);
if(requestAtom == None)
if (requestAtom == None) {
return NULL;
}
Atom actualType;
unsigned long unused;
unsigned char* result = NULL;
if(data->ffXGetWindowProperty(display, window, requestAtom, 0, 64, False, AnyPropertyType, &actualType, (int*) &unused, &unused, &unused, &result) != Success)
if (data->ffXGetWindowProperty(display, window, requestAtom, 0, 64, False, AnyPropertyType, &actualType, (int*) &unused, &unused, &unused, &result) != Success) {
return NULL;
}
return result;
}
static uint8_t* xrandrGetProperty(XrandrData* data, RROutput output, const char* name, uint32_t* bufSize)
{
static uint8_t* xrandrGetProperty(XrandrData* data, RROutput output, const char* name, uint32_t* bufSize) {
unsigned long size = 0;
uint8_t* result = NULL;
Atom atomEdid = data->ffXInternAtom(data->display, name, true);
if (atomEdid != None)
{
if (atomEdid != None) {
int actual_format = 0;
unsigned long bytes_after = 0;
Atom actual_type = None;
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &size, &bytes_after, &result) == Success)
{
if (size == 0)
if (data->ffXRRGetOutputProperty(data->display, output, atomEdid, 0, 100, false, false, AnyPropertyType, &actual_type, &actual_format, &size, &bytes_after, &result) == Success) {
if (size == 0) {
data->ffXFree(result);
else
{
if (bufSize)
} else {
if (bufSize) {
*bufSize = (uint32_t) size;
}
return result;
}
}
@@ -74,46 +71,49 @@ static uint8_t* xrandrGetProperty(XrandrData* data, RROutput output, const char*
return NULL;
}
static void x11DetectWMFromEWMH(XrandrData* data, FFDisplayServerResult* result)
{
if(result->wmProcessName.length > 0 || ffStrbufEqualS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND))
static void x11DetectWMFromEWMH(XrandrData* data, FFDisplayServerResult* result) {
if (result->wmProcessName.length > 0 || ffStrbufEqualS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND)) {
return;
}
Window* wmWindow = (Window*) x11GetProperty(data, data->display, DefaultRootWindow(data->display), "_NET_SUPPORTING_WM_CHECK");
if(wmWindow == NULL)
if (wmWindow == NULL) {
return;
}
char* wmName = (char*) x11GetProperty(data, data->display, *wmWindow, "WM_NAME");
if(!ffStrSet(wmName))
if (!ffStrSet(wmName)) {
wmName = (char*) x11GetProperty(data, data->display, *wmWindow, "_NET_WM_NAME");
}
if(ffStrSet(wmName))
if (ffStrSet(wmName)) {
ffStrbufSetS(&result->wmProcessName, wmName);
}
data->ffXFree(wmName);
data->ffXFree(wmWindow);
}
static void x11FetchServerVendor(XrandrData* data, FFDisplayServerResult* result)
{
static void x11FetchServerVendor(XrandrData* data, FFDisplayServerResult* result) {
const char* serverVendor = data->ffXServerVendor(data->display);
if (serverVendor && !ffStrEquals(serverVendor, "The X.Org Foundation"))
if (serverVendor && !ffStrEquals(serverVendor, "The X.Org Foundation")) {
ffStrbufSetS(&result->wmProtocolName, serverVendor);
}
}
static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength, XRRScreenResources* screenResources, uint8_t bitDepth, uint32_t dpi, bool randrEmulation)
{
//We do the check here, because we want the best fallback display if this call failed
if(screenResources == NULL)
static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf* name, bool primary, FFDisplayType displayType, uint8_t* edidData, uint32_t edidLength, XRRScreenResources* screenResources, uint8_t bitDepth, uint32_t dpi, bool randrEmulation) {
// We do the check here, because we want the best fallback display if this call failed
if (screenResources == NULL) {
return false;
}
XRRCrtcInfo* crtcInfo = data->ffXRRGetCrtcInfo(data->display, screenResources, output->crtc);
if(crtcInfo == NULL)
if (crtcInfo == NULL) {
return false;
}
uint32_t rotation;
switch (crtcInfo->rotation)
{
switch (crtcInfo->rotation) {
case RR_Rotate_90:
rotation = 90;
break;
@@ -129,10 +129,8 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
}
XRRModeInfo* currentMode = NULL;
for(int i = 0; i < screenResources->nmode; i++)
{
if(screenResources->modes[i].id == crtcInfo->mode)
{
for (int i = 0; i < screenResources->nmode; i++) {
if (screenResources->modes[i].id == crtcInfo->mode) {
currentMode = &screenResources->modes[i];
break;
}
@@ -158,19 +156,15 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
(uint32_t) output->mm_height,
randrEmulation
? (currentMode ? "xlib-randr-emu-mode" : "xlib-randr-emu-crtc")
: (currentMode ? "xlib-randr-mode" : "xlib-randr-crtc")
);
: (currentMode ? "xlib-randr-mode" : "xlib-randr-crtc"));
if (item)
{
if (edidLength)
{
if (item) {
if (edidLength) {
item->hdrStatus = ffEdidGetHdrCompatible(edidData, edidLength) ? FF_DISPLAY_HDR_STATUS_SUPPORTED : FF_DISPLAY_HDR_STATUS_UNSUPPORTED;
ffEdidGetSerialAndManufactureDate(edidData, &item->serial, &item->manufactureYear, &item->manufactureWeek);
}
item->bitDepth = bitDepth;
if ((rotation == 90 || rotation == 180) && !randrEmulation)
{
if ((rotation == 90 || rotation == 180) && !randrEmulation) {
// In XWayland mode, width / height has been swapped out of box
uint32_t tmp = item->width;
item->width = item->height;
@@ -182,50 +176,52 @@ static bool xrandrHandleCrtc(XrandrData* data, XRROutputInfo* output, FFstrbuf*
return !!item;
}
static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType, XRRScreenResources* screenResources, uint8_t bitDepth, uint32_t dpi)
{
static bool xrandrHandleOutput(XrandrData* data, RROutput output, FFstrbuf* name, bool primary, FFDisplayType displayType, XRRScreenResources* screenResources, uint8_t bitDepth, uint32_t dpi) {
XRROutputInfo* outputInfo = data->ffXRRGetOutputInfo(data->display, screenResources, output);
if(outputInfo == NULL)
if (outputInfo == NULL) {
return false;
}
uint32_t edidLength = 0;
uint8_t* edidData = xrandrGetProperty(data, output, RR_PROPERTY_RANDR_EDID, &edidLength);
if (edidLength >= 128)
{
if (edidLength >= 128) {
ffStrbufClear(name);
ffEdidGetName(edidData, name);
}
else
} else {
edidLength = 0;
}
uint8_t* randrEmulation = xrandrGetProperty(data, output, "RANDR Emulation", NULL);
bool res = xrandrHandleCrtc(data, outputInfo, name, primary, displayType, edidData, edidLength, screenResources, bitDepth, dpi, randrEmulation ? !!randrEmulation[0] : false);
if (edidData)
if (edidData) {
data->ffXFree(edidData);
if (randrEmulation)
}
if (randrEmulation) {
data->ffXFree(randrEmulation);
}
data->ffXRRFreeOutputInfo(outputInfo);
return res;
}
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo, XRRScreenResources* screenResources, uint8_t bitDepth, uint32_t dpi)
{
static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo, XRRScreenResources* screenResources, uint8_t bitDepth, uint32_t dpi) {
bool foundOutput = false;
char* xname = data->ffXGetAtomName(data->display, monitorInfo->name);
FF_STRBUF_AUTO_DESTROY name = ffStrbufCreateS(xname);
data->ffXFree(xname);
FFDisplayType displayType = ffdsGetDisplayType(name.chars);
for(int i = 0; i < monitorInfo->noutput; i++)
{
if(xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary, displayType, screenResources, bitDepth, dpi))
for (int i = 0; i < monitorInfo->noutput; i++) {
if (xrandrHandleOutput(data, monitorInfo->outputs[i], &name, monitorInfo->primary, displayType, screenResources, bitDepth, dpi)) {
foundOutput = true;
}
}
if (foundOutput) return true;
if (foundOutput) {
return true;
}
FFDisplayResult* display = ffdsAppendDisplay(
data->result,
@@ -233,7 +229,9 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo, X
(uint32_t) monitorInfo->height,
0,
dpi,
0, 0, 0,
0,
0,
0,
0,
&name,
displayType,
@@ -241,38 +239,39 @@ static bool xrandrHandleMonitor(XrandrData* data, XRRMonitorInfo* monitorInfo, X
0,
(uint32_t) monitorInfo->mwidth,
(uint32_t) monitorInfo->mheight,
"xlib-randr-monitor"
);
if (display) display->bitDepth = bitDepth;
"xlib-randr-monitor");
if (display) {
display->bitDepth = bitDepth;
}
return !!display;
}
static bool xrandrHandleMonitors(XrandrData* data, Screen* screen)
{
static bool xrandrHandleMonitors(XrandrData* data, Screen* screen) {
int numberOfMonitors;
XRRMonitorInfo* monitorInfos = data->ffXRRGetMonitors(data->display, RootWindowOfScreen(screen), True, &numberOfMonitors);
if(monitorInfos == NULL)
if (monitorInfos == NULL) {
return false;
}
XRRScreenResources* screenResources = data->ffXRRGetScreenResourcesCurrent(data->display, RootWindowOfScreen(screen));
uint32_t dpi = 1;
char* resourceManager = (char*) x11GetProperty(data, data->display, screen->root, "RESOURCE_MANAGER");
if (resourceManager)
{
if (resourceManager) {
FF_STRBUF_AUTO_DESTROY dpiStr = ffStrbufCreate();
if (ffParsePropLines(resourceManager, "Xft.dpi:", &dpiStr))
if (ffParsePropLines(resourceManager, "Xft.dpi:", &dpiStr)) {
dpi = (uint32_t) ffStrbufToUInt(&dpiStr, 96);
}
data->ffXFree(resourceManager);
}
uint8_t bitDepth = (uint8_t) (screen->root_depth / 3);
bool foundAMonitor = false;
for(int i = 0; i < numberOfMonitors; i++)
{
if(xrandrHandleMonitor(data, &monitorInfos[i], screenResources, bitDepth, dpi))
for (int i = 0; i < numberOfMonitors; i++) {
if (xrandrHandleMonitor(data, &monitorInfos[i], screenResources, bitDepth, dpi)) {
foundAMonitor = true;
}
}
data->ffXRRFreeMonitors(monitorInfos);
@@ -281,19 +280,21 @@ static bool xrandrHandleMonitors(XrandrData* data, Screen* screen)
return foundAMonitor;
}
static void xrandrHandleScreen(XrandrData* data, Screen* screen)
{
if(xrandrHandleMonitors(data, screen))
static void xrandrHandleScreen(XrandrData* data, Screen* screen) {
if (xrandrHandleMonitors(data, screen)) {
return;
}
//Fallback to screen
// Fallback to screen
ffdsAppendDisplay(
data->result,
(uint32_t) WidthOfScreen(screen),
(uint32_t) HeightOfScreen(screen),
0,
0,
0, 0, 0,
0,
0,
0,
0,
NULL,
FF_DISPLAY_TYPE_UNKNOWN,
@@ -301,12 +302,10 @@ static void xrandrHandleScreen(XrandrData* data, Screen* screen)
RootWindowOfScreen(screen),
(uint32_t) WidthMMOfScreen(screen),
(uint32_t) HeightMMOfScreen(screen),
"xlib-randr-screen"
);
"xlib-randr-screen");
}
const char* ffdsConnectXrandr(FFDisplayServerResult* result)
{
const char* ffdsConnectXrandr(FFDisplayServerResult* result) {
FF_LIBRARY_LOAD_MESSAGE(xrandr, "libXrandr" FF_LIBRARY_EXTENSION, 3)
FF_LIBRARY_LOAD_SYMBOL_MESSAGE(xrandr, XOpenDisplay)
@@ -330,33 +329,35 @@ const char* ffdsConnectXrandr(FFDisplayServerResult* result)
FF_LIBRARY_LOAD_SYMBOL_VAR_MESSAGE(xrandr, data, XRRFreeMonitors);
data.display = ffXOpenDisplay(NULL);
if(data.display == NULL)
if (data.display == NULL) {
return "XOpenDisplay() failed";
}
if(ScreenCount(data.display) > 0) {
if (ScreenCount(data.display) > 0) {
x11DetectWMFromEWMH(&data, result);
x11FetchServerVendor(&data, result);
}
data.result = result;
for(int i = 0; i < ScreenCount(data.display); i++)
for (int i = 0; i < ScreenCount(data.display); i++) {
xrandrHandleScreen(&data, ScreenOfDisplay(data.display, i));
}
ffXCloseDisplay(data.display);
//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)
// 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_WM_PROTOCOL_X11);
}
return NULL;
}
#else
const char* ffdsConnectXrandr(FFDisplayServerResult* result)
{
//Do nothing here. There are more x11 implementations to come.
const char* ffdsConnectXrandr(FFDisplayServerResult* result) {
// Do nothing here. There are more x11 implementations to come.
FF_UNUSED(result);
return "Fastfetch was compiled without libXrandr support";
}