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: d7a304a006/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
This commit is contained in:
Magnus Groß 2022-02-16 23:08:43 +01:00 committed by Jonathan White
parent 58615d78bd
commit d10c5a4e2a
2 changed files with 37 additions and 0 deletions

View File

@ -18,6 +18,7 @@
#include "NixUtils.h" #include "NixUtils.h"
#include <QApplication> #include <QApplication>
#include <QDBusInterface>
#include <QDir> #include <QDir>
#include <QPointer> #include <QPointer>
#include <QStandardPaths> #include <QStandardPaths>
@ -60,6 +61,15 @@ NixUtils::NixUtils(QObject* parent)
{ {
dpy = QX11Info::display(); dpy = QX11Info::display();
rootWindow = QX11Info::appRootWindow(); 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() NixUtils::~NixUtils()
@ -68,6 +78,11 @@ NixUtils::~NixUtils()
bool NixUtils::isDarkMode() const 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()) { if (!qApp || !qApp->style()) {
return false; return false;
} }
@ -257,3 +272,11 @@ bool NixUtils::unregisterGlobalShortcut(const QString& name)
m_globalShortcuts.remove(name); m_globalShortcuts.remove(name);
return true; return true;
} }
void NixUtils::handleColorSchemeChanged(QString ns, QString key, QDBusVariant value)
{
if (ns == "org.freedesktop.appearance" && key == "color-scheme") {
m_systemColorschemePref = static_cast<ColorschemePref>(value.variant().toInt());
emit interfaceThemeChanged();
}
}

View File

@ -21,6 +21,7 @@
#include "gui/osutils/OSUtilsBase.h" #include "gui/osutils/OSUtilsBase.h"
#include <QAbstractNativeEventFilter> #include <QAbstractNativeEventFilter>
#include <QSharedPointer> #include <QSharedPointer>
#include <QtDBus/QDBusVariant>
class NixUtils : public OSUtilsBase, QAbstractNativeEventFilter class NixUtils : public OSUtilsBase, QAbstractNativeEventFilter
{ {
@ -48,6 +49,9 @@ public:
return false; return false;
} }
private slots:
void handleColorSchemeChanged(QString ns, QString key, QDBusVariant value);
private: private:
explicit NixUtils(QObject* parent = nullptr); explicit NixUtils(QObject* parent = nullptr);
~NixUtils() override; ~NixUtils() override;
@ -66,6 +70,16 @@ private:
}; };
QHash<QString, QSharedPointer<globalShortcut>> m_globalShortcuts; QHash<QString, QSharedPointer<globalShortcut>> 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) Q_DISABLE_COPY(NixUtils)
}; };