[PATCH v3 1/2] weston-info: Add support for tablet-unstable-v2

wl at ongy.net wl at ongy.net
Mon Apr 30 09:35:49 UTC 2018


From: Markus Ongyerth <wl at ongy.net>

This now prints each tablet seat with at least one tablet/pad/tool
attached.
For each tablet seat, each tablet, pad and tool is printed with as much
detail about the device as the protocol provides.
Seat info is stored to be referenced, because the protocol requires to
request a tablet_seat for each wl_seat and it's not guaranteed that the
tablet_v2_manager is available when seats are advertised.

Signed-off-by: Markus Ongyerth <wl at ongy.net>
Acked-by: Pekka Paalanen <pekka.paalanen at collabora.co.uk>
---
 Makefile.am           |  14 +-
 clients/weston-info.c | 845 ++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 854 insertions(+), 5 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 69ca6cba..ac0f5471 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -824,11 +824,13 @@ weston_simple_im_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
 weston_info_SOURCES = 					\
 	clients/weston-info.c				\
 	shared/helpers.h
-nodist_weston_info_SOURCES =				\
-	protocol/presentation-time-protocol.c		\
-	protocol/presentation-time-client-protocol.h	\
-	protocol/linux-dmabuf-unstable-v1-protocol.c	\
-	protocol/linux-dmabuf-unstable-v1-client-protocol.h
+nodist_weston_info_SOURCES =					\
+	protocol/presentation-time-protocol.c			\
+	protocol/presentation-time-client-protocol.h		\
+	protocol/linux-dmabuf-unstable-v1-protocol.c		\
+	protocol/linux-dmabuf-unstable-v1-client-protocol.h	\
+	protocol/tablet-unstable-v2-protocol.c			\
+	protocol/tablet-unstable-v2-client-protocol.h
 weston_info_LDADD = $(WESTON_INFO_LIBS) libshared.la
 weston_info_CFLAGS = $(AM_CFLAGS) $(CLIENT_CFLAGS)
 
@@ -888,6 +890,8 @@ BUILT_SOURCES +=					\
 	protocol/ivi-application-client-protocol.h	\
 	protocol/linux-dmabuf-unstable-v1-protocol.c	\
 	protocol/linux-dmabuf-unstable-v1-client-protocol.h		\
+	protocol/tablet-unstable-v2-protocol.c		\
+	protocol/tablet-unstable-v2-client-protocol.h			\
 	protocol/input-timestamps-unstable-v1-protocol.c		\
 	protocol/input-timestamps-unstable-v1-client-protocol.h
 
diff --git a/clients/weston-info.c b/clients/weston-info.c
index 386bd412..6606117a 100644
--- a/clients/weston-info.c
+++ b/clients/weston-info.c
@@ -41,6 +41,7 @@
 #include "shared/zalloc.h"
 #include "presentation-time-client-protocol.h"
 #include "linux-dmabuf-unstable-v1-client-protocol.h"
+#include "tablet-unstable-v2-client-protocol.h"
 
 typedef void (*print_info_t)(void *info);
 typedef void (*destroy_info_t)(void *info);
