From 5819f4fb0a9337fab4c32dac557a02ec6497bce5 Mon Sep 17 00:00:00 2001 From: Martin Rudalics Date: Sun, 18 Apr 2021 09:51:32 +0200 Subject: [PATCH] Avoid selecting tooltip windows and frames (Bug#47207) * src/frame.c (do_switch_frame): Don't switch to a tooltip frame. (Fselect_frame): Do not select a tooltip frame. * src/w32fns.c (Fx_show_tip): * src/xfns.c (Fx_show_tip): Set the tooltip window's `no-other-window' parameter so `other-window' will skip it. * src/window.c (select_window): Do not select a tooltip window. (candidate_window_p): Make sure MINIBUF is live. (decode_next_window_args): Make sure that W's frame's minibuffer window is live before including it. (Qno_other_window): New symbol. --- src/frame.c | 15 +++++++++++++-- src/w32fns.c | 2 ++ src/window.c | 36 +++++++++++++++++++++++------------- src/xfns.c | 2 ++ 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/frame.c b/src/frame.c index 028a45afeb7..097cd555c64 100644 --- a/src/frame.c +++ b/src/frame.c @@ -1384,7 +1384,8 @@ do_switch_frame (Lisp_Object frame, int track, int for_deletion, Lisp_Object nor especially when deleting the initial frame during startup. */ CHECK_FRAME (frame); f = XFRAME (frame); - if (!FRAME_LIVE_P (f)) + /* Silently ignore dead and tooltip frames (Bug#47207). */ + if (!FRAME_LIVE_P (f) || FRAME_TOOLTIP_P (f)) return Qnil; else if (f == sf) return frame; @@ -1508,7 +1509,16 @@ redisplay will display FRAME. This function returns FRAME, or nil if FRAME has been deleted. */) (Lisp_Object frame, Lisp_Object norecord) { - return do_switch_frame (frame, 1, 0, norecord); + struct frame *f; + + CHECK_LIVE_FRAME (frame); + f = XFRAME (frame); + + if (FRAME_TOOLTIP_P (f)) + /* Do not select a tooltip frame (Bug#47207). */ + error ("Cannot select a tooltip frame"); + else + return do_switch_frame (frame, 1, 0, norecord); } DEFUN ("handle-switch-frame", Fhandle_switch_frame, @@ -1523,6 +1533,7 @@ necessarily represent user-visible input focus. */) /* Preserve prefix arg that the command loop just cleared. */ kset_prefix_arg (current_kboard, Vcurrent_prefix_arg); run_hook (Qmouse_leave_buffer_hook); + return do_switch_frame (event, 0, 0, Qnil); } diff --git a/src/w32fns.c b/src/w32fns.c index 9db367bfafe..c07f32ab0cc 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -7434,6 +7434,8 @@ DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, set_window_buffer (window, tip_buf, false, false); w = XWINDOW (window); w->pseudo_window_p = true; + /* Try to avoid that `other-window' select us (Bug#47207). */ + Fset_window_parameter (window, Qno_other_window, Qt); /* Set up the frame's root window. Note: The following code does not try to size the window or its frame correctly. Its only purpose is diff --git a/src/window.c b/src/window.c index 7c238a33fcb..9a49032ba8a 100644 --- a/src/window.c +++ b/src/window.c @@ -504,10 +504,18 @@ select_window (Lisp_Object window, Lisp_Object norecord, { struct window *w; struct frame *sf; + Lisp_Object frame; + struct frame *f; CHECK_LIVE_WINDOW (window); w = XWINDOW (window); + frame = WINDOW_FRAME (w); + f = XFRAME (frame); + + if (FRAME_TOOLTIP_P (f)) + /* Do not select a tooltip window (Bug#47207). */ + error ("Cannot select a tooltip window"); /* Make the selected window's buffer current. */ Fset_buffer (w->contents); @@ -528,14 +536,14 @@ select_window (Lisp_Object window, Lisp_Object norecord, redisplay_other_windows (); sf = SELECTED_FRAME (); - if (XFRAME (WINDOW_FRAME (w)) != sf) + if (f != sf) { - fset_selected_window (XFRAME (WINDOW_FRAME (w)), window); + fset_selected_window (f, window); /* Use this rather than Fhandle_switch_frame so that FRAME_FOCUS_FRAME is moved appropriately as we move around in the state where a minibuffer in a separate frame is active. */ - Fselect_frame (WINDOW_FRAME (w), norecord); + Fselect_frame (frame, norecord); /* Fselect_frame called us back so we've done all the work already. */ eassert (EQ (window, selected_window)); return window; @@ -2596,7 +2604,7 @@ candidate_window_p (Lisp_Object window, Lisp_Object owindow, candidate_p = false; else if (MINI_WINDOW_P (w) && (EQ (minibuf, Qlambda) - || (WINDOWP (minibuf) && !EQ (minibuf, window)))) + || (WINDOW_LIVE_P (minibuf) && !EQ (minibuf, window)))) { /* If MINIBUF is `lambda' don't consider any mini-windows. If it is a window, consider only that one. */ @@ -2659,12 +2667,12 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object Lisp_Object miniwin = XFRAME (w->frame)->minibuffer_window; XSETWINDOW (*window, w); - /* MINIBUF nil may or may not include minibuffers. Decide if it - does. */ - if (NILP (*minibuf)) - *minibuf = this_minibuffer_depth (XWINDOW (miniwin)->contents) - ? miniwin - : Qlambda; + /* MINIBUF nil may or may not include minibuffer windows. Decide if + it does. But first make sure that this frame's minibuffer window + is live (Bug#47207). */ + if (WINDOW_LIVE_P (miniwin) && NILP (*minibuf)) + *minibuf = (this_minibuffer_depth (XWINDOW (miniwin)->contents) + ? miniwin : Qlambda); else if (!EQ (*minibuf, Qt)) *minibuf = Qlambda; @@ -2675,9 +2683,10 @@ decode_next_window_args (Lisp_Object *window, Lisp_Object *minibuf, Lisp_Object /* ALL_FRAMES nil doesn't specify which frames to include. */ if (NILP (*all_frames)) *all_frames - = (!EQ (*minibuf, Qlambda) - ? FRAME_MINIBUF_WINDOW (XFRAME (w->frame)) - : Qnil); + /* Once more make sure that this frame's minibuffer window is live + before including it (Bug#47207). */ + = ((WINDOW_LIVE_P (miniwin) && !EQ (*minibuf, Qlambda)) + ? miniwin : Qnil); else if (EQ (*all_frames, Qvisible)) ; else if (EQ (*all_frames, make_fixnum (0))) @@ -8232,6 +8241,7 @@ syms_of_window (void) DEFSYM (Qmode_line_format, "mode-line-format"); DEFSYM (Qheader_line_format, "header-line-format"); DEFSYM (Qtab_line_format, "tab-line-format"); + DEFSYM (Qno_other_window, "no-other-window"); DEFVAR_LISP ("temp-buffer-show-function", Vtemp_buffer_show_function, doc: /* Non-nil means call as function to display a help buffer. diff --git a/src/xfns.c b/src/xfns.c index 0507dc8f61d..f120653ee7b 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -7076,6 +7076,8 @@ Text larger than the specified size is clipped. */) set_window_buffer (window, tip_buf, false, false); w = XWINDOW (window); w->pseudo_window_p = true; + /* Try to avoid that `other-window' select us (Bug#47207). */ + Fset_window_parameter (window, Qno_other_window, Qt); /* Set up the frame's root window. Note: The following code does not try to size the window or its frame correctly. Its only purpose is -- 2.39.2