summaryrefslogtreecommitdiff
path: root/src/frame.c
diff options
context:
space:
mode:
authorAlan Mackenzie <acm@muc.de>2023-06-21 14:23:14 +0000
committerAlan Mackenzie <acm@muc.de>2023-06-21 14:23:14 +0000
commit4ca371e9cc7178572cc25cbe47371c0075405ff7 (patch)
treefcb790b0431b6a47739fc2644298676c28076306 /src/frame.c
parenta0ccf1859cc636998403c52cb25d5aaf43744d47 (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.c50
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