[PATCH weston v3 6/6] libweston: Implement touch timestamps for input_timestamps_unstable_v1

Alexandros Frantzis alexandros.frantzis at collabora.com
Tue Feb 20 12:07:03 UTC 2018


Implement the zwp_input_timestamps_manager_v1.get_touch_timestamps
request to subscribe to timestamp events for wl_touch resources. Ensure
that the request handling code can gracefully handle inert touch
resources.

Signed-off-by: Alexandros Frantzis <alexandros.frantzis at collabora.com>
---
Changes in v3:
 - In touch_timestamps_stop_after_client_releases_wl_touch test
   check for changes to touch->input_timestamp instead of 
   touch->up_time_timespec.

Changes in v2:
 - Remove the head of timestamps_list in weston_touch_destroy.
 - Gracefully handle inert touch resources in destroy_touch_resource
   and input_timestamps_manager_get_touch_timestamps.

 libweston/compositor.h |  2 ++
 libweston/input.c      | 61 ++++++++++++++++++++++++++++++++++++++++++++------
 tests/touch-test.c     | 52 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 108 insertions(+), 7 deletions(-)

diff --git a/libweston/compositor.h b/libweston/compositor.h
index 78d2668e..010f1fa8 100644
--- a/libweston/compositor.h
+++ b/libweston/compositor.h
@@ -415,6 +415,8 @@ struct weston_touch {
 	wl_fixed_t grab_x, grab_y;
 	uint32_t grab_serial;
 	struct timespec grab_time;
+
+	struct wl_list timestamps_list;
 };
 
 void
diff --git a/libweston/input.c b/libweston/input.c
index 632c9c3c..3f616941 100644
--- a/libweston/input.c
+++ b/libweston/input.c
@@ -758,10 +758,14 @@ weston_touch_send_down(struct weston_touch *touch, const struct timespec *time,
 	resource_list = &touch->focus_resource_list;
 	serial = wl_display_next_serial(display);
 	msecs = timespec_to_msec(time);
-	wl_resource_for_each(resource, resource_list)
-			wl_touch_send_down(resource, serial, msecs,
-					   touch->focus->surface->resource,
-					   touch_id, sx, sy);
+	wl_resource_for_each(resource, resource_list) {
+		send_timestamps_for_input_resource(resource,
+						   &touch->timestamps_list,
+						   time);
+		wl_touch_send_down(resource, serial, msecs,
+				   touch->focus->surface->resource,
+				   touch_id, sx, sy);
+	}
 }
 
 static void
@@ -798,8 +802,12 @@ weston_touch_send_up(struct weston_touch *touch, const struct timespec *time,
 	resource_list = &touch->focus_resource_list;
 	serial = wl_display_next_serial(display);
 	msecs = timespec_to_msec(time);
-	wl_resource_for_each(resource, resource_list)
+	wl_resource_for_each(resource, resource_list) {
+		send_timestamps_for_input_resource(resource,
+						   &touch->timestamps_list,
+						   time);
 		wl_touch_send_up(resource, serial, msecs, touch_id);
+	}
 }
 
 static void
@@ -839,6 +847,9 @@ weston_touch_send_motion(struct weston_touch *touch,
 	resource_list = &touch->focus_resource_list;
 	msecs = timespec_to_msec(time);
 	wl_resource_for_each(resource, resource_list) {
+		send_timestamps_for_input_resource(resource,
+						   &touch->timestamps_list,
+						   time);
 		wl_touch_send_motion(resource, msecs,
 				     touch_id, sx, sy);
 	}
@@ -1276,6 +1287,7 @@ weston_touch_create(void)
 	touch->default_grab.touch = touch;
 	touch->grab = &touch->default_grab;
 	wl_signal_init(&touch->focus_signal);
+	wl_list_init(&touch->timestamps_list);
 
 	return touch;
 }
@@ -1297,6 +1309,7 @@ weston_touch_destroy(struct weston_touch *touch)
 	wl_list_remove(&touch->focus_resource_list);
 	wl_list_remove(&touch->focus_view_listener.link);
 	wl_list_remove(&touch->focus_resource_listener.link);
+	wl_list_remove(&touch->timestamps_list);
 	free(touch);
 }
 
@@ -2647,6 +2660,19 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
 	}
 }
 
