Subject: Re: bug#48674: Frames and minibuffer bug

From: Alan Mackenzie <[email-masked]>
Date: Thu, 27 May 2021 20:01:19 +0000

Hello, Martin.

On Thu, May 27, 2021 at 18:33:45 +0200, martin rudalics wrote:
>  > What is happening is that the with-selected-frame invocation is
>  > selecting (temporarily) a different frame from the minibuffer's
>  > frame.  This has the (intended) side effect of making the MB no
>  > longer selected in that frame.  When the MB's frame becomes selected
>  > again, nothing makes the mini-window the selected window.  This
>  > needs fixing.

> Does this mean that the

>    Fselect_window (f->selected_window, norecord);

> in do_switch_frame fails?  If so, why?

For some values of "fails", yes.  When we're in frame F1's minibuffer,
and do (with-selected-frame F2 (foo)):
(i) Frame F2 becomes selected.
(ii) The current window in F1 ceases to be the mini-window, becoming some
other window.
(iii) The minibuffer is moved from F1 to F2.

(iv) We evaluate (foo).

(v) Frame F1 becomes selected again.
(vi) The current window in F1 doesn't revert to being the mini-window.

> Do we anywhere violate the

>    (eq (selected-window) (frame-selected-window (selected-frame)))

> invariant?

No.  The variables selected-\(window\|frame\) are not set directly
anywhere in minibuf.c, only by calling functions like Fselect_window.

> That might be fatal.  Both, `with-selected-frame' and
> `with-selected-window', should leave no traces behind.

This is what has preoccupied me over the last few hours.  It seems we
want do_switch_frame to do different things for (i) a "permanent" frame
switch (e.g. C-x 5 o) and (i) a "temporary" frame switch (e.g.
with-selected-frame).  If the selected window in F1 is the mini-window,
we want it to select a different window in (i), but stay the same in
(ii). 

Or perhaps we want a variant of select-frame which wouldn't move a stack
of minibuffers from F1 to F2.  Something like Ftemporarily_select_frame,
which would come with discouragement from use in its doc string, and
wouldn't be interactive.  with-selected-frame would use this.  Something
like (untested):

DEFUN ("temporarily-select-frame", Ftemporarily_select_frame,
       Stemporarily_select_frame, 1, 1, null,
       doc: /* Temporarily select FRAME.

More doc string.......

This function returns FRAME, or nil if FRAME has been deleted.  */)
  (Lisp_Object frame)
{
  struct frame *f;

  CHECK_LIVE_FRAME (frame);
  f = XFRAME (frame);

  if (FRAME_TOOLTIP_P (f))
    /* Do not select a tooltip frame (Bug#47207).  */
    error ("Cannot select a tooltip frame");
  else
    return do_switch_frame (frame, 1, 0, Qt, 1); <==== Extra argument here.
}

(This is all with minibuffer-follows-selected-frame set to t.)

>  > Martin, that Qt in the Fselect_window call (the NORECORD argument) -
>  > would it be perhaps be better as Qnil?

>  > diff --git a/src/minibuf.c b/src/minibuf.c
>  > index cffb7fe787..3468643a7e 100644
>  > --- a/src/minibuf.c
>  > +++ b/src/minibuf.c
>  > @@ -893,6 +893,11 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
>  >
>  >     run_hook (Qminibuffer_setup_hook);
>  >
>  > +  /* If the above hook has made the mini-window no longer the selected
>  > +     window, restore it.  */
>  > +  if (!EQ (selected_window, minibuf_window))
>  > +    Fselect_window (minibuf_window , Qt);
>  > +

> Are we sure that we want to disallow a function on
> `minibuffer-setup-hook' to change the selected window?  With Emacs 27

> (defun foo ()
>    (select-window (frame-first-window)))

> (add-hook 'minibuffer-setup-hook 'foo)

> works without any problems here.

Are you sure?  For me, that setup makes C-x C-f open a minibuffer, but
leave point in the same window, not the miniwindow.  That was a quick try
with the emacs-27 branch, not Emacs 27.{1,2}, and was on a GUI.

I think we should disallow selecting windows in minibuffer-setup-hook.
This hook is run after the mini-window has been selected in read_minibuf,
just before the recursive edit.

> The NORECORD argument is important only if you need it - so far, the
> previous buffers of the minibuffer window were largely ignored.

Thanks.  I'll think about that when my head's a bit clearer.

> martin