unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes
@ 2021-03-21 10:48 Daphne Preston-Kendal
  2021-03-23 18:05 ` Matt Armstrong
  0 siblings, 1 reply; 6+ messages in thread
From: Daphne Preston-Kendal @ 2021-03-21 10:48 UTC (permalink / raw)
  To: 47291

[-- Attachment #1: Type: text/plain, Size: 1119 bytes --]

This is a slightly cleaned-up version of the patch I initially posted for
commentary on emacs-devel.
<https://lists.gnu.org/archive/html/emacs-devel/2021-03/msg00482.html>

The patch makes two closely related changes: when a new frame is
created, the ns-appearance parameter (which was already in Emacs) is
bound to 'light or 'dark depending on the system theme. (Previously,
it could be set explicitly and Emacs would respect that change on a
per-frame basis, but if it wasn't explicitly set it was unbound.)
Secondly, it registers an event handler for changes to the system-wide
theme, and when the system theme changes, it changes the ns-appearance
parameter of all frames to match the new system theme, and runs a new
hook, ns-dark-mode-changed-hook so that users can e.g. set a new Emacs
theme to match the new system theme or whatever.

The patch is against Emacs HEAD as of time of writing. (3cbf92323c)

As mentioned on emacs-devel, this is my first Emacs patch and my first
time programming Objective-C in a long while, so I’d definitely
appreciate feedback!


Daphne Preston-Kendal


[-- Attachment #2: 0001-Auto-detect-ns-appearance-of-frames-and-call-a-hook-.patch --]
[-- Type: application/octet-stream, Size: 5071 bytes --]

From f0fec3e277432d20a38c50685a84448e7cd5a536 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-detect ns-appearance of frames and call a hook when it
 changes.

* src/nsfns.m (Fx_create_frame): Automatically set the ns-appearance
paramter of a frame from the current system appearance on Mac OS.
* src/nsterm.m: Register for system dark/light mode change events on
Mac OS, and update the ns-appearance parameter of frames when the
system theme changes, calling a new ns-dark-mode-changed-hook when
done.
---
 src/nsfns.m  | 10 +++++++++-
 src/nsterm.m | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 61 insertions(+), 1 deletion(-)

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..2a0213dcb4 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,36 @@ - (void)antialiasThresholdDidChange:(NSNotification *)notification
 #endif
 }
 
+- (void)darkModeDidChange:(NSNotification *)notification
+{
+#ifdef NS_IMPL_COCOA
+  NSTRACE ("[EmacsApp darkModeDidChange:]");
+
+  /* It appears that the AppleInterfaceThemeChangedNotification is
+     sent to the app before the effectiveAppearance is set, so
+     if the effectiveAppearance matches the dark theme, we assume
+     the new theme is the light theme, and vice-versa. */
+  Lisp_Object new_value = [[[self effectiveAppearance]
+                             bestMatchFromAppearancesWithNames:@[
+                                                                 NSAppearanceNameAqua,
+                                                                 NSAppearanceNameDarkAqua
+                                                                 ]
+                            ] isEqualToString:NSAppearanceNameDarkAqua] ? Qlight : Qdark;
+
+  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:
@@ -10199,6 +10246,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)


[-- Attachment #3: Type: text/plain, Size: 2 bytes --]




^ permalink raw reply related	[flat|nested] 6+ messages in thread

* bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes
  2021-03-21 10:48 bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes Daphne Preston-Kendal
@ 2021-03-23 18:05 ` Matt Armstrong
  2021-05-18 14:43   ` Lars Ingebrigtsen
  2021-05-18 18:03   ` Daphne Preston-Kendal
  0 siblings, 2 replies; 6+ messages in thread
From: Matt Armstrong @ 2021-03-23 18:05 UTC (permalink / raw)
  To: Daphne Preston-Kendal, 47291

Daphne Preston-Kendal <dpk@nonceword.org> writes:

