Skip to content

Commit d628bde

Browse files
committed
Display (Linux): support primary display detection for GNOME & Cinnamon
1 parent f9ce2fa commit d628bde

File tree

2 files changed

+74
-4
lines changed

2 files changed

+74
-4
lines changed

src/detection/displayserver/linux/wayland/global-output.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ static struct zxdg_output_v1_listener zxdgOutputListener = {
6565
.logical_position = (void*) stubListener,
6666
.logical_size = handleXdgLogicalSize,
6767
.done = (void*) stubListener,
68-
.name = (void*) stubListener,
69-
.description = (void*) stubListener,
68+
.name = (void*) ffWaylandOutputNameListener,
69+
.description = (void*) ffWaylandOutputDescriptionListener,
7070
};
7171

7272
void ffWaylandHandleGlobalOutput(WaylandData* wldata, struct wl_registry* registry, uint32_t name, uint32_t version)

src/detection/displayserver/linux/wayland/wayland.c

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,30 +9,35 @@
99

1010
#include <sys/socket.h>
1111

12+
#include "common/properties.h"
13+
1214
#include "wayland.h"
1315
#include "wlr-output-management-unstable-v1-client-protocol.h"
1416
#include "kde-output-device-v2-client-protocol.h"
1517
#include "kde-output-order-v1-client-protocol.h"
1618
#include "xdg-output-unstable-v1-client-protocol.h"
1719

1820
#ifndef __FreeBSD__
19-
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
21+
static bool waylandDetectWM(int fd, FFDisplayServerResult* result)
2022
{
2123
struct ucred ucred;
2224
socklen_t len = sizeof(struct ucred);
2325
if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &len) == -1)
24-
return;
26+
return false;
2527

2628
FF_STRBUF_AUTO_DESTROY procPath = ffStrbufCreate();
2729
ffStrbufAppendF(&procPath, "/proc/%d/cmdline", ucred.pid); //We check the cmdline for the process name, because it is not trimmed.
2830
ffReadFileBuffer(procPath.chars, &result->wmProcessName);
2931
ffStrbufSubstrBeforeFirstC(&result->wmProcessName, '\0'); //Trim the arguments
3032
ffStrbufSubstrAfterLastC(&result->wmProcessName, '/'); //Trim the path
33+
puts(result->wmProcessName.chars);
34+
return true;
3135
}
3236
#else
3337
static void waylandDetectWM(int fd, FFDisplayServerResult* result)
3438
{
3539
FF_UNUSED(fd, result);
40+
return false;
3641
}
3742
#endif
3843

@@ -112,6 +117,67 @@ bool detectWayland(FFDisplayServerResult* result)
112117
data.ffwl_proxy_destroy(registry);
113118
ffwl_display_disconnect(data.display);
114119

120+
if(data.primaryDisplayId == 0 && result->wmProcessName.length > 0)
121+
{
122+
const char* fileName = ffStrbufEqualS(&result->wmProcessName, "gnome-shell")
123+
? "monitors.xml"
124+
: ffStrbufEqualS(&result->wmProcessName, "cinnamon")
125+
? "cinnamon-monitors.xml"
126+
: NULL;
127+
if (fileName)
128+
{
129+
FF_STRBUF_AUTO_DESTROY monitorsXml = ffStrbufCreate();
130+
FF_LIST_FOR_EACH(FFstrbuf, basePath, instance.state.platform.configDirs)
131+
{
132+
char path[1024];
133+
snprintf(path, sizeof(path) - 1, "%s%s", basePath->chars, fileName);
134+
if (ffReadFileBuffer(path, &monitorsXml))
135+
break;
136+
}
137+
if (monitorsXml.length)
138+
{
139+
// <monitors version="2">
140+
// <configuration>
141+
// <logicalmonitor>
142+
// <x>0</x>
143+
// <y>0</y>
144+
// <scale>1.7489879131317139</scale>
145+
// <primary>yes</primary>
146+
// <monitor>
147+
// <monitorspec>
148+
// <connector>Virtual-1</connector>
149+
// <vendor>unknown</vendor>
150+
// <product>unknown</product>
151+
// <serial>unknown</serial>
152+
// </monitorspec>
153+
// <mode>
154+
// <width>3456</width>
155+
// <height>2160</height>
156+
// <rate>60.000068664550781</rate>
157+
// </mode>
158+
// </monitor>
159+
// </logicalmonitor>
160+
// </configuration>
161+
// </monitors>
162+
uint32_t start = ffStrbufFirstIndexS(&monitorsXml, "<primary>yes</primary>");
163+
if (start < monitorsXml.length)
164+
{
165+
start = ffStrbufNextIndexS(&monitorsXml, start, "<connector>");
166+
if (start < monitorsXml.length)
167+
{
168+
uint32_t end = ffStrbufNextIndexS(&monitorsXml, start, "</connector>");
169+
if (end < monitorsXml.length)
170+
{
171+
ffStrbufSubstrBefore(&monitorsXml, end);
172+
const char* name = monitorsXml.chars + start + strlen("<connector>");
173+
data.primaryDisplayId = ffWaylandGenerateIdFromName(name);
174+
}
175+
}
176+
}
177+
}
178+
}
179+
}
180+
115181
if(data.primaryDisplayId)
116182
{
117183
FF_LIST_FOR_EACH(FFDisplayResult, d, data.result->displays)
@@ -134,6 +200,8 @@ bool detectWayland(FFDisplayServerResult* result)
134200
void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const char *name)
135201
{
136202
WaylandDisplay* display = data;
203+
if (display->id) return;
204+
137205
if(ffStrStartsWith(name, "eDP-"))
138206
display->type = FF_DISPLAY_TYPE_BUILTIN;
139207
else if(ffStrStartsWith(name, "HDMI-"))
@@ -147,6 +215,8 @@ void ffWaylandOutputNameListener(void* data, FF_MAYBE_UNUSED void* output, const
147215
void ffWaylandOutputDescriptionListener(void* data, FF_MAYBE_UNUSED void* output, const char* description)
148216
{
149217
WaylandDisplay* display = data;
218+
if (display->description.length) return;
219+
150220
while (*description == ' ') ++description;
151221
if (!ffStrEquals(description, "Unknown Display") && !ffStrContains(description, "(null)"))
152222
ffStrbufAppendS(&display->description, description);

0 commit comments

Comments
 (0)