libweston: Implement touch timestamps for input_timestamps_unstable_v1
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@collabora.com> Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
parent
db907b7188
commit
d715784734
@ -415,6 +415,8 @@ struct weston_touch {
|
|||||||
wl_fixed_t grab_x, grab_y;
|
wl_fixed_t grab_x, grab_y;
|
||||||
uint32_t grab_serial;
|
uint32_t grab_serial;
|
||||||
struct timespec grab_time;
|
struct timespec grab_time;
|
||||||
|
|
||||||
|
struct wl_list timestamps_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -758,10 +758,14 @@ weston_touch_send_down(struct weston_touch *touch, const struct timespec *time,
|
|||||||
resource_list = &touch->focus_resource_list;
|
resource_list = &touch->focus_resource_list;
|
||||||
serial = wl_display_next_serial(display);
|
serial = wl_display_next_serial(display);
|
||||||
msecs = timespec_to_msec(time);
|
msecs = timespec_to_msec(time);
|
||||||
wl_resource_for_each(resource, resource_list)
|
wl_resource_for_each(resource, resource_list) {
|
||||||
wl_touch_send_down(resource, serial, msecs,
|
send_timestamps_for_input_resource(resource,
|
||||||
touch->focus->surface->resource,
|
&touch->timestamps_list,
|
||||||
touch_id, sx, sy);
|
time);
|
||||||
|
wl_touch_send_down(resource, serial, msecs,
|
||||||
|
touch->focus->surface->resource,
|
||||||
|
touch_id, sx, sy);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -798,8 +802,12 @@ weston_touch_send_up(struct weston_touch *touch, const struct timespec *time,
|
|||||||
resource_list = &touch->focus_resource_list;
|
resource_list = &touch->focus_resource_list;
|
||||||
serial = wl_display_next_serial(display);
|
serial = wl_display_next_serial(display);
|
||||||
msecs = timespec_to_msec(time);
|
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);
|
wl_touch_send_up(resource, serial, msecs, touch_id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -839,6 +847,9 @@ weston_touch_send_motion(struct weston_touch *touch,
|
|||||||
resource_list = &touch->focus_resource_list;
|
resource_list = &touch->focus_resource_list;
|
||||||
msecs = timespec_to_msec(time);
|
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_motion(resource, msecs,
|
wl_touch_send_motion(resource, msecs,
|
||||||
touch_id, sx, sy);
|
touch_id, sx, sy);
|
||||||
}
|
}
|
||||||
@ -1276,6 +1287,7 @@ weston_touch_create(void)
|
|||||||
touch->default_grab.touch = touch;
|
touch->default_grab.touch = touch;
|
||||||
touch->grab = &touch->default_grab;
|
touch->grab = &touch->default_grab;
|
||||||
wl_signal_init(&touch->focus_signal);
|
wl_signal_init(&touch->focus_signal);
|
||||||
|
wl_list_init(&touch->timestamps_list);
|
||||||
|
|
||||||
return touch;
|
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_resource_list);
|
||||||
wl_list_remove(&touch->focus_view_listener.link);
|
wl_list_remove(&touch->focus_view_listener.link);
|
||||||
wl_list_remove(&touch->focus_resource_listener.link);
|
wl_list_remove(&touch->focus_resource_listener.link);
|
||||||
|
wl_list_remove(&touch->timestamps_list);
|
||||||
free(touch);
|
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
|
static void
|
||||||
touch_release(struct wl_client *client, struct wl_resource *resource)
|
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_list_init(wl_resource_get_link(cr));
|
||||||
wl_resource_set_implementation(cr, &touch_interface,
|
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
|
/* If we don't have a touch_state, the resource is inert, so there
|
||||||
* is nothing more to set up */
|
* is nothing more to set up */
|
||||||
@ -4731,7 +4757,28 @@ input_timestamps_manager_get_touch_timestamps(struct wl_client *client,
|
|||||||
uint32_t id,
|
uint32_t id,
|
||||||
struct wl_resource *touch_resource)
|
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
|
static const struct zwp_input_timestamps_manager_v1_interface
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
#include "input-timestamps-helper.h"
|
||||||
#include "shared/timespec-util.h"
|
#include "shared/timespec-util.h"
|
||||||
#include "weston-test-client-helper.h"
|
#include "weston-test-client-helper.h"
|
||||||
#include "wayland-server-protocol.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 t1 = { .tv_sec = 1, .tv_nsec = 1000001 };
|
||||||
static const struct timespec t2 = { .tv_sec = 2, .tv_nsec = 2000001 };
|
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 t3 = { .tv_sec = 3, .tv_nsec = 3000001 };
|
||||||
|
static const struct timespec t_other = { .tv_sec = 123, .tv_nsec = 456 };
|
||||||
|
|
||||||
static struct client *
|
static struct client *
|
||||||
create_touch_test_client(void)
|
create_touch_test_client(void)
|
||||||
@ -59,13 +61,63 @@ TEST(touch_events)
|
|||||||
{
|
{
|
||||||
struct client *client = create_touch_test_client();
|
struct client *client = create_touch_test_client();
|
||||||
struct touch *touch = client->input->touch;
|
struct touch *touch = client->input->touch;
|
||||||
|
struct input_timestamps *input_ts =
|
||||||
|
input_timestamps_create_for_touch(client);
|
||||||
|
|
||||||
send_touch(client, &t1, WL_TOUCH_DOWN);
|
send_touch(client, &t1, WL_TOUCH_DOWN);
|
||||||
assert(touch->down_time_msec == timespec_to_msec(&t1));
|
assert(touch->down_time_msec == timespec_to_msec(&t1));
|
||||||
|
assert(timespec_eq(&touch->down_time_timespec, &t1));
|
||||||
|
|
||||||
send_touch(client, &t2, WL_TOUCH_MOTION);
|
send_touch(client, &t2, WL_TOUCH_MOTION);
|
||||||
assert(touch->motion_time_msec == timespec_to_msec(&t2));
|
assert(touch->motion_time_msec == timespec_to_msec(&t2));
|
||||||
|
assert(timespec_eq(&touch->motion_time_timespec, &t2));
|
||||||
|
|
||||||
send_touch(client, &t3, WL_TOUCH_UP);
|
send_touch(client, &t3, WL_TOUCH_UP);
|
||||||
assert(touch->up_time_msec == timespec_to_msec(&t3));
|
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);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user