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

From: martin rudalics <[email-masked]>
Date: Mon, 11 Jul 2022 09:45:59 +0200

> Thanks!  I use xfce, too.  But I haven't changed anything here away from
 > its default.  I run Emacs on a tty anyway.

So you implemented 'minibuffer-follows-selected-frame' despite the fact
that multiple frames hardly make sense on your usual setup?

 >> Now note that when in my scenario I type C-x C-c, the minibuffer frame
 >> is selected and has focus.
 >
 > But not raised, though?  Surely the MB frame being selected and having
 > focus is what we want, so that we can type "yes" or "no" next.

With "when" I meant "at the time" I type C-x C-c.

 > Try running GDB in an Emacs on a Linux tty.  That's what I do anyway.  I
 > seem to remember watching the focus, last time I did this, a day or two
 > ago.

I have no experience with running GDB from anywhere but Emacs itself.
IIRC Linux ttys are full-screen, so where would my Emacs frames fit in?

 > Anyway, we'll have to decide soon what to do for Emacs 28.2.  The first
 > pretest is already out there.  What we do needs to be simple and safe.
 > The alternatives so far seem to be do nothing, apply the 53-line
 > deletion from master (which Eli has already rejected) or apply my patch
 > above (fixed to work with tty's).  At the moment, I would favour the
 > last of these.

For Emacs 28.2 I could imagine something like

diff --git a/src/frame.c b/src/frame.c
index 0c278259a7..27442ee120 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1499,7 +1499,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
  #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)
+  if (track && NILP (Vinhibit_redisplay)
+      && FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->get_focus_frame)
      {
        Lisp_Object focus, gfocus;

that is use the analogous unpleasant hack from resize_mini_window.

 > select-window and select-frame should NOT move the focus.

I'd like to agree with you but implementing it is virtually impossible.
Emacs would probably stop working immediately.  Just try to tell people
that 'select-window' will not give input focus to a window only because
it happens to reside on another frame.

 > select-frame
 > is even documented (in the Elisp manual) not to do this.  That
 > documentation is not true for Emacs 28.x, but may now have become true
 > in master since I removed those 53 lines from do_switch_frame, but I'm
 > not sure.

The Elisp manual is controversial about this.  A sentence like

   Note that sometimes selecting a window is not enough to show it, or
   make its frame the top-most frame on display: you may also need to
   raise the frame or make sure input focus is directed to that frame.

wouldn't make sense if in a majority of cases selecting a window would
_not_ also raise its frame and direct input focus to it.

 >> Unfortunately, it breaks C-x o.  Try with my scenario but instead of
 >> answering the 'yes-or-no-p' question type C-x o.  With Emacs 28.1 this
 >> selects the window on top of the normal frame.  With current master it
 >> does nothing.
 >
 > I don't think that's true.  It selects the other window on the normal
 > frame (which is the selected frame), but retains the focus in the
 > minibuffer frame (the focus being redirected from the normal frame).

Indeed.  Which means that it contradicts the Elisp manual which says
about 'select-window' that

   This function makes WINDOW the selected window and the window
   selected within its frame, and selects that frame.

and about the window “selected within the frame”

   For the selected frame, that window is
   called the “selected window”—the one in which most editing takes place,
   and in which the cursor for selected windows appears

Here the cursor for the selected window appears in the minibuffer frame
window and that's what fooled me.  In which window should the cursor
appear in your opinion?

 >> It doesn't even tell me that there is no other window to select.  So
 >> this cure is certainly worse than the disease.
 >
 > I think that might be over-stating things.  Most of the time, users are
 > just going to be typing "yes" or "no" here.

Then with

emacs -Q --eval "(setq default-frame-alist '((minibuffer . nil)))"

select the "normal" frame and type C-h f.  In the minibuffer frame now
type C-x o.  This always used to select _and_ focus the window on the
normal frame and would be needed, for example, to fetch the name of the
function to describe from the normal window.  This is the behavior
described in the comment your patch elided as

   /* 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.  */

I we were to change that, we would change the entire cyclic ordering of
windows concept which explicitly states that "If the minibuffer is
active, the minibuffer window is included too" and that window may
reside on any frame.

martin