From eb3f8d1b648d0aa5e5fcaec66d9003817f00ce42 Mon Sep 17 00:00:00 2001 From: Po Lu Date: Mon, 24 Oct 2022 19:18:17 +0800 Subject: [PATCH] Fix focus stealing in the Emacs server for old window managers * src/xterm.c (x_focus_frame): Apply focus stealing preference to non-EWMH focus as well. Otherwise frames get raised but not focused. --- src/xterm.c | 44 ++++++++++++++++++++++++++++++-------------- 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/src/xterm.c b/src/xterm.c index 06c84e2b534..205c948c461 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -27348,6 +27348,7 @@ static void x_focus_frame (struct frame *f, bool noactivate) { struct x_display_info *dpyinfo; + Time time; dpyinfo = FRAME_DISPLAY_INFO (f); @@ -27373,16 +27374,25 @@ x_focus_frame (struct frame *f, bool noactivate) /* Ignore any BadMatch error this request might result in. */ x_ignore_errors_for_next_request (dpyinfo); if (NILP (Vx_no_window_manager)) - XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), - /* It is invalid to use CurrentTime according to - the ICCCM: - - Clients that use a SetInputFocus request must - set the time field to the timestamp of the - event that caused them to make the - attempt. [...] Note that clients must not use - CurrentTime in the time field. */ - RevertToParent, dpyinfo->last_user_time); + { + /* Use the last user time. It is invalid to use CurrentTime + according to the ICCCM: + + Clients that use a SetInputFocus request must set the + time field to the timestamp of the event that caused + them to make the attempt. [...] Note that clients must + not use CurrentTime in the time field. */ + time = dpyinfo->last_user_time; + + /* Unless the focus doesn't belong to Emacs anymore and + `x-allow-focus-stealing' is set to Qnewer_time. */ + if (EQ (Vx_allow_focus_stealing, Qnewer_time) + && !dpyinfo->x_focus_frame) + time = x_get_server_time (f); + + XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), + RevertToParent, time); + } else XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_OUTER_WINDOW (f), /* But when no window manager is in use, we @@ -31049,10 +31059,16 @@ connection setup. */); Some window managers prevent `x-focus-frame' from activating the given frame when Emacs is in the background, which is especially prone to -cause problems when the Emacs server wants to activate itself. This -variable specifies the strategy used to activate frames when that is -the case, and has several valid values (any other value means to not -bypass window manager focus stealing prevention): +cause problems when the Emacs server wants to activate itself. + +In addition, when an old-fashioned (pre-EWMH) window manager is being +run and `x-no-window-manager' is nil, the X server will not let Emacs +focus itself if another program was focused after the last time Emacs +obtained the input focus. + +This variable specifies the strategy used to activate frames when that +is the case, and has several valid values (any other value means to +not bypass window manager focus stealing prevention): - The symbol `imitate-pager', which means to pretend that Emacs is a pager. -- 2.39.2