1

I have a few cron jobs which switch between light and dark themes automatically on my KDE system (for those interested, there's the lookandfeeltool where I simply switch between global light and dark themes (I had to define my own based on others with the alterations I wanted to make), or you can adjust the colours using plasma-theme-switcher (works on X and Wayland)). It works well, except I happen to rely on a handful of GTK applications, which don't respect these. The most significant of which are Chromium-based browsers / Electron apps such as Chrome itself, or VSCode.

Interestingly however, Firefox handles this perfectly, and responds to theme changes despite being a GTK application. It's also the only GTK application I run that seems to understand that I don't want to use the Nautilus file explorer, and instead uses Dolphin for all file prompts.

My question is how does Firefox do this, and why don't regular GTK apps handle this more gracefully?

The second part of my question is whether there is some sort of DBUS command I can fire which causes GTK applications to "check for theme changes", in order to allow my programs to respond to my scripts.

Thanks for any pointers

3
  • Maybe gdbus monitor and dbus-monitor can help May 31, 2023 at 19:19
  • Thanks to your suggestion, I found the DBUS events which are emitted when the theme changes, however am unsure how to use this information to cause other systems to respond to this. Would you be able to elaborate on how firefox is able to detect changes, but why other programs struggle?
    – J-Cake
    May 31, 2023 at 19:37
  • 1
    To further integrate Plasma settings on GTK applications, one may want to install gnome-settings-daemon, gsettings-desktop-schemas and gsettings-qt. This will offer proper Qt bindings for GTK. Ref: Arch Linux. Packages might be named differently on Debian/Ubuntu
    – kanehekili
    May 31, 2023 at 19:59

1 Answer 1

5
+50

I think that the answer is located in the file /widget/gtk/nsLookAndFeel.cpp.

Lines 1190-1200 in the latest stable code:


// It seems GTK doesn't have an API to query if the current theme is "light" or
// "dark", so we synthesize it from the CSS2 Window/WindowText colors instead,
// by comparing their luminosity.
static bool GetThemeIsDark() {
  GdkRGBA bg, fg;
  GtkStyleContext* style = GetStyleContext(MOZ_GTK_WINDOW);
  gtk_style_context_get_background_color(style, GTK_STATE_FLAG_NORMAL, &bg);
  gtk_style_context_get_color(style, GTK_STATE_FLAG_NORMAL, &fg);
  return RelativeLuminanceUtils::Compute(GDK_RGBA_TO_NS_RGBA(bg)) <
         RelativeLuminanceUtils::Compute(GDK_RGBA_TO_NS_RGBA(fg));
}

The function GDK_RGBA_TO_NS_RGBA() can be simplified as:

(Note that this is not the actual implementation)

#define GDK_RGBA_TO_NS_RGBA(c)                             \
  (                                                        \
      ((c.alpha * 255) << 24)                              \
    | ((c.blue * 255) << 16)                               \
    | ((c.green * 255) << 8)                               \
    | (c.red * 255)                                        \
  )

The functions gtk_style_context_get_background_color() and gtk_style_context_get_color() returns the background and foreground colors for a given state (respectively).

So apparently the answer is by checking which integer value is bigger, the background or the foreground, and deciding based on that whether the theme is dark or not.

1
  • 1
    Interesting. This approach seems to be a lot more reliable than what ever Chromium does. I've just been playing with themes, some of which allow Chromium to detect themes, most don't. Thank you sir
    – J-Cake
    Jun 4, 2023 at 10:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .