commit 614a694

Michael Forney  ·  2023-07-01 20:56:06 +0000 UTC
parent 70922f9
pointer: Implement protocol version 8
3 files changed,  +106, -27
+65, -6
  1@@ -32,6 +32,7 @@
  2 #include "util.h"
  3 #include "cursor/cursor_data.h"
  4 
  5+#include <assert.h>
  6 #include <stdio.h>
  7 #include <wld/wld.h>
  8 
  9@@ -204,19 +205,53 @@ client_handle_button(struct pointer_handler *handler, uint32_t time, struct butt
 10 }
 11 
 12 static bool
 13-client_handle_axis(struct pointer_handler *handler, uint32_t time, uint32_t axis, wl_fixed_t amount)
 14+client_handle_axis(struct pointer_handler *handler, uint32_t time, enum wl_pointer_axis axis, enum wl_pointer_axis_source source, wl_fixed_t value, int value120)
 15 {
 16 	struct pointer *pointer = wl_container_of(handler, pointer, client_handler);
 17 	struct wl_resource *resource;
 18+	int ver;
 19 
 20 	if (wl_list_empty(&pointer->focus.active))
 21 		return false;
 22 
 23-	wl_resource_for_each (resource, &pointer->focus.active)
 24-		wl_pointer_send_axis(resource, time, axis, amount);
 25+	if (pointer->client_axis_source != -1) {
 26+		assert(pointer->client_axis_source == source);
 27+		source = -1;
 28+	} else {
 29+		pointer->client_axis_source = source;
 30+	}
 31+
 32+	wl_resource_for_each (resource, &pointer->focus.active) {
 33+		ver = wl_resource_get_version(resource);
 34+		if (source != -1 && ver >= WL_POINTER_AXIS_SOURCE_SINCE_VERSION)
 35+			wl_pointer_send_axis_source(resource, source);
 36+		if (value120) {
 37+			if (ver >= WL_POINTER_AXIS_VALUE120_SINCE_VERSION)
 38+				wl_pointer_send_axis_value120(resource, axis, value120);
 39+			else if (ver >= WL_POINTER_AXIS_DISCRETE_SINCE_VERSION)
 40+				wl_pointer_send_axis_discrete(resource, axis, value120 / 120);
 41+		}
 42+		if (value)
 43+			wl_pointer_send_axis(resource, time, axis, value);
 44+		else if (ver >= WL_POINTER_AXIS_STOP_SINCE_VERSION)
 45+			wl_pointer_send_axis_stop(resource, time, axis);
 46+	}
 47 	return true;
 48 }
 49 
 50+static void
 51+client_handle_frame(struct pointer_handler *handler)
 52+{
 53+	struct pointer *pointer = wl_container_of(handler, pointer, client_handler);
 54+	struct wl_resource *resource;
 55+
 56+	wl_resource_for_each (resource, &pointer->focus.active) {
 57+		if (wl_resource_get_version(resource) >= WL_POINTER_FRAME_SINCE_VERSION)
 58+			wl_pointer_send_frame(resource);
 59+	}
 60+	pointer->client_axis_source = -1;
 61+}
 62+
 63 bool
 64 pointer_initialize(struct pointer *pointer)
 65 {
 66@@ -232,6 +267,9 @@ pointer_initialize(struct pointer *pointer)
 67 	pointer->client_handler.motion = client_handle_motion;
 68 	pointer->client_handler.button = client_handle_button;
 69 	pointer->client_handler.axis = client_handle_axis;
 70+	pointer->client_handler.frame = client_handle_frame;
 71+	pointer->client_handler.pending = false;
 72+	pointer->client_axis_source = -1;
 73 	wl_list_init(&pointer->handlers);
 74 	wl_list_insert(&pointer->handlers, &pointer->client_handler.link);
 75 	wl_array_init(&pointer->buttons);
 76@@ -385,6 +423,7 @@ pointer_handle_button(struct pointer *pointer, uint32_t time, uint32_t value, ui
 77 				if (button->handler) {
 78 					button->press.serial = serial;
 79 					button->handler->button(button->handler, time, button, state);
 80+					button->handler->pending = true;
 81 				}
 82 
 83 				array_remove(&pointer->buttons, button, sizeof(*button));
 84@@ -404,6 +443,7 @@ pointer_handle_button(struct pointer *pointer, uint32_t time, uint32_t value, ui
 85 		wl_list_for_each (handler, &pointer->handlers, link) {
 86 			if (handler->button && handler->button(handler, time, button, state)) {
 87 				button->handler = handler;
 88+				handler->pending = true;
 89 				break;
 90 			}
 91 		}
 92@@ -411,13 +451,15 @@ pointer_handle_button(struct pointer *pointer, uint32_t time, uint32_t value, ui
 93 }
 94 
 95 void
 96-pointer_handle_axis(struct pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t amount)
 97+pointer_handle_axis(struct pointer *pointer, uint32_t time, enum wl_pointer_axis axis, enum wl_pointer_axis_source source, wl_fixed_t value, int value120)
 98 {
 99 	struct pointer_handler *handler;
100 
101 	wl_list_for_each (handler, &pointer->handlers, link) {
102-		if (handler->axis && handler->axis(handler, time, axis, amount))
103+		if (handler->axis && handler->axis(handler, time, axis, source, value, value120)) {
104+			handler->pending = true;
105 			break;
106+		}
107 	}
108 }
109 
110@@ -435,8 +477,25 @@ pointer_handle_absolute_motion(struct pointer *pointer, uint32_t time, wl_fixed_
111 	clip_position(pointer, x, y);
112 
113 	wl_list_for_each (handler, &pointer->handlers, link) {
114-		if (handler->motion && handler->motion(handler, time, pointer->x, pointer->y))
115+		if (handler->motion && handler->motion(handler, time, pointer->x, pointer->y)) {
116+			handler->pending = true;
117 			break;
118+		}
119+	}
120+
121+	update_cursor(pointer);
122+}
123+
124+void
125+pointer_handle_frame(struct pointer *pointer)
126+{
127+	struct pointer_handler *handler;
128+
129+	wl_list_for_each (handler, &pointer->handlers, link) {
130+		if (handler->pending && handler->frame) {
131+			handler->frame(handler);
132+			handler->pending = false;
133+		}
134 	}
135 
136 	update_cursor(pointer);
+6, -2
 1@@ -38,8 +38,10 @@ struct button {
 2 struct pointer_handler {
 3 	bool (*motion)(struct pointer_handler *handler, uint32_t time, wl_fixed_t x, wl_fixed_t y);
 4 	bool (*button)(struct pointer_handler *handler, uint32_t time, struct button *button, uint32_t state);
 5-	bool (*axis)(struct pointer_handler *handler, uint32_t time, enum wl_pointer_axis axis, wl_fixed_t amount);
 6+	bool (*axis)(struct pointer_handler *handler, uint32_t time, enum wl_pointer_axis axis, enum wl_pointer_axis_source source, wl_fixed_t value, int value120);
 7+	void (*frame)(struct pointer_handler *handler);
 8 
 9+	int pending;
10 	struct wl_list link;
11 };
12 
13@@ -64,6 +66,7 @@ struct pointer {
14 	struct wl_array buttons;
15 	struct wl_list handlers;
16 	struct pointer_handler client_handler;
17+	enum wl_pointer_axis_source client_axis_source;
18 
19 	wl_fixed_t x, y;
20 	pixman_region32_t region;
21@@ -79,8 +82,9 @@ struct button *pointer_get_button(struct pointer *pointer, uint32_t serial);
22 
23 struct wl_resource *pointer_bind(struct pointer *pointer, struct wl_client *client, uint32_t version, uint32_t id);
24 void pointer_handle_button(struct pointer *pointer, uint32_t time, uint32_t button, uint32_t state);
25-void pointer_handle_axis(struct pointer *pointer, uint32_t time, uint32_t axis, wl_fixed_t amount);
26+void pointer_handle_axis(struct pointer *pointer, uint32_t time, enum wl_pointer_axis axis, enum wl_pointer_axis_source source, wl_fixed_t value, int value120);
27 void pointer_handle_relative_motion(struct pointer *pointer, uint32_t time, wl_fixed_t dx, wl_fixed_t dy);
28 void pointer_handle_absolute_motion(struct pointer *pointer, uint32_t time, wl_fixed_t x, wl_fixed_t y);
29+void pointer_handle_frame(struct pointer *pointer);
30 
31 #endif
+35, -19
  1@@ -220,18 +220,6 @@ device_capabilities(struct libinput_device *device)
  2 	return capabilities;
  3 }
  4 
  5-static void
  6-handle_libinput_axis_event(struct seat *seat, struct libinput_event_pointer *event, enum libinput_pointer_axis axis)
  7-{
  8-	wl_fixed_t amount;
  9-
 10-	if (!libinput_event_pointer_has_axis(event, axis))
 11-		return;
 12-
 13-	amount = wl_fixed_from_double(libinput_event_pointer_get_axis_value(event, axis));
 14-	pointer_handle_axis(&seat->pointer, libinput_event_pointer_get_time(event), axis, amount);
 15-}
 16-
 17 static int
 18 handle_libinput_data(int fd, uint32_t mask, void *data)
 19 {
 20@@ -244,8 +232,10 @@ handle_libinput_data(int fd, uint32_t mask, void *data)
 21 		struct libinput_event_keyboard *k;
 22 		struct libinput_event_pointer *p;
 23 	} event;
 24-	wl_fixed_t x, y;
 25+	wl_fixed_t x, y, value;
 26 	uint32_t time, key, state;
 27+	enum wl_pointer_axis_source source;
 28+	int value120;
 29 
 30 	if (libinput_dispatch(seat->libinput) != 0) {
 31 		WARNING("libinput_dispatch failed: %s\n", strerror(errno));
 32@@ -273,6 +263,7 @@ handle_libinput_data(int fd, uint32_t mask, void *data)
 33 			x = wl_fixed_from_double(libinput_event_pointer_get_dx(event.p));
 34 			y = wl_fixed_from_double(libinput_event_pointer_get_dy(event.p));
 35 			pointer_handle_relative_motion(&seat->pointer, time, x, y);
 36+			pointer_handle_frame(&seat->pointer);
 37 			break;
 38 		case LIBINPUT_EVENT_POINTER_MOTION_ABSOLUTE:
 39 			screen = wl_container_of(swc.screens.next, screen, link);
 40@@ -282,6 +273,7 @@ handle_libinput_data(int fd, uint32_t mask, void *data)
 41 			x = wl_fixed_from_double(libinput_event_pointer_get_absolute_x_transformed(event.p, rect->width));
 42 			y = wl_fixed_from_double(libinput_event_pointer_get_absolute_y_transformed(event.p, rect->height));
 43 			pointer_handle_absolute_motion(&seat->pointer, time, x, y);
 44+			pointer_handle_frame(&seat->pointer);
 45 			break;
 46 		case LIBINPUT_EVENT_POINTER_BUTTON:
 47 			event.p = libinput_event_get_pointer_event(generic_event);
 48@@ -292,20 +284,44 @@ handle_libinput_data(int fd, uint32_t mask, void *data)
 49 			if (state == LIBINPUT_BUTTON_STATE_PRESSED) {
 50 		                /* qemu generates GEAR_UP/GEAR_DOWN events on scroll, so pass
 51 				 * those through as axis events. */
 52+				source = WL_POINTER_AXIS_SOURCE_WHEEL;
 53 				switch (key) {
 54 				case BTN_GEAR_DOWN:
 55-					pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(10));
 56+					pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, source, wl_fixed_from_int(10), 120);
 57 					break;
 58 				case BTN_GEAR_UP:
 59-					pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, wl_fixed_from_int(-10));
 60+					pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, source, wl_fixed_from_int(-10), -120);
 61 					break;
 62 				}
 63 			}
 64+			pointer_handle_frame(&seat->pointer);
 65 			break;
 66-		case LIBINPUT_EVENT_POINTER_AXIS:
 67+		case LIBINPUT_EVENT_POINTER_SCROLL_WHEEL:
 68+			source = WL_POINTER_AXIS_SOURCE_WHEEL;
 69+			goto scroll;
 70+		case LIBINPUT_EVENT_POINTER_SCROLL_FINGER:
 71+			source = WL_POINTER_AXIS_SOURCE_FINGER;
 72+			goto scroll;
 73+		case LIBINPUT_EVENT_POINTER_SCROLL_CONTINUOUS:
 74+			source = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
 75+			goto scroll;
 76+		scroll:
 77 			event.p = libinput_event_get_pointer_event(generic_event);
 78-			handle_libinput_axis_event(seat, event.p, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
 79-			handle_libinput_axis_event(seat, event.p, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
 80+			time = libinput_event_pointer_get_time(event.p);
 81+			value120 = 0;
 82+			if (libinput_event_pointer_has_axis(event.p, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL)) {
 83+				value = wl_fixed_from_double(libinput_event_pointer_get_scroll_value(event.p, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL));
 84+				if (source == WL_POINTER_AXIS_SOURCE_WHEEL)
 85+					value120 = libinput_event_pointer_get_scroll_value_v120(event.p, LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL);
 86+				pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_VERTICAL_SCROLL, source, value, value120);
 87+			}
 88+			if (libinput_event_pointer_has_axis(event.p, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL)) {
 89+				value = wl_fixed_from_double(libinput_event_pointer_get_scroll_value(event.p, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL));
 90+				if (source == WL_POINTER_AXIS_SOURCE_WHEEL)
 91+					value120 = libinput_event_pointer_get_scroll_value_v120(event.p, LIBINPUT_POINTER_AXIS_SCROLL_HORIZONTAL);
 92+				pointer_handle_axis(&seat->pointer, time, WL_POINTER_AXIS_HORIZONTAL_SCROLL, source, value, value120);
 93+			}
 94+			pointer_handle_frame(&seat->pointer);
 95 			break;
 96 		default:
 97 			break;
 98@@ -382,7 +398,7 @@ seat_create(struct wl_display *display, const char *seat_name)
 99 		ERROR("Could not allocate seat name string\n");
100 		goto error1;
101 	}
102-	seat->global = wl_global_create(display, &wl_seat_interface, 4, seat, &bind_seat);
103+	seat->global = wl_global_create(display, &wl_seat_interface, 8, seat, &bind_seat);
104 	if (!seat->global)
105 		goto error2;
106 	seat->capabilities = 0;