From 714511736ba2357d238e7d7de321ccc8d948fa97 Mon Sep 17 00:00:00 2001 From: Consolatis <35009135+Consolatis@users.noreply.github.com> Date: Wed, 10 Jul 2024 20:22:52 +0200 Subject: [PATCH] src/xdg.c: verify source surface for xdg_activation request wlroots < 0.17 didn't allow to reliably check the source surface of an xdg activation request as it reset the surface to NULL when it was destroyed before the token was used. This happens regularly for notifications for example. Thus we treated the token as valid even without checking for the source surface. wlroots 0.17 added a new_token signal where we can attach information to the existing token which we can then use when evaluating activation requests. This patch implements that check. --- include/labwc.h | 1 + src/xdg.c | 49 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index a19f8243..c4faf55b 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -248,6 +248,7 @@ struct server { struct wlr_xdg_activation_v1 *xdg_activation; struct wl_listener xdg_activation_request; + struct wl_listener xdg_activation_new_token; struct wl_list views; struct wl_list unmanaged_surfaces; diff --git a/src/xdg.c b/src/xdg.c index 86ee06c3..a24de0a8 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -665,10 +665,39 @@ static const struct view_impl xdg_toplevel_view_impl = { .get_pid = xdg_view_get_pid, }; +struct token_data { + bool had_valid_surface; + bool had_valid_seat; + struct wl_listener destroy; +}; + +static void +xdg_activation_handle_token_destroy(struct wl_listener *listener, void *data) +{ + struct token_data *token_data = wl_container_of(listener, token_data, destroy); + wl_list_remove(&token_data->destroy.link); + free(token_data); +} + +static void +xdg_activation_handle_new_token(struct wl_listener *listener, void *data) +{ + struct wlr_xdg_activation_token_v1 *token = data; + struct token_data *token_data = znew(*token_data); + token_data->had_valid_surface = !!token->surface; + token_data->had_valid_seat = !!token->seat; + token->data = token_data; + + token_data->destroy.notify = xdg_activation_handle_token_destroy; + wl_signal_add(&token->events.destroy, &token_data->destroy); +} + static void xdg_activation_handle_request(struct wl_listener *listener, void *data) { const struct wlr_xdg_activation_v1_request_activate_event *event = data; + struct token_data *token_data = event->token->data; + assert(token_data); struct wlr_xdg_surface *xdg_surface = wlr_xdg_surface_try_from_wlr_surface(event->surface); @@ -681,17 +710,16 @@ xdg_activation_handle_request(struct wl_listener *listener, void *data) wlr_log(WLR_INFO, "Not activating surface - no view attached to surface"); return; } - if (!event->token->seat) { + + if (!token_data->had_valid_seat) { wlr_log(WLR_INFO, "Denying focus request, seat wasn't supplied"); return; } - /* - * We do not check for event->token->surface here because it may already - * be destroyed and thus being NULL. With wlroots 0.17 we can hook into - * the `new_token` signal, attach further information to the token and - * then react to that information here instead. For now we just check - * for the seat / serial being correct and then allow the request. - */ + + if (!token_data->had_valid_surface) { + wlr_log(WLR_INFO, "Denying focus request, source surface not set"); + return; + } if (window_rules_get_property(view, "ignoreFocusRequest") == LAB_PROP_TRUE) { wlr_log(WLR_INFO, "Ignoring focus request due to window rule configuration"); @@ -830,8 +858,13 @@ xdg_shell_init(struct server *server) wlr_log(WLR_ERROR, "unable to create xdg_activation interface"); exit(EXIT_FAILURE); } + server->xdg_activation_request.notify = xdg_activation_handle_request; wl_signal_add(&server->xdg_activation->events.request_activate, &server->xdg_activation_request); + + server->xdg_activation_new_token.notify = xdg_activation_handle_new_token; + wl_signal_add(&server->xdg_activation->events.new_token, + &server->xdg_activation_new_token); }