| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <assert.h>
 | 
					
						
							|  |  |  | #include <math.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <string.h>
 | 
					
						
							|  |  |  | #include <wlr/interfaces/wlr_tablet_pad.h>
 | 
					
						
							|  |  |  | #include <wlr/interfaces/wlr_tablet_tool.h>
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | #include <wlr/util/log.h>
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | #include "backend/wayland.h"
 | 
					
						
							| 
									
										
										
										
											2020-06-05 17:44:30 -04:00
										 |  |  | #include "util/time.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-12 14:55:17 +02:00
										 |  |  | #include "tablet-v2-client-protocol.h"
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | struct tablet_tool { | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	/* static */ | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	/* semi-static */ | 
					
						
							| 
									
										
										
										
											2020-06-01 15:54:32 -04:00
										 |  |  | 	struct wlr_wl_output *output; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	double pre_x, pre_y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* per frame */ | 
					
						
							|  |  |  | 	double x, y; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	double pressure; | 
					
						
							|  |  |  | 	double distance; | 
					
						
							|  |  |  | 	double tilt_x, tilt_y; | 
					
						
							|  |  |  | 	double rotation; | 
					
						
							|  |  |  | 	double slider; | 
					
						
							|  |  |  | 	double wheel_delta; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool is_in; | 
					
						
							|  |  |  | 	bool is_out; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bool is_up; | 
					
						
							|  |  |  | 	bool is_down; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | struct tablet_pad_ring { | 
					
						
							| 
									
										
										
										
											2023-10-02 22:06:44 +03:00
										 |  |  | 	struct wl_list link; // tablet_pad_group.rings
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	/* static */ | 
					
						
							|  |  |  | 	struct zwp_tablet_pad_ring_v2 *ring; | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_group *group; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	size_t index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* per frame */ | 
					
						
							|  |  |  | 	enum wlr_tablet_pad_ring_source source; | 
					
						
							|  |  |  | 	double angle; | 
					
						
							|  |  |  | 	bool stopped; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | struct tablet_pad_strip { | 
					
						
							| 
									
										
										
										
											2023-10-02 22:06:44 +03:00
										 |  |  | 	struct wl_list link; // tablet_pad_group.strips
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	struct zwp_tablet_pad_strip_v2 *strip; | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_group *group; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	size_t index; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	enum wlr_tablet_pad_strip_source source; | 
					
						
							|  |  |  | 	double position; | 
					
						
							|  |  |  | 	bool stopped; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | struct tablet_pad_group { | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	struct zwp_tablet_pad_group_v2 *pad_group; | 
					
						
							|  |  |  | 	struct wlr_tablet_pad *pad; | 
					
						
							|  |  |  | 	unsigned int mode; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	struct wlr_tablet_pad_group group; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-02 22:06:44 +03:00
										 |  |  | 	struct wl_list rings; // tablet_pad_ring.link
 | 
					
						
							|  |  |  | 	struct wl_list strips; // tablet_pad_strips.link
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_ring_source(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_ring_v2 *zwp_tablet_pad_ring_v2, | 
					
						
							|  |  |  | 		uint32_t source) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_ring *ring = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_ring *ring = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_ring *ring = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_ring *ring = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 15:16:04 -05:00
										 |  |  | 	struct wlr_tablet_pad_ring_event evt = { | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		.time_msec = time, | 
					
						
							|  |  |  | 		.source = ring->source, | 
					
						
							|  |  |  | 		.ring = ring->index, | 
					
						
							|  |  |  | 		.position = ring->angle, | 
					
						
							|  |  |  | 		.mode = ring->group->mode, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (ring->angle >= 0) { | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 		wl_signal_emit_mutable(&ring->group->pad->events.ring, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (ring->stopped) { | 
					
						
							|  |  |  | 		evt.position = -1; | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 		wl_signal_emit_mutable(&ring->group->pad->events.ring, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ring->angle = -1; | 
					
						
							|  |  |  | 	ring->stopped = false; | 
					
						
							|  |  |  | 	ring->source = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct zwp_tablet_pad_ring_v2_listener tablet_pad_ring_listener = { | 
					
						
							|  |  |  | 	.source = handle_tablet_pad_ring_source, | 
					
						
							|  |  |  | 	.angle = handle_tablet_pad_ring_angle, | 
					
						
							|  |  |  | 	.stop = handle_tablet_pad_ring_stop, | 
					
						
							|  |  |  | 	.frame = handle_tablet_pad_ring_frame, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_strip_source(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_strip_v2 *zwp_tablet_pad_strip_v2, | 
					
						
							|  |  |  | 		uint32_t source) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_strip *strip = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_strip *strip = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_strip *strip = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_strip *strip = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 15:16:04 -05:00
										 |  |  | 	struct wlr_tablet_pad_strip_event evt = { | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		.time_msec = time, | 
					
						
							|  |  |  | 		.source = strip->source, | 
					
						
							|  |  |  | 		.strip = strip->index, | 
					
						
							|  |  |  | 		.position = strip->position, | 
					
						
							|  |  |  | 		.mode = strip->group->mode, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (strip->position >= 0) { | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 		wl_signal_emit_mutable(&strip->group->pad->events.strip, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	if (strip->stopped) { | 
					
						
							|  |  |  | 		evt.position = -1; | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 		wl_signal_emit_mutable(&strip->group->pad->events.strip, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	strip->position = -1; | 
					
						
							|  |  |  | 	strip->stopped = false; | 
					
						
							|  |  |  | 	strip->source = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct zwp_tablet_pad_strip_v2_listener tablet_pad_strip_listener = { | 
					
						
							|  |  |  | 	.source = handle_tablet_pad_strip_source, | 
					
						
							|  |  |  | 	.position = handle_tablet_pad_strip_position, | 
					
						
							|  |  |  | 	.stop = handle_tablet_pad_strip_stop, | 
					
						
							|  |  |  | 	.frame = handle_tablet_pad_strip_frame, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_group_buttons(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_group_v2 *pad_group, | 
					
						
							|  |  |  | 		struct wl_array *buttons) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_group *group = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-07-14 06:48:22 +02:00
										 |  |  | 	free(group->group.buttons); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	group->group.buttons = calloc(1, buttons->size); | 
					
						
							|  |  |  | 	if (!group->group.buttons) { | 
					
						
							|  |  |  | 		// FIXME: Add actual error handling
 | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	group->group.button_count = buttons->size / sizeof(int); | 
					
						
							|  |  |  | 	memcpy(group->group.buttons, buttons->data, buttons->size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_group_modes(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_group_v2 *pad_group, uint32_t modes) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_group *group = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	group->group.mode_count = modes; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_group_ring(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_group_v2 *pad_group, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_ring_v2 *ring) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_group *group = data; | 
					
						
							| 
									
										
										
										
											2023-10-03 01:51:07 -04:00
										 |  |  | 	struct tablet_pad_ring *tablet_ring = calloc(1, sizeof(*tablet_ring)); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	if (!tablet_ring) { | 
					
						
							|  |  |  | 		zwp_tablet_pad_ring_v2_destroy(ring); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	tablet_ring->index = group->pad->ring_count++; | 
					
						
							|  |  |  | 	tablet_ring->group = group; | 
					
						
							| 
									
										
										
										
											2020-05-04 15:38:49 -04:00
										 |  |  | 	zwp_tablet_pad_ring_v2_add_listener(ring, &tablet_pad_ring_listener, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		tablet_ring); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	group->group.rings = realloc(group->group.rings, | 
					
						
							|  |  |  | 		++group->group.ring_count * sizeof(unsigned int)); | 
					
						
							|  |  |  | 	group->group.rings[group->group.ring_count - 1] = | 
					
						
							|  |  |  | 		tablet_ring->index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_group_strip(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_group_v2 *pad_group, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_strip_v2 *strip) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_group *group = data; | 
					
						
							| 
									
										
										
										
											2023-10-03 01:51:07 -04:00
										 |  |  | 	struct tablet_pad_strip *tablet_strip = calloc(1, sizeof(*tablet_strip)); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	if (!tablet_strip) { | 
					
						
							|  |  |  | 		zwp_tablet_pad_strip_v2_destroy(strip); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	tablet_strip->index = group->pad->strip_count++; | 
					
						
							|  |  |  | 	tablet_strip->group = group; | 
					
						
							| 
									
										
										
										
											2020-05-04 15:38:49 -04:00
										 |  |  | 	zwp_tablet_pad_strip_v2_add_listener(strip, &tablet_pad_strip_listener, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		tablet_strip); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	group->group.strips = realloc(group->group.strips, | 
					
						
							|  |  |  | 		++group->group.strip_count * sizeof(unsigned int)); | 
					
						
							|  |  |  | 	group->group.strips[group->group.strip_count - 1] = | 
					
						
							|  |  |  | 		tablet_strip->index; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_group_done(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_group_v2 *pad_group) { | 
					
						
							|  |  |  | 	/* Empty for now */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_group *group = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	group->mode = mode; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | static void destroy_tablet_pad_group(struct tablet_pad_group *group) { | 
					
						
							| 
									
										
										
										
											2023-10-02 22:06:44 +03:00
										 |  |  | 	/* No need to remove the link on strips rings as long as we do *not*
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	 * wl_list_remove on the wl_groups ring/strip attributes here */ | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_ring *ring, *tmp_ring; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	wl_list_for_each_safe(ring, tmp_ring, &group->rings, link) { | 
					
						
							|  |  |  | 		zwp_tablet_pad_ring_v2_destroy(ring->ring); | 
					
						
							|  |  |  | 		free(ring); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_pad_strip *strip, *tmp_strip; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	wl_list_for_each_safe(strip, tmp_strip, &group->strips, link) { | 
					
						
							|  |  |  | 		zwp_tablet_pad_strip_v2_destroy(strip->strip); | 
					
						
							|  |  |  | 		free(strip); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	zwp_tablet_pad_group_v2_destroy(group->pad_group); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-02 15:11:25 -05:00
										 |  |  | 	free(group->group.buttons); | 
					
						
							|  |  |  | 	free(group->group.strips); | 
					
						
							|  |  |  | 	free(group->group.rings); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	wl_list_remove(&group->group.link); | 
					
						
							| 
									
										
										
										
											2022-03-02 15:11:25 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	free(group); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct zwp_tablet_pad_group_v2_listener tablet_pad_group_listener = { | 
					
						
							|  |  |  | 	.buttons = handle_tablet_pad_group_buttons, | 
					
						
							|  |  |  | 	.modes = handle_tablet_pad_group_modes, | 
					
						
							|  |  |  | 	.ring = handle_tablet_pad_group_ring, | 
					
						
							|  |  |  | 	.strip = handle_tablet_pad_group_strip, | 
					
						
							|  |  |  | 	.done = handle_tablet_pad_group_done, | 
					
						
							|  |  |  | 	.mode_switch = handle_tablet_pad_group_mode_switch, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_group(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_v2 *zwp_tablet_pad, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_group_v2 *pad_group) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							|  |  |  | 	struct wlr_tablet_pad *pad = &seat->wlr_tablet_pad; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-03 01:51:07 -04:00
										 |  |  | 	struct tablet_pad_group *group = calloc(1, sizeof(*group)); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	if (!group) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		wlr_log_errno(WLR_ERROR, "failed to allocate tablet_pad_group"); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		zwp_tablet_pad_group_v2_destroy(pad_group); | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	group->pad_group = pad_group; | 
					
						
							|  |  |  | 	group->pad = pad; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wl_list_init(&group->rings); | 
					
						
							|  |  |  | 	wl_list_init(&group->strips); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	zwp_tablet_pad_group_v2_add_listener(pad_group, | 
					
						
							|  |  |  | 		&tablet_pad_group_listener, group); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wl_list_insert(&pad->groups, &group->group.link); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_path(void *data, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-01 10:09:35 +02:00
										 |  |  | 	char **dst = wl_array_add(&tablet_pad->paths, sizeof(char *)); | 
					
						
							|  |  |  | 	*dst = strdup(path); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_buttons(void *data, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tablet_pad->button_count = buttons; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							| 
									
										
										
										
											2022-03-09 15:16:04 -05:00
										 |  |  | 	struct wlr_tablet_pad_button_event evt = { | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		.time_msec = time, | 
					
						
							|  |  |  | 		.button = button, | 
					
						
							|  |  |  | 		.state = state, | 
					
						
							|  |  |  | 		.mode = 0, | 
					
						
							|  |  |  | 		.group = 0, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 	wl_signal_emit_mutable(&seat->wlr_tablet_pad.events.button, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_done(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 	wl_signal_emit_mutable(&seat->backend->backend.events.new_input, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		&seat->wlr_tablet_pad.base); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							|  |  |  | 	assert(seat->zwp_tablet_v2 == tablet_p); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 	wl_signal_emit_mutable(&seat->wlr_tablet_pad.events.attach_tablet, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		&seat->wlr_tablet_tool); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_leave(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2, | 
					
						
							|  |  |  | 		uint32_t serial, struct wl_surface *surface) { | 
					
						
							|  |  |  | 	/* Empty. Probably staying that way, unless we want to create/destroy
 | 
					
						
							|  |  |  | 	 * tablet on enter/leave events (ehh) */ | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_pad_removed(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_tablet_pad *tablet_pad = &seat->wlr_tablet_pad; | 
					
						
							|  |  |  | 	struct tablet_pad_group *group, *it; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	wl_list_for_each_safe(group, it, &tablet_pad->groups, group.link) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		destroy_tablet_pad_group(group); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	wlr_tablet_pad_finish(tablet_pad); | 
					
						
							|  |  |  | 	zwp_tablet_pad_v2_destroy(seat->zwp_tablet_pad_v2); | 
					
						
							|  |  |  | 	seat->zwp_tablet_pad_v2 = NULL; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct zwp_tablet_pad_v2_listener tablet_pad_listener = { | 
					
						
							|  |  |  | 	.group = handle_tablet_pad_group, | 
					
						
							|  |  |  | 	.path = handle_tablet_pad_path, | 
					
						
							|  |  |  | 	.buttons = handle_tablet_pad_buttons, | 
					
						
							|  |  |  | 	.button = handle_tablet_pad_button, | 
					
						
							|  |  |  | 	.done = handle_tablet_pad_done, | 
					
						
							|  |  |  | 	.enter = handle_tablet_pad_enter, | 
					
						
							|  |  |  | 	.leave = handle_tablet_pad_leave, | 
					
						
							|  |  |  | 	.removed = handle_tablet_pad_removed, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | const struct wlr_tablet_pad_impl wl_tablet_pad_impl = { | 
					
						
							| 
									
										
										
										
											2022-03-02 15:11:25 -05:00
										 |  |  | 	.name = "wl-tablet-pad", | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2022-02-09 14:08:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | static void handle_pad_added(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		struct zwp_tablet_pad_v2 *zwp_tablet_pad_v2) { | 
					
						
							| 
									
										
										
										
											2020-10-03 20:48:11 +02:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	if (seat->zwp_tablet_pad_v2 != NULL) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "zwp_tablet_pad_v2 is already present"); | 
					
						
							| 
									
										
										
										
											2024-06-20 11:12:01 +03:00
										 |  |  | 		zwp_tablet_pad_v2_destroy(zwp_tablet_pad_v2); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	seat->zwp_tablet_pad_v2 = zwp_tablet_pad_v2; | 
					
						
							|  |  |  | 	zwp_tablet_pad_v2_add_listener(zwp_tablet_pad_v2, &tablet_pad_listener, | 
					
						
							|  |  |  | 		seat); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	wlr_tablet_pad_init(&seat->wlr_tablet_pad, &wl_tablet_pad_impl, | 
					
						
							|  |  |  | 		"wlr_tablet_v2"); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_done(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_tool_v2 *id) { | 
					
						
							|  |  |  | 	/* empty */ | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2019-07-14 06:48:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | static enum wlr_tablet_tool_type tablet_type_to_wlr_type( | 
					
						
							|  |  |  | 		enum zwp_tablet_tool_v2_type type) { | 
					
						
							| 
									
										
										
										
											2019-07-14 06:48:22 +02:00
										 |  |  | 	switch (type) { | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	case ZWP_TABLET_TOOL_V2_TYPE_PEN: | 
					
						
							|  |  |  | 		return WLR_TABLET_TOOL_TYPE_PEN; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_TYPE_ERASER: | 
					
						
							|  |  |  | 		return WLR_TABLET_TOOL_TYPE_ERASER; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_TYPE_BRUSH: | 
					
						
							|  |  |  | 		return WLR_TABLET_TOOL_TYPE_BRUSH; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_TYPE_PENCIL: | 
					
						
							|  |  |  | 		return WLR_TABLET_TOOL_TYPE_PENCIL; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_TYPE_AIRBRUSH: | 
					
						
							|  |  |  | 		return WLR_TABLET_TOOL_TYPE_AIRBRUSH; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_TYPE_MOUSE: | 
					
						
							|  |  |  | 		return WLR_TABLET_TOOL_TYPE_MOUSE; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_TYPE_LENS: | 
					
						
							|  |  |  | 		return WLR_TABLET_TOOL_TYPE_LENS; | 
					
						
							| 
									
										
										
										
											2020-05-28 12:54:17 +02:00
										 |  |  | 	case ZWP_TABLET_TOOL_V2_TYPE_FINGER: | 
					
						
							|  |  |  | 		// unused, see:
 | 
					
						
							|  |  |  | 		// https://gitlab.freedesktop.org/wayland/wayland-protocols/-/issues/18
 | 
					
						
							|  |  |  | 		abort(); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-05-19 12:23:23 +02:00
										 |  |  | 	abort(); // unreachable
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_type(void *data, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		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); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_serial(void *data, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_id_wacom(void *data, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_capability(void *data, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		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; | 
					
						
							| 
									
										
										
										
											2020-05-04 15:38:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	/* One event is sent for each capability */ | 
					
						
							|  |  |  | 	switch (capability) { | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	case ZWP_TABLET_TOOL_V2_CAPABILITY_TILT: | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		wlr_tool->tilt = true; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_CAPABILITY_PRESSURE: | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		wlr_tool->pressure = true; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_CAPABILITY_DISTANCE: | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		wlr_tool->distance = true; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_CAPABILITY_ROTATION: | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		wlr_tool->rotation = true; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_CAPABILITY_SLIDER: | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		wlr_tool->slider = true; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	case ZWP_TABLET_TOOL_V2_CAPABILITY_WHEEL: | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		wlr_tool->wheel = true; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		break; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_proximity_in(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_tool_v2 *id, uint32_t serial, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		struct zwp_tablet_v2 *tablet_id, struct wl_surface *surface) { | 
					
						
							|  |  |  | 	struct tablet_tool *tool = data; | 
					
						
							|  |  |  | 	assert(tablet_id == tool->seat->zwp_tablet_v2); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-06-14 18:16:44 +02:00
										 |  |  | 	struct wlr_wl_output *output = get_wl_output_from_surface(tool->seat->backend, surface); | 
					
						
							|  |  |  | 	if (output == NULL) { | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->is_in = true; | 
					
						
							| 
									
										
										
										
											2023-06-14 18:16:44 +02:00
										 |  |  | 	tool->output = output; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_proximity_out(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_tool_v2 *id) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->is_out = true; | 
					
						
							| 
									
										
										
										
											2020-06-01 15:54:32 -04:00
										 |  |  | 	tool->output = NULL; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | static void handle_tablet_tool_down(void *data, struct zwp_tablet_tool_v2 *id, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		unsigned int serial) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->is_down = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | static void handle_tablet_tool_up(void *data, struct zwp_tablet_tool_v2 *id) { | 
					
						
							|  |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->is_up = true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | static void handle_tablet_tool_motion(void *data, struct zwp_tablet_tool_v2 *id, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		wl_fixed_t x, wl_fixed_t y) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2020-06-01 15:54:32 -04:00
										 |  |  | 	struct wlr_wl_output *output = tool->output; | 
					
						
							|  |  |  | 	assert(output); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	tool->x = wl_fixed_to_double(x) / output->wlr_output.width; | 
					
						
							|  |  |  | 	tool->y = wl_fixed_to_double(y) / output->wlr_output.height; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_pressure(void *data, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		struct zwp_tablet_tool_v2 *id, uint32_t pressure) { | 
					
						
							|  |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->pressure = (double) pressure / 65535.0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_distance(void *data, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		struct zwp_tablet_tool_v2 *id, uint32_t distance) { | 
					
						
							|  |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->distance = (double) distance / 65535.0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | static void handle_tablet_tool_tilt(void *data, struct zwp_tablet_tool_v2 *id, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		wl_fixed_t x, wl_fixed_t y) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->tilt_x = wl_fixed_to_double(x); | 
					
						
							|  |  |  | 	tool->tilt_y = wl_fixed_to_double(y); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_rotation(void *data, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		struct zwp_tablet_tool_v2 *id, wl_fixed_t rotation) { | 
					
						
							|  |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->rotation = wl_fixed_to_double(rotation); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | static void handle_tablet_tool_slider(void *data, struct zwp_tablet_tool_v2 *id, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		int slider) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->slider = (double) slider / 65535.0;; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // TODO: This looks wrong :/
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | static void handle_tablet_tool_wheel(void *data, struct zwp_tablet_tool_v2 *id, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		wl_fixed_t degree, int clicks) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_tool *tool = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	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) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_tool *tool = data; | 
					
						
							|  |  |  | 	struct wlr_wl_seat *seat = tool->seat; | 
					
						
							|  |  |  | 	struct wlr_tablet *tablet = &seat->wlr_tablet; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-09 15:43:28 -05:00
										 |  |  | 	struct wlr_tablet_tool_button_event evt = { | 
					
						
							|  |  |  | 		.tablet = tablet, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		.tool = &seat->wlr_tablet_tool, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		.time_msec = get_current_time_msec(), | 
					
						
							|  |  |  | 		.button = button, | 
					
						
							|  |  |  | 		.state = state == ZWP_TABLET_TOOL_V2_BUTTON_STATE_RELEASED ? | 
					
						
							|  |  |  | 			WLR_BUTTON_RELEASED : WLR_BUTTON_PRESSED, | 
					
						
							|  |  |  | 	}; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 	wl_signal_emit_mutable(&tablet->events.button, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | static void clear_tablet_tool_values(struct tablet_tool *tool) { | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	tool->is_out = tool->is_in = false; | 
					
						
							|  |  |  | 	tool->is_up = tool->is_down = false; | 
					
						
							|  |  |  | 	tool->x = tool->y = NAN; | 
					
						
							|  |  |  | 	tool->pressure = NAN; | 
					
						
							|  |  |  | 	tool->distance = NAN; | 
					
						
							|  |  |  | 	tool->tilt_x = tool->tilt_y = NAN; | 
					
						
							|  |  |  | 	tool->rotation = NAN; | 
					
						
							|  |  |  | 	tool->slider = NAN; | 
					
						
							|  |  |  | 	tool->wheel_delta = NAN; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_frame(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_tool_v2 *id, | 
					
						
							|  |  |  | 		uint32_t time) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct tablet_tool *tool = data; | 
					
						
							|  |  |  | 	struct wlr_wl_seat *seat = tool->seat; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	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; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_tablet *tablet = &seat->wlr_tablet; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if (tool->is_in) { | 
					
						
							| 
									
										
										
										
											2022-03-09 15:43:28 -05:00
										 |  |  | 		struct wlr_tablet_tool_proximity_event evt = { | 
					
						
							|  |  |  | 			.tablet = tablet, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 			.tool = &seat->wlr_tablet_tool, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 			.time_msec = time, | 
					
						
							|  |  |  | 			.x = tool->x, | 
					
						
							|  |  |  | 			.y = tool->y, | 
					
						
							|  |  |  | 			.state = WLR_TABLET_TOOL_PROXIMITY_IN, | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2020-05-04 15:38:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 		wl_signal_emit_mutable(&tablet->events.proximity, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2022-03-09 15:43:28 -05:00
										 |  |  | 		struct wlr_tablet_tool_axis_event evt = { | 
					
						
							|  |  |  | 			.tablet = tablet, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 			.tool = &seat->wlr_tablet_tool, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 			.time_msec = time, | 
					
						
							|  |  |  | 			.updated_axes = 0, | 
					
						
							|  |  |  | 		}; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!isnan(tool->x) && !tool->is_in) { | 
					
						
							|  |  |  | 			evt.updated_axes |= WLR_TABLET_TOOL_AXIS_X; | 
					
						
							|  |  |  | 			evt.x = tool->x; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!isnan(tool->y) && !tool->is_in) { | 
					
						
							|  |  |  | 			evt.updated_axes |= WLR_TABLET_TOOL_AXIS_Y; | 
					
						
							|  |  |  | 			evt.y = tool->y; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!isnan(tool->pressure)) { | 
					
						
							|  |  |  | 			evt.updated_axes |= WLR_TABLET_TOOL_AXIS_PRESSURE; | 
					
						
							|  |  |  | 			evt.pressure = tool->pressure; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!isnan(tool->distance)) { | 
					
						
							|  |  |  | 			evt.updated_axes |= WLR_TABLET_TOOL_AXIS_DISTANCE; | 
					
						
							|  |  |  | 			evt.distance = tool->distance; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!isnan(tool->tilt_x)) { | 
					
						
							|  |  |  | 			evt.updated_axes |= WLR_TABLET_TOOL_AXIS_TILT_X; | 
					
						
							|  |  |  | 			evt.tilt_x = tool->tilt_x; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!isnan(tool->tilt_y)) { | 
					
						
							|  |  |  | 			evt.updated_axes |= WLR_TABLET_TOOL_AXIS_TILT_Y; | 
					
						
							|  |  |  | 			evt.tilt_y = tool->tilt_y; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!isnan(tool->rotation)) { | 
					
						
							|  |  |  | 			evt.updated_axes |= WLR_TABLET_TOOL_AXIS_ROTATION; | 
					
						
							|  |  |  | 			evt.rotation = tool->rotation; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!isnan(tool->slider)) { | 
					
						
							|  |  |  | 			evt.updated_axes |= WLR_TABLET_TOOL_AXIS_SLIDER; | 
					
						
							|  |  |  | 			evt.slider = tool->slider; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!isnan(tool->wheel_delta)) { | 
					
						
							|  |  |  | 			evt.updated_axes |= WLR_TABLET_TOOL_AXIS_WHEEL; | 
					
						
							|  |  |  | 			evt.wheel_delta = tool->wheel_delta; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (evt.updated_axes) { | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 			wl_signal_emit_mutable(&tablet->events.axis, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* This will always send down then up if we got both.
 | 
					
						
							|  |  |  | 	 * Maybe we should send them right away, in case we get up then both in | 
					
						
							|  |  |  | 	 * series? | 
					
						
							|  |  |  | 	 * Downside: Here we have the frame time, if we sent right away, we | 
					
						
							|  |  |  | 	 * need to generate the time */ | 
					
						
							|  |  |  | 	if (tool->is_down) { | 
					
						
							| 
									
										
										
										
											2022-03-09 15:43:28 -05:00
										 |  |  | 		struct wlr_tablet_tool_tip_event evt = { | 
					
						
							|  |  |  | 			.tablet = tablet, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 			.tool = &seat->wlr_tablet_tool, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 			.time_msec = time, | 
					
						
							|  |  |  | 			.x = tool->x, | 
					
						
							|  |  |  | 			.y = tool->y, | 
					
						
							|  |  |  | 			.state = WLR_TABLET_TOOL_TIP_DOWN, | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2020-05-04 15:38:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 		wl_signal_emit_mutable(&tablet->events.tip, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (tool->is_up) { | 
					
						
							| 
									
										
										
										
											2022-03-09 15:43:28 -05:00
										 |  |  | 		struct wlr_tablet_tool_tip_event evt = { | 
					
						
							|  |  |  | 			.tablet = tablet, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 			.tool = &seat->wlr_tablet_tool, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 			.time_msec = time, | 
					
						
							|  |  |  | 			.x = tool->x, | 
					
						
							|  |  |  | 			.y = tool->y, | 
					
						
							|  |  |  | 			.state = WLR_TABLET_TOOL_TIP_UP, | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2020-05-04 15:38:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 		wl_signal_emit_mutable(&tablet->events.tip, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (tool->is_out) { | 
					
						
							| 
									
										
										
										
											2022-03-09 15:43:28 -05:00
										 |  |  | 		struct wlr_tablet_tool_proximity_event evt = { | 
					
						
							|  |  |  | 			.tablet = tablet, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 			.tool = &seat->wlr_tablet_tool, | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 			.time_msec = time, | 
					
						
							|  |  |  | 			.x = tool->x, | 
					
						
							|  |  |  | 			.y = tool->y, | 
					
						
							|  |  |  | 			.state = WLR_TABLET_TOOL_PROXIMITY_OUT, | 
					
						
							|  |  |  | 		}; | 
					
						
							| 
									
										
										
										
											2020-05-04 15:38:49 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 		wl_signal_emit_mutable(&tablet->events.proximity, &evt); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | clear_values: | 
					
						
							|  |  |  | 	clear_tablet_tool_values(tool); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_tool_removed(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_tool_v2 *id) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	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; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	free(tool); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct zwp_tablet_tool_v2_listener tablet_tool_listener = { | 
					
						
							|  |  |  | 	.removed = handle_tablet_tool_removed, | 
					
						
							|  |  |  | 	.done = handle_tablet_tool_done, | 
					
						
							|  |  |  | 	.type = handle_tablet_tool_type, | 
					
						
							|  |  |  | 	.hardware_serial = handle_tablet_tool_serial, | 
					
						
							|  |  |  | 	.hardware_id_wacom = handle_tablet_tool_id_wacom, | 
					
						
							|  |  |  | 	.capability = handle_tablet_tool_capability, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.proximity_in = handle_tablet_tool_proximity_in, | 
					
						
							|  |  |  | 	.proximity_out = handle_tablet_tool_proximity_out, | 
					
						
							|  |  |  | 	.down = handle_tablet_tool_down, | 
					
						
							|  |  |  | 	.up = handle_tablet_tool_up, | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	.motion = handle_tablet_tool_motion, | 
					
						
							|  |  |  | 	.pressure = handle_tablet_tool_pressure, | 
					
						
							|  |  |  | 	.distance = handle_tablet_tool_distance, | 
					
						
							|  |  |  | 	.tilt = handle_tablet_tool_tilt, | 
					
						
							|  |  |  | 	.rotation = handle_tablet_tool_rotation, | 
					
						
							|  |  |  | 	.slider = handle_tablet_tool_slider, | 
					
						
							|  |  |  | 	.wheel = handle_tablet_tool_wheel, | 
					
						
							|  |  |  | 	.button = handle_tablet_tool_button, | 
					
						
							|  |  |  | 	.frame = handle_tablet_tool_frame, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tool_added(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		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"); | 
					
						
							| 
									
										
										
										
											2024-06-20 11:12:01 +03:00
										 |  |  | 		zwp_tablet_tool_v2_destroy(zwp_tablet_tool_v2); | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wl_signal_init(&seat->wlr_tablet_tool.events.destroy); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-03 01:51:07 -04:00
										 |  |  | 	struct tablet_tool *tool = calloc(1, sizeof(*tool)); | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	if (tool == NULL) { | 
					
						
							|  |  |  | 		wlr_log_errno(WLR_ERROR, "failed to allocate tablet_tool"); | 
					
						
							|  |  |  | 		zwp_tablet_tool_v2_destroy(zwp_tablet_tool_v2); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tool->seat = seat; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	clear_tablet_tool_values(tool); | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	seat->zwp_tablet_tool_v2 = zwp_tablet_tool_v2; | 
					
						
							|  |  |  | 	zwp_tablet_tool_v2_add_listener(seat->zwp_tablet_tool_v2, &tablet_tool_listener, | 
					
						
							|  |  |  | 		tool); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_name(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, | 
					
						
							|  |  |  | 		const char *name) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							|  |  |  | 	struct wlr_tablet *tablet = &seat->wlr_tablet; | 
					
						
							| 
									
										
										
										
											2019-07-14 06:48:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-11 11:47:56 +01:00
										 |  |  | 	free(tablet->base.name); | 
					
						
							|  |  |  | 	tablet->base.name = strdup(name); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_id(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, | 
					
						
							|  |  |  | 		uint32_t vid, uint32_t pid) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							|  |  |  | 	struct wlr_tablet *tablet = &seat->wlr_tablet; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-02-29 12:20:02 +01:00
										 |  |  | 	tablet->usb_vendor_id = vid; | 
					
						
							|  |  |  | 	tablet->usb_product_id = pid; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_path(void *data, struct zwp_tablet_v2 *zwp_tablet_v2, | 
					
						
							|  |  |  | 		const char *path) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							|  |  |  | 	struct wlr_tablet *tablet = &seat->wlr_tablet; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-07-01 10:09:35 +02:00
										 |  |  | 	char **dst = wl_array_add(&tablet->paths, sizeof(char *)); | 
					
						
							|  |  |  | 	*dst = strdup(path); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_done(void *data, struct zwp_tablet_v2 *zwp_tablet_v2) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-18 07:16:16 -04:00
										 |  |  | 	wl_signal_emit_mutable(&seat->backend->backend.events.new_input, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		&seat->wlr_tablet.base); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static void handle_tablet_removed(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_v2 *zwp_tablet_v2) { | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	wlr_tablet_finish(&seat->wlr_tablet); | 
					
						
							|  |  |  | 	zwp_tablet_v2_destroy(seat->zwp_tablet_v2); | 
					
						
							|  |  |  | 	seat->zwp_tablet_v2 = NULL; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct zwp_tablet_v2_listener tablet_listener = { | 
					
						
							|  |  |  | 	.name = handle_tablet_name, | 
					
						
							|  |  |  | 	.id = handle_tablet_id, | 
					
						
							|  |  |  | 	.path = handle_tablet_path, | 
					
						
							|  |  |  | 	.done = handle_tablet_done, | 
					
						
							|  |  |  | 	.removed = handle_tablet_removed, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | const struct wlr_tablet_impl wl_tablet_impl = { | 
					
						
							| 
									
										
										
										
											2022-03-02 15:58:44 -05:00
										 |  |  | 	.name = "wl-tablet-tool", | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2022-02-09 14:08:20 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | static void handle_tab_added(void *data, | 
					
						
							|  |  |  | 		struct zwp_tablet_seat_v2 *zwp_tablet_seat_v2, | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 		struct zwp_tablet_v2 *zwp_tablet_v2) { | 
					
						
							| 
									
										
										
										
											2020-10-03 20:48:11 +02:00
										 |  |  | 	struct wlr_wl_seat *seat = data; | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	if (seat->zwp_tablet_v2 != NULL) { | 
					
						
							|  |  |  | 		wlr_log(WLR_ERROR, "zwp_tablet_v2 already present"); | 
					
						
							| 
									
										
										
										
											2024-06-20 11:12:01 +03:00
										 |  |  | 		zwp_tablet_v2_destroy(zwp_tablet_v2); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 		return; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-07-14 06:48:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	seat->zwp_tablet_v2 = zwp_tablet_v2; | 
					
						
							|  |  |  | 	zwp_tablet_v2_add_listener(zwp_tablet_v2, &tablet_listener, seat); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	wlr_tablet_init(&seat->wlr_tablet, &wl_tablet_impl, "wlr_tablet_v2"); | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const struct zwp_tablet_seat_v2_listener tablet_seat_listener = { | 
					
						
							|  |  |  | 	.tablet_added = handle_tab_added, | 
					
						
							|  |  |  | 	.tool_added = handle_tool_added, | 
					
						
							|  |  |  | 	.pad_added = handle_pad_added, | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | void init_seat_tablet(struct wlr_wl_seat *seat) { | 
					
						
							|  |  |  | 	struct zwp_tablet_manager_v2 *manager = seat->backend->tablet_manager; | 
					
						
							|  |  |  | 	assert(manager); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/**
 | 
					
						
							|  |  |  | 	 * 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; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	zwp_tablet_seat_v2_add_listener(seat->zwp_tablet_seat_v2, | 
					
						
							| 
									
										
										
										
											2020-10-03 20:48:11 +02:00
										 |  |  | 		&tablet_seat_listener, seat); | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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); | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-03-08 09:33:58 -05:00
										 |  |  | 	zwp_tablet_seat_v2_destroy(seat->zwp_tablet_seat_v2); | 
					
						
							|  |  |  | 	seat->zwp_tablet_seat_v2 = NULL; | 
					
						
							| 
									
										
										
										
											2019-05-10 08:36:19 +02:00
										 |  |  | } |