@@ -113,6 +114,7 @@ struct linux_dmabuf_info {
 
 struct seat_info {
 	struct global_info global;
+	struct wl_list global_link;
 	struct wl_seat *seat;
 	struct weston_info *info;
 
@@ -123,6 +125,75 @@ struct seat_info {
 	int32_t repeat_delay;
 };
 
+struct tablet_v2_path {
+	struct wl_list link;
+	char *path;
+};
+
+struct tablet_tool_info {
+	struct wl_list link;
+	struct zwp_tablet_tool_v2 *tool;
+
+	uint64_t hardware_serial;
+	uint64_t hardware_id_wacom;
+	enum zwp_tablet_tool_v2_type type;
+	
+	bool has_tilt;
+	bool has_pressure;
+	bool has_distance;
+	bool has_rotation;
+	bool has_slider;
+	bool has_wheel;
+};
+
+struct tablet_pad_group_info {
+	struct wl_list link;
+	struct zwp_tablet_pad_group_v2 *group;
+
+	uint32_t modes;
+	size_t button_count;
+	int *buttons;
+	size_t strips;
+	size_t rings;
+};
+
+struct tablet_pad_info {
+	struct wl_list link;
+	struct zwp_tablet_pad_v2 *pad;
+
+	uint32_t buttons;
+	struct wl_list paths;
+	struct wl_list groups;
+};
+
+struct tablet_info {
+	struct wl_list link;
+	struct zwp_tablet_v2 *tablet;
+
+	char *name;
+	uint32_t vid, pid;
+	struct wl_list paths;
+};
+
+struct tablet_seat_info {
+	struct wl_list link;
+
+	struct zwp_tablet_seat_v2 *seat;
+	struct seat_info *seat_info;
+
+	struct wl_list tablets;
+	struct wl_list tools;
+	struct wl_list pads;
+};
+
+struct tablet_v2_info {
+	struct global_info global;
+	struct zwp_tablet_manager_v2 *manager;
+	struct weston_info *info;
+
+	struct wl_list seats;
+};
+
 struct presentation_info {
 	struct global_info global;
 	struct wp_presentation *presentation;
@@ -136,6 +207,10 @@ struct weston_info {
 
 	struct wl_list infos;
 	bool roundtrip_needed;
+
+	/* required for tablet-unstable-v2 */
+	struct wl_list seats;
+	struct tablet_v2_info *tablet_info;
 };
 
 static void
@@ -455,6 +530,767 @@ destroy_seat_info(void *data)
 
 	if (seat->name != NULL)
 		free(seat->name);
+
+	wl_list_remove(&seat->global_link);
+}
+
+static const char *
+tablet_tool_type_to_str(enum zwp_tablet_tool_v2_type type)
+{
+	switch (type) {
+	case ZWP_TABLET_TOOL_V2_TYPE_PEN:
+		return "pen";
+	case ZWP_TABLET_TOOL_V2_TYPE_ERASER:
+		return "eraser";
+	case ZWP_TABLET_TOOL_V2_TYPE_BRUSH:
+		return "brush";
+	case ZWP_TABLET_TOOL_V2_TYPE_PENCIL:
+		return "pencil";
+	case ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH:
+		return "airbrush";
+	case ZWP_TABLET_TOOL_V2_TYPE_FINGER:
+		return "finger";
+	case ZWP_TABLET_TOOL_V2_TYPE_MOUSE:
+		return "mouse";
+	case ZWP_TABLET_TOOL_V2_TYPE_LENS:
+		return "lens";
+	}
+
+	return "Unknown type";
+}
+
+static void
+print_tablet_tool_info(const struct tablet_tool_info *info)
+{
+	printf("\t\ttablet_tool: %s\n", tablet_tool_type_to_str(info->type));
+	if (info->hardware_serial) {
+		printf("\t\t\thardware serial: %lx\n", info->hardware_serial);
+	}
+	if (info->hardware_id_wacom) {
+		printf("\t\t\thardware wacom: %lx\n", info->hardware_id_wacom);
+	}
+
+	printf("\t\t\tcapabilities:");
+
+	if (info->has_tilt) {
+		printf(" tilt");
+	}
+	if (info->has_pressure) {
+		printf(" pressure");
+	}
+	if (info->has_distance) {
+		printf(" distance");
+	}
+	if (info->has_rotation) {
+		printf(" rotation");
+	}
+	if (info->has_slider) {
+		printf(" slider");
+	}
+	if (info->has_wheel) {
+		printf(" wheel");
+	}
+	printf("\n");
+}
+
+static void
+destroy_tablet_tool_info(struct tablet_tool_info *info)
+{
+	wl_list_remove(&info->link);
+	zwp_tablet_tool_v2_destroy(info->tool);
+	free(info);
+}
+
+static void
+print_tablet_pad_group_info(const struct tablet_pad_group_info *info)
+{
+	size_t i;
+	printf("\t\t\tgroup:\n");
+	printf("\t\t\t\tmodes: %u\n", info->modes);
+	printf("\t\t\t\tstrips: %zu\n", info->strips);
+	printf("\t\t\t\trings: %zu\n", info->rings);
+	printf("\t\t\t\tbuttons:");
+
+	for (i = 0; i < info->button_count; ++i) {
+		printf(" %d", info->buttons[i]);
+	}
+
+	printf("\n");
+}
+
+static void
+destroy_tablet_pad_group_info(struct tablet_pad_group_info *info)
+{
+	wl_list_remove(&info->link);
+	zwp_tablet_pad_group_v2_destroy(info->group);
+
+	if (info->buttons) {
+		free(info->buttons);
+	}
+	free(info);
+}
+
+static void
+print_tablet_pad_info(const struct tablet_pad_info *info)
+{
+	const struct tablet_v2_path *path;
+	const struct tablet_pad_group_info *group;
+
+	printf("\t\tpad:\n");
+	printf("\t\t\tbuttons: %u\n", info->buttons);
+
+	wl_list_for_each(path, &info->paths, link) {
+		printf("\t\t\tpath: %s\n", path->path);
+	}
+
+	wl_list_for_each(group, &info->groups, link) {
+		print_tablet_pad_group_info(group);
+	}
+}
+
+static void
+destroy_tablet_pad_info(struct tablet_pad_info *info)
+{
+	struct tablet_v2_path *path;
+	struct tablet_v2_path *tmp_path;
+	struct tablet_pad_group_info *group;
+	struct tablet_pad_group_info *tmp_group;
+
+	wl_list_remove(&info->link);
+	zwp_tablet_pad_v2_destroy(info->pad);
+
+	wl_list_for_each_safe(path, tmp_path, &info->paths, link) {
+		wl_list_remove(&path->link);
+		free(path->path);
+		free(path);
+	}
+
+	wl_list_for_each_safe(group, tmp_group, &info->groups, link) {
+		destroy_tablet_pad_group_info(group);
+	}
+
+	free(info);
+}
+
+static void
+print_tablet_info(const struct tablet_info *info)
+{
+	const struct tablet_v2_path *path;
+
+	printf("\t\ttablet: %s\n", info->name);
+	printf("\t\t\tvendor: %u\n", info->vid);
+	printf("\t\t\tproduct: %u\n", info->pid);
+
+	wl_list_for_each(path, &info->paths, link) {
+		printf("\t\t\tpath: %s\n", path->path);
+	}
+}
+
+static void
+destroy_tablet_info(struct tablet_info *info)
+{
+	struct tablet_v2_path *path;
+	struct tablet_v2_path *tmp;
+
+	wl_list_remove(&info->link);
+	zwp_tablet_v2_destroy(info->tablet);
+
+	if (info->name) {
+		free(info->name);
+	}
+
+	wl_list_for_each_safe(path, tmp, &info->paths, link) {
+		wl_list_remove(&path->link);
+		free(path->path);
+		free(path);
+	}
+
+	free(info);
+}
+
+static void
+print_tablet_seat_info(const struct tablet_seat_info *info)
+{
+	const struct tablet_info *tablet;
+	const struct tablet_pad_info *pad;
+	const struct tablet_tool_info *tool;
+
+	printf("\ttablet_seat: %s\n", info->seat_info->name);
+
+	wl_list_for_each(tablet, &info->tablets, link) {
+		print_tablet_info(tablet);
+	}
+
+	wl_list_for_each(pad, &info->pads, link) {
+		print_tablet_pad_info(pad);
+	}
+
+	wl_list_for_each(tool, &info->tools, link) {
+		print_tablet_tool_info(tool);
+	}
+}
+
+static void
+destroy_tablet_seat_info(struct tablet_seat_info *info)
+{
+	struct tablet_info *tablet;
+	struct tablet_info *tmp_tablet;
+	struct tablet_pad_info *pad;
+	struct tablet_pad_info *tmp_pad;
+	struct tablet_tool_info *tool;
+	struct tablet_tool_info *tmp_tool;
+
+	wl_list_remove(&info->link);
+	zwp_tablet_seat_v2_destroy(info->seat);
+
+	wl_list_for_each_safe(tablet, tmp_tablet, &info->tablets, link) {
+		destroy_tablet_info(tablet);
+	}
+
+	wl_list_for_each_safe(pad, tmp_pad, &info->pads, link) {
+		destroy_tablet_pad_info(pad);
+	}
+
+	wl_list_for_each_safe(tool, tmp_tool, &info->tools, link) {
+		destroy_tablet_tool_info(tool);
+	}
+
+	free(info);
+}
+
+static void
+print_tablet_v2_info(void *data)
+{
+	struct tablet_v2_info *info = data;
+	struct tablet_seat_info *seat;
+	print_global_info(data);
+
+	wl_list_for_each(seat, &info->seats, link) {
+		/* Skip tablet_seats without a tablet, they are irrelevant */
+		if (wl_list_empty(&seat->pads) &&
+		    wl_list_empty(&seat->tablets) &&
+		    wl_list_empty(&seat->tools)) {
+			continue;
+		}
+
+		print_tablet_seat_info(seat);
+	}
+}
+
+static void
+destroy_tablet_v2_info(void *data)
+{
+	struct tablet_v2_info *info = data;
+	struct tablet_seat_info *seat;
+	struct tablet_seat_info *tmp;
+
+	zwp_tablet_manager_v2_destroy(info->manager);
+
+	wl_list_for_each_safe(seat, tmp, &info->seats, link) {
+		destroy_tablet_seat_info(seat);
+	}
+}
+
+static void
+handle_tablet_v2_tablet_tool_done(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+	/* don't bother waiting for this; there's no good reason a
+	 * compositor will wait more than one roundtrip before sending
+	 * these initial events. */
+}
+
+static void
+handle_tablet_v2_tablet_tool_removed(void *data, struct zwp_tablet_tool_v2 *tool)
+{
+	/* don't bother waiting for this; we never make any request either way. */
+}
+
+static void
+handle_tablet_v2_tablet_tool_type(void *data, struct zwp_tablet_tool_v2 *tool,
+                                  uint32_t tool_type)
+{
+	struct tablet_tool_info *info = data;
+	info->type = tool_type;
+}
+
+static void
+handle_tablet_v2_tablet_tool_hardware_serial(void *data,
+                                             struct zwp_tablet_tool_v2 *tool,
+                                             uint32_t serial_hi,
+                                             uint32_t serial_lo)
+{
+	struct tablet_tool_info *info = data;
+
+	info->hardware_serial = ((uint64_t) serial_hi) << 32 |
+		(uint64_t) serial_lo;
+}
+
+static void
+handle_tablet_v2_tablet_tool_hardware_id_wacom(void *data,
+                                               struct zwp_tablet_tool_v2 *tool,
+                                               uint32_t id_hi, uint32_t id_lo)
+{
+	struct tablet_tool_info *info = data;
+
+	info->hardware_id_wacom = ((uint64_t) id_hi) << 32 | (uint64_t) id_lo;
+}
+
+static void
+handle_tablet_v2_tablet_tool_capability(void *data,
+                                        struct zwp_tablet_tool_v2 *tool,
+                                        uint32_t capability)
+{
+	struct tablet_tool_info *info = data;
+	enum zwp_tablet_tool_v2_capability cap = capability;
+	
+	switch(cap) {
+	case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT:
+		info->has_tilt = true;
+		break;
+	case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE:
+		info->has_pressure = true;
+		break;
+	case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE:
+		info->has_distance = true;
+		break;
+	case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION:
+		info->has_rotation = true;
+		break;
+	case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER:
+		info->has_slider = true;
+		break;
+	case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL:
+		info->has_wheel = true;
+		break;
+	}
+}
+
+static void
+handle_tablet_v2_tablet_tool_proximity_in(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 uint32_t serial, struct zwp_tablet_v2 *tablet,
+                                 struct wl_surface *surface)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_proximity_out(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_down(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 uint32_t serial)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_up(void *data,
+                                struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2)
+{
+
+}
+
+
+static void
+handle_tablet_v2_tablet_tool_motion(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 wl_fixed_t x,
+                                 wl_fixed_t y)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_pressure(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 uint32_t pressure)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_distance(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 uint32_t distance)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_tilt(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 wl_fixed_t tilt_x,
+                                 wl_fixed_t tilt_y)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_rotation(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 wl_fixed_t degrees)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_slider(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 int32_t position)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_wheel(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 wl_fixed_t degrees,
+                                 int32_t clicks)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_button(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 uint32_t serial,
+                                 uint32_t button,
+                                 uint32_t state)
+{
+
+}
+
+static void
+handle_tablet_v2_tablet_tool_frame(void *data,
+                                 struct zwp_tablet_tool_v2 *zwp_tablet_tool_v2,
+                                 uint32_t time)
+{
+
+}
+
+static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = {
+	.removed = handle_tablet_v2_tablet_tool_removed,
+	.done = handle_tablet_v2_tablet_tool_done,
+	.type = handle_tablet_v2_tablet_tool_type,
+	.hardware_serial = handle_tablet_v2_tablet_tool_hardware_serial,
+	.hardware_id_wacom = handle_tablet_v2_tablet_tool_hardware_id_wacom,
+	.capability = handle_tablet_v2_tablet_tool_capability,
+
+	.proximity_in = handle_tablet_v2_tablet_tool_proximity_in,
+	.proximity_out = handle_tablet_v2_tablet_tool_proximity_out,
+	.down = handle_tablet_v2_tablet_tool_down,
+	.up = handle_tablet_v2_tablet_tool_up,
+
+	.motion = handle_tablet_v2_tablet_tool_motion,
+	.pressure = handle_tablet_v2_tablet_tool_pressure,
+	.distance = handle_tablet_v2_tablet_tool_distance,
+	.tilt = handle_tablet_v2_tablet_tool_tilt,
+	.rotation = handle_tablet_v2_tablet_tool_rotation,
+	.slider = handle_tablet_v2_tablet_tool_slider,
+	.wheel = handle_tablet_v2_tablet_tool_wheel,
+	.button = handle_tablet_v2_tablet_tool_button,
+	.frame = handle_tablet_v2_tablet_tool_frame,
+};
+
+static void add_tablet_v2_tablet_tool_info(void *data,
+                                     struct zwp_tablet_seat_v2 *tablet_seat_v2,
+                                     struct zwp_tablet_tool_v2 *tool)
+{
+	struct tablet_seat_info *tablet_seat = data;
+	struct tablet_tool_info *tool_info = xzalloc(sizeof *tool_info);
+
+	tool_info->tool = tool;
+	wl_list_insert(&tablet_seat->tools, &tool_info->link);
+
+	zwp_tablet_tool_v2_add_listener(tool, &tablet_tool_listener, tool_info);
+}
+
+static void
+handle_tablet_v2_tablet_pad_group_mode_switch(void *data,
+                       struct zwp_tablet_pad_group_v2 *zwp_tablet_pad_group_v2,
+                       uint32_t time, uint32_t serial, uint32_t mode)
+{
+	/* This shouldn't ever happen  */
+}
+
+static void
+handle_tablet_v2_tablet_pad_group_done(void *data,
+                                       struct zwp_tablet_pad_group_v2 *group)
+{
+	/* don't bother waiting for this; there's no good reason a
+	 * compositor will wait more than one roundtrip before sending
+	 * these initial events. */
+}
+
+static void
+handle_tablet_v2_tablet_pad_group_modes(void *data,
+                                        struct zwp_tablet_pad_group_v2 *group,
+                                        uint32_t modes)
+{
+	struct tablet_pad_group_info *info = data;
+	info->modes = modes;
+}
+
+static void
+handle_tablet_v2_tablet_pad_group_buttons(void *data,
+                                          struct zwp_tablet_pad_group_v2 *group,
+                                          struct wl_array *buttons)
+{
+	struct tablet_pad_group_info *info = data;
+
+	info->button_count = buttons->size / sizeof(int);
+	info->buttons = xzalloc(buttons->size);
+	memcpy(info->buttons, buttons->data, buttons->size);
+}
+
+static void
+handle_tablet_v2_tablet_pad_group_ring(void *data,
+                                       struct zwp_tablet_pad_group_v2 *group,
+                                       struct zwp_tablet_pad_ring_v2 *ring)
+{
+	struct tablet_pad_group_info *info = data;
+	++info->rings;
+
+	zwp_tablet_pad_ring_v2_destroy(ring);
+}
+
+static void
+handle_tablet_v2_tablet_pad_group_strip(void *data,
+                                        struct zwp_tablet_pad_group_v2 *group,
+                                        struct zwp_tablet_pad_strip_v2 *strip)
+{
+	struct tablet_pad_group_info *info = data;
+	++info->strips;
+
+	zwp_tablet_pad_strip_v2_destroy(strip);
+}
+
+static const struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = {
+	.buttons = handle_tablet_v2_tablet_pad_group_buttons,
+	.modes = handle_tablet_v2_tablet_pad_group_modes,
+	.ring = handle_tablet_v2_tablet_pad_group_ring,
+	.strip = handle_tablet_v2_tablet_pad_group_strip,
+	.done = handle_tablet_v2_tablet_pad_group_done,
+	.mode_switch = handle_tablet_v2_tablet_pad_group_mode_switch,
+};
+
+static void
+handle_tablet_v2_tablet_pad_group(void *data,
+                                  struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2,
+                                  struct zwp_tablet_pad_group_v2 *pad_group)
+{
+	struct tablet_pad_info *pad_info = data;
+	struct tablet_pad_group_info *group = xzalloc(sizeof *group);
+
+	wl_list_insert(&pad_info->groups, &group->link);
+	group->group = pad_group;
+	zwp_tablet_pad_group_v2_add_listener(pad_group,
+	                                     &tablet_pad_group_listener, group);
+}
+
+static void
+handle_tablet_v2_tablet_pad_path(void *data, struct zwp_tablet_pad_v2 *pad,
+                                 const char *path)
+{
+	struct tablet_pad_info *pad_info = data;
+	struct tablet_v2_path *path_elem = xzalloc(sizeof *path_elem);
+	path_elem->path = xstrdup(path);
+
+	wl_list_insert(&pad_info->paths, &path_elem->link);
+}
+
+static void
+handle_tablet_v2_tablet_pad_buttons(void *data, struct zwp_tablet_pad_v2 *pad,
+                                    uint32_t buttons)
+{
+	struct tablet_pad_info *pad_info = data;
+
+	pad_info->buttons = buttons;
+}
+
+static void
+handle_tablet_v2_tablet_pad_done(void *data, struct zwp_tablet_pad_v2 *pad)
+{
+	/* don't bother waiting for this; there's no good reason a
+	 * compositor will wait more than one roundtrip before sending
+	 * these initial events. */
+}
+
+static void
+handle_tablet_v2_tablet_pad_removed(void *data, struct zwp_tablet_pad_v2 *pad)
+{
+	/* don't bother waiting for this; We never make any request that's not
+	 * allowed to be issued either way. */
+}
+
+static void
+handle_tablet_v2_tablet_pad_button(void *data, struct zwp_tablet_pad_v2 *pad,
+                                   uint32_t time, uint32_t button, uint32_t state)
+{
+	/* we don't have a surface, so this can't ever happen */
+}
+
+static void
+handle_tablet_v2_tablet_pad_enter(void *data, struct zwp_tablet_pad_v2 *pad,
+                                  uint32_t serial,
+                                  struct zwp_tablet_v2 *tablet,
+                                  struct wl_surface *surface)
+{
+	/* we don't have a surface, so this can't ever happen */
+}
+
+static void
+handle_tablet_v2_tablet_pad_leave(void *data, struct zwp_tablet_pad_v2 *pad,
+		uint32_t serial, struct wl_surface *surface)
+{
+	/* we don't have a surface, so this can't ever happen */
+}
+
+static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = {
+	.group = handle_tablet_v2_tablet_pad_group,
+	.path = handle_tablet_v2_tablet_pad_path,
+	.buttons = handle_tablet_v2_tablet_pad_buttons,
+	.done = handle_tablet_v2_tablet_pad_done,
+	.removed = handle_tablet_v2_tablet_pad_removed,
+	.button = handle_tablet_v2_tablet_pad_button,
+	.enter = handle_tablet_v2_tablet_pad_enter,
+	.leave = handle_tablet_v2_tablet_pad_leave,
+};
+
+static void add_tablet_v2_tablet_pad_info(void *data,
+                                     struct zwp_tablet_seat_v2 *tablet_seat_v2,
+                                     struct zwp_tablet_pad_v2 *pad)
+{
+	struct tablet_seat_info *tablet_seat = data;
+	struct tablet_pad_info *pad_info = xzalloc(sizeof *pad_info);
+
+	wl_list_init(&pad_info->paths);
+	wl_list_init(&pad_info->groups);
+	pad_info->pad = pad;
+	wl_list_insert(&tablet_seat->pads, &pad_info->link);
+
+	zwp_tablet_pad_v2_add_listener(pad, &tablet_pad_listener, pad_info);
+}
+
+static void
+handle_tablet_v2_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
+                             const char *name)
+{
+	struct tablet_info *tablet_info = data;
+	tablet_info->name = xstrdup(name);
+}
+
+static void
+handle_tablet_v2_tablet_path(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
+                             const char *path)
+{
+	struct tablet_info *tablet_info = data;
+	struct tablet_v2_path *path_elem = xzalloc(sizeof *path_elem);
+	path_elem->path = xstrdup(path);
+
+	wl_list_insert(&tablet_info->paths, &path_elem->link);
+}
+
+static void
+handle_tablet_v2_tablet_id(void *data, struct zwp_tablet_v2 *zwp_tablet_v2,
+                           uint32_t vid, uint32_t pid)
+{
+	struct tablet_info *tablet_info = data;
+
+	tablet_info->vid = vid;
+	tablet_info->pid = pid;
+}
+
+static void
+handle_tablet_v2_tablet_done(void *data, struct zwp_tablet_v2 *zwp_tablet_v2)
+{
+	/* don't bother waiting for this; there's no good reason a
+	 * compositor will wait more than one roundtrip before sending
+	 * these initial events. */
+}
+
+static void
+handle_tablet_v2_tablet_removed(void *data, struct zwp_tablet_v2 *zwp_tablet_v2)
+{
+	/* don't bother waiting for this; We never make any request that's not
+	 * allowed to be issued either way. */
+}
+
+static const struct zwp_tablet_v2_listener tablet_listener = {
+	.name = handle_tablet_v2_tablet_name,
+	.id = handle_tablet_v2_tablet_id,
+	.path = handle_tablet_v2_tablet_path,
+	.done = handle_tablet_v2_tablet_done,
+	.removed = handle_tablet_v2_tablet_removed
+};
+
+static void
+add_tablet_v2_tablet_info(void *data, struct zwp_tablet_seat_v2 *tablet_seat_v2,
+                          struct zwp_tablet_v2 *tablet)
+{
+	struct tablet_seat_info *tablet_seat = data;
+	struct tablet_info *tablet_info = xzalloc(sizeof *tablet_info);
+
+	wl_list_init(&tablet_info->paths);
+	tablet_info->tablet = tablet;
+	wl_list_insert(&tablet_seat->tablets, &tablet_info->link);
+
+	zwp_tablet_v2_add_listener(tablet, &tablet_listener, tablet_info);
+}
+
+static const struct zwp_tablet_seat_v2_listener tablet_seat_listener =  {
+	.tablet_added = add_tablet_v2_tablet_info,
+	.pad_added = add_tablet_v2_tablet_pad_info,
+	.tool_added = add_tablet_v2_tablet_tool_info,
+};
+
+static void
+add_tablet_seat_info(struct tablet_v2_info *tablet_info, struct seat_info *seat)
+{
+	struct tablet_seat_info *tablet_seat = xzalloc(sizeof *tablet_seat);
+
+	wl_list_insert(&tablet_info->seats, &tablet_seat->link);
+	tablet_seat->seat = zwp_tablet_manager_v2_get_tablet_seat(
+		tablet_info->manager, seat->seat);
+	zwp_tablet_seat_v2_add_listener(tablet_seat->seat,
+		&tablet_seat_listener, tablet_seat);
+
+	wl_list_init(&tablet_seat->pads);
+	wl_list_init(&tablet_seat->tablets);
+	wl_list_init(&tablet_seat->tools);
+	tablet_seat->seat_info = seat;
+
+	tablet_info->info->roundtrip_needed = true;
+}
+
+static void
+add_tablet_v2_info(struct weston_info *info, uint32_t id, uint32_t version)
+{
+	struct seat_info *seat;
+	struct tablet_v2_info *tablet = xzalloc(sizeof *tablet);
+
+	wl_list_init(&tablet->seats);
+	tablet->info = info;
+
+	init_global_info(info, &tablet->global, id,
+		zwp_tablet_manager_v2_interface.name, version);
+	tablet->global.print = print_tablet_v2_info;
+	tablet->global.destroy = destroy_tablet_v2_info;
+
+	tablet->manager = wl_registry_bind(info->registry,
+		id, &zwp_tablet_manager_v2_interface, 1);
+
+	wl_list_for_each(seat, &info->seats, global_link) {
+		add_tablet_seat_info(tablet, seat);
+	}
+
+	info->tablet_info = tablet;
 }
 
 static void
@@ -477,6 +1313,11 @@ add_seat_info(struct weston_info *info, uint32_t id, uint32_t version)
 	seat->repeat_rate = seat->repeat_delay = -1;
 
 	info->roundtrip_needed = true;
+	wl_list_insert(&info->seats, &seat->global_link);
+
+	if (info->tablet_info) {
+		add_tablet_seat_info(info->tablet_info, seat);
+	}
 }
 
 static void
@@ -784,6 +1625,8 @@ global_handler(void *data, struct wl_registry *registry, uint32_t id,
 		add_output_info(info, id, version);
 	else if (!strcmp(interface, wp_presentation_interface.name))
 		add_presentation_info(info, id, version);
+	else if (!strcmp(interface, zwp_tablet_manager_v2_interface.name))
+		add_tablet_v2_info(info, id, version);
 	else
 		add_global_info(info, id, interface, version);
 }
@@ -837,7 +1680,9 @@ main(int argc, char **argv)
 		return -1;
 	}
 
+	info.tablet_info = NULL;
 	wl_list_init(&info.infos);
+	wl_list_init(&info.seats);
 
 	info.registry = wl_display_get_registry(info.display);
 	wl_registry_add_listener(info.registry, &registry_listener, &info);
-- 
2.17.0



More information about the wayland-devel mailing list