From: Daphne Preston-Kendal <dpk@nonceword.org>
To: 47291@debbugs.gnu.org
Subject: bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes
Date: Sun, 21 Mar 2021 11:48:10 +0100 [thread overview]
Message-ID: <1B39376A-B108-41FD-87EE-52D68E8F7256@nonceword.org> (raw)
[-- 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 --]
next reply other threads:[~2021-03-21 10:48 UTC|newest]
Thread overview: 6+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-03-21 10:48 Daphne Preston-Kendal [this message]
2021-03-23 18:05 ` bug#47291: [PATCH] Auto-detect ns-appearance of frames and call a hook when it changes 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
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1B39376A-B108-41FD-87EE-52D68E8F7256@nonceword.org \
--to=dpk@nonceword.org \
--cc=47291@debbugs.gnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).