diff options
| author | Alan Mackenzie | 2021-01-10 20:32:40 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2021-01-10 20:32:40 +0000 |
| commit | c7c154bb5756e0ae71d342c5d8aabf725877f186 (patch) | |
| tree | 4db61dff837b5e5f5b864c2e1b53a1051ec536bf | |
| parent | a583c72305530f7d3ecc9ba50eefa70b6ddecdd9 (diff) | |
| download | emacs-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.texi | 10 | ||||
| -rw-r--r-- | doc/emacs/trouble.texi | 7 | ||||
| -rw-r--r-- | doc/lispref/minibuf.texi | 24 | ||||
| -rw-r--r-- | etc/NEWS | 13 | ||||
| -rw-r--r-- | lisp/cus-start.el | 6 | ||||
| -rw-r--r-- | lisp/minibuffer.el | 8 | ||||
| -rw-r--r-- | lisp/window.el | 5 | ||||
| -rw-r--r-- | src/eval.c | 26 | ||||
| -rw-r--r-- | src/lisp.h | 2 | ||||
| -rw-r--r-- | src/minibuf.c | 182 | ||||
| -rw-r--r-- | src/window.c | 5 | ||||
| -rw-r--r-- | src/window.h | 4 |
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 | |||
| 76 | the user option @code{minibuffer-follows-selected-frame} to | 76 | the 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 |
| 78 | it, and you must switch back to that frame in order to complete (or | 78 | it, and you must switch back to that frame in order to complete (or |
| 79 | abort) the current command. Note that the effect of the command, when | 79 | abort) the current command. If you set that option to a value which |
| 80 | you finally finish using the minibuffer, always takes place in the | 80 | is neither @code{nil} nor @code{t}, the minibuffer moves frame only |
| 81 | frame where you first opened it. | 81 | after 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 | ||
| 84 | effect of the command, when you finally finish using the minibuffer, | ||
| 85 | always 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 | |||
| 57 | successive @kbd{C-g} characters to get out of a search. | 57 | successive @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 | ||
| 61 | opened that minibuffer, closing it. If that minibuffer is not the | ||
| 62 | most recently opened one (which can happen when | ||
| 63 | @code{minibuffer-follows-selected-frame} is @code{nil} (@pxref{Basic | ||
| 64 | Minibuffer})), @kbd{C-g} also closes the more recently opened ones, | ||
| 65 | quitting 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 |
| 61 | like @kbd{C-g}. The reason is that it is not feasible, on MS-DOS, to | 68 | like @kbd{C-g}. The reason is that it is not feasible, on MS-DOS, to |
| 62 | recognize @kbd{C-g} while a command is running, between interactions | 69 | recognize @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 | |||
| 82 | incrementing the number at the end of the name. (The names begin with | 82 | incrementing the number at the end of the name. (The names begin with |
| 83 | a space so that they won't show up in normal buffer lists.) Of | 83 | a space so that they won't show up in normal buffer lists.) Of |
| 84 | several recursive minibuffers, the innermost (or most recently | 84 | several recursive minibuffers, the innermost (or most recently |
| 85 | entered) is the active minibuffer. We usually call this @emph{the} | 85 | entered) is the @dfn{active minibuffer}--it is the one you can |
| 86 | minibuffer. You can permit or forbid recursive minibuffers by setting | 86 | terminate by typing @key{RET} (@code{exit-minibuffer}) in. We usually |
| 87 | the variable @code{enable-recursive-minibuffers}, or by putting | 87 | call this @emph{the} minibuffer. You can permit or forbid recursive |
| 88 | properties of that name on command symbols (@xref{Recursive Mini}.) | 88 | minibuffers by setting the variable |
| 89 | @code{enable-recursive-minibuffers}, or by putting properties of that | ||
| 90 | name 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 |
| 2382 | This command exits the active minibuffer. It is normally bound to | 2384 | This command exits the active minibuffer. It is normally bound to |
| 2383 | keys in minibuffer local keymaps. | 2385 | keys in minibuffer local keymaps. The command throws an error if the |
| 2386 | current 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. | |||
| 2594 | If this variable is non-@code{nil}, you can invoke commands (such as | 2597 | If 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 |
| 2596 | active. Such invocation produces a recursive editing level for a new | 2599 | active. Such invocation produces a recursive editing level for a new |
| 2597 | minibuffer. The outer-level minibuffer is invisible while you are | 2600 | minibuffer. By default, the outer-level minibuffer is invisible while |
| 2598 | editing the inner one. | 2601 | you are editing the inner one. If you have |
| 2602 | @code{minibuffer-follows-selected-frame} set to @code{nil}, you can | ||
| 2603 | have minibuffers visible on several frames at the same time. | ||
| 2604 | @xref{Basic Minibuffer,,, emacs}. | ||
| 2599 | 2605 | ||
| 2600 | If this variable is @code{nil}, you cannot invoke minibuffer commands | 2606 | If this variable is @code{nil}, you cannot invoke minibuffer commands |
| 2601 | when the minibuffer is active, not even if you switch to another window | 2607 | when 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 |
| 2626 | This is a normal hook that is run whenever the minibuffer is entered. | 2632 | This 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 |
| 2644 | This is a normal hook that is run whenever the minibuffer is exited. | 2650 | This 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 | ||
| @@ -102,12 +102,13 @@ effect should be negligible in the vast majority of cases anyway. | |||
| 102 | By default, when you switch to another frame, an active minibuffer now | 102 | By default, when you switch to another frame, an active minibuffer now |
| 103 | moves to the newly selected frame. Nevertheless, the effect of what | 103 | moves to the newly selected frame. Nevertheless, the effect of what |
| 104 | you type in the minibuffer happens in the frame where the minibuffer | 104 | you type in the minibuffer happens in the frame where the minibuffer |
| 105 | was first activated, even if it moved to another frame. An | 105 | was first activated. An alternative behavior is available by |
| 106 | alternative behavior is available by customizing | 106 | customizing 'minibuffer-follows-selected-frame' to nil. Here, the |
| 107 | 'minibuffer-follows-selected-frame' to nil. Here, the minibuffer | 107 | minibuffer stays in the frame where you first opened it, and you must |
| 108 | stays in the frame where you first opened it, and you must switch back | 108 | switch back to this frame to continue or abort its command. The old |
| 109 | to this frame to continue or abort its command. The old, somewhat | 109 | behavior, which mixed these two, can be approximated by customizing |
| 110 | unsystematic behavior, which mixed these two is no longer available. | 110 | 'minibuffer-follows-selected-frame' to a value which is neither nil |
| 111 | nor 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 | |||
| 1167 | internal_catch (Lisp_Object tag, | 1167 | internal_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; | |||
| 4346 | extern Lisp_Object last_minibuf_string; | 4346 | extern Lisp_Object last_minibuf_string; |
| 4347 | extern void move_minibuffer_onto_frame (void); | 4347 | extern void move_minibuffer_onto_frame (void); |
| 4348 | extern bool is_minibuffer (EMACS_INT, Lisp_Object); | 4348 | extern bool is_minibuffer (EMACS_INT, Lisp_Object); |
| 4349 | extern EMACS_INT this_minibuffer_depth (Lisp_Object); | ||
| 4350 | extern EMACS_INT minibuf_level; | ||
| 4349 | extern Lisp_Object get_minibuffer (EMACS_INT); | 4351 | extern Lisp_Object get_minibuffer (EMACS_INT); |
| 4350 | extern void init_minibuf_once (void); | 4352 | extern void init_minibuf_once (void); |
| 4351 | extern void syms_of_minibuf (void); | 4353 | extern 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 | ||
| 64 | static ptrdiff_t minibuf_prompt_width; | 64 | static ptrdiff_t minibuf_prompt_width; |
| 65 | 65 | ||
| 66 | static 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. */ | ||
| 67 | static bool | 71 | static bool |
| 68 | minibuf_follows_frame (void) | 72 | minibuf_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. */ | ||
| 80 | static bool | ||
| 81 | minibuf_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. */ | ||
| 88 | static bool | ||
| 89 | minibuf_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. */ | ||
| 128 | void move_minibuffer_onto_frame (void) | 163 | void 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 | ||
| 378 | DEFUN ("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. | ||
| 381 | No 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. */ | ||
| 395 | EMACS_INT | ||
| 396 | this_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 | |||
| 411 | DEFUN ("abort-minibuffers", Fabort_minibuffers, Sabort_minibuffers, 0, 0, "", | ||
| 412 | doc: /* Abort the current minibuffer. | ||
| 413 | If we are not currently in the innermost minibuffer, prompt the user to | ||
| 414 | confirm 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 | |||
| 339 | DEFUN ("minibuffer-prompt-end", Fminibuffer_prompt_end, | 435 | DEFUN ("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. */ | ||
| 922 | static Lisp_Object | ||
| 923 | nth_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. */); | |||
| 2032 | The function is called with the arguments passed to `read-buffer'. */); | 2168 | The 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. |
| 2037 | Nil means that a minibuffer will appear only in the frame which created it. | 2173 | Nil means that a minibuffer will appear only in the frame which created it. |
| 2174 | Any other value means the minibuffer will move onto another frame, but | ||
| 2175 | only when the user starts using a minibuffer there. | ||
| 2038 | 2176 | ||
| 2039 | Any buffer local or dynamic binding of this variable is ignored. Only the | 2177 | Any buffer local or dynamic binding of this variable is ignored. Only the |
| 2040 | default top level value is used. */); | 2178 | default 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 | |||
| 2663 | decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object *all_frames) | 2663 | decode_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 | ||
| 1125 | extern EMACS_INT command_loop_level; | 1125 | extern EMACS_INT command_loop_level; |
| 1126 | 1126 | ||
| 1127 | /* Depth in minibuffer invocations. */ | ||
| 1128 | |||
| 1129 | extern 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'. */ |