[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, 28 Nov 2020 15:35:49 +0000 |
> Hello, Gregory and Martin.
On Sat, Nov 28, 2020 at 10:45:34 +0000, Alan Mackenzie wrote:
> On Fri, Nov 27, 2020 at 07:33:04 +0000, Gregory Heytings wrote:
> [ .... ]
> > | Emacs 21-27 | Emacs 28 with (setq m-f-s-f t) | Emacs 28 with (setq
> > m-f-s-f nil)
> > A | MB1 on F1 | MB1 on F2 | MB1 on F1
> > B | MB1+2 on F2 | MB1+2 on F2 | MB1 on F1, MB2 on F2 [1]
> > A: type C-x C-f on frame F1, switch to frame F2
> > B: type C-x C-f on frame F1, switch to frame F2, type M-:
> > [1] There is also a severe regression in this case. Type C-x C-f on frame
> > F1, switch to frame F2, type M-:. "Find file" is still visible in the
> > miniwindow on frame F1; switch to frame F1.
> > Experiment 1: Type the name of a file and RET. You'll get the error
> > message "End of file during parsing", and MB2 on frame F2 will be left.
> > MB1 is now unuseable, and impossible to leave, it will stay on F1 whatever
> > you do.
> > Experiment 2: Type C-g. MB2 on frame F2 will be left, and "Find file"
> > will stay in MB1 on frame F1. However you cannot use it anymore, the
> > keymap of MB1 is now minibuffer-inactive-mode-map. And like in experiment
> > 1, you cannot leave it.
> The abstract cause of this situation would appear to be using F1's
> minibuffer while a more deeply nested minibuffer is still active. It is
> a violation of the "recursive" nature of these buffers.
> I think a solution would be to put F1's minibuffer into
> minibuffer-inactive-mode until the recursive MB in F2 has terminated.
> What do you think of this?
Here's a trial implementation, which doesn't quite put F1's MB into
minibuffer-inactive-mode, but sets its local keymap to the mode's
keymap.
diff --git a/src/minibuf.c b/src/minibuf.c
index fc3fd92a88..58e72bc4a4 100644
--- a/src/minibuf.c
+++ b/src/minibuf.c
@@ -63,6 +63,8 @@ static Lisp_Object minibuf_prompt;
static ptrdiff_t minibuf_prompt_width;
+static Lisp_Object nth_minibuffer (EMACS_INT depth);
+
static bool
minibuf_follows_frame (void)
@@ -90,7 +92,7 @@ choose_minibuf_frame (void)
minibuf_window = sf->minibuffer_window;
/* If we've still got another minibuffer open, use its mini-window
instead. */
- if (minibuf_level && !minibuf_follows_frame ())
+ if (minibuf_level > 1 && !minibuf_follows_frame ())
{
Lisp_Object buffer = get_minibuffer (minibuf_level);
Lisp_Object tail, frame;
@@ -411,6 +413,7 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt,
Lisp_Object val;
ptrdiff_t count = SPECPDL_INDEX ();
Lisp_Object mini_frame, ambient_dir, minibuffer, input_method;
+ Lisp_Object calling_frame = selected_frame;
Lisp_Object enable_multibyte;
EMACS_INT pos = 0;
/* String to add to the history. */
@@ -532,7 +535,9 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt,
minibuf_save_list
= Fcons (Voverriding_local_map,
Fcons (minibuf_window,
- minibuf_save_list));
+ Fcons (BVAR (XBUFFER (nth_minibuffer (minibuf_level - 1)),
+ keymap),
+ minibuf_save_list)));
minibuf_save_list
= Fcons (minibuf_prompt,
Fcons (make_fixnum (minibuf_prompt_width),
@@ -727,8 +732,26 @@ read_minibuf (Lisp_Object map, Lisp_Object initial,
Lisp_Object prompt,
/* Don't allow the user to undo past this point. */
bset_undo_list (current_buffer, Qnil);
+ /* Prevent the user manipulating outer levels of recursive minibuffers. */
+ if (minibuf_level > 1)
+ {
+ Lisp_Object inactive_map;
+ if ((inactive_map =
+ find_symbol_value (intern ("minibuffer-inactive-mode-map")))
+ != Qunbound)
+ bset_keymap (XBUFFER (nth_minibuffer (minibuf_level - 1)),
+ inactive_map);
+ }
+
recursive_edit_1 ();
+ /* We've exited the recursive edit without an error, so switch the frame
+ back to the calling frame. */
+ if (!EQ (selected_frame, calling_frame)
+ && FRAMEP (calling_frame)
+ && FRAME_LIVE_P (XFRAME (calling_frame)))
+ do_switch_frame (calling_frame, 1, 0, Qnil);
+
/* If cursor is on the minibuffer line,
show the user we have exited by putting it in column 0. */
if (XWINDOW (minibuf_window)->cursor.vpos >= 0
@@ -790,6 +813,14 @@ is_minibuffer (EMACS_INT depth, Lisp_Object buf)
&& EQ (Fcar (tail), buf);
}
+/* Return the DEPTHth minibuffer, or nil if such does not yet exist. */
+static Lisp_Object
+nth_minibuffer (EMACS_INT depth)
+{
+ Lisp_Object tail = Fnthcdr (make_fixnum (depth), Vminibuffer_list);
+ return XCAR (tail);
+}
+
/* 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. */
@@ -852,6 +883,7 @@ read_minibuf_unwind (void)
Lisp_Object old_deactivate_mark;
Lisp_Object window;
Lisp_Object future_mini_window;
+ Lisp_Object map;
/* If this was a recursive minibuffer,
tie the minibuffer window back to the outer level minibuffer buffer. */
@@ -888,6 +920,8 @@ read_minibuf_unwind (void)
#endif
future_mini_window = Fcar (minibuf_save_list);
minibuf_save_list = Fcdr (minibuf_save_list);
+ map = Fcar (minibuf_save_list);
+ minibuf_save_list = Fcdr (minibuf_save_list);
/* Erase the minibuffer we were using at this level. */
{
@@ -901,6 +935,10 @@ read_minibuf_unwind (void)
unbind_to (count, Qnil);
}
+ /* Restore the keymap of any outer level recursive minibuffer. */
+ if (minibuf_level > 0)
+ bset_keymap (XBUFFER (nth_minibuffer (minibuf_level)), map);
+
/* When we get to the outmost level, make sure we resize the
mini-window back to its normal size. */
if (minibuf_level == 0
--
Alan Mackenzie (Nuremberg, Germany).
- Re: Stop frames stealing eachothers' minibuffers!, (continued)
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, martin rudalics, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, martin rudalics, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, martin rudalics, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, martin rudalics, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, Alan Mackenzie, 2020/11/28
- Re: Stop frames stealing eachothers' minibuffers!,
Alan Mackenzie <=
- Re: Stop frames stealing eachothers' minibuffers!, Stefan Monnier, 2020/11/28
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/11/28
- Re: Stop frames stealing eachothers' minibuffers!, Stefan Monnier, 2020/11/28
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/11/28
- Re: Stop frames stealing eachothers' minibuffers!, Stefan Monnier, 2020/11/28
- Re: Stop frames stealing eachothers' minibuffers!, Gregory Heytings, 2020/11/28
- Re: Stop frames stealing eachothers' minibuffers!, Alan Mackenzie, 2020/11/29
- Re: Stop frames stealing eachothers' minibuffers!, Alan Mackenzie, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, martin rudalics, 2020/11/27
- Re: Stop frames stealing eachothers' minibuffers!, Alan Mackenzie, 2020/11/27