[PATCH weston v3 2/5] compositor: Implement wl_pointer_gesture_swipe/pinch interfaces

Carlos Garnacho carlosg at gnome.org
Fri Jul 31 06:59:52 PDT 2015


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 _wl_pointer_gesture_pinch/swipe
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.

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 at gnome.org>
---
 src/compositor.c      |   2 +
 src/compositor.h      |  12 +++
 src/input.c           | 218 +++++++++++++++++++++++++++++++++++++++++++++++++-
 src/libinput-device.c | 141 ++++++++++++++++++++++++++++++++
 4 files changed, 372 insertions(+), 1 deletion(-)

diff --git a/src/compositor.c b/src/compositor.c
index 66c3eee..351fdb6 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -4501,6 +4501,8 @@ weston_compositor_create(struct wl_display *display, void *user_data)
 			      ec, bind_presentation))
 		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/src/compositor.h b/src/compositor.h
index dd9c046..e91ff9e 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -315,6 +315,8 @@ struct weston_pointer_client {
 	struct wl_list link;
 	struct wl_client *client;
 	struct wl_list pointer_resources;
+	struct wl_list swipe_gesture_resources;
+	struct wl_list pinch_gesture_resources;
 };
 
 struct weston_pointer {
@@ -1099,6 +1101,13 @@ void
 notify_touch_frame(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
@@ -1423,6 +1432,9 @@ weston_compositor_xkb_init(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/src/input.c b/src/input.c
index 1365869..fdbec04 100644
--- a/src/input.c
+++ b/src/input.c
@@ -37,6 +37,7 @@
 #include "shared/helpers.h"
 #include "shared/os-compatibility.h"
 #include "compositor.h"
+#include "protocol/pointer-gestures-server-protocol.h"
 
 static void
 empty_region(pixman_region32_t *region)
@@ -56,6 +57,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->swipe_gesture_resources);
+	wl_list_init(&pointer_client->pinch_gesture_resources);
 
 	return pointer_client;
 }
@@ -69,7 +72,9 @@ weston_pointer_client_destroy(struct weston_pointer_client *pointer_client)
 static bool
 weston_pointer_client_is_empty(struct weston_pointer_client *pointer_client)
 {
-	return wl_list_empty(&pointer_client->pointer_resources);
+	return (wl_list_empty(&pointer_client->pointer_resources) &&
+		wl_list_empty(&pointer_client->swipe_gesture_resources) &&
+		wl_list_empty(&pointer_client->pinch_gesture_resources));
 }
 
 static struct weston_pointer_client *
@@ -1815,6 +1820,112 @@ 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_compositor *ec = seat->compositor;
+	struct weston_pointer *pointer = seat->pointer;
+	struct weston_view *focus;
+	struct wl_display *display = ec->wl_display;
+	struct wl_list *resource_list;
+	struct wl_resource *resource;
+	uint32_t serial;
+
+	/* XXX: make gestures go through grab interface? */
+
+	if (!pointer || !pointer->focus || !pointer->focus_client)
+		return;
+
+	weston_compositor_wake(ec);
+	resource_list = &pointer->focus_client->swipe_gesture_resources;
+	focus = seat->pointer->focus;
+
+	if (wl_list_empty(resource_list))
+		return;
+
+	switch (gesture_type) {
+	case _WL_POINTER_GESTURE_SWIPE_BEGIN:
+		serial = wl_display_next_serial(display);
+		wl_resource_for_each(resource, resource_list) {
+			_wl_pointer_gesture_swipe_send_begin(resource, serial,
+							     time,
+							     focus->surface->resource,
+							     fingers);
+		}
+		break;
+	case _WL_POINTER_GESTURE_SWIPE_UPDATE:
+		wl_resource_for_each(resource, resource_list) {
+			_wl_pointer_gesture_swipe_send_update(resource, time,
+							      dx, dy);
+		}
+		break;
+	case _WL_POINTER_GESTURE_SWIPE_END:
+		serial = wl_display_next_serial(display);
+		wl_resource_for_each(resource, resource_list) {
+			_wl_pointer_gesture_swipe_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_compositor *ec = seat->compositor;
+	struct weston_pointer *pointer = seat->pointer;
+	struct weston_view *focus;
+	struct wl_display *display = ec->wl_display;
+	struct wl_list *resource_list;
+	struct wl_resource *resource;
+	uint32_t serial;
+
+	if (!pointer || !pointer->focus || !pointer->focus_client)
+		return;
+
+	/* XXX: make gestures go through grab interface? */
+
+	weston_compositor_wake(ec);
+	resource_list = &pointer->focus_client->pinch_gesture_resources;
+	focus = seat->pointer->focus;
+
+	if (wl_list_empty(resource_list))
+		return;
+
+	switch (gesture_type) {
+	case _WL_POINTER_GESTURE_PINCH_BEGIN:
+		serial = wl_display_next_serial(display);
+		wl_resource_for_each(resource, resource_list) {
+			_wl_pointer_gesture_pinch_send_begin(resource, serial,
+							     time,
+							     focus->surface->resource,
+							     fingers);
+		}
+		break;
+	case _WL_POINTER_GESTURE_PINCH_UPDATE:
+		wl_resource_for_each(resource, resource_list) {
+			_wl_pointer_gesture_pinch_send_update(resource, time,
+							      dx, dy, scale,
+							      rotation_diff);
+		}
+		break;
+	case _WL_POINTER_GESTURE_PINCH_END:
+		serial = wl_display_next_serial(display);
+		wl_resource_for_each(resource, resource_list) {
+			_wl_pointer_gesture_pinch_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)
@@ -2446,3 +2557,108 @@ weston_seat_release(struct weston_seat *seat)
 
 	wl_signal_emit(&seat->destroy_signal, seat);
 }
+
+static void
+pointer_gesture_swipe_destroy(struct wl_client *client,
+			      struct wl_resource *resource)
+{
+	wl_resource_destroy(resource);
+}
+
+static const struct
+_wl_pointer_gesture_swipe_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
+_wl_pointer_gesture_swipe_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, &_wl_pointer_gesture_swipe_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, &_wl_pointer_gesture_pinch_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
+_wl_pointer_gestures_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, &_wl_pointer_gestures_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, &_wl_pointer_gestures_interface, 1,
+			 ec, bind_pointer_gestures);
+}
diff --git a/src/libinput-device.c b/src/libinput-device.c
index 2cbfb88..60a8b5f 100644
--- a/src/libinput-device.c
+++ b/src/libinput-device.c
@@ -39,6 +39,7 @@
 #include "compositor.h"
 #include "libinput-device.h"
 #include "shared/helpers.h"
+#include "protocol/pointer-gestures-server-protocol.h"
 
 #define DEFAULT_AXIS_STEP_DISTANCE wl_fixed_from_int(10)
 
@@ -287,6 +288,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,
+			     _WL_POINTER_GESTURE_SWIPE_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_dx(gesture_event);
+
+	notify_pointer_swipe(seat, time, 0, fingers,
+			     wl_fixed_from_double(dx),
+			     wl_fixed_from_double(dy),
+			     _WL_POINTER_GESTURE_SWIPE_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,
+			     _WL_POINTER_GESTURE_SWIPE_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,
+			     _WL_POINTER_GESTURE_PINCH_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_dx(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),
+			     _WL_POINTER_GESTURE_PINCH_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,
+			     _WL_POINTER_GESTURE_PINCH_END);
+}
+
 int
 evdev_device_process_event(struct libinput_event *event)
 {
@@ -332,6 +449,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",
-- 
2.4.3



More information about the wayland-devel mailing list