[weston,v5,1/4] compositor: Implement zwp_pointer_gesture_[pinch|swipe]_v1 interfaces

Submitted by Carlos Garnacho on Jan. 27, 2017, 3:41 p.m.

Details

Message ID 20170127154146.15590-1-carlosg@gnome.org
State New
Headers show
Series "Series without cover letter" ( rev: 1 ) in Wayland

Not browsing as part of any series.

Commit Message

Carlos Garnacho Jan. 27, 2017, 3:41 p.m.
These are obtained from the _wl_pointer_gestures global resource,
although each pointer will maintain the resources list and additional
information for the pinch/swipe gestures. The lifetime and focus
management of gesture resources is thus attached to the pointer.

The translation of libinput events into zwp_pointer_gesture_pinch/swipe_v1
ones is fairly straight forward.

It could be deemed convenient in the future that gesture events
go through the pointer grab interface. It could be useful in case
we want gesture support in any weston_pointer_grab_interface, it is
just not needed at the moment, so has been left aside.

v5: Update to zwp namespace. Apply previous reviews' remaining issues.
v4: Use seat->pointer_device_count for pointer detection
v3: Update commit log. Merged protocol implementation and input handling
    together. Reworked above weston_pointer_client.
v2: Update to use standalone XML.

Signed-off-by: Carlos Garnacho <carlosg@gnome.org>
---
 Makefile.am                 |   4 +-
 libweston/compositor.c      |   2 +
 libweston/compositor.h      |  12 +++
 libweston/input.c           | 216 +++++++++++++++++++++++++++++++++++++++++++-
 libweston/libinput-device.c | 141 +++++++++++++++++++++++++++++
 5 files changed, 373 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/Makefile.am b/Makefile.am
index 7743158..d41acd6 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -178,7 +178,9 @@  nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES =				\
 	protocol/relative-pointer-unstable-v1-protocol.c		\
 	protocol/relative-pointer-unstable-v1-server-protocol.h		\
 	protocol/pointer-constraints-unstable-v1-protocol.c		\
-	protocol/pointer-constraints-unstable-v1-server-protocol.h
+	protocol/pointer-constraints-unstable-v1-server-protocol.h	\
+	protocol/pointer-gestures-unstable-v1-protocol.c		\
+	protocol/pointer-gestures-unstable-v1-server-protocol.h
 
 BUILT_SOURCES += $(nodist_libweston_@LIBWESTON_MAJOR@_la_SOURCES)
 
diff --git a/libweston/compositor.c b/libweston/compositor.c
index 5e23277..142cf58 100644
--- a/libweston/compositor.c
+++ b/libweston/compositor.c
@@ -5059,6 +5059,8 @@  weston_compositor_create(struct wl_display *display, void *user_data)
 	if (weston_input_init(ec) != 0)
 		goto fail;
 
+	weston_pointer_gestures_init(ec);
+
 	wl_list_init(&ec->view_list);
 	wl_list_init(&ec->plane_list);
 	wl_list_init(&ec->layer_list);
