mirror of
https://github.com/fastfetch-cli/fastfetch.git
synced 2026-11-08 06:00:08 +01:00
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:
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+708
-718
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)) ®istry_listener, &data);
|
||||
data.ffwl_proxy_add_listener(registry, (void (**)(void)) ®istry_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);
|
||||
|
||||
+482
-498
File diff suppressed because it is too large
Load Diff
+94
-79
@@ -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
|
||||
|
||||
+146
-146
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user