diff options
author | Alan Mackenzie <acm@muc.de> | 2023-06-21 14:23:14 +0000 |
---|---|---|
committer | Alan Mackenzie <acm@muc.de> | 2023-06-21 14:23:14 +0000 |
commit | 4ca371e9cc7178572cc25cbe47371c0075405ff7 (patch) | |
tree | fcb790b0431b6a47739fc2644298676c28076306 /src/frame.c | |
parent | a0ccf1859cc636998403c52cb25d5aaf43744d47 (diff) |
Fix bug#64152 (Minibuffer sometimes goes "modal")
In particular, when a frame has no minibuffer and is using that
of a different "normal" frame, C-x 5 o, etc., and GUI
operations fail.
Fix by partially reverting the commit from 2022-07-07 15:38:09
+0000 "Remove obscure, obsolete code from do_switch_frame". As
a consequent change, also revert the commit from 2022-07-08
20:19:03 +0000 "Remove now unused parameter TRACK from
do_switch_frame".
* src/frame.c (do_switch_frame): Restore the TRACK parameter.
Restore the code which redirects the frame focus when a new
frame gets selected.
* src/frame.c (Fselect_frame, Fhandle_switch_frame)
(delete_frame)
* src/keyboard.c (quit_throw_to_read_char)
* src/lisp.h (do_switch_frame prototype)
* src/minibuf.c (read_minibuf_unwind)
* src/window.c (Fset_window_configuration): Restore the TRACK
argument to do_switch_frame.
* src/xterm.c (x_try_restore_frame): Add a zero TRACK argument
to do_switch_frame.
Diffstat (limited to 'src/frame.c')
-rw-r--r-- | src/frame.c | 50 |
1 files changed, 46 insertions, 4 deletions
diff --git a/src/frame.c b/src/frame.c index 38a6583605c..fc6a3459482 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1444,6 +1444,10 @@ affects all frames on the same terminal device. */) If FRAME is a switch-frame event `(switch-frame FRAME1)', use FRAME1 as frame. + If TRACK is non-zero and the frame that currently has the focus + redirects its focus to the selected frame, redirect that focused + frame's focus to FRAME instead. + FOR_DELETION non-zero means that the selected frame is being deleted, which includes the possibility that the frame's terminal is dead. @@ -1451,7 +1455,7 @@ affects all frames on the same terminal device. */) The value of NORECORD is passed as argument to Fselect_window. */ Lisp_Object -do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord) +do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object norecord) { struct frame *sf = SELECTED_FRAME (), *f; @@ -1473,6 +1477,44 @@ do_switch_frame (Lisp_Object frame, int for_deletion, Lisp_Object norecord) else if (f == sf) return frame; + /* If the frame with GUI focus has had it's Emacs focus redirected + toward the currently selected frame, we should change the + redirection to point to the newly selected frame. This means + that if the focus is redirected from a minibufferless frame to a + surrogate minibuffer frame, we can use `other-window' to switch + between all the frames using that minibuffer frame, and the focus + redirection will follow us around. This code is necessary when + we have a minibufferless frame using the MB in another (normal) + frame (bug#64152) (ACM, 2023-06-20). */ +#ifdef HAVE_WINDOW_SYSTEM + if (track && FRAME_WINDOW_P (f) && FRAME_TERMINAL (f)->get_focus_frame) + { + Lisp_Object gfocus; /* The frame which still has focus on the + current terminal, according to the GUI + system. */ + Lisp_Object focus; /* The frame to which Emacs has redirected + the focus from `gfocus'. This might be a + frame with a minibuffer when `gfocus' + doesn't have a MB. */ + + gfocus = FRAME_TERMINAL (f)->get_focus_frame (f); + if (FRAMEP (gfocus)) + { + focus = FRAME_FOCUS_FRAME (XFRAME (gfocus)); + if (FRAMEP (focus) && XFRAME (focus) == SELECTED_FRAME ()) + /* Redirect frame focus also when FRAME has its minibuffer + window on the selected frame (see Bug#24500). + + Don't do that: It causes redirection problem with a + separate minibuffer frame (Bug#24803) and problems + when updating the cursor on such frames. + || (NILP (focus) + && EQ (FRAME_MINIBUF_WINDOW (f), sf->selected_window))) */ + Fredirect_frame_focus (gfocus, frame); + } + } +#endif /* HAVE_X_WINDOWS */ + if (!for_deletion && FRAME_HAS_MINIBUF_P (sf)) resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1); @@ -1574,7 +1616,7 @@ This function returns FRAME, or nil if FRAME has been deleted. */) /* Do not select a tooltip frame (Bug#47207). */ error ("Cannot select a tooltip frame"); else - return do_switch_frame (frame, 0, norecord); + return do_switch_frame (frame, 1, 0, norecord); } DEFUN ("handle-switch-frame", Fhandle_switch_frame, @@ -1590,7 +1632,7 @@ necessarily represent user-visible input focus. */) kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); run_hook (Qmouse_leave_buffer_hook); - return do_switch_frame (event, 0, Qnil); + return do_switch_frame (event, 0, 0, Qnil); } DEFUN ("selected-frame", Fselected_frame, Sselected_frame, 0, 0, 0, @@ -2108,7 +2150,7 @@ delete_frame (Lisp_Object frame, Lisp_Object force) Fraise_frame (frame1); #endif - do_switch_frame (frame1, 1, Qnil); + do_switch_frame (frame1, 0, 1, Qnil); sf = SELECTED_FRAME (); } else |