From 2ee5ce208f212ed658cf2125ef6bc24a435dda50 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Mon, 31 May 2021 16:24:11 +0000 Subject: [PATCH] Make frames record when their selected window was the mini-window When a frame in this state is selected again by Fselect_frame (but not by Fselect_window), the mini-window rather than the frame's currently selected window, is chosen for selection, should there still be an active minibuffer in it. This fixes bug #48674. * src/frame.h (struct frame): Add new boolean field select_mini_window_flag. * src/frame.c (make_frame): Initialize select_mini_window_flag to false. (do_switch_frame): Set the new flag appropriately for the old frame, and process the new frame's setting of this flag, before setting it to false. * src/window.c (select_window): Set f->select_mini_window_flag to false. (Fset_frame_selected_window, Fdelete_other_windows_internal) (Fdelete_window_internal): Add comments clarifying that there is no clearing of f->select_mini_window_flag in these functions. --- src/frame.c | 12 +++++++++++- src/frame.h | 5 +++++ src/window.c | 10 ++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/src/frame.c b/src/frame.c index e3d65dd28f3..623e4ba2cde 100644 --- a/src/frame.c +++ b/src/frame.c @@ -982,6 +982,7 @@ make_frame (bool mini_p) f->ns_transparent_titlebar = false; #endif #endif + f->select_mini_window_flag = false; /* This one should never be zero. */ f->change_stamp = 1; root_window = make_window (); @@ -1542,7 +1543,17 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor tty->top_frame = frame; } + sf->select_mini_window_flag = MINI_WINDOW_P (XWINDOW (sf->selected_window)); + selected_frame = frame; + + move_minibuffers_onto_frame (sf, for_deletion); + + if (f->select_mini_window_flag + && !NILP (Fminibufferp (XWINDOW (f->minibuffer_window)->contents, Qt))) + f->selected_window = f->minibuffer_window; + f->select_mini_window_flag = false; + if (! FRAME_MINIBUF_ONLY_P (XFRAME (selected_frame))) last_nonminibuf_frame = XFRAME (selected_frame); @@ -1559,7 +1570,6 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor #endif internal_last_event_frame = Qnil; - move_minibuffers_onto_frame (sf, for_deletion); return frame; } diff --git a/src/frame.h b/src/frame.h index 75a0b184c19..cad3df5ae10 100644 --- a/src/frame.h +++ b/src/frame.h @@ -462,6 +462,11 @@ struct frame in X builds only. */ bool_bf was_invisible : 1; + /* True when the frame isn't selected, and selecting it in the + future should select the mini-window rather than the currently + selected window in the frame, assuming there is still an active + minibuffer in that mini-window. */ + bool_bf select_mini_window_flag : 1; /* Bitfield area ends here. */ /* This frame's change stamp, set the last time window change diff --git a/src/window.c b/src/window.c index 9961c54161d..2d98ae5f156 100644 --- a/src/window.c +++ b/src/window.c @@ -468,6 +468,7 @@ Return WINDOW. */) else { fset_selected_window (XFRAME (frame), window); + /* Don't clear FRAME's select_mini_window_flag here. */ return window; } } @@ -517,6 +518,9 @@ select_window (Lisp_Object window, Lisp_Object norecord, /* Do not select a tooltip window (Bug#47207). */ error ("Cannot select a tooltip window"); + /* We deinitely want to select WINDOW, not the mini-window. */ + f->select_mini_window_flag = false; + /* Make the selected window's buffer current. */ Fset_buffer (w->contents); @@ -3242,6 +3246,9 @@ window-start value is reasonable when this function is called. */) if (EQ (selected_frame, w->frame)) Fselect_window (window, Qnil); else + /* Do not clear f->select_mini_window_flag here. If the + last selected window on F was an active minibuffer, we + want to return to it on a later Fselect_frame. */ fset_selected_window (f, window); } } @@ -5153,6 +5160,9 @@ Signal an error when WINDOW is the only window on its frame. */) if (EQ (FRAME_SELECTED_WINDOW (f), selected_window)) Fselect_window (new_selected_window, Qt); else + /* Do not clear f->select_mini_window_flag here. If the + last selected window on F was an active minibuffer, we + want to return to it on a later Fselect_frame. */ fset_selected_window (f, new_selected_window); unblock_input (); -- 2.39.2