Add timestamps to frame events

Currently only implemented for frame events, the vague plan for the
future is to merely queue the device events internally and "release"
them once a frame event was received, retrofitting the timestamp to the
C event struct (i.e. making ei_event_get_time() available on all device
events).

Meanwhile, the frame event it is.
This commit is contained in:
Peter Hutterer 2022-05-16 11:17:32 +10:00
parent e913462a23
commit d99e42b808
24 changed files with 547 additions and 175 deletions

View file

@ -66,6 +66,7 @@ src_libutil = [
'src/util-sources.c',
'src/util-strings.c',
'src/util-strings.h',
'src/util-time.h',
]
lib_util = static_library('util', src_libutil)

View file

@ -150,6 +150,7 @@ message StopEmulating {
message Frame {
uint32 deviceid = 1;
uint64 timestamp = 2;
}
message Property {

View file

@ -348,13 +348,21 @@ ei_device_has_capability(struct ei_device *device,
return false;
}
static void
ei_device_frame_now(struct ei_device *device)
{
uint64_t now = ei_now(ei_device_get_context(device));
ei_device_frame(device, now);
}
static void
_flush_frame(struct ei_device *device, const char *func)
{
if (device->send_frame_event) {
log_bug_client(ei_device_get_context(device),
"%s: missing call to ei_device_frame()\n", func);
ei_device_frame(device);
ei_device_frame_now(device);
}
}
#define ei_device_flush_frame(d_) _flush_frame(d_, __func__)
@ -617,7 +625,7 @@ ei_touch_destroy(struct ei_touch *touch)
ei_touch_up(touch);
/* Enforce a frame, otherwise we're just pending. If the client
* doesn't want this, it needs to ei_touch_up() */
ei_device_frame(touch->device);
ei_device_frame_now(touch->device);
ei_device_unref(touch->device);
}
@ -723,12 +731,12 @@ ei_touch_up(struct ei_touch *touch)
}
_public_ void
ei_device_frame(struct ei_device *device)
ei_device_frame(struct ei_device *device, uint64_t time)
{
if (device->state != EI_DEVICE_STATE_EMULATING)
return;
ei_send_frame(device);
ei_send_frame(device, time);
}
void
@ -770,12 +778,12 @@ ei_device_event_stop_emulating(struct ei_device *device)
}
int
ei_device_event_frame(struct ei_device *device)
ei_device_event_frame(struct ei_device *device, uint64_t time)
{
if (device->state != EI_DEVICE_STATE_EMULATING)
return -EINVAL;
ei_queue_frame_event(device);
ei_queue_frame_event(device, time);
return 0;
}

View file

@ -422,3 +422,11 @@ ei_event_touch_get_y(struct ei_event *event)
return event->touch.y;
}
_public_ uint64_t
ei_event_get_time(struct ei_event *event)
{
require_event_type(event, 0, EI_EVENT_FRAME);
return event->timestamp;
}

View file

