c++qtgnomekde-plasma

Detect dark application style/theme of currently used desktop in Qt


In our Qt-based C++ application, I'm trying to automatically switch application styles based on whether the user has configured dark or bright theme.

I have figured out the notification of when a change happens (see below, for other's reference).

My main problem is the reliable detection of whether currently a dark or bright theme is used on linux (for windows see below); on XFCE, the check for QPalette color roles as mentioned in this answer works, but this does not work on Gnome and KDE Plasma for me (tested under both Ubuntu 22.04 and Fedora 36, my app built against Qt versions 6.5beta2 and 6.4.2, respectively); there the colors still seem to be taken from what I've set as XFCE theme on the same machine (and when starting xfce4-appearance-settings and changing the theme there, my app picks up the change). I would however like to adapt to the current desktop's dark mode setting.

So, my question is: How do I reliably detect application dark mode of the currently used desktop on Qt? I'm not averse to implementing a little custom platform-specific code if nothing is available directly in Qt, but it would be great if it would work without using additional libraries.

A note I saw for QApplication::setPalette I thought might be relevant here, namely "Some styles do not use the palette for all drawing, for instance, if they make use of native theme engines.", what are these all about? I did not see a link to a documentation for this feature, and a quick search for the term "qt native theme engine" also didn't seem to yield any useful results.

Since on Linux, some events are reliably triggered whenever a system theme change happens (see below), I suppose Qt can detect the theme change, it just doesn't expose data about it publicly?

Getting notified of theme changes

Detecting dark theme on Windows


Solution

  • For those looking for a simple isDarkMode function that works in Qt 6.4 and 6.5:

    #include <QGuiApplication>
    #include <QPalette>
    #include <QStyleHints>
    
    inline bool isDarkMode() {
    #if QT_VERSION >= QT_VERSION_CHECK(6, 5, 0)
      const auto scheme = QGuiApplication::styleHints()->colorScheme();
      return scheme == Qt::ColorScheme::Dark;
    #else
      const QPalette defaultPalette;
      const auto text = defaultPalette.color(QPalette::WindowText);
      const auto window = defaultPalette.color(QPalette::Window);
      return text.lightness() > window.lightness();
    #endif // QT_VERSION
    }