ohmu
·
2026-10-15
1#include "displayserver_linux.h"
2#include "common/io.h"
3#include "common/strutil.h"
4
5#ifdef __FreeBSD__
6 #include "common/settings.h"
7#endif
8
9static void getWMProtocolNameFromEnv(FFDisplayServerResult* result) {
10 const char* env = getenv("XDG_SESSION_TYPE");
11 if (env) {
12 if (ffStrEqualsIgnCase(env, "wayland")) {
13 ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
14 } else if (ffStrEqualsIgnCase(env, "x11") || ffStrEqualsIgnCase(env, "xorg")) {
15 ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
16 } else if (ffStrEqualsIgnCase(env, "tty")) {
17 ffStrbufSetS(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
18 } else {
19 ffStrbufSetS(&result->wmProtocolName, env);
20 }
21
22 return;
23 }
24
25 if (getenv("WAYLAND_DISPLAY") != nullptr || getenv("WAYLAND_SOCKET") != nullptr) {
26 ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_WAYLAND);
27 return;
28 }
29
30 if (getenv("DISPLAY") != nullptr) // XWayland also set this
31 {
32 ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_X11);
33 return;
34 }
35
36 env = getenv("TERM");
37 if (ffStrSet(env) && ffStrEqualsIgnCase(env, "linux")) {
38 ffStrbufSetStatic(&result->wmProtocolName, FF_WM_PROTOCOL_TTY);
39 return;
40 }
41}
42
43void ffConnectDisplayServerImpl(FFDisplayServerResult* ds) {
44 if (instance.config.general.dsForceDrm == FF_DS_FORCE_DRM_TYPE_FALSE) {
45 // We try wayland as our preferred display server, as it supports the most features.
46 // This method can't detect the name of our WM / DE
47 ffdsConnectWayland(ds);
48
49 // Try the x11 libs, from most feature rich to least.
50 // We use the display list to detect if a connection is needed.
51 // They respect wmProtocolName, and only detect display if it is set.
52 if (ds->displays.length == 0) {
53 ffdsConnectXcbRandr(ds);
54 }
55
56 if (ds->displays.length == 0) {
57 ffdsConnectXrandr(ds);
58 }
59 }
60
61 // This display detection method is display server independent.
62 // Use it if all connections failed
63 if (ds->displays.length == 0) {
64 ffdsConnectDrm(ds);
65 }
66
67#ifdef __FreeBSD__
68 if (ds->displays.length == 0) {
69 FF_STRBUF_AUTO_DESTROY buf = ffStrbufCreate();
70 if (ffSettingsGetFreeBSDKenv("screen.width", &buf)) {
71 uint32_t width = (uint32_t) ffStrbufToUInt(&buf, 0);
72 if (width) {
73 ffStrbufClear(&buf);
74 if (ffSettingsGetFreeBSDKenv("screen.height", &buf)) {
75 uint32_t height = (uint32_t) ffStrbufToUInt(&buf, 0);
76 ffdsAppendDisplay(ds, width, height, 0, 0, 0, 0, 0, 0, nullptr, FF_DISPLAY_TYPE_UNKNOWN, false, 0, 0, 0, "kenv");
77 }
78 }
79 }
80 }
81#endif
82
83 if (ds->wmProtocolName.length == 0) {
84 getWMProtocolNameFromEnv(ds);
85 }
86
87 if (!ffStrbufEqualS(&ds->wmProtocolName, FF_WM_PROTOCOL_TTY)) {
88 // This fills in missing information about WM / DE by using env vars and iterating processes
89 ffdsDetectWMDE(ds);
90 }
91}