@ -182,6 +182,8 @@ struct ei_event {
struct ei_seat *seat; /* NULL if device is non-NULL */
struct ei_device *device;
uint64_t timestamp;
union {
struct ei_xkb_modifiers modifiers;
struct {
@ -274,7 +276,7 @@ int
ei_send_stop_emulating(struct ei_device *device);
int
ei_send_frame(struct ei_device *device);
ei_send_frame(struct ei_device *device, uint64_t time);
void
ei_queue_device_removed_event(struct ei_device *device);
@ -292,7 +294,7 @@ void
ei_queue_device_stop_emulating_event(struct ei_device *device);
void
ei_queue_frame_event(struct ei_device *device);
ei_queue_frame_event(struct ei_device *device, uint64_t time);
void
ei_queue_pointer_rel_event(struct ei_device *device, double x, double y);
@ -342,7 +344,7 @@ void
ei_device_removed_by_server(struct ei_device *device);
int
ei_device_event_frame(struct ei_device *device);
ei_device_event_frame(struct ei_device *device, uint64_t time);
void
ei_device_event_start_emulating(struct ei_device *device);

View file

@ -207,7 +207,7 @@ ei_proto_handle_message(struct ei *ei,
proto->touch_up->touchid);
break;
case SERVER_MESSAGE__MSG_FRAME:
rc = call(frame, ei, proto->frame->deviceid);
rc = call(frame, ei, proto->frame->deviceid, proto->frame->timestamp);
break;
default:
rc = -EBADMSG;
@ -515,11 +515,12 @@ ei_proto_send_touch_up(struct ei_device *device, uint32_t tid)
}
static int
ei_proto_send_frame(struct ei_device *device)
ei_proto_send_frame(struct ei_device *device, uint64_t time)
{
prepare_msg(FRAME, Frame, frame);
frame.deviceid = device->id;
frame.timestamp = time;
return ei_proto_send_msg(ei_device_get_context(device), &msg);
}

View file

@ -75,7 +75,7 @@ struct ei_proto_interface {
int (*touch_motion)(struct ei *ei, uint32_t deviceid,
uint32_t tid, double x, double y);
int (*touch_up)(struct ei *ei, uint32_t deviceid, uint32_t tid);
int (*frame) (struct ei *ei, uint32_t deviceid);
int (*frame) (struct ei *ei, uint32_t deviceid, uint64_t time);
};
struct ei_proto_requests {
@ -101,7 +101,7 @@ struct ei_proto_requests {
int (*touch_motion)(struct ei_device *device,
uint32_t tid, double x, double y);
int (*touch_up)(struct ei_device *device, uint32_t tid);
int (*frame)(struct ei_device *device);
int (*frame)(struct ei_device *device, uint64_t time);
int (*property)(struct ei *ei,
const char *name, const char *value,
uint32_t permissions);

View file

@ -28,15 +28,16 @@
#include <fcntl.h>
#include <stdbool.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include "util-io.h"
#include "util-macros.h"
#include "util-object.h"
#include "util-sources.h"
#include "util-strings.h"
#include "util-time.h"
#include "libei.h"
#include "libei-private.h"
@ -226,7 +227,7 @@ queue_event(struct ei *ei, struct ei_event *event)
default:
if (device) {
if (device->queue_frame_event)
ei_queue_frame_event(device);
ei_queue_frame_event(device, ei_now(ei));
device->queue_frame_event = false;
}
break;
@ -378,11 +379,12 @@ queue_property_event(struct ei *ei, const char *name,
}
void
ei_queue_frame_event(struct ei_device *device)
ei_queue_frame_event(struct ei_device *device, uint64_t time)
{
struct ei_event *e = ei_event_new_for_device(device);
e->type = EI_EVENT_FRAME;
e->timestamp = time;
queue_event(ei_device_get_context(device), e);
}
@ -872,7 +874,7 @@ ei_send_seat_bind(struct ei_seat *seat, uint32_t capabilities)
}
int
ei_send_frame(struct ei_device *device)
ei_send_frame(struct ei_device *device, uint64_t time)
{
struct ei *ei = ei_device_get_context(device);
@ -884,7 +886,7 @@ ei_send_frame(struct ei_device *device)
device->send_frame_event = false;
int rc = ei->requests->frame(device);
int rc = ei->requests->frame(device, time);
if (rc)
ei_disconnect(ei);
return rc;
@ -1131,14 +1133,14 @@ handle_msg_stop_emulating(struct ei *ei, uint32_t deviceid)
}
static int
handle_msg_frame(struct ei *ei, uint32_t deviceid)
handle_msg_frame(struct ei *ei, uint32_t deviceid, uint64_t time)
{
DISCONNECT_IF_SENDER_CONTEXT(ei);
struct ei_device *device = ei_find_device(ei, deviceid);
if (device)
return ei_device_event_frame(device);
return ei_device_event_frame(device, time);
return 0;
}
@ -1427,6 +1429,22 @@ ei_configure_name(struct ei *ei, const char *name)
ei->name = xstrdup(name);
}
_public_ uint64_t
ei_now(struct ei *ei)
{
uint64_t ts = 0;
int rc = now(&ts);
if (rc < 0) {
/* We should probably disconnect here but the chances of this
* happening are so slim it's not worth worrying about. Plus,
* if this fails we're likely to be inside eis_device_frame()
* so we should flush a frame event before disconnecting and... */
log_error(ei, "clock_gettime failed: %s\n", strerror(-rc));
}
return ts;
}
#ifdef _enable_tests_
#include "util-munit.h"

View file

@ -762,6 +762,12 @@ struct ei_device *
ei_event_get_device(struct ei_event *event);
/**
* Return the time for the event of type @ref EI_EVENT_FRAME in microseconds.
*
* @note: This function is currently only implemented for events of type @ref
* EI_EVENT_FRAME. In the future, it may become available to other event types
* too.
*
* @return the event time in microseconds
*/
uint64_t
@ -1153,9 +1159,16 @@ ei_device_stop_emulating(struct ei_device *device);
* Generate a frame event to group the current set of events
* into a logical hardware event. This function **must** be called after any
* other event has been generated.
*
* The given timestamp applies to all events in the current frame.
* The timestamp must be in microseconds of CLOCK_MONOTONIC, use the return
* value of ei_now() to get a compatible timestamp.
*
* @note libei does not prevent a caller from passing in a future time but it
* is strongly recommended that this is avoided by the caller.
*/
void
ei_device_frame(struct ei_device *device);
ei_device_frame(struct ei_device *device, uint64_t time);
/**
* Generate a relative motion event on a device with
@ -1564,6 +1577,16 @@ ei_event_touch_get_x(struct ei_event *event);
double
ei_event_touch_get_y(struct ei_event *event);
/**
* @returns a timestamp in microseconds for the current time to pass into
* ei_device_frame().
*
* In the current implementation, the returned timestamp is CLOCK_MONOTONIC
* for compatibility with evdev and libinput.
*/
uint64_t
ei_now(struct ei *ei);
/**
* @}
*/

View file

@ -298,14 +298,14 @@ client_msg_stop_emulating(struct eis_client *client, uint32_t deviceid)
}
static int
client_msg_frame(struct eis_client *client, uint32_t deviceid)
client_msg_frame(struct eis_client *client, uint32_t deviceid, uint64_t time)
{
DISCONNECT_IF_RECEIVER_CONTEXT(client);
struct eis_device *device = eis_client_find_device(client, deviceid);
if (device)
return eis_device_event_frame(device);
return eis_device_event_frame(device, time);
return 0;
}

View file

@ -308,13 +308,21 @@ eis_device_has_capability(struct eis_device *device,
eis->requests->func_(device_, device->id, __VA_ARGS__); \
}
static void
eis_device_frame_now(struct eis_device *device)
{
uint64_t now = eis_now(eis_device_get_context(device));
eis_device_frame(device, now);
}
static void
_flush_frame(struct eis_device *device, const char *func)
{
if (device->send_frame_event) {
log_bug_client(eis_device_get_context(device),
"%s: missing call to eis_device_frame()\n", func);
eis_device_frame(device);
eis_device_frame_now(device);
}
}
#define eis_device_flush_frame(d_) _flush_frame(d_, __func__)
@ -564,7 +572,7 @@ eis_touch_destroy(struct eis_touch *touch)
eis_touch_up(touch);
/* Enforce a frame, otherwise we're just pending. If the client
* doesn't want this, it needs to eis_touch_up() */
eis_device_frame(touch->device);
eis_device_frame_now(touch->device);
eis_device_unref(touch->device);
}
@ -654,7 +662,7 @@ eis_touch_up(struct eis_touch *touch)
}
_public_ void
eis_device_frame(struct eis_device *device)
eis_device_frame(struct eis_device *device, uint64_t time)
{
if (device->state != EIS_DEVICE_STATE_EMULATING)
return;
@ -665,16 +673,16 @@ eis_device_frame(struct eis_device *device)
device->send_frame_event = false;
handle_request_noargs(device, frame);
handle_request(device, frame, time);
}
int
eis_device_event_frame(struct eis_device *device)
eis_device_event_frame(struct eis_device *device, uint64_t time)
{
if (device->state != EIS_DEVICE_STATE_EMULATING)
return -EINVAL;
eis_queue_frame_event(device);
eis_queue_frame_event(device, time);
return 0;
}

