aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Mackenzie2021-01-10 20:32:40 +0000
committerAlan Mackenzie2021-01-10 20:32:40 +0000
commitc7c154bb5756e0ae71d342c5d8aabf725877f186 (patch)
tree4db61dff837b5e5f5b864c2e1b53a1051ec536bf
parenta583c72305530f7d3ecc9ba50eefa70b6ddecdd9 (diff)
downloademacs-c7c154bb5756e0ae71d342c5d8aabf725877f186.tar.gz
emacs-c7c154bb5756e0ae71d342c5d8aabf725877f186.zip
Fix incompleteness in the implementation of minibuffer-follows-selected-frame
In particular, add a new value to the variable, and fix several bugs apparent with the implementation up till now. * doc/emacs/mini.texi (Basic Minibuffer): Add a description of the new non-nil, non-t value of minibuffer-follows-selected-frame. * doc/emacs/trouble.texi (Quitting): Add a description of how C-g handles recursive minibuffers when typed in one which isn't the most nested. * doc/lispref/minibuf.texi (Intro to Minibuffers): Add an @dfn for "active minibuffer". (Minibuffer Commands): Document that exit-minibuffer throws an error when not invoked from the innermost Minibuffer. (Recursive Mini): Amend the description of the visibility of outer level minibuffers. (Minibuffer Misc): In the description of the minibuffer hooks, replace "the minibuffer" with "a minibuffer". * etc/NEWS (Entry announcing minibuffer-follows-selected-frame): Add a description of the new non-nil, non-t value. * lisp/cus-start.el (top level): make the customize entry for minibuffer-follows-selected-frame a choice between three entries. * lisp/minibuffer.el (exit-minibuffer): throw an error when we're not in the most nested minibuffer. (top level): Bind C-g to abort-minibuffers in minibuffer-local-map. * lisp/window.el (window-deletable-p): return the symbol `frame' when (amongst other things) minibuffer-follows-selected-frame is t. * src/eval.c (internal_catch): Add a mechanism to (throw 'exit t) repeatedly when the throw currently being processed doesn't terminate the current minibuffer. * src/lisp.h (this_minibuffer_depth): New extern declaration (minibuf_level): extern declaration moved here from window.h. * src/minibuf.c (minibuffer_follows_frame, minibuf_stays_put) (minibuf_moves_frame_when_opened): New and amended functions to query the value of minibuffer-follows-selected-frame. (choose_minibuf_frame): check (minibuf > 1) in place of (minibufer > 0) at a particular place. At another place, check that an alleged frame is so and is live. Before selecting a non-miniwindow on a different frame, ensure it really is a different frame. (move_minibuffer_onto_frame): Stack up all recursive minibuffers on the target frame. Check the minibuf_window isn't in the old frame before setting that frame's miniwindow to an inactive minibuffer. (Finnermost_minibuffer_p, Fabort_minibuffers): New primitives. (this_minibuffer_depth): New function. (read_minibuf): Record the calling frame in a variable, and switch back to it after the recursive edit has terminated normally, using select-frame-set-input-focus. Stack up all the recursive minibuffers on the miniwindow where a new minibuffer is being opened. After the recursive edit, switch the selected window away from the expired minibuffer's window. (nth_minibuffer): New function. (minibuffer-follows-selected-frame): Change from a DEFVAR_BOOL to a DEFVAR_LISP. * src/window.c (decode_next_window_args): Set *minibuf to w's mini-window's content when that content is a minibuffer. * src/window.h (minibuf_level) Declaration moved from here to lisp.h.
-rw-r--r--doc/emacs/mini.texi10
-rw-r--r--doc/emacs/trouble.texi7
-rw-r--r--doc/lispref/minibuf.texi24
-rw-r--r--etc/NEWS13
-rw-r--r--lisp/cus-start.el6
-rw-r--r--lisp/minibuffer.el8
-rw-r--r--lisp/window.el5
-rw-r--r--src/eval.c26
-rw-r--r--src/lisp.h2
-rw-r--r--src/minibuf.c182
-rw-r--r--src/window.c5
-rw-r--r--src/window.h4
12 files changed, 243 insertions, 49 deletions
diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi
index c7c8fb30ac6..f81e64bdf9b 100644
--- a/doc/emacs/mini.texi
+++ b/doc/emacs/mini.texi
@@ -76,9 +76,13 @@ default, the active minibuffer moves to this new frame. If you set
76the user option @code{minibuffer-follows-selected-frame} to 76the user option @code{minibuffer-follows-selected-frame} to
77@code{nil}, then the minibuffer stays in the frame where you opened 77@code{nil}, then the minibuffer stays in the frame where you opened
78it, and you must switch back to that frame in order to complete (or 78it, and you must switch back to that frame in order to complete (or
79abort) the current command. Note that the effect of the command, when 79abort) the current command. If you set that option to a value which
80you finally finish using the minibuffer, always takes place in the 80is neither @code{nil} nor @code{t}, the minibuffer moves frame only
81frame where you first opened it. 81after a recursive minibuffer has been opened in the current command
82(@pxref{Recursive Mini,,, elisp}). This option is mainly to retain
83(approximately) the behavior prior to Emacs 28.1. Note that the
84effect of the command, when you finally finish using the minibuffer,
85always takes place in the frame where you first opened it.
82 86
83@node Minibuffer File 87@node Minibuffer File
84@section Minibuffers for File Names 88@section Minibuffers for File Names
diff --git a/doc/emacs/trouble.texi b/doc/emacs/trouble.texi
index 4da3d4a3e89..9a638818c91 100644
--- a/doc/emacs/trouble.texi
+++ b/doc/emacs/trouble.texi
@@ -57,6 +57,13 @@ incremental search, @kbd{C-g} behaves specially; it may take two
57successive @kbd{C-g} characters to get out of a search. 57successive @kbd{C-g} characters to get out of a search.
58@xref{Incremental Search}, for details. 58@xref{Incremental Search}, for details.
59 59
60 If you type @kbd{C-g} in a minibuffer, this quits the command that
61opened that minibuffer, closing it. If that minibuffer is not the
62most recently opened one (which can happen when
63@code{minibuffer-follows-selected-frame} is @code{nil} (@pxref{Basic
64Minibuffer})), @kbd{C-g} also closes the more recently opened ones,
65quitting their associated commands, after asking you for confirmation.
66
60 On MS-DOS, the character @kbd{C-@key{Break}} serves as a quit character 67 On MS-DOS, the character @kbd{C-@key{Break}} serves as a quit character
61like @kbd{C-g}. The reason is that it is not feasible, on MS-DOS, to 68like @kbd{C-g}. The reason is that it is not feasible, on MS-DOS, to
62recognize @kbd{C-g} while a command is running, between interactions 69recognize @kbd{C-g} while a command is running, between interactions
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index f0036f0ccfc..d316c1f0602 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -82,10 +82,12 @@ there is an active minibuffer; such a minibuffer is called a
82incrementing the number at the end of the name. (The names begin with 82incrementing the number at the end of the name. (The names begin with
83a space so that they won't show up in normal buffer lists.) Of 83a space so that they won't show up in normal buffer lists.) Of
84several recursive minibuffers, the innermost (or most recently 84several recursive minibuffers, the innermost (or most recently
85entered) is the active minibuffer. We usually call this @emph{the} 85entered) is the @dfn{active minibuffer}--it is the one you can
86minibuffer. You can permit or forbid recursive minibuffers by setting 86terminate by typing @key{RET} (@code{exit-minibuffer}) in. We usually
87the variable @code{enable-recursive-minibuffers}, or by putting 87call this @emph{the} minibuffer. You can permit or forbid recursive
88properties of that name on command symbols (@xref{Recursive Mini}.) 88minibuffers by setting the variable
89@code{enable-recursive-minibuffers}, or by putting properties of that
90name on command symbols (@xref{Recursive Mini}.)
89 91
90 Like other buffers, a minibuffer uses a local keymap 92 Like other buffers, a minibuffer uses a local keymap
91(@pxref{Keymaps}) to specify special key bindings. The function that 93(@pxref{Keymaps}) to specify special key bindings. The function that
@@ -2380,7 +2382,8 @@ minibuffer.
2380 2382
2381@deffn Command exit-minibuffer 2383@deffn Command exit-minibuffer
2382This command exits the active minibuffer. It is normally bound to 2384This command exits the active minibuffer. It is normally bound to
2383keys in minibuffer local keymaps. 2385keys in minibuffer local keymaps. The command throws an error if the
2386current buffer is not the active minibuffer.
2384@end deffn 2387@end deffn
2385 2388
2386@deffn Command self-insert-and-exit 2389@deffn Command self-insert-and-exit
@@ -2594,8 +2597,11 @@ returns zero.
2594If this variable is non-@code{nil}, you can invoke commands (such as 2597If this variable is non-@code{nil}, you can invoke commands (such as
2595@code{find-file}) that use minibuffers even while the minibuffer is 2598@code{find-file}) that use minibuffers even while the minibuffer is
2596active. Such invocation produces a recursive editing level for a new 2599active. Such invocation produces a recursive editing level for a new
2597minibuffer. The outer-level minibuffer is invisible while you are 2600minibuffer. By default, the outer-level minibuffer is invisible while
2598editing the inner one. 2601you are editing the inner one. If you have
2602@code{minibuffer-follows-selected-frame} set to @code{nil}, you can
2603have minibuffers visible on several frames at the same time.
2604@xref{Basic Minibuffer,,, emacs}.
2599 2605
2600If this variable is @code{nil}, you cannot invoke minibuffer commands 2606If this variable is @code{nil}, you cannot invoke minibuffer commands
2601when the minibuffer is active, not even if you switch to another window 2607when the minibuffer is active, not even if you switch to another window
@@ -2623,7 +2629,7 @@ active minibuffer.
2623@end defun 2629@end defun
2624 2630
2625@defvar minibuffer-setup-hook 2631@defvar minibuffer-setup-hook
2626This is a normal hook that is run whenever the minibuffer is entered. 2632This is a normal hook that is run whenever a minibuffer is entered.
2627@xref{Hooks}. 2633@xref{Hooks}.
2628@end defvar 2634@end defvar
2629 2635
@@ -2641,7 +2647,7 @@ called once, for the outermost use of the minibuffer.
2641@end defmac 2647@end defmac
2642 2648
2643@defvar minibuffer-exit-hook 2649@defvar minibuffer-exit-hook
2644This is a normal hook that is run whenever the minibuffer is exited. 2650This is a normal hook that is run whenever a minibuffer is exited.
2645@xref{Hooks}. 2651@xref{Hooks}.
2646@end defvar 2652@end defvar
2647 2653
diff --git a/etc/NEWS b/etc/NEWS
index 1a1f76d1281..a7a872d9791 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -102,12 +102,13 @@ effect should be negligible in the vast majority of cases anyway.
102By default, when you switch to another frame, an active minibuffer now 102By default, when you switch to another frame, an active minibuffer now
103moves to the newly selected frame. Nevertheless, the effect of what 103moves to the newly selected frame. Nevertheless, the effect of what
104you type in the minibuffer happens in the frame where the minibuffer 104you type in the minibuffer happens in the frame where the minibuffer
105was first activated, even if it moved to another frame. An 105was first activated. An alternative behavior is available by
106alternative behavior is available by customizing 106customizing 'minibuffer-follows-selected-frame' to nil. Here, the
107'minibuffer-follows-selected-frame' to nil. Here, the minibuffer 107minibuffer stays in the frame where you first opened it, and you must
108stays in the frame where you first opened it, and you must switch back 108switch back to this frame to continue or abort its command. The old
109to this frame to continue or abort its command. The old, somewhat 109behavior, which mixed these two, can be approximated by customizing
110unsystematic behavior, which mixed these two is no longer available. 110'minibuffer-follows-selected-frame' to a value which is neither nil
111nor t.
111 112
112+++ 113+++
113** New system for displaying documentation for groups of functions. 114** New system for displaying documentation for groups of functions.
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index 85dd14f6282..0293d34d1cd 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -394,7 +394,11 @@ Leaving \"Default\" unchecked is equivalent with specifying a default of
394 ;; (directory :format "%v")))) 394 ;; (directory :format "%v"))))
395 (load-prefer-newer lisp boolean "24.4") 395 (load-prefer-newer lisp boolean "24.4")
396 ;; minibuf.c 396 ;; minibuf.c
397 (minibuffer-follows-selected-frame minibuffer boolean "28.1") 397 (minibuffer-follows-selected-frame
398 minibuffer (choice (const :tag "Always" t)
399 (const :tag "When used" hybrid)
400 (const :tag "Never" nil))
401 "28.1")
398 (enable-recursive-minibuffers minibuffer boolean) 402 (enable-recursive-minibuffers minibuffer boolean)
399 (history-length minibuffer 403 (history-length minibuffer
400 (choice (const :tag "Infinite" t) integer) 404 (choice (const :tag "Infinite" t) integer)
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 556f5d3a564..315f2d369af 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2125,8 +2125,10 @@ variables.")
2125 ;; A better solution would be to make deactivate-mark buffer-local 2125 ;; A better solution would be to make deactivate-mark buffer-local
2126 ;; (or to turn it into a list of buffers, ...), but in the mean time, 2126 ;; (or to turn it into a list of buffers, ...), but in the mean time,
2127 ;; this should do the trick in most cases. 2127 ;; this should do the trick in most cases.
2128 (setq deactivate-mark nil) 2128 (when (innermost-minibuffer-p)
2129 (throw 'exit nil)) 2129 (setq deactivate-mark nil)
2130 (throw 'exit nil))
2131 (error "%s" "Not in most nested minibuffer"))
2130 2132
2131(defun self-insert-and-exit () 2133(defun self-insert-and-exit ()
2132 "Terminate minibuffer input." 2134 "Terminate minibuffer input."
@@ -2394,7 +2396,7 @@ The completion method is determined by `completion-at-point-functions'."
2394;;; Key bindings. 2396;;; Key bindings.
2395 2397
2396(let ((map minibuffer-local-map)) 2398(let ((map minibuffer-local-map))
2397 (define-key map "\C-g" 'abort-recursive-edit) 2399 (define-key map "\C-g" 'abort-minibuffers)
2398 (define-key map "\M-<" 'minibuffer-beginning-of-buffer) 2400 (define-key map "\M-<" 'minibuffer-beginning-of-buffer)
2399 2401
2400 (define-key map "\r" 'exit-minibuffer) 2402 (define-key map "\r" 'exit-minibuffer)
diff --git a/lisp/window.el b/lisp/window.el
index 38be7789062..a6cdd4dec2f 100644
--- a/lisp/window.el
+++ b/lisp/window.el
@@ -4116,7 +4116,10 @@ frame can be safely deleted."
4116 frame)) 4116 frame))
4117 (throw 'other t)))) 4117 (throw 'other t))))
4118 (let ((minibuf (active-minibuffer-window))) 4118 (let ((minibuf (active-minibuffer-window)))
4119 (and minibuf (eq frame (window-frame minibuf))))) 4119 (and minibuf (eq frame (window-frame minibuf))
4120 (not (eq (default-toplevel-value
4121 minibuffer-follows-selected-frame)
4122 t)))))
4120 'frame)) 4123 'frame))
4121 ((window-minibuffer-p window) 4124 ((window-minibuffer-p window)
4122 ;; If WINDOW is the minibuffer window of a non-minibuffer-only 4125 ;; If WINDOW is the minibuffer window of a non-minibuffer-only
diff --git a/src/eval.c b/src/eval.c
index 706aafdf509..5bf3faebc85 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1167,9 +1167,18 @@ Lisp_Object
1167internal_catch (Lisp_Object tag, 1167internal_catch (Lisp_Object tag,
1168 Lisp_Object (*func) (Lisp_Object), Lisp_Object arg) 1168 Lisp_Object (*func) (Lisp_Object), Lisp_Object arg)
1169{ 1169{
1170 /* MINIBUFFER_QUIT_LEVEL is to handle quitting from nested minibuffers by
1171 throwing t to tag `exit'.
1172 Value -1 means there is no (throw 'exit t) in progress;
1173 0 means the `throw' wasn't done from an active minibuffer;
1174 N > 0 means the `throw' was done from the minibuffer at level N. */
1175 static EMACS_INT minibuffer_quit_level = -1;
1170 /* This structure is made part of the chain `catchlist'. */ 1176 /* This structure is made part of the chain `catchlist'. */
1171 struct handler *c = push_handler (tag, CATCHER); 1177 struct handler *c = push_handler (tag, CATCHER);
1172 1178
1179 if (EQ (tag, Qexit))
1180 minibuffer_quit_level = -1;
1181
1173 /* Call FUNC. */ 1182 /* Call FUNC. */
1174 if (! sys_setjmp (c->jmp)) 1183 if (! sys_setjmp (c->jmp))
1175 { 1184 {
@@ -1183,6 +1192,23 @@ internal_catch (Lisp_Object tag,
1183 Lisp_Object val = handlerlist->val; 1192 Lisp_Object val = handlerlist->val;
1184 clobbered_eassert (handlerlist == c); 1193 clobbered_eassert (handlerlist == c);
1185 handlerlist = handlerlist->next; 1194 handlerlist = handlerlist->next;
1195 if (EQ (tag, Qexit) && EQ (val, Qt))
1196 /* If we've thrown t to tag `exit' from within a minibuffer, we
1197 exit all minibuffers more deeply nested than the current
1198 one. */
1199 {
1200 EMACS_INT mini_depth = this_minibuffer_depth (Qnil);
1201 if (mini_depth && mini_depth != minibuffer_quit_level)
1202 {
1203 if (minibuffer_quit_level == -1)
1204 minibuffer_quit_level = mini_depth;
1205 if (minibuffer_quit_level
1206 && (minibuf_level > minibuffer_quit_level))
1207 Fthrow (Qexit, Qt);
1208 }
1209 else
1210 minibuffer_quit_level = -1;
1211 }
1186 return val; 1212 return val;
1187 } 1213 }
1188} 1214}
diff --git a/src/lisp.h b/src/lisp.h
index d139df93424..86be25852a6 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4346,6 +4346,8 @@ extern Lisp_Object Vminibuffer_list;
4346extern Lisp_Object last_minibuf_string; 4346extern Lisp_Object last_minibuf_string;
4347extern void move_minibuffer_onto_frame (void); 4347extern void move_minibuffer_onto_frame (void);
4348extern bool is_minibuffer (EMACS_INT, Lisp_Object); 4348extern bool is_minibuffer (EMACS_INT, Lisp_Object);
4349extern EMACS_INT this_minibuffer_depth (Lisp_Object);
4350extern EMACS_INT minibuf_level;
4349extern Lisp_Object get_minibuffer (EMACS_INT); 4351extern Lisp_Object get_minibuffer (EMACS_INT);
4350extern void init_minibuf_once (void); 4352extern void init_minibuf_once (void);
4351extern void syms_of_minibuf (void); 4353extern void syms_of_minibuf (void);
diff --git a/src/minibuf.c b/src/minibuf.c
index 5ee440f6622..c527e2bc9c6 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -63,10 +63,31 @@ static Lisp_Object minibuf_prompt;
63 63
64static ptrdiff_t minibuf_prompt_width; 64static ptrdiff_t minibuf_prompt_width;
65 65
66static Lisp_Object nth_minibuffer (EMACS_INT depth);
67
66 68
69/* Return TRUE when a frame switch causes a minibuffer on the old
70 frame to move onto the new one. */
67static bool 71static bool
68minibuf_follows_frame (void) 72minibuf_follows_frame (void)
69{ 73{
74 return EQ (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame),
75 Qt);
76}
77
78/* Return TRUE when a minibuffer always remains on the frame where it
79 was first invoked. */
80static bool
81minibuf_stays_put (void)
82{
83 return NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame));
84}
85
86/* Return TRUE when opening a (recursive) minibuffer causes
87 minibuffers on other frames to move to the selected frame. */
88static bool
89minibuf_moves_frame_when_opened (void)
90{
70 return !NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame)); 91 return !NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame));
71} 92}
72 93
@@ -90,7 +111,7 @@ choose_minibuf_frame (void)
90 minibuf_window = sf->minibuffer_window; 111 minibuf_window = sf->minibuffer_window;
91 /* If we've still got another minibuffer open, use its mini-window 112 /* If we've still got another minibuffer open, use its mini-window
92 instead. */ 113 instead. */
93 if (minibuf_level && !minibuf_follows_frame ()) 114 if (minibuf_level > 1 && minibuf_stays_put ())
94 { 115 {
95 Lisp_Object buffer = get_minibuffer (minibuf_level); 116 Lisp_Object buffer = get_minibuffer (minibuf_level);
96 Lisp_Object tail, frame; 117 Lisp_Object tail, frame;
@@ -105,26 +126,40 @@ choose_minibuf_frame (void)
105 } 126 }
106 } 127 }
107 128
108 if (minibuf_follows_frame ()) 129 if (minibuf_moves_frame_when_opened ()
130 && FRAMEP (selected_frame)
131 && FRAME_LIVE_P (XFRAME (selected_frame)))
109 /* Make sure no other frame has a minibuffer as its selected window, 132 /* Make sure no other frame has a minibuffer as its selected window,
110 because the text would not be displayed in it, and that would be 133 because the text would not be displayed in it, and that would be
111 confusing. Only allow the selected frame to do this, 134 confusing. Only allow the selected frame to do this,
112 and that only if the minibuffer is active. */ 135 and that only if the minibuffer is active. */
113 { 136 {
114 Lisp_Object tail, frame; 137 Lisp_Object tail, frame;
115 138 struct frame *of;
116 FOR_EACH_FRAME (tail, frame) 139
117 if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (XFRAME (frame)))) 140 FOR_EACH_FRAME (tail, frame)
118 && !(EQ (frame, selected_frame) 141 if (!EQ (frame, selected_frame)
119 && minibuf_level > 0)) 142 && minibuf_level > 1
120 Fset_frame_selected_window (frame, Fframe_first_window (frame), 143 /* The frame's minibuffer can be on a different frame. */
121 Qnil); 144 && XWINDOW ((of = XFRAME (frame))->minibuffer_window)->frame
122 } 145 != selected_frame)
146 {
147 if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (of))))
148 Fset_frame_selected_window (frame, Fframe_first_window (frame),
149 Qnil);
150
151 if (!EQ (XWINDOW (of->minibuffer_window)->contents,
152 nth_minibuffer (0)))
153 set_window_buffer (of->minibuffer_window,
154 nth_minibuffer (0), 0, 0);
155 }
156 }
123} 157}
124 158
125/* If `minibuffer_follows_selected_frame' and we have a minibuffer, move it 159/* If `minibuffer_follows_selected_frame' is t and we have a
126 from its current frame to the selected frame. This function is 160 minibuffer, move it from its current frame to the selected frame.
127 intended to be called from `do_switch_frame' in frame.c. */ 161 This function is intended to be called from `do_switch_frame' in
162 frame.c. */
128void move_minibuffer_onto_frame (void) 163void move_minibuffer_onto_frame (void)
129{ 164{
130 if (!minibuf_level) 165 if (!minibuf_level)
@@ -135,14 +170,18 @@ void move_minibuffer_onto_frame (void)
135 && FRAME_LIVE_P (XFRAME (selected_frame)) 170 && FRAME_LIVE_P (XFRAME (selected_frame))
136 && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window)) 171 && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window))
137 { 172 {
173 EMACS_INT i;
138 struct frame *sf = XFRAME (selected_frame); 174 struct frame *sf = XFRAME (selected_frame);
139 Lisp_Object old_frame = XWINDOW (minibuf_window)->frame; 175 Lisp_Object old_frame = XWINDOW (minibuf_window)->frame;
140 struct frame *of = XFRAME (old_frame); 176 struct frame *of = XFRAME (old_frame);
141 Lisp_Object buffer = XWINDOW (minibuf_window)->contents;
142 177
143 set_window_buffer (sf->minibuffer_window, buffer, 0, 0); 178 /* Stack up all the (recursively) open minibuffers on the selected
179 mini_window. */
180 for (i = 1; i <= minibuf_level; i++)
181 set_window_buffer (sf->minibuffer_window, nth_minibuffer (i), 0, 0);
144 minibuf_window = sf->minibuffer_window; 182 minibuf_window = sf->minibuffer_window;
145 set_window_buffer (of->minibuffer_window, get_minibuffer (0), 0, 0); 183 if (of != sf)
184 set_window_buffer (of->minibuffer_window, get_minibuffer (0), 0, 0);
146 } 185 }
147} 186}
148 187
@@ -336,6 +375,63 @@ return t only if BUFFER is an active minibuffer. */)
336 ? Qt : Qnil; 375 ? Qt : Qnil;
337} 376}
338 377
378DEFUN ("innermost-minibuffer-p", Finnermost_minibuffer_p,
379 Sinnermost_minibuffer_p, 0, 1, 0,
380 doc: /* Return t if BUFFER is the most nested active minibuffer.
381No argument or nil as argument means use the current buffer as BUFFER. */)
382 (Lisp_Object buffer)
383{
384 if (NILP (buffer))
385 buffer = Fcurrent_buffer ();
386 return EQ (buffer, (Fcar (Fnthcdr (make_fixnum (minibuf_level),
387 Vminibuffer_list))))
388 ? Qt
389 : Qnil;
390}
391
392/* Return the nesting depth of the active minibuffer BUFFER, or 0 if
393 BUFFER isn't such a thing. If BUFFER is nil, this means use the current
394 buffer. */
395EMACS_INT
396this_minibuffer_depth (Lisp_Object buffer)
397{
398 EMACS_INT i;
399 Lisp_Object bufs;
400
401 if (NILP (buffer))
402 buffer = Fcurrent_buffer ();
403 for (i = 1, bufs = Fcdr (Vminibuffer_list);
404 i <= minibuf_level;
405 i++, bufs = Fcdr (bufs))
406 if (EQ (Fcar (bufs), buffer))
407 return i;
408 return 0;
409}
410
411DEFUN ("abort-minibuffers", Fabort_minibuffers, Sabort_minibuffers, 0, 0, "",
412 doc: /* Abort the current minibuffer.
413If we are not currently in the innermost minibuffer, prompt the user to
414confirm the aborting of the current minibuffer and all contained ones. */)
415 (void)
416{
417 EMACS_INT minibuf_depth = this_minibuffer_depth (Qnil);
418 Lisp_Object array[2];
419 AUTO_STRING (fmt, "Abort %s minibuffer levels? ");
420
421 if (!minibuf_depth)
422 error ("Not in a minibuffer");
423 if (minibuf_depth < minibuf_level)
424 {
425 array[0] = fmt;
426 array[1] = make_fixnum (minibuf_level - minibuf_depth + 1);
427 if (!NILP (Fyes_or_no_p (Fformat (2, array))))
428 Fthrow (Qexit, Qt);
429 }
430 else
431 Fthrow (Qexit, Qt);
432 return Qnil;
433}
434
339DEFUN ("minibuffer-prompt-end", Fminibuffer_prompt_end, 435DEFUN ("minibuffer-prompt-end", Fminibuffer_prompt_end,
340 Sminibuffer_prompt_end, 0, 0, 0, 436 Sminibuffer_prompt_end, 0, 0, 0,
341 doc: /* Return the buffer position of the end of the minibuffer prompt. 437 doc: /* Return the buffer position of the end of the minibuffer prompt.
@@ -411,6 +507,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
411 Lisp_Object val; 507 Lisp_Object val;
412 ptrdiff_t count = SPECPDL_INDEX (); 508 ptrdiff_t count = SPECPDL_INDEX ();
413 Lisp_Object mini_frame, ambient_dir, minibuffer, input_method; 509 Lisp_Object mini_frame, ambient_dir, minibuffer, input_method;
510 Lisp_Object calling_frame = selected_frame;
414 Lisp_Object enable_multibyte; 511 Lisp_Object enable_multibyte;
415 EMACS_INT pos = 0; 512 EMACS_INT pos = 0;
416 /* String to add to the history. */ 513 /* String to add to the history. */
@@ -648,6 +745,17 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
648 } 745 }
649 } 746 }
650 747
748 if (minibuf_moves_frame_when_opened ())
749 {
750 EMACS_INT i;
751
752 /* Stack up all the (recursively) open minibuffers on the selected
753 mini_window. */
754 for (i = 1; i < minibuf_level; i++)
755 set_window_buffer (XFRAME (mini_frame)->minibuffer_window,
756 nth_minibuffer (i), 0, 0);
757 }
758
651 /* Display this minibuffer in the proper window. */ 759 /* Display this minibuffer in the proper window. */
652 /* Use set_window_buffer instead of Fset_window_buffer (see 760 /* Use set_window_buffer instead of Fset_window_buffer (see
653 discussion of bug#11984, bug#12025, bug#12026). */ 761 discussion of bug#11984, bug#12025, bug#12026). */
@@ -729,6 +837,20 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
729 837
730 recursive_edit_1 (); 838 recursive_edit_1 ();
731 839
840 /* We've exited the recursive edit without an error, so switch the
841 current window away from the expired minibuffer window. */
842 {
843 Lisp_Object prev = Fprevious_window (minibuf_window, Qnil, Qnil);
844 /* PREV can be on a different frame when we have a minibuffer only
845 frame, the other frame's minibuffer window is MINIBUF_WINDOW,
846 and its "focus window" is also MINIBUF_WINDOW. */
847 while (!EQ (prev, minibuf_window)
848 && !EQ (selected_frame, WINDOW_FRAME (XWINDOW (prev))))
849 prev = Fprevious_window (prev, Qnil, Qnil);
850 if (!EQ (prev, minibuf_window))
851 Fset_frame_selected_window (selected_frame, prev, Qnil);
852 }
853
732 /* If cursor is on the minibuffer line, 854 /* If cursor is on the minibuffer line,
733 show the user we have exited by putting it in column 0. */ 855 show the user we have exited by putting it in column 0. */
734 if (XWINDOW (minibuf_window)->cursor.vpos >= 0 856 if (XWINDOW (minibuf_window)->cursor.vpos >= 0
@@ -767,6 +889,12 @@ read_minibuf (Lisp_Object map, Lisp_Object initial, Lisp_Object prompt,
767 in set-window-configuration. */ 889 in set-window-configuration. */
768 unbind_to (count, Qnil); 890 unbind_to (count, Qnil);
769 891
892 /* Switch the frame back to the calling frame. */
893 if (!EQ (selected_frame, calling_frame)
894 && FRAMEP (calling_frame)
895 && FRAME_LIVE_P (XFRAME (calling_frame)))
896 call2 (intern ("select-frame-set-input-focus"), calling_frame, Qnil);
897
770 /* Add the value to the appropriate history list, if any. This is 898 /* Add the value to the appropriate history list, if any. This is
771 done after the previous buffer has been made current again, in 899 done after the previous buffer has been made current again, in
772 case the history variable is buffer-local. */ 900 case the history variable is buffer-local. */
@@ -790,6 +918,14 @@ is_minibuffer (EMACS_INT depth, Lisp_Object buf)
790 && EQ (Fcar (tail), buf); 918 && EQ (Fcar (tail), buf);
791} 919}
792 920
921/* Return the DEPTHth minibuffer, or nil if such does not yet exist. */
922static Lisp_Object
923nth_minibuffer (EMACS_INT depth)
924{
925 Lisp_Object tail = Fnthcdr (make_fixnum (depth), Vminibuffer_list);
926 return XCAR (tail);
927}
928
793/* Return a buffer to be used as the minibuffer at depth `depth'. 929/* Return a buffer to be used as the minibuffer at depth `depth'.
794 depth = 0 is the lowest allowed argument, and that is the value 930 depth = 0 is the lowest allowed argument, and that is the value
795 used for nonrecursive minibuffer invocations. */ 931 used for nonrecursive minibuffer invocations. */
@@ -2032,13 +2168,15 @@ For example, `eval-expression' uses this. */);
2032The function is called with the arguments passed to `read-buffer'. */); 2168The function is called with the arguments passed to `read-buffer'. */);
2033 Vread_buffer_function = Qnil; 2169 Vread_buffer_function = Qnil;
2034 2170
2035 DEFVAR_BOOL ("minibuffer-follows-selected-frame", minibuffer_follows_selected_frame, 2171 DEFVAR_LISP ("minibuffer-follows-selected-frame", minibuffer_follows_selected_frame,
2036 doc: /* Non-nil means the active minibuffer always displays on the selected frame. 2172 doc: /* t means the active minibuffer always displays on the selected frame.
2037Nil means that a minibuffer will appear only in the frame which created it. 2173Nil means that a minibuffer will appear only in the frame which created it.
2174Any other value means the minibuffer will move onto another frame, but
2175only when the user starts using a minibuffer there.
2038 2176
2039Any buffer local or dynamic binding of this variable is ignored. Only the 2177Any buffer local or dynamic binding of this variable is ignored. Only the
2040default top level value is used. */); 2178default top level value is used. */);
2041 minibuffer_follows_selected_frame = 1; 2179 minibuffer_follows_selected_frame = Qt;
2042 2180
2043 DEFVAR_BOOL ("read-buffer-completion-ignore-case", 2181 DEFVAR_BOOL ("read-buffer-completion-ignore-case",
2044 read_buffer_completion_ignore_case, 2182 read_buffer_completion_ignore_case,
@@ -2196,6 +2334,8 @@ uses to hide passwords. */);
2196 defsubr (&Sminibuffer_prompt); 2334 defsubr (&Sminibuffer_prompt);
2197 2335
2198 defsubr (&Sminibufferp); 2336 defsubr (&Sminibufferp);
2337 defsubr (&Sinnermost_minibuffer_p);
2338 defsubr (&Sabort_minibuffers);
2199 defsubr (&Sminibuffer_prompt_end); 2339 defsubr (&Sminibuffer_prompt_end);
2200 defsubr (&Sminibuffer_contents); 2340 defsubr (&Sminibuffer_contents);
2201 defsubr (&Sminibuffer_contents_no_properties); 2341 defsubr (&Sminibuffer_contents_no_properties);
diff --git a/src/window.c b/src/window.c
index 5e78aa400b5..e025e0b0821 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2663,12 +2663,15 @@ static void
2663decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames) 2663decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames)
2664{ 2664{
2665 struct window *w = decode_live_window (*window); 2665 struct window *w = decode_live_window (*window);
2666 Lisp_Object miniwin = XFRAME (w->frame)->minibuffer_window;
2666 2667
2667 XSETWINDOW (*window, w); 2668 XSETWINDOW (*window, w);
2668 /* MINIBUF nil may or may not include minibuffers. Decide if it 2669 /* MINIBUF nil may or may not include minibuffers. Decide if it
2669 does. */ 2670 does. */
2670 if (NILP (*minibuf)) 2671 if (NILP (*minibuf))
2671 *minibuf = minibuf_level ? minibuf_window : Qlambda; 2672 *minibuf = this_minibuffer_depth (XWINDOW (miniwin)->contents)
2673 ? miniwin
2674 : Qlambda;
2672 else if (!EQ (*minibuf, Qt)) 2675 else if (!EQ (*minibuf, Qt))
2673 *minibuf = Qlambda; 2676 *minibuf = Qlambda;
2674 2677
diff --git a/src/window.h b/src/window.h
index 332cb3091fd..79eb44e7a38 100644
--- a/src/window.h
+++ b/src/window.h
@@ -1124,10 +1124,6 @@ extern Lisp_Object echo_area_window;
1124 1124
1125extern EMACS_INT command_loop_level; 1125extern EMACS_INT command_loop_level;
1126 1126
1127/* Depth in minibuffer invocations. */
1128
1129extern EMACS_INT minibuf_level;
1130
1131/* Non-zero if we should redraw the mode lines on the next redisplay. 1127/* Non-zero if we should redraw the mode lines on the next redisplay.
1132 Usually set to a unique small integer so we can track the main causes of 1128 Usually set to a unique small integer so we can track the main causes of
1133 full redisplays in `redisplay--mode-lines-cause'. */ 1129 full redisplays in `redisplay--mode-lines-cause'. */