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: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3651>
This commit is contained in:
Sebastian Keller 2024-03-08 10:46:21 +01:00 committed by Marge Bot
parent 7ddb3abfbb
commit a66b4c3da9
3 changed files with 26 additions and 18 deletions

View File

@ -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)

View File

@ -152,6 +152,8 @@ struct _MetaX11Display
*/
guint focused_by_us : 1;
guint is_server_focus : 1;
guint keys_grabbed : 1;
guint closing : 1;

View File

@ -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 ())