diff --git a/libweston/compositor.h b/libweston/compositor.h
index b049c98..e46c47c 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -341,6 +341,8 @@  struct weston_pointer_client {
 	struct wl_client *client;
 	struct wl_list pointer_resources;
 	struct wl_list relative_pointer_resources;
+	struct wl_list swipe_gesture_resources;
+	struct wl_list pinch_gesture_resources;
 };
 
 struct weston_pointer {
@@ -1350,6 +1352,13 @@  void
 notify_touch_cancel(struct weston_seat *seat);
 
 void
+notify_pointer_swipe(struct weston_seat *seat, uint32_t time, int cancelled,
+		     int fingers, wl_fixed_t dx, wl_fixed_t dy, int gesture_type);
+void
+notify_pointer_pinch(struct weston_seat *seat, uint32_t time, int cancelled,
+		     int fingers, wl_fixed_t dx, wl_fixed_t dy,
+		     wl_fixed_t scale, wl_fixed_t rotation_diff, int gesture_type);
+void
 weston_layer_entry_insert(struct weston_layer_entry *list,
 			  struct weston_layer_entry *entry);
 void
@@ -1700,6 +1709,9 @@  weston_compositor_set_xkb_rule_names(struct weston_compositor *ec,
 void
 weston_compositor_xkb_destroy(struct weston_compositor *ec);
 
+void
+weston_pointer_gestures_init(struct weston_compositor *ec);
+
 /* String literal of spaces, the same width as the timestamp. */
 #define STAMP_SPACE "               "
 
diff --git a/libweston/input.c b/libweston/input.c
index 4fedc55..b881856 100644
--- a/libweston/input.c
+++ b/libweston/input.c
@@ -41,6 +41,7 @@ 
 #include "compositor.h"
 #include "relative-pointer-unstable-v1-server-protocol.h"
 #include "pointer-constraints-unstable-v1-server-protocol.h"
+#include "pointer-gestures-unstable-v1-server-protocol.h"
 
 enum pointer_constraint_type {
 	POINTER_CONSTRAINT_TYPE_LOCK,
@@ -97,6 +98,8 @@  weston_pointer_client_create(struct wl_client *client)
 	pointer_client->client = client;
 	wl_list_init(&pointer_client->pointer_resources);
 	wl_list_init(&pointer_client->relative_pointer_resources);
+	wl_list_init(&pointer_client->swipe_gesture_resources);
+	wl_list_init(&pointer_client->pinch_gesture_resources);
 
 	return pointer_client;
 }
@@ -111,7 +114,9 @@  static bool
 weston_pointer_client_is_empty(struct weston_pointer_client *pointer_client)
 {
 	return (wl_list_empty(&pointer_client->pointer_resources) &&
-		wl_list_empty(&pointer_client->relative_pointer_resources));
+		wl_list_empty(&pointer_client->relative_pointer_resources) &&
+		wl_list_empty(&pointer_client->swipe_gesture_resources) &&
+		wl_list_empty(&pointer_client->pinch_gesture_resources));
 }
 
 static struct weston_pointer_client *
@@ -2364,6 +2369,110 @@  static const struct wl_pointer_interface pointer_interface = {
 	pointer_release
 };
 
+WL_EXPORT void
+notify_pointer_swipe(struct weston_seat *seat, uint32_t time, int cancelled,
+		     int fingers, wl_fixed_t dx, wl_fixed_t dy, int gesture_type)
+{
+	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+	struct weston_compositor *ec = seat->compositor;
+	struct weston_view *focus;
+	struct wl_display *display = ec->wl_display;
+	struct wl_list *resource_list;
+	struct wl_resource *resource;
+	uint32_t serial;
+
+	if (!seat->pointer_device_count ||
+	    !pointer->focus || !pointer->focus_client)
+		return;
+
+	weston_compositor_wake(ec);
+	resource_list = &pointer->focus_client->swipe_gesture_resources;
+	focus = pointer->focus;
+
+	if (wl_list_empty(resource_list))
+		return;
+
+	switch (gesture_type) {
+	case ZWP_POINTER_GESTURE_SWIPE_V1_BEGIN:
+		serial = wl_display_next_serial(display);
+		wl_resource_for_each(resource, resource_list) {
+			zwp_pointer_gesture_swipe_v1_send_begin(resource, serial,
+								time,
+								focus->surface->resource,
+								fingers);
+		}
+		break;
+	case ZWP_POINTER_GESTURE_SWIPE_V1_UPDATE:
+		wl_resource_for_each(resource, resource_list) {
+			zwp_pointer_gesture_swipe_v1_send_update(resource, time,
+								 dx, dy);
+		}
+		break;
+	case ZWP_POINTER_GESTURE_SWIPE_V1_END:
+		serial = wl_display_next_serial(display);
+		wl_resource_for_each(resource, resource_list) {
+			zwp_pointer_gesture_swipe_v1_send_end(resource, serial,
+							      time, cancelled);
+		}
+		break;
+	default:
+		return;
+	}
+}
+
+WL_EXPORT void
+notify_pointer_pinch(struct weston_seat *seat, uint32_t time, int cancelled,
+		     int fingers, wl_fixed_t dx, wl_fixed_t dy,
+		     wl_fixed_t scale, wl_fixed_t rotation_diff, int gesture_type)
+{
+	struct weston_pointer *pointer = weston_seat_get_pointer(seat);
+	struct weston_compositor *ec = seat->compositor;
+	struct weston_view *focus;
+	struct wl_display *display = ec->wl_display;
+	struct wl_list *resource_list;
+	struct wl_resource *resource;
+	uint32_t serial;
+
+	if (!seat->pointer_device_count ||
+	    !pointer->focus || !pointer->focus_client)
+		return;
+
+	weston_compositor_wake(ec);
+	resource_list = &pointer->focus_client->pinch_gesture_resources;
+	focus = pointer->focus;
+
+	if (wl_list_empty(resource_list))
+		return;
+
+	switch (gesture_type) {
+	case ZWP_POINTER_GESTURE_PINCH_V1_BEGIN:
+		serial = wl_display_next_serial(display);
+		wl_resource_for_each(resource, resource_list) {
+			zwp_pointer_gesture_pinch_v1_send_begin(resource, serial,
+								time,
+								focus->surface->resource,
+								fingers);
+		}
+		break;
+	case ZWP_POINTER_GESTURE_PINCH_V1_UPDATE:
+		wl_resource_for_each(resource, resource_list) {
+			zwp_pointer_gesture_pinch_v1_send_update(resource, time,
+								 dx, dy, scale,
+								 rotation_diff);
+		}
+		break;
+	case ZWP_POINTER_GESTURE_PINCH_V1_END:
+		serial = wl_display_next_serial(display);
+		wl_resource_for_each(resource, resource_list) {
+			zwp_pointer_gesture_pinch_v1_send_end(resource, serial,
+							      time, cancelled);
+		}
+		break;
+	default:
+		return;
+	}
+}
+
 static void
 seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
 		 uint32_t id)
