diff options
| author | Alan Mackenzie | 2021-03-21 16:54:31 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2021-03-21 16:54:31 +0000 |
| commit | 7c2ebf6e23663fdc7b1880a4d7caeadc8c47c00e (patch) | |
| tree | 19216102a0b7fc0212b8cdfa6fc8d70ed6ad86b4 | |
| parent | e276810dff9838e1bb8c2ec450f85835ed60bf14 (diff) | |
| download | emacs-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.texi | 4 | ||||
| -rw-r--r-- | lisp/window.el | 5 | ||||
| -rw-r--r-- | src/fns.c | 46 | ||||
| -rw-r--r-- | src/frame.c | 2 | ||||
| -rw-r--r-- | src/lisp.h | 3 | ||||
| -rw-r--r-- | src/minibuf.c | 292 | ||||
| -rw-r--r-- | src/window.c | 3 | ||||
| -rw-r--r-- | src/xdisp.c | 3 |
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 |
| 84 | effect of the command, when you finally finish using the minibuffer, | 84 | effect of the command, when you finally finish using the minibuffer, |
| 85 | always takes place in the frame where you first opened it. | 85 | always takes place in the frame where you first opened it. The sole |
| 86 | exception is that when that frame no longer exists, the action takes | ||
| 87 | place 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 | ||
| 4159 | This function is called only if `switch-to-buffer-preserve-window-point' | 4159 | This function is called only if `switch-to-buffer-preserve-window-point' |
| 4160 | evaluates non-nil." | 4160 | evaluates 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)) |
| @@ -2279,6 +2279,52 @@ merge (Lisp_Object org_l1, Lisp_Object org_l2, Lisp_Object pred) | |||
| 2279 | } | 2279 | } |
| 2280 | } | 2280 | } |
| 2281 | 2281 | ||
| 2282 | Lisp_Object | ||
| 2283 | merge_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, | |||
| 3610 | extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t, | 3610 | extern Lisp_Object substring_both (Lisp_Object, ptrdiff_t, ptrdiff_t, |
| 3611 | ptrdiff_t, ptrdiff_t); | 3611 | ptrdiff_t, ptrdiff_t); |
| 3612 | extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object); | 3612 | extern Lisp_Object merge (Lisp_Object, Lisp_Object, Lisp_Object); |
| 3613 | extern Lisp_Object merge_c (Lisp_Object, Lisp_Object, bool (*) (Lisp_Object, Lisp_Object)); | ||
| 3613 | extern Lisp_Object do_yes_or_no_p (Lisp_Object); | 3614 | extern Lisp_Object do_yes_or_no_p (Lisp_Object); |
| 3614 | extern int string_version_cmp (Lisp_Object, Lisp_Object); | 3615 | extern int string_version_cmp (Lisp_Object, Lisp_Object); |
| 3615 | extern Lisp_Object concat2 (Lisp_Object, Lisp_Object); | 3616 | extern Lisp_Object concat2 (Lisp_Object, Lisp_Object); |
| @@ -4348,7 +4349,7 @@ extern void clear_regexp_cache (void); | |||
| 4348 | 4349 | ||
| 4349 | extern Lisp_Object Vminibuffer_list; | 4350 | extern Lisp_Object Vminibuffer_list; |
| 4350 | extern Lisp_Object last_minibuf_string; | 4351 | extern Lisp_Object last_minibuf_string; |
| 4351 | extern void move_minibuffer_onto_frame (void); | 4352 | extern void move_minibuffers_onto_frame (struct frame *, bool); |
| 4352 | extern bool is_minibuffer (EMACS_INT, Lisp_Object); | 4353 | extern bool is_minibuffer (EMACS_INT, Lisp_Object); |
| 4353 | extern EMACS_INT this_minibuffer_depth (Lisp_Object); | 4354 | extern EMACS_INT this_minibuffer_depth (Lisp_Object); |
| 4354 | extern EMACS_INT minibuf_level; | 4355 | extern 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 | ||
| 60 | static Lisp_Object minibuf_prompt; | 60 | static 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 | |||
| 66 | static 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; | |||
| 67 | static Lisp_Object nth_minibuffer (EMACS_INT depth); | 73 | static Lisp_Object nth_minibuffer (EMACS_INT depth); |
| 68 | static EMACS_INT minibuf_c_loop_level (EMACS_INT depth); | 74 | static EMACS_INT minibuf_c_loop_level (EMACS_INT depth); |
| 69 | static void set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth); | 75 | static void set_minibuffer_mode (Lisp_Object buf, EMACS_INT depth); |
| 76 | static 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. */ |
| 83 | static bool | 91 | static 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) | 128 | precisely, compare the buffer components of each window->prev_buffers |
| 134 | && FRAME_LIVE_P (XFRAME (selected_frame))) | 129 | entry. */ |
| 135 | /* Make sure no other frame has a minibuffer as its selected window, | 130 | static bool |
| 136 | because the text would not be displayed in it, and that would be | 131 | minibuffer_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 |
| 166 | void move_minibuffer_onto_frame (void) | 141 | in DEST/SOURCE_WINDOW together with any recorded in the |
| 142 | ->prev_buffers field of the struct window. */ | ||
| 143 | static void | ||
| 144 | zip_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. */ | ||
| 188 | void | ||
| 189 | move_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 | ||
| 223 | static void read_minibuf_unwind (void); | 233 | static void read_minibuf_unwind (void); |
| 234 | static void minibuffer_unwind (void); | ||
| 224 | static void run_exit_minibuf_hook (void); | 235 | static 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. */ | ||
| 1037 | static 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. */ | ||
| 1187 | static void | ||
| 1188 | minibuffer_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 | ||
| 1146 | void | 1219 | void |
| @@ -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; |