backend/wayland/tablet_v2: give wlr_tablet_* ownership to wlr_wl_seat

This commit is contained in:
Simon Zeni 2022-03-08 09:33:58 -05:00 committed by Kirill Primak
parent d3fb44314c
commit 56f7c000b5
4 changed files with 262 additions and 255 deletions

View file

@ -418,7 +418,7 @@ static bool backend_start(struct wlr_backend *backend) {
} }
if (wl->tablet_manager) { if (wl->tablet_manager) {
wl_add_tablet_seat(wl->tablet_manager, seat); init_seat_tablet(seat);
} }
} }

View file

@ -255,6 +255,9 @@ void destroy_wl_seats(struct wlr_wl_backend *wl) {
wl_keyboard_release(seat->wl_keyboard); wl_keyboard_release(seat->wl_keyboard);
wlr_keyboard_finish(&seat->wlr_keyboard); wlr_keyboard_finish(&seat->wlr_keyboard);
} }
if (seat->zwp_tablet_seat_v2) {
finish_seat_tablet(seat);
}
free(seat->name); free(seat->name);
assert(seat->wl_seat); assert(seat->wl_seat);
@ -281,9 +284,9 @@ bool wlr_input_device_is_wl(struct wlr_input_device *dev) {
case WLR_INPUT_DEVICE_TOUCH: case WLR_INPUT_DEVICE_TOUCH:
return dev->touch->impl == &touch_impl; return dev->touch->impl == &touch_impl;
case WLR_INPUT_DEVICE_TABLET_TOOL: 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: case WLR_INPUT_DEVICE_TABLET_PAD:
return dev->tablet_pad->impl == &tablet_pad_impl; return dev->tablet_pad->impl == &wl_tablet_pad_impl;
default: default:
return false; return false;
} }
@ -318,11 +321,13 @@ struct wlr_wl_input_device *create_wl_input_device(
free(dev); free(dev);
return NULL; return NULL;
case WLR_INPUT_DEVICE_TABLET_TOOL: case WLR_INPUT_DEVICE_TABLET_TOOL:
type_name = "tablet-tool"; wlr_log(WLR_ERROR, "can't create tablet tool wlr_wl_input_device");
break; free(dev);
return NULL;
case WLR_INPUT_DEVICE_TABLET_PAD: case WLR_INPUT_DEVICE_TABLET_PAD:
type_name = "tablet-pad"; wlr_log(WLR_ERROR, "can't create tablet pad wlr_wl_input_device");
break; free(dev);
return NULL;
default: default:
wlr_log(WLR_ERROR, "device not handled"); wlr_log(WLR_ERROR, "device not handled");
free(dev); 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"); wlr_log(WLR_ERROR, "wlr_wl_input_device has no pointer");
break; break;
case WLR_INPUT_DEVICE_TABLET_PAD: case WLR_INPUT_DEVICE_TABLET_PAD:
wlr_tablet_pad_finish(wlr_dev->tablet_pad); wlr_log(WLR_ERROR, "wlr_wl_input_device has no tablet pad");
free(wlr_dev->tablet_pad);
break; break;
case WLR_INPUT_DEVICE_TABLET_TOOL: case WLR_INPUT_DEVICE_TABLET_TOOL:
wlr_tablet_finish(wlr_dev->tablet); wlr_log(WLR_ERROR, "wlr_wl_input_device has no tablet_tool");
free(wlr_dev->tablet);
break; break;
case WLR_INPUT_DEVICE_TOUCH: case WLR_INPUT_DEVICE_TOUCH:
wlr_log(WLR_ERROR, "wlr_wl_input_device has no touch"); wlr_log(WLR_ERROR, "wlr_wl_input_device has no touch");

View file

@ -1,35 +1,25 @@
#ifndef _POSIX_C_SOURCE
#define _POSIX_C_SOURCE 200809L #define _POSIX_C_SOURCE 200809L
#endif
#include <wayland-util.h>
#include <assert.h> #include <assert.h>
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <wlr/interfaces/wlr_tablet_pad.h> #include <wlr/interfaces/wlr_tablet_pad.h>
#include <wlr/interfaces/wlr_tablet_tool.h> #include <wlr/interfaces/wlr_tablet_tool.h>
#include <wlr/types/wlr_input_device.h> #include <wlr/util/log.h>
#include "util/signal.h"
#include "util/time.h"
#include "wlr/util/log.h"
#include "tablet-unstable-v2-client-protocol.h"
#include "backend/wayland.h" #include "backend/wayland.h"
#include "util/signal.h"
#include "util/time.h"
struct wlr_wl_tablet_seat { #include "tablet-unstable-v2-client-protocol.h"
struct zwp_tablet_seat_v2 *tablet_seat;
};
struct wlr_wl_tablet_tool { struct tablet_tool {
/* static */ /* static */
struct zwp_tablet_tool_v2 *tool; struct wlr_wl_seat *seat;
struct wlr_tablet_tool wlr_tool;
/* semi-static */ /* semi-static */
struct wlr_wl_output *output; struct wlr_wl_output *output;
struct wlr_wl_input_device *tablet;
double pre_x, pre_y; double pre_x, pre_y;
/* per frame */ /* per frame */
@ -49,11 +39,11 @@ struct wlr_wl_tablet_tool {
bool is_down; bool is_down;
}; };
struct wlr_wl_tablet_pad_ring { struct tablet_pad_ring {
struct wl_list link; // wlr_wl_tablet_pad_group::rings struct wl_list link; // tablet_pad_group::rings
/* static */ /* static */
struct zwp_tablet_pad_ring_v2 *ring; struct zwp_tablet_pad_ring_v2 *ring;
struct wlr_wl_tablet_pad_group *group; struct tablet_pad_group *group;
size_t index; size_t index;
/* per frame */ /* per frame */
@ -62,10 +52,10 @@ struct wlr_wl_tablet_pad_ring {
bool stopped; bool stopped;
}; };
struct wlr_wl_tablet_pad_strip { struct tablet_pad_strip {
struct wl_list link; // wlr_wl_tablet_pad_group::strips struct wl_list link; // tablet_pad_group::strips
struct zwp_tablet_pad_strip_v2 *strip; struct zwp_tablet_pad_strip_v2 *strip;
struct wlr_wl_tablet_pad_group *group; struct tablet_pad_group *group;
size_t index; size_t index;
enum wlr_tablet_pad_strip_source source; enum wlr_tablet_pad_strip_source source;
@ -73,41 +63,41 @@ struct wlr_wl_tablet_pad_strip {
bool stopped; bool stopped;
}; };
struct wlr_wl_tablet_pad_group { struct tablet_pad_group {
struct zwp_tablet_pad_group_v2 *pad_group; struct zwp_tablet_pad_group_v2 *pad_group;
struct wlr_tablet_pad *pad; struct wlr_tablet_pad *pad;
unsigned int mode; unsigned int mode;
struct wlr_tablet_pad_group group; struct wlr_tablet_pad_group group;
struct wl_list rings; // wlr_wl_tablet_pad_ring::link struct wl_list rings; // tablet_pad_ring::link
struct wl_list strips; // wlr_wl_tablet_pad_strips::link struct wl_list strips; // tablet_pad_strips::link
}; };
static void handle_tablet_pad_ring_source(void *data, static void handle_tablet_pad_ring_source(void *data,
struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
uint32_t source) { uint32_t source) {
struct wlr_wl_tablet_pad_ring *ring = data; struct tablet_pad_ring *ring = data;
ring->source = source; ring->source = source;
} }
static void handle_tablet_pad_ring_angle(void *data, static void handle_tablet_pad_ring_angle(void *data,
struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
wl_fixed_t degrees) { 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); ring->angle = wl_fixed_to_double(degrees);
} }
static void handle_tablet_pad_ring_stop(void *data, static void handle_tablet_pad_ring_stop(void *data,
struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2) { 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; ring->stopped = true;
} }
static void handle_tablet_pad_ring_frame(void *data, static void handle_tablet_pad_ring_frame(void *data,
struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2,
uint32_t time) { uint32_t time) {
struct wlr_wl_tablet_pad_ring *ring = data; struct tablet_pad_ring *ring = data;
struct wlr_event_tablet_pad_ring evt = { struct wlr_event_tablet_pad_ring evt = {
.time_msec = time, .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, static void handle_tablet_pad_strip_source(void *data,
struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
uint32_t source) { uint32_t source) {
struct wlr_wl_tablet_pad_strip *strip = data; struct tablet_pad_strip *strip = data;
strip->source = source; strip->source = source;
} }
static void handle_tablet_pad_strip_position(void *data, static void handle_tablet_pad_strip_position(void *data,
struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
uint32_t position) { uint32_t position) {
struct wlr_wl_tablet_pad_strip *strip = data; struct tablet_pad_strip *strip = data;
strip->position = (double) position / 65536.0; strip->position = (double) position / 65536.0;
} }
static void handle_tablet_pad_strip_stop(void *data, static void handle_tablet_pad_strip_stop(void *data,
struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2) { 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; strip->stopped = true;
} }
static void handle_tablet_pad_strip_frame(void *data, static void handle_tablet_pad_strip_frame(void *data,
struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2,
uint32_t time) { uint32_t time) {
struct wlr_wl_tablet_pad_strip *strip = data; struct tablet_pad_strip *strip = data;
struct wlr_event_tablet_pad_strip evt = { struct wlr_event_tablet_pad_strip evt = {
.time_msec = time, .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, static void handle_tablet_pad_group_buttons(void *data,
struct zwp_tablet_pad_group_v2 *pad_group, struct zwp_tablet_pad_group_v2 *pad_group,
struct wl_array *buttons) { struct wl_array *buttons) {
struct wlr_wl_tablet_pad_group *group = data; struct tablet_pad_group *group = data;
free(group->group.buttons); free(group->group.buttons);
group->group.buttons = calloc(1, buttons->size); 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, static void handle_tablet_pad_group_modes(void *data,
struct zwp_tablet_pad_group_v2 *pad_group, uint32_t modes) { 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; 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, static void handle_tablet_pad_group_ring(void *data,
struct zwp_tablet_pad_group_v2 *pad_group, struct zwp_tablet_pad_group_v2 *pad_group,
struct zwp_tablet_pad_ring_v2 *ring) { struct zwp_tablet_pad_ring_v2 *ring) {
struct wlr_wl_tablet_pad_group *group = data; struct tablet_pad_group *group = data;
struct wlr_wl_tablet_pad_ring *tablet_ring = struct tablet_pad_ring *tablet_ring =
calloc(1, sizeof(struct wlr_wl_tablet_pad_ring)); calloc(1, sizeof(struct tablet_pad_ring));
if (!tablet_ring) { if (!tablet_ring) {
zwp_tablet_pad_ring_v2_destroy(ring); zwp_tablet_pad_ring_v2_destroy(ring);
return; return;
@ -237,9 +227,9 @@ static void handle_tablet_pad_group_ring(void *data,
static void handle_tablet_pad_group_strip(void *data, static void handle_tablet_pad_group_strip(void *data,
struct zwp_tablet_pad_group_v2 *pad_group, struct zwp_tablet_pad_group_v2 *pad_group,
struct zwp_tablet_pad_strip_v2 *strip) { struct zwp_tablet_pad_strip_v2 *strip) {
struct wlr_wl_tablet_pad_group *group = data; struct tablet_pad_group *group = data;
struct wlr_wl_tablet_pad_strip *tablet_strip = struct tablet_pad_strip *tablet_strip =
calloc(1, sizeof(struct wlr_wl_tablet_pad_strip)); calloc(1, sizeof(struct tablet_pad_strip));
if (!tablet_strip) { if (!tablet_strip) {
zwp_tablet_pad_strip_v2_destroy(strip); zwp_tablet_pad_strip_v2_destroy(strip);
return; return;
@ -263,25 +253,20 @@ static void handle_tablet_pad_group_done(void *data,
static void handle_tablet_pad_group_mode_switch(void *data, static void handle_tablet_pad_group_mode_switch(void *data,
struct zwp_tablet_pad_group_v2 *pad_group, struct zwp_tablet_pad_group_v2 *pad_group,
uint32_t time, uint32_t serial, uint32_t mode) { 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; group->mode = mode;
} }
/* This isn't in the listener, but keep the naming scheme around since the static void destroy_tablet_pad_group(struct tablet_pad_group *group) {
* 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) {
/* No need to remove the ::link on strips rings as long as we do *not* /* 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 */ * 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) { wl_list_for_each_safe(ring, tmp_ring, &group->rings, link) {
zwp_tablet_pad_ring_v2_destroy(ring->ring); zwp_tablet_pad_ring_v2_destroy(ring->ring);
free(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) { wl_list_for_each_safe(strip, tmp_strip, &group->strips, link) {
zwp_tablet_pad_strip_v2_destroy(strip->strip); zwp_tablet_pad_strip_v2_destroy(strip->strip);
free(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, static void handle_tablet_pad_group(void *data,
struct zwp_tablet_pad_v2 *zwp_tablet_pad, struct zwp_tablet_pad_v2 *zwp_tablet_pad,
struct zwp_tablet_pad_group_v2 *pad_group) { struct zwp_tablet_pad_group_v2 *pad_group) {
struct wlr_wl_input_device *dev = data; struct wlr_wl_seat *seat = data;
struct wlr_tablet_pad *pad = dev->wlr_input_device.tablet_pad; struct wlr_tablet_pad *pad = &seat->wlr_tablet_pad;
struct wlr_wl_tablet_pad_group *group = struct tablet_pad_group *group =
calloc(1, sizeof(struct wlr_wl_tablet_pad_group)); calloc(1, sizeof(struct tablet_pad_group));
if (!group) { if (!group) {
wlr_log_errno(WLR_ERROR, "failed to allocate tablet_pad_group");
zwp_tablet_pad_group_v2_destroy(pad_group); zwp_tablet_pad_group_v2_destroy(pad_group);
return; return;
} }
@ -331,20 +317,18 @@ static void handle_tablet_pad_group(void *data,
} }
static void handle_tablet_pad_path(void *data, static void handle_tablet_pad_path(void *data,
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, const char *path) {
const char *path) { struct wlr_wl_seat *seat = data;
struct wlr_wl_input_device *dev = data; struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad;
struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad;
char **dst = wl_array_add(&tablet_pad->paths, sizeof(char *)); char **dst = wl_array_add(&tablet_pad->paths, sizeof(char *));
*dst = strdup(path); *dst = strdup(path);
} }
static void handle_tablet_pad_buttons(void *data, static void handle_tablet_pad_buttons(void *data,
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, uint32_t buttons) {
uint32_t buttons) { struct wlr_wl_seat *seat = data;
struct wlr_wl_input_device *dev = data; struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad;
struct wlr_tablet_pad *tablet_pad = dev->wlr_input_device.tablet_pad;
tablet_pad->button_count = buttons; 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, static void handle_tablet_pad_button(void *data,
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
uint32_t time, uint32_t button, uint32_t state) { uint32_t time, uint32_t button, uint32_t state) {
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_event_tablet_pad_button evt = { struct wlr_event_tablet_pad_button evt = {
.time_msec = time, .time_msec = time,
.button = button, .button = button,
@ -363,28 +345,25 @@ static void handle_tablet_pad_button(void *data,
.group = 0, .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, static void handle_tablet_pad_done(void *data,
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) {
struct wlr_wl_input_device *dev = data; struct wlr_wl_seat *seat = data;
wlr_signal_emit_safe(&seat->backend->backend.events.new_input,
wlr_signal_emit_safe(&dev->backend->backend.events.new_input, &seat->wlr_tablet_pad.base);
&dev->wlr_input_device);
} }
static void handle_tablet_pad_enter(void *data, static void handle_tablet_pad_enter(void *data,
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
uint32_t serial, struct zwp_tablet_v2 *tablet_p, uint32_t serial, struct zwp_tablet_v2 *tablet_p,
struct wl_surface *surface) { struct wl_surface *surface) {
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; assert(seat->zwp_tablet_v2 == tablet_p);
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);
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, 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, static void handle_tablet_pad_removed(void *data,
struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { 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_tablet_pad *tablet_pad = &seat->wlr_tablet_pad;
struct wlr_wl_tablet_pad_group *group, *it; struct tablet_pad_group *group, *it;
wl_list_for_each_safe(group, it, &tablet_pad->groups, group.link) { 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); wlr_tablet_pad_finish(tablet_pad);
destroy_wl_input_device(dev); 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 = { 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, .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", .name = "wl-tablet-pad",
}; };
static void handle_pad_added(void *data, static void handle_pad_added(void *data,
struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,
struct zwp_tablet_pad_v2 *id) { struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) {
wlr_log(WLR_DEBUG, "New tablet pad");
struct wlr_wl_seat *seat = data; struct wlr_wl_seat *seat = data;
struct wlr_wl_input_device *dev = create_wl_input_device( if (seat->zwp_tablet_pad_v2 != NULL) {
seat, WLR_INPUT_DEVICE_TABLET_PAD); wlr_log(WLR_ERROR, "zwp_tablet_pad_v2 is already present");
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);
return; return;
} }
dev->resource = id; seat->zwp_tablet_pad_v2 = zwp_tablet_pad_v2;
struct wlr_input_device *wlr_dev = &dev->wlr_input_device; zwp_tablet_pad_v2_add_listener(zwp_tablet_pad_v2, &tablet_pad_listener,
wlr_dev->tablet_pad = calloc(1, sizeof(*wlr_dev->tablet_pad)); seat);
if (!wlr_dev->tablet_pad) { wlr_tablet_pad_init(&seat->wlr_tablet_pad, &wl_tablet_pad_impl,
/* This leaks a couple of server-sent resource ids. iirc this "wlr_tablet_v2");
* 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);
} }
static void handle_tablet_tool_done(void *data, static void handle_tablet_tool_done(void *data,
@ -459,7 +425,8 @@ static void handle_tablet_tool_done(void *data,
/* empty */ /* 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) { switch (type) {
case ZWP_TABLET_TOOL_V2_TYPE_PEN: case ZWP_TABLET_TOOL_V2_TYPE_PEN:
return WLR_TABLET_TOOL_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, static void handle_tablet_tool_type(void *data,
struct zwp_tablet_tool_v2 *id, struct zwp_tablet_tool_v2 *id, uint32_t tool_type) {
uint32_t tool_type) { struct tablet_tool *tool = data;
struct wlr_wl_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);
tool->wlr_tool.type = tablet_type_to_wlr_type(tool_type);
} }
static void handle_tablet_tool_serial(void *data, static void handle_tablet_tool_serial(void *data,
struct zwp_tablet_tool_v2 *id, struct zwp_tablet_tool_v2 *id, uint32_t high, uint32_t low) {
uint32_t high, uint32_t low) { struct tablet_tool *tool = data;
struct wlr_wl_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;
tool->wlr_tool.hardware_serial =
((uint64_t) high) << 32 | (uint64_t) low;
} }
static void handle_tablet_tool_id_wacom(void *data, static void handle_tablet_tool_id_wacom(void *data,
struct zwp_tablet_tool_v2 *id, struct zwp_tablet_tool_v2 *id, uint32_t high, uint32_t low) {
uint32_t high, uint32_t low) { struct tablet_tool *tool = data;
struct wlr_wl_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;
tool->wlr_tool.hardware_wacom =
((uint64_t) high) << 32 | (uint64_t) low;
} }
static void handle_tablet_tool_capability(void *data, static void handle_tablet_tool_capability(void *data,
struct zwp_tablet_tool_v2 *id, struct zwp_tablet_tool_v2 *id, uint32_t capability) {
uint32_t capability) { struct tablet_tool *tool = data;
struct wlr_wl_tablet_tool *tool = data; struct wlr_tablet_tool *wlr_tool = &tool->seat->wlr_tablet_tool;
enum zwp_tablet_tool_v2_capability cap = capability; /* One event is sent for each capability */
switch (capability) {
switch (cap) {
case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT: case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT:
tool->wlr_tool.tilt = true; wlr_tool->tilt = true;
break; break;
case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE: case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE:
tool->wlr_tool.pressure = true; wlr_tool->pressure = true;
break; break;
case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE: case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE:
tool->wlr_tool.distance = true; wlr_tool->distance = true;
break; break;
case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION: case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION:
tool->wlr_tool.rotation = true; wlr_tool->rotation = true;
break; break;
case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER: case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER:
tool->wlr_tool.slider = true; wlr_tool->slider = true;
break; break;
case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL: case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL:
tool->wlr_tool.wheel = true; wlr_tool->wheel = true;
break; break;
} }
} }
static void handle_tablet_tool_proximity_in(void *data, static void handle_tablet_tool_proximity_in(void *data,
struct zwp_tablet_tool_v2 *id, uint32_t serial, struct zwp_tablet_tool_v2 *id, uint32_t serial,
struct zwp_tablet_v2 *tablet_id, struct zwp_tablet_v2 *tablet_id, struct wl_surface *surface) {
struct wl_surface *surface) { struct tablet_tool *tool = data;
struct wlr_wl_tablet_tool *tool = data; assert(tablet_id == tool->seat->zwp_tablet_v2);
tool->is_in = true; tool->is_in = true;
tool->tablet = zwp_tablet_v2_get_user_data(tablet_id);
tool->output = wl_surface_get_user_data(surface); tool->output = wl_surface_get_user_data(surface);
} }
static void handle_tablet_tool_proximity_out(void *data, static void handle_tablet_tool_proximity_out(void *data,
struct zwp_tablet_tool_v2 *id) { struct zwp_tablet_tool_v2 *id) {
struct wlr_wl_tablet_tool *tool = data; struct tablet_tool *tool = data;
tool->is_out = true; tool->is_out = true;
tool->output = NULL; tool->output = NULL;
} }
static void handle_tablet_tool_down(void *data, static void handle_tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *id,
struct zwp_tablet_tool_v2 *id,
unsigned int serial) { unsigned int serial) {
struct wlr_wl_tablet_tool *tool = data; struct tablet_tool *tool = data;
tool->is_down = true; tool->is_down = true;
} }
static void handle_tablet_tool_up(void *data, static void handle_tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *id) {
struct zwp_tablet_tool_v2 *id) { struct tablet_tool *tool = data;
struct wlr_wl_tablet_tool *tool = data;
tool->is_up = true; tool->is_up = true;
} }
static void handle_tablet_tool_motion(void *data, static void handle_tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *id,
struct zwp_tablet_tool_v2 *id,
wl_fixed_t x, wl_fixed_t y) { 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; struct wlr_wl_output *output = tool->output;
assert(output); assert(output);
@ -580,58 +538,53 @@ static void handle_tablet_tool_motion(void *data,
} }
static void handle_tablet_tool_pressure(void *data, static void handle_tablet_tool_pressure(void *data,
struct zwp_tablet_tool_v2 *id, struct zwp_tablet_tool_v2 *id, uint32_t pressure) {
uint32_t pressure) { struct tablet_tool *tool = data;
struct wlr_wl_tablet_tool *tool = data;
tool->pressure = (double) pressure / 65535.0; tool->pressure = (double) pressure / 65535.0;
} }
static void handle_tablet_tool_distance(void *data, static void handle_tablet_tool_distance(void *data,
struct zwp_tablet_tool_v2 *id, struct zwp_tablet_tool_v2 *id, uint32_t distance) {
uint32_t distance) { struct tablet_tool *tool = data;
struct wlr_wl_tablet_tool *tool = data;
tool->distance = (double) distance / 65535.0; tool->distance = (double) distance / 65535.0;
} }
static void handle_tablet_tool_tilt(void *data, static void handle_tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *id,
struct zwp_tablet_tool_v2 *id,
wl_fixed_t x, wl_fixed_t y) { 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_x = wl_fixed_to_double(x);
tool->tilt_y = wl_fixed_to_double(y); tool->tilt_y = wl_fixed_to_double(y);
} }
static void handle_tablet_tool_rotation(void *data, static void handle_tablet_tool_rotation(void *data,
struct zwp_tablet_tool_v2 *id, struct zwp_tablet_tool_v2 *id, wl_fixed_t rotation) {
wl_fixed_t rotation) { struct tablet_tool *tool = data;
struct wlr_wl_tablet_tool *tool = data;
tool->rotation = wl_fixed_to_double(rotation); tool->rotation = wl_fixed_to_double(rotation);
} }
static void handle_tablet_tool_slider(void *data, static void handle_tablet_tool_slider(void *data, struct zwp_tablet_tool_v2 *id,
struct zwp_tablet_tool_v2 *id,
int slider) { int slider) {
struct wlr_wl_tablet_tool *tool = data; struct tablet_tool *tool = data;
tool->slider = (double) slider / 65535.0;; tool->slider = (double) slider / 65535.0;;
} }
// TODO: This looks wrong :/ // TODO: This looks wrong :/
static void handle_tablet_tool_wheel(void *data, static void handle_tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *id,
struct zwp_tablet_tool_v2 *id,
wl_fixed_t degree, int clicks) { 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); tool->wheel_delta = wl_fixed_to_double(degree);
} }
static void handle_tablet_tool_button(void *data, static void handle_tablet_tool_button(void *data,
struct zwp_tablet_tool_v2 *id, struct zwp_tablet_tool_v2 *id,
uint32_t serial, uint32_t button, uint32_t state) { uint32_t serial, uint32_t button, uint32_t state) {
struct wlr_wl_tablet_tool *tool = data; struct tablet_tool *tool = data;
struct wlr_tablet *tablet = tool->tablet->wlr_input_device.tablet; struct wlr_wl_seat *seat = tool->seat;
struct wlr_tablet *tablet = &seat->wlr_tablet;
struct wlr_event_tablet_tool_button evt = { struct wlr_event_tablet_tool_button evt = {
.device = &tool->tablet->wlr_input_device, .device = &tablet->base,
.tool = &tool->wlr_tool, .tool = &seat->wlr_tablet_tool,
.time_msec = get_current_time_msec(), .time_msec = get_current_time_msec(),
.button = button, .button = button,
.state = state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED ? .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); 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_out = tool->is_in = false;
tool->is_up = tool->is_down = false; tool->is_up = tool->is_down = false;
tool->x = tool->y = NAN; 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, static void handle_tablet_tool_frame(void *data,
struct zwp_tablet_tool_v2 *id, struct zwp_tablet_tool_v2 *id,
uint32_t time) { 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) { if (tool->is_out && tool->is_in) {
/* we got a tablet tool coming in and out of proximity before /* we got a tablet tool coming in and out of proximity before
* we could process it. Just ignore anything it did */ * we could process it. Just ignore anything it did */
goto clear_values; goto clear_values;
} }
struct wlr_tablet *tablet = tool->tablet->wlr_input_device.tablet; struct wlr_tablet *tablet = &seat->wlr_tablet;
if (tool->is_in) { if (tool->is_in) {
struct wlr_event_tablet_tool_proximity evt = { struct wlr_event_tablet_tool_proximity evt = {
.device = &tool->tablet->wlr_input_device, .device = &tablet->base,
.tool = &tool->wlr_tool, .tool = &seat->wlr_tablet_tool,
.time_msec = time, .time_msec = time,
.x = tool->x, .x = tool->x,
.y = tool->y, .y = tool->y,
@ -679,8 +634,8 @@ static void handle_tablet_tool_frame(void *data,
{ {
struct wlr_event_tablet_tool_axis evt = { struct wlr_event_tablet_tool_axis evt = {
.device = &tool->tablet->wlr_input_device, .device = &tablet->base,
.tool = &tool->wlr_tool, .tool = &seat->wlr_tablet_tool,
.time_msec = time, .time_msec = time,
.updated_axes = 0, .updated_axes = 0,
}; };
@ -742,8 +697,8 @@ static void handle_tablet_tool_frame(void *data,
* need to generate the time */ * need to generate the time */
if (tool->is_down) { if (tool->is_down) {
struct wlr_event_tablet_tool_tip evt = { struct wlr_event_tablet_tool_tip evt = {
.device = &tool->tablet->wlr_input_device, .device = &tablet->base,
.tool = &tool->wlr_tool, .tool = &seat->wlr_tablet_tool,
.time_msec = time, .time_msec = time,
.x = tool->x, .x = tool->x,
.y = tool->y, .y = tool->y,
@ -755,8 +710,8 @@ static void handle_tablet_tool_frame(void *data,
if (tool->is_up) { if (tool->is_up) {
struct wlr_event_tablet_tool_tip evt = { struct wlr_event_tablet_tool_tip evt = {
.device = &tool->tablet->wlr_input_device, .device = &tablet->base,
.tool = &tool->wlr_tool, .tool = &seat->wlr_tablet_tool,
.time_msec = time, .time_msec = time,
.x = tool->x, .x = tool->x,
.y = tool->y, .y = tool->y,
@ -768,8 +723,8 @@ static void handle_tablet_tool_frame(void *data,
if (tool->is_out) { if (tool->is_out) {
struct wlr_event_tablet_tool_proximity evt = { struct wlr_event_tablet_tool_proximity evt = {
.device = &tool->tablet->wlr_input_device, .device = &tablet->base,
.tool = &tool->wlr_tool, .tool = &seat->wlr_tablet_tool,
.time_msec = time, .time_msec = time,
.x = tool->x, .x = tool->x,
.y = tool->y, .y = tool->y,
@ -785,10 +740,12 @@ clear_values:
static void handle_tablet_tool_removed(void *data, static void handle_tablet_tool_removed(void *data,
struct zwp_tablet_tool_v2 *id) { 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); free(tool);
} }
@ -818,23 +775,34 @@ static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
static void handle_tool_added(void *data, static void handle_tool_added(void *data,
struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,
struct zwp_tablet_tool_v2 *id) { struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2) {
wlr_log(WLR_DEBUG, "New tablet tool"); struct wlr_wl_seat *seat = data;
struct wlr_wl_tablet_tool *tool = calloc(1, sizeof(*tool)); if (seat->zwp_tablet_tool_v2 != NULL) {
if (!tool) { wlr_log(WLR_ERROR, "zwp_tablet_tool_v2 already present");
zwp_tablet_tool_v2_destroy(id);
return; 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); 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, static void handle_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
const char *name) { const char *name) {
struct wlr_wl_input_device *dev = data; struct wlr_wl_seat *seat = data;
struct wlr_tablet *tablet = dev->wlr_input_device.tablet; struct wlr_tablet *tablet = &seat->wlr_tablet;
free(tablet->base.name); free(tablet->base.name);
tablet->base.name = strdup(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, static void handle_tablet_id(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
uint32_t vid, uint32_t pid) { uint32_t vid, uint32_t pid) {
struct wlr_wl_input_device *dev = data; struct wlr_wl_seat *seat = data;
dev->wlr_input_device.vendor = vid; struct wlr_tablet *tablet = &seat->wlr_tablet;
dev->wlr_input_device.product = pid;
tablet->base.vendor = vid;
tablet->base.product = pid;
} }
static void handle_tablet_path(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, static void handle_tablet_path(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
const char *path) { const char *path) {
struct wlr_wl_input_device *dev = data; struct wlr_wl_seat *seat = data;
struct wlr_tablet *tablet = dev->wlr_input_device.tablet; struct wlr_tablet *tablet = &seat->wlr_tablet;
char **dst = wl_array_add(&tablet->paths, sizeof(char *)); char **dst = wl_array_add(&tablet->paths, sizeof(char *));
*dst = strdup(path); *dst = strdup(path);
} }
static void handle_tablet_done(void *data, struct zwp_tablet_v2 *zwp_tablet_v2) { 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, wlr_signal_emit_safe(&seat->backend->backend.events.new_input,
&dev->wlr_input_device); &seat->wlr_tablet.base);
} }
static void handle_tablet_removed(void *data, static void handle_tablet_removed(void *data,
struct zwp_tablet_v2 *zwp_tablet_v2) { 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); wlr_tablet_finish(&seat->wlr_tablet);
destroy_wl_input_device(dev); zwp_tablet_v2_destroy(seat->zwp_tablet_v2);
seat->zwp_tablet_v2 = NULL;
} }
static const struct zwp_tablet_v2_listener tablet_listener = { 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, .removed = handle_tablet_removed,
}; };
const struct wlr_tablet_impl tablet_impl = { const struct wlr_tablet_impl wl_tablet_impl = {
.name = "wl-tablet-tool", .name = "wl-tablet-tool",
}; };
static void handle_tab_added(void *data, static void handle_tab_added(void *data,
struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2,
struct zwp_tablet_v2 *id) { struct zwp_tablet_v2 *zwp_tablet_v2) {
wlr_log(WLR_DEBUG, "New tablet");
struct wlr_wl_seat *seat = data; struct wlr_wl_seat *seat = data;
struct wlr_wl_input_device *dev = create_wl_input_device( if (seat->zwp_tablet_v2 != NULL) {
seat, WLR_INPUT_DEVICE_TABLET_TOOL); wlr_log(WLR_ERROR, "zwp_tablet_v2 already present");
if (!dev) {
zwp_tablet_v2_destroy(id);
return; return;
} }
dev->resource = id;
struct wlr_input_device *wlr_dev = &dev->wlr_input_device; seat->zwp_tablet_v2 = zwp_tablet_v2;
wlr_dev->tablet = calloc(1, sizeof(*wlr_dev->tablet)); zwp_tablet_v2_add_listener(zwp_tablet_v2, &tablet_listener, seat);
if (!wlr_dev->tablet) { wlr_tablet_init(&seat->wlr_tablet, &wl_tablet_impl, "wlr_tablet_v2");
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);
} }
static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { 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, .pad_added = handle_pad_added,
}; };
struct wlr_wl_tablet_seat *wl_add_tablet_seat( void init_seat_tablet(struct wlr_wl_seat *seat) {
struct zwp_tablet_manager_v2 *manager, struct zwp_tablet_manager_v2 *manager = seat->backend->tablet_manager;
struct wlr_wl_seat *seat) { assert(manager);
struct wlr_wl_tablet_seat *ret =
calloc(1, sizeof(struct wlr_wl_tablet_seat));
if (!(ret->tablet_seat = /**
zwp_tablet_manager_v2_get_tablet_seat(manager, seat->wl_seat))) { * TODO: multi tablet support
free(ret); * The wlr_wl_seat should support multiple tablet_v2 devices, but for
return NULL; * 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); &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;
} }

View file

@ -10,6 +10,8 @@
#include <wlr/render/wlr_renderer.h> #include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_keyboard.h> #include <wlr/types/wlr_keyboard.h>
#include <wlr/types/wlr_pointer.h> #include <wlr/types/wlr_pointer.h>
#include <wlr/types/wlr_tablet_pad.h>
#include <wlr/types/wlr_tablet_tool.h>
#include <wlr/types/wlr_touch.h> #include <wlr/types/wlr_touch.h>
#include <wlr/render/drm_format_set.h> #include <wlr/render/drm_format_set.h>
@ -132,6 +134,14 @@ struct wlr_wl_seat {
struct wl_touch *wl_touch; struct wl_touch *wl_touch;
struct wlr_touch wlr_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 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 finish_seat_pointer(struct wlr_wl_seat *seat);
void create_pointer(struct wlr_wl_seat *seat, struct wlr_wl_output *output); 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_input_device *create_wl_input_device(
struct wlr_wl_seat *seat, enum wlr_input_device_type type); 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); 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 wl_seat_listener seat_listener;
extern const struct wlr_pointer_impl wl_pointer_impl; extern const struct wlr_pointer_impl wl_pointer_impl;
extern const struct wlr_tablet_pad_impl tablet_pad_impl; extern const struct wlr_tablet_pad_impl wl_tablet_pad_impl;
extern const struct wlr_tablet_impl tablet_impl; extern const struct wlr_tablet_impl wl_tablet_impl;
struct wlr_wl_tablet_seat *wl_add_tablet_seat(
struct zwp_tablet_manager_v2 *manager,
struct wlr_wl_seat *seat);
#endif #endif