Skip to content

Commit

Permalink
wayland: Fix seat resource release logic
Browse files Browse the repository at this point in the history
The existing logic leads to leaks in several scenarios:

1. Neither `wl_pointer_destroy` nor `wl_touch_destroy` are ever called,
   so pointer and touch objects are never released.

2. The logic for `wl_keyboard_destroy` is not solid as seats can lose
   the `WL_SEAT_CAPABILITY_POINTER` capability without losing the
   `WL_SEAT_CAPABILITY_KEYBOARD`. Thus it's possible for the calls to
   `wl_seat_get_keyboard` and `wl_keyboard_destroy` to be unbalanced.

3. Those resources were not released in the renderer destructor.

This reworks the seat resource release logic in a systematic way to
ensure that seat resources are always released.
  • Loading branch information
joanbm authored and Cloudef committed Jul 7, 2024
1 parent 8a79713 commit 498be46
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 15 deletions.
34 changes: 20 additions & 14 deletions lib/renderers/wayland/registry.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,30 +477,27 @@ seat_handle_capabilities(void *data, struct wl_seat *seat, enum wl_seat_capabili
{
struct input *input = data;

if (!input->seat) {
input->seat = seat;
}

if (caps & WL_SEAT_CAPABILITY_KEYBOARD) {
if ((caps & WL_SEAT_CAPABILITY_KEYBOARD) && !input->keyboard) {
input->keyboard = wl_seat_get_keyboard(seat);
wl_keyboard_add_listener(input->keyboard, &keyboard_listener, data);
} else if (!(caps & WL_SEAT_CAPABILITY_KEYBOARD) && input->keyboard) {
wl_keyboard_destroy(input->keyboard);
input->keyboard = NULL;
}

if (caps & WL_SEAT_CAPABILITY_POINTER) {
if ((caps & WL_SEAT_CAPABILITY_POINTER) && !input->pointer) {
input->pointer = wl_seat_get_pointer(seat);
wl_pointer_add_listener(input->pointer, &pointer_listener, data);
} else if (!(caps & WL_SEAT_CAPABILITY_POINTER) && input->pointer) {
wl_pointer_destroy(input->pointer);
input->pointer = NULL;
}

if (caps & WL_SEAT_CAPABILITY_TOUCH) {
if ((caps & WL_SEAT_CAPABILITY_TOUCH) && !input->touch) {
input->touch = wl_seat_get_touch(seat);
wl_touch_add_listener(input->touch, &wl_touch_listener, data);
}

if (seat == input->seat && !(caps & WL_SEAT_CAPABILITY_KEYBOARD) && !(caps & WL_SEAT_CAPABILITY_POINTER)) {
wl_keyboard_destroy(input->keyboard);
input->seat = NULL;
input->keyboard = NULL;
input->pointer = NULL;
} else if (!(caps & WL_SEAT_CAPABILITY_TOUCH) && input->touch) {
wl_touch_destroy(input->touch);
input->touch = NULL;
}
}
Expand Down Expand Up @@ -631,6 +628,15 @@ bm_wl_registry_destroy(struct wayland *wayland)
{
assert(wayland);

if (wayland->input.keyboard)
wl_keyboard_destroy(wayland->input.keyboard);

if (wayland->input.pointer)
wl_pointer_destroy(wayland->input.pointer);

if (wayland->input.touch)
wl_touch_destroy(wayland->input.touch);

if (wayland->viewporter)
wp_viewporter_destroy(wayland->viewporter);

Expand Down
1 change: 0 additions & 1 deletion lib/renderers/wayland/wayland.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,6 @@ struct touch_event {
struct input {
int *repeat_fd;

struct wl_seat *seat;
struct wl_keyboard *keyboard;
struct wl_pointer *pointer;
struct wl_touch *touch;
Expand Down

0 comments on commit 498be46

Please sign in to comment.