mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-10-31 22:25:21 -04:00
Allow keyboard and pointer grabs to hook clear_focus()
This is necessary for some grabs, which currently have no way of knowing when the pointer/keyboard focus has left a surface. For example, without this, a drag-and-drop grab can erroneously drop into a window that the cursor is no longer over. This is the plumbing needed to properly fix swaywm/sway#5220. The existing fix, swaywm/sway#5222, relies on every grab's `enter()` hook allowing a `NULL` surface. This is not guaranteed by the API and, in fact, is not the case for the xdg-shell popup grab and results in a crash when the cursor leaves a surface and does not immediately enter another one while a popup is open (#2161). This fix also adds an assertion to wlr_seat_pointer_notify_enter() that ensures it's never called with a `NULL` surface. This will make Sway crash much more until it fixes its usage of the API, so we should land this at the same time as a fix in Sway (which I haven't posted yet).
This commit is contained in:
parent
8bf9f5bb8b
commit
dcae6f1431
6 changed files with 75 additions and 1 deletions
|
|
@ -21,6 +21,10 @@ static void default_keyboard_enter(struct wlr_seat_keyboard_grab *grab,
|
|||
wlr_seat_keyboard_enter(grab->seat, surface, keycodes, num_keycodes, modifiers);
|
||||
}
|
||||
|
||||
static void default_keyboard_clear_focus(struct wlr_seat_keyboard_grab *grab) {
|
||||
wlr_seat_keyboard_clear_focus(grab->seat);
|
||||
}
|
||||
|
||||
static void default_keyboard_key(struct wlr_seat_keyboard_grab *grab,
|
||||
uint32_t time, uint32_t key, uint32_t state) {
|
||||
wlr_seat_keyboard_send_key(grab->seat, time, key, state);
|
||||
|
|
@ -37,6 +41,7 @@ static void default_keyboard_cancel(struct wlr_seat_keyboard_grab *grab) {
|
|||
|
||||
const struct wlr_keyboard_grab_interface default_keyboard_grab_impl = {
|
||||
.enter = default_keyboard_enter,
|
||||
.clear_focus = default_keyboard_clear_focus,
|
||||
.key = default_keyboard_key,
|
||||
.modifiers = default_keyboard_modifiers,
|
||||
.cancel = default_keyboard_cancel,
|
||||
|
|
@ -311,15 +316,22 @@ void wlr_seat_keyboard_enter(struct wlr_seat *seat,
|
|||
void wlr_seat_keyboard_notify_enter(struct wlr_seat *seat,
|
||||
struct wlr_surface *surface, uint32_t keycodes[], size_t num_keycodes,
|
||||
struct wlr_keyboard_modifiers *modifiers) {
|
||||
// NULL surfaces are prohibited in the grab-compatible API. Use
|
||||
// wlr_seat_keyboard_notify_clear_focus() instead.
|
||||
assert(surface);
|
||||
struct wlr_seat_keyboard_grab *grab = seat->keyboard_state.grab;
|
||||
grab->interface->enter(grab, surface, keycodes, num_keycodes, modifiers);
|
||||
}
|
||||
|
||||
void wlr_seat_keyboard_clear_focus(struct wlr_seat *seat) {
|
||||
// TODO respect grabs here?
|
||||
wlr_seat_keyboard_enter(seat, NULL, NULL, 0, NULL);
|
||||
}
|
||||
|
||||
void wlr_seat_keyboard_notify_clear_focus(struct wlr_seat *seat) {
|
||||
struct wlr_seat_keyboard_grab *grab = seat->keyboard_state.grab;
|
||||
grab->interface->clear_focus(grab);
|
||||
}
|
||||
|
||||
bool wlr_seat_keyboard_has_grab(struct wlr_seat *seat) {
|
||||
return seat->keyboard_state.grab->interface != &default_keyboard_grab_impl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,10 @@ static void default_pointer_enter(struct wlr_seat_pointer_grab *grab,
|
|||
wlr_seat_pointer_enter(grab->seat, surface, sx, sy);
|
||||
}
|
||||
|
||||
static void default_pointer_clear_focus(struct wlr_seat_pointer_grab *grab) {
|
||||
wlr_seat_pointer_clear_focus(grab->seat);
|
||||
}
|
||||
|
||||
static void default_pointer_motion(struct wlr_seat_pointer_grab *grab,
|
||||
uint32_t time, double sx, double sy) {
|
||||
wlr_seat_pointer_send_motion(grab->seat, time, sx, sy);
|
||||
|
|
@ -42,6 +46,7 @@ static void default_pointer_cancel(struct wlr_seat_pointer_grab *grab) {
|
|||
|
||||
const struct wlr_pointer_grab_interface default_pointer_grab_impl = {
|
||||
.enter = default_pointer_enter,
|
||||
.clear_focus = default_pointer_clear_focus,
|
||||
.motion = default_pointer_motion,
|
||||
.button = default_pointer_button,
|
||||
.axis = default_pointer_axis,
|
||||
|
|
@ -331,10 +336,18 @@ void wlr_seat_pointer_end_grab(struct wlr_seat *wlr_seat) {
|
|||
|
||||
void wlr_seat_pointer_notify_enter(struct wlr_seat *wlr_seat,
|
||||
struct wlr_surface *surface, double sx, double sy) {
|
||||
// NULL surfaces are prohibited in the grab-compatible API. Use
|
||||
// wlr_seat_pointer_notify_clear_focus() instead.
|
||||
assert(surface);
|
||||
struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
|
||||
grab->interface->enter(grab, surface, sx, sy);
|
||||
}
|
||||
|
||||
void wlr_seat_pointer_notify_clear_focus(struct wlr_seat *wlr_seat) {
|
||||
struct wlr_seat_pointer_grab *grab = wlr_seat->pointer_state.grab;
|
||||
grab->interface->clear_focus(grab);
|
||||
}
|
||||
|
||||
void wlr_seat_pointer_notify_motion(struct wlr_seat *wlr_seat, uint32_t time,
|
||||
double sx, double sy) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &wlr_seat->last_event);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue