Subject: bug#63967: 28.2; switch-to-buffer in normal window fails if minibuffer window is active

From: Eli Zaretskii <[email-masked]>
Date: Sat, 10 Jun 2023 11:28:29 +0300

> Date: Sat, 10 Jun 2023 08:52:57 +0200
> Cc: [email-masked]
> From: martin rudalics <[email-masked]>
> 
>  > diff --git a/lisp/window.el b/lisp/window.el
>  > index a11b1a5..6777944 100644
>  > --- a/lisp/window.el
>  > +++ b/lisp/window.el
>  > @@ -8941,7 +8941,9 @@ switch-to-buffer
>  >                       "Cannot switch buffers in a dedicated window")))
>  >                   ('pop nil)
>  >                   (_ (set-window-dedicated-p nil nil) 'force-same-window)))))))
>  > -     (list (read-buffer-to-switch "Switch to buffer: ") nil force-same-window)))
>  > +     (save-selected-window
>  > +       (list
>  > +        (read-buffer-to-switch "Switch to buffer: ") nil force-same-window))))
>  >     (let ((buffer (window-normalize-buffer-to-switch-to buffer-or-name))
>  >           (set-window-start-and-point (not switch-to-buffer-obey-display-actions)))
>  >       (cond
> 
> That wouldn't help in all other use cases of read_minibuf where the user
> will be thrown back to the minibuffer window as well.  I'd rather try (the
> still timid)
> 
> -static void minibuffer_unwind (void);
> +static void minibuffer_unwind (Lisp_Object);
> ...
> -  record_unwind_protect_void (minibuffer_unwind);
> +  record_unwind_protect (minibuffer_unwind, selected_window);
> ...
> -minibuffer_unwind (void)
> +minibuffer_unwind (Lisp_Object old_selected_window)
> ...
> +	  if (!EQ (old_selected_window, FRAME_SELECTED_WINDOW (f)))
> +	    Fset_frame_selected_window (exp_MB_frame, window, Qnil);
> 
> since the last line seems to suggest that exp_MB_frame should not be the
> selected frame.

That works, but does it make sens to do the other stuff in that if
clause in that case?  We do:

      if (!NILP (w->prev_buffers))
	{
	  entry = Fcar (w->prev_buffers);
	  w->prev_buffers = Fcdr (w->prev_buffers);
	  set_window_buffer (window, Fcar (entry), 0, 0);
	  Fset_window_start (window, Fcar (Fcdr (entry)), Qnil);
	  Fset_window_point (window, Fcar (Fcdr (Fcdr (entry))));
	  /* set-window-configuration may/will have unselected the
	     mini-window as the selected window.  Restore it. */
	  if (!EQ (orig_selected_window, FRAME_SELECTED_WINDOW (f)))
	    Fset_frame_selected_window (exp_MB_frame, window, Qnil);
	}

Does it make sense to manipulate the buffer, window-start, and
window-point of WINDOW if we are not going to make it the selected
window?

In general, I don't think I understand the logic of this function at
all.  Since this is about the "expired minibuffer", then the code
seems to assume that when a minibuffer is "expired", and there are
previous minibuffers for that mini-window, the mini-window stays the
selected-window?  But that is not true when recursive minibuffers are
enabled, right?

IOW, I wonder whether your suggested change just postpones the problem
by moving it to the rarer cases when more than one frame is involved
in this dance.  Why is it okay to set the selected-window of another
frame here?