From 813b66cff906bc39b7615b7ca71689da3388029c Mon Sep 17 00:00:00 2001
From: Daphne Preston-Kendal <git@dpk.io>
Date: Tue, 9 Mar 2021 13:05:13 +0100
Subject: [PATCH] auto-detection of ns-appearance, and an
 ns-dark-mode-change-hook

---
 src/nsfns.m  | 10 +++++++++-
 src/nsterm.m | 50 +++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 58 insertions(+), 2 deletions(-)

diff --git a/src/nsfns.m b/src/nsfns.m
index 5c4cc915e7..fc73725226 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -1284,7 +1284,15 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side.
   else if (EQ (tem, Qlight))
     FRAME_NS_APPEARANCE (f) = ns_appearance_aqua;
   else
-    FRAME_NS_APPEARANCE (f) = ns_appearance_system_default;
+    {
+      tem = [[[NSApp effectiveAppearance]
+               bestMatchFromAppearancesWithNames:@[
+                                                   NSAppearanceNameAqua,
+                                                   NSAppearanceNameDarkAqua
+                                                   ]
+              ] isEqualToString:NSAppearanceNameDarkAqua] ? Qdark : Qlight;
+      FRAME_NS_APPEARANCE (f) = (tem == Qdark ? ns_appearance_vibrant_dark : ns_appearance_aqua);
+    }
   store_frame_param (f, Qns_appearance,
                      (!NILP (tem) && !EQ (tem, Qunbound)) ? tem : Qnil);
 
diff --git a/src/nsterm.m b/src/nsterm.m
index bf175bbd18..e0632e347e 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2207,6 +2207,14 @@ so some key presses (TAB) are swallowed by the system.  */
 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 */
 }
 
+void
+ns_update_system_appearance (struct frame *f, Lisp_Object new_value)
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
+  store_frame_param (f, Qns_appearance, new_value);
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 */
+}
+
 void
 ns_set_transparent_titlebar (struct frame *f, Lisp_Object new_value,
                              Lisp_Object old_value)
@@ -5926,6 +5934,15 @@ - (void)applicationDidFinishLaunching: (NSNotification *)notification
 	 object:nil];
 #endif
 
+#ifdef NS_IMPL_COCOA
+  [[NSDistributedNotificationCenter defaultCenter]
+    addObserver:self
+       selector:@selector(darkModeDidChange:)
+           name:@"AppleInterfaceThemeChangedNotification"
+         object:nil
+   ];
+#endif
+
 #ifdef NS_IMPL_COCOA
   /* Some functions/methods in CoreFoundation/Foundation increase the
      maximum number of open files for the process in their first call.
@@ -5964,6 +5981,32 @@ - (void)antialiasThresholdDidChange:(NSNotification *)notification
 #endif
 }
 
+- (void)darkModeDidChange:(NSNotification *)notification
+{
+#ifdef NS_IMPL_COCOA
+  NSTRACE ("[EmacsApp darkModeDidChange:]");
+
+  Lisp_Object new_value = [[[self effectiveAppearance]
+                             bestMatchFromAppearancesWithNames:@[
+                                                                 NSAppearanceNameAqua,
+                                                                 NSAppearanceNameDarkAqua
+                                                                 ]
+                            ] isEqualToString:NSAppearanceNameDarkAqua] ? Qlight : Qdark; /* this is backwards; i have no idea why */
+
+  Lisp_Object tail, frame;
+  FOR_EACH_FRAME (tail, frame)
+    {
+      struct frame *f = XFRAME (frame);
+      EmacsView *view = (EmacsView *)FRAME_NS_VIEW (f);
+      EmacsWindow *window = (EmacsWindow *)[view window];
+      ns_update_system_appearance (f, new_value);
+      ns_set_appearance (f, new_value,
+                         (new_value == Qdark ? Qlight : Qdark));
+    }
+
+  run_hook (Qns_dark_mode_changed_hook);
+#endif
+}
 
 /* Termination sequences:
     C-x C-c:
@@ -9790,7 +9833,7 @@ - (CGContextRef) getContext
   IOSurfaceRef surface = NULL;
 
   NSTRACE ("[EmacsSurface getContextWithSize:]");
-  NSTRACE_MSG (@"IOSurface count: %lu", [cache count] + (lastSurface ? 1 : 0));
+  // NSTRACE_MSG (@"IOSurface count: %lu", [cache count] + (lastSurface ? 1 : 0));
 
   for (id object in cache)
     {
@@ -10199,6 +10242,11 @@ Nil means use fullscreen the old (< 10.7) way.  The old way works better with
 This variable is ignored on Mac OS X < 10.7 and GNUstep.  */);
   ns_use_srgb_colorspace = YES;
 
+  DEFSYM (Qns_dark_mode_changed_hook, "ns-dark-mode-changed-hook");
+
+  DEFVAR_LISP ("ns-dark-mode-changed-hook", Vns_dark_mode_changed_hook,
+               doc: /* Hook run when the Mac OS system-wide UI theme changes from dark to light or vice versa. */);
+
   DEFVAR_BOOL ("ns-use-mwheel-acceleration",
                ns_use_mwheel_acceleration,
      doc: /* Non-nil means use macOS's standard mouse wheel acceleration.
-- 
2.24.3 (Apple Git-128)

