From df205592c231eed03003fae66cb27f3c491abe23 Mon Sep 17 00:00:00 2001 From: Johan Malm Date: Thu, 23 Oct 2025 19:06:33 +0100 Subject: [PATCH] Give keyboard focus to xdg-popups of unfocused layer-shell clients ...in support of enabling panel menus to be opened by keyboard shortcuts and get keyboard focus so that they can be operated with the keyboard. An example use-case is the xfce4-panel applications-menu being opened by the command xfce4-popup-applicationmenu. --- include/labwc.h | 1 + src/layers.c | 9 +++++++++ src/seat.c | 11 +++++++++++ 3 files changed, 21 insertions(+) diff --git a/include/labwc.h b/include/labwc.h index 735f57b8..21cbe186 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -380,6 +380,7 @@ void desktop_focus_topmost_view(struct server *server); void seat_init(struct server *server); void seat_finish(struct server *server); void seat_reconfigure(struct server *server); +void seat_force_focus_surface(struct seat *seat, struct wlr_surface *surface); void seat_focus_surface(struct seat *seat, struct wlr_surface *surface); void seat_pointer_end_grab(struct seat *seat, struct wlr_surface *surface); diff --git a/src/layers.c b/src/layers.c index f26208ef..8ee11d64 100644 --- a/src/layers.c +++ b/src/layers.c @@ -546,6 +546,15 @@ handle_new_popup(struct wl_listener *listener, void *data) struct wlr_scene_layer_surface_v1 *surface = toplevel->scene_layer_surface; struct output *output = surface->layer_surface->output->data; + /* + * When a popup is opened by a client without keyboard focus we need to + * force focus it so that it can be operated by the keyboard. An example + * of a use-case is the xfce4-panel start menu which can be opened by a + * keyboard shortcut (linked to xfce4-popup-applicationmenu). + */ + seat_force_focus_surface(&server->seat, + toplevel->layer_surface->surface); + int lx, ly; wlr_scene_node_coords(&surface->tree->node, &lx, &ly); diff --git a/src/seat.c b/src/seat.c index 05f5a006..58b96a36 100644 --- a/src/seat.c +++ b/src/seat.c @@ -756,6 +756,17 @@ seat_reconfigure(struct server *server) } } +void +seat_force_focus_surface(struct seat *seat, struct wlr_surface *surface) +{ + uint32_t *pressed_sent_keycodes = key_state_pressed_sent_keycodes(); + int nr_pressed_sent_keycodes = key_state_nr_pressed_sent_keycodes(); + struct wlr_keyboard *kb = &seat->keyboard_group->keyboard; + + wlr_seat_keyboard_enter(seat->seat, surface, + pressed_sent_keycodes, nr_pressed_sent_keycodes, &kb->modifiers); +} + static void seat_focus(struct seat *seat, struct wlr_surface *surface, bool replace_exclusive_layer, bool is_lock_surface)