From 956b7f7da52fa3fae2e66187d7673528202e5cf6 Mon Sep 17 00:00:00 2001
From: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com>
Date: Wed, 16 Nov 2022 16:02:59 -0300
Subject: [PATCH] windows: add support for system theme

Use registry
"HKEY_CURRENT_USER/Software/Microsoft/Windows/CurrentVersion
/Themes/Personalize/AppsUseLightTheme"
to check if system theme is supported and if it is dark or
light.

Removes "EnableDarkTheme" in favor of "AppTheme".

Requires Windows SDK version 10.0.18362.0 to build with
system theme support.

Note: This does not watch for changes in system theme in
runtime as the support for it requires Windows Runtime
version 10.0.10240.0.

GitLab: #723

Change-Id: Ice8f7936a90535f47dc1870d4f18215e062684ba
---
 INSTALL.md                      |  4 +-
 build.py                        |  2 +-
 extras/scripts/build-windows.py |  5 ++-
 src/app/appsettingsmanager.h    |  1 -
 src/app/utilsadapter.cpp        | 79 +++++++++++++++++++++++++++------
 src/app/utilsadapter.h          | 26 +++++++----
 6 files changed, 90 insertions(+), 27 deletions(-)

diff --git a/INSTALL.md b/INSTALL.md
index b47cdc02c..b834f175b 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -164,7 +164,7 @@ Only 64-bit MSVC build can be compiled.
 
   |              | SDK          | Toolset | MFC    |
   | ------------ | ------------ | ------- | ------ |
-  | Requirement: | 10.0.16299.0 | V142    | latest |
+  | Requirement: | 10.0.18362.0 | V142    | latest |
 
 - Install Qt Vs Tools under extensions, and configure msvc2017_64 path under Qt Options. _See the Qt notes below._
 
@@ -200,7 +200,7 @@ Only 64-bit MSVC build can be compiled.
 ```
 
 > **SDK and Toolset** Note:
-> Jami can be build with more rencents Windows SDK and Toolset than the ones specified in the table above. However, if your have another version than SDK 10.0.16299.0 and/or Toolset v142 installed, you need to identify it according to the example below.
+> Jami can be build with more recent Windows SDK and Toolset than the ones specified in the table above. However, if your have another version than SDK 10.0.18362.0 and/or Toolset v142 installed, you need to identify it according to the example below. For the SDK, you still need to have the required version in addition to the one you chose.
 
 ```bash
     python build.py --install --sdk <your-sdk-version> --toolset <your-toolset-version>
diff --git a/build.py b/build.py
index d7617e522..1ea2feb35 100755
--- a/build.py
+++ b/build.py
@@ -32,7 +32,7 @@ OSX_DISTRIBUTION_NAME = "osx"
 WIN32_DISTRIBUTION_NAME = "win32"
 
 # vs vars
-win_sdk_default = '10.0.16299.0'
+win_sdk_default = '10.0.18362.0'
 win_toolset_default = '142'
 
 APT_BASED_DISTROS = [
diff --git a/extras/scripts/build-windows.py b/extras/scripts/build-windows.py
index 38b5685b6..d00df385a 100644
--- a/extras/scripts/build-windows.py
+++ b/extras/scripts/build-windows.py
@@ -210,10 +210,13 @@ def build(config_str, qtver, tests=False):
     daemon_dir = os.path.dirname(repo_root_dir) + '\\daemon'
     daemon_bin_dir = daemon_dir + '\\build\\x64\\ReleaseLib_win32\\bin'
 
+    # We need to update the minimum SDK version to be able to
+    # build with system theme support
     cmake_options = [
         '-DCMAKE_PREFIX_PATH=' + qt_dir,
         '-DCMAKE_INSTALL_PREFIX=' + daemon_bin_dir,
-        '-DLIBJAMI_INCLUDE_DIR=' + daemon_dir + '\\src\\jami'
+        '-DLIBJAMI_INCLUDE_DIR=' + daemon_dir + '\\src\\jami',
+        '-DCMAKE_SYSTEM_VERSION=10.0.18362.0'
     ]
     if tests:
         cmake_options.append('-DENABLE_TESTS=true')
diff --git a/src/app/appsettingsmanager.h b/src/app/appsettingsmanager.h
index 272d972ca..d69a3acee 100644
--- a/src/app/appsettingsmanager.h
+++ b/src/app/appsettingsmanager.h
@@ -42,7 +42,6 @@ extern const QString defaultDownloadPath;
     X(AcceptTransferBelow, 20) \
     X(AutoAcceptFiles, true) \
     X(DisplayHyperlinkPreviews, true) \
-    X(EnableDarkTheme, false) \
     X(AppTheme, "System") \
     X(BaseZoom, 1.0) \
     X(ParticipantsSide, false) \
diff --git a/src/app/utilsadapter.cpp b/src/app/utilsadapter.cpp
index f3cc9fa14..76cfd5c99 100644
--- a/src/app/utilsadapter.cpp
+++ b/src/app/utilsadapter.cpp
@@ -599,6 +599,43 @@ settingsCallback(GSettings* self, gchar* key, gpointer user_data)
 }
 #endif
 
