Subject: bug#48674: Frames and minibuffer bug

From: martin rudalics <[email-masked]>
Date: Sat, 29 May 2021 17:12:58 +0200

> When the user switches from F1 to F2 with C-x 5 o, and there was an
 > active minibuffer on F1, that MB gets moved to F2.  The user then
 > terminnates the MB....then switches back to F1.  There is no longer an
 > active MB.
 >
 >> As a user I can always do
 >
 >> (select-window (minibuffer-window))
 >
 >> regardless of whether a minibuffer is active.  Switching away from that
 >> window's frame and back to it is problematic in Emacs 27 - no window has
 >> the active cursor.  You apparently fixed this by selecting the frame's
 >> first window when switching back.  Right?
 >
 > Yes.

This is safe but not quite right.  The last window on that frame
selected before the minibuffer window got selected should be selected
instead - that's the window returned by `minibuffer-selected-window'
immediately after selecting the minibuffer window.  We'd probably have
to put that into the frame structure to make it work but this can wait.

 >> One reason why I ask is because with emacs -Q and the present patch
 >
 >> (setq default-frame-alist '((minibuffer . nil)))
 >
 >> followed by C-x 5 2 and
 >
 >> (select-window (minibuffer-window))
 >
 >> in the new frame violates the assertion on line 548 of window.c
 >
 >>         /* Fselect_frame called us back so we've done all the work already.  */
 >>         eassert (EQ (window, selected_window));
 >
 >> with the backtrace below.
 >
 > Just as a quick aside, how do I configure Emacs so as to generate these
 > easserts?  At the moment I've got CFLAGS='-O0 -g3' and --enable-checking

I use

  --enable-checking='yes,glyphs' --enable-check-lisp-object-type=yes

but cannot tell which ones are right, which matter and from where I
obtained them.

 > in my ./configure command line.  I think I'm missing something.
 >
 >> Basically, I would try to avoid that a non-selected frame's selected
 >> window is an inactive minibuffer window.  But I'm not sure how difficult
 >> it is to achieve that.
 >
 > That's the way it currently is (without the patch).  It is difficult to
 > make it work properly.
 >
 > Maybe the best workaround would be to create a new flag in struct frame,
 > which when set means "select mini-window if "possible" when selecting
 > this frame".  "Possible" meaning there's an active MB.
 > (i) This flag would be set, somehow, by with-selected-frame when moving
 > away from F1.

I doubt that anyone knows when we move away from a frame.  With

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

do in the normal, non-minibuffer frame

(select-window (minibuffer-window))

You will see that the previous window remains selected but its mode line
changes to inactive.  So even the display engine doesn't know which
frame is selected here.  Maybe on purpose ...

 > (ii) do_switch_frame would test this flag, act on it, and clear it.
 > f->flag would always be clear when f is the selected frame.
 >
 > With this, F1's selected window would be moved away from the mini-window
 > and the flag set, when F2 gets selected.  Or something like that.

do_switch_frame is called by (i) and (ii) - so how would you "set" this
flag in (i) and "test this flag and act on it" in (ii)?  How would
do_switch_frame distinguish between (i) and (ii)?

OTOH what would go wrong if we did always auto-select a minibuffer
window in do_switch_frame when it is its `frame-selected-window' and
`minibuffer-depth' is non-zero regardless of whether the window's
minibuffer is on live_minibuffer_p or not?  If it is not, then this
frame would just become the next participant in moving the minibuffer
from one frame to another.

martin