Bug 1528960 - Query MacOS system dark mode only on the main browser process or it's the initial query on the child process. r=hiro
authorBoris Chiou <boris.chiou@gmail.com>
Fri, 01 Mar 2019 18:09:19 +0000
changeset 519884 2b32f21ec0dc870475a73ac52cd53706ff023657
parent 519883 d4a7d1ef0bb971fee314e1b9738ab7cf01f21935
child 519885 5ab896c5a05d166321bc8e71424d94bb004f7153
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewershiro
bugs1528960
milestone67.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 1528960 - Query MacOS system dark mode only on the main browser process or it's the initial query on the child process. r=hiro Based on the implementation and issues on prefers-reduced-motion, it seems we have the same issue on the dark mode. In child processes on MacOSX we don't spin native event loop at all. Without native event loops, the global preference returned from `SystemWantsDarkTheme()` doesn't return up-to-date value when the system setting changed for some reasons. To workaround this we call `SystemWantsDarkTheme()` only on the parent process which spins native event loop or when it's the initial query on the child process. And we give the up-to-date value to the child process via an IPC call just like other cached values do. Differential Revision: https://phabricator.services.mozilla.com/D21303
widget/cocoa/nsLookAndFeel.h
widget/cocoa/nsLookAndFeel.mm
--- a/widget/cocoa/nsLookAndFeel.h
+++ b/widget/cocoa/nsLookAndFeel.h
@@ -43,16 +43,19 @@ class nsLookAndFeel final : public nsXPL
   bool mUseOverlayScrollbarsCached;
 
   int32_t mAllowOverlayScrollbarsOverlap;
   bool mAllowOverlayScrollbarsOverlapCached;
 
   int32_t mPrefersReducedMotion;
   bool mPrefersReducedMotionCached;
 
+  int32_t mSystemUsesDarkTheme;
+  bool mSystemUsesDarkThemeCached;
+
   nscolor mColorTextSelectBackground;
   nscolor mColorTextSelectBackgroundDisabled;
   nscolor mColorHighlight;
   nscolor mColorMenuHover;
   nscolor mColorTextSelectForeground;
   nscolor mColorMenuHoverText;
   nscolor mColorButtonText;
   bool mHasColorButtonText;
--- a/widget/cocoa/nsLookAndFeel.mm
+++ b/widget/cocoa/nsLookAndFeel.mm
@@ -38,16 +38,18 @@ typedef NSInteger mozNSScrollerStyle;
 nsLookAndFeel::nsLookAndFeel()
     : nsXPLookAndFeel(),
       mUseOverlayScrollbars(-1),
       mUseOverlayScrollbarsCached(false),
       mAllowOverlayScrollbarsOverlap(-1),
       mAllowOverlayScrollbarsOverlapCached(false),
       mPrefersReducedMotion(-1),
       mPrefersReducedMotionCached(false),
+      mSystemUsesDarkTheme(-1),
+      mSystemUsesDarkThemeCached(false),
       mColorTextSelectBackground(0),
       mColorTextSelectBackgroundDisabled(0),
       mColorHighlight(0),
       mColorMenuHover(0),
       mColorTextSelectForeground(0),
       mColorMenuHoverText(0),
       mColorButtonText(0),
       mHasColorButtonText(false),
@@ -107,16 +109,17 @@ void nsLookAndFeel::RefreshImpl() {
 
   // We should only clear the cache if we're in the main browser process.
   // Otherwise, we should wait for the parent to inform us of new values
   // to cache via LookAndFeel::SetIntCache.
   if (XRE_IsParentProcess()) {
     mUseOverlayScrollbarsCached = false;
     mAllowOverlayScrollbarsOverlapCached = false;
     mPrefersReducedMotionCached = false;
+    mSystemUsesDarkThemeCached = false;
   }
 
   // Fetch colors next time they are requested.
   mInitialized = false;
 }
 
 // Turns an opaque selection color into a partially transparent selection color,
 // which usually leads to better contrast with the text color and which should