+static void
+destroy_touch_resource(struct wl_resource *resource)
+{
+	struct weston_touch *touch = wl_resource_get_user_data(resource);
+
+	wl_list_remove(wl_resource_get_link(resource));
+
+	if (touch) {
+		remove_input_resource_from_timestamps(resource,
+						      &touch->timestamps_list);
+	}
+}
+
 static void
 touch_release(struct wl_client *client, struct wl_resource *resource)
 {
@@ -2682,7 +2708,7 @@ seat_get_touch(struct wl_client *client, struct wl_resource *resource,
 
 	wl_list_init(wl_resource_get_link(cr));
 	wl_resource_set_implementation(cr, &touch_interface,
-				       touch, unbind_resource);
+				       touch, destroy_touch_resource);
 
 	/* If we don't have a touch_state, the resource is inert, so there
 	 * is nothing more to set up */
@@ -4731,7 +4757,28 @@ input_timestamps_manager_get_touch_timestamps(struct wl_client *client,
 					      uint32_t id,
 					      struct wl_resource *touch_resource)
 {
-	wl_client_post_no_memory(client);
+	struct weston_touch *touch = wl_resource_get_user_data(touch_resource);
+	struct wl_resource *input_ts;
+
+	input_ts = wl_resource_create(client,
+				      &zwp_input_timestamps_v1_interface,
+				      1, id);
+	if (!input_ts) {
+		wl_client_post_no_memory(client);
+		return;
+	}
+
+	if (touch) {
+		wl_list_insert(&touch->timestamps_list,
+			       wl_resource_get_link(input_ts));
+	} else {
+		wl_list_init(wl_resource_get_link(input_ts));
+	}
+
+	wl_resource_set_implementation(input_ts,
+				       &input_timestamps_interface,
+				       touch_resource,
+				       unbind_resource);
 }
 
 static const struct zwp_input_timestamps_manager_v1_interface
diff --git a/tests/touch-test.c b/tests/touch-test.c
index 9635257f..baf5bc58 100644
--- a/tests/touch-test.c
+++ b/tests/touch-test.c
@@ -27,6 +27,7 @@
 
 #include <time.h>
 
+#include "input-timestamps-helper.h"
 #include "shared/timespec-util.h"
 #include "weston-test-client-helper.h"
 #include "wayland-server-protocol.h"
@@ -34,6 +35,7 @@
 static const struct timespec t1 = { .tv_sec = 1, .tv_nsec = 1000001 };
 static const struct timespec t2 = { .tv_sec = 2, .tv_nsec = 2000001 };
 static const struct timespec t3 = { .tv_sec = 3, .tv_nsec = 3000001 };
+static const struct timespec t_other = { .tv_sec = 123, .tv_nsec = 456 };
 
 static struct client *
 create_touch_test_client(void)
@@ -59,13 +61,63 @@ TEST(touch_events)
 {
 	struct client *client = create_touch_test_client();
 	struct touch *touch = client->input->touch;
+	struct input_timestamps *input_ts =
+		input_timestamps_create_for_touch(client);
 
 	send_touch(client, &t1, WL_TOUCH_DOWN);
 	assert(touch->down_time_msec == timespec_to_msec(&t1));
+	assert(timespec_eq(&touch->down_time_timespec, &t1));
 
 	send_touch(client, &t2, WL_TOUCH_MOTION);
 	assert(touch->motion_time_msec == timespec_to_msec(&t2));
+	assert(timespec_eq(&touch->motion_time_timespec, &t2));
 
 	send_touch(client, &t3, WL_TOUCH_UP);
 	assert(touch->up_time_msec == timespec_to_msec(&t3));
+	assert(timespec_eq(&touch->up_time_timespec, &t3));
+
+	input_timestamps_destroy(input_ts);
+}
+
+TEST(touch_timestamps_stop_after_input_timestamps_object_is_destroyed)
+{
+	struct client *client = create_touch_test_client();
+	struct touch *touch = client->input->touch;
+	struct input_timestamps *input_ts =
+		input_timestamps_create_for_touch(client);
+
+	send_touch(client, &t1, WL_TOUCH_DOWN);
+	assert(touch->down_time_msec == timespec_to_msec(&t1));
+	assert(timespec_eq(&touch->down_time_timespec, &t1));
+
+	input_timestamps_destroy(input_ts);
+
+	send_touch(client, &t2, WL_TOUCH_UP);
+	assert(touch->up_time_msec == timespec_to_msec(&t2));
+	assert(timespec_is_zero(&touch->up_time_timespec));
+}
+
+TEST(touch_timestamps_stop_after_client_releases_wl_touch)
+{
+	struct client *client = create_touch_test_client();
+	struct touch *touch = client->input->touch;
+	struct input_timestamps *input_ts =
+		input_timestamps_create_for_touch(client);
+
+	send_touch(client, &t1, WL_TOUCH_DOWN);
+	assert(touch->down_time_msec == timespec_to_msec(&t1));
+	assert(timespec_eq(&touch->down_time_timespec, &t1));
+
+	wl_touch_release(client->input->touch->wl_touch);
+
+	/* Set input_timestamp to an arbitrary value (different from t1, t2
+	 * and 0) and check that it is not changed by sending the event.
+	 * This is preferred over just checking for 0, since 0 is used
+	 * internally for resetting the timestamp after handling an input
+	 * event and checking for it here may lead to false negatives. */
+	touch->input_timestamp = t_other;
+	send_touch(client, &t2, WL_TOUCH_UP);
+	assert(timespec_eq(&touch->input_timestamp, &t_other));
+
+	input_timestamps_destroy(input_ts);
 }
-- 
2.14.1



More information about the wayland-devel mailing list