From 7c080c3b60a48c9b8602f181a1bc436d5df223e8 Mon Sep 17 00:00:00 2001 From: Sarunas Valaskevicius Date: Sat, 13 Jan 2024 22:28:44 +0000 Subject: [PATCH] Fix disappearing menus in QT apps A motivating example of such problem - Zoom's popups that open on button presses. Before this fix the popup would flicker and immediately disappear - because the PID is not yet available for the verification (as the surface has not been associated yet), wlroots would refuse to focus the popup and instead focus the previous window. This leads QT to interpret this as a sign to close the popup. This change moves the PID aqcuisition to an earlier phase - just where the window is created. --- xwayland/xwm.c | 82 +++++++++++++++++++++++++------------------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/xwayland/xwm.c b/xwayland/xwm.c index d728f405..b6a794dc 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -133,6 +133,34 @@ static int xwayland_surface_handle_ping_timeout(void *data) { return 1; } +static void read_surface_client_id(struct wlr_xwm *xwm, + struct wlr_xwayland_surface *xsurface, + xcb_res_query_client_ids_cookie_t cookie) { + xcb_res_query_client_ids_reply_t *reply = xcb_res_query_client_ids_reply( + xwm->xcb_conn, cookie, NULL); + if (reply == NULL) { + return; + } + + uint32_t *pid = NULL; + xcb_res_client_id_value_iterator_t iter = + xcb_res_query_client_ids_ids_iterator(reply); + while (iter.rem > 0) { + if (iter.data->spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID && + xcb_res_client_id_value_value_length(iter.data) > 0) { + pid = xcb_res_client_id_value_value(iter.data); + break; + } + xcb_res_client_id_value_next(&iter); + } + if (pid == NULL) { + free(reply); + return; + } + xsurface->pid = *pid; + free(reply); +} + static struct wlr_xwayland_surface *xwayland_surface_create( struct wlr_xwm *xwm, xcb_window_t window_id, int16_t x, int16_t y, uint16_t width, uint16_t height, bool override_redirect) { @@ -145,6 +173,15 @@ static struct wlr_xwayland_surface *xwayland_surface_create( xcb_get_geometry_cookie_t geometry_cookie = xcb_get_geometry(xwm->xcb_conn, window_id); + xcb_res_query_client_ids_cookie_t client_id_cookie; + if (xwm->xres) { + xcb_res_client_id_spec_t spec = { + .client = window_id, + .mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID + }; + client_id_cookie = xcb_res_query_client_ids(xwm->xcb_conn, 1, &spec); + } + uint32_t values[1]; values[0] = XCB_EVENT_MASK_FOCUS_CHANGE | @@ -205,6 +242,10 @@ static struct wlr_xwayland_surface *xwayland_surface_create( wl_list_insert(&xwm->surfaces, &surface->link); + if (xwm->xres) { + read_surface_client_id(xwm, surface, client_id_cookie); + } + wl_signal_emit_mutable(&xwm->xwayland->events.new_surface, surface); return surface; @@ -598,34 +639,6 @@ static void read_surface_parent(struct wlr_xwm *xwm, wl_signal_emit_mutable(&xsurface->events.set_parent, NULL); } -static void read_surface_client_id(struct wlr_xwm *xwm, - struct wlr_xwayland_surface *xsurface, - xcb_res_query_client_ids_cookie_t cookie) { - xcb_res_query_client_ids_reply_t *reply = xcb_res_query_client_ids_reply( - xwm->xcb_conn, cookie, NULL); - if (reply == NULL) { - return; - } - - uint32_t *pid = NULL; - xcb_res_client_id_value_iterator_t iter = - xcb_res_query_client_ids_ids_iterator(reply); - while (iter.rem > 0) { - if (iter.data->spec.mask & XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID && - xcb_res_client_id_value_value_length(iter.data) > 0) { - pid = xcb_res_client_id_value_value(iter.data); - break; - } - xcb_res_client_id_value_next(&iter); - } - if (pid == NULL) { - free(reply); - return; - } - xsurface->pid = *pid; - free(reply); -} - static void read_surface_window_type(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { @@ -924,15 +937,6 @@ static void xwayland_surface_associate(struct wlr_xwm *xwm, props[i], XCB_ATOM_ANY, 0, 2048); } - xcb_res_query_client_ids_cookie_t client_id_cookie; - if (xwm->xres) { - xcb_res_client_id_spec_t spec = { - .client = xsurface->window_id, - .mask = XCB_RES_CLIENT_ID_MASK_LOCAL_CLIENT_PID - }; - client_id_cookie = xcb_res_query_client_ids(xwm->xcb_conn, 1, &spec); - } - for (size_t i = 0; i < sizeof(props) / sizeof(props[0]); i++) { xcb_get_property_reply_t *reply = xcb_get_property_reply(xwm->xcb_conn, cookies[i], NULL); @@ -944,10 +948,6 @@ static void xwayland_surface_associate(struct wlr_xwm *xwm, free(reply); } - if (xwm->xres) { - read_surface_client_id(xwm, xsurface, client_id_cookie); - } - wl_signal_emit_mutable(&xsurface->events.associate, NULL); }