View file

@ -172,6 +172,14 @@ check_event_type(struct eis_event *event,
if (!check_event_type(event_, __func__, __VA_ARGS__, -1)) \
return retval_; \
_public_ uint64_t
eis_event_get_time(struct eis_event *event)
{
require_event_type(event, 0, EIS_EVENT_FRAME);
return event->timestamp;
}
_public_ bool
eis_event_seat_has_capability(struct eis_event *event, enum eis_device_capability cap)
{

View file

@ -174,6 +174,8 @@ struct eis_event {
struct eis_seat *seat;
struct eis_device *device;
uint64_t timestamp;
union {
struct {
uint32_t capabilities;
@ -286,7 +288,7 @@ eis_device_set_client_keymap(struct eis_device *device,
enum eis_keymap_type type,
int keymap_fd, size_t size);
int
eis_device_event_frame(struct eis_device *device);
eis_device_event_frame(struct eis_device *device, uint64_t time);
int
eis_device_event_pointer_rel(struct eis_device *device,
@ -371,7 +373,7 @@ void
eis_queue_device_closed_event(struct eis_device *device);
void
eis_queue_frame_event(struct eis_device *device);
eis_queue_frame_event(struct eis_device *device, uint64_t time);
void
eis_queue_device_start_emulating_event(struct eis_device *device);

View file

@ -440,11 +440,12 @@ eis_proto_send_touch_up(struct eis_device *device, uint32_t deviceid, uint32_t t
}
static int
eis_proto_send_frame(struct eis_device *device, uint32_t deviceid)
eis_proto_send_frame(struct eis_device *device, uint32_t deviceid, uint64_t time)
{
prepare_msg(FRAME, Frame, frame);
frame.deviceid = device->id;
frame.timestamp = time;
return eis_proto_send_msg(eis_device_get_client(device), &msg);
}
@ -613,7 +614,7 @@ eis_proto_handle_message(struct eis_client *client,
proto->touch_up->touchid);
break;
case CLIENT_MESSAGE__MSG_FRAME:
rc = call(frame, client, proto->frame->deviceid);
rc = call(frame, client, proto->frame->deviceid, proto->frame->timestamp);
break;
default:
rc = -EBADMSG;

View file

@ -61,7 +61,7 @@ struct eis_proto_interface {
int (*touch_motion)(struct eis_client *client, uint32_t deviceid,
uint32_t tid, double x, double y);
int (*touch_up)(struct eis_client *client, uint32_t deviceid, uint32_t tid);
int (*frame) (struct eis_client *client, uint32_t deviceid);
int (*frame) (struct eis_client *client, uint32_t deviceid, uint64_t time);
};
struct eis_proto_requests {
@ -97,7 +97,7 @@ struct eis_proto_requests {
int (*touch_motion)(struct eis_device *device, uint32_t deviceid,
uint32_t tid, double x, double y);
int (*touch_up)(struct eis_device *device, uint32_t deviceid, uint32_t tid);
int (*frame) (struct eis_device *device, uint32_t deviceid);
int (*frame) (struct eis_device *device, uint32_t deviceid, uint64_t time);
};
int

View file

@ -33,6 +33,7 @@
#include "util-object.h"
#include "util-sources.h"
#include "util-strings.h"
#include "util-time.h"
#include "libeis.h"
#include "libeis-proto.h"
@ -164,7 +165,7 @@ eis_queue_event(struct eis_event *event)
default:
if (device) {
if (device->queue_frame_event)
eis_queue_frame_event(device);
eis_queue_frame_event(device, eis_now(eis));
device->queue_frame_event = false;
}
break;
@ -222,10 +223,11 @@ eis_queue_device_closed_event(struct eis_device *device)
}
void
eis_queue_frame_event(struct eis_device *device)
eis_queue_frame_event(struct eis_device *device, uint64_t time)
{
struct eis_event *e = eis_event_new_for_device(device);
e->type = EIS_EVENT_FRAME;
e->timestamp = time;
eis_queue_event(e);
}
@ -392,3 +394,19 @@ eis_add_client(struct eis *eis, struct eis_client *client)
{
list_append(&eis->clients, &client->link);
}
_public_ uint64_t
eis_now(struct eis *eis)
{
uint64_t ts = 0;
int rc = now(&ts);
if (rc < 0) {
/* We should probably disconnect here but the chances of this
* happening are so slim it's not worth worrying about. Plus,
* if this fails we're likely to be inside ei_device_frame()
* so we should flush a frame event before disconnecting and... */
log_error(eis, "clock_gettime failed: %s\n", strerror(-rc));
}
return ts;
}

View file

@ -953,7 +953,7 @@ eis_device_stop_emulating(struct eis_device *device);
/** see @ref ei_device_frame */
void
eis_device_frame(struct eis_device *device);
eis_device_frame(struct eis_device *device, uint64_t time);
/** see @ref ei_device_pointer_motion */
void
@ -1044,6 +1044,18 @@ eis_event_seat_has_capability(struct eis_event *event, enum eis_device_capabilit
struct eis_device *
eis_event_get_device(struct eis_event *event);
/**
* Return the time for the event of type @ref EIS_EVENT_FRAME in microseconds.
*
* @note: This function is currently only implemented for events of type @ref
* EIS_EVENT_FRAME. In the future, it may become available to other event types
* too.
*
* @return the event time in microseconds
*/
uint64_t
eis_event_get_time(struct eis_event *event);
/**
* For an event of type @ref EIS_EVENT_POINTER_MOTION return the relative x
* movement in logical pixels or mm, depending on the device type.
@ -1177,6 +1189,16 @@ eis_event_touch_get_x(struct eis_event *event);
double
eis_event_touch_get_y(struct eis_event *event);
/**
* @returns a timestamp for the current time to pass into
* eis_device_frame().
*
* In the current implementation, the returned timestamp is CLOCK_MONOTONIC
* for compatibility with evdev and libinput.
*/
uint64_t
eis_now(struct eis *ei);
/**
* @}
*/

79
src/util-time.h Normal file
View file

@ -0,0 +1,79 @@
/* SPDX-License-Identifier: MIT */
/*
* Copyright © 2020 Red Hat, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
#pragma once
#include "config.h"
#include <assert.h>
#include <errno.h>
#include <time.h>
#include <stdint.h>
/* Merely for code readability, e.g. timeout = us(100); */
static inline uint64_t
us(uint64_t us)
{
return us;
}
static inline uint64_t
us2ms(uint64_t us)
{
return us * 1000;
}
static inline uint64_t
ns2us(uint64_t ns)
{
return us(ns / 1000);
}
static inline uint64_t
ms2us(uint64_t ms)
{
return us(ms * 1000);
}
static inline uint64_t
s2us(uint64_t s)
{
return ms2us(s * 1000);
}
static inline int
now(uint64_t *now_out)
{
struct timespec ts = { 0, 0 };
assert(now_out != NULL);
if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) {
*now_out = s2us(ts.tv_sec) + ns2us(ts.tv_nsec);
return 0;
} else {
return -errno;
}
}

View file

@ -40,6 +40,7 @@
#include "util-logger.h"
#include "util-object.h"
#include "util-strings.h"
#include "util-time.h"
DEFINE_TRISTATE(yes, no, unset);
@ -64,6 +65,8 @@ struct peck {
struct ei_device *ei_abs;
struct ei_device *ei_touch;
uint64_t now;
struct eis_client *eis_client;
uint32_t indent;
@ -212,6 +215,34 @@ peck_ei_get_default_touch(struct peck *peck)
return peck->ei_touch;
};
/* Ensures that device frames in tests always have an ascending and fixed
* interval. We start with 30 * interval in the past, every event then goes
* forward by 10ms.
*
* Tests that have more than 30 events will run into the future with their
* timestamps, shouldn't be an issue for the test suite though.
*/
uint64_t
peck_ei_now(struct peck *peck)
{
const uint32_t interval = ms2us(10);
const uint32_t past_offset = interval * 30;
peck->now = peck->now == 0 ? ei_now(peck->ei) - past_offset : peck->now + interval;
return peck->now;
}
uint64_t
peck_eis_now(struct peck *peck)
{
const uint32_t interval = ms2us(10);
const uint32_t past_offset = interval * 30;
peck->now = peck->now == 0 ? eis_now(peck->eis) - past_offset : peck->now + interval;
return peck->now;
}
static void
peck_ei_log_handler(struct ei *ei,
enum ei_log_priority priority,
@ -655,6 +686,7 @@ _peck_dispatch_eis(struct peck *peck, int lineno)
struct eis *eis = peck->eis;
bool had_event = false;
bool need_frame = false;
static uint64_t last_timestamp;
log_debug(peck, "EIS Dispatch, line %d\n", lineno);
peck_indent(peck);
@ -747,6 +779,16 @@ _peck_dispatch_eis(struct peck *peck, int lineno)
case EIS_EVENT_DEVICE_CLOSED:
peck_eis_device_remove(peck, eis_event_get_device(e));
break;
case EIS_EVENT_FRAME: {
uint64_t timestamp = eis_event_get_time(e);
uint64_t ts_now = 0;
munit_assert_int(now(&ts_now), ==, 0);
munit_assert_int64(last_timestamp, <, timestamp);
munit_assert_int64(last_timestamp, <=, ts_now);
last_timestamp = timestamp;
break;
}
default:
break;
}

View file

@ -23,6 +23,7 @@
*/
#include "config.h"
#include <stdint.h>
#pragma once
@ -194,6 +195,12 @@ peck_ei_get_default_pointer_absolute(struct peck *peck);
struct ei_device *
peck_ei_get_default_touch(struct peck *peck);
uint64_t
peck_ei_now(struct peck *peck);
uint64_t
peck_eis_now(struct peck *peck);
/**
* Dispatch all events according to the currently defined behavior.
* When this function returns false, the connection is in a "stable" state

View file

@ -283,9 +283,9 @@ MUNIT_TEST(test_ei_device_keyboard_key)
with_client(peck) {
struct ei_device *device = peck_ei_get_default_keyboard(peck);
ei_device_keyboard_key(device, KEY_Q, true);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_keyboard_key(device, KEY_Q, false);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -317,11 +317,11 @@ MUNIT_TEST(test_ei_device_pointer_rel)
with_client(peck) {
struct ei_device *device = peck_ei_get_default_pointer(peck);
ei_device_pointer_motion(device, 1, 2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_motion(device, 0.3, 1.4);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_motion(device, 100, 200);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -498,7 +498,7 @@ MUNIT_TEST(test_ei_device_pointer_abs)
for (int i = 0; i < 10; i++) {
ei_device_pointer_motion_absolute(device, 1 * i , 2 + i);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
}
@ -522,9 +522,9 @@ MUNIT_TEST(test_ei_device_pointer_abs)
/* outside of pointer range, expect to be discarded */
ei_device_pointer_motion_absolute(device, maxx + 1, maxy/2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_motion_absolute(device, maxx/2 , maxy + 1);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -567,9 +567,9 @@ MUNIT_TEST(test_ei_device_pointer_scroll)
with_client(peck) {
struct ei_device *device = peck_ei_get_default_pointer(peck);
ei_device_pointer_scroll(device, 1.1, 2.2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_discrete(device, 3, 4);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -601,26 +601,26 @@ MUNIT_TEST(test_ei_device_pointer_scroll_stop)
with_client(peck) {
struct ei_device *device = peck_ei_get_default_pointer(peck);
ei_device_pointer_scroll(device, 1.1, 2.2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_stop(device, true, false);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_stop(device, false, true);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
/* This should not generate an event */
ei_device_pointer_scroll_stop(device, true, true);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
/* But scrolling again will re-enable stopping */
ei_device_pointer_scroll(device, 3.3, 4.4);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_stop(device, true, true);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll(device, 3.3, 4.4);
/* This one is a client bug and shouldn't trigger an event */
ei_device_pointer_scroll_stop(device, false, false);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -670,26 +670,26 @@ MUNIT_TEST(test_ei_device_pointer_scroll_cancel)
with_client(peck) {
struct ei_device *device = peck_ei_get_default_pointer(peck);
ei_device_pointer_scroll(device, 1.1, 2.2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_cancel(device, true, false);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_cancel(device, false, true);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
/* This should not generate an event */
ei_device_pointer_scroll_cancel(device, true, true);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
/* But scrolling again will re-enable stopping */
ei_device_pointer_scroll(device, 3.3, 4.4);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_cancel(device, true, true);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll(device, 3.3, 4.4);
/* This one is a client bug and shouldn't trigger an event */
ei_device_pointer_scroll_cancel(device, false, false);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -740,17 +740,17 @@ MUNIT_TEST(test_ei_device_pointer_scroll_stop_cancel)
with_client(peck) {
struct ei_device *device = peck_ei_get_default_pointer(peck);
ei_device_pointer_scroll(device, 1.1, 2.2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_stop(device, true, false);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_cancel(device, true, false);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_pointer_scroll_cancel(device, false, true);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
/* This should not generate an event */
ei_device_pointer_scroll_stop(device, true, true);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -802,11 +802,11 @@ MUNIT_TEST(test_ei_device_touch)
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 1, 2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_motion(t, 200, 500);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -828,19 +828,19 @@ MUNIT_TEST(test_ei_device_touch)
_unref_(ei_touch) *t = ei_device_touch_new(device);
/* outside clip range, expect touch to be dropped */
ei_touch_down(t, maxx + 1, maxy/2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_motion(t, maxx + 1, maxy/3);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
/* outside clip range, expect touch to be dropped */
ei_touch_down(t, maxx/2, maxy + 1);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_motion(t, maxx/3, maxy + 1);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -852,12 +852,12 @@ MUNIT_TEST(test_ei_device_touch)
with_client(peck) {
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 100, 200);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
/* outside allowed range, generates a touch up */
ei_touch_motion(t, maxx + 1, 200);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -871,7 +871,7 @@ MUNIT_TEST(test_ei_device_touch)
with_client(peck) {
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 100, 100);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
/* client forgets to touch up, touch_unref takes care of it */
}
@ -890,14 +890,14 @@ MUNIT_TEST(test_ei_device_touch)
/* touch never set down */
_unref_(ei_touch) *t2 = ei_device_touch_new(device);
ei_touch_up(t2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
/* touch never set down */
_unref_(ei_touch) *t3 = ei_device_touch_new(device);
ei_touch_motion(t3, 100, 200);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t3);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -909,15 +909,15 @@ MUNIT_TEST(test_ei_device_touch)
/* touch re-used */
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 100, 200);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_down(t, 200, 300);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_motion(t, 300, 400);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -932,15 +932,15 @@ MUNIT_TEST(test_ei_device_touch)
/* double-down, double-up */
_unref_(ei_touch) *t = ei_device_touch_new(device);
ei_touch_down(t, 100, 200);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_down(t, 200, 300); /* ignored */
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_motion(t, 300, 400);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t); /* ignored */
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
}
peck_dispatch_until_stable(peck);
@ -972,14 +972,14 @@ MUNIT_TEST(test_ei_device_multitouch)
_unref_(ei_touch) *t1 = ei_device_touch_new(device);
_unref_(ei_touch) *t2 = ei_device_touch_new(device);
ei_touch_down(t1, 1, 2);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_motion(t1, 2, 3);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_down(t2, 3, 4);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_motion(t2, 4, 5);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_touch_up(t2);
ei_touch_up(t1);
@ -1153,6 +1153,53 @@ MUNIT_TEST(test_ei_keyboard_modifiers)
return MUNIT_OK;
}
MUNIT_TEST(test_ei_frame_timestamp)
{
_unref_(peck) *peck = peck_new();
uint64_t ts1 = 0, ts2 = 0;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_dispatch_until_stable(peck);
with_client(peck) {
ts1 = peck_ei_now(peck);
struct ei_device *device = peck_ei_get_default_keyboard(peck);
ei_device_keyboard_key(device, KEY_Q, true);
ei_device_frame(device, ts1);
ts2 = peck_ei_now(peck);
ei_device_keyboard_key(device, KEY_Q, false);
ei_device_frame(device, ts2);
}
peck_dispatch_until_stable(peck);
with_server(peck) {
_unref_(eis_event) *kbd1 =
peck_eis_next_event(eis, EIS_EVENT_KEYBOARD_KEY);
_unref_(eis_event) *frame1 =
peck_eis_next_event(eis, EIS_EVENT_FRAME);
_unref_(eis_event) *kbd2 =
peck_eis_next_event(eis, EIS_EVENT_KEYBOARD_KEY);
_unref_(eis_event) *frame2 =
peck_eis_next_event(eis, EIS_EVENT_FRAME);
uint64_t timestamp = eis_event_get_time(frame1);
munit_assert_uint64(timestamp, ==, ts1);
timestamp = eis_event_get_time(frame2);
munit_assert_uint64(timestamp, ==, ts2);
peck_assert_no_eis_events(eis);
}
return MUNIT_OK;
}
MUNIT_TEST(test_ei_no_empty_frames)
{
_unref_(peck) *peck = peck_new();
@ -1166,10 +1213,10 @@ MUNIT_TEST(test_ei_no_empty_frames)
with_client(peck) {
struct ei_device *device = peck_ei_get_default_keyboard(peck);
ei_device_frame(device); /* Expect to be filtered */
ei_device_frame(device, peck_ei_now(peck)); /* Expect to be filtered */
ei_device_keyboard_key(device, KEY_Q, true);
ei_device_frame(device);
ei_device_frame(device); /* Expect to be filtered */
ei_device_frame(device, peck_ei_now(peck));
ei_device_frame(device, peck_ei_now(peck)); /* Expect to be filtered */
}
peck_dispatch_until_stable(peck);
@ -1317,9 +1364,9 @@ MUNIT_TEST(test_passive_ei_device_keyboard_key)
with_server(peck) {
struct eis_device *device = peck_eis_get_default_keyboard(peck);
eis_device_keyboard_key(device, KEY_Q, true);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_keyboard_key(device, KEY_Q, false);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1364,11 +1411,11 @@ MUNIT_TEST(test_passive_ei_device_pointer_rel)
with_server(peck) {
struct eis_device *device = peck_eis_get_default_pointer(peck);
eis_device_pointer_motion(device, 1, 2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_motion(device, 0.3, 1.4);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_motion(device, 100, 200);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1421,7 +1468,7 @@ MUNIT_TEST(test_passive_ei_device_pointer_abs)
for (int i = 0; i < 10; i++) {
eis_device_pointer_motion_absolute(device, 1 * i , 2 + i);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
}
@ -1445,9 +1492,9 @@ MUNIT_TEST(test_passive_ei_device_pointer_abs)
/* outside of pointer range, expect to be discarded */
eis_device_pointer_motion_absolute(device, maxx + 1, maxy/2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_motion_absolute(device, maxx/2 , maxy + 1);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1500,9 +1547,9 @@ MUNIT_TEST(test_passive_ei_device_pointer_scroll)
with_server(peck) {
struct eis_device *device = peck_eis_get_default_pointer(peck);
eis_device_pointer_scroll(device, 1.1, 2.2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll_discrete(device, 3, 4);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1547,26 +1594,26 @@ MUNIT_TEST(test_passive_ei_device_pointer_scroll_stop)
with_server(peck) {
struct eis_device *device = peck_eis_get_default_pointer(peck);
eis_device_pointer_scroll(device, 1.1, 2.2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll_stop(device, true, false);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll_stop(device, false, true);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
/* This should not generate an event */
eis_device_pointer_scroll_stop(device, true, true);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
/* But scrolling again will re-enable stopping */
eis_device_pointer_scroll(device, 3.3, 4.4);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll_stop(device, true, true);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll(device, 3.3, 4.4);
/* This one is a client bug and shouldn't trigger an event */
eis_device_pointer_scroll_stop(device, false, false);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1629,26 +1676,26 @@ MUNIT_TEST(test_passive_ei_device_pointer_scroll_cancel)
with_server(peck) {
struct eis_device *device = peck_eis_get_default_pointer(peck);
eis_device_pointer_scroll(device, 1.1, 2.2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll_cancel(device, true, false);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll_cancel(device, false, true);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
/* This should not generate an event */
eis_device_pointer_scroll_cancel(device, true, true);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
/* But scrolling again will re-enable stopping */
eis_device_pointer_scroll(device, 3.3, 4.4);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll_cancel(device, true, true);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll(device, 3.3, 4.4);
/* This one is a client bug and shouldn't trigger an event */
eis_device_pointer_scroll_cancel(device, false, false);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1712,21 +1759,21 @@ MUNIT_TEST(test_passive_ei_device_pointer_scroll_stop_cancel)
with_server(peck) {
struct eis_device *device = peck_eis_get_default_pointer(peck);
eis_device_pointer_scroll(device, 1.1, 2.2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
peck_mark(peck);
eis_device_pointer_scroll_stop(device, true, false);
peck_mark(peck);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll_cancel(device, true, false);
peck_mark(peck);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_pointer_scroll_cancel(device, false, true);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
peck_mark(peck);
/* This should not generate an event */
eis_device_pointer_scroll_stop(device, true, true);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1793,11 +1840,11 @@ MUNIT_TEST(test_passive_ei_device_touch)
_unref_(eis_touch) *t = eis_device_touch_new(device);
eis_touch_down(t, 1, 2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_motion(t, 200, 500);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1818,19 +1865,19 @@ MUNIT_TEST(test_passive_ei_device_touch)
_unref_(eis_touch) *t = eis_device_touch_new(device);
/* outside clip range, expect touch to be dropped */
eis_touch_down(t, maxx + 1, maxy/2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_motion(t, maxx + 1, maxy/3);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
/* outside clip range, expect touch to be dropped */
eis_touch_down(t, maxx/2, maxy + 1);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_motion(t, maxx/3, maxy + 1);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1842,12 +1889,12 @@ MUNIT_TEST(test_passive_ei_device_touch)
with_server(peck) {
_unref_(eis_touch) *t = eis_device_touch_new(device);
eis_touch_down(t, 100, 200);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
/* outside allowed range, generates a touch up */
eis_touch_motion(t, maxx + 1, 200);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1861,7 +1908,7 @@ MUNIT_TEST(test_passive_ei_device_touch)
with_server(peck) {
_unref_(eis_touch) *t = eis_device_touch_new(device);
eis_touch_down(t, 100, 100);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
/* client forgets to touch up, touch_unref takes care of it */
}
@ -1880,14 +1927,14 @@ MUNIT_TEST(test_passive_ei_device_touch)
/* touch never set down */
_unref_(eis_touch) *t2 = eis_device_touch_new(device);
eis_touch_up(t2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
/* touch never set down */
_unref_(eis_touch) *t3 = eis_device_touch_new(device);
eis_touch_motion(t3, 100, 200);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t3);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1899,15 +1946,15 @@ MUNIT_TEST(test_passive_ei_device_touch)
/* touch re-used */
_unref_(eis_touch) *t = eis_device_touch_new(device);
eis_touch_down(t, 100, 200);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_down(t, 200, 300);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_motion(t, 300, 400);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1922,15 +1969,15 @@ MUNIT_TEST(test_passive_ei_device_touch)
/* double-down, double-up */
_unref_(eis_touch) *t = eis_device_touch_new(device);
eis_touch_down(t, 100, 200);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_down(t, 200, 300); /* ignored */
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_motion(t, 300, 400);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t); /* ignored */
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
}
peck_dispatch_until_stable(peck);
@ -1963,18 +2010,18 @@ MUNIT_TEST(test_passive_ei_device_multitouch)
_unref_(eis_touch) *t2 = eis_device_touch_new(device);
eis_device_start_emulating(device);
eis_touch_down(t1, 1, 2);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_motion(t1, 2, 3);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_down(t2, 3, 4);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_motion(t2, 4, 5);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_touch_up(t2);
eis_touch_up(t1);
eis_device_frame(device);
eis_device_frame(device, peck_eis_now(peck));
eis_device_stop_emulating(device);
}
@ -2011,6 +2058,60 @@ MUNIT_TEST(test_passive_ei_device_multitouch)
return MUNIT_OK;
}
MUNIT_TEST(test_passive_ei_frame_timestamp)
{
_unref_(peck) *peck = peck_new_context(PECK_EI_RECEIVER);
uint64_t ts1 = 0, ts2 = 0;
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_NONE);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ACCEPT_ALL);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_RESUME_DEVICE);
peck_enable_eis_behavior(peck, PECK_EIS_BEHAVIOR_ADD_KEYBOARD);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_NONE);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTOCONNECT);
peck_enable_ei_behavior(peck, PECK_EI_BEHAVIOR_AUTODEVICES);
peck_dispatch_until_stable(peck);
with_server(peck) {
struct eis_device *device = peck_eis_get_default_keyboard(peck);
eis_device_start_emulating(device);
ts1 = peck_eis_now(peck);
eis_device_keyboard_key(device, KEY_Q, true);
eis_device_frame(device, ts1);
ts2 = peck_eis_now(peck);
eis_device_keyboard_key(device, KEY_Q, false);
eis_device_frame(device, ts2);
}
peck_dispatch_until_stable(peck);
with_client(peck) {
_unref_(ei_event) *start =
peck_ei_next_event(ei, EI_EVENT_DEVICE_START_EMULATING);
_unref_(ei_event) *kbd1 =
peck_ei_next_event(ei, EI_EVENT_KEYBOARD_KEY);
_unref_(ei_event) *frame1 =
peck_ei_next_event(ei, EI_EVENT_FRAME);
_unref_(ei_event) *kbd2 =
peck_ei_next_event(ei, EI_EVENT_KEYBOARD_KEY);
_unref_(ei_event) *frame2 =
peck_ei_next_event(ei, EI_EVENT_FRAME);
uint64_t timestamp = ei_event_get_time(frame1);
munit_assert_uint64(timestamp, ==, ts1);
timestamp = ei_event_get_time(frame2);
munit_assert_uint64(timestamp, ==, ts2);
peck_assert_no_ei_events(ei);
}
return MUNIT_OK;
}
MUNIT_TEST(test_passive_ei_flush_frame)
{
_unref_(peck) *peck = peck_new_context(PECK_EI_RECEIVER);

View file

@ -921,7 +921,7 @@ MUNIT_TEST(test_xdotool_rel_motion)
with_client(peck) {
struct ei_device *device = peck_ei_get_default_pointer(peck);
ei_device_pointer_motion(device, -1, 10);
ei_device_frame(device);
ei_device_frame(device, peck_ei_now(peck));
ei_device_close(device);
ei_unref(ei);
peck_drop_ei(peck);

View file

@ -58,6 +58,7 @@
#include "src/util-memfile.h"
#include "src/util-color.h"
#include "src/util-strings.h"
#include "src/util-time.h"
DEFINE_UNREF_CLEANUP_FUNC(ei);
DEFINE_UNREF_CLEANUP_FUNC(ei_device);
@ -445,29 +446,38 @@ int main(int argc, char **argv)
}
if (!receiver) {
uint64_t now = ei_now(ei);
uint32_t interval = us2ms(10); /* pretend events are 10ms apart */
if (have_ptr) {
colorprint("sending motion event\n");
ei_device_pointer_motion(ptr, -1, 1);
/* BTN_LEFT */
colorprint("sending button event\n");
ei_device_pointer_button(ptr, BTN_LEFT, true);
ei_device_frame(ptr);
ei_device_frame(ptr, now);
now += interval;
ei_device_pointer_button(ptr, BTN_LEFT, false);
ei_device_frame(ptr);
ei_device_frame(ptr, now);
now += interval;
colorprint("sending scroll events\n");
ei_device_pointer_scroll(ptr, 1, 1);
ei_device_frame(ptr);
ei_device_frame(ptr, now);
now += interval;
ei_device_pointer_scroll_discrete(ptr, 1, 1);
ei_device_frame(ptr);
ei_device_frame(ptr, now);
now += interval;
}
if (have_kbd) {
static int key = 0;
colorprint("sending key event\n");
ei_device_keyboard_key(kbd, KEY_Q + key, true); /* KEY_Q */
ei_device_frame(kbd);
ei_device_frame(kbd, now);
now += interval;
ei_device_keyboard_key(kbd, KEY_Q + key, false); /* KEY_Q */
ei_device_frame(kbd);
ei_device_frame(kbd, now);
now += interval;
key = (key + 1) % 6;
}
@ -475,7 +485,8 @@ int main(int argc, char **argv)
static int x, y;
colorprint("sending abs event\n");
ei_device_pointer_motion_absolute(abs, 150 + ++x, 150 - ++y);
ei_device_frame(abs);
ei_device_frame(abs, now);
now += interval;
}
}
}

View file

@ -58,6 +58,7 @@
#include "src/util-mem.h"
#include "src/util-memfile.h"
#include "src/util-strings.h"
#include "src/util-time.h"
#include "eis-demo-server.h"
@ -575,6 +576,9 @@ int main(int argc, char **argv)
}
struct eis_demo_client *democlient;
uint64_t now = eis_now(eis);
const int interval = ms2us(12); /* events are 12ms apart */
list_for_each(democlient, &server.clients, link) {
if (eis_client_is_sender(democlient->client))
continue;
@ -588,23 +592,29 @@ int main(int argc, char **argv)
/* BTN_LEFT */
colorprint("sending button event\n");
eis_device_pointer_button(ptr, BTN_LEFT, true);
eis_device_frame(ptr);
eis_device_frame(ptr, now);
now += interval;
eis_device_pointer_button(ptr, BTN_LEFT, false);
eis_device_frame(ptr);
eis_device_frame(ptr, now);
now += interval;
colorprint("sending scroll events\n");
eis_device_pointer_scroll(ptr, 1, 1);
eis_device_frame(ptr);
eis_device_frame(ptr, now);
now += interval;
eis_device_pointer_scroll_discrete(ptr, 1, 1);
eis_device_frame(ptr);
eis_device_frame(ptr, now);
now += interval;
}
if (kbd) {
static int key = 0;
colorprint("sending key event\n");
eis_device_keyboard_key(kbd, KEY_Q + key, true); /* KEY_Q */
eis_device_frame(kbd);
eis_device_frame(kbd, now);
now += interval;
eis_device_keyboard_key(kbd, KEY_Q + key, false); /* KEY_Q */
eis_device_frame(kbd);
eis_device_frame(kbd, now);
now += interval;
key = (key + 1) % 6;
}
@ -612,7 +622,8 @@ int main(int argc, char **argv)
static int x, y;
colorprint("sending abs event\n");
eis_device_pointer_motion_absolute(abs, 150 + ++x, 150 - ++y);
eis_device_frame(abs);
eis_device_frame(abs, now);
now += interval;
}
}
}