diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 44468a26..3428488e 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -418,7 +418,7 @@ static bool backend_start(struct wlr_backend *backend) { } if (wl->tablet_manager) { - wl_add_tablet_seat(wl->tablet_manager, seat); + init_seat_tablet(seat); } } diff --git a/backend/wayland/seat.c b/backend/wayland/seat.c index e2d5278c..854447ee 100644 --- a/backend/wayland/seat.c +++ b/backend/wayland/seat.c @@ -255,6 +255,9 @@ void destroy_wl_seats(struct wlr_wl_backend *wl) { wl_keyboard_release(seat->wl_keyboard); wlr_keyboard_finish(&seat->wlr_keyboard); } + if (seat->zwp_tablet_seat_v2) { + finish_seat_tablet(seat); + } free(seat->name); assert(seat->wl_seat); @@ -281,9 +284,9 @@ bool wlr_input_device_is_wl(struct wlr_input_device *dev) { case WLR_INPUT_DEVICE_TOUCH: return dev->touch->impl == &touch_impl; case WLR_INPUT_DEVICE_TABLET_TOOL: - return dev->tablet->impl == &tablet_impl; + return dev->tablet->impl == &wl_tablet_impl; case WLR_INPUT_DEVICE_TABLET_PAD: - return dev->tablet_pad->impl == &tablet_pad_impl; + return dev->tablet_pad->impl == &wl_tablet_pad_impl; default: return false; } @@ -318,11 +321,13 @@ struct wlr_wl_input_device *create_wl_input_device( free(dev); return NULL; case WLR_INPUT_DEVICE_TABLET_TOOL: - type_name = "tablet-tool"; - break; + wlr_log(WLR_ERROR, "can't create tablet tool wlr_wl_input_device"); + free(dev); + return NULL; case WLR_INPUT_DEVICE_TABLET_PAD: - type_name = "tablet-pad"; - break; + wlr_log(WLR_ERROR, "can't create tablet pad wlr_wl_input_device"); + free(dev); + return NULL; default: wlr_log(WLR_ERROR, "device not handled"); free(dev); @@ -355,12 +360,10 @@ void destroy_wl_input_device(struct wlr_wl_input_device *dev) { wlr_log(WLR_ERROR, "wlr_wl_input_device has no pointer"); break; case WLR_INPUT_DEVICE_TABLET_PAD: - wlr_tablet_pad_finish(wlr_dev->tablet_pad); - free(wlr_dev->tablet_pad); + wlr_log(WLR_ERROR, "wlr_wl_input_device has no tablet pad"); break; case WLR_INPUT_DEVICE_TABLET_TOOL: - wlr_tablet_finish(wlr_dev->tablet); - free(wlr_dev->tablet); + wlr_log(WLR_ERROR, "wlr_wl_input_device has no tablet_tool"); break; case WLR_INPUT_DEVICE_TOUCH: wlr_log(WLR_ERROR, "wlr_wl_input_device has no touch"); diff --git a/backend/wayland/tablet_v2.c b/backend/wayland/tablet_v2.c index dc7f50fd..5666aa5f 100644 --- a/backend/wayland/tablet_v2.c +++ b/backend/wayland/tablet_v2.c @@ -1,35 +1,25 @@ -#ifndef _POSIX_C_SOURCE #define _POSIX_C_SOURCE 200809L -#endif -#include #include #include #include #include #include #include -#include - -#include "util/signal.h" -#include "util/time.h" -#include "wlr/util/log.h" -#include "tablet-unstable-v2-client-protocol.h" +#include #include "backend/wayland.h" +#include "util/signal.h" +#include "util/time.h" -struct wlr_wl_tablet_seat { - struct zwp_tablet_seat_v2 *tablet_seat; -}; +#include "tablet-unstable-v2-client-protocol.h" -struct wlr_wl_tablet_tool { +struct tablet_tool { /* static */ - struct zwp_tablet_tool_v2 *tool; - struct wlr_tablet_tool wlr_tool; + struct wlr_wl_seat *seat; /* semi-static */ struct wlr_wl_output *output; - struct wlr_wl_input_device *tablet; double pre_x, pre_y; /* per frame */ @@ -49,11 +39,11 @@ struct wlr_wl_tablet_tool { bool is_down; }; -struct wlr_wl_tablet_pad_ring { - struct wl_list link; // wlr_wl_tablet_pad_group::rings +struct tablet_pad_ring { + struct wl_list link; // tablet_pad_group::rings /* static */ struct zwp_tablet_pad_ring_v2 *ring; - struct wlr_wl_tablet_pad_group *group; + struct tablet_pad_group *group; size_t index; /* per frame */ @@ -62,10 +52,10 @@ struct wlr_wl_tablet_pad_ring { bool stopped; }; -struct wlr_wl_tablet_pad_strip { - struct wl_list link; // wlr_wl_tablet_pad_group::strips +struct tablet_pad_strip { + struct wl_list link; // tablet_pad_group::strips struct zwp_tablet_pad_strip_v2 *strip; - struct wlr_wl_tablet_pad_group *group; + struct tablet_pad_group *group; size_t index; enum wlr_tablet_pad_strip_source source; @@ -73,41 +63,41 @@ struct wlr_wl_tablet_pad_strip { bool stopped; }; -struct wlr_wl_tablet_pad_group { +struct tablet_pad_group { struct zwp_tablet_pad_group_v2 *pad_group; struct wlr_tablet_pad *pad; unsigned int mode; struct wlr_tablet_pad_group group; - struct wl_list rings; // wlr_wl_tablet_pad_ring::link - struct wl_list strips; // wlr_wl_tablet_pad_strips::link + struct wl_list rings; // tablet_pad_ring::link + struct wl_list strips; // tablet_pad_strips::link }; static void handle_tablet_pad_ring_source(void *data, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, uint32_t source) { - struct wlr_wl_tablet_pad_ring *ring = data; + struct tablet_pad_ring *ring = data; ring->source = source; } static void handle_tablet_pad_ring_angle(void *data, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, wl_fixed_t degrees) { - struct wlr_wl_tablet_pad_ring *ring = data; + struct tablet_pad_ring *ring = data; ring->angle = wl_fixed_to_double(degrees); } static void handle_tablet_pad_ring_stop(void *data, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2) { - struct wlr_wl_tablet_pad_ring *ring = data; + struct tablet_pad_ring *ring = data; ring->stopped = true; } static void handle_tablet_pad_ring_frame(void *data, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, uint32_t time) { - struct wlr_wl_tablet_pad_ring *ring = data; + struct tablet_pad_ring *ring = data; struct wlr_event_tablet_pad_ring evt = { .time_msec = time, @@ -140,27 +130,27 @@ static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = { static void handle_tablet_pad_strip_source(void *data, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, uint32_t source) { - struct wlr_wl_tablet_pad_strip *strip = data; + struct tablet_pad_strip *strip = data; strip->source = source; } static void handle_tablet_pad_strip_position(void *data, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, uint32_t position) { - struct wlr_wl_tablet_pad_strip *strip = data; + struct tablet_pad_strip *strip = data; strip->position = (double) position / 65536.0; } static void handle_tablet_pad_strip_stop(void *data, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2) { - struct wlr_wl_tablet_pad_strip *strip = data; + struct tablet_pad_strip *strip = data; strip->stopped = true; } static void handle_tablet_pad_strip_frame(void *data, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, uint32_t time) { - struct wlr_wl_tablet_pad_strip *strip = data; + struct tablet_pad_strip *strip = data; struct wlr_event_tablet_pad_strip evt = { .time_msec = time, @@ -193,7 +183,7 @@ static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener = static void handle_tablet_pad_group_buttons(void *data, struct zwp_tablet_pad_group_v2 *pad_group, struct wl_array *buttons) { - struct wlr_wl_tablet_pad_group *group = data; + struct tablet_pad_group *group = data; free(group->group.buttons); group->group.buttons = calloc(1, buttons->size); @@ -208,7 +198,7 @@ static void handle_tablet_pad_group_buttons(void *data, static void handle_tablet_pad_group_modes(void *data, struct zwp_tablet_pad_group_v2 *pad_group, uint32_t modes) { - struct wlr_wl_tablet_pad_group *group = data; + struct tablet_pad_group *group = data; group->group.mode_count = modes; } @@ -216,9 +206,9 @@ static void handle_tablet_pad_group_modes(void *data, static void handle_tablet_pad_group_ring(void *data, struct zwp_tablet_pad_group_v2 *pad_group, struct zwp_tablet_pad_ring_v2 *ring) { - struct wlr_wl_tablet_pad_group *group = data; - struct wlr_wl_tablet_pad_ring *tablet_ring = - calloc(1, sizeof(struct wlr_wl_tablet_pad_ring)); + struct tablet_pad_group *group = data; + struct tablet_pad_ring *tablet_ring = + calloc(1, sizeof(struct tablet_pad_ring)); if (!tablet_ring) { zwp_tablet_pad_ring_v2_destroy(ring); return; @@ -237,9 +227,9 @@ static void handle_tablet_pad_group_ring(void *data, static void handle_tablet_pad_group_strip(void *data, struct zwp_tablet_pad_group_v2 *pad_group, struct zwp_tablet_pad_strip_v2 *strip) { - struct wlr_wl_tablet_pad_group *group = data; - struct wlr_wl_tablet_pad_strip *tablet_strip = - calloc(1, sizeof(struct wlr_wl_tablet_pad_strip)); + struct tablet_pad_group *group = data; + struct tablet_pad_strip *tablet_strip = + calloc(1, sizeof(struct tablet_pad_strip)); if (!tablet_strip) { zwp_tablet_pad_strip_v2_destroy(strip); return; @@ -263,25 +253,20 @@ static void handle_tablet_pad_group_done(void *data, static void handle_tablet_pad_group_mode_switch(void *data, struct zwp_tablet_pad_group_v2 *pad_group, uint32_t time, uint32_t serial, uint32_t mode) { - struct wlr_wl_tablet_pad_group *group = data; + struct tablet_pad_group *group = data; group->mode = mode; } -/* This isn't in the listener, but keep the naming scheme around since the - * other removed functions work like this, and pad sub-resources are just a bit - * special */ -static void handle_tablet_pad_group_removed( - struct wlr_wl_tablet_pad_group *group) { - +static void destroy_tablet_pad_group(struct tablet_pad_group *group) { /* No need to remove the ::link on strips rings as long as we do *not* * wl_list_remove on the wl_groups ring/strip attributes here */ - struct wlr_wl_tablet_pad_ring *ring, *tmp_ring; + struct tablet_pad_ring *ring, *tmp_ring; wl_list_for_each_safe(ring, tmp_ring, &group->rings, link) { zwp_tablet_pad_ring_v2_destroy(ring->ring); free(ring); } - struct wlr_wl_tablet_pad_strip *strip, *tmp_strip; + struct tablet_pad_strip *strip, *tmp_strip; wl_list_for_each_safe(strip, tmp_strip, &group->strips, link) { zwp_tablet_pad_strip_v2_destroy(strip->strip); free(strip); @@ -309,12 +294,13 @@ static const struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = static void handle_tablet_pad_group(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad, struct zwp_tablet_pad_group_v2 *pad_group) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *pad = dev->wlr_input_device.tablet_pad; + struct wlr_wl_seat *seat = data; + struct wlr_tablet_pad *pad = &seat->wlr_tablet_pad; - struct wlr_wl_tablet_pad_group *group = - calloc(1, sizeof(struct wlr_wl_tablet_pad_group)); + struct tablet_pad_group *group = + calloc(1, sizeof(struct tablet_pad_group)); if (!group) { + wlr_log_errno(WLR_ERROR, "failed to allocate tablet_pad_group"); zwp_tablet_pad_group_v2_destroy(pad_group); return; } @@ -331,20 +317,18 @@ static void handle_tablet_pad_group(void *data, } static void handle_tablet_pad_path(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - const char *path) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, const char *path) { + struct wlr_wl_seat *seat = data; + struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad; char **dst = wl_array_add(&tablet_pad->paths, sizeof(char *)); *dst = strdup(path); } static void handle_tablet_pad_buttons(void *data, - struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, - uint32_t buttons) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t buttons) { + struct wlr_wl_seat *seat = data; + struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad; tablet_pad->button_count = buttons; } @@ -352,9 +336,7 @@ static void handle_tablet_pad_buttons(void *data, static void handle_tablet_pad_button(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t time, uint32_t button, uint32_t state) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; - + struct wlr_wl_seat *seat = data; struct wlr_event_tablet_pad_button evt = { .time_msec = time, .button = button, @@ -363,28 +345,25 @@ static void handle_tablet_pad_button(void *data, .group = 0, }; - wlr_signal_emit_safe(&tablet_pad->events.button, &evt); + wlr_signal_emit_safe(&seat->wlr_tablet_pad.events.button, &evt); } static void handle_tablet_pad_done(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { - struct wlr_wl_input_device *dev = data; - - wlr_signal_emit_safe(&dev->backend->backend.events.new_input, - &dev->wlr_input_device); + struct wlr_wl_seat *seat = data; + wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + &seat->wlr_tablet_pad.base); } static void handle_tablet_pad_enter(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t serial, struct zwp_tablet_v2 *tablet_p, struct wl_surface *surface) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; - struct wlr_wl_input_device *tab_dev = zwp_tablet_v2_get_user_data(tablet_p); - struct wlr_input_device *tablet = &tab_dev->wlr_input_device; - wlr_log(WLR_DEBUG, "Tablet: %p\n", tablet); + struct wlr_wl_seat *seat = data; + assert(seat->zwp_tablet_v2 == tablet_p); - wlr_signal_emit_safe(&tablet_pad->events.attach_tablet, tablet); + wlr_signal_emit_safe(&seat->wlr_tablet_pad.events.attach_tablet, + &seat->wlr_tablet_tool); } static void handle_tablet_pad_leave(void *data, @@ -396,16 +375,17 @@ static void handle_tablet_pad_leave(void *data, static void handle_tablet_pad_removed(void *data, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { - struct wlr_wl_input_device *dev = data; + struct wlr_wl_seat *seat = data; - struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad; - struct wlr_wl_tablet_pad_group *group, *it; + struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad; + struct tablet_pad_group *group, *it; wl_list_for_each_safe(group, it, &tablet_pad->groups, group.link) { - handle_tablet_pad_group_removed(group); + destroy_tablet_pad_group(group); } - zwp_tablet_pad_v2_destroy(dev->resource); - destroy_wl_input_device(dev); + wlr_tablet_pad_finish(tablet_pad); + zwp_tablet_pad_v2_destroy(seat->zwp_tablet_pad_v2); + seat->zwp_tablet_pad_v2 = NULL; } static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { @@ -419,39 +399,25 @@ 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 = { +const struct wlr_tablet_pad_impl wl_tablet_pad_impl = { .name = "wl-tablet-pad", }; static void handle_pad_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, - struct zwp_tablet_pad_v2 *id) { - wlr_log(WLR_DEBUG, "New tablet pad"); + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { struct wlr_wl_seat *seat = data; - struct wlr_wl_input_device *dev = create_wl_input_device( - seat, WLR_INPUT_DEVICE_TABLET_PAD); - if (!dev) { - /* This leaks a couple of server-sent resource ids. iirc this - * shouldn't ever be a problem, but it isn't exactly nice - * either. */ - zwp_tablet_pad_v2_destroy(id); + if (seat->zwp_tablet_pad_v2 != NULL) { + wlr_log(WLR_ERROR, "zwp_tablet_pad_v2 is already present"); return; } - dev->resource = id; - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - wlr_dev->tablet_pad = calloc(1, sizeof(*wlr_dev->tablet_pad)); + seat->zwp_tablet_pad_v2 = zwp_tablet_pad_v2; + zwp_tablet_pad_v2_add_listener(zwp_tablet_pad_v2, &tablet_pad_listener, + seat); - if (!wlr_dev->tablet_pad) { - /* This leaks a couple of server-sent resource ids. iirc this - * shouldn't ever be a problem, but it isn't exactly nice - * either. */ - free(dev); - zwp_tablet_pad_v2_destroy(id); - return; - } - wlr_tablet_pad_init(wlr_dev->tablet_pad, &tablet_pad_impl, "wlr_tablet_v2"); - zwp_tablet_pad_v2_add_listener(id, &tablet_pad_listener, dev); + wlr_tablet_pad_init(&seat->wlr_tablet_pad, &wl_tablet_pad_impl, + "wlr_tablet_v2"); } static void handle_tablet_tool_done(void *data, @@ -459,7 +425,8 @@ static void handle_tablet_tool_done(void *data, /* empty */ } -static enum wlr_tablet_tool_type tablet_type_to_wlr_type(enum zwp_tablet_tool_v2_type type) { +static enum wlr_tablet_tool_type tablet_type_to_wlr_type( + enum zwp_tablet_tool_v2_type type) { switch (type) { case ZWP_TABLET_TOOL_V2_TYPE_PEN: return WLR_TABLET_TOOL_TYPE_PEN; @@ -484,94 +451,85 @@ static enum wlr_tablet_tool_type tablet_type_to_wlr_type(enum zwp_tablet_tool_v2 } static void handle_tablet_tool_type(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t tool_type) { - struct wlr_wl_tablet_tool *tool = data; - - tool->wlr_tool.type = tablet_type_to_wlr_type(tool_type); + struct zwp_tablet_tool_v2 *id, uint32_t tool_type) { + struct tablet_tool *tool = data; + struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool; + wlr_tool->type = tablet_type_to_wlr_type(tool_type); } static void handle_tablet_tool_serial(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t high, uint32_t low) { - struct wlr_wl_tablet_tool *tool = data; - - tool->wlr_tool.hardware_serial = - ((uint64_t) high) << 32 | (uint64_t) low; + struct zwp_tablet_tool_v2 *id, uint32_t high, uint32_t low) { + struct tablet_tool *tool = data; + struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool; + wlr_tool->hardware_serial = ((uint64_t) high) << 32 | (uint64_t) low; } static void handle_tablet_tool_id_wacom(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t high, uint32_t low) { - struct wlr_wl_tablet_tool *tool = data; - - tool->wlr_tool.hardware_wacom = - ((uint64_t) high) << 32 | (uint64_t) low; + struct zwp_tablet_tool_v2 *id, uint32_t high, uint32_t low) { + struct tablet_tool *tool = data; + struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool; + wlr_tool->hardware_wacom = ((uint64_t) high) << 32 | (uint64_t) low; } static void handle_tablet_tool_capability(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t capability) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_tool_v2 *id, uint32_t capability) { + struct tablet_tool *tool = data; + struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool; - enum zwp_tablet_tool_v2_capability cap = capability; - - switch (cap) { + /* One event is sent for each capability */ + switch (capability) { case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT: - tool->wlr_tool.tilt = true; + wlr_tool->tilt = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE: - tool->wlr_tool.pressure = true; + wlr_tool->pressure = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE: - tool->wlr_tool.distance = true; + wlr_tool->distance = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION: - tool->wlr_tool.rotation = true; + wlr_tool->rotation = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER: - tool->wlr_tool.slider = true; + wlr_tool->slider = true; break; case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL: - tool->wlr_tool.wheel = true; + wlr_tool->wheel = true; break; } } static void handle_tablet_tool_proximity_in(void *data, struct zwp_tablet_tool_v2 *id, uint32_t serial, - struct zwp_tablet_v2 *tablet_id, - struct wl_surface *surface) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_v2 *tablet_id, struct wl_surface *surface) { + struct tablet_tool *tool = data; + assert(tablet_id == tool->seat->zwp_tablet_v2); + tool->is_in = true; - tool->tablet = zwp_tablet_v2_get_user_data(tablet_id); tool->output = wl_surface_get_user_data(surface); } static void handle_tablet_tool_proximity_out(void *data, struct zwp_tablet_tool_v2 *id) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->is_out = true; tool->output = NULL; } -static void handle_tablet_tool_down(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *id, unsigned int serial) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->is_down = true; } -static void handle_tablet_tool_up(void *data, - struct zwp_tablet_tool_v2 *id) { - struct wlr_wl_tablet_tool *tool = data; +static void handle_tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *id) { + struct tablet_tool *tool = data; tool->is_up = true; } -static void handle_tablet_tool_motion(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *id, wl_fixed_t x, wl_fixed_t y) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; struct wlr_wl_output *output = tool->output; assert(output); @@ -580,58 +538,53 @@ static void handle_tablet_tool_motion(void *data, } static void handle_tablet_tool_pressure(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t pressure) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_tool_v2 *id, uint32_t pressure) { + struct tablet_tool *tool = data; tool->pressure = (double) pressure / 65535.0; } static void handle_tablet_tool_distance(void *data, - struct zwp_tablet_tool_v2 *id, - uint32_t distance) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_tool_v2 *id, uint32_t distance) { + struct tablet_tool *tool = data; tool->distance = (double) distance / 65535.0; } -static void handle_tablet_tool_tilt(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *id, wl_fixed_t x, wl_fixed_t y) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->tilt_x = wl_fixed_to_double(x); tool->tilt_y = wl_fixed_to_double(y); } static void handle_tablet_tool_rotation(void *data, - struct zwp_tablet_tool_v2 *id, - wl_fixed_t rotation) { - struct wlr_wl_tablet_tool *tool = data; + struct zwp_tablet_tool_v2 *id, wl_fixed_t rotation) { + struct tablet_tool *tool = data; tool->rotation = wl_fixed_to_double(rotation); } -static void handle_tablet_tool_slider(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_slider(void *data, struct zwp_tablet_tool_v2 *id, int slider) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->slider = (double) slider / 65535.0;; } // TODO: This looks wrong :/ -static void handle_tablet_tool_wheel(void *data, - struct zwp_tablet_tool_v2 *id, +static void handle_tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *id, wl_fixed_t degree, int clicks) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; tool->wheel_delta = wl_fixed_to_double(degree); } static void handle_tablet_tool_button(void *data, struct zwp_tablet_tool_v2 *id, uint32_t serial, uint32_t button, uint32_t state) { - struct wlr_wl_tablet_tool *tool = data; - struct wlr_tablet *tablet = tool->tablet->wlr_input_device.tablet; + struct tablet_tool *tool = data; + struct wlr_wl_seat *seat = tool->seat; + struct wlr_tablet *tablet = &seat->wlr_tablet; struct wlr_event_tablet_tool_button evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = get_current_time_msec(), .button = button, .state = state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED ? @@ -641,7 +594,7 @@ static void handle_tablet_tool_button(void *data, wlr_signal_emit_safe(&tablet->events.button, &evt); } -static void clear_tablet_tool_values(struct wlr_wl_tablet_tool *tool) { +static void clear_tablet_tool_values(struct tablet_tool *tool) { tool->is_out = tool->is_in = false; tool->is_up = tool->is_down = false; tool->x = tool->y = NAN; @@ -656,18 +609,20 @@ static void clear_tablet_tool_values(struct wlr_wl_tablet_tool *tool) { static void handle_tablet_tool_frame(void *data, struct zwp_tablet_tool_v2 *id, uint32_t time) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; + struct wlr_wl_seat *seat = tool->seat; + if (tool->is_out && tool->is_in) { /* we got a tablet tool coming in and out of proximity before * we could process it. Just ignore anything it did */ goto clear_values; } - struct wlr_tablet *tablet = tool->tablet->wlr_input_device.tablet; + struct wlr_tablet *tablet = &seat->wlr_tablet; if (tool->is_in) { struct wlr_event_tablet_tool_proximity evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, .y = tool->y, @@ -679,8 +634,8 @@ static void handle_tablet_tool_frame(void *data, { struct wlr_event_tablet_tool_axis evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .updated_axes = 0, }; @@ -742,8 +697,8 @@ static void handle_tablet_tool_frame(void *data, * need to generate the time */ if (tool->is_down) { struct wlr_event_tablet_tool_tip evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, .y = tool->y, @@ -755,8 +710,8 @@ static void handle_tablet_tool_frame(void *data, if (tool->is_up) { struct wlr_event_tablet_tool_tip evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, .y = tool->y, @@ -768,8 +723,8 @@ static void handle_tablet_tool_frame(void *data, if (tool->is_out) { struct wlr_event_tablet_tool_proximity evt = { - .device = &tool->tablet->wlr_input_device, - .tool = &tool->wlr_tool, + .device = &tablet->base, + .tool = &seat->wlr_tablet_tool, .time_msec = time, .x = tool->x, .y = tool->y, @@ -785,10 +740,12 @@ clear_values: static void handle_tablet_tool_removed(void *data, struct zwp_tablet_tool_v2 *id) { - struct wlr_wl_tablet_tool *tool = data; + struct tablet_tool *tool = data; + struct wlr_wl_seat *seat = tool->seat; + + zwp_tablet_tool_v2_destroy(seat->zwp_tablet_tool_v2); + seat->zwp_tablet_tool_v2 = NULL; - zwp_tablet_tool_v2_destroy(tool->tool); - wlr_signal_emit_safe(&tool->wlr_tool.events.destroy, &tool->wlr_tool); free(tool); } @@ -818,23 +775,34 @@ static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { static void handle_tool_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, - struct zwp_tablet_tool_v2 *id) { - wlr_log(WLR_DEBUG, "New tablet tool"); - struct wlr_wl_tablet_tool *tool = calloc(1, sizeof(*tool)); - if (!tool) { - zwp_tablet_tool_v2_destroy(id); + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) { + struct wlr_wl_seat *seat = data; + if (seat->zwp_tablet_tool_v2 != NULL) { + wlr_log(WLR_ERROR, "zwp_tablet_tool_v2 already present"); return; } - tool->tool = id; + + wl_signal_init(&seat->wlr_tablet_tool.events.destroy); + + struct tablet_tool *tool = calloc(1, sizeof(struct tablet_tool)); + if (tool == NULL) { + wlr_log_errno(WLR_ERROR, "failed to allocate tablet_tool"); + zwp_tablet_tool_v2_destroy(zwp_tablet_tool_v2); + return; + } + + tool->seat = seat; clear_tablet_tool_values(tool); - wl_signal_init(&tool->wlr_tool.events.destroy); - zwp_tablet_tool_v2_add_listener(id, &tablet_tool_listener, tool); + + seat->zwp_tablet_tool_v2 = zwp_tablet_tool_v2; + zwp_tablet_tool_v2_add_listener(seat->zwp_tablet_tool_v2, &tablet_tool_listener, + tool); } static void handle_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, const char *name) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet *tablet = dev->wlr_input_device.tablet; + struct wlr_wl_seat *seat = data; + struct wlr_tablet *tablet = &seat->wlr_tablet; free(tablet->base.name); tablet->base.name = strdup(name); @@ -842,33 +810,36 @@ static void handle_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, static void handle_tablet_id(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, uint32_t vid, uint32_t pid) { - struct wlr_wl_input_device *dev = data; - dev->wlr_input_device.vendor = vid; - dev->wlr_input_device.product = pid; + struct wlr_wl_seat *seat = data; + struct wlr_tablet *tablet = &seat->wlr_tablet; + + tablet->base.vendor = vid; + tablet->base.product = pid; } static void handle_tablet_path(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, const char *path) { - struct wlr_wl_input_device *dev = data; - struct wlr_tablet *tablet = dev->wlr_input_device.tablet; + struct wlr_wl_seat *seat = data; + struct wlr_tablet *tablet = &seat->wlr_tablet; char **dst = wl_array_add(&tablet->paths, sizeof(char *)); *dst = strdup(path); } static void handle_tablet_done(void *data, struct zwp_tablet_v2 *zwp_tablet_v2) { - struct wlr_wl_input_device *dev = data; + struct wlr_wl_seat *seat = data; - wlr_signal_emit_safe(&dev->backend->backend.events.new_input, - &dev->wlr_input_device); + wlr_signal_emit_safe(&seat->backend->backend.events.new_input, + &seat->wlr_tablet.base); } static void handle_tablet_removed(void *data, struct zwp_tablet_v2 *zwp_tablet_v2) { - struct wlr_wl_input_device *dev = data; + struct wlr_wl_seat *seat = data; - zwp_tablet_v2_destroy(dev->resource); - destroy_wl_input_device(dev); + wlr_tablet_finish(&seat->wlr_tablet); + zwp_tablet_v2_destroy(seat->zwp_tablet_v2); + seat->zwp_tablet_v2 = NULL; } static const struct zwp_tablet_v2_listener tablet_listener = { @@ -879,34 +850,23 @@ static const struct zwp_tablet_v2_listener tablet_listener = { .removed = handle_tablet_removed, }; -const struct wlr_tablet_impl tablet_impl = { +const struct wlr_tablet_impl wl_tablet_impl = { .name = "wl-tablet-tool", }; static void handle_tab_added(void *data, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, - struct zwp_tablet_v2 *id) { - wlr_log(WLR_DEBUG, "New tablet"); + struct zwp_tablet_v2 *zwp_tablet_v2) { struct wlr_wl_seat *seat = data; - struct wlr_wl_input_device *dev = create_wl_input_device( - seat, WLR_INPUT_DEVICE_TABLET_TOOL); - - if (!dev) { - zwp_tablet_v2_destroy(id); + if (seat->zwp_tablet_v2 != NULL) { + wlr_log(WLR_ERROR, "zwp_tablet_v2 already present"); return; } - dev->resource = id; - struct wlr_input_device *wlr_dev = &dev->wlr_input_device; - wlr_dev->tablet = calloc(1, sizeof(*wlr_dev->tablet)); + seat->zwp_tablet_v2 = zwp_tablet_v2; + zwp_tablet_v2_add_listener(zwp_tablet_v2, &tablet_listener, seat); - if (!wlr_dev->tablet) { - zwp_tablet_v2_destroy(id); - return; - } - zwp_tablet_v2_set_user_data(id, wlr_dev->tablet); - wlr_tablet_init(wlr_dev->tablet, &tablet_impl, "wlr_tablet_v2"); - zwp_tablet_v2_add_listener(id, &tablet_listener, dev); + wlr_tablet_init(&seat->wlr_tablet, &wl_tablet_impl, "wlr_tablet_v2"); } static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { @@ -915,20 +875,55 @@ static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { .pad_added = handle_pad_added, }; -struct wlr_wl_tablet_seat *wl_add_tablet_seat( - struct zwp_tablet_manager_v2 *manager, - struct wlr_wl_seat *seat) { - struct wlr_wl_tablet_seat *ret = - calloc(1, sizeof(struct wlr_wl_tablet_seat)); +void init_seat_tablet(struct wlr_wl_seat *seat) { + struct zwp_tablet_manager_v2 *manager = seat->backend->tablet_manager; + assert(manager); - if (!(ret->tablet_seat = - zwp_tablet_manager_v2_get_tablet_seat(manager, seat->wl_seat))) { - free(ret); - return NULL; + /** + * TODO: multi tablet support + * The wlr_wl_seat should support multiple tablet_v2 devices, but for + * the sake of simplicity, it supports only one device of each. + * If this is a feature you want/need, please open an issue on the wlroots + * tracker here https://gitlab.freedesktop.org/wlroots/wlroots/-/issues + */ + + seat->zwp_tablet_seat_v2 = + zwp_tablet_manager_v2_get_tablet_seat(manager, seat->wl_seat); + if (seat->zwp_tablet_seat_v2 == NULL) { + wlr_log(WLR_ERROR, "failed to get zwp_tablet_manager_v2 from seat '%s'", + seat->name); + return; } - zwp_tablet_seat_v2_add_listener(ret->tablet_seat, + zwp_tablet_seat_v2_add_listener(seat->zwp_tablet_seat_v2, &tablet_seat_listener, seat); - - return ret; +} + +void finish_seat_tablet(struct wlr_wl_seat *seat) { + if (seat->zwp_tablet_v2 != NULL) { + wlr_tablet_finish(&seat->wlr_tablet); + zwp_tablet_v2_destroy(seat->zwp_tablet_v2); + } + + if (seat->zwp_tablet_tool_v2 != NULL) { + struct tablet_tool *tool = + zwp_tablet_tool_v2_get_user_data(seat->zwp_tablet_tool_v2); + free(tool); + + zwp_tablet_tool_v2_destroy(seat->zwp_tablet_tool_v2); + } + + if (seat->zwp_tablet_pad_v2 != NULL) { + struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad; + struct tablet_pad_group *group, *it; + wl_list_for_each_safe(group, it, &tablet_pad->groups, group.link) { + destroy_tablet_pad_group(group); + } + + wlr_tablet_pad_finish(tablet_pad); + zwp_tablet_pad_v2_destroy(seat->zwp_tablet_pad_v2); + } + + zwp_tablet_seat_v2_destroy(seat->zwp_tablet_seat_v2); + seat->zwp_tablet_seat_v2 = NULL; } diff --git a/include/backend/wayland.h b/include/backend/wayland.h index e07daa4f..d683dfca 100644 --- a/include/backend/wayland.h +++ b/include/backend/wayland.h @@ -10,6 +10,8 @@ #include #include #include +#include +#include #include #include @@ -132,6 +134,14 @@ struct wlr_wl_seat { struct wl_touch *wl_touch; struct wlr_touch wlr_touch; + struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2; + struct zwp_tablet_v2 *zwp_tablet_v2; + struct wlr_tablet wlr_tablet; + struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2; + struct wlr_tablet_tool wlr_tablet_tool; + struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2; + struct wlr_tablet_pad wlr_tablet_pad; + struct wl_list link; // wlr_wl_backend.seats }; @@ -144,6 +154,9 @@ void init_seat_pointer(struct wlr_wl_seat *seat); void finish_seat_pointer(struct wlr_wl_seat *seat); void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); +void init_seat_tablet(struct wlr_wl_seat *seat); +void finish_seat_tablet(struct wlr_wl_seat *seat); + 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); @@ -154,11 +167,7 @@ void destroy_wl_buffer(struct wlr_wl_buffer *buffer); extern const struct wl_seat_listener seat_listener; extern const struct wlr_pointer_impl wl_pointer_impl; -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, - struct wlr_wl_seat *seat); +extern const struct wlr_tablet_pad_impl wl_tablet_pad_impl; +extern const struct wlr_tablet_impl wl_tablet_impl; #endif