From a66b4c3da9ac05b5ff245fe35e05de0e42bd5c05 Mon Sep 17 00:00:00 2001 From: Sebastian Keller Date: Fri, 8 Mar 2024 10:46:21 +0100 Subject: [PATCH] x11/display: Always use meta_display_set_input_focus() for focus change X11 server side focus changes, such as when a focus change was requested by mutter for a globally active window, did not go through meta_display_set_input_focus(), which is responsible for emitting the `focus-window` signal. Since this signal is what triggers the display server specific code to handle focus changes, this was leading to a problem on Wayland where the focus remained on the last active Wayland window when the focus got changed to a globally active XWayland window. This commit now changes handling X11 server side focus changes to also go through the code path that emits the signal while making sure to not trigger another focus change and keeping the same serials as the previous code to not interfere with future focus changes. Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/3328 Part-of: --- src/x11/events.c | 23 ++++++++++------------- src/x11/meta-x11-display-private.h | 2 ++ src/x11/meta-x11-display.c | 19 ++++++++++++++----- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/x11/events.c b/src/x11/events.c index 03179e4af..f4a279d9b 100644 --- a/src/x11/events.c +++ b/src/x11/events.c @@ -907,12 +907,11 @@ handle_window_focus_event (MetaX11Display *x11_display, (!x11_display->focused_by_us && x11_display->server_focus_serial == x11_display->focus_serial)) { - meta_x11_display_update_focus_window (x11_display, - focus_window ? - meta_window_x11_get_xwindow (focus_window) : None, - x11_display->server_focus_serial, - FALSE); - meta_display_update_focus_window (display, focus_window); + x11_display->is_server_focus = TRUE; + meta_display_set_input_focus (display, focus_window, + meta_display_get_current_time_roundtrip (display)); + x11_display->is_server_focus = FALSE; + return TRUE; } else @@ -1895,13 +1894,11 @@ meta_x11_display_handle_xevent (MetaX11Display *x11_display, { meta_topic (META_DEBUG_FOCUS, "Earlier attempt to focus %s failed", display->focus_window->desc); - meta_x11_display_update_focus_window (x11_display, - x11_display->server_focus_window, - x11_display->server_focus_serial, - FALSE); - meta_display_update_focus_window (display, - meta_x11_display_lookup_x_window (x11_display, - x11_display->server_focus_window)); + + x11_display->is_server_focus = TRUE; + meta_display_set_input_focus (display, display->focus_window, + meta_display_get_current_time_roundtrip (display)); + x11_display->is_server_focus = FALSE; } if (event->xany.window == x11_display->xroot) diff --git a/src/x11/meta-x11-display-private.h b/src/x11/meta-x11-display-private.h index 1c3dc7d2b..1f47849b7 100644 --- a/src/x11/meta-x11-display-private.h +++ b/src/x11/meta-x11-display-private.h @@ -152,6 +152,8 @@ struct _MetaX11Display */ guint focused_by_us : 1; + guint is_server_focus : 1; + guint keys_grabbed : 1; guint closing : 1; diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c index 40339cef8..438f3bd1e 100644 --- a/src/x11/meta-x11-display.c +++ b/src/x11/meta-x11-display.c @@ -2118,11 +2118,20 @@ meta_x11_display_set_input_focus (MetaX11Display *x11_display, meta_topic (META_DEBUG_FOCUS, "Setting X11 input focus for window %s to 0x%lx", window ? window->desc : "none", xwindow); - mtk_x11_error_trap_push (x11_display->xdisplay); - meta_x11_display_set_input_focus_internal (x11_display, xwindow, timestamp); - serial = XNextRequest (x11_display->xdisplay); - meta_x11_display_update_focus_window (x11_display, xwindow, serial, TRUE); - mtk_x11_error_trap_pop (x11_display->xdisplay); + if (x11_display->is_server_focus) + { + serial = x11_display->server_focus_serial; + } + else + { + meta_x11_display_set_input_focus_internal (x11_display, xwindow, timestamp); + mtk_x11_error_trap_push (x11_display->xdisplay); + serial = XNextRequest (x11_display->xdisplay); + mtk_x11_error_trap_pop (x11_display->xdisplay); + } + + meta_x11_display_update_focus_window (x11_display, xwindow, serial, + !x11_display->is_server_focus); #ifdef HAVE_X11 if (window && !meta_is_wayland_compositor ())