@@ -4555,3 +4664,108 @@  weston_input_init(struct weston_compositor *compositor)
 
 	return 0;
 }
+
+static void
+pointer_gesture_swipe_destroy(struct wl_client *client,
+			      struct wl_resource *resource)
+{
+	wl_resource_destroy(resource);
+}
+
+static const struct
+zwp_pointer_gesture_swipe_v1_interface pointer_gesture_swipe_interface = {
+	pointer_gesture_swipe_destroy
+};
+
+static void
+pointer_gesture_pinch_destroy(struct wl_client *client,
+			      struct wl_resource *resource)
+{
+	wl_resource_destroy(resource);
+}
+
+static const struct
+zwp_pointer_gesture_swipe_v1_interface pointer_gesture_pinch_interface = {
+	pointer_gesture_pinch_destroy
+};
+
+static void
+pointer_gestures_get_swipe(struct wl_client *client,
+			   struct wl_resource *resource,
+			   uint32_t id, struct wl_resource *pointer_resource)
+{
+	struct weston_pointer *pointer =
+		wl_resource_get_user_data(pointer_resource);
+	struct weston_pointer_client *pointer_client;
+	struct wl_resource *cr;
+
+	cr = wl_resource_create(client, &zwp_pointer_gesture_swipe_v1_interface,
+				wl_resource_get_version(resource), id);
+	if (cr == NULL) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	wl_resource_set_implementation(cr, &pointer_gesture_swipe_interface,
+				       pointer, unbind_resource);
+
+	pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
+	wl_list_insert(&pointer_client->swipe_gesture_resources,
+		       wl_resource_get_link(cr));
+}
+
+static void
+pointer_gestures_get_pinch(struct wl_client *client,
+			   struct wl_resource *resource,
+			   uint32_t id, struct wl_resource *pointer_resource)
+{
+	struct weston_pointer *pointer =
+		wl_resource_get_user_data(pointer_resource);
+	struct weston_pointer_client *pointer_client;
+	struct wl_resource *cr;
+
+	cr = wl_resource_create(client, &zwp_pointer_gesture_pinch_v1_interface,
+				wl_resource_get_version(resource), id);
+	if (cr == NULL) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	wl_resource_set_implementation(cr, &pointer_gesture_pinch_interface,
+				       pointer, unbind_resource);
+
+	pointer_client = weston_pointer_ensure_pointer_client(pointer, client);
+	wl_list_insert(&pointer_client->pinch_gesture_resources,
+		       wl_resource_get_link(cr));
+}
+
+static const struct
+zwp_pointer_gestures_v1_interface pointer_gestures_interface = {
+	pointer_gestures_get_swipe,
+	pointer_gestures_get_pinch
+};
+
+static void
+bind_pointer_gestures(struct wl_client *client,
+		      void *data, uint32_t version, uint32_t id)
+{
+	struct weston_compositor *compositor = data;
+	struct wl_resource *resource;
+
+	resource = wl_resource_create(client, &zwp_pointer_gestures_v1_interface,
+				      MIN(version, 1), id);
+	if (resource == NULL) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	wl_resource_set_implementation(resource, &pointer_gestures_interface,
+				       compositor, NULL);
+}
+
+WL_EXPORT void
+weston_pointer_gestures_init(struct weston_compositor *ec)
+{
+	wl_global_create(ec->wl_display, &zwp_pointer_gestures_v1_interface, 1,
+			 ec, bind_pointer_gestures);
+}
diff --git a/libweston/libinput-device.c b/libweston/libinput-device.c
index f97afcf..16e2456 100644
--- a/libweston/libinput-device.c
+++ b/libweston/libinput-device.c
@@ -40,6 +40,7 @@ 
 #include "compositor.h"
 #include "libinput-device.h"
 #include "shared/helpers.h"
