mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-02-03 11:10:29 +01:00
Introduce our own evdev_event struct
In addition to the evdev_frame this struct is what contains our actual events instead of a struct input_event. The goal of this is twofold: slightly better memory usage per frame since we can skip the timestamp and refer to the evdev frame's timestamp only. This also improves handling a frame since we no longer need to care about updating all events when the timestamp changes during appending events. Secondly it merges the evdev type + code into a single "usage" (term obviously and shamelessly stolen from HID). Those usages are the same as the code names but with an extra EVDEV_ prepended, i.e. EV_SYN / SYN_REPORT becomes EVDEV_SYN_REPORT. And they are wrapped in a newtype so passing it around provides some typesafety. This only switches one part of the processing over, the dispatch interfaces still use a struct input_event Part-of: <https://gitlab.freedesktop.org/libinput/libinput/-/merge_requests/1215>
This commit is contained in:
parent
540605f8e4
commit
41e988c99e
5 changed files with 299 additions and 119 deletions
|
|
@ -303,6 +303,7 @@ foreach h: util_headers
|
|||
executable('test-build-@0@'.format(h),
|
||||
testfile,
|
||||
include_directories : [includes_src, includes_include],
|
||||
dependencies: [dep_libevdev],
|
||||
install : false)
|
||||
endforeach
|
||||
|
||||
|
|
|
|||
|
|
@ -28,10 +28,223 @@
|
|||
|
||||
#include "util-mem.h"
|
||||
#include "util-input-event.h"
|
||||
#include "util-newtype.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <linux/input.h>
|
||||
|
||||
#define _evbit(t_, c_) ((t_) << 16 | (c_))
|
||||
|
||||
/**
|
||||
* This is an enum to have the compiler help us a bit.
|
||||
* The enum doesn't need to contain all event codes, only
|
||||
* the ones we use in libinput - add to here as required.
|
||||
*
|
||||
* The order doesn't matter either since each enum value
|
||||
* is just the type | code value anyway, keep it in somewhat
|
||||
* logical groups where possible.
|
||||
*/
|
||||
enum evdev_usage {
|
||||
EVDEV_SYN_REPORT = _evbit(EV_SYN, SYN_REPORT),
|
||||
|
||||
EVDEV_KEY_RESERVED = _evbit(EV_KEY, KEY_RESERVED),
|
||||
EVDEV_KEY_ESC= _evbit(EV_KEY, KEY_ESC),
|
||||
EVDEV_KEY_MICMUTE = _evbit(EV_KEY, KEY_MICMUTE),
|
||||
EVDEV_KEY_OK = _evbit(EV_KEY, KEY_OK),
|
||||
EVDEV_KEY_LIGHTS_TOGGLE = _evbit(EV_KEY, KEY_LIGHTS_TOGGLE),
|
||||
EVDEV_KEY_ALS_TOGGLE = _evbit(EV_KEY, KEY_ALS_TOGGLE),
|
||||
EVDEV_KEY_MAX = _evbit(EV_KEY, KEY_MAX),
|
||||
|
||||
EVDEV_BTN_LEFT = _evbit(EV_KEY, BTN_LEFT),
|
||||
EVDEV_BTN_RIGHT = _evbit(EV_KEY, BTN_RIGHT),
|
||||
EVDEV_BTN_MIDDLE = _evbit(EV_KEY, BTN_MIDDLE),
|
||||
EVDEV_BTN_SIDE = _evbit(EV_KEY, BTN_SIDE),
|
||||
EVDEV_BTN_EXTRA = _evbit(EV_KEY, BTN_EXTRA),
|
||||
EVDEV_BTN_FORWARD = _evbit(EV_KEY, BTN_FORWARD),
|
||||
EVDEV_BTN_BACK = _evbit(EV_KEY, BTN_BACK),
|
||||
EVDEV_BTN_TASK = _evbit(EV_KEY, BTN_TASK),
|
||||
|
||||
EVDEV_BTN_JOYSTICK = _evbit(EV_KEY, BTN_JOYSTICK),
|
||||
|
||||
EVDEV_BTN_0 = _evbit(EV_KEY, BTN_0),
|
||||
EVDEV_BTN_1 = _evbit(EV_KEY, BTN_1),
|
||||
EVDEV_BTN_2 = _evbit(EV_KEY, BTN_2),
|
||||
|
||||
EVDEV_BTN_STYLUS = _evbit(EV_KEY, BTN_STYLUS),
|
||||
EVDEV_BTN_STYLUS2 = _evbit(EV_KEY, BTN_STYLUS2),
|
||||
EVDEV_BTN_STYLUS3 = _evbit(EV_KEY, BTN_STYLUS3),
|
||||
|
||||
EVDEV_BTN_TOUCH = _evbit(EV_KEY, BTN_TOUCH),
|
||||
EVDEV_BTN_TOOL_PEN = _evbit(EV_KEY, BTN_TOOL_PEN),
|
||||
EVDEV_BTN_TOOL_RUBBER = _evbit(EV_KEY, BTN_TOOL_RUBBER),
|
||||
EVDEV_BTN_TOOL_BRUSH = _evbit(EV_KEY, BTN_TOOL_BRUSH),
|
||||
EVDEV_BTN_TOOL_PENCIL = _evbit(EV_KEY, BTN_TOOL_PENCIL),
|
||||
EVDEV_BTN_TOOL_AIRBRUSH = _evbit(EV_KEY, BTN_TOOL_AIRBRUSH),
|
||||
EVDEV_BTN_TOOL_MOUSE = _evbit(EV_KEY, BTN_TOOL_MOUSE),
|
||||
EVDEV_BTN_TOOL_LENS = _evbit(EV_KEY, BTN_TOOL_LENS),
|
||||
EVDEV_BTN_TOOL_QUINTTAP = _evbit(EV_KEY, BTN_TOOL_QUINTTAP),
|
||||
EVDEV_BTN_TOOL_DOUBLETAP = _evbit(EV_KEY, BTN_TOOL_DOUBLETAP),
|
||||
EVDEV_BTN_TOOL_TRIPLETAP = _evbit(EV_KEY, BTN_TOOL_TRIPLETAP),
|
||||
EVDEV_BTN_TOOL_QUADTAP = _evbit(EV_KEY, BTN_TOOL_QUADTAP),
|
||||
EVDEV_BTN_TOOL_FINGER = _evbit(EV_KEY, BTN_TOOL_FINGER),
|
||||
EVDEV_BTN_MISC = _evbit(EV_KEY, BTN_MISC),
|
||||
EVDEV_BTN_GEAR_UP = _evbit(EV_KEY, BTN_GEAR_UP),
|
||||
EVDEV_BTN_DPAD_UP = _evbit(EV_KEY, BTN_DPAD_UP),
|
||||
EVDEV_BTN_DPAD_RIGHT = _evbit(EV_KEY, BTN_DPAD_RIGHT),
|
||||
EVDEV_BTN_TRIGGER_HAPPY = _evbit(EV_KEY, BTN_TRIGGER_HAPPY),
|
||||
EVDEV_BTN_TRIGGER_HAPPY40 = _evbit(EV_KEY, BTN_TRIGGER_HAPPY40),
|
||||
|
||||
EVDEV_REL_X = _evbit(EV_REL, REL_X),
|
||||
EVDEV_REL_Y = _evbit(EV_REL, REL_Y),
|
||||
EVDEV_REL_WHEEL = _evbit(EV_REL, REL_WHEEL),
|
||||
EVDEV_REL_WHEEL_HI_RES = _evbit(EV_REL, REL_WHEEL_HI_RES),
|
||||
EVDEV_REL_HWHEEL = _evbit(EV_REL, REL_HWHEEL),
|
||||
EVDEV_REL_HWHEEL_HI_RES = _evbit(EV_REL, REL_HWHEEL_HI_RES),
|
||||
EVDEV_REL_DIAL = _evbit(EV_REL, REL_DIAL),
|
||||
EVDEV_REL_MAX = _evbit(EV_REL, REL_MAX),
|
||||
|
||||
EVDEV_ABS_X = _evbit(EV_ABS, ABS_X),
|
||||
EVDEV_ABS_Y = _evbit(EV_ABS, ABS_Y),
|
||||
EVDEV_ABS_Z = _evbit(EV_ABS, ABS_Z),
|
||||
EVDEV_ABS_RX = _evbit(EV_ABS, ABS_RX),
|
||||
EVDEV_ABS_RY = _evbit(EV_ABS, ABS_RY),
|
||||
EVDEV_ABS_RZ = _evbit(EV_ABS, ABS_RZ),
|
||||
EVDEV_ABS_PRESSURE = _evbit(EV_ABS, ABS_PRESSURE),
|
||||
EVDEV_ABS_DISTANCE = _evbit(EV_ABS, ABS_DISTANCE),
|
||||
EVDEV_ABS_THROTTLE = _evbit(EV_ABS, ABS_THROTTLE),
|
||||
EVDEV_ABS_RUDDER = _evbit(EV_ABS, ABS_RUDDER),
|
||||
EVDEV_ABS_WHEEL = _evbit(EV_ABS, ABS_WHEEL),
|
||||
EVDEV_ABS_MISC = _evbit(EV_ABS, ABS_MISC),
|
||||
EVDEV_ABS_TILT_X = _evbit(EV_ABS, ABS_TILT_X),
|
||||
EVDEV_ABS_TILT_Y = _evbit(EV_ABS, ABS_TILT_Y),
|
||||
|
||||
EVDEV_ABS_MT_SLOT = _evbit(EV_ABS, ABS_MT_SLOT),
|
||||
EVDEV_ABS_MT_POSITION_X = _evbit(EV_ABS, ABS_MT_POSITION_X),
|
||||
EVDEV_ABS_MT_POSITION_Y = _evbit(EV_ABS, ABS_MT_POSITION_Y),
|
||||
EVDEV_ABS_MT_TOOL_TYPE = _evbit(EV_ABS, ABS_MT_TOOL_TYPE),
|
||||
EVDEV_ABS_MT_TRACKING_ID = _evbit(EV_ABS, ABS_MT_TRACKING_ID),
|
||||
EVDEV_ABS_MT_TOUCH_MAJOR = _evbit(EV_ABS, ABS_MT_TOUCH_MAJOR),
|
||||
EVDEV_ABS_MT_TOUCH_MINOR = _evbit(EV_ABS, ABS_MT_TOUCH_MINOR),
|
||||
EVDEV_ABS_MT_ORIENTATION = _evbit(EV_ABS, ABS_MT_ORIENTATION),
|
||||
EVDEV_ABS_MT_PRESSURE = _evbit(EV_ABS, ABS_MT_PRESSURE),
|
||||
EVDEV_ABS_MT_DISTANCE = _evbit(EV_ABS, ABS_MT_DISTANCE),
|
||||
EVDEV_ABS_MAX = _evbit(EV_ABS, ABS_MAX),
|
||||
|
||||
EVDEV_SW_LID = _evbit(EV_SW, SW_LID),
|
||||
EVDEV_SW_TABLET_MODE = _evbit(EV_SW, SW_TABLET_MODE),
|
||||
EVDEV_SW_MAX = _evbit(EV_SW, SW_MAX),
|
||||
|
||||
EVDEV_MSC_SCAN = _evbit(EV_MSC, MSC_SCAN),
|
||||
EVDEV_MSC_SERIAL = _evbit(EV_MSC, MSC_SERIAL),
|
||||
EVDEV_MSC_TIMESTAMP = _evbit(EV_MSC, MSC_TIMESTAMP),
|
||||
};
|
||||
|
||||
/**
|
||||
* Declares evdev_usage_t as uint32_t wrapper that we
|
||||
* use for passing event codes around.
|
||||
*
|
||||
* This way we can't accidentally mix up a code vs
|
||||
* type or a random integer with what needs to be a usage.
|
||||
*/
|
||||
DECLARE_NEWTYPE(evdev_usage, uint32_t);
|
||||
|
||||
static inline evdev_usage_t
|
||||
evdev_usage_from(enum evdev_usage usage)
|
||||
{
|
||||
return evdev_usage_from_uint32_t((uint32_t)usage);
|
||||
}
|
||||
|
||||
static inline enum evdev_usage
|
||||
evdev_usage_enum(evdev_usage_t usage)
|
||||
{
|
||||
return (enum evdev_usage)evdev_usage_as_uint32_t(usage);
|
||||
}
|
||||
|
||||
static inline evdev_usage_t
|
||||
evdev_usage_from_code(unsigned int type, unsigned int code)
|
||||
{
|
||||
return evdev_usage_from_uint32_t(_evbit(type, code));
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
evdev_usage_type(evdev_usage_t usage)
|
||||
{
|
||||
return evdev_usage_as_uint32_t(usage) >> 16;
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
evdev_usage_code(evdev_usage_t usage)
|
||||
{
|
||||
return evdev_usage_as_uint32_t(usage) & 0xFFFF;
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
evdev_usage_code_name(evdev_usage_t usage)
|
||||
{
|
||||
return libevdev_event_code_get_name(evdev_usage_type(usage),
|
||||
evdev_usage_code(usage));
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
evdev_usage_type_name(evdev_usage_t usage)
|
||||
{
|
||||
return libevdev_event_type_get_name(evdev_usage_type(usage));
|
||||
}
|
||||
|
||||
struct evdev_event {
|
||||
/* this may be a value outside the known usages above but it's just an int */
|
||||
evdev_usage_t usage;
|
||||
int32_t value;
|
||||
};
|
||||
|
||||
static inline uint16_t
|
||||
evdev_event_type(const struct evdev_event *e)
|
||||
{
|
||||
return evdev_usage_type(e->usage);
|
||||
}
|
||||
|
||||
static inline uint16_t
|
||||
evdev_event_code(const struct evdev_event *e)
|
||||
{
|
||||
return evdev_usage_code(e->usage);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
evdev_event_get_type_name(const struct evdev_event *e)
|
||||
{
|
||||
return evdev_usage_type_name(e->usage);
|
||||
}
|
||||
|
||||
static inline const char *
|
||||
evdev_event_get_code_name(const struct evdev_event *e)
|
||||
{
|
||||
return evdev_usage_code_name(e->usage);
|
||||
}
|
||||
|
||||
static inline struct input_event
|
||||
evdev_event_to_input_event(const struct evdev_event *e, uint64_t time)
|
||||
{
|
||||
struct timeval tv = us2tv(time);
|
||||
return (struct input_event) {
|
||||
.type = evdev_event_type(e),
|
||||
.code = evdev_event_code(e),
|
||||
.value = e->value,
|
||||
.input_event_sec = tv.tv_sec,
|
||||
.input_event_usec = tv.tv_usec,
|
||||
};
|
||||
}
|
||||
|
||||
static inline struct evdev_event
|
||||
evdev_event_from_input_event(const struct input_event *e, uint64_t *time)
|
||||
{
|
||||
if (time)
|
||||
*time = input_event_time(e);
|
||||
return (struct evdev_event) {
|
||||
.usage = evdev_usage_from_code(e->type, e->code),
|
||||
.value = e->value,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* A wrapper around a SYN_REPORT-terminated set of input events.
|
||||
*
|
||||
|
|
@ -49,7 +262,8 @@ struct evdev_frame {
|
|||
int refcount;
|
||||
size_t max_size;
|
||||
size_t count;
|
||||
struct input_event events[];
|
||||
uint64_t time;
|
||||
struct evdev_event events[];
|
||||
};
|
||||
|
||||
static inline struct evdev_frame *
|
||||
|
|
@ -88,7 +302,7 @@ evdev_frame_get_count(const struct evdev_frame *frame)
|
|||
return frame->count;
|
||||
}
|
||||
|
||||
static inline struct input_event *
|
||||
static inline struct evdev_event *
|
||||
evdev_frame_get_events(struct evdev_frame *frame, size_t *nevents)
|
||||
{
|
||||
if (nevents)
|
||||
|
|
@ -103,24 +317,19 @@ evdev_frame_get_events(struct evdev_frame *frame, size_t *nevents)
|
|||
static inline void
|
||||
evdev_frame_set_time(struct evdev_frame *frame, uint64_t time)
|
||||
{
|
||||
assert(frame->count > 0);
|
||||
|
||||
for (size_t i = 0; i < frame->count; i++)
|
||||
input_event_set_time(&frame->events[i], time);
|
||||
frame->time = time;
|
||||
}
|
||||
|
||||
static inline uint64_t
|
||||
evdev_frame_get_time(const struct evdev_frame *frame)
|
||||
{
|
||||
assert(frame->count > 0);
|
||||
|
||||
return input_event_time(&frame->events[frame->count - 1]);
|
||||
return frame->time;
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_frame_reset(struct evdev_frame *frame)
|
||||
{
|
||||
memset(frame->events, 0, frame->max_size * sizeof(struct input_event));
|
||||
memset(frame->events, 0, frame->max_size * sizeof(*frame->events));
|
||||
frame->count = 1; /* SYN_REPORT is always there */
|
||||
|
||||
return 0;
|
||||
|
|
@ -129,7 +338,7 @@ evdev_frame_reset(struct evdev_frame *frame)
|
|||
static inline struct evdev_frame *
|
||||
evdev_frame_new(size_t max_size)
|
||||
{
|
||||
struct evdev_frame *frame = zalloc(max_size * sizeof(struct input_event) + sizeof(*frame));
|
||||
struct evdev_frame *frame = zalloc(max_size * sizeof(sizeof(*frame->events)) + sizeof(*frame));
|
||||
|
||||
frame->refcount = 1;
|
||||
frame->max_size = max_size;
|
||||
|
|
@ -142,12 +351,12 @@ static inline struct evdev_frame *
|
|||
evdev_frame_new_on_stack(size_t max_size)
|
||||
{
|
||||
assert(max_size <= 64);
|
||||
struct evdev_frame *frame = alloca(max_size * sizeof(struct input_event) + sizeof(*frame));
|
||||
struct evdev_frame *frame = alloca(max_size * sizeof(*frame->events) + sizeof(*frame));
|
||||
|
||||
frame->refcount = 1;
|
||||
frame->max_size = max_size;
|
||||
frame->count = 1; /* SYN_REPORT is always there */
|
||||
memset(frame->events, 0, max_size * sizeof(struct input_event));
|
||||
memset(frame->events, 0, max_size * sizeof(*frame->events));
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
|
@ -178,35 +387,41 @@ evdev_frame_new_on_stack(size_t max_size)
|
|||
*/
|
||||
static inline int
|
||||
evdev_frame_append(struct evdev_frame *frame,
|
||||
const struct input_event *events,
|
||||
const struct evdev_event *events,
|
||||
size_t nevents)
|
||||
{
|
||||
assert(nevents > 0);
|
||||
|
||||
uint64_t time = 0;
|
||||
|
||||
for (size_t i = 0; i < nevents; i++) {
|
||||
if (events[i].type == EV_SYN && events[i].code == SYN_REPORT) {
|
||||
if (evdev_usage_eq(events[i].usage, EVDEV_SYN_REPORT)) {
|
||||
nevents = i;
|
||||
time = input_event_time(&events[i]);
|
||||
break;
|
||||
}
|
||||
time = max(time, input_event_time(&events[i]));
|
||||
}
|
||||
|
||||
if (nevents > 0) {
|
||||
if (frame->count + nevents > frame->max_size)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy(frame->events + frame->count - 1, events, nevents * sizeof(struct input_event));
|
||||
memcpy(frame->events + frame->count - 1, events, nevents * sizeof(*events));
|
||||
frame->count += nevents;
|
||||
}
|
||||
if (time)
|
||||
evdev_frame_set_time(frame, time);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
evdev_frame_append_input_event(struct evdev_frame *frame,
|
||||
const struct input_event *event)
|
||||
{
|
||||
struct evdev_event e = evdev_event_from_input_event(event, NULL);
|
||||
if (evdev_usage_as_uint32_t(e.usage) == EVDEV_SYN_REPORT) {
|
||||
uint64_t time = input_event_time(event);
|
||||
evdev_frame_set_time(frame, time);
|
||||
}
|
||||
return evdev_frame_append(frame, &e, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Behaves like evdev_frame_append() but resets the frame before appending.
|
||||
*
|
||||
|
|
@ -216,7 +431,7 @@ evdev_frame_append(struct evdev_frame *frame,
|
|||
*/
|
||||
static inline int
|
||||
evdev_frame_set(struct evdev_frame *frame,
|
||||
const struct input_event *events,
|
||||
const struct evdev_event *events,
|
||||
size_t nevents)
|
||||
{
|
||||
assert(nevents > 0);
|
||||
|
|
@ -224,7 +439,7 @@ evdev_frame_set(struct evdev_frame *frame,
|
|||
size_t count = nevents;
|
||||
|
||||
for (size_t i = 0; i < nevents; i++) {
|
||||
if (events[i].type == EV_SYN && events[i].code == SYN_REPORT) {
|
||||
if (evdev_usage_as_uint32_t(events[i].usage) == EVDEV_SYN_REPORT) {
|
||||
count = i;
|
||||
break;
|
||||
}
|
||||
|
|
@ -241,7 +456,7 @@ static inline struct evdev_frame *
|
|||
evdev_frame_clone(struct evdev_frame *frame)
|
||||
{
|
||||
size_t nevents;
|
||||
struct input_event *events = evdev_frame_get_events(frame, &nevents);
|
||||
struct evdev_event *events = evdev_frame_get_events(frame, &nevents);
|
||||
struct evdev_frame *clone = evdev_frame_new(nevents);
|
||||
|
||||
evdev_frame_append(clone, events, nevents);
|
||||
|
|
|
|||
58
src/evdev.c
58
src/evdev.c
|
|
@ -1027,11 +1027,12 @@ evdev_read_switch_reliability_prop(struct evdev_device *device)
|
|||
_unused_
|
||||
static inline void
|
||||
evdev_print_event(struct evdev_device *device,
|
||||
const struct input_event *e)
|
||||
const struct evdev_event *e,
|
||||
uint64_t time_in_us)
|
||||
{
|
||||
static uint32_t offset = 0;
|
||||
static uint32_t last_time = 0;
|
||||
uint32_t time = us2ms(input_event_time(e));
|
||||
uint32_t time = us2ms(time_in_us);
|
||||
|
||||
if (offset == 0) {
|
||||
offset = time;
|
||||
|
|
@ -1040,7 +1041,8 @@ evdev_print_event(struct evdev_device *device,
|
|||
|
||||
time -= offset;
|
||||
|
||||
if (libevdev_event_is_code(e, EV_SYN, SYN_REPORT)) {
|
||||
switch (evdev_usage_enum(e->usage)) {
|
||||
case EVDEV_SYN_REPORT:
|
||||
evdev_log_debug(device,
|
||||
"%u.%03u ----------------- EV_SYN ----------------- +%ums\n",
|
||||
time / 1000,
|
||||
|
|
@ -1048,53 +1050,63 @@ evdev_print_event(struct evdev_device *device,
|
|||
time - last_time);
|
||||
|
||||
last_time = time;
|
||||
} else if (libevdev_event_is_code(e, EV_MSC, MSC_SERIAL)) {
|
||||
break;
|
||||
case EVDEV_MSC_SERIAL:
|
||||
evdev_log_debug(device,
|
||||
"%u.%03u %-16s %-16s %#010x\n",
|
||||
time / 1000,
|
||||
time % 1000,
|
||||
libevdev_event_type_get_name(e->type),
|
||||
libevdev_event_code_get_name(e->type, e->code),
|
||||
evdev_event_get_type_name(e),
|
||||
evdev_event_get_code_name(e),
|
||||
e->value);
|
||||
} else {
|
||||
break;
|
||||
default:
|
||||
evdev_log_debug(device,
|
||||
"%u.%03u %-16s %-20s %4d\n",
|
||||
time / 1000,
|
||||
time % 1000,
|
||||
libevdev_event_type_get_name(e->type),
|
||||
libevdev_event_code_get_name(e->type, e->code),
|
||||
evdev_event_get_type_name(e),
|
||||
evdev_event_get_code_name(e),
|
||||
e->value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_process_event(struct evdev_device *device, struct input_event *e)
|
||||
evdev_process_event(struct evdev_device *device,
|
||||
struct evdev_event *e,
|
||||
uint64_t time)
|
||||
{
|
||||
struct evdev_dispatch *dispatch = device->dispatch;
|
||||
uint64_t time = input_event_time(e);
|
||||
|
||||
#if EVENT_DEBUGGING
|
||||
evdev_print_event(device, e);
|
||||
evdev_print_event(device, e, time);
|
||||
#endif
|
||||
|
||||
libinput_timer_flush(evdev_libinput_context(device), time);
|
||||
|
||||
dispatch->interface->process(dispatch, device, e, time);
|
||||
struct input_event ev = evdev_event_to_input_event(e, time);
|
||||
dispatch->interface->process(dispatch, device, &ev, time);
|
||||
}
|
||||
|
||||
static inline void
|
||||
evdev_device_dispatch_one(struct evdev_device *device,
|
||||
struct input_event *ev)
|
||||
struct evdev_event *ev,
|
||||
uint64_t time)
|
||||
{
|
||||
if (!device->mtdev) {
|
||||
evdev_process_event(device, ev);
|
||||
evdev_process_event(device, ev, time);
|
||||
} else {
|
||||
mtdev_put_event(device->mtdev, ev);
|
||||
if (libevdev_event_is_code(ev, EV_SYN, SYN_REPORT)) {
|
||||
struct input_event e = evdev_event_to_input_event(ev, time);
|
||||
mtdev_put_event(device->mtdev, &e);
|
||||
if (evdev_usage_eq(ev->usage, EVDEV_SYN_REPORT)) {
|
||||
while (!mtdev_empty(device->mtdev)) {
|
||||
struct input_event e;
|
||||
mtdev_get_event(device->mtdev, &e);
|
||||
evdev_process_event(device, &e);
|
||||
|
||||
uint64_t time;
|
||||
struct evdev_event ev = evdev_event_from_input_event(&e, &time);
|
||||
evdev_process_event(device, &ev, time);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1105,10 +1117,10 @@ evdev_device_dispatch_frame(struct evdev_device *device,
|
|||
struct evdev_frame *frame)
|
||||
{
|
||||
size_t nevents;
|
||||
struct input_event *events = evdev_frame_get_events(frame, &nevents);
|
||||
struct evdev_event *events = evdev_frame_get_events(frame, &nevents);
|
||||
|
||||
for (size_t i = 0; i < nevents; i++) {
|
||||
evdev_device_dispatch_one(device, &events[i]);
|
||||
evdev_device_dispatch_one(device, &events[i], evdev_frame_get_time(frame));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -1127,7 +1139,7 @@ evdev_sync_device(struct evdev_device *device)
|
|||
break;
|
||||
|
||||
/* No ENOMEM check here because >maxevents really should never happen */
|
||||
evdev_frame_append(frame, &ev, 1);
|
||||
evdev_frame_append_input_event(frame, &ev);
|
||||
} while (rc == LIBEVDEV_READ_STATUS_SYNC);
|
||||
|
||||
evdev_device_dispatch_frame(device, frame);
|
||||
|
|
@ -1188,7 +1200,7 @@ evdev_device_dispatch(void *data)
|
|||
to the current state */
|
||||
ev.code = SYN_REPORT;
|
||||
|
||||
if (evdev_frame_append(frame, &ev, 1) == -ENOMEM) {
|
||||
if (evdev_frame_append_input_event(frame, &ev) == -ENOMEM) {
|
||||
evdev_log_bug_libinput(device,
|
||||
"event frame overflow, discarding events.\n");
|
||||
}
|
||||
|
|
@ -1204,7 +1216,7 @@ evdev_device_dispatch(void *data)
|
|||
once = true;
|
||||
}
|
||||
|
||||
if (evdev_frame_append(frame, &ev, 1) == -ENOMEM) {
|
||||
if (evdev_frame_append_input_event(frame, &ev) == -ENOMEM) {
|
||||
evdev_log_bug_libinput(device,
|
||||
"event frame overflow, discarding events.\n");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,9 +27,11 @@
|
|||
|
||||
#include "util-time.h"
|
||||
#include "util-mem.h"
|
||||
#include "util-newtype.h"
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include <linux/input.h>
|
||||
#include <libevdev/libevdev.h>
|
||||
|
||||
static inline struct input_event
|
||||
input_event_init(uint64_t time,
|
||||
|
|
|
|||
|
|
@ -2562,6 +2562,7 @@ END_TEST
|
|||
|
||||
START_TEST(evdev_frames)
|
||||
{
|
||||
#define U(u_) evdev_usage_from_uint32_t(u_)
|
||||
{
|
||||
evdev_frame_unref(NULL); /* unref on NULL is permitted */
|
||||
}
|
||||
|
|
@ -2574,21 +2575,21 @@ START_TEST(evdev_frames)
|
|||
}
|
||||
{
|
||||
_unref_(evdev_frame) *frame = evdev_frame_new(3);
|
||||
struct input_event toobig[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = 1, },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = 2, },
|
||||
{ .type = EV_ABS, .code = ABS_Z, .value = 3, },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0, },
|
||||
struct evdev_event toobig[] = {
|
||||
{ .usage = U(EVDEV_ABS_X), .value = 1, },
|
||||
{ .usage = U(EVDEV_ABS_Y), .value = 2, },
|
||||
{ .usage = U(EVDEV_ABS_Z), .value = 3, },
|
||||
{ .usage = U(EVDEV_SYN_REPORT), .value = 0, },
|
||||
};
|
||||
|
||||
int rc = evdev_frame_set(frame, toobig, ARRAY_LENGTH(toobig));
|
||||
litest_assert_int_eq(rc, -ENOMEM);
|
||||
}
|
||||
{
|
||||
struct input_event events[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = 1, },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = 2, },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0, },
|
||||
struct evdev_event events[] = {
|
||||
{ .usage = U(EVDEV_ABS_X), .value = 1, },
|
||||
{ .usage = U(EVDEV_ABS_Y), .value = 2, },
|
||||
{ .usage = U(EVDEV_SYN_REPORT), .value = 0, },
|
||||
};
|
||||
|
||||
_unref_(evdev_frame) *frame = evdev_frame_new(3);
|
||||
|
|
@ -2607,10 +2608,10 @@ START_TEST(evdev_frames)
|
|||
litest_assert_int_eq(rc, -ENOMEM);
|
||||
}
|
||||
{
|
||||
struct input_event events[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = 1, },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = 2, },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0, },
|
||||
struct evdev_event events[] = {
|
||||
{ .usage = U(EVDEV_ABS_X), .value = 1, },
|
||||
{ .usage = U(EVDEV_ABS_Y), .value = 2, },
|
||||
{ .usage = U(EVDEV_SYN_REPORT), .value = 0, },
|
||||
};
|
||||
|
||||
_unref_(evdev_frame) *frame = evdev_frame_new(3);
|
||||
|
|
@ -2625,13 +2626,13 @@ START_TEST(evdev_frames)
|
|||
litest_assert_int_eq(evdev_frame_get_count(frame), 3U); /* SYN_REPORT already there */
|
||||
}
|
||||
{
|
||||
struct input_event interrupted[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = 1, },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = 2, },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0, },
|
||||
{ .type = EV_ABS, .code = ABS_RX, .value = 1, },
|
||||
{ .type = EV_ABS, .code = ABS_RY, .value = 2, },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0, },
|
||||
struct evdev_event interrupted[] = {
|
||||
{ .usage = U(EVDEV_ABS_X), .value = 1, },
|
||||
{ .usage = U(EVDEV_ABS_Y), .value = 2, },
|
||||
{ .usage = U(EVDEV_SYN_REPORT), .value = 0, },
|
||||
{ .usage = U(EVDEV_ABS_RX), .value = 1, },
|
||||
{ .usage = U(EVDEV_ABS_RY), .value = 2, },
|
||||
{ .usage = U(EVDEV_SYN_REPORT), .value = 0, },
|
||||
};
|
||||
|
||||
_unref_(evdev_frame) *frame = evdev_frame_new(5);
|
||||
|
|
@ -2650,57 +2651,6 @@ START_TEST(evdev_frames)
|
|||
/* We never appended a timestamp */
|
||||
litest_assert_int_eq(evdev_frame_get_time(frame), 0U);
|
||||
}
|
||||
{
|
||||
struct input_event e = {
|
||||
.type = EV_ABS,
|
||||
.code = ABS_X,
|
||||
.value = 1,
|
||||
.input_event_sec = 1234,
|
||||
.input_event_usec = 567,
|
||||
|
||||
};
|
||||
|
||||
_unref_(evdev_frame) *frame = evdev_frame_new(3);
|
||||
litest_assert_int_eq(evdev_frame_get_time(frame), 0U);
|
||||
|
||||
evdev_frame_append(frame, &e, 1);
|
||||
litest_assert_int_eq(evdev_frame_get_time(frame), 1234000567U);
|
||||
evdev_frame_append(frame, &e, 1);
|
||||
litest_assert_int_eq(evdev_frame_get_time(frame), 1234000567U);
|
||||
|
||||
struct input_event syn = {
|
||||
.type = EV_SYN,
|
||||
.code = SYN_REPORT,
|
||||
.value = 0,
|
||||
.input_event_sec = 111,
|
||||
.input_event_usec = 333,
|
||||
|
||||
};
|
||||
|
||||
litest_assert_neg_errno_success(evdev_frame_append(frame, &syn, 1));
|
||||
litest_assert_int_eq(evdev_frame_get_time(frame), 111000333U);
|
||||
|
||||
/* SYN_REPORT overwrites lower timestamp */
|
||||
syn.input_event_usec = 111;
|
||||
litest_assert_neg_errno_success(evdev_frame_append(frame, &syn, 1));
|
||||
litest_assert_int_eq(evdev_frame_get_time(frame), 111000111U);
|
||||
}
|
||||
{
|
||||
/* Expect highest timestamp */
|
||||
_unref_(evdev_frame) *frame = evdev_frame_new(4);
|
||||
struct input_event mixed_times[] = {
|
||||
{ .type = EV_ABS, .code = ABS_X, .value = 1, .input_event_sec = 12, .input_event_usec = 700, },
|
||||
{ .type = EV_ABS, .code = ABS_Y, .value = 2, .input_event_sec = 56, .input_event_usec = 800, },
|
||||
{ .type = EV_ABS, .code = ABS_Z, .value = 3, .input_event_sec = 34, .input_event_usec = 900, },
|
||||
{ .type = EV_SYN, .code = SYN_REPORT, .value = 0, .input_event_sec = 0, .input_event_usec = 1, },
|
||||
};
|
||||
evdev_frame_set(frame, mixed_times, 3);
|
||||
litest_assert_int_eq(evdev_frame_get_time(frame), 56000800U);
|
||||
|
||||
/* but SYN_REPORT overwrites any other timestamp */
|
||||
evdev_frame_set(frame, mixed_times, 4);
|
||||
litest_assert_int_eq(evdev_frame_get_time(frame), 1U);
|
||||
}
|
||||
}
|
||||
END_TEST
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue