diff --git a/src/os/desktop.zig b/src/os/desktop.zig index 3a61e2eaa..c73f150e0 100644 --- a/src/os/desktop.zig +++ b/src/os/desktop.zig @@ -60,6 +60,9 @@ pub fn launchedFromDesktop() bool { }; } +/// The list of desktop environments that we detect. New Linux desktop +/// environments should only be added to this list if there's a specific reason +/// to differentiate between `gnome` and `other`. pub const DesktopEnvironment = enum { gnome, macos, @@ -67,21 +70,84 @@ pub const DesktopEnvironment = enum { windows, }; -/// Detect what desktop environment we are running under. This is mainly used on -/// Linux to enable or disable GTK client-side decorations but there may be more -/// uses in the future. +/// Detect what desktop environment we are running under. This is mainly used +/// on Linux to enable or disable certain features but there may be more uses in +/// the future. pub fn desktopEnvironment() DesktopEnvironment { return switch (comptime builtin.os.tag) { .macos => .macos, .windows => .windows, .linux => de: { if (@inComptime()) @compileError("Checking for the desktop environment on Linux must be done at runtime."); - // use $XDG_SESSION_DESKTOP to determine what DE we are using on Linux + + // Use $XDG_SESSION_DESKTOP to determine what DE we are using on Linux // https://www.freedesktop.org/software/systemd/man/latest/pam_systemd.html#desktop= - const de = posix.getenv("XDG_SESSION_DESKTOP") orelse break :de .other; - if (std.ascii.eqlIgnoreCase("gnome", de)) break :de .gnome; + if (posix.getenv("XDG_SESSION_DESKTOP")) |sd| { + if (std.ascii.eqlIgnoreCase("gnome", sd)) break :de .gnome; + if (std.ascii.eqlIgnoreCase("gnome-xorg", sd)) break :de .gnome; + } + + // If $XDG_SESSION_DESKTOP is not set, or doesn't match any known + // DE, check $XDG_CURRENT_DESKTOP. $XDG_CURRENT_DESKTOP is a + // colon-separated list of up to three desktop names, although we + // only look at the first. + // https://specifications.freedesktop.org/desktop-entry-spec/latest/recognized-keys.html + if (posix.getenv("XDG_CURRENT_DESKTOP")) |cd| { + var cd_it = std.mem.splitScalar(u8, cd, ':'); + const cd_first = cd_it.first(); + if (std.ascii.eqlIgnoreCase(cd_first, "gnome")) break :de .gnome; + } + break :de .other; }, else => .other, }; } + +test "desktop environment" { + const testing = std.testing; + + switch (builtin.os.tag) { + .macos => try testing.expectEqual(.macos, desktopEnvironment()), + .windows => try testing.expectEqual(.windows, desktopEnvironment()), + .linux => { + const getenv = std.posix.getenv; + const setenv = @import("env.zig").setenv; + const unsetenv = @import("env.zig").unsetenv; + + const xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP"); + defer if (xdg_current_desktop) |v| { + _ = setenv("XDG_CURRENT_DESKTOP", v); + } else { + _ = unsetenv("XDG_CURRENT_DESKTOP"); + }; + _ = unsetenv("XDG_CURRENT_DESKTOP"); + + const xdg_session_desktop = getenv("XDG_SESSION_DESKTOP"); + defer if (xdg_session_desktop) |v| { + _ = setenv("XDG_SESSION_DESKTOP", v); + } else { + _ = unsetenv("XDG_SESSION_DESKTOP"); + }; + _ = unsetenv("XDG_SESSION_DESKTOP"); + + _ = setenv("XDG_SESSION_DESKTOP", "gnome"); + try testing.expectEqual(.gnome, desktopEnvironment()); + _ = setenv("XDG_SESSION_DESKTOP", "gnome-xorg"); + try testing.expectEqual(.gnome, desktopEnvironment()); + _ = setenv("XDG_SESSION_DESKTOP", "foobar"); + try testing.expectEqual(.other, desktopEnvironment()); + + _ = unsetenv("XDG_SESSION_DESKTOP"); + try testing.expectEqual(.other, desktopEnvironment()); + + _ = setenv("XDG_CURRENT_DESKTOP", "GNOME"); + try testing.expectEqual(.gnome, desktopEnvironment()); + _ = setenv("XDG_CURRENT_DESKTOP", "FOOBAR"); + try testing.expectEqual(.other, desktopEnvironment()); + _ = unsetenv("XDG_CURRENT_DESKTOP"); + try testing.expectEqual(.other, desktopEnvironment()); + }, + else => try testing.expectEqual(.other, DesktopEnvironment()), + } +}