mirror of
https://gitlab.freedesktop.org/libinput/libinput.git
synced 2026-05-07 18:58:03 +02:00
Hook up event processing to libevdev
This gives us the ability to handle SYN_DROPPED transparently to the caller. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Jonas Ådahl <jadahl@gmail.com>
This commit is contained in:
parent
f925cee8df
commit
0fea6226f1
1 changed files with 58 additions and 31 deletions
89
src/evdev.c
89
src/evdev.c
|
|
@ -29,7 +29,7 @@
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <mtdev.h>
|
#include <mtdev-plumbing.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
#include "libinput.h"
|
#include "libinput.h"
|
||||||
|
|
@ -438,56 +438,83 @@ fallback_dispatch_create(void)
|
||||||
return dispatch;
|
return dispatch;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static inline void
|
||||||
evdev_process_events(struct evdev_device *device,
|
evdev_process_event(struct evdev_device *device, struct input_event *e)
|
||||||
struct input_event *ev, int count)
|
|
||||||
{
|
{
|
||||||
struct evdev_dispatch *dispatch = device->dispatch;
|
struct evdev_dispatch *dispatch = device->dispatch;
|
||||||
struct input_event *e, *end;
|
uint32_t time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
|
||||||
uint32_t time = 0;
|
|
||||||
|
|
||||||
e = ev;
|
dispatch->interface->process(dispatch, device, e, time);
|
||||||
end = e + count;
|
}
|
||||||
for (e = ev; e < end; e++) {
|
|
||||||
time = e->time.tv_sec * 1000 + e->time.tv_usec / 1000;
|
|
||||||
|
|
||||||
dispatch->interface->process(dispatch, device, e, time);
|
static inline void
|
||||||
|
evdev_device_dispatch_one(struct evdev_device *device,
|
||||||
|
struct input_event *ev)
|
||||||
|
{
|
||||||
|
if (!device->mtdev) {
|
||||||
|
evdev_process_event(device, ev);
|
||||||
|
} else {
|
||||||
|
mtdev_put_event(device->mtdev, ev);
|
||||||
|
if (libevdev_event_is_code(ev, EV_SYN, SYN_REPORT)) {
|
||||||
|
while (!mtdev_empty(device->mtdev)) {
|
||||||
|
struct input_event e;
|
||||||
|
mtdev_get_event(device->mtdev, &e);
|
||||||
|
evdev_process_event(device, &e);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
evdev_sync_device(struct evdev_device *device)
|
||||||
|
{
|
||||||
|
struct input_event ev;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
do {
|
||||||
|
rc = libevdev_next_event(device->evdev,
|
||||||
|
LIBEVDEV_READ_FLAG_SYNC, &ev);
|
||||||
|
if (rc < 0)
|
||||||
|
break;
|
||||||
|
evdev_device_dispatch_one(device, &ev);
|
||||||
|
} while (rc == LIBEVDEV_READ_STATUS_SYNC);
|
||||||
|
|
||||||
|
return rc == -EAGAIN ? 0 : rc;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
evdev_device_dispatch(void *data)
|
evdev_device_dispatch(void *data)
|
||||||
{
|
{
|
||||||
struct evdev_device *device = data;
|
struct evdev_device *device = data;
|
||||||
struct libinput *libinput = device->base.seat->libinput;
|
struct libinput *libinput = device->base.seat->libinput;
|
||||||
int fd = device->fd;
|
struct input_event ev;
|
||||||
struct input_event ev[32];
|
int rc;
|
||||||
int len;
|
|
||||||
|
|
||||||
/* If the compositor is repainting, this function is called only once
|
/* If the compositor is repainting, this function is called only once
|
||||||
* per frame and we have to process all the events available on the
|
* per frame and we have to process all the events available on the
|
||||||
* fd, otherwise there will be input lag. */
|
* fd, otherwise there will be input lag. */
|
||||||
do {
|
do {
|
||||||
if (device->mtdev)
|
rc = libevdev_next_event(device->evdev,
|
||||||
len = mtdev_get(device->mtdev, fd, ev,
|
LIBEVDEV_READ_FLAG_NORMAL, &ev);
|
||||||
ARRAY_LENGTH(ev)) *
|
if (rc == LIBEVDEV_READ_STATUS_SYNC) {
|
||||||
sizeof (struct input_event);
|
/* send one more sync event so we handle all
|
||||||
else
|
currently pending events before we sync up
|
||||||
len = read(fd, &ev, sizeof ev);
|
to the current state */
|
||||||
|
ev.code = SYN_REPORT;
|
||||||
|
evdev_device_dispatch_one(device, &ev);
|
||||||
|
|
||||||
if (len < 0 || len % sizeof ev[0] != 0) {
|
rc = evdev_sync_device(device);
|
||||||
if (len < 0 && errno != EAGAIN && errno != EINTR) {
|
if (rc == 0)
|
||||||
libinput_remove_source(libinput,
|
rc = LIBEVDEV_READ_STATUS_SUCCESS;
|
||||||
device->source);
|
} else if (rc == LIBEVDEV_READ_STATUS_SUCCESS) {
|
||||||
device->source = NULL;
|
evdev_device_dispatch_one(device, &ev);
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
} while (rc == LIBEVDEV_READ_STATUS_SUCCESS);
|
||||||
|
|
||||||
evdev_process_events(device, ev, len / sizeof ev[0]);
|
if (rc != -EAGAIN && rc != -EINTR) {
|
||||||
|
libinput_remove_source(libinput, device->source);
|
||||||
} while (len > 0);
|
device->source = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue