From d10c5a4e2a5ca1a28f3cf2023bce41167c6a1a9c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Magnus=20Gro=C3=9F?= Date: Wed, 16 Feb 2022 23:08:43 +0100 Subject: [PATCH] Detect system dark mode preference changes without restart on Linux The new org.freedesktop.appearance.color-scheme key allows us to do this in a reliable way. Recently freedesktop standardized the system dark mode preference in a desktop environment independent way in the xdg-desktop-portal specification. The specification can be seen here: https://github.com/flatpak/xdg-desktop-portal/blob/d7a304a00697d7d608821253cd013f3b97ac0fb6/data/org.freedesktop.impl.portal.Settings.xml#L33-L45 KDE supports this since KDE Plasma 5.24 and Gnome supports this since Gnome 42. Relevant blog post: https://blogs.gnome.org/alexm/2021/10/04/dark-style-preference/ Fixes #7146 --- src/gui/osutils/nixutils/NixUtils.cpp | 23 +++++++++++++++++++++++ src/gui/osutils/nixutils/NixUtils.h | 14 ++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/gui/osutils/nixutils/NixUtils.cpp b/src/gui/osutils/nixutils/NixUtils.cpp index db5594ee2..d0fa84f3c 100644 --- a/src/gui/osutils/nixutils/NixUtils.cpp +++ b/src/gui/osutils/nixutils/NixUtils.cpp @@ -18,6 +18,7 @@ #include "NixUtils.h" #include +#include #include #include #include @@ -60,6 +61,15 @@ NixUtils::NixUtils(QObject* parent) { dpy = QX11Info::display(); rootWindow = QX11Info::appRootWindow(); + + // notify about system color scheme changes + QDBusConnection sessionBus = QDBusConnection::sessionBus(); + sessionBus.connect("org.freedesktop.portal.Desktop", + "/org/freedesktop/portal/desktop", + "org.freedesktop.portal.Settings", + "SettingChanged", + this, + SLOT(handleColorSchemeChanged(QString, QString, QDBusVariant))); } NixUtils::~NixUtils() @@ -68,6 +78,11 @@ NixUtils::~NixUtils() bool NixUtils::isDarkMode() const { + // prefer freedesktop "org.freedesktop.appearance color-scheme" setting + if (m_systemColorschemePref != ColorschemePref::PreferNone) { + return m_systemColorschemePref == ColorschemePref::PreferDark; + } + if (!qApp || !qApp->style()) { return false; } @@ -257,3 +272,11 @@ bool NixUtils::unregisterGlobalShortcut(const QString& name) m_globalShortcuts.remove(name); return true; } + +void NixUtils::handleColorSchemeChanged(QString ns, QString key, QDBusVariant value) +{ + if (ns == "org.freedesktop.appearance" && key == "color-scheme") { + m_systemColorschemePref = static_cast(value.variant().toInt()); + emit interfaceThemeChanged(); + } +} diff --git a/src/gui/osutils/nixutils/NixUtils.h b/src/gui/osutils/nixutils/NixUtils.h index ac5adb7c9..ed54f9b53 100644 --- a/src/gui/osutils/nixutils/NixUtils.h +++ b/src/gui/osutils/nixutils/NixUtils.h @@ -21,6 +21,7 @@ #include "gui/osutils/OSUtilsBase.h" #include #include +#include class NixUtils : public OSUtilsBase, QAbstractNativeEventFilter { @@ -48,6 +49,9 @@ public: return false; } +private slots: + void handleColorSchemeChanged(QString ns, QString key, QDBusVariant value); + private: explicit NixUtils(QObject* parent = nullptr); ~NixUtils() override; @@ -66,6 +70,16 @@ private: }; QHash> m_globalShortcuts; + // defined as per "org.freedesktop.appearance color-scheme" spec in + // https://github.com/flatpak/xdg-desktop-portal/blob/d7a304a00697d7d608821253cd013f3b97ac0fb6/data/org.freedesktop.impl.portal.Settings.xml#L33-L45 + enum ColorschemePref + { + PreferNone, + PreferDark, + PreferLight + }; + ColorschemePref m_systemColorschemePref = ColorschemePref::PreferNone; + Q_DISABLE_COPY(NixUtils) };