aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2021-03-21 16:54:31 +0000
committerAlan Mackenzie2021-03-21 16:54:31 +0000
commit7c2ebf6e23663fdc7b1880a4d7caeadc8c47c00e (patch)
tree19216102a0b7fc0212b8cdfa6fc8d70ed6ad86b4
parente276810dff9838e1bb8c2ec450f85835ed60bf14 (diff)
downloademacs-7c2ebf6e23663fdc7b1880a4d7caeadc8c47c00e.tar.gz
emacs-7c2ebf6e23663fdc7b1880a4d7caeadc8c47c00e.zip
Prevent open minibuffers getting lost when their frame gets deleted
This happened with minibuffer-follows-selected-frame set to t. * doc/emacs/mini.texi (Basic Minibuffer): State where a command's action takes place when a minibuffer's frame has been deleted. * lisp/window.el (window--before-delete-windows, record-window-buffer): Take into account that minibuffers are now recorded on w->prev_buffers field. * src/fns.c (merge_c): New version of `merge' taking a C function, rather than a Lisp function as the comparison function. * src/frame.c (do_switch_frame): Pass arguments sf and for_deletion to move_minibuffers_onnto_frame. * src/lisp.h (top level): Declare merge_c and move_minibuffers_onto_selected_frame. * src/minibuf.c (MB_frame): New Lisp_Object recording the minibuffer's frame. (choose_minibuf_frame): Remove all code except that which sets minibuf_window to the current frame's minibuffer. (minibuffer_ent_greater): New comparison function, passed to merge_c. (zip_minibuffer_stacks): New function. (move_minibuffers_onto_frame): Renamed from `move_minibuffer_onto_frame' given two arguments, the old frame and for_deletion, and simplified. Minibuffers are now stacked in the mini-window's ->prev_buffers field. (read_minibuf): Several detailed amendments. (exp_MB_frame): New Lisp_Object, the expired minibuffer's frame. (read_minibuf_unwind): Search for the expired minibuffer's frame, rather than taking it from (unreliable) variables. Switch temporarily to this frame for tidying up operations. (minibuffer_unwind): New function which pops a stacked minibuffer. (syms_of_minibuf): Call staticpro for the two new Lisp variables. * src/window.c (Fset_window_configuration): Don't record minibuffers with record-window-buffer. * src/xdisp.c (gui_consider_frame_title): Remove redundant Fselect_window, which caused an unwanted frame switch. Amend the arguments to format_mode_line_unwind_data to match.
-rw-r--r--doc/emacs/mini.texi4
-rw-r--r--lisp/window.el5
-rw-r--r--src/fns.c46
-rw-r--r--src/frame.c2
-rw-r--r--src/lisp.h3
-rw-r--r--src/minibuf.c292
-rw-r--r--src/window.c3
-rw-r--r--src/xdisp.c3
8 files changed, 242 insertions, 116 deletions
diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi
index 9c1b9757593..d0865c5d0bd 100644
--- a/doc/emacs/mini.texi
+++ b/doc/emacs/mini.texi
@@ -82,7 +82,9 @@ after a recursive minibuffer has been opened in the current command
82(@pxref{Recursive Mini,,, elisp}). This option is mainly to retain 82(@pxref{Recursive Mini,,, elisp}). This option is mainly to retain
83(approximately) the behavior prior to Emacs 28.1. Note that the 83(approximately) the behavior prior to Emacs 28.1. Note that the
84effect of the command, when you finally finish using the minibuffer, 84effect of the command, when you finally finish using the minibuffer,
85always takes place in the frame where you first opened it. 85always takes place in the frame where you first opened it. The sole
86exception is that when that frame no longer exists, the action takes
87place in the currently selected frame.
86 88
87@node Minibuffer File 89@node Minibuffer File
88@section Minibuffers for File Names 90@section Minibuffers for File Names
diff --git a/lisp/window.el b/lisp/window.el
index cfd9876ed05..f27631bb86a 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4158,7 +4158,7 @@ returned by `window-start' and `window-point' respectively.
4158 4158
4159This function is called only if `switch-to-buffer-preserve-window-point' 4159This function is called only if `switch-to-buffer-preserve-window-point'
4160evaluates non-nil." 4160evaluates non-nil."
4161 (dolist (win (window-list)) 4161 (dolist (win (window-list nil 'no-minibuf))
4162 (let* ((buf (window-buffer (or window win))) 4162 (let* ((buf (window-buffer (or window win)))
4163 (start (window-start win)) 4163 (start (window-start win))
4164 (pos (window-point win)) 4164 (pos (window-point win))
@@ -4416,7 +4416,8 @@ WINDOW must be a live window and defaults to the selected one."
4416 window (assq-delete-all buffer (window-prev-buffers window)))) 4416 window (assq-delete-all buffer (window-prev-buffers window))))
4417 4417
4418 ;; Don't record insignificant buffers. 4418 ;; Don't record insignificant buffers.
4419 (unless (eq (aref (buffer-name buffer) 0) ?\s) 4419 (when (or (not (eq (aref (buffer-name buffer) 0) ?\s))
4420 (minibufferp buffer))
4420 ;; Add an entry for buffer to WINDOW's previous buffers. 4421 ;; Add an entry for buffer to WINDOW's previous buffers.
4421 (with-current-buffer buffer 4422 (with-current-buffer buffer
4422 (let ((start (window-start window)) 4423 (let ((start (window-start window))
diff --git a/src/fns.c b/src/fns.c
index 766e767e123..2cd59c83d91 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -2279,6 +2279,52 @@ merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred)
2279 } 2279 }
2280} 2280}
2281 2281
2282Lisp_Object
2283merge_c (Lisp_Object org_l1, Lisp_Object org_l2, bool (*less) (Lisp_Object, Lisp_Object))
2284{
2285 Lisp_Object l1 = org_l1;
2286 Lisp_Object l2 = org_l2;
2287 Lisp_Object tail = Qnil;
2288 Lisp_Object value = Qnil;
2289
2290 while (1)
2291 {
2292 if (NILP (l1))
2293 {
2294 if (NILP (tail))
2295 return l2;
2296 Fsetcdr (tail, l2);
2297 return value;
2298 }
2299 if (NILP (l2))
2300 {
2301 if (NILP (tail))
2302 return l1;
2303 Fsetcdr (tail, l1);
2304 return value;
2305 }
2306
2307 Lisp_Object tem;
2308 if (less (Fcar (l1), Fcar (l2)))
2309 {
2310 tem = l1;
2311 l1 = Fcdr (l1);
2312 org_l1 = l1;
2313 }
2314 else
2315 {
2316 tem = l2;
2317 l2 = Fcdr (l2);
2318 org_l2 = l2;
2319 }
2320 if (NILP (tail))
2321 value = tem;
2322 else
2323 Fsetcdr (tail, tem);
2324 tail = tem;
2325 }
2326}
2327
2282 2328
2283/* This does not check for quits. That is safe since it must terminate. */ 2329/* This does not check for quits. That is safe since it must terminate. */
2284 2330
diff --git a/src/frame.c b/src/frame.c
index cfdf3b61938..66ae4943ba2 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1487,7 +1487,7 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor
1487#endif 1487#endif
1488 internal_last_event_frame = Qnil; 1488 internal_last_event_frame = Qnil;
1489 1489
1490 move_minibuffer_onto_frame (); 1490 move_minibuffers_onto_frame (sf, for_deletion);
1491 return frame; 1491 return frame;
1492} 1492}
1493 1493
diff --git a/src/lisp.h b/src/lisp.h
index b95f389b890..c67c8b08573 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -3610,6 +3610,7 @@ extern void validate_subarray (Lisp_Object, Lisp_Object, Lisp_Object,
3610extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t, 3610extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t,
3611 ptrdiff_t, ptrdiff_t); 3611 ptrdiff_t, ptrdiff_t);
3612extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object); 3612extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object);
3613extern Lisp_Object merge_c (Lisp_Object, Lisp_Object, bool (*) (Lisp_Object, Lisp_Object));
3613extern Lisp_Object do_yes_or_no_p (Lisp_Object); 3614extern Lisp_Object do_yes_or_no_p (Lisp_Object);
3614extern int string_version_cmp (Lisp_Object, Lisp_Object); 3615extern int string_version_cmp (Lisp_Object, Lisp_Object);
3615extern Lisp_Object concat2 (Lisp_Object, Lisp_Object); 3616extern Lisp_Object concat2 (Lisp_Object, Lisp_Object);
@@ -4348,7 +4349,7 @@ extern void clear_regexp_cache (void);
4348 4349
4349extern Lisp_Object Vminibuffer_list; 4350extern Lisp_Object Vminibuffer_list;
4350extern Lisp_Object last_minibuf_string; 4351extern Lisp_Object last_minibuf_string;
4351extern void move_minibuffer_onto_frame (void); 4352extern void move_minibuffers_onto_frame (struct frame *, bool);
4352extern bool is_minibuffer (EMACS_INT, Lisp_Object); 4353extern bool is_minibuffer (EMACS_INT, Lisp_Object);
4353extern EMACS_INT this_minibuffer_depth (Lisp_Object); 4354extern EMACS_INT this_minibuffer_depth (Lisp_Object);
4354extern EMACS_INT minibuf_level; 4355extern EMACS_INT minibuf_level;
diff --git a/src/minibuf.c b/src/minibuf.c
index 4b1f4b1ff72..d58924ae520 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -59,6 +59,12 @@ Lisp_Object last_minibuf_string;
59 59
60static Lisp_Object minibuf_prompt; 60static Lisp_Object minibuf_prompt;
61 61
62/* The frame containinug the most recently opened Minibuffer. This is
63 used only when `minibuffer-follows-selected-frame' is neither nil
64 nor t. */
65
66static Lisp_Object MB_frame;
67
62/* Width of current mini-buffer prompt. Only set after display_line 68/* Width of current mini-buffer prompt. Only set after display_line
63 of the line that contains the prompt. */ 69 of the line that contains the prompt. */
64 70
@@ -67,6 +73,7 @@ static ptrdiff_t minibuf_prompt_width;
67static Lisp_Object nth_minibuffer (EMACS_INT depth); 73static Lisp_Object nth_minibuffer (EMACS_INT depth);
68static EMACS_INT minibuf_c_loop_level (EMACS_INT depth); 74static EMACS_INT minibuf_c_loop_level (EMACS_INT depth);
69static void set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth); 75static void set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth);
76static bool live_minibuffer_p (Lisp_Object);
70 77
71 78
72/* Return TRUE when a frame switch causes a minibuffer on the old 79/* Return TRUE when a frame switch causes a minibuffer on the old
@@ -78,6 +85,7 @@ minibuf_follows_frame (void)
78 Qt); 85 Qt);
79} 86}
80 87
88#if 0
81/* Return TRUE when a minibuffer always remains on the frame where it 89/* Return TRUE when a minibuffer always remains on the frame where it
82 was first invoked. */ 90 was first invoked. */
83static bool 91static bool
@@ -85,6 +93,7 @@ minibuf_stays_put (void)
85{ 93{
86 return NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame)); 94 return NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame));
87} 95}
96#endif
88 97
89/* Return TRUE when opening a (recursive) minibuffer causes 98/* Return TRUE when opening a (recursive) minibuffer causes
90 minibuffers on other frames to move to the selected frame. */ 99 minibuffers on other frames to move to the selected frame. */
@@ -112,84 +121,85 @@ choose_minibuf_frame (void)
112 emacs_abort (); 121 emacs_abort ();
113 122
114 minibuf_window = sf->minibuffer_window; 123 minibuf_window = sf->minibuffer_window;
115 /* If we've still got another minibuffer open, use its mini-window
116 instead. */
117 if (minibuf_level > 1 && minibuf_stays_put ())
118 {
119 Lisp_Object buffer = get_minibuffer (minibuf_level);
120 Lisp_Object tail, frame;
121
122 FOR_EACH_FRAME (tail, frame)
123 if (EQ (XWINDOW (XFRAME (frame)->minibuffer_window)->contents,
124 buffer))
125 {
126 minibuf_window = XFRAME (frame)->minibuffer_window;
127 break;
128 }
129 }
130 } 124 }
125}
131 126
132 if (minibuf_moves_frame_when_opened () 127/* If ENT1 has a higher minibuffer index than ENT2, return true. More
133 && FRAMEP (selected_frame) 128precisely, compare the buffer components of each window->prev_buffers
134 && FRAME_LIVE_P (XFRAME (selected_frame))) 129entry. */
135 /* Make sure no other frame has a minibuffer as its selected window, 130static bool
136 because the text would not be displayed in it, and that would be 131minibuffer_ent_greater (Lisp_Object ent1, Lisp_Object ent2)
137 confusing. Only allow the selected frame to do this, 132{
138 and that only if the minibuffer is active. */ 133 return this_minibuffer_depth (Fcar (ent1))
139 { 134 > this_minibuffer_depth (Fcar (ent2)) ;
140 Lisp_Object tail, frame;
141 struct frame *of;
142
143 FOR_EACH_FRAME (tail, frame)
144 if (!EQ (frame, selected_frame)
145 && minibuf_level > 1
146 /* The frame's minibuffer can be on a different frame. */
147 && ! EQ (XWINDOW ((of = XFRAME (frame))->minibuffer_window)->frame,
148 selected_frame))
149 {
150 if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
151 Fset_frame_selected_window (frame, Fframe_first_window (frame),
152 Qnil);
153
154 if (!EQ (XWINDOW (of->minibuffer_window)->contents,
155 nth_minibuffer (0)))
156 set_window_buffer (of->minibuffer_window,
157 nth_minibuffer (0), 0, 0);
158 }
159 }
160} 135}
161 136
162/* If `minibuffer_follows_selected_frame' is t and we have a 137/* Move the ordered "stack" of minibuffers from SOURCE_WINDOW to
163 minibuffer, move it from its current frame to the selected frame. 138 DEST_WINDOW, interleaving those minibuffers with any in DEST_WINDOW
164 This function is intended to be called from `do_switch_frame' in 139 to produce an ordered combination. The ordering is by minibuffer
165 frame.c. */ 140 depth. A stack of minibuffers consists of the minibuffer currently
166void move_minibuffer_onto_frame (void) 141 in DEST/SOURCE_WINDOW together with any recorded in the
142 ->prev_buffers field of the struct window. */
143static void
144zip_minibuffer_stacks (Lisp_Object dest_window, Lisp_Object source_window)
167{ 145{
168 if (!minibuf_level) 146 struct window *dw = XWINDOW (dest_window);
169 return; 147 struct window *sw = XWINDOW (source_window);
170 if (!minibuf_follows_frame ()) 148 Lisp_Object acc;
171 return; 149 Lisp_Object d_ent; /* Entry from dw->prev_buffers */
172 if (FRAMEP (selected_frame) 150
173 && FRAME_LIVE_P (XFRAME (selected_frame)) 151 if (!live_minibuffer_p (dw->contents)
174 && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window)) 152 && NILP (dw->prev_buffers))
175 { 153 {
176 EMACS_INT i; 154 set_window_buffer (dest_window, sw->contents, 0, 0);
177 struct frame *sf = XFRAME (selected_frame); 155 Fset_window_start (dest_window, Fwindow_start (source_window), Qnil);
178 Lisp_Object old_frame = XWINDOW (minibuf_window)->frame; 156 Fset_window_point (dest_window, Fwindow_point (source_window));
179 struct frame *of = XFRAME (old_frame); 157 dw->prev_buffers = sw->prev_buffers;
158 set_window_buffer (source_window, get_minibuffer (0), 0, 0);
159 sw->prev_buffers = Qnil;
160 return;
161 }
180 162
181 /* Stack up all the (recursively) open minibuffers on the selected 163 if (live_minibuffer_p (dw->contents))
182 mini_window. */ 164 call1 (Qrecord_window_buffer, dest_window);
183 for (i = 1; i <= minibuf_level; i++) 165 if (live_minibuffer_p (sw->contents))
184 set_window_buffer (sf->minibuffer_window, nth_minibuffer (i), 0, 0); 166 call1 (Qrecord_window_buffer, source_window);
185 minibuf_window = sf->minibuffer_window;
186 if (of != sf)
187 {
188 Lisp_Object temp = get_minibuffer (0);
189 167
190 set_window_buffer (of->minibuffer_window, temp, 0, 0); 168 acc = merge_c (dw->prev_buffers, sw->prev_buffers, minibuffer_ent_greater);
191 set_minibuffer_mode (temp, 0); 169
192 } 170 if (!NILP (acc))
171 {
172 d_ent = Fcar (acc);
173 acc = Fcdr (acc);
174 set_window_buffer (dest_window, Fcar (d_ent), 0, 0);
175 Fset_window_start (dest_window, Fcar (Fcdr (d_ent)), Qnil);
176 Fset_window_point (dest_window, Fcar (Fcdr (Fcdr (d_ent))));
177 }
178 dw->prev_buffers = acc;
179 sw->prev_buffers = Qnil;
180 set_window_buffer (source_window, get_minibuffer (0), 0, 0);
181}
182
183/* If `minibuffer_follows_selected_frame' is t, or we're about to
184 delete a frame which potentially "contains" minibuffers, move them
185 from the old frame to the selected frame. This function is
186 intended to be called from `do_switch_frame' in frame.c. OF is the
187 old frame, FOR_DELETION is true if OF is about to be deleted. */
188void
189move_minibuffers_onto_frame (struct frame *of, bool for_deletion)
190{
191 struct frame *f = XFRAME (selected_frame);
192
193 minibuf_window = f->minibuffer_window;
194 if (!(minibuf_level
195 && (for_deletion || minibuf_follows_frame () || FRAME_INITIAL_P (of))))
196 return;
197 if (FRAME_LIVE_P (f)
198 && !EQ (f->minibuffer_window, of->minibuffer_window))
199 {
200 zip_minibuffer_stacks (f->minibuffer_window, of->minibuffer_window);
201 if (for_deletion && XFRAME (MB_frame) != of)
202 MB_frame = selected_frame;
193 } 203 }
194} 204}
195 205
@@ -221,6 +231,7 @@ without invoking the usual minibuffer commands. */)
221/* Actual minibuffer invocation. */ 231/* Actual minibuffer invocation. */
222 232
223static void read_minibuf_unwind (void); 233static void read_minibuf_unwind (void);
234static void minibuffer_unwind (void);
224static void run_exit_minibuf_hook (void); 235static void run_exit_minibuf_hook (void);
225 236
226 237
@@ -544,7 +555,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
544 Lisp_Object histval; 555 Lisp_Object histval;
545 556
546 Lisp_Object empty_minibuf; 557 Lisp_Object empty_minibuf;
547 Lisp_Object dummy, frame;
548 558
549 specbind (Qminibuffer_default, defalt); 559 specbind (Qminibuffer_default, defalt);
550 specbind (Qinhibit_read_only, Qnil); 560 specbind (Qinhibit_read_only, Qnil);
@@ -626,17 +636,24 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
626 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window)); 636 mini_frame = WINDOW_FRAME (XWINDOW (minibuf_window));
627 637
628 if (minibuf_level > 1 638 if (minibuf_level > 1
639 && !EQ (XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame,
640 MB_frame)
629 && minibuf_moves_frame_when_opened () 641 && minibuf_moves_frame_when_opened ()
630 && (!minibuf_follows_frame () 642 && (!minibuf_follows_frame ()))
631 || (!EQ (mini_frame, selected_frame))))
632 { 643 {
633 EMACS_INT i; 644 struct frame *of = XFRAME (MB_frame);
634 645
635 /* Stack up the existing minibuffers on the current mini-window */ 646 zip_minibuffer_stacks (minibuf_window, of->minibuffer_window);
636 for (i = 1; i < minibuf_level; i++) 647 /* MB_frame's minibuffer can be on a different frame. */
637 set_window_buffer (minibuf_window, nth_minibuffer (i), 0, 0); 648 if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
649 Fset_frame_selected_window (MB_frame,
650 Fframe_first_window (MB_frame), Qnil);
638 } 651 }
652 MB_frame = XWINDOW (XFRAME (selected_frame)->minibuffer_window)->frame;
653 if (live_minibuffer_p (XWINDOW (minibuf_window)->contents))
654 call1 (Qrecord_window_buffer, minibuf_window);
639 655
656 record_unwind_protect_void (minibuffer_unwind);
640 record_unwind_protect (restore_window_configuration, 657 record_unwind_protect (restore_window_configuration,
641 Fcons (Qt, Fcurrent_window_configuration (Qnil))); 658 Fcons (Qt, Fcurrent_window_configuration (Qnil)));
642 659
@@ -771,23 +788,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
771 empty_minibuf = get_minibuffer (0); 788 empty_minibuf = get_minibuffer (0);
772 set_minibuffer_mode (empty_minibuf, 0); 789 set_minibuffer_mode (empty_minibuf, 0);
773 790
774 FOR_EACH_FRAME (dummy, frame)
775 {
776 Lisp_Object root_window = Fframe_root_window (frame);
777 Lisp_Object mini_window = XWINDOW (root_window)->next;
778 Lisp_Object buffer;
779
780 if (!NILP (mini_window) && !EQ (mini_window, minibuf_window)
781 && !NILP (Fwindow_minibuffer_p (mini_window)))
782 {
783 buffer = XWINDOW (mini_window)->contents;
784 if (!live_minibuffer_p (buffer))
785 /* Use set_window_buffer instead of Fset_window_buffer (see
786 discussion of bug#11984, bug#12025, bug#12026). */
787 set_window_buffer (mini_window, empty_minibuf, 0, 0);
788 }
789 }
790
791 /* Display this minibuffer in the proper window. */ 791 /* Display this minibuffer in the proper window. */
792 /* Use set_window_buffer instead of Fset_window_buffer (see 792 /* Use set_window_buffer instead of Fset_window_buffer (see
793 discussion of bug#11984, bug#12025, bug#12026). */ 793 discussion of bug#11984, bug#12025, bug#12026). */
@@ -908,7 +908,9 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
908 unbind_to (count, Qnil); 908 unbind_to (count, Qnil);
909 909
910 /* Switch the frame back to the calling frame. */ 910 /* Switch the frame back to the calling frame. */
911 if (!EQ (selected_frame, calling_frame) 911 if ((!EQ (selected_frame, calling_frame)
912 || !EQ (XWINDOW (XFRAME (calling_frame)->minibuffer_window)->frame,
913 calling_frame))
912 && FRAMEP (calling_frame) 914 && FRAMEP (calling_frame)
913 && FRAME_LIVE_P (XFRAME (calling_frame))) 915 && FRAME_LIVE_P (XFRAME (calling_frame)))
914 call2 (intern ("select-frame-set-input-focus"), calling_frame, Qnil); 916 call2 (intern ("select-frame-set-input-focus"), calling_frame, Qnil);
@@ -1026,6 +1028,14 @@ run_exit_minibuf_hook (void)
1026 safe_run_hooks (Qminibuffer_exit_hook); 1028 safe_run_hooks (Qminibuffer_exit_hook);
1027} 1029}
1028 1030
1031/* This variable records the expired minibuffer's frame between the
1032 calls of `read_minibuf_unwind' and `minibuffer_unwind'. It should
1033 be used only by these two functions. Note that the same search
1034 method for the MB's frame won't always work in `minibuffer_unwind'
1035 because the intervening `restore-window-configuration' will have
1036 changed the buffer in the mini-window. */
1037static Lisp_Object exp_MB_frame;
1038
1029/* This function is called on exiting minibuffer, whether normally or 1039/* This function is called on exiting minibuffer, whether normally or
1030 not, and it restores the current window, buffer, etc. */ 1040 not, and it restores the current window, buffer, etc. */
1031 1041
@@ -1036,6 +1046,28 @@ read_minibuf_unwind (void)
1036 Lisp_Object calling_frame; 1046 Lisp_Object calling_frame;
1037 Lisp_Object calling_window; 1047 Lisp_Object calling_window;
1038 Lisp_Object future_mini_window; 1048 Lisp_Object future_mini_window;
1049 Lisp_Object saved_selected_frame = selected_frame;
1050 Lisp_Object window, frames;
1051 struct window *w;
1052 struct frame *f;
1053
1054 /* Locate the expired minibuffer. */
1055 FOR_EACH_FRAME (frames, exp_MB_frame)
1056 {
1057 f = XFRAME (exp_MB_frame);
1058 window = f->minibuffer_window;
1059 w = XWINDOW (window);
1060 if (EQ (w->frame, exp_MB_frame)
1061 && EQ (w->contents, nth_minibuffer (minibuf_level)))
1062 goto found;
1063 }
1064 return; /* expired minibuffer not found. Maybe we should output an
1065 error, here. */
1066
1067 found:
1068 if (!EQ (exp_MB_frame, saved_selected_frame))
1069 do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets
1070 minibuff_window */
1039 1071
1040 /* To keep things predictable, in case it matters, let's be in the 1072 /* To keep things predictable, in case it matters, let's be in the
1041 minibuffer when we reset the relevant variables. Don't depend on 1073 minibuffer when we reset the relevant variables. Don't depend on
@@ -1127,20 +1159,61 @@ read_minibuf_unwind (void)
1127 away from the expired minibuffer window, both in the current 1159 away from the expired minibuffer window, both in the current
1128 minibuffer's frame and the original calling frame. */ 1160 minibuffer's frame and the original calling frame. */
1129 choose_minibuf_frame (); 1161 choose_minibuf_frame ();
1130 if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame)) 1162 if (NILP (XWINDOW (minibuf_window)->prev_buffers))
1131 { 1163 {
1132 Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil); 1164 if (!EQ (WINDOW_FRAME (XWINDOW (minibuf_window)), calling_frame))
1133 /* PREV can be on a different frame when we have a minibuffer only 1165 {
1134 frame, the other frame's minibuffer window is MINIBUF_WINDOW, 1166 Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil);
1135 and its "focus window" is also MINIBUF_WINDOW. */ 1167 /* PREV can be on a different frame when we have a minibuffer only
1136 if (!EQ (prev, minibuf_window) 1168 frame, the other frame's minibuffer window is MINIBUF_WINDOW,
1137 && EQ (WINDOW_FRAME (XWINDOW (prev)), 1169 and its "focus window" is also MINIBUF_WINDOW. */
1138 WINDOW_FRAME (XWINDOW (minibuf_window)))) 1170 if (!EQ (prev, minibuf_window)
1139 Fset_frame_selected_window (selected_frame, prev, Qnil); 1171 && EQ (WINDOW_FRAME (XWINDOW (prev)),
1140 } 1172 WINDOW_FRAME (XWINDOW (minibuf_window))))
1141 else 1173 Fset_frame_selected_window (selected_frame, prev, Qnil);
1142 Fset_frame_selected_window (calling_frame, calling_window, Qnil); 1174 }
1175 else
1176 Fset_frame_selected_window (calling_frame, calling_window, Qnil);
1177 }
1178
1179 /* Restore the selected frame. */
1180 if (!EQ (exp_MB_frame, saved_selected_frame))
1181 do_switch_frame (saved_selected_frame, 0, 0, Qt);
1182}
1183
1184/* Replace the expired minibuffer in frame exp_MB_frame with the next less
1185 nested minibuffer in that frame, if any. Otherwise, replace it
1186 with the null minibuffer. MINIBUF_WINDOW is not changed. */
1187static void
1188minibuffer_unwind (void)
1189{
1190 struct frame *f;
1191 struct window *w;
1192 Lisp_Object window;
1193 Lisp_Object entry;
1194
1195 f = XFRAME (exp_MB_frame);
1196 window = f->minibuffer_window;
1197 w = XWINDOW (window);
1198 if (FRAME_LIVE_P (f))
1199 {
1200 /* minibuf_window = sf->minibuffer_window; */
1201 if (!NILP (w->prev_buffers))
1202 {
1203 entry = Fcar (w->prev_buffers);
1204 w->prev_buffers = Fcdr (w->prev_buffers);
1205 set_window_buffer (window, Fcar (entry), 0, 0);
1206 Fset_window_start (window, Fcar (Fcdr (entry)), Qnil);
1207 Fset_window_point (window, Fcar (Fcdr (Fcdr (entry))));
1208 /* set-window-configuration may/will have unselected the
1209 mini-window as the selected window. Restore it. */
1210 Fset_frame_selected_window (exp_MB_frame, window, Qnil);
1211 }
1212 else
1213 set_window_buffer (window, nth_minibuffer (0), 0, 0);
1214 }
1143} 1215}
1216
1144 1217
1145 1218
1146void 1219void
@@ -2213,6 +2286,9 @@ syms_of_minibuf (void)
2213{ 2286{
2214 staticpro (&minibuf_prompt); 2287 staticpro (&minibuf_prompt);
2215 staticpro (&minibuf_save_list); 2288 staticpro (&minibuf_save_list);
2289 staticpro (&MB_frame);
2290 MB_frame = Qnil;
2291 staticpro (&exp_MB_frame);
2216 2292
2217 DEFSYM (Qminibuffer_follows_selected_frame, 2293 DEFSYM (Qminibuffer_follows_selected_frame,
2218 "minibuffer-follows-selected-frame"); 2294 "minibuffer-follows-selected-frame");
diff --git a/src/window.c b/src/window.c
index eb16e2a4338..4d5c7e763ec 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6958,7 +6958,8 @@ the return value is nil. Otherwise the value is t. */)
6958 6958
6959 if (BUFFERP (w->contents) 6959 if (BUFFERP (w->contents)
6960 && !EQ (w->contents, p->buffer) 6960 && !EQ (w->contents, p->buffer)
6961 && BUFFER_LIVE_P (XBUFFER (p->buffer))) 6961 && BUFFER_LIVE_P (XBUFFER (p->buffer))
6962 && (NILP (Fminibufferp (p->buffer, Qnil))))
6962 /* If a window we restore gets another buffer, record the 6963 /* If a window we restore gets another buffer, record the
6963 window's old buffer. */ 6964 window's old buffer. */
6964 call1 (Qrecord_window_buffer, window); 6965 call1 (Qrecord_window_buffer, window);
diff --git a/src/xdisp.c b/src/xdisp.c
index cc0a689ba32..a405d51f803 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -12650,9 +12650,8 @@ gui_consider_frame_title (Lisp_Object frame)
12650 mode_line_noprop_buf; then display the title. */ 12650 mode_line_noprop_buf; then display the title. */
12651 record_unwind_protect (unwind_format_mode_line, 12651 record_unwind_protect (unwind_format_mode_line,
12652 format_mode_line_unwind_data 12652 format_mode_line_unwind_data
12653 (f, current_buffer, selected_window, false)); 12653 (NULL, current_buffer, Qnil, false));
12654 12654
12655 Fselect_window (f->selected_window, Qt);
12656 set_buffer_internal_1 12655 set_buffer_internal_1
12657 (XBUFFER (XWINDOW (f->selected_window)->contents)); 12656 (XBUFFER (XWINDOW (f->selected_window)->contents));
12658 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format; 12657 fmt = FRAME_ICONIFIED_P (f) ? Vicon_title_format : Vframe_title_format;