]> git.eshelyaron.com Git - emacs.git/commitdiff
Make frames record when their selected window was the mini-window
authorAlan Mackenzie <acm@muc.de>
Mon, 31 May 2021 16:24:11 +0000 (16:24 +0000)
committerAlan Mackenzie <acm@muc.de>
Mon, 31 May 2021 16:24:11 +0000 (16:24 +0000)
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
src/frame.h
src/window.c

index e3d65dd28f36ef2af1fa2de07232fca29729e69b..623e4ba2cdeda416e2c207241a29ba429dbe3a2e 100644 (file)
@@ -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;
 }
 
index 75a0b184c19bd24ea9f44ad389bf44f7f835b609..cad3df5ae108ddf2e4a9979268808aa37eeb1f1d 100644 (file)
@@ -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
index 9961c54161da0a6b66c940d70bd8a1f707f8135b..2d98ae5f156123cd61d4d794a240c2a52708bde6 100644 (file)
@@ -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 ();