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.
This commit is contained in:
parent
a0ccf1859c
commit
4ca371e9cc
6 changed files with 53 additions and 11 deletions
50
src/frame.c
50
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
|
If FRAME is a switch-frame event `(switch-frame FRAME1)', use
|
||||||
FRAME1 as frame.
|
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
|
FOR_DELETION non-zero means that the selected frame is being
|
||||||
deleted, which includes the possibility that the frame's terminal
|
deleted, which includes the possibility that the frame's terminal
|
||||||
is dead.
|
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. */
|
The value of NORECORD is passed as argument to Fselect_window. */
|
||||||
|
|
||||||
Lisp_Object
|
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;
|
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)
|
else if (f == sf)
|
||||||
return frame;
|
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))
|
if (!for_deletion && FRAME_HAS_MINIBUF_P (sf))
|
||||||
resize_mini_window (XWINDOW (FRAME_MINIBUF_WINDOW (sf)), 1);
|
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). */
|
/* Do not select a tooltip frame (Bug#47207). */
|
||||||
error ("Cannot select a tooltip frame");
|
error ("Cannot select a tooltip frame");
|
||||||
else
|
else
|
||||||
return do_switch_frame (frame, 0, norecord);
|
return do_switch_frame (frame, 1, 0, norecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
DEFUN ("handle-switch-frame", Fhandle_switch_frame,
|
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);
|
kset_prefix_arg (current_kboard, Vcurrent_prefix_arg);
|
||||||
run_hook (Qmouse_leave_buffer_hook);
|
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,
|
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);
|
Fraise_frame (frame1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
do_switch_frame (frame1, 1, Qnil);
|
do_switch_frame (frame1, 0, 1, Qnil);
|
||||||
sf = SELECTED_FRAME ();
|
sf = SELECTED_FRAME ();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -11561,7 +11561,7 @@ quit_throw_to_read_char (bool from_signal)
|
||||||
if (FRAMEP (internal_last_event_frame)
|
if (FRAMEP (internal_last_event_frame)
|
||||||
&& !EQ (internal_last_event_frame, selected_frame))
|
&& !EQ (internal_last_event_frame, selected_frame))
|
||||||
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
|
do_switch_frame (make_lispy_switch_frame (internal_last_event_frame),
|
||||||
0, Qnil);
|
0, 0, Qnil);
|
||||||
|
|
||||||
sys_longjmp (getcjmp, 1);
|
sys_longjmp (getcjmp, 1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4878,7 +4878,7 @@ extern void syms_of_indent (void);
|
||||||
/* Defined in frame.c. */
|
/* Defined in frame.c. */
|
||||||
extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
|
extern void store_frame_param (struct frame *, Lisp_Object, Lisp_Object);
|
||||||
extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
|
extern void store_in_alist (Lisp_Object *, Lisp_Object, Lisp_Object);
|
||||||
extern Lisp_Object do_switch_frame (Lisp_Object, int, Lisp_Object);
|
extern Lisp_Object do_switch_frame (Lisp_Object, int, int, Lisp_Object);
|
||||||
extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
|
extern Lisp_Object get_frame_param (struct frame *, Lisp_Object);
|
||||||
extern void frames_discard_buffer (Lisp_Object);
|
extern void frames_discard_buffer (Lisp_Object);
|
||||||
extern void init_frame_once (void);
|
extern void init_frame_once (void);
|
||||||
|
|
|
@ -1125,8 +1125,8 @@ read_minibuf_unwind (void)
|
||||||
found:
|
found:
|
||||||
if (!EQ (exp_MB_frame, saved_selected_frame)
|
if (!EQ (exp_MB_frame, saved_selected_frame)
|
||||||
&& !NILP (exp_MB_frame))
|
&& !NILP (exp_MB_frame))
|
||||||
do_switch_frame (exp_MB_frame, 0, Qt); /* This also sets
|
do_switch_frame (exp_MB_frame, 0, 0, Qt); /* This also sets
|
||||||
minibuf_window */
|
minibuf_window */
|
||||||
|
|
||||||
/* To keep things predictable, in case it matters, let's be in the
|
/* To keep things predictable, in case it matters, let's be in the
|
||||||
minibuffer when we reset the relevant variables. Don't depend on
|
minibuffer when we reset the relevant variables. Don't depend on
|
||||||
|
@ -1238,7 +1238,7 @@ read_minibuf_unwind (void)
|
||||||
/* Restore the selected frame. */
|
/* Restore the selected frame. */
|
||||||
if (!EQ (exp_MB_frame, saved_selected_frame)
|
if (!EQ (exp_MB_frame, saved_selected_frame)
|
||||||
&& !NILP (exp_MB_frame))
|
&& !NILP (exp_MB_frame))
|
||||||
do_switch_frame (saved_selected_frame, 0, Qt);
|
do_switch_frame (saved_selected_frame, 0, 0, Qt);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Replace the expired minibuffer in frame exp_MB_frame with the next less
|
/* Replace the expired minibuffer in frame exp_MB_frame with the next less
|
||||||
|
|
|
@ -7399,7 +7399,7 @@ the return value is nil. Otherwise the value is t. */)
|
||||||
do_switch_frame (NILP (dont_set_frame)
|
do_switch_frame (NILP (dont_set_frame)
|
||||||
? data->selected_frame
|
? data->selected_frame
|
||||||
: old_frame
|
: old_frame
|
||||||
, 0, Qnil);
|
, 0, 0, Qnil);
|
||||||
}
|
}
|
||||||
|
|
||||||
FRAME_WINDOW_CHANGE (f) = true;
|
FRAME_WINDOW_CHANGE (f) = true;
|
||||||
|
|
|
@ -25792,7 +25792,7 @@ x_try_restore_frame (void)
|
||||||
|
|
||||||
FOR_EACH_FRAME (tail, frame)
|
FOR_EACH_FRAME (tail, frame)
|
||||||
{
|
{
|
||||||
if (!NILP (do_switch_frame (frame, 1, Qnil)))
|
if (!NILP (do_switch_frame (frame, 0, 1, Qnil)))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue