Subject: Re: bug#39000: Light frame after desktop-read on MacOS

From: Alan Third <[email-masked]>
Date: Tue, 7 Jan 2020 15:03:20 +0000

On Tue, Jan 07, 2020 at 12:18:16PM +0900, Tak Kunihiro wrote:
> Emacs 26.3 offers dark frames on MacOS 10.14.6 with `Dark (Still)'
> mode.  However after the following operations,
> 
>  $ emacs -Q
>  M-x about-emacs
>  GNU Emacs 26.3 (build 1, x86_64-apple-darwin18.7.0, NS appkit-1671.60 Version 10.14.6 (Build 18G87))
>  M-x desktop-save
>  M-x desktop-read
> 
> a dark frame turns into light frame.  I think this is a bug.

I’ve attached a patch.

It also fixes a niggle I had in that you could force the frame to use
a dark theme, or an aqua theme, but not the system default even though
Emacs would launch with the system default. The documentation was also
wrong in that it described the light theme as the system default, even
though it may not have been.

I’m not sure if this is too big a change for emacs 27 at this stage,
as it’s not entirely fixing bugs, although I’d argue it’s completing a
feature that is incomplete in Emacs 26.
-- 
Alan Third
>From c36ab8ccced2b32425160d33777df7dccdb233e4 Mon Sep 17 00:00:00 2001
From: Alan Third <[email-masked]>
Date: Tue, 7 Jan 2020 14:19:01 +0000
Subject: [PATCH] Fix NS frame parameters (bug#39000)

* src/frame.c (make_frame): Use new system default setting.
* src/frame.h (enum ns_appearance_type): Add new system default
setting.
* src/nsfns.m (Fx_create_frame): Correctly handle Qunbound and support
system default appearance.
(syms_of_nsfns): Add Qlight.
* src/nsterm.h: New method definition.
* src/nsterm.m (ns_set_appearance): Correctly handle Qlight and use new
setAppearance method.
([EmacsView initFrameFromEmacs:]): Use new setAppearance method.
([EmacsWindow setAppearance]): New method.
* doc/lispref/frames.texi (Management Parameters): Document 'light'.
---
 doc/lispref/frames.texi |  9 +++----
 src/frame.c             |  2 +-
 src/frame.h             |  5 ++--
 src/nsfns.m             | 15 ++++++++----
 src/nsterm.h            |  2 ++
 src/nsterm.m            | 52 ++++++++++++++++++++++++++---------------
 6 files changed, 55 insertions(+), 30 deletions(-)

diff --git a/doc/lispref/frames.texi b/doc/lispref/frames.texi
index 05038c6f52..9bd8bedc66 100644
--- a/doc/lispref/frames.texi
+++ b/doc/lispref/frames.texi
@@ -2192,10 +2192,11 @@ Management Parameters
 @vindex ns-appearance@r{, a frame parameter}
 @item ns-appearance
 Only available on macOS, if set to @code{dark} draw this frame's
-window-system window using the ``vibrant dark'' theme, otherwise use
-the system default.  The ``vibrant dark'' theme can be used to set the
-toolbar and scrollbars to a dark appearance when using an Emacs theme
-with a dark background.
+window-system window using the ``vibrant dark'' theme, and if set to
+@code{light} use the ``aqua'' theme, otherwise use the system default.
+The ``vibrant dark'' theme can be used to set the toolbar and
+scrollbars to a dark appearance when using an Emacs theme with a dark
+background.
 
 @vindex ns-transparent-titlebar@r{, a frame parameter}
 @item ns-transparent-titlebar
diff --git a/src/frame.c b/src/frame.c
index 88d6f22fc0..51fc78ab70 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -904,7 +904,7 @@ make_frame (bool mini_p)
   f->last_tool_bar_item = -1;
 #endif
 #ifdef NS_IMPL_COCOA
-  f->ns_appearance = ns_appearance_aqua;
+  f->ns_appearance = ns_appearance_system_default;
   f->ns_transparent_titlebar = false;
 #endif
 #endif
diff --git a/src/frame.h b/src/frame.h
index 6ab690c0ff..68dc0ce364 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -69,8 +69,9 @@ #define EMACS_FRAME_H
 #ifdef NS_IMPL_COCOA
 enum ns_appearance_type
   {
-   ns_appearance_aqua,
-   ns_appearance_vibrant_dark
+    ns_appearance_system_default,
+    ns_appearance_aqua,
+    ns_appearance_vibrant_dark
   };
 #endif
 #endif /* HAVE_WINDOW_SYSTEM */
diff --git a/src/nsfns.m b/src/nsfns.m
index 13ff67df09..18488bd46f 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -1271,14 +1271,20 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side.
 #ifdef NS_IMPL_COCOA
   tem = gui_display_get_arg (dpyinfo, parms, Qns_appearance, NULL, NULL,
                              RES_TYPE_SYMBOL);
-  FRAME_NS_APPEARANCE (f) = EQ (tem, Qdark)
-    ? ns_appearance_vibrant_dark : ns_appearance_aqua;
-  store_frame_param (f, Qns_appearance, tem);
+  if (EQ (tem, Qdark))
+    FRAME_NS_APPEARANCE (f) = ns_appearance_vibrant_dark;
+  else if (EQ (tem, Qlight))
+    FRAME_NS_APPEARANCE (f) = ns_appearance_aqua;
+  else
+    FRAME_NS_APPEARANCE (f) = ns_appearance_system_default;
+  store_frame_param (f, Qns_appearance,
+                     (!NILP (tem) && !EQ (tem, Qunbound)) ? tem : Qnil);
 
   tem = gui_display_get_arg (dpyinfo, parms, Qns_transparent_titlebar,
                              NULL, NULL, RES_TYPE_BOOLEAN);
   FRAME_NS_TRANSPARENT_TITLEBAR (f) = !NILP (tem) && !EQ (tem, Qunbound);
-  store_frame_param (f, Qns_transparent_titlebar, tem);
+  store_frame_param (f, Qns_transparent_titlebar,
+                     FRAME_NS_TRANSPARENT_TITLEBAR (f) ? Qt : Qnil);
 #endif
 
   parent_frame = gui_display_get_arg (dpyinfo, parms, Qparent_frame, NULL, NULL,
@@ -3135,6 +3141,7 @@ - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
   DEFSYM (Qframe_title_format, "frame-title-format");
   DEFSYM (Qicon_title_format, "icon-title-format");
   DEFSYM (Qdark, "dark");
+  DEFSYM (Qlight, "light");
 
   DEFVAR_LISP ("ns-icon-type-alist", Vns_icon_type_alist,
                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
diff --git a/src/nsterm.h b/src/nsterm.h
index fb9ac1b462..8baa65f578 100644
--- a/src/nsterm.h
+++ b/src/nsterm.h
@@ -471,6 +471,8 @@ #define NSTRACE_UNSILENCE()
 {
   NSPoint grabOffset;
 }
+
+- (void)setAppearance;
 @end

diff --git a/src/nsterm.m b/src/nsterm.m
index 03754e5ae5..d66a3d7495 100644
--- a/src/nsterm.m
+++ b/src/nsterm.m
@@ -2025,17 +2025,13 @@ so some key presses (TAB) are swallowed by the system.  */
     return;
 
   if (EQ (new_value, Qdark))
-    {
-      window.appearance = [NSAppearance
-                            appearanceNamed: NSAppearanceNameVibrantDark];
-      FRAME_NS_APPEARANCE (f) = ns_appearance_vibrant_dark;
-    }
+    FRAME_NS_APPEARANCE (f) = ns_appearance_vibrant_dark;
+  else if (EQ (new_value, Qlight))
+    FRAME_NS_APPEARANCE (f) = ns_appearance_aqua;
   else
-    {
-      window.appearance = [NSAppearance
-                            appearanceNamed: NSAppearanceNameAqua];
-      FRAME_NS_APPEARANCE (f) = ns_appearance_aqua;
-    }
+    FRAME_NS_APPEARANCE (f) = ns_appearance_system_default;
+
+  [window setAppearance];
 #endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 */
 }
 
@@ -7465,16 +7461,8 @@ - (instancetype) initFrameFromEmacs: (struct frame *)f
   if (! FRAME_UNDECORATED (f))
     [self createToolbar: f];
 
-#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
-#ifndef NSAppKitVersionNumber10_10
-#define NSAppKitVersionNumber10_10 1343
-#endif
 
-  if (NSAppKitVersionNumber >= NSAppKitVersionNumber10_10
-      && FRAME_NS_APPEARANCE (f) != ns_appearance_aqua)
-    win.appearance = [NSAppearance
-                          appearanceNamed: NSAppearanceNameVibrantDark];
-#endif
+  [win setAppearance];
 
 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
   if ([win respondsToSelector: @selector(titlebarAppearsTransparent)])
@@ -8724,6 +8712,32 @@ - (void)zoom:(id)sender
 #endif
 }
 
+- (void)setAppearance
+{
+#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101000
+  struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
+  NSAppearance *appearance = nil;
+
+  NSTRACE ("[EmacsWindow setAppearance]");
+
+#ifndef NSAppKitVersionNumber10_10
+#define NSAppKitVersionNumber10_10 1343
+#endif
+
+  if (NSAppKitVersionNumber < NSAppKitVersionNumber10_10)
+    return;
+
+  if (FRAME_NS_APPEARANCE (f) == ns_appearance_vibrant_dark)
+    appearance =
+      [NSAppearance appearanceNamed:NSAppearanceNameVibrantDark];
+  else if (FRAME_NS_APPEARANCE (f) == ns_appearance_aqua)
+    appearance =
+      [NSAppearance appearanceNamed:NSAppearanceNameAqua];
+
+  [self setAppearance:appearance];
+#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 101000 */
+}
+
 - (void)setFrame:(NSRect)windowFrame
          display:(BOOL)displayViews
 {
-- 
2.24.0