Bug 1368808 - Honor the system light/dark mode setting on Windows 10. r=jimm
authorMatt Howell <mhowell@mozilla.com>
Sun, 08 Jul 2018 17:32:52 -0700
changeset 480629 48bb14249b0667377ba8b598fd890ca876539118
parent 480628 5b8041f7f604fbdb84c507e31a196235db2cff41
child 480630 3b0c43b107ff1e48c70891124b0c9cbe199e9e73
push id9719
push userffxbld-merge
push dateFri, 24 Aug 2018 17:49:46 +0000
treeherdermozilla-beta@719ec98fba77 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjimm
bugs1368808
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1368808 - Honor the system light/dark mode setting on Windows 10. r=jimm MozReview-Commit-ID: 3bzhX9bfR4s
widget/windows/nsLookAndFeel.cpp
widget/windows/nsWindow.cpp
--- a/widget/windows/nsLookAndFeel.cpp
+++ b/widget/windows/nsLookAndFeel.cpp
@@ -57,16 +57,48 @@ static nsresult GetColorFromTheme(nsUXTh
 }
 
 static int32_t GetSystemParam(long flag, int32_t def)
 {
     DWORD value;
     return ::SystemParametersInfo(flag, 0, &value, 0) ? value : def;
 }
 
+static nsresult
+SystemWantsDarkTheme(int32_t& darkThemeEnabled)
+{
+  if (!IsWin10OrLater()) {
+    darkThemeEnabled = 0;
+    return NS_OK;
+  }
+
+  nsresult rv = NS_OK;
+  nsCOMPtr<nsIWindowsRegKey> personalizeKey =
+    do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  rv = personalizeKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
+    NS_LITERAL_STRING("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"),
+    nsIWindowsRegKey::ACCESS_QUERY_VALUE);
+  if (NS_FAILED(rv)) {
+    return rv;
+  }
+
+  uint32_t lightThemeEnabled;
+  rv = personalizeKey->ReadIntValue(NS_LITERAL_STRING("AppsUseLightTheme"),
+                                    &lightThemeEnabled);
+  if (NS_SUCCEEDED(rv)) {
+    darkThemeEnabled = !lightThemeEnabled;
+  }
+
+  return rv;
+}
+
 nsLookAndFeel::nsLookAndFeel()
   : nsXPLookAndFeel()
   , mUseAccessibilityTheme(0)
   , mUseDefaultTheme(0)
   , mNativeThemeId(eWindowsTheme_Generic)
   , mCaretBlinkTime(-1)
   , mHasColorMenuHoverText(false)
   , mHasColorAccent(false)
@@ -568,16 +600,19 @@ nsLookAndFeel::GetIntImpl(IntID aID, int
         break;
     case eIntID_ScrollbarFadeDuration:
         aResult = 350;
         break;
     case eIntID_ContextMenuOffsetVertical:
     case eIntID_ContextMenuOffsetHorizontal:
         aResult = 2;
         break;
+    case eIntID_SystemUsesDarkTheme:
+        res = SystemWantsDarkTheme(aResult);
+        break;
     default:
         aResult = 0;
         res = NS_ERROR_FAILURE;
     }
   return res;
 }
 
 nsresult
--- a/widget/windows/nsWindow.cpp
+++ b/widget/windows/nsWindow.cpp
@@ -5316,16 +5316,25 @@ nsWindow::ProcessMessage(UINT msg, WPARA
       if (wParam == SPI_SETKEYBOARDDELAY) {
         // CaretBlinkTime is cached in nsLookAndFeel
         NotifyThemeChanged();
         break;
       }
       if (lParam) {
         auto lParamString = reinterpret_cast<const wchar_t*>(lParam);
         if (!wcscmp(lParamString, L"ImmersiveColorSet")) {
+          // This might be the Win10 dark mode setting; only way to tell
+          // is to actually force a theme change, since we don't get
+          // WM_THEMECHANGED or WM_SYSCOLORCHANGE when that happens.
+          if (IsWin10OrLater() && mWindowType == eWindowType_toplevel) {
+            nsIPresShell* presShell = mWidgetListener->GetPresShell();
+            if (presShell) {
+              presShell->ThemeChanged();
+            }
+          }
           // WM_SYSCOLORCHANGE is not dispatched for accent color changes
           OnSysColorChanged();
           break;
         }
         if (IsWin10OrLater() && mWindowType == eWindowType_invisible) {
           if (!wcscmp(lParamString, L"UserInteractionMode")) {
             nsCOMPtr<nsIWindowsUIUtils> uiUtils(do_GetService("@mozilla.org/windows-ui-utils;1"));
             if (uiUtils) {