[libadwaita/wip/chergert/macos-appearance] macos: monitor light/dark changes on macOS 10.14+




commit a29120e5127b9c84c52370805bcd583eee1ed365
Author: Christian Hergert <christian hergert me>
Date:   Tue Mar 1 16:49:28 2022 -0800

    macos: monitor light/dark changes on macOS 10.14+
    
    This is a minimal implementation that gets basic light/dark updating to
    work on macOS 10.14+. There are certainly additional things we can do to
    improve support for High Contrast and what not, but that will take some
    more research by interested individuals.

 src/adw-settings.c | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/meson.build    | 11 +++++++
 2 files changed, 98 insertions(+), 2 deletions(-)
---
diff --git a/src/adw-settings.c b/src/adw-settings.c
index d71eb24c..c2571ac0 100644
--- a/src/adw-settings.c
+++ b/src/adw-settings.c
@@ -15,6 +15,10 @@
 #include <gio/gio.h>
 #include <gtk/gtk.h>
 
+#ifdef __APPLE__
+# include <AppKit/AppKit.h>
+#endif
+
 #define PORTAL_BUS_NAME "org.freedesktop.portal.Desktop"
 #define PORTAL_OBJECT_PATH "/org/freedesktop/portal/desktop"
 #define PORTAL_SETTINGS_INTERFACE "org.freedesktop.portal.Settings"
@@ -84,7 +88,7 @@ set_high_contrast (AdwSettings *self,
 
 /* Settings portal */
 
-#ifndef G_OS_WIN32
+#if defined(G_OS_UNIX) && !defined(__APPLE__)
 static gboolean
 get_disable_portal (void)
 {
@@ -297,6 +301,85 @@ init_portal (AdwSettings *self)
 }
 #endif
 
+#ifdef __APPLE__
+@interface ThemeChangedObserver : NSObject
+{
+  AdwSettings *settings;
+}
+@end
+
+@implementation ThemeChangedObserver
+
+-(instancetype)initWithSettings:(AdwSettings *)_settings
+{
+  [self init];
+  g_set_weak_pointer (&self->settings, _settings);
+  return self;
+}
+
+-(void)dealloc
+{
+  g_clear_weak_pointer (&self->settings);
+  [super dealloc];
+}
+
+static AdwSystemColorScheme
+get_ns_color_scheme (void)
+{
+  if (@available(*, macOS 10.14)) {
+    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
+    NSString *style = [userDefaults stringForKey:@"AppleInterfaceStyle"];
+    BOOL isDark = [style isEqualToString:@"Dark"];
+#if 0
+    BOOL isAuto = [userDefaults boolForKey:@"AppleInterfaceStyleSwitchesAutomatically"];
+    BOOL isHighContrast = NO;
+
+    /* We can get HighContrast using [NSAppearance currentAppearance] and
+     * checking for the variants with HighContrast in their name, however
+     * those do not update when the notifications come in (or ever it
+     * seems unless a NSView changes them while drawing. If we can monitor
+     * a NSView, we could watch for effectiveAppearance changes.
+     */
+#endif
+
+    [style release];
+
+    return isDark ?
+      ADW_SYSTEM_COLOR_SCHEME_PREFER_DARK :
+      ADW_SYSTEM_COLOR_SCHEME_DEFAULT;
+  }
+
+  return ADW_SYSTEM_COLOR_SCHEME_DEFAULT;
+}
+
+-(void)appDidChangeTheme:(NSNotification *)notification
+{
+  if (self->settings != NULL)
+    set_color_scheme (self->settings, get_ns_color_scheme ());
+}
+@end
+
+static void
+init_nsapp_observer (AdwSettings *settings)
+{
+  static ThemeChangedObserver *observer;
+
+  if (@available(*, macOS 10.14)) {
+    settings->has_color_scheme = TRUE;
+  }
+
+  observer = [[ThemeChangedObserver alloc] initWithSettings:settings];
+
+  [[NSDistributedNotificationCenter defaultCenter]
+    addObserver:observer
+       selector:@selector(appDidChangeTheme:)
+           name:@"AppleInterfaceThemeChangedNotification"
+         object:nil];
+
+  [observer appDidChangeTheme:nil];
+}
+#endif
+
 /* GSettings */
 
 #ifndef G_OS_WIN32
@@ -423,7 +506,9 @@ adw_settings_constructed (GObject *object)
 
   G_OBJECT_CLASS (adw_settings_parent_class)->constructed (object);
 
-#ifndef G_OS_WIN32
+#ifdef __APPLE__
+  init_nsapp_observer (self);
+#elif defined(G_OS_UNIX)
   init_portal (self);
 #endif
 
diff --git a/src/meson.build b/src/meson.build
index cfd52054..e76d029e 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -255,6 +255,17 @@ else
   config_h.set('_ADW_EXTERN', '__attribute__((visibility("default"))) extern')
 endif
 
+if target_system == 'darwin'
+  appleframework_modules = [
+    'AppKit',
+    'Foundation',
+  ]
+  libadwaita_deps += [
+    dependency('appleframeworks', modules: appleframework_modules),
+  ]
+  libadwaita_c_args += ['-xobjective-c']
+endif
+
 configure_file(
          output: 'config.h',
   configuration: config_h,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]