mirror of
https://gitlab.freedesktop.org/libevdev/libevdev.git
synced 2025-12-25 00:00:15 +01:00
After a SYN_DROPPED, drop all events in the queue
Ideally, we could sync by pre-pending all the sync events and then pretend nothing happened but our queue is too small and likely too full for any extra events. So drop all events, then add the sync events to the queue. Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
This commit is contained in:
parent
549f0f0bcd
commit
ec093aa398
2 changed files with 72 additions and 14 deletions
|
|
@ -35,6 +35,19 @@
|
|||
#define ABS_MT_MAX ABS_MT_TOOL_Y
|
||||
#define ABS_MT_CNT (ABS_MT_MAX - ABS_MT_MIN + 1)
|
||||
|
||||
#undef min
|
||||
#undef max
|
||||
#define min(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _b : _a; \
|
||||
})
|
||||
#define max(a,b) \
|
||||
({ __typeof__ (a) _a = (a); \
|
||||
__typeof__ (b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
})
|
||||
|
||||
struct libevdev {
|
||||
int fd;
|
||||
libevdev_log_func_t log;
|
||||
|
|
@ -90,6 +103,46 @@ queue_pop(struct libevdev *dev, struct input_event *ev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
queue_peek(struct libevdev *dev, size_t idx, struct input_event *ev)
|
||||
{
|
||||
if (idx > dev->queue_next)
|
||||
return 1;
|
||||
*ev = dev->queue[idx];
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Shift the first n elements into ev and return the number of elements
|
||||
* shifted.
|
||||
* ev must be large enough to store n elements.
|
||||
*
|
||||
* @param ev The buffer to copy into, or NULL
|
||||
* @return The number of elements in ev.
|
||||
*/
|
||||
static inline int
|
||||
queue_shift_multiple(struct libevdev *dev, int n, struct input_event *ev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dev->queue_next == 0)
|
||||
return 0;
|
||||
|
||||
n = min(n, dev->queue_next);
|
||||
|
||||
if (ev) {
|
||||
for (i = 0; i < n; i++)
|
||||
ev[i] = dev->queue[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < dev->queue_next - n; i++)
|
||||
dev->queue[i] = dev->queue[n + i];
|
||||
|
||||
dev->queue_next -= n;
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ev to the first element in the queue, shifting everything else
|
||||
* forward by one.
|
||||
|
|
@ -99,19 +152,7 @@ queue_pop(struct libevdev *dev, struct input_event *ev)
|
|||
static inline int
|
||||
queue_shift(struct libevdev *dev, struct input_event *ev)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (dev->queue_next == 0)
|
||||
return 1;
|
||||
|
||||
*ev = dev->queue[0];
|
||||
|
||||
for (i = 0; i < dev->queue_next - 1; i++)
|
||||
dev->queue[i] = dev->queue[i + 1];
|
||||
|
||||
dev->queue_next--;
|
||||
|
||||
return 0;
|
||||
return queue_shift_multiple(dev, 1, ev) == 1 ? 0 : 1;
|
||||
}
|
||||
|
||||
static inline int
|
||||
|
|
|
|||
|
|
@ -381,13 +381,30 @@ out:
|
|||
static int
|
||||
sync_state(struct libevdev *dev)
|
||||
{
|
||||
int i;
|
||||
int rc = 0;
|
||||
struct input_event *ev;
|
||||
|
||||
/* FIXME: if we have events in the queue after the SYN_DROPPED (which was
|
||||
queue[0]) we need to shift this backwards somehow.
|
||||
queue[0]) we need to shift this backwards. Except that chances are that the
|
||||
queue may be either full or too full to prepend all the events needed for
|
||||
syncing.
|
||||
|
||||
so we search for the last sync event in the queue and drop everything before
|
||||
including that event and rely on the kernel to tell us the right value for that
|
||||
bitfield during the sync process.
|
||||
*/
|
||||
|
||||
for (i = queue_num_elements(dev) - 1; i >= 0; i--) {
|
||||
struct input_event e;
|
||||
queue_peek(dev, i, &e);
|
||||
if (e.type == EV_SYN)
|
||||
break;
|
||||
}
|
||||
|
||||
if (i > 0)
|
||||
queue_shift_multiple(dev, i + 1, NULL);
|
||||
|
||||
if (libevdev_has_event_type(dev, EV_KEY))
|
||||
rc = sync_key_state(dev);
|
||||
if (rc == 0 && libevdev_has_event_type(dev, EV_ABS))
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue