summaryrefslogtreecommitdiffstats
path: root/src/gui/platform/unix/qgenericunixthemes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui/platform/unix/qgenericunixthemes.cpp')
-rw-r--r--src/gui/platform/unix/qgenericunixthemes.cpp516
1 files changed, 506 insertions, 10 deletions
diff --git a/src/gui/platform/unix/qgenericunixthemes.cpp b/src/gui/platform/unix/qgenericunixthemes.cpp
index d90d5de098..ce729a74a3 100644
--- a/src/gui/platform/unix/qgenericunixthemes.cpp
+++ b/src/gui/platform/unix/qgenericunixthemes.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2022 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
#include "qgenericunixthemes_p.h"
@@ -33,6 +33,12 @@
#include <QDBusConnectionInterface>
#include <private/qdbusplatformmenu_p.h>
#include <private/qdbusmenubar_p.h>
+#include <private/qflatmap_p.h>
+#include <QJsonDocument>
+#include <QJsonArray>
+#include <QJsonObject>
+#include <QJsonValue>
+#include <QJsonParseError>
#endif
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
#include <private/qdbustrayicon_p.h>
@@ -41,6 +47,9 @@
#include <algorithm>
QT_BEGIN_NAMESPACE
+#ifndef QT_NO_DBUS
+Q_LOGGING_CATEGORY(lcQpaThemeDBus, "qt.qpa.theme.dbus")
+#endif
using namespace Qt::StringLiterals;
@@ -74,7 +83,7 @@ static bool isDBusTrayAvailable() {
static bool dbusTrayAvailableKnown = false;
if (!dbusTrayAvailableKnown) {
QDBusMenuConnection conn;
- if (conn.isStatusNotifierHostRegistered())
+ if (conn.isWatcherRegistered())
dbusTrayAvailable = true;
dbusTrayAvailableKnown = true;
qCDebug(qLcTray) << "D-Bus tray available:" << dbusTrayAvailable;
@@ -83,6 +92,20 @@ static bool isDBusTrayAvailable() {
}
#endif
+static QString mouseCursorTheme()
+{
+ static QString themeName = qEnvironmentVariable("XCURSOR_THEME");
+ return themeName;
+}
+
+static QSize mouseCursorSize()
+{
+ constexpr int defaultCursorSize = 24;
+ static const int xCursorSize = qEnvironmentVariableIntValue("XCURSOR_SIZE");
+ static const int s = xCursorSize > 0 ? xCursorSize : defaultCursorSize;
+ return QSize(s, s);
+}
+
#ifndef QT_NO_DBUS
static bool checkDBusGlobalMenuAvailable()
{
@@ -98,7 +121,288 @@ static bool isDBusGlobalMenuAvailable()
static bool dbusGlobalMenuAvailable = checkDBusGlobalMenuAvailable();
return dbusGlobalMenuAvailable;
}
+
+/*!
+ * \internal
+ * The QGenericUnixThemeDBusListener class listens to the SettingChanged DBus signal
+ * and translates it into combinations of the enums \c Provider and \c Setting.
+ * Upon construction, it logs success/failure of the DBus connection.
+ *
+ * The signal settingChanged delivers the normalized setting type and the new value as a string.
+ * It is emitted on known setting types only.
+ */
+
+class QGenericUnixThemeDBusListener : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ enum class Provider {
+ Kde,
+ Gtk,
+ Gnome,
+ };
+ Q_ENUM(Provider)
+
+ enum class Setting {
+ Theme,
+ ApplicationStyle,
+ ColorScheme,
+ };
+ Q_ENUM(Setting)
+
+ QGenericUnixThemeDBusListener();
+ QGenericUnixThemeDBusListener(const QString &service, const QString &path,
+ const QString &interface, const QString &signal);
+
+private Q_SLOTS:
+ void onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value);
+
+Q_SIGNALS:
+ void settingChanged(QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value);
+
+private:
+ struct DBusKey
+ {
+ QString location;
+ QString key;
+ DBusKey(const QString &loc, const QString &k) : location(loc), key(k) {};
+ bool operator<(const DBusKey &other) const
+ {
+ return location + key < other.location + other.key;
+ }
+ };
+
+ struct ChangeSignal
+ {
+ Provider provider;
+ Setting setting;
+ ChangeSignal(Provider p, Setting s) : provider(p), setting(s) {}
+ ChangeSignal() {}
+ };
+
+ // Json keys
+ static constexpr QLatin1StringView s_dbusLocation = QLatin1StringView("DBusLocation");
+ static constexpr QLatin1StringView s_dbusKey = QLatin1StringView("DBusKey");
+ static constexpr QLatin1StringView s_provider = QLatin1StringView("Provider");
+ static constexpr QLatin1StringView s_setting = QLatin1StringView("Setting");
+ static constexpr QLatin1StringView s_signals = QLatin1StringView("DbusSignals");
+ static constexpr QLatin1StringView s_root = QLatin1StringView("Qt.qpa.DBusSignals");
+
+ QFlatMap <DBusKey, ChangeSignal> m_signalMap;
+
+ void init(const QString &service, const QString &path,
+ const QString &interface, const QString &signal);
+
+ std::optional<ChangeSignal> findSignal(const QString &location, const QString &key) const;
+ void populateSignalMap();
+ void loadJson(const QString &fileName);
+ void saveJson(const QString &fileName) const;
+};
+
+QGenericUnixThemeDBusListener::QGenericUnixThemeDBusListener(const QString &service,
+ const QString &path, const QString &interface, const QString &signal)
+{
+ init (service, path, interface, signal);
+}
+
+QGenericUnixThemeDBusListener::QGenericUnixThemeDBusListener()
+{
+ static constexpr QLatin1StringView service("");
+ static constexpr QLatin1StringView path("/org/freedesktop/portal/desktop");
+ static constexpr QLatin1StringView interface("org.freedesktop.portal.Settings");
+ static constexpr QLatin1StringView signal("SettingChanged");
+
+ init (service, path, interface, signal);
+}
+
+void QGenericUnixThemeDBusListener::init(const QString &service, const QString &path,
+ const QString &interface, const QString &signal)
+{
+ QDBusConnection dbus = QDBusConnection::sessionBus();
+ const bool dBusRunning = dbus.isConnected();
+ bool dBusSignalConnected = false;
+#define LOG service << path << interface << signal;
+
+ if (dBusRunning) {
+ populateSignalMap();
+ qRegisterMetaType<QDBusVariant>();
+ dBusSignalConnected = dbus.connect(service, path, interface, signal, this,
+ SLOT(onSettingChanged(QString,QString,QDBusVariant)));
+ }
+
+ if (dBusSignalConnected) {
+ // Connection successful
+ qCDebug(lcQpaThemeDBus) << LOG;
+ } else {
+ if (dBusRunning) {
+ // DBus running, but connection failed
+ qCWarning(lcQpaThemeDBus) << "DBus connection failed:" << LOG;
+ } else {
+ // DBus not running
+ qCWarning(lcQpaThemeDBus) << "Session DBus not running.";
+ }
+ qCWarning(lcQpaThemeDBus) << "Application will not react to setting changes.\n"
+ << "Check your DBus installation.";
+ }
+#undef LOG
+}
+
+void QGenericUnixThemeDBusListener::loadJson(const QString &fileName)
+{
+ Q_ASSERT(!fileName.isEmpty());
+#define CHECK(cond, warning)\
+ if (!cond) {\
+ qCWarning(lcQpaThemeDBus) << fileName << warning << "Falling back to default.";\
+ return;\
+ }
+
+#define PARSE(var, enumeration, string)\
+ enumeration var;\
+ {\
+ bool success;\
+ const int val = QMetaEnum::fromType<enumeration>().keyToValue(string.toLatin1(), &success);\
+ CHECK(success, "Parse Error: Invalid value" << string << "for" << #var);\
+ var = static_cast<enumeration>(val);\
+ }
+
+ QFile file(fileName);
+ CHECK(file.exists(), fileName << "doesn't exist.");
+ CHECK(file.open(QIODevice::ReadOnly), "could not be opened for reading.");
+
+ QJsonParseError error;
+ QJsonDocument doc = QJsonDocument::fromJson(file.readAll(), &error);
+ CHECK((error.error == QJsonParseError::NoError), error.errorString());
+ CHECK(doc.isObject(), "Parse Error: Expected root object" << s_root);
+
+ const QJsonObject &root = doc.object();
+ CHECK(root.contains(s_root), "Parse Error: Expected root object" << s_root);
+ CHECK(root[s_root][s_signals].isArray(), "Parse Error: Expected array" << s_signals);
+
+ const QJsonArray &sigs = root[s_root][s_signals].toArray();
+ CHECK((sigs.count() > 0), "Parse Error: Found empty array" << s_signals);
+
+ for (auto sig = sigs.constBegin(); sig != sigs.constEnd(); ++sig) {
+ CHECK(sig->isObject(), "Parse Error: Expected object array" << s_signals);
+ const QJsonObject &obj = sig->toObject();
+ CHECK(obj.contains(s_dbusLocation), "Parse Error: Expected key" << s_dbusLocation);
+ CHECK(obj.contains(s_dbusKey), "Parse Error: Expected key" << s_dbusKey);
+ CHECK(obj.contains(s_provider), "Parse Error: Expected key" << s_provider);
+ CHECK(obj.contains(s_setting), "Parse Error: Expected key" << s_setting);
+ const QString &location = obj[s_dbusLocation].toString();
+ const QString &key = obj[s_dbusKey].toString();
+ const QString &providerString = obj[s_provider].toString();
+ const QString &settingString = obj[s_setting].toString();
+ PARSE(provider, Provider, providerString);
+ PARSE(setting, Setting, settingString);
+ const DBusKey dkey(location, key);
+ CHECK (!m_signalMap.contains(dkey), "Duplicate key" << location << key);
+ m_signalMap.insert(dkey, ChangeSignal(provider, setting));
+ }
+#undef PARSE
+#undef CHECK
+
+ if (m_signalMap.count() > 0)
+ qCInfo(lcQpaThemeDBus) << "Successfully imported" << fileName;
+ else
+ qCWarning(lcQpaThemeDBus) << "No data imported from" << fileName << "falling back to default.";
+
+#ifdef QT_DEBUG
+ const int count = m_signalMap.count();
+ if (count == 0)
+ return;
+
+ qCDebug(lcQpaThemeDBus) << "Listening to" << count << "signals:";
+ for (auto it = m_signalMap.constBegin(); it != m_signalMap.constEnd(); ++it) {
+ qDebug() << it.key().key << it.key().location << "mapped to"
+ << it.value().provider << it.value().setting;
+ }
+
#endif
+}
+
+void QGenericUnixThemeDBusListener::saveJson(const QString &fileName) const
+{
+ Q_ASSERT(!m_signalMap.isEmpty());
+ Q_ASSERT(!fileName.isEmpty());
+ QFile file(fileName);
+ if (!file.open(QIODevice::WriteOnly)) {
+ qCWarning(lcQpaThemeDBus) << fileName << "could not be opened for writing.";
+ return;
+ }
+
+ QJsonArray sigs;
+ for (auto sig = m_signalMap.constBegin(); sig != m_signalMap.constEnd(); ++sig) {
+ const DBusKey &dkey = sig.key();
+ const ChangeSignal &csig = sig.value();
+ QJsonObject obj;
+ obj[s_dbusLocation] = dkey.location;
+ obj[s_dbusKey] = dkey.key;
+ obj[s_provider] = QLatin1StringView(QMetaEnum::fromType<Provider>()
+ .valueToKey(static_cast<int>(csig.provider)));
+ obj[s_setting] = QLatin1StringView(QMetaEnum::fromType<Setting>()
+ .valueToKey(static_cast<int>(csig.setting)));
+ sigs.append(obj);
+ }
+ QJsonObject obj;
+ obj[s_signals] = sigs;
+ QJsonObject root;
+ root[s_root] = obj;
+ QJsonDocument doc(root);
+ file.write(doc.toJson());
+ file.close();
+}
+
+void QGenericUnixThemeDBusListener::populateSignalMap()
+{
+ m_signalMap.clear();
+ const QString &loadJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS");
+ if (!loadJsonFile.isEmpty())
+ loadJson(loadJsonFile);
+ if (!m_signalMap.isEmpty())
+ return;
+
+ m_signalMap.insert(DBusKey("org.kde.kdeglobals.KDE"_L1, "widgetStyle"_L1),
+ ChangeSignal(Provider::Kde, Setting::ApplicationStyle));
+
+ m_signalMap.insert(DBusKey("org.kde.kdeglobals.General"_L1, "ColorScheme"_L1),
+ ChangeSignal(Provider::Kde, Setting::Theme));
+
+ m_signalMap.insert(DBusKey("org.gnome.desktop.interface"_L1, "gtk-theme"_L1),
+ ChangeSignal(Provider::Gtk, Setting::Theme));
+
+ m_signalMap.insert(DBusKey("org.freedesktop.appearance"_L1, "color-scheme"_L1),
+ ChangeSignal(Provider::Gnome, Setting::ColorScheme));
+
+ const QString &saveJsonFile = qEnvironmentVariable("QT_QPA_DBUS_SIGNALS_SAVE");
+ if (!saveJsonFile.isEmpty())
+ saveJson(saveJsonFile);
+}
+
+std::optional<QGenericUnixThemeDBusListener::ChangeSignal>
+ QGenericUnixThemeDBusListener::findSignal(const QString &location, const QString &key) const
+{
+ const DBusKey dkey(location, key);
+ std::optional<QGenericUnixThemeDBusListener::ChangeSignal> ret;
+ if (m_signalMap.contains(dkey))
+ ret.emplace(m_signalMap.value(dkey));
+
+ return ret;
+}
+
+void QGenericUnixThemeDBusListener::onSettingChanged(const QString &location, const QString &key, const QDBusVariant &value)
+{
+ auto sig = findSignal(location, key);
+ if (!sig.has_value())
+ return;
+
+ emit settingChanged(sig.value().provider, sig.value().setting, value.variant().toString());
+}
+
+#endif //QT_NO_DBUS
class QGenericUnixThemePrivate : public QPlatformThemePrivate
{
@@ -198,6 +502,10 @@ QVariant QGenericUnixTheme::themeHint(ThemeHint hint) const
return QVariant(int(X11KeyboardScheme));
case QPlatformTheme::UiEffects:
return QVariant(int(HoverEffect));
+ case QPlatformTheme::MouseCursorTheme:
+ return QVariant(mouseCursorTheme());
+ case QPlatformTheme::MouseCursorSize:
+ return QVariant(mouseCursorSize());
default:
break;
}
@@ -231,11 +539,9 @@ static QIcon xdgFileIcon(const QFileInfo &fileInfo)
#if QT_CONFIG(settings)
class QKdeThemePrivate : public QPlatformThemePrivate
{
+
public:
- QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion)
- : kdeDirs(kdeDirs)
- , kdeVersion(kdeVersion)
- { }
+ QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion);
static QString kdeGlobals(const QString &kdeDir, int kdeVersion)
{
@@ -266,8 +572,66 @@ public:
int startDragDist = 10;
int startDragTime = 500;
int cursorBlinkRate = 1000;
+ Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
+ void updateColorScheme(const QString &themeName);
+
+#ifndef QT_NO_DBUS
+private:
+ std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
+ bool initDbus();
+ void settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value);
+#endif // QT_NO_DBUS
};
+#ifndef QT_NO_DBUS
+void QKdeThemePrivate::settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value)
+{
+ if (provider != QGenericUnixThemeDBusListener::Provider::Kde)
+ return;
+
+ switch (setting) {
+ case QGenericUnixThemeDBusListener::Setting::ColorScheme:
+ qCDebug(lcQpaThemeDBus) << "KDE color theme changed to:" << value;
+ break;
+ case QGenericUnixThemeDBusListener::Setting::Theme:
+ qCDebug(lcQpaThemeDBus) << "KDE global theme changed to:" << value;
+ break;
+ case QGenericUnixThemeDBusListener::Setting::ApplicationStyle:
+ qCDebug(lcQpaThemeDBus) << "KDE application style changed to:" << value;
+ break;
+ }
+
+ refresh();
+}
+
+bool QKdeThemePrivate::initDbus()
+{
+ dbus.reset(new QGenericUnixThemeDBusListener());
+ Q_ASSERT(dbus);
+
+ // Wrap slot in a lambda to avoid inheriting QKdeThemePrivate from QObject
+ auto wrapper = [this](QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value) {
+ settingChangedHandler(provider, setting, value);
+ };
+
+ return QObject::connect(dbus.get(), &QGenericUnixThemeDBusListener::settingChanged, dbus.get(), wrapper);
+}
+#endif // QT_NO_DBUS
+
+QKdeThemePrivate::QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion)
+ : kdeDirs(kdeDirs), kdeVersion(kdeVersion)
+{
+#ifndef QT_NO_DBUS
+ initDbus();
+#endif // QT_NO_DBUS
+}
+
void QKdeThemePrivate::refresh()
{
resources.clear();
@@ -297,6 +661,14 @@ void QKdeThemePrivate::refresh()
styleNames.push_front(style);
}
+ const QVariant colorScheme = readKdeSetting(QStringLiteral("ColorScheme"), kdeDirs,
+ kdeVersion, kdeSettings);
+
+ if (colorScheme.isValid())
+ updateColorScheme(colorScheme.toString());
+ else
+ m_colorScheme = Qt::ColorScheme::Unknown;
+
const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeVersion, kdeSettings);
if (singleClickValue.isValid())
singleClick = singleClickValue.toBool();
@@ -368,6 +740,8 @@ void QKdeThemePrivate::refresh()
if (QFont *toolBarFont = kdeFont(readKdeSetting(QStringLiteral("toolBarFont"), kdeDirs, kdeVersion, kdeSettings)))
resources.fonts[QPlatformTheme::ToolButtonFont] = toolBarFont;
+ QWindowSystemInterface::handleThemeChange();
+
qCDebug(lcQpaFonts) << "default fonts: system" << resources.fonts[QPlatformTheme::SystemFont]
<< "fixed" << resources.fonts[QPlatformTheme::FixedFont];
qDeleteAll(kdeSettings);
@@ -556,6 +930,10 @@ QVariant QKdeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
return QVariant(d->cursorBlinkRate);
case QPlatformTheme::UiEffects:
return QVariant(int(HoverEffect));
+ case QPlatformTheme::MouseCursorTheme:
+ return QVariant(mouseCursorTheme());
+ case QPlatformTheme::MouseCursorSize:
+ return QVariant(mouseCursorSize());
default:
break;
}
@@ -572,6 +950,48 @@ QIcon QKdeTheme::fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions
#endif
}
+Qt::ColorScheme QKdeTheme::colorScheme() const
+{
+ return d_func()->m_colorScheme;
+}
+
+/*!
+ \internal
+ \brief QKdeTheme::setColorScheme - guess and set appearance for unix themes.
+ KDE themes do not have an appearance property.
+ The key words "dark" or "light" should be part of the theme name.
+ This is, however, not a mandatory convention.
+
+ If \param themeName contains a key word, the respective appearance is set.
+ If it doesn't, the appearance is heuristically determined by comparing text and base color
+ of the system palette.
+ */
+void QKdeThemePrivate::updateColorScheme(const QString &themeName)
+{
+ if (themeName.contains(QLatin1StringView("light"), Qt::CaseInsensitive)) {
+ m_colorScheme = Qt::ColorScheme::Light;
+ return;
+ }
+ if (themeName.contains(QLatin1StringView("dark"), Qt::CaseInsensitive)) {
+ m_colorScheme = Qt::ColorScheme::Dark;
+ return;
+ }
+
+ if (systemPalette) {
+ if (systemPalette->text().color().lightness() < systemPalette->base().color().lightness()) {
+ m_colorScheme = Qt::ColorScheme::Light;
+ return;
+ }
+ if (systemPalette->text().color().lightness() > systemPalette->base().color().lightness()) {
+ m_colorScheme = Qt::ColorScheme::Dark;
+ return;
+ }
+ }
+
+ m_colorScheme = Qt::ColorScheme::Unknown;
+}
+
+
const QPalette *QKdeTheme::palette(Palette type) const
{
Q_D(const QKdeTheme);
@@ -672,8 +1092,8 @@ const char *QGnomeTheme::name = "gnome";
class QGnomeThemePrivate : public QPlatformThemePrivate
{
public:
- QGnomeThemePrivate() : systemFont(nullptr), fixedFont(nullptr) {}
- ~QGnomeThemePrivate() { delete systemFont; delete fixedFont; }
+ QGnomeThemePrivate();
+ ~QGnomeThemePrivate();
void configureFonts(const QString &gtkFontName) const
{
@@ -688,10 +1108,70 @@ public:
qCDebug(lcQpaFonts) << "default fonts: system" << systemFont << "fixed" << fixedFont;
}
- mutable QFont *systemFont;
- mutable QFont *fixedFont;
+ mutable QFont *systemFont = nullptr;
+ mutable QFont *fixedFont = nullptr;
+
+#ifndef QT_NO_DBUS
+ Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
+private:
+ std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
+ bool initDbus();
+ void updateColorScheme(const QString &themeName);
+#endif // QT_NO_DBUS
};
+QGnomeThemePrivate::QGnomeThemePrivate()
+{
+#ifndef QT_NO_DBUS
+ initDbus();
+#endif // QT_NO_DBUS
+}
+QGnomeThemePrivate::~QGnomeThemePrivate()
+{
+ if (systemFont)
+ delete systemFont;
+ if (fixedFont)
+ delete fixedFont;
+}
+
+#ifndef QT_NO_DBUS
+bool QGnomeThemePrivate::initDbus()
+{
+ dbus.reset(new QGenericUnixThemeDBusListener());
+ Q_ASSERT(dbus);
+
+ // Wrap slot in a lambda to avoid inheriting QGnomeThemePrivate from QObject
+ auto wrapper = [this](QGenericUnixThemeDBusListener::Provider provider,
+ QGenericUnixThemeDBusListener::Setting setting,
+ const QString &value) {
+ if (provider != QGenericUnixThemeDBusListener::Provider::Gnome
+ && provider != QGenericUnixThemeDBusListener::Provider::Gtk) {
+ return;
+ }
+
+ if (setting == QGenericUnixThemeDBusListener::Setting::Theme)
+ updateColorScheme(value);
+ };
+
+ return QObject::connect(dbus.get(), &QGenericUnixThemeDBusListener::settingChanged, dbus.get(), wrapper);
+}
+
+void QGnomeThemePrivate::updateColorScheme(const QString &themeName)
+{
+ const auto oldColorScheme = m_colorScheme;
+ if (themeName.contains(QLatin1StringView("light"), Qt::CaseInsensitive)) {
+ m_colorScheme = Qt::ColorScheme::Light;
+ } else if (themeName.contains(QLatin1StringView("dark"), Qt::CaseInsensitive)) {
+ m_colorScheme = Qt::ColorScheme::Dark;
+ } else {
+ m_colorScheme = Qt::ColorScheme::Unknown;
+ }
+
+ if (oldColorScheme != m_colorScheme)
+ QWindowSystemInterface::handleThemeChange();
+}
+#endif // QT_NO_DBUS
+
QGnomeTheme::QGnomeTheme()
: QPlatformTheme(new QGnomeThemePrivate())
{
@@ -726,6 +1206,12 @@ QVariant QGnomeTheme::themeHint(QPlatformTheme::ThemeHint hint) const
case QPlatformTheme::ButtonPressKeys:
return QVariant::fromValue(
QList<Qt::Key>({ Qt::Key_Space, Qt::Key_Return, Qt::Key_Enter, Qt::Key_Select }));
+ case QPlatformTheme::PreselectFirstFileInDirectory:
+ return true;
+ case QPlatformTheme::MouseCursorTheme:
+ return QVariant(mouseCursorTheme());
+ case QPlatformTheme::MouseCursorSize:
+ return QVariant(mouseCursorSize());
default:
break;
}
@@ -769,6 +1255,12 @@ QPlatformMenuBar *QGnomeTheme::createPlatformMenuBar() const
return new QDBusMenuBar();
return nullptr;
}
+
+Qt::ColorScheme QGnomeTheme::colorScheme() const
+{
+ return d_func()->m_colorScheme;
+}
+
#endif
#if !defined(QT_NO_DBUS) && !defined(QT_NO_SYSTEMTRAYICON)
@@ -853,3 +1345,7 @@ QStringList QGenericUnixTheme::themeNames()
}
QT_END_NAMESPACE
+
+#ifndef QT_NO_DBUS
+#include "qgenericunixthemes.moc"
+#endif // QT_NO_DBUS