From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Alan Mackenzie Newsgroups: gmane.emacs.devel Subject: Re: Stop frames stealing eachothers' minibuffers! Date: Sat, 28 Nov 2020 15:35:49 +0000 Message-ID: References: <53833023-d959-07af-7611-aa2e0bdcc1bc@gmx.at> <0d14bfc4-8e8e-d3b9-e0e1-ee4bf2e6449d@gmx.at> <20201125210947.GB8228@ACM> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="24285"; mail-complaints-to="usenet@ciao.gmane.io" Cc: enometh@meer.net, emacs-devel@gnu.org, Eli Zaretskii , Andrii Kolomoiets , Stefan Monnier To: Gregory Heytings , martin rudalics Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Sat Nov 28 16:36:35 2020 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1kj2H5-0006BW-84 for ged-emacs-devel@m.gmane-mx.org; Sat, 28 Nov 2020 16:36:35 +0100 Original-Received: from localhost ([::1]:42204 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1kj2H4-0004nV-0o for ged-emacs-devel@m.gmane-mx.org; Sat, 28 Nov 2020 10:36:34 -0500 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:51106) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1kj2GS-0004N7-Kh for emacs-devel@gnu.org; Sat, 28 Nov 2020 10:35:57 -0500 Original-Received: from colin.muc.de ([193.149.48.1]:65249 helo=mail.muc.de) by eggs.gnu.org with smtp (Exim 4.90_1) (envelope-from ) id 1kj2GP-0001pH-0L for emacs-devel@gnu.org; Sat, 28 Nov 2020 10:35:56 -0500 Original-Received: (qmail 42003 invoked by uid 3782); 28 Nov 2020 15:35:50 -0000 Original-Received: from acm.muc.de (p2e5d54e3.dip0.t-ipconnect.de [46.93.84.227]) by localhost.muc.de (tmda-ofmipd) with ESMTP; Sat, 28 Nov 2020 16:35:49 +0100 Original-Received: (qmail 8587 invoked by uid 1000); 28 Nov 2020 15:35:49 -0000 Content-Disposition: inline In-Reply-To: X-Delivery-Agent: TMDA/1.1.12 (Macallan) X-Primary-Address: acm@muc.de Received-SPF: pass client-ip=193.149.48.1; envelope-from=acm@muc.de; helo=mail.muc.de X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=unavailable autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:259955 Archived-At: > 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).