[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Stop frames stealing eachothers' minibuffers!
From: |
Alan Mackenzie |
Subject: |
Re: Stop frames stealing eachothers' minibuffers! |
Date: |
Sat, 31 Oct 2020 16:14:22 +0000 |
Hello, Eli.
Thanks for such a quick reply to my last post.
On Sat, Oct 31, 2020 at 09:25:00 +0200, Eli Zaretskii wrote:
> > Date: Fri, 30 Oct 2020 22:09:17 +0000
> > Cc: emacs-devel@gnu.org
> > From: Alan Mackenzie <acm@muc.de>
> > DEFUN ("minibufferp", Fminibufferp,
> > - Sminibufferp, 0, 1, 0,
> > + Sminibufferp, 0, 2, 0,
> > doc: /* Return t if BUFFER is a minibuffer.
> > No argument or nil as argument means use current buffer as BUFFER.
> > -BUFFER can be a buffer or a buffer name. */)
> > - (Lisp_Object buffer)
> > +BUFFER can be a buffer or a buffer name. If LIVE is non-nil, then
> > +t will be returned only if BUFFER is an active minibuffer. */)
> > + (Lisp_Object buffer, Lisp_Object live)
> > {
> This uses passive tense in the last sentence.
Fixed. I've also added a bit to lispref/minibuf.texi for the new
argument. (See amended patch below).
> > + /* tem = Fmemq (buffer, Vminibuffer_list); */
> > + /* return (!NILP (tem) && !EQ (tem, Vminibuffer_list)) ? Qt : Qnil; */
> This seems to be a leftover from developing the new code
Yes, sorry about that. I've now removed it.
> > + if (!NILP (live))
> > + return !NILP (Fmemq (buffer, Vminibuffer_list)) ? Qt : Qnil;
> > + if (EQ (buffer, Fcar (Vminibuffer_list)))
> > + /* *Minibuf-0* is never active. */
> > + return Qnil;
> > + tem = Fcdr (Vminibuffer_list);
> > + for (i = 1; i <= minibuf_level; i++)
> > + {
> > + if (NILP (tem))
> > + return Qnil;
> Why is this test inside the loop?
What was wrong here was forgetting to (cdr tem) each time through the
loop. I've fixed that. I've also removed the test, since it really
isn't needed.
Also in that snippet, the (!NILP (live)) was the wrong way round, and
I've corrected it to (NILP (live)).
> > @@ -416,11 +471,12 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
> > Lisp_Object prompt,
> > {
> > Lisp_Object str
> > = build_string ("Command attempted to use minibuffer while in
> > minibuffer");
> > - if (EQ (selected_window, minibuf_window))
> > - Fsignal (Quser_error, (list1 (str)));
> > + if (!minibuf_follows_frame ()
> > + || EQ (selected_window, minibuf_window))
> > + Fsignal (Quser_error, (list1 (str)));
> I don't think I understand this change: what does
> minibuffer-follows-selected-frame have to do with recursive minibuffer
> usage? They are two independent features.
They're not as independent as all that. The existing logic appeared to
say "if we're in the miniwindow, just abort the current command,
otherwise abort all nested commands.". Extending that logic to when we
have several miniwindows, we'd (perhaps) get "if we're in _A_ miniwindow
just abort the current command.".
Which, further extended, goes "if we're in ANY window, just abort the
current command.". I agree, this is an independent feature from the
main one. But it brings consistency (and, possibly, usability) to this
abort facility. I can put this back to more or less what it was. But
why do we abort the whole command stack when there's just a single
error?
> > - /* Empty out the minibuffers of all frames other than the one
> > - where we are going to display one now.
> > - Set them to point to ` *Minibuf-0*', which is always empty. */
> > - empty_minibuf = get_minibuffer (0);
> > -
> > - FOR_EACH_FRAME (dummy, frame)
> > - {
> > - Lisp_Object root_window = Fframe_root_window (frame);
> > - Lisp_Object mini_window = XWINDOW (root_window)->next;
> > -
> > - if (! NILP (mini_window) && ! EQ (mini_window, minibuf_window)
> > - && !NILP (Fwindow_minibuffer_p (mini_window)))
> > - /* Use set_window_buffer instead of Fset_window_buffer (see
> > - discussion of bug#11984, bug#12025, bug#12026). */
> > - set_window_buffer (mini_window, empty_minibuf, 0, 0);
> > - }
> Does this mean the minibuffers on other frames will now not be emptied?
Yes, indeed. If minibuffer-follows-selected-frame, there'll only be a
single mini-window, which we're about to write into, so there's no point
emptying out a null set of other windows. If
!minibuffer-follows-selected-frame, we don't want to empty these other
mini-windows. They're there for when the user eventually comes back to
them.
> > +/* Returns whether a Lisp_Object is a particular existing minibuffer. */
> Our style of comments in these cases is like this:
> "Return non-zero if BUF is a particular existing minibuffer."
Fixed.
> > + DEFVAR_BOOL ("minibuffer-follows-selected-frame",
> > minibuffer_follows_selected_frame,
> > + doc: /* Non-nil means an open minibuffer will move to a
> > newly selected frame.
> Talking about "moving" and "newly selected" here might come as a
> surprise, because the context was not described. How about
> Non-nil means active minibuffer always displays on the selected frame.
OK, I've put that in with a "the" before "active minibuffer", to be
definite we're only talking about the innermost minibuffer.
> Thanks.
OK, here's the amended patch:
diff --git a/doc/emacs/mini.texi b/doc/emacs/mini.texi
index 54f046a7e0..ede95a28d4 100644
--- a/doc/emacs/mini.texi
+++ b/doc/emacs/mini.texi
@@ -69,6 +69,17 @@ Basic Minibuffer
the minibuffer comes back. While the minibuffer is in use, Emacs does
not echo keystrokes.
+@vindex minibuffer-follows-selected-frame
+ While using the minibuffer, you can switch to a different frame,
+perhaps to note text you need to enter (@pxref{Frame Commands}). By
+default, the active minibuffer moves to this new frame. If you set
+the user option @code{minibuffer-follows-selected-frame} to
+@code{nil}, then the minibuffer stays in the frame where you opened
+it, and you must switch back to that frame in order to complete (or
+abort) the current command. Note that the effect of the command, when
+you finally finish using the minibuffer, always takes place in the
+frame where you first opened it.
+
@node Minibuffer File
@section Minibuffers for File Names
diff --git a/doc/lispref/minibuf.texi b/doc/lispref/minibuf.texi
index e5a0233b3c..b6a3434d15 100644
--- a/doc/lispref/minibuf.texi
+++ b/doc/lispref/minibuf.texi
@@ -2586,10 +2586,12 @@ Recursive Mini
@node Minibuffer Misc
@section Minibuffer Miscellany
-@defun minibufferp &optional buffer-or-name
+@defun minibufferp &optional buffer-or-name live
This function returns non-@code{nil} if @var{buffer-or-name} is a
-minibuffer. If @var{buffer-or-name} is omitted, it tests the current
-buffer.
+minibuffer. If @var{buffer-or-name} is omitted or @code{nil}, it
+tests the current buffer. When @var{live} is non-@code{nil}, the
+function returns non-@code{nil} only when @var{buffer-or-name} is an
+active minibuffer.
@end defun
@defvar minibuffer-setup-hook
diff --git a/etc/NEWS b/etc/NEWS
index 4cc66aef6b..2489706d89 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -85,6 +85,17 @@ useful on systems such as FreeBSD which ships only with
"etc/termcap".
* Changes in Emacs 28.1
++++
+** Improved handling of minibuffers on switching frames.
+By default, an active minibuffer now moves to a newly selected frame.
+When continuing the current command (by completing the minibuffer
+action), the effect happens in the frame where the minibuffer was
+first opened. An alternative behavior is available by customizing
+'minibuffer-follows-selected-frame' to nil. Here, the minibuffer
+stays in the frame where you first opened it, and you must switch back
+to this frame to continue or abort its command. The old, somewhat
+unsystematic behavior is no longer available.
+
+++
** New system for displaying documentation for groups of function.
This can either be used by saying 'M-x shortdoc-display-group' and
diff --git a/lisp/cus-start.el b/lisp/cus-start.el
index 6927b6df6b..04fb1dc6d0 100644
--- a/lisp/cus-start.el
+++ b/lisp/cus-start.el
@@ -394,6 +394,7 @@ minibuffer-prompt-properties--setter
;; (directory :format "%v"))))
(load-prefer-newer lisp boolean "24.4")
;; minibuf.c
+ (minibuffer-follows-selected-frame minibuffer boolean "28.1")
(enable-recursive-minibuffers minibuffer boolean)
(history-length minibuffer
(choice (const :tag "Infinite" t) integer)
diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 5a41e2f30b..9d57a817b2 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -701,7 +701,7 @@ minibuffer-message
or until the next input event arrives, whichever comes first.
Enclose MESSAGE in [...] if this is not yet the case.
If ARGS are provided, then pass MESSAGE through `format-message'."
- (if (not (minibufferp (current-buffer)))
+ (if (not (minibufferp (current-buffer) t))
(progn
(if args
(apply #'message message args)
diff --git a/src/frame.c b/src/frame.c
index 7c377da445..512aaf5f45 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -1482,6 +1482,7 @@ do_switch_frame (Lisp_Object frame, int track, int
for_deletion, Lisp_Object nor
#endif
internal_last_event_frame = Qnil;
+ move_minibuffer_onto_frame ();
return frame;
}
diff --git a/src/lisp.h b/src/lisp.h
index 45353fbef3..548eebc9c7 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -4336,6 +4336,8 @@ extern void clear_regexp_cache (void);
extern Lisp_Object Vminibuffer_list;
extern Lisp_Object last_minibuf_string;
+extern void move_minibuffer_onto_frame (void);
+extern bool is_minibuffer (EMACS_INT, Lisp_Object);
extern Lisp_Object get_minibuffer (EMACS_INT);
extern void init_minibuf_once (void);
extern void syms_of_minibuf (void);
diff --git a/src/minibuf.c b/src/minibuf.c
index f957b2ae17..ff3201b4ae 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -64,6 +64,12 @@ static Lisp_Object minibuf_prompt;
static ptrdiff_t minibuf_prompt_width;
+static bool
+minibuf_follows_frame (void)
+{
+ return !NILP (Fdefault_toplevel_value (Qminibuffer_follows_selected_frame));
+}
+
/* Put minibuf on currently selected frame's minibuffer.
We do this whenever the user starts a new minibuffer
or when a minibuffer exits. */
@@ -76,37 +82,72 @@ choose_minibuf_frame (void)
&& !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window))
{
struct frame *sf = XFRAME (selected_frame);
- Lisp_Object buffer;
-
/* I don't think that any frames may validly have a null minibuffer
window anymore. */
if (NILP (sf->minibuffer_window))
emacs_abort ();
- /* Under X, we come here with minibuf_window being the
- minibuffer window of the unused termcap window created in
- init_window_once. That window doesn't have a buffer. */
- buffer = XWINDOW (minibuf_window)->contents;
- if (BUFFERP (buffer))
- /* Use set_window_buffer instead of Fset_window_buffer (see
- discussion of bug#11984, bug#12025, bug#12026). */
- set_window_buffer (sf->minibuffer_window, buffer, 0, 0);
minibuf_window = sf->minibuffer_window;
+ /* If we've still got another minibuffer open, use its mini-window
+ instead. */
+ if (minibuf_level && !minibuf_follows_frame ())
+ {
+ Lisp_Object buffer = get_minibuffer (minibuf_level);
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ if (EQ (XWINDOW (XFRAME (frame)->minibuffer_window)->contents,
+ buffer))
+ {
+ minibuf_window = XFRAME (frame)->minibuffer_window;
+ break;
+ }
+ }
}
- /* Make sure no other frame has a minibuffer as its selected window,
- because the text would not be displayed in it, and that would be
- confusing. Only allow the selected frame to do this,
- and that only if the minibuffer is active. */
- {
- Lisp_Object tail, frame;
+ if (minibuf_follows_frame ())
+ /* Make sure no other frame has a minibuffer as its selected window,
+ because the text would not be displayed in it, and that would be
+ confusing. Only allow the selected frame to do this,
+ and that only if the minibuffer is active. */
+ {
+ Lisp_Object tail, frame;
+
+ FOR_EACH_FRAME (tail, frame)
+ if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (XFRAME (frame))))
+ && !(EQ (frame, selected_frame)
+ && minibuf_level > 0))
+ Fset_frame_selected_window (frame, Fframe_first_window (frame),
+ Qnil);
+ }
+}
- FOR_EACH_FRAME (tail, frame)
- if (MINI_WINDOW_P (XWINDOW (FRAME_SELECTED_WINDOW (XFRAME (frame))))
- && !(EQ (frame, selected_frame)
- && minibuf_level > 0))
- Fset_frame_selected_window (frame, Fframe_first_window (frame), Qnil);
- }
+/* If `minibuffer_follows_selected_frame' and we have a minibuffer, move it
+ from its current frame to the selected frame. This function is
+ intended to be called from `do_switch_frame' in frame.c. */
+void move_minibuffer_onto_frame (void)
+{
+ if (!minibuf_level)
+ return;
+ if (!minibuf_follows_frame ())
+ return;
+ if (FRAMEP (selected_frame)
+ && FRAME_LIVE_P (XFRAME (selected_frame))
+ && !EQ (minibuf_window, XFRAME (selected_frame)->minibuffer_window))
+ {
+ struct frame *sf = XFRAME (selected_frame);
+ Lisp_Object old_frame = XWINDOW (minibuf_window)->frame;
+ struct frame *of = XFRAME (old_frame);
+ Lisp_Object buffer = XWINDOW (minibuf_window)->contents;
+
+ set_window_buffer (sf->minibuffer_window, buffer, 0, 0);
+ minibuf_window = sf->minibuffer_window;
+ if (XWINDOW (minibuf_window)->frame == selected_frame)
+ /* The minibuffer might be on another frame. */
+ Fset_frame_selected_window (selected_frame, sf->minibuffer_window,
+ Qnil);
+ set_window_buffer (of->minibuffer_window, get_minibuffer (0), 0, 0);
+ }
}
DEFUN ("active-minibuffer-window", Factive_minibuffer_window,
@@ -262,13 +303,15 @@ read_minibuf_noninteractive (Lisp_Object prompt, bool
expflag,
}
DEFUN ("minibufferp", Fminibufferp,
- Sminibufferp, 0, 1, 0,
+ Sminibufferp, 0, 2, 0,
doc: /* Return t if BUFFER is a minibuffer.
No argument or nil as argument means use current buffer as BUFFER.
-BUFFER can be a buffer or a buffer name. */)
- (Lisp_Object buffer)
+BUFFER can be a buffer or a buffer name. If LIVE is non-nil, then
+return t only if BUFFER is an active minibuffer. */)
+ (Lisp_Object buffer, Lisp_Object live)
{
Lisp_Object tem;
+ EMACS_INT i;
if (NILP (buffer))
buffer = Fcurrent_buffer ();
@@ -277,8 +320,16 @@ BUFFER can be a buffer or a buffer name. */)
else
CHECK_BUFFER (buffer);
- tem = Fmemq (buffer, Vminibuffer_list);
- return ! NILP (tem) ? Qt : Qnil;
+ if (NILP (live))
+ return !NILP (Fmemq (buffer, Vminibuffer_list)) ? Qt : Qnil;
+ if (EQ (buffer, Fcar (Vminibuffer_list)))
+ /* *Minibuf-0* is never active. */
+ return Qnil;
+ tem = Fcdr (Vminibuffer_list);
+ for (i = 1; i <= minibuf_level; i++, tem = Fcdr (tem))
+ if (EQ (Fcar (tem), buffer))
+ return Qt;
+ return Qnil;
}
DEFUN ("minibuffer-prompt-end", Fminibuffer_prompt_end,
@@ -362,9 +413,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt,
Lisp_Object histstring;
Lisp_Object histval;
- Lisp_Object empty_minibuf;
- Lisp_Object dummy, frame;
-
specbind (Qminibuffer_default, defalt);
specbind (Qinhibit_read_only, Qnil);
@@ -416,11 +464,12 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt,
{
Lisp_Object str
= build_string ("Command attempted to use minibuffer while in
minibuffer");
- if (EQ (selected_window, minibuf_window))
- Fsignal (Quser_error, (list1 (str)));
+ if (!minibuf_follows_frame ()
+ || EQ (selected_window, minibuf_window))
+ Fsignal (Quser_error, (list1 (str)));
else
- /* If we're in another window, cancel the minibuffer that's active. */
- Fthrow (Qexit, str);
+ /* If we're in another window, cancel the minibuffer that's active. */
+ Fthrow (Qexit, str);
}
if ((noninteractive
@@ -433,6 +482,8 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt,
return unbind_to (count, val);
}
+ minibuf_level++; /* Before calling choose_minibuf_frame. */
+
/* Choose the minibuffer window and frame, and take action on them. */
/* Prepare for restoring the current buffer since choose_minibuf_frame
@@ -484,7 +535,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt,
= Fcons (Fthis_command_keys_vector (), minibuf_save_list);
record_unwind_protect_void (read_minibuf_unwind);
- minibuf_level++;
/* We are exiting the minibuffer one way or the other, so run the hook.
It should be run before unwinding the minibuf settings. Do it
separately from read_minibuf_unwind because we need to make sure that
@@ -566,23 +616,6 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt,
if (minibuf_level == 1 || !EQ (minibuf_window, selected_window))
minibuf_selected_window = selected_window;
- /* Empty out the minibuffers of all frames other than the one
- where we are going to display one now.
- Set them to point to ` *Minibuf-0*', which is always empty. */
- empty_minibuf = get_minibuffer (0);
-
- FOR_EACH_FRAME (dummy, frame)
- {
- Lisp_Object root_window = Fframe_root_window (frame);
- Lisp_Object mini_window = XWINDOW (root_window)->next;
-
- if (! NILP (mini_window) && ! EQ (mini_window, minibuf_window)
- && !NILP (Fwindow_minibuffer_p (mini_window)))
- /* Use set_window_buffer instead of Fset_window_buffer (see
- discussion of bug#11984, bug#12025, bug#12026). */
- set_window_buffer (mini_window, empty_minibuf, 0, 0);
- }
-
/* Display this minibuffer in the proper window. */
/* Use set_window_buffer instead of Fset_window_buffer (see
discussion of bug#11984, bug#12025, bug#12026). */
@@ -714,6 +747,16 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt,
return val;
}
+/* Return true if BUF is a particular existing minibuffer. */
+bool
+is_minibuffer (EMACS_INT depth, Lisp_Object buf)
+{
+ Lisp_Object tail = Fnthcdr (make_fixnum (depth), Vminibuffer_list);
+ return
+ !NILP (tail)
+ && EQ (Fcar (tail), buf);
+}
+
/* Return a buffer to be used as the minibuffer at depth `depth'.
depth = 0 is the lowest allowed argument, and that is the value
used for nonrecursive minibuffer invocations. */
@@ -775,6 +818,7 @@ read_minibuf_unwind (void)
{
Lisp_Object old_deactivate_mark;
Lisp_Object window;
+ Lisp_Object future_mini_window;
/* If this was a recursive minibuffer,
tie the minibuffer window back to the outer level minibuffer buffer. */
@@ -809,6 +853,7 @@ read_minibuf_unwind (void)
if (FRAME_LIVE_P (XFRAME (WINDOW_FRAME (XWINDOW (temp)))))
minibuf_window = temp;
#endif
+ future_mini_window = Fcar (minibuf_save_list);
minibuf_save_list = Fcdr (minibuf_save_list);
/* Erase the minibuffer we were using at this level. */
@@ -825,7 +870,8 @@ read_minibuf_unwind (void)
/* When we get to the outmost level, make sure we resize the
mini-window back to its normal size. */
- if (minibuf_level == 0)
+ if (minibuf_level == 0
+ || !EQ (selected_frame, WINDOW_FRAME (XWINDOW (future_mini_window))))
resize_mini_window (XWINDOW (window), 0);
/* Deal with frames that should be removed when exiting the
@@ -1911,6 +1957,8 @@ syms_of_minibuf (void)
staticpro (&minibuf_prompt);
staticpro (&minibuf_save_list);
+ DEFSYM (Qminibuffer_follows_selected_frame,
+ "minibuffer-follows-selected-frame");
DEFSYM (Qcompletion_ignore_case, "completion-ignore-case");
DEFSYM (Qminibuffer_default, "minibuffer-default");
Fset (Qminibuffer_default, Qnil);
@@ -1954,6 +2002,14 @@ For example, `eval-expression' uses this. */);
The function is called with the arguments passed to `read-buffer'. */);
Vread_buffer_function = Qnil;
+ DEFVAR_BOOL ("minibuffer-follows-selected-frame",
minibuffer_follows_selected_frame,
+ doc: /* Non-nil means the active minibuffer always displays on
the selected frame.
+Nil means that a minibuffer will appear only in the frame which created it.
+
+Any buffer local or dynamic binding of this variable is ignored. Only the
+default top level value is used. */);
+ minibuffer_follows_selected_frame = 1;
+
DEFVAR_BOOL ("read-buffer-completion-ignore-case",
read_buffer_completion_ignore_case,
doc: /* Non-nil means completion ignores case when reading a
buffer name. */);
diff --git a/src/window.c b/src/window.c
index e7433969d2..2eba509727 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2643,8 +2643,10 @@ candidate_window_p (Lisp_Object window, Lisp_Object
owindow,
/* To qualify as candidate, it's not sufficient for WINDOW's frame
to just share the minibuffer window - it must be active as well
(see Bug#24500). */
- candidate_p = (EQ (XWINDOW (all_frames)->frame, w->frame)
- || EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME (f)));
+ candidate_p = ((EQ (XWINDOW (all_frames)->frame, w->frame)
+ || (EQ (f->minibuffer_window, all_frames)
+ && EQ (XWINDOW (all_frames)->frame, FRAME_FOCUS_FRAME
(f))))
+ && !is_minibuffer (0, XWINDOW (all_frames)->contents));
else if (FRAMEP (all_frames))
candidate_p = EQ (all_frames, w->frame);
diff --git a/src/xdisp.c b/src/xdisp.c
index 0e5dffbe00..0dfe34a011 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -31220,7 +31220,9 @@ get_window_cursor_type (struct window *w, struct glyph
*glyph, int *width,
{
*active_cursor = false;
- if (MINI_WINDOW_P (w) && minibuf_level == 0)
+ if (MINI_WINDOW_P (w) &&
+ (minibuf_level == 0
+ || is_minibuffer (0, w->contents)))
return NO_CURSOR;
non_selected = true;
--
Alan Mackenzie (Nuremberg, Germany).
- Re: Stop frames stealing eachothers' minibuffers!, (continued)
- Re: Stop frames stealing eachothers' minibuffers!, Alan Mackenzie, 2020/10/21
- Re: Stop frames stealing eachothers' minibuffers!, Eli Zaretskii, 2020/10/22
- C-x o is moving between frames. [Was: Stop frames stealing eachothers' minibuffers!], Alan Mackenzie, 2020/10/23
- Re: C-x o is moving between frames. [Was: Stop frames stealing eachothers' minibuffers!], Stefan Monnier, 2020/10/23
- Re: C-x o is moving between frames. [Was: Stop frames stealing eachothers' minibuffers!], Eli Zaretskii, 2020/10/24
- Re: C-x o is moving between frames. [Was: Stop frames stealing eachothers' minibuffers!], Alan Mackenzie, 2020/10/24
- Re: C-x o is moving between frames. [Was: Stop frames stealing eachothers' minibuffers!], Stefan Monnier, 2020/10/24
- Re: C-x o is moving between frames. [Was: Stop frames stealing eachothers' minibuffers!], Alan Mackenzie, 2020/10/24
- Re: Stop frames stealing eachothers' minibuffers!, Alan Mackenzie, 2020/10/30
- Re: Stop frames stealing eachothers' minibuffers!, Eli Zaretskii, 2020/10/31
- Re: Stop frames stealing eachothers' minibuffers!,
Alan Mackenzie <=
- Re: Stop frames stealing eachothers' minibuffers!, Eli Zaretskii, 2020/10/31
- Re: Stop frames stealing eachothers' minibuffers!, Alan Mackenzie, 2020/10/31
- Re: Stop frames stealing eachothers' minibuffers!, Eli Zaretskii, 2020/10/31
- Re: Stop frames stealing eachothers' minibuffers!, Alan Mackenzie, 2020/10/31
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/10/14
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/10/14
- Re: Stop frames stealing eachothers' minibuffers!, Andreas Schwab, 2020/10/13
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/10/13
- Re: Stop frames stealing eachothers' minibuffers!, Stefan Monnier, 2020/10/13
Re: Stop frames stealing eachothers' minibuffers!, Stefan Monnier, 2020/10/13