Subject: Re: bug#61525: 29.0.60; delete-frame will raise frames in another virtual desktop

From: Daniel Martín <[email-masked]>
Date: Thu, 16 Feb 2023 00:48:59 +0100

Eli Zaretskii <[email-masked]> writes:

>> +void ns_make_frame_key_window (struct frame *f)
>> +{
>> +  [[FRAME_NS_VIEW (f) window] makeKeyWindow];
>> +}
>
> Is this new call guaranteed to exist and work well on all the
> supported OS versions where we have the NS build?  I wouldn't want to
> fix this on some systems and break it on others at the same time.

makeKeyWindow is a very old API that should be available on every macOS
and GNUstep we support, AFAIK.  I see usages of that API in other parts
of the NS build, in things as central as frame creation, and they are
not protected by any version or system check.

>
> Alternatively, can we come up with a change that does both what the
> old code did and this addition?  That old code did work at some point,
> I presume?

This is not the case of the old code breaking at some point.  It's a
difference in behavior between the GNU/Linux version of Emacs and the NS
version of Emacs.  In GNU/Linux, if you place an Emacs frame in a
separate desktop and press C-x 5 0, the window manager does not
automatically switch to the desktop where the other Emacs frames reside.

I don't know the reason why the NS build has been calling raise-frame
for so long.  I presume it was considered a good enough way to refocus
to another frame after closing one, in a world where virtual desktops
were not very common and the behavior reported by the OP was ignored.

I've attached a revised version of the patch, to fix a couple of code
style issues.

>From 07035d7bfadff32d6ff954c221331f2060e0f5fc Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Mart=C3=ADn?= <[email-masked]>
Date: Wed, 15 Feb 2023 16:33:14 +0100
Subject: [PATCH] [NS] Do not raise a different frame when closing a frame

* src/frame.h: Declare an NS-only function to make a frame the key
window.
* src/nsfns.m (ns_make_frame_key_window): Implement it.
* src/frame.c (delete_frame): Call ns_make_frame_key_window instead of
Fraise_frame.  (Bug#61525)
---
 src/frame.c | 5 ++---
 src/frame.h | 5 +++++
 src/nsfns.m | 6 ++++++
 3 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/src/frame.c b/src/frame.c
index 983424b0bee..b2319a35aed 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -2152,9 +2152,8 @@ delete_frame (Lisp_Object frame, Lisp_Object force)
 	/* Under NS, there is no system mechanism for choosing a new
 	   window to get focus -- it is left to application code.
 	   So the portion of THIS application interfacing with NS
-	   needs to know about it.  We call Fraise_frame, but the
-	   purpose is really to transfer focus.  */
-	Fraise_frame (frame1);
+	   needs to make the frame we switch to the key window.  */
+	ns_make_frame_key_window (XFRAME (frame1));
 #endif
 
       do_switch_frame (frame1, 1, Qnil);
diff --git a/src/frame.h b/src/frame.h
index b95b94c7685..30c1de20fde 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -1380,6 +1380,11 @@ window_system_available (struct frame *f)
 extern void frame_size_history_plain (struct frame *, Lisp_Object);
 extern void frame_size_history_extra (struct frame *, Lisp_Object,
 				      int, int, int, int, int, int);
+#ifdef NS_IMPL_COCOA
+/* Implemented in nsfns.m.  */
+extern void ns_make_frame_key_window (struct frame *);
+#endif
+
 extern Lisp_Object Vframe_list;
 
 /* Value is a pointer to the selected frame.  If the selected frame
diff --git a/src/nsfns.m b/src/nsfns.m
index 8804a7df7cf..96434230cc6 100644
--- a/src/nsfns.m
+++ b/src/nsfns.m
@@ -685,6 +685,12 @@ Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side.
   SET_FRAME_GARBAGED (f);
 }
 
+void
+ns_make_frame_key_window (struct frame *f)
+{
+  [[FRAME_NS_VIEW (f) window] makeKeyWindow];
+}
+
 /* tabbar support */
 static void
 ns_set_tab_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
-- 
2.34.1