Subject: Re: bug#56305: 29.0.50; 'yes-or-no-p' deselects minibuffer frame

From: Alan Mackenzie <[email-masked]>
Date: Wed, 6 Jul 2022 17:04:40 +0000

Hello, Eli, Martin and Stefan.

On Tue, Jul 05, 2022 at 19:24:02 +0300, Eli Zaretskii wrote:
> > Date: Tue, 5 Jul 2022 15:59:00 +0000
> > Cc: [email-masked], [email-masked], [email-masked]
> > From: Alan Mackenzie <[email-masked]>

> > > > After typing C-x C-c, rather than exiting, this particular Emacs
> > > > prompts:

> > > >     "Active processes exist; kill them and exit anyway? (yes or no) "

> > > > on MBF and it opens a window *Process List* on NF.

> > > Sounds right to me: the frame where Emacs presents some important
> > > information has focus.  If you think this is wrong, please tell why.

> > Well, I don't have a firm opinion on this, but yes-or-no-p is an active
> > function, here.  We always leave the minibuffer as the selected window
> > for this function, certainly when we've a normal minibuffer in the frame.
> > Why should it be different when we've got a minibuffer-only frame?

> > Also, the mechanism by which NF gets the focus in the bug scenario
> > appears to be random.  When the focus starts out in NF and we do C-x C-c,
> > the focus moves to MBF.  This is inconsistent.

> > The place where the randomness takes effect is the 

> >     Fredirect_frame_focus (gfocus, frame);

> > in do_switch_frame I drew attention to yesterday.

> Do you have a suggestion for a change there to improve the behavior?

I do now.  I think we should expunge the entire section of code.

I've spent several hours trying to make sense of it, and failed.  The
code section is 30 years old, and Jim Blandy's comment (from 1992)
suggests that the code was inserted to enable movement between frames
using other-window.

That code was written a few months before the new function other-window
was first committed.  The #ifdef 0 made its appearance in 1993, it being
written by Karl Heuer.

My feeling is that the code section became redundant in the early 1990s,
immediately after the introduction of other-frame, but lived on since
nobody could be sure it wasn't needed.

As I said, I don't understand the code section, and my Emacs appears to
run OK without it.  I think we should get rid of it.  Alternatively, if
somebody else can see a purpose for it, maybe we could amend it to leave
that purpose intact and solve Martin's bug #56305 at the same time.

Here's the patch (based on master) I propose should be committed,
possibly experimentally.  Comments would we welcome:

diff --git a/src/frame.c b/src/frame.c
index c21461d49f..f9e4b2a0e2 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1477,59 +1477,6 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
   else if (f == sf)
     return frame;
 
-  /* If a frame's focus has been redirected toward the currently
-     selected frame, we should change the redirection to point to the
-     newly selected frame.  This means that if the focus is redirected
-     from a minibufferless frame to a surrogate minibuffer frame, we
-     can use `other-window' to switch between all the frames using
-     that minibuffer frame, and the focus redirection will follow us
-     around.  */
-#if 0
-  /* This is too greedy; it causes inappropriate focus redirection
-     that's hard to get rid of.  */
-  if (track)
-    {
-      Lisp_Object tail;
-
-      for (tail = Vframe_list; CONSP (tail); tail = XCDR (tail))
-	{
-	  Lisp_Object focus;
-
-	  if (!FRAMEP (XCAR (tail)))
-	    emacs_abort ();
-
-	  focus = FRAME_FOCUS_FRAME (XFRAME (XCAR (tail)));
-
-	  if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
-	    Fredirect_frame_focus (XCAR (tail), frame);
-	}
-    }
-#else /* ! 0 */
-  /* Instead, apply it only to the frame we're pointing to.  */
-#ifdef HAVE_WINDOW_SYSTEM
-  if (track && FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->get_focus_frame)
-    {
-      Lisp_Object focus, gfocus;
-
-      gfocus = FRAME_TERMINAL (f)->get_focus_frame (f);
-      if (FRAMEP (gfocus))
-	{
-	  focus = FRAME_FOCUS_FRAME (XFRAME (gfocus));
-	  if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ())
-	      /* Redirect frame focus also when FRAME has its minibuffer
-		 window on the selected frame (see Bug#24500).
-
-		 Don't do that: It causes redirection problem with a
-		 separate minibuffer frame (Bug#24803) and problems
-		 when updating the cursor on such frames.
-	      || (NILP (focus)
-		  && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window)))  */
-	    Fredirect_frame_focus (gfocus, frame);
-	}
-    }
-#endif /* HAVE_X_WINDOWS */
-#endif /* ! 0 */
-
   if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
     resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);

-- 
Alan Mackenzie (Nuremberg, Germany).