libweston: Implement keyboard timestamps for input_timestamps_unstable_v1
Implement the zwp_input_timestamps_manager_v1.get_keyboard_timestamps request to subscribe to timestamp events for wl_keyboard resources. Ensure that the request handling code can gracefully handle inert keyboard resources. This commit introduces a few internal helper functions which will also be useful in the implementation of the remaining zwp_input_timestamps_manager_v1 requests. Signed-off-by: Alexandros Frantzis <alexandros.frantzis@collabora.com> Reviewed-by: Pekka Paalanen <pekka.paalanen@collabora.co.uk>
This commit is contained in:
parent
538749de7b
commit
2b44248f60
|
@ -605,6 +605,8 @@ struct weston_keyboard {
|
|||
enum weston_led leds;
|
||||
} xkb_state;
|
||||
struct xkb_keymap *pending_keymap;
|
||||
|
||||
struct wl_list timestamps_list;
|
||||
};
|
||||
|
||||
struct weston_seat {
|
||||
|
|
|
@ -87,6 +87,42 @@ region_init_infinite(pixman_region32_t *region)
|
|||
UINT32_MAX, UINT32_MAX);
|
||||
}
|
||||
|
||||
static void
|
||||
send_timestamp(struct wl_resource *resource,
|
||||
const struct timespec *time)
|
||||
{
|
||||
uint32_t tv_sec_hi, tv_sec_lo, tv_nsec;
|
||||
|
||||
timespec_to_proto(time, &tv_sec_hi, &tv_sec_lo, &tv_nsec);
|
||||
zwp_input_timestamps_v1_send_timestamp(resource, tv_sec_hi, tv_sec_lo,
|
||||
tv_nsec);
|
||||
}
|
||||
|
||||
static void
|
||||
send_timestamps_for_input_resource(struct wl_resource *input_resource,
|
||||
struct wl_list *list,
|
||||
const struct timespec *time)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each(resource, list) {
|
||||
if (wl_resource_get_user_data(resource) == input_resource)
|
||||
send_timestamp(resource, time);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
remove_input_resource_from_timestamps(struct wl_resource *input_resource,
|
||||
struct wl_list *list)
|
||||
{
|
||||
struct wl_resource *resource;
|
||||
|
||||
wl_resource_for_each(resource, list) {
|
||||
if (wl_resource_get_user_data(resource) == input_resource)
|
||||
wl_resource_set_user_data(resource, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static struct weston_pointer_client *
|
||||
weston_pointer_client_create(struct wl_client *client)
|
||||
{
|
||||
|
@ -884,8 +920,12 @@ weston_keyboard_send_key(struct weston_keyboard *keyboard,
|
|||
resource_list = &keyboard->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,
|
||||
&keyboard->timestamps_list,
|
||||
time);
|
||||
wl_keyboard_send_key(resource, serial, msecs, key, state);
|
||||
}
|
||||
};
|
||||
|
||||
static void
|
||||
|
@ -1157,6 +1197,7 @@ weston_keyboard_create(void)
|
|||
keyboard->default_grab.keyboard = keyboard;
|
||||
keyboard->grab = &keyboard->default_grab;
|
||||
wl_signal_init(&keyboard->focus_signal);
|
||||
wl_list_init(&keyboard->timestamps_list);
|
||||
|
||||
return keyboard;
|
||||
}
|
||||
|
@ -1187,6 +1228,7 @@ weston_keyboard_destroy(struct weston_keyboard *keyboard)
|
|||
|
||||
wl_array_release(&keyboard->keys);
|
||||
wl_list_remove(&keyboard->focus_resource_listener.link);
|
||||
wl_list_remove(&keyboard->timestamps_list);
|
||||
free(keyboard);
|
||||
}
|
||||
|
||||
|
@ -2467,6 +2509,19 @@ seat_get_pointer(struct wl_client *client, struct wl_resource *resource,
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_keyboard_resource(struct wl_resource *resource)
|
||||
{
|
||||
struct weston_keyboard *keyboard = wl_resource_get_user_data(resource);
|
||||
|
||||
wl_list_remove(wl_resource_get_link(resource));
|
||||
|
||||
if (keyboard) {
|
||||
remove_input_resource_from_timestamps(resource,
|
||||
&keyboard->timestamps_list);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
keyboard_release(struct wl_client *client, struct wl_resource *resource)
|
||||
{
|
||||
|
@ -2524,7 +2579,7 @@ seat_get_keyboard(struct wl_client *client, struct wl_resource *resource,
|
|||
|
||||
wl_list_init(wl_resource_get_link(cr));
|
||||
wl_resource_set_implementation(cr, &keyboard_interface,
|
||||
keyboard, unbind_resource);
|
||||
keyboard, destroy_keyboard_resource);
|
||||
|
||||
/* If we don't have a keyboard_state, the resource is inert, so there
|
||||
* is nothing more to set up */
|
||||
|
@ -4570,6 +4625,18 @@ bind_pointer_constraints(struct wl_client *client, void *data,
|
|||
NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
input_timestamps_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
{
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
||||
static const struct zwp_input_timestamps_v1_interface
|
||||
input_timestamps_interface = {
|
||||
input_timestamps_destroy,
|
||||
};
|
||||
|
||||
static void
|
||||
input_timestamps_manager_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource)
|
||||
|
@ -4583,7 +4650,29 @@ input_timestamps_manager_get_keyboard_timestamps(struct wl_client *client,
|
|||
uint32_t id,
|
||||
struct wl_resource *keyboard_resource)
|
||||
{
|
||||
wl_client_post_no_memory(client);
|
||||
struct weston_keyboard *keyboard =
|
||||
wl_resource_get_user_data(keyboard_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 (keyboard) {
|
||||
wl_list_insert(&keyboard->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,
|
||||
keyboard_resource,
|
||||
unbind_resource);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -27,11 +27,13 @@
|
|||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "input-timestamps-helper.h"
|
||||
#include "shared/timespec-util.h"
|
||||
#include "weston-test-client-helper.h"
|
||||
|
||||
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 t_other = { .tv_sec = 123, .tv_nsec = 456 };
|
||||
|
||||
static struct client *
|
||||
create_client_with_keyboard_focus(void)
|
||||
|
@ -97,10 +99,59 @@ TEST(keyboard_key_event_time)
|
|||
{
|
||||
struct client *client = create_client_with_keyboard_focus();
|
||||
struct keyboard *keyboard = client->input->keyboard;
|
||||
struct input_timestamps *input_ts =
|
||||
input_timestamps_create_for_keyboard(client);
|
||||
|
||||
send_key(client, &t1, 1, WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
assert(keyboard->key_time_msec == timespec_to_msec(&t1));
|
||||
assert(timespec_eq(&keyboard->key_time_timespec, &t1));
|
||||
|
||||
send_key(client, &t2, 1, WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||
assert(keyboard->key_time_msec == timespec_to_msec(&t2));
|
||||
assert(timespec_eq(&keyboard->key_time_timespec, &t2));
|
||||
|
||||
input_timestamps_destroy(input_ts);
|
||||
}
|
||||
|
||||
TEST(keyboard_timestamps_stop_after_input_timestamps_object_is_destroyed)
|
||||
{
|
||||
struct client *client = create_client_with_keyboard_focus();
|
||||
struct keyboard *keyboard = client->input->keyboard;
|
||||
struct input_timestamps *input_ts =
|
||||
input_timestamps_create_for_keyboard(client);
|
||||
|
||||
send_key(client, &t1, 1, WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
assert(keyboard->key_time_msec == timespec_to_msec(&t1));
|
||||
assert(timespec_eq(&keyboard->key_time_timespec, &t1));
|
||||
|
||||
input_timestamps_destroy(input_ts);
|
||||
|
||||
send_key(client, &t2, 1, WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||
assert(keyboard->key_time_msec == timespec_to_msec(&t2));
|
||||
assert(timespec_is_zero(&keyboard->key_time_timespec));
|
||||
}
|
||||
|
||||
TEST(keyboard_timestamps_stop_after_client_releases_wl_keyboard)
|
||||
{
|
||||
struct client *client = create_client_with_keyboard_focus();
|
||||
struct keyboard *keyboard = client->input->keyboard;
|
||||
struct input_timestamps *input_ts =
|
||||
input_timestamps_create_for_keyboard(client);
|
||||
|
||||
send_key(client, &t1, 1, WL_KEYBOARD_KEY_STATE_PRESSED);
|
||||
assert(keyboard->key_time_msec == timespec_to_msec(&t1));
|
||||
assert(timespec_eq(&keyboard->key_time_timespec, &t1));
|
||||
|
||||
wl_keyboard_release(client->input->keyboard->wl_keyboard);
|
||||
|
||||
/* 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. */
|
||||
keyboard->input_timestamp = t_other;
|
||||
send_key(client, &t2, 1, WL_KEYBOARD_KEY_STATE_RELEASED);
|
||||
assert(timespec_eq(&keyboard->input_timestamp, &t_other));
|
||||
|
||||
input_timestamps_destroy(input_ts);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue