Skip to content

Add support for ColorScheme detection on Linux with the GTK backend.#517

Open
tosage05 wants to merge 1 commit intomoreSwift:mainfrom
tosage05:main
Open

Add support for ColorScheme detection on Linux with the GTK backend.#517
tosage05 wants to merge 1 commit intomoreSwift:mainfrom
tosage05:main

Conversation

@tosage05
Copy link
Copy Markdown

@tosage05 tosage05 commented Apr 9, 2026

Fixes #386

Does so by making use of org.freedesktop.appearance->color-scheme through dbus (method supported by most desktop environments), both at launch and while the scui app is running.

Copy link
Copy Markdown
Collaborator

@stackotter stackotter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for tackling this! This will be a nice QoL improvement for Linux users. I've requested some changes, and I'll test locally next

Comment thread Sources/GtkBackend/GtkBackend.swift Outdated
guard
let proxy = g_dbus_proxy_new_for_bus_sync(
G_BUS_TYPE_SESSION,
.init(0),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you may be able to use G_DBUS_PROXY_FLAGS_NONE here? Otherwise use an explicit initialiser such as gint(0) or guint(0) depending on the required underlying type

Comment thread Sources/GtkBackend/GtkBackend.swift Outdated
Comment on lines +477 to +486
let proxy = g_dbus_proxy_new_for_bus_sync(
G_BUS_TYPE_SESSION,
.init(0),
nil,
"org.freedesktop.portal.Desktop",
"/org/freedesktop/portal/desktop",
"org.freedesktop.portal.Settings",
nil,
nil
)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we instead initialise this proxy once when initialising the backend and then reuse it as necessary?

Comment thread Sources/GtkBackend/GtkBackend.swift Outdated
nil,
nil
)
else { return .light }
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As a formatting thing, we generally put the else body on its own line if the guard condition got its own line;

guard 
    ...
else {
    ...
}

Comment thread Sources/GtkBackend/GtkBackend.swift Outdated
guard
let v =
("('org.freedesktop.appearance', 'color-scheme')".withCString {
g_variant_parse(nil, $0, nil, nil, nil)
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that you can pass the string as an argument directly and Swift should do the necessary conversion to a c string (because the parameter is a const char *)

Comment thread Sources/GtkBackend/GtkBackend.swift Outdated
proxy,
"Read",
v,
.init(0),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible to use G_DBUS_CALL_FLAGS_NONE here?

Comment thread Sources/GtkBackend/GtkBackend.swift Outdated
"Read",
v,
.init(0),
.init(-1),
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explicitly cast this to gint instead of using .init (just a style choice I've made for the code base)


let colorSchemeId = g_variant_get_uint32(final)

if colorSchemeId == 1 {
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Link to https://github.com/flatpak/xdg-desktop-portal/blob/fae2c09a530eeef30af8d6401870fd5bae5d3989/data/org.freedesktop.portal.Settings.xml#L38 in a comment so that it's easy for people to look up these values

Comment thread Sources/GtkBackend/GtkBackend.swift Outdated
Comment thread Sources/GtkBackend/GtkBackend.swift Outdated
private func getPreferredColorScheme() -> ColorScheme {
#if os(Linux)
guard
let proxy = g_dbus_proxy_new_for_bus_sync(
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would you feel comfortable refactoring these two proxy implementations (proxy.call_sync and setting the signal handler) into a wrapper class in the Gtk target? I think it'd be great to have this bundled up in a reusable way so that we can easily fetch other settings too in future. For reference I'd recommend looking at the existing TextBuffer wrapper because it has an init, and a signal handler example.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[GTK] Support dark mode

2 participants