From dac2f146eae20f958186b70725f86e7b9d541ded Mon Sep 17 00:00:00 2001 From: Derek Foreman Date: Wed, 27 Jul 2022 17:02:57 -0500 Subject: [PATCH] xwm: Perform a roundtrip to send a deferred WM_TAKE_FOCUS WM_TAKE_FOCUS requires a valid timestamp that isn't XCB_TIME_CURRENT. To get one, we set a property on the window and wait for the notification that it was set - this notification comes with a valid timestamp. Once we have that timestamp, delete the property, and fire off the slightly delayed WM_TAKE_FOCUS client request. Signed-off-by: Derek Foreman --- shared/xcb-xwayland.c | 1 + shared/xcb-xwayland.h | 1 + xwayland/window-manager.c | 50 +++++++++++++++++++++++++++++---------- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/shared/xcb-xwayland.c b/shared/xcb-xwayland.c index bb207b90..bd64e4c9 100644 --- a/shared/xcb-xwayland.c +++ b/shared/xcb-xwayland.c @@ -139,6 +139,7 @@ x11_get_atoms(xcb_connection_t *connection, struct atom_x11 *atom) { "XdndActionCopy", F(xdnd_action_copy) }, { "_XWAYLAND_ALLOW_COMMITS", F(allow_commits) }, { "WL_SURFACE_ID", F(wl_surface_id) }, + { "_WESTON_FOCUS_PING", F(weston_focus_ping) }, }; xcb_intern_atom_cookie_t cookies[ARRAY_LENGTH(atoms)]; diff --git a/shared/xcb-xwayland.h b/shared/xcb-xwayland.h index 8157240c..38eea82a 100644 --- a/shared/xcb-xwayland.h +++ b/shared/xcb-xwayland.h @@ -97,6 +97,7 @@ struct atom_x11 { xcb_atom_t xdnd_action_copy; xcb_atom_t wl_surface_id; xcb_atom_t allow_commits; + xcb_atom_t weston_focus_ping; }; const char * diff --git a/xwayland/window-manager.c b/xwayland/window-manager.c index 50380562..f0655a7f 100644 --- a/xwayland/window-manager.c +++ b/xwayland/window-manager.c @@ -931,8 +931,6 @@ static void weston_wm_send_focus_window(struct weston_wm *wm, struct weston_wm_window *window) { - xcb_client_message_event_t client_message; - if (window) { uint32_t values[1]; @@ -940,16 +938,15 @@ weston_wm_send_focus_window(struct weston_wm *wm, return; if (window->take_focus) { - client_message.response_type = XCB_CLIENT_MESSAGE; - client_message.format = 32; - client_message.window = window->id; - client_message.type = wm->atom.wm_protocols; - client_message.data.data32[0] = wm->atom.wm_take_focus; - client_message.data.data32[1] = XCB_TIME_CURRENT_TIME; - - xcb_send_event(wm->conn, 0, window->id, - XCB_EVENT_MASK_NO_EVENT, - (char *) &client_message); + /* Set a property to get a roundtrip + * with a timestamp for WM_TAKE_FOCUS */ + xcb_change_property(wm->conn, + XCB_PROP_MODE_REPLACE, + window->id, + wm->atom.weston_focus_ping, + XCB_ATOM_STRING, + 8, /* format */ + 0, NULL); } xcb_set_input_focus (wm->conn, XCB_INPUT_FOCUS_POINTER_ROOT, @@ -1502,6 +1499,35 @@ weston_wm_handle_property_notify(struct weston_wm *wm, xcb_generic_event_t *even if (!wm_lookup_window(wm, property_notify->window, &window)) return; + /* We set the weston_focus_ping property on this window to + * get a timestamp to send a WM_TAKE_FOCUS... send it now, + * or just return if this is confirming we deleted the + * property. + */ + if (property_notify->atom == wm->atom.weston_focus_ping) { + xcb_client_message_event_t client_message; + + if (property_notify->state == XCB_PROPERTY_DELETE) + return; + + /* delete our ping property */ + xcb_delete_property(window->wm->conn, + window->id, + window->wm->atom.weston_focus_ping); + + client_message.response_type = XCB_CLIENT_MESSAGE; + client_message.format = 32; + client_message.window = window->id; + client_message.type = wm->atom.wm_protocols; + client_message.data.data32[0] = wm->atom.wm_take_focus; + client_message.data.data32[1] = property_notify->time; + xcb_send_event(wm->conn, 0, window->id, + XCB_EVENT_MASK_NO_EVENT, + (char *) &client_message); + + return; + } + window->properties_dirty = 1; if (wm_debug_is_enabled(wm))