From 330eb299b7d28dfc93c54df5402c72524b22b730 Mon Sep 17 00:00:00 2001
From: Matthieu Gallien <matthieu.gallien@nextcloud.com>
Date: Tue, 12 Nov 2024 14:52:04 +0100
Subject: [PATCH] on Windows 10 follow color scheme changes and apply them

Signed-off-by: Matthieu Gallien <matthieu.gallien@nextcloud.com>
---
 src/gui/application.cpp | 23 +++++------------------
 src/gui/application.h   |  1 +
 src/libsync/theme.cpp   | 22 ++++++++++++----------
 src/libsync/theme.h     |  1 +
 4 files changed, 19 insertions(+), 28 deletions(-)

diff --git a/src/gui/application.cpp b/src/gui/application.cpp
index f05f222a351bf..fb34647618350 100644
--- a/src/gui/application.cpp
+++ b/src/gui/application.cpp
@@ -126,21 +126,6 @@ namespace {
 
 // ----------------------------------------------------------------------------------
 
-#ifdef Q_OS_WIN
-class WindowsNativeEventFilter : public QAbstractNativeEventFilter {
-public:
-    bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *result) override {
-        const auto msg = static_cast<MSG *>(message);
-        if(msg->message == WM_SYSCOLORCHANGE || msg->message == WM_SETTINGCHANGE) {
-            if (const auto ptr = qobject_cast<QGuiApplication *>(QGuiApplication::instance())) {
-                emit ptr->paletteChanged(ptr->palette());
-            }
-        }
-        return false;
-    }
-};
-#endif
-
 bool Application::configVersionMigration()
 {
     QStringList deleteKeys, ignoreKeys;
@@ -237,9 +222,6 @@ Application::Application(int &argc, char **argv)
     // Ensure OpenSSL config file is only loaded from app directory
     QString opensslConf = QCoreApplication::applicationDirPath() + QString("/openssl.cnf");
     qputenv("OPENSSL_CONF", opensslConf.toLocal8Bit());
-
-    // Set up event listener for Windows theme changing
-    installNativeEventFilter(new WindowsNativeEventFilter());
 #endif
 
     // TODO: Can't set this without breaking current config paths
@@ -384,6 +366,8 @@ Application::Application(int &argc, char **argv)
 
     _theme->setSystrayUseMonoIcons(ConfigFile().monoIcons());
     connect(_theme, &Theme::systrayUseMonoIconsChanged, this, &Application::slotUseMonoIconsChanged);
+    connect(this, &Application::systemPaletteChanged,
+            _theme, &Theme::systemPaletteHasChanged);
 
 #if defined(Q_OS_WIN)
     _shellExtensionsServer.reset(new ShellExtensionsServer);
@@ -1127,6 +1111,9 @@ bool Application::event(QEvent *event)
             qCInfo(lcApplication) << errorParsingLocalFileEditingUrl;
             showHint(errorParsingLocalFileEditingUrl.toStdString());
         }
+    } else if (event->type() == QEvent::ApplicationPaletteChange) {
+        qCInfo(lcApplication) << "application palette changed";
+        emit systemPaletteChanged();
     }
     return SharedTools::QtSingleApplication::event(event);
 }
diff --git a/src/gui/application.h b/src/gui/application.h
index 9ec6e121bda39..f2c41fe453768 100644
--- a/src/gui/application.h
+++ b/src/gui/application.h
@@ -96,6 +96,7 @@ public slots:
     void folderRemoved();
     void folderStateChanged(OCC::Folder *);
     void isShowingSettingsDialog();
+    void systemPaletteChanged();
 
 protected slots:
     void slotParseMessage(const QString &, QObject *);
diff --git a/src/libsync/theme.cpp b/src/libsync/theme.cpp
index 2bb08cbf11275..c527f4eb2cef6 100644
--- a/src/libsync/theme.cpp
+++ b/src/libsync/theme.cpp
@@ -969,16 +969,8 @@ QColor Theme::defaultColor()
 void Theme::connectToPaletteSignal()
 {
     if (!_paletteSignalsConnected) {
-        if (const auto ptr = qobject_cast<QGuiApplication *>(QGuiApplication::instance())) {
-#ifdef Q_OS_WIN
-            // Windows 10 does not have proper dark mode support via Qt 6 so hack detection
-            if (!isWindows11OrGreater()) {
-                connect(ptr, &QGuiApplication::paletteChanged, this, &Theme::darkModeChanged);
-            } else
-#endif
-            {
-                connect(ptr->styleHints(), &QStyleHints::colorSchemeChanged, this, &Theme::darkModeChanged);
-            }
+        if (const auto ptr = qobject_cast<QGuiApplication*>(qApp)) {
+            connect(ptr->styleHints(), &QStyleHints::colorSchemeChanged, this, &Theme::darkModeChanged);
             _paletteSignalsConnected = true;
         }
     }
@@ -1088,4 +1080,14 @@ void Theme::setStartLoginFlowAutomatically(bool startLoginFlowAuto)
     }
 }
 
+void Theme::systemPaletteHasChanged()
+{
+    qCInfo(lcTheme()) << "system palette changed";
+#ifdef Q_OS_WIN
+    if (darkMode() && !isWindows11OrGreater()) {
+        qApp->setPalette(reserveDarkPalette);
+    }
+#endif
+}
+
 } // end namespace client
diff --git a/src/libsync/theme.h b/src/libsync/theme.h
index 37fea143ac8d9..a7e817de15ca9 100644
--- a/src/libsync/theme.h
+++ b/src/libsync/theme.h
@@ -609,6 +609,7 @@ public slots:
     void setForceOverrideServerUrl(bool forceOverride);
     void setVfsEnabled(bool enabled);
     void setStartLoginFlowAutomatically(bool startLoginFlowAuto);
+    void systemPaletteHasChanged();
 
 protected:
 #ifndef TOKEN_AUTH_ONLY