+#include "pointer-gestures-unstable-v1-server-protocol.h"
 
 void
 evdev_led_update(struct evdev_device *device, enum weston_led weston_leds)
@@ -355,6 +356,122 @@  handle_touch_frame(struct libinput_device *libinput_device,
 	notify_touch_frame(seat);
 }
 
+static void
+handle_pointer_swipe_begin(struct libinput_device *libinput_device,
+			   struct libinput_event_gesture *gesture_event)
+{
+	struct evdev_device *device =
+		libinput_device_get_user_data(libinput_device);
+	struct weston_seat *seat = device->seat;
+	uint32_t time, fingers;
+
+	time = libinput_event_gesture_get_time(gesture_event);
+	fingers = libinput_event_gesture_get_finger_count(gesture_event);
+	notify_pointer_swipe(seat, time, 0, fingers, 0, 0,
+			     ZWP_POINTER_GESTURE_SWIPE_V1_BEGIN);
+}
+
+static void
+handle_pointer_swipe_update(struct libinput_device *libinput_device,
+			   struct libinput_event_gesture *gesture_event)
+{
+	struct evdev_device *device =
+		libinput_device_get_user_data(libinput_device);
+	struct weston_seat *seat = device->seat;
+	uint32_t time, fingers;
+	double dx, dy;
+
+	time = libinput_event_gesture_get_time(gesture_event);
+	fingers = libinput_event_gesture_get_finger_count(gesture_event);
+	dx = libinput_event_gesture_get_dx(gesture_event);
+	dy = libinput_event_gesture_get_dy(gesture_event);
+
+	notify_pointer_swipe(seat, time, 0, fingers,
+			     wl_fixed_from_double(dx),
+			     wl_fixed_from_double(dy),
+			     ZWP_POINTER_GESTURE_SWIPE_V1_UPDATE);
+}
+
+static void
+handle_pointer_swipe_end(struct libinput_device *libinput_device,
+			   struct libinput_event_gesture *gesture_event)
+{
+	struct evdev_device *device =
+		libinput_device_get_user_data(libinput_device);
+	struct weston_seat *seat = device->seat;
+	uint32_t time, fingers, cancelled;
+
+	time = libinput_event_gesture_get_time(gesture_event);
+	fingers = libinput_event_gesture_get_finger_count(gesture_event);
+	cancelled = libinput_event_gesture_get_cancelled(gesture_event);
+
+	notify_pointer_swipe(seat, time, cancelled, fingers, 0, 0,
+			     ZWP_POINTER_GESTURE_SWIPE_V1_END);
+}
+
+static void
+handle_pointer_pinch_begin(struct libinput_device *libinput_device,
+			   struct libinput_event_gesture *gesture_event)
+{
+	struct evdev_device *device =
+		libinput_device_get_user_data(libinput_device);
+	struct weston_seat *seat = device->seat;
+	uint32_t time, fingers;
+	double scale;
+
+	time = libinput_event_gesture_get_time(gesture_event);
+	fingers = libinput_event_gesture_get_finger_count(gesture_event);
+	scale = libinput_event_gesture_get_scale(gesture_event);
+
+	notify_pointer_pinch(seat, time, 0, fingers, 0, 0, scale, 0,
+			     ZWP_POINTER_GESTURE_PINCH_V1_BEGIN);
+}
+
+static void
+handle_pointer_pinch_update(struct libinput_device *libinput_device,
+			   struct libinput_event_gesture *gesture_event)
+{
+	struct evdev_device *device =
+		libinput_device_get_user_data(libinput_device);
+	struct weston_seat *seat = device->seat;
+	double scale, angle_delta, dx, dy;
+	uint32_t time, fingers;
+
+	time = libinput_event_gesture_get_time(gesture_event);
+	fingers = libinput_event_gesture_get_finger_count(gesture_event);
+	scale = libinput_event_gesture_get_scale(gesture_event);
+	angle_delta = libinput_event_gesture_get_angle_delta(gesture_event);
+	dx = libinput_event_gesture_get_dx(gesture_event);
+	dy = libinput_event_gesture_get_dy(gesture_event);
+
+	notify_pointer_pinch(seat, time, 0, fingers,
+			     wl_fixed_from_double(dx),
+			     wl_fixed_from_double(dy),
+			     wl_fixed_from_double(scale),
+			     wl_fixed_from_double(angle_delta),
+			     ZWP_POINTER_GESTURE_PINCH_V1_UPDATE);
+}
+
+static void
+handle_pointer_pinch_end(struct libinput_device *libinput_device,
+			 struct libinput_event_gesture *gesture_event)
+{
+	struct evdev_device *device =
+		libinput_device_get_user_data(libinput_device);
+	struct weston_seat *seat = device->seat;
+	uint32_t time, fingers, cancelled;
+	double scale;
+
+	time = libinput_event_gesture_get_time(gesture_event);
+	fingers = libinput_event_gesture_get_finger_count(gesture_event);
+	cancelled = libinput_event_gesture_get_cancelled(gesture_event);
+	scale = libinput_event_gesture_get_scale(gesture_event);
+
+	notify_pointer_pinch(seat, time, cancelled, fingers,
+			     0, 0, wl_fixed_from_double(scale), 0,
+			     ZWP_POINTER_GESTURE_PINCH_V1_END);
+}
+
 int
 evdev_device_process_event(struct libinput_event *event)
 {
@@ -404,6 +521,30 @@  evdev_device_process_event(struct libinput_event *event)
 		handle_touch_frame(libinput_device,
 				   libinput_event_get_touch_event(event));
 		break;
+	case LIBINPUT_EVENT_GESTURE_SWIPE_BEGIN:
+		handle_pointer_swipe_begin(libinput_device,
+					   libinput_event_get_gesture_event(event));
+		break;
+	case LIBINPUT_EVENT_GESTURE_SWIPE_UPDATE:
+		handle_pointer_swipe_update(libinput_device,
+					    libinput_event_get_gesture_event(event));
+		break;
+	case LIBINPUT_EVENT_GESTURE_SWIPE_END:
+		handle_pointer_swipe_end(libinput_device,
+					 libinput_event_get_gesture_event(event));
+		break;
+	case LIBINPUT_EVENT_GESTURE_PINCH_BEGIN:
+		handle_pointer_pinch_begin(libinput_device,
+					   libinput_event_get_gesture_event(event));
+		break;
+	case LIBINPUT_EVENT_GESTURE_PINCH_UPDATE:
+		handle_pointer_pinch_update(libinput_device,
+					    libinput_event_get_gesture_event(event));
+		break;
+	case LIBINPUT_EVENT_GESTURE_PINCH_END:
+		handle_pointer_pinch_end(libinput_device,
+					 libinput_event_get_gesture_event(event));
+		break;
 	default:
 		handled = 0;
 		weston_log("unknown libinput event %d\n",