+#if defined(WIN32) && __has_include(<winrt/Windows.Foundation.h>)
+bool
+readAppsUseLightThemeRegistry(bool getValue)
+{
+    auto returnValue = true;
+    HKEY hKey;
+    auto lResult
+        = RegOpenKeyEx(HKEY_CURRENT_USER,
+                       TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"),
+                       0,
+                       KEY_READ,
+                       &hKey);
+
+    if (lResult != ERROR_SUCCESS) {
+        RegCloseKey(hKey);
+        return false;
+    }
+
+    DWORD dwBufferSize(sizeof(DWORD));
+    DWORD nResult(0);
+    LONG nError = ::RegQueryValueExW(hKey,
+                                     TEXT("AppsUseLightTheme"),
+                                     0,
+                                     NULL,
+                                     reinterpret_cast<LPBYTE>(&nResult),
+                                     &dwBufferSize);
+    if (nError != ERROR_SUCCESS) {
+        returnValue = false;
+    } else if (getValue) {
+        returnValue = !nResult;
+    }
+
+    RegCloseKey(hKey);
+    return returnValue;
+}
+#endif
+
 bool
 UtilsAdapter::isSystemThemeDark()
 {
@@ -636,23 +673,37 @@ UtilsAdapter::isSystemThemeDark()
     }
     return false;
 #else
-    qWarning("System theme detection is not implemented");
+#if defined(WIN32) && __has_include(<winrt/Windows.Foundation.h>)
+    return readAppsUseLightThemeRegistry(true);
+#else
+    qWarning("System theme detection is not implemented or is not supported");
     return false;
-#endif
+#endif // WIN32
+#endif // __has_include(<gio/gio.h>)
 }
 
 bool
 UtilsAdapter::useApplicationTheme()
 {
-    if (hasNativeDarkTheme()) {
-        QString theme = getAppValue(Settings::Key::AppTheme).toString();
-        if (theme == "Dark")
-            return true;
-        else if (theme == "Light")
-            return false;
-        return isSystemThemeDark();
-    }
-    bool enableDark = getAppValue(Settings::Key::EnableDarkTheme).toBool();
-    setAppValue(Settings::Key::AppTheme, enableDark ? "Dark" : "Light");
-    return enableDark;
-}
\ No newline at end of file
+    QString theme = getAppValue(Settings::Key::AppTheme).toString();
+    if (theme == "Dark")
+        return true;
+    else if (theme == "Light")
+        return false;
+    return isSystemThemeDark();
+}
+
+
+bool
+UtilsAdapter::hasNativeDarkTheme() const
+{
+#if __has_include(<gio/gio.h>)
+    return true;
+#else
+#if defined(WIN32) && __has_include(<winrt/Windows.Foundation.h>)
+    return readAppsUseLightThemeRegistry(false);
+#else
+    return false;
+#endif
+#endif
+}
diff --git a/src/app/utilsadapter.h b/src/app/utilsadapter.h
index cd8aae2ec..9fb0c96c0 100644
--- a/src/app/utilsadapter.h
+++ b/src/app/utilsadapter.h
@@ -33,11 +33,28 @@
 #include <gio/gio.h>
 #endif
 
+#if defined(WIN32) && __has_include(<winrt/Windows.Foundation.h>)
+#include <winrt/Windows.Foundation.h>
+#endif
+
 class QClipboard;
 class SystemTray;
 
 #define LOGSLIMIT 10000
 
+
+#if defined(WIN32) && __has_include(<winrt/Windows.Foundation.h>)
+/**
+ * @brief Read if "AppsUseLightTheme" registry exists and its value
+ *
+ * @param getValue false to check if registry exists;
+ *
+ * @param getValue true if want the registry value.
+ * @return if getValue is true, returns if the native theme is Dark (defaults to false).
+ */
+bool readAppsUseLightThemeRegistry(bool getValue);
+#endif
+
 class UtilsAdapter final : public QmlAdapterBase
 {
     Q_OBJECT
@@ -112,14 +129,7 @@ public:
                                                           const QString& uri);
     Q_INVOKABLE bool luma(const QColor& color) const;
     Q_INVOKABLE bool useApplicationTheme();
-    Q_INVOKABLE bool hasNativeDarkTheme() const
-    {
-#if __has_include(<gio/gio.h>)
-        return true;
-#else
-        return false;
-#endif
-    }
+    Q_INVOKABLE bool hasNativeDarkTheme() const;
 
 Q_SIGNALS:
     void debugMessageReceived(const QString& message);
-- 
GitLab