> This is a slightly cleaned-up version of the patch I initially posted for
> commentary on emacs-devel.
> <https://lists.gnu.org/archive/html/emacs-devel/2021-03/msg00482.html>
>
> The patch makes two closely related changes: when a new frame is
> created, the ns-appearance parameter (which was already in Emacs) is
> bound to 'light or 'dark depending on the system theme. (Previously,
> it could be set explicitly and Emacs would respect that change on a
> per-frame basis, but if it wasn't explicitly set it was unbound.)

I think GTK already has similar functionality.  When I change the GTK
theme Emacs' frame decorations change accordingly.  So, to me this part
of the patch seems fine from the policy perspective that Lars raised on
emacs-devel.


> Secondly, it registers an event handler for changes to the system-wide
> theme, and when the system theme changes, it changes the ns-appearance
> parameter of all frames to match the new system theme, and runs a new
> hook, ns-dark-mode-changed-hook so that users can e.g. set a new Emacs
> theme to match the new system theme or whatever.

I suggested an alternative approach on emacs-devel -- use the
dynamic-setting.el mechanism which is used for GTK but expressed in a
general way.

Since Emacs already has that mechanism for GTK, I think this approach
would satisfy the policy issue Lars raised as well.





^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes
  2021-03-23 18:05 ` Matt Armstrong
@ 2021-05-18 14:43   ` Lars Ingebrigtsen
  2021-05-18 17:44     ` Alan Third
  2021-05-18 18:03   ` Daphne Preston-Kendal
  1 sibling, 1 reply; 6+ messages in thread
From: Lars Ingebrigtsen @ 2021-05-18 14:43 UTC (permalink / raw)
  To: Matt Armstrong; +Cc: Alan Third, 47291, Daphne Preston-Kendal

Matt Armstrong <matt@rfc20.org> writes:

> I suggested an alternative approach on emacs-devel -- use the
> dynamic-setting.el mechanism which is used for GTK but expressed in a
> general way.
>
> Since Emacs already has that mechanism for GTK, I think this approach
> would satisfy the policy issue Lars raised as well.

Yes, I think that might make sense...  but I've added Alan to the CCs,
since this affects Macos things.  Perhaps he has some comments on these
alternative approaches.

-- 
(domestic pets only, the antidote for overdose, milk.)
   bloggy blog: http://lars.ingebrigtsen.no





^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes
  2021-05-18 14:43   ` Lars Ingebrigtsen
@ 2021-05-18 17:44     ` Alan Third
  0 siblings, 0 replies; 6+ messages in thread
From: Alan Third @ 2021-05-18 17:44 UTC (permalink / raw)
  To: Lars Ingebrigtsen; +Cc: Matt Armstrong, 47291, Daphne Preston-Kendal

On Tue, May 18, 2021 at 04:43:33PM +0200, Lars Ingebrigtsen wrote:
> Matt Armstrong <matt@rfc20.org> writes:
> 
> > I suggested an alternative approach on emacs-devel -- use the
> > dynamic-setting.el mechanism which is used for GTK but expressed in a
> > general way.
> >
> > Since Emacs already has that mechanism for GTK, I think this approach
> > would satisfy the policy issue Lars raised as well.
> 
> Yes, I think that might make sense...  but I've added Alan to the CCs,
> since this affects Macos things.  Perhaps he has some comments on these
> alternative approaches.

I don't really have much of an opinion. I feel tying in with
pre-existing functionality is probably the way to go but I don't know
anything about it.

I think the first part of Daphne's change can go straight in if it's
in a separate patch.

-- 
Alan Third





^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes
  2021-03-23 18:05 ` Matt Armstrong
  2021-05-18 14:43   ` Lars Ingebrigtsen
@ 2021-05-18 18:03   ` Daphne Preston-Kendal
  2021-10-08  8:24     ` Daphne Preston-Kendal
  1 sibling, 1 reply; 6+ messages in thread
From: Daphne Preston-Kendal @ 2021-05-18 18:03 UTC (permalink / raw)
  To: Matt Armstrong; +Cc: 47291

On 23 Mar 2021, at 19:05, Matt Armstrong <matt@rfc20.org> wrote:

> I suggested an alternative approach on emacs-devel -- use the
> dynamic-setting.el mechanism which is used for GTK but expressed in a
> general way.

I took a look at dynamic-setting.el but couldn’t quite see how what
this patch does would fit in with it/how it would enable the same
functionality as this patch provides. It doesn’t seem to be
documented? (Though in fairness, either is my patch at the moment!)

The goal of this patch is to allow Emacs to automatically select
different themes depending on the system-wide setting, and
automatically change which theme is in use when the system-wide
setting changes. There may be multiple themes involved in the change —
for instance, I would want the light smart-mode-line theme plus light
buffer theme enabled when the system is in light mode, but both should
be deactivated and changed to the dark smart-mode-line and buffer
themes when the system changes to dark mode.

Is it possible to do that within the framework of what dynamic-setting
provides? Sorry if this is obvious, I’m just not familiar with this
bit of Emacs.


Daphne






^ permalink raw reply	[flat|nested] 6+ messages in thread

* bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes
  2021-05-18 18:03   ` Daphne Preston-Kendal
@ 2021-10-08  8:24     ` Daphne Preston-Kendal
  0 siblings, 0 replies; 6+ messages in thread
From: Daphne Preston-Kendal @ 2021-10-08  8:24 UTC (permalink / raw)
  To: 47291

On 18 May 2021, at 20:03, Daphne Preston-Kendal <dpk@nonceword.org> wrote:

> Is it possible to do that within the framework of what dynamic-setting
> provides? Sorry if this is obvious, I’m just not familiar with this
> bit of Emacs.

Since there have been no answers since May, I’d like to suggest/
request that my patch be merged in more or less as it is. If there is
an OS-portable mechanism for detecting light/dark switches somewhere
in a Lisp library, like dynamic-setting.el, then the patch I provide
here can still work as the underlying C implementation, and we can
bridge them together at the Lisp level later. An analogy for this
approach would be how the Lisp-level interprogram-{cut,paste}-function
settings bridge to underlying ns-get-selection and ns-own-selection
functions on Mac OS, but to other things on free OSes.

I’d really like to see this in Emacs 28 if possible!


Daphne






^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2021-10-08  8:24 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-03-21 10:48 bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes Daphne Preston-Kendal
2021-03-23 18:05 ` Matt Armstrong
2021-05-18 14:43   ` Lars Ingebrigtsen
2021-05-18 17:44     ` Alan Third
2021-05-18 18:03   ` Daphne Preston-Kendal
2021-10-08  8:24     ` Daphne Preston-Kendal

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).