mirror of
https://github.com/labwc/labwc.git
synced 2026-03-21 05:33:52 -04:00
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.
This commit is contained in:
parent
89325fbff8
commit
180293e0bb
4 changed files with 70 additions and 0 deletions
|
|
@ -372,6 +372,7 @@ void desktop_focus_topmost_view(struct server *server);
|
||||||
void seat_init(struct server *server);
|
void seat_init(struct server *server);
|
||||||
void seat_finish(struct server *server);
|
void seat_finish(struct server *server);
|
||||||
void seat_reconfigure(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_focus_surface(struct seat *seat, struct wlr_surface *surface);
|
||||||
|
|
||||||
void seat_pointer_end_grab(struct seat *seat, struct wlr_surface *surface);
|
void seat_pointer_end_grab(struct seat *seat, struct wlr_surface *surface);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,7 @@ struct lab_layer_popup {
|
||||||
struct wlr_xdg_popup *wlr_popup;
|
struct wlr_xdg_popup *wlr_popup;
|
||||||
struct wlr_scene_tree *scene_tree;
|
struct wlr_scene_tree *scene_tree;
|
||||||
struct server *server;
|
struct server *server;
|
||||||
|
struct lab_layer_surface *lab_layer_surface;
|
||||||
|
|
||||||
/* To simplify moving popup nodes from the bottom to the top layer */
|
/* To simplify moving popup nodes from the bottom to the top layer */
|
||||||
struct wlr_box output_toplevel_sx_box;
|
struct wlr_box output_toplevel_sx_box;
|
||||||
|
|
|
||||||
57
src/layers.c
57
src/layers.c
|
|
@ -23,6 +23,7 @@
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "node.h"
|
#include "node.h"
|
||||||
#include "output.h"
|
#include "output.h"
|
||||||
|
#include "session-lock.h"
|
||||||
|
|
||||||
#define LAB_LAYERSHELL_VERSION 4
|
#define LAB_LAYERSHELL_VERSION 4
|
||||||
|
|
||||||
|
|
@ -452,6 +453,51 @@ handle_popup_destroy(struct wl_listener *listener, void *data)
|
||||||
free(popup);
|
free(popup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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-applicationsmenu`, and the same for lxqt-panel with
|
||||||
|
* `lxqt-qdbus openmenu`.
|
||||||
|
*
|
||||||
|
* We check wlr_popup->seat here to make sure that the popup requested a grab,
|
||||||
|
* so that we do not give keyboard-focus to tooltips and the like. The
|
||||||
|
* wlr_popup->seat check works because it is set by wlroots only when a
|
||||||
|
* popup-grab has been handled. See xdg_popup_handle_grab() in
|
||||||
|
* types/xdg_shell/wlr_xdg_popup.c
|
||||||
|
*
|
||||||
|
* From a technical perspective it would seem nicer to explicitly set the focus
|
||||||
|
* on catching a xdg_popup.grab event but this is not possible for two reasons:
|
||||||
|
*
|
||||||
|
* 1. The xdg_popup.grab event is not emitted from wlroots in such a way
|
||||||
|
* that it can be differentiated from dnd grabs (see #3375).
|
||||||
|
* 2. There is a sequencing issue with some clients (notably layer-shell-qt
|
||||||
|
* ones) that means this cannot be managed from the labwc side.
|
||||||
|
* Specifically, the grab event takes place before the get_popup one
|
||||||
|
* which means that the lab_layer_popup object has not yet been created
|
||||||
|
* when the grab is requested.
|
||||||
|
*
|
||||||
|
* WAYLAND_DEBUG=1 lxqt-panel 2>&1 | grep 'grab\|get_popup'
|
||||||
|
* ...xdg_surface#50.get_popup(new id xdg_popup#52, nil, xdg_positioner#51)
|
||||||
|
* ...xdg_popup#52.grab(wl_seat#11, 205)
|
||||||
|
* ...zwlr_layer_surface_v1#38.get_popup(xdg_popup#52)
|
||||||
|
*
|
||||||
|
* WAYLAND_DEBUG=1 xfce4-panel 2>&1 | grep 'grab\|get_popup'
|
||||||
|
* ...xdg_surface#50.get_popup(new id xdg_popup#51, nil, xdg_positioner#49)
|
||||||
|
* ...zwlr_layer_surface_v1#41.get_popup(xdg_popup#51)
|
||||||
|
* ...xdg_popup#51.grab(wl_seat#23, 540)
|
||||||
|
*
|
||||||
|
* So for the time being we make {xfce4,lxqt}-panel work by just checking
|
||||||
|
* wlr_popup->seat and then setting the focus in handle_popup_commit()
|
||||||
|
*
|
||||||
|
* Ref:
|
||||||
|
* - https://github.com/labwc/labwc/pull/3165
|
||||||
|
* - https://github.com/labwc/labwc/pull/3375
|
||||||
|
* - https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/5265
|
||||||
|
* - https://github.com/labwc/labwc/issues/2467#issuecomment-2585927886
|
||||||
|
* - https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3689
|
||||||
|
* - https://gitlab.freedesktop.org/wlroots/wlroots/-/merge_requests/4950
|
||||||
|
*/
|
||||||
static void
|
static void
|
||||||
handle_popup_commit(struct wl_listener *listener, void *data)
|
handle_popup_commit(struct wl_listener *listener, void *data)
|
||||||
{
|
{
|
||||||
|
|
@ -465,6 +511,14 @@ handle_popup_commit(struct wl_listener *listener, void *data)
|
||||||
/* Prevent getting called over and over again */
|
/* Prevent getting called over and over again */
|
||||||
wl_list_remove(&popup->commit.link);
|
wl_list_remove(&popup->commit.link);
|
||||||
popup->commit.notify = NULL;
|
popup->commit.notify = NULL;
|
||||||
|
|
||||||
|
if (!seat->server->session_lock_manager->locked
|
||||||
|
&& popup->wlr_popup->seat) {
|
||||||
|
struct wlr_layer_surface_v1 *layer_surface =
|
||||||
|
popup->lab_layer_surface->layer_surface;
|
||||||
|
seat_force_focus_surface(&popup->server->seat,
|
||||||
|
layer_surface->surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -533,6 +587,8 @@ handle_popup_new_popup(struct wl_listener *listener, void *data)
|
||||||
|
|
||||||
new_popup->output_toplevel_sx_box =
|
new_popup->output_toplevel_sx_box =
|
||||||
lab_layer_popup->output_toplevel_sx_box;
|
lab_layer_popup->output_toplevel_sx_box;
|
||||||
|
|
||||||
|
new_popup->lab_layer_surface = lab_layer_popup->lab_layer_surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -598,6 +654,7 @@ handle_new_popup(struct wl_listener *listener, void *data)
|
||||||
}
|
}
|
||||||
|
|
||||||
popup->output_toplevel_sx_box = output_toplevel_sx_box;
|
popup->output_toplevel_sx_box = output_toplevel_sx_box;
|
||||||
|
popup->lab_layer_surface = toplevel;
|
||||||
|
|
||||||
if (surface->layer_surface->current.layer
|
if (surface->layer_surface->current.layer
|
||||||
<= ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
|
<= ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM) {
|
||||||
|
|
|
||||||
11
src/seat.c
11
src/seat.c
|
|
@ -759,6 +759,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
|
static void
|
||||||
seat_focus(struct seat *seat, struct wlr_surface *surface,
|
seat_focus(struct seat *seat, struct wlr_surface *surface,
|
||||||
bool replace_exclusive_layer, bool is_lock_surface)
|
bool replace_exclusive_layer, bool is_lock_surface)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue