Bug 1697331 - Add a pref called widget.macos.respect-system-appearance which defaults to false. false means "force aqua appearance". r=emilio
authorMarkus Stange <mstange.moz@gmail.com>
Fri, 12 Mar 2021 18:36:00 +0000
changeset 570914 60794002f3ef1434a8a741371e8c06e857598237
parent 570913 7480579b4348dab5e34196a26fe7c6f39160f418
child 570915 ebf64c2e7256cb30f0555ccbbadd48a9e693d749
push id38282
push usernbeleuzu@mozilla.com
push dateSat, 13 Mar 2021 09:43:00 +0000
treeherdermozilla-central@6264f13d54a1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1697331
milestone88.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 1697331 - Add a pref called widget.macos.respect-system-appearance which defaults to false. false means "force aqua appearance". r=emilio This patch also sets the Info.plist keys to <false/>, i.e. "we don't require aqua". Differential Revision: https://phabricator.services.mozilla.com/D107749
modules/libpref/init/StaticPrefList.yaml
widget/cocoa/nsLookAndFeel.mm
--- a/modules/libpref/init/StaticPrefList.yaml
+++ b/modules/libpref/init/StaticPrefList.yaml
@@ -10674,16 +10674,23 @@
   value: false
   mirror: always
 
 - name: widget.window-transforms.disabled
   type: RelaxedAtomicBool
   value: false
   mirror: always
 
+#ifdef XP_MACOSX
+- name: widget.macos.respect-system-appearance
+  type: RelaxedAtomicBool
+  value: false
+  mirror: always
+#endif
+
 # Whether to allow gtk dark themes in content.
 - name: widget.content.allow-gtk-dark-theme
   type: bool
   value: false
   mirror: always
 
 # Whether to use gtk high contrast themes to disable content styling like on
 # windows high contrast mode.
--- a/widget/cocoa/nsLookAndFeel.mm
+++ b/widget/cocoa/nsLookAndFeel.mm
@@ -10,28 +10,37 @@
 #include "nsCocoaFeatures.h"
 #include "nsIContent.h"
 #include "gfxFont.h"
 #include "gfxFontConstants.h"
 #include "gfxPlatformMac.h"
 #include "nsCSSColorUtils.h"
 #include "mozilla/FontPropertyTypes.h"
 #include "mozilla/gfx/2D.h"
+#include "mozilla/StaticPrefs_widget.h"
 #include "mozilla/widget/WidgetMessageUtils.h"
 
 #import <Cocoa/Cocoa.h>
 
 // This must be included last:
 #include "nsObjCExceptions.h"
 
 // Available from 10.12 onwards; test availability at runtime before using
 @interface NSWorkspace (AvailableSinceSierra)
 @property(readonly) BOOL accessibilityDisplayShouldReduceMotion;
 @end
 
+#if !defined(MAC_OS_X_VERSION_10_14) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_14
+@interface NSApplication (NSApplicationAppearance)
+@property(strong) NSAppearance* appearance NS_AVAILABLE_MAC(10_14);
+@end
+#endif
+
+static void RegisterRespectSystemAppearancePrefListenerOnce();
+
 nsLookAndFeel::nsLookAndFeel(const LookAndFeelCache* aCache)
     : nsXPLookAndFeel(),
       mUseOverlayScrollbars(-1),
       mUseOverlayScrollbarsCached(false),
       mAllowOverlayScrollbarsOverlap(-1),
       mAllowOverlayScrollbarsOverlapCached(false),
       mSystemUsesDarkTheme(-1),
       mSystemUsesDarkThemeCached(false),
@@ -68,16 +77,17 @@ nsLookAndFeel::nsLookAndFeel(const LookA
       mColorCellHighlight(0),
       mColorEvenTreeRow(0),
       mColorOddTreeRow(0),
       mColorActiveSourceListSelection(0),
       mInitialized(false) {
   if (aCache) {
     DoSetCache(*aCache);
   }
+  RegisterRespectSystemAppearancePrefListenerOnce();
 }
 
 nsLookAndFeel::~nsLookAndFeel() {}
 
 static nscolor GetColorFromNSColor(NSColor* aColor) {
   NSColor* deviceColor = [aColor colorUsingColorSpaceName:NSDeviceRGBColorSpace];
   return NS_RGB((unsigned int)([deviceColor redComponent] * 255.0),
                 (unsigned int)([deviceColor greenComponent] * 255.0),
@@ -884,8 +894,43 @@ void nsLookAndFeel::EnsureInit() {
   color = [NSColor currentControlTint];
   mColorActiveSourceListSelection =
       (color == NSGraphiteControlTint) ? NS_RGB(0xa0, 0xa0, 0xa0) : NS_RGB(0x0a, 0x64, 0xdc);
 
   RecordTelemetry();
 
   NS_OBJC_END_TRY_IGNORE_BLOCK
 }
+
+static void RespectSystemAppearancePrefChanged(const char* aPref, void* UserInfo) {
+  MOZ_RELEASE_ASSERT(XRE_IsParentProcess());
+  MOZ_RELEASE_ASSERT(NS_IsMainThread());
+
+  if (@available(macOS 10.14, *)) {
+    if (StaticPrefs::widget_macos_respect_system_appearance()) {
+      // nil means "no override".
+      NSApp.appearance = nil;
+    } else {
+      // Override with aqua.
+      NSApp.appearance = [NSAppearance appearanceNamed:NSAppearanceNameAqua];
+    }
+  }
+
+  // Send a notification that ChildView reacts to. This will cause it to call ThemeChanged and
+  // invalidate LookAndFeel colors.
+  [[NSDistributedNotificationCenter defaultCenter]
+      postNotificationName:@"AppleInterfaceThemeChangedNotification"
+                    object:nil
+                  userInfo:nil
+        deliverImmediately:YES];
+}
+
+static void RegisterRespectSystemAppearancePrefListenerOnce() {
+  static bool sRegistered = false;
+  if (sRegistered || !XRE_IsParentProcess()) {
+    return;
+  }
+
+  sRegistered = true;
+  Preferences::RegisterCallbackAndCall(
+      &RespectSystemAppearancePrefChanged,
+      nsDependentCString(StaticPrefs::GetPrefName_widget_macos_respect_system_appearance()));
+}