diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 1df753b9..a5b297ba 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -444,7 +444,7 @@ static void backend_destroy(struct wlr_backend *backend) { struct wlr_wl_input_device *input_device, *tmp_input_device; wl_list_for_each_safe(input_device, tmp_input_device, &wl->devices, link) { - wlr_input_device_destroy(&input_device->wlr_input_device); + destroy_wl_input_device(input_device); } struct wlr_wl_buffer *buffer, *tmp_buffer; diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index 6382347f..ae669c4d 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -14,6 +14,8 @@ #include #include #include +#include +#include #include #include "pointer-gestures-unstable-v1-client-protocol.h" @@ -22,6 +24,10 @@ #include "util/signal.h" #include "util/time.h" +static const struct wlr_pointer_impl pointer_impl; +static const struct wlr_keyboard_impl keyboard_impl; +static const struct wlr_touch_impl touch_impl; + static struct wlr_wl_pointer *output_get_pointer( struct wlr_wl_output *output, const struct wl_pointer *wl_pointer) { @@ -431,26 +437,21 @@ static struct wlr_wl_seat *input_device_get_seat(struct wlr_input_device *wlr_de return dev->seat; } -static void input_device_destroy(struct wlr_input_device *wlr_dev) { - struct wlr_wl_input_device *dev = - get_wl_input_device_from_input_device(wlr_dev); - if (dev->wlr_input_device.type == WLR_INPUT_DEVICE_KEYBOARD) { - struct wlr_wl_seat *seat = input_device_get_seat(wlr_dev); - wl_keyboard_release(seat->keyboard); - seat->keyboard = NULL; - } - // We can't destroy pointer here because we might have multiple devices - // exposing it to compositor. - wl_list_remove(&dev->link); - free(dev); -} - -static const struct wlr_input_device_impl input_device_impl = { - .destroy = input_device_destroy, -}; - bool wlr_input_device_is_wl(struct wlr_input_device *dev) { - return dev->impl == &input_device_impl; + switch (dev->type) { + case WLR_INPUT_DEVICE_KEYBOARD: + return dev->keyboard->impl == &keyboard_impl; + case WLR_INPUT_DEVICE_POINTER: + return dev->pointer->impl == &pointer_impl; + case WLR_INPUT_DEVICE_TOUCH: + return dev->touch->impl == &touch_impl; + case WLR_INPUT_DEVICE_TABLET_TOOL: + return dev->tablet->impl == &tablet_impl; + case WLR_INPUT_DEVICE_TABLET_PAD: + return dev->tablet_pad->impl == &tablet_pad_impl; + default: + return false; + } } struct wlr_wl_input_device *create_wl_input_device( @@ -493,12 +494,24 @@ struct wlr_wl_input_device *create_wl_input_device( char name[name_size]; (void) snprintf(name, name_size, "wayland-%s-%s", type_name, seat->name); - wlr_input_device_init(wlr_dev, type, &input_device_impl, name); + wlr_input_device_init(wlr_dev, type, NULL, name); wl_list_insert(&seat->backend->devices, &dev->link); return dev; } -static const struct wlr_pointer_impl pointer_impl; +void destroy_wl_input_device(struct wlr_wl_input_device *dev) { + /** + * TODO remove the redundant wlr_input_device from wlr_wl_input_device + * wlr_wl_input_device::wlr_input_device is not owned by its input device + * type, which means we have 2 wlr_input_device to cleanup + */ + wlr_input_device_finish(&dev->wlr_input_device); + if (dev->wlr_input_device._device) { + wlr_input_device_destroy(&dev->wlr_input_device); + } + wl_list_remove(&dev->link); + free(dev); +} struct wlr_wl_pointer *pointer_get_wl(struct wlr_pointer *wlr_pointer) { assert(wlr_pointer->impl == &pointer_impl); @@ -532,10 +545,6 @@ static void pointer_destroy(struct wlr_pointer *wlr_pointer) { zwp_relative_pointer_v1_destroy(pointer->relative_pointer); } - wlr_input_device_finish(&pointer->input_device->wlr_input_device); - wl_list_remove(&pointer->input_device->link); - free(pointer->input_device); - wl_list_remove(&pointer->output_destroy.link); free(pointer); } @@ -709,7 +718,7 @@ static void pointer_handle_output_destroy(struct wl_listener *listener, void *data) { struct wlr_wl_pointer *pointer = wl_container_of(listener, pointer, output_destroy); - wlr_pointer_destroy(&pointer->wlr_pointer); + destroy_wl_input_device(pointer->input_device); } void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) { @@ -741,13 +750,14 @@ void create_wl_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output) { } pointer->input_device = dev; - wl_signal_add(&output->wlr_output.events.destroy, &pointer->output_destroy); - pointer->output_destroy.notify = pointer_handle_output_destroy; - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; wlr_dev->pointer = &pointer->wlr_pointer; wlr_dev->output_name = strdup(output->wlr_output.name); - wlr_pointer_init(wlr_dev->pointer, &pointer_impl, wlr_dev->name); + + wlr_pointer_init(&pointer->wlr_pointer, &pointer_impl, wlr_dev->name); + + wl_signal_add(&output->wlr_output.events.destroy, &pointer->output_destroy); + pointer->output_destroy.notify = pointer_handle_output_destroy; if (backend->zwp_pointer_gestures_v1) { uint32_t version = zwp_pointer_gestures_v1_get_version( @@ -792,11 +802,11 @@ void create_wl_keyboard(struct wlr_wl_seat *seat) { wlr_dev->keyboard = calloc(1, sizeof(*wlr_dev->keyboard)); if (!wlr_dev->keyboard) { wlr_log_errno(WLR_ERROR, "Allocation failed"); - wlr_input_device_destroy(wlr_dev); + destroy_wl_input_device(dev); return; } - wlr_keyboard_init(wlr_dev->keyboard, NULL, wlr_dev->name); + wlr_keyboard_init(wlr_dev->keyboard, &keyboard_impl, wlr_dev->name); wl_keyboard_add_listener(wl_keyboard, &keyboard_listener, wlr_dev); wlr_signal_emit_safe(&seat->backend->backend.events.new_input, wlr_dev); @@ -816,16 +826,15 @@ void create_wl_touch(struct wlr_wl_seat *seat) { wlr_dev->touch = calloc(1, sizeof(*wlr_dev->touch)); if (!wlr_dev->touch) { wlr_log_errno(WLR_ERROR, "Allocation failed"); - wlr_input_device_destroy(wlr_dev); + destroy_wl_input_device(dev); return; } - wlr_touch_init(wlr_dev->touch, NULL, wlr_dev->name); + wlr_touch_init(wlr_dev->touch, &touch_impl, wlr_dev->name); wl_touch_add_listener(wl_touch, &touch_listener, dev); wlr_signal_emit_safe(&seat->backend->backend.events.new_input, wlr_dev); } - static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, enum wl_seat_capability caps) { struct wlr_wl_seat *seat = data; @@ -860,7 +869,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, wlr_log(WLR_DEBUG, "dropping pointer %s", pointer->input_device->wlr_input_device.name); struct wlr_wl_output *output = pointer->output; - wlr_input_device_destroy(&device->wlr_input_device); + destroy_wl_input_device(device); assert(seat->active_pointer != pointer); assert(output->cursor.pointer != pointer); } @@ -891,7 +900,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, if (device->seat != seat) { continue; } - wlr_input_device_destroy(&device->wlr_input_device); + destroy_wl_input_device(device); } assert(seat->keyboard == NULL); // free'ed by input_device_destroy } @@ -910,7 +919,7 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat, struct wlr_wl_input_device *device, *tmp; wl_list_for_each_safe(device, tmp, &backend->devices, link) { if (device->wlr_input_device.type == WLR_INPUT_DEVICE_TOUCH) { - wlr_input_device_destroy(&device->wlr_input_device); + destroy_wl_input_device(device); } } diff --git a/backend/wayland/tablet_v2.c b/backend/wayland/tablet_v2.c index 4ddcce07..d24bf340 100644 --- a/backend/wayland/tablet_v2.c +++ b/backend/wayland/tablet_v2.c @@ -426,6 +426,8 @@ static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { .removed = handle_tablet_pad_removed, }; +const struct wlr_tablet_pad_impl tablet_pad_impl = {0}; + static void handle_pad_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_pad_v2 *id) { @@ -453,7 +455,7 @@ static void handle_pad_added(void *data, zwp_tablet_pad_v2_destroy(id); return; } - wlr_tablet_pad_init(wlr_dev->tablet_pad, NULL, wlr_dev->name); + wlr_tablet_pad_init(wlr_dev->tablet_pad, &tablet_pad_impl, wlr_dev->name); zwp_tablet_pad_v2_add_listener(id, &tablet_pad_listener, dev); } @@ -887,6 +889,8 @@ static const struct zwp_tablet_v2_listener tablet_listener = { .removed = handle_tablet_removed, }; +const struct wlr_tablet_impl tablet_impl = {0}; + static void handle_tab_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_v2 *id) { @@ -909,7 +913,7 @@ static void handle_tab_added(void *data, return; } zwp_tablet_v2_set_user_data(id, wlr_dev->tablet); - wlr_tablet_init(wlr_dev->tablet, NULL, wlr_dev->name); + wlr_tablet_init(wlr_dev->tablet, &tablet_impl, wlr_dev->name); zwp_tablet_v2_add_listener(id, &tablet_listener, dev); } diff --git a/include/backend/wayland.h b/include/backend/wayland.h index 4e5d3636..668b69ae 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -134,9 +134,12 @@ struct wlr_wl_input_device *create_wl_input_device( struct wlr_wl_seat *seat, enum wlr_input_device_type type); bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl); void destroy_wl_seats(struct wlr_wl_backend *wl); +void destroy_wl_input_device(struct wlr_wl_input_device *dev); void destroy_wl_buffer(struct wlr_wl_buffer *buffer); extern const struct wl_seat_listener seat_listener; +extern const struct wlr_tablet_pad_impl tablet_pad_impl; +extern const struct wlr_tablet_impl tablet_impl; struct wlr_wl_tablet_seat *wl_add_tablet_seat( struct zwp_tablet_manager_v2 *manager,