@@ -559,17 +562,21 @@ nsresult nsLookAndFeel::GetIntImpl(IntID
       break;
     case eIntID_ContextMenuOffsetVertical:
       aResult = -6;
       break;
     case eIntID_ContextMenuOffsetHorizontal:
       aResult = 1;
       break;
     case eIntID_SystemUsesDarkTheme:
-      aResult = SystemWantsDarkTheme();
+      if (!mSystemUsesDarkThemeCached) {
+        mSystemUsesDarkTheme = SystemWantsDarkTheme();
+        mSystemUsesDarkThemeCached = true;
+      }
+      aResult = mSystemUsesDarkTheme;
       break;
     case eIntID_PrefersReducedMotion:
       // Without native event loops,
       // NSWorkspace.accessibilityDisplayShouldReduceMotion returns stale
       // information, so we get the information only on the parent processes
       // or when it's the initial query on child processes.  Otherwise we will
       // get the info via LookAndFeel::SetIntCache on child processes.
       if (!mPrefersReducedMotionCached &&
@@ -617,20 +624,20 @@ bool nsLookAndFeel::SystemWantsOverlaySc
           [NSScroller preferredScrollerStyle] == mozNSScrollerStyleOverlay);
 }
 
 bool nsLookAndFeel::AllowOverlayScrollbarsOverlap() { return (UseOverlayScrollbars()); }
 
 bool nsLookAndFeel::SystemWantsDarkTheme() {
   // This returns true if the macOS system appearance is set to dark mode on
   // 10.14+, false otherwise.
-  if (nsCocoaFeatures::OnMojaveOrLater()) {
-    return !![[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
+  if (!nsCocoaFeatures::OnMojaveOrLater()) {
+    return false;
   }
-  return false;
+  return !![[NSUserDefaults standardUserDefaults] stringForKey:@"AppleInterfaceStyle"];
 }
 
 bool nsLookAndFeel::GetFontImpl(FontID aID, nsString& aFontName, gfxFontStyle& aFontStyle) {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
   // hack for now
   if (aID == eFont_Window || aID == eFont_Document) {
     aFontStyle.style = mozilla::FontSlantStyle::Normal();
@@ -665,30 +672,39 @@ nsTArray<LookAndFeelInt> nsLookAndFeel::
   allowOverlayScrollbarsOverlap.value = GetInt(eIntID_AllowOverlayScrollbarsOverlap);
   lookAndFeelIntCache.AppendElement(allowOverlayScrollbarsOverlap);
 
   LookAndFeelInt prefersReducedMotion;
   prefersReducedMotion.id = eIntID_PrefersReducedMotion;
   prefersReducedMotion.value = GetInt(eIntID_PrefersReducedMotion);
   lookAndFeelIntCache.AppendElement(prefersReducedMotion);
 
+  LookAndFeelInt systemUsesDarkTheme;
+  systemUsesDarkTheme.id = eIntID_SystemUsesDarkTheme;
+  systemUsesDarkTheme.value = GetInt(eIntID_SystemUsesDarkTheme);
+  lookAndFeelIntCache.AppendElement(systemUsesDarkTheme);
+
   return lookAndFeelIntCache;
 }
 
 void nsLookAndFeel::SetIntCacheImpl(const nsTArray<LookAndFeelInt>& aLookAndFeelIntCache) {
   for (auto entry : aLookAndFeelIntCache) {
     switch (entry.id) {
       case eIntID_UseOverlayScrollbars:
         mUseOverlayScrollbars = entry.value;
         mUseOverlayScrollbarsCached = true;
         break;
       case eIntID_AllowOverlayScrollbarsOverlap:
         mAllowOverlayScrollbarsOverlap = entry.value;
         mAllowOverlayScrollbarsOverlapCached = true;
         break;
+      case eIntID_SystemUsesDarkTheme:
+        mSystemUsesDarkTheme = entry.value;
+        mSystemUsesDarkThemeCached = true;
+        break;
       case eIntID_PrefersReducedMotion:
         mPrefersReducedMotion = entry.value;
         mPrefersReducedMotionCached = true;
         break;
     }
   }
 }