summaryrefslogtreecommitdiff
path: root/libevdev/libevdev.c
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2013-05-30 12:20:21 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2013-05-30 13:37:44 +1000
commitec093aa39840e79892b409749ac006c9aaa23026 (patch)
tree1834f0b2ec2307b4d1671938aae969c8730811b9 /libevdev/libevdev.c
parent549f0f0bcd3ceec21393e953e13a86a716fc9580 (diff)
downloadlibevdev-ec093aa39840e79892b409749ac006c9aaa23026.tar.gz
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>
Diffstat (limited to 'libevdev/libevdev.c')
-rw-r--r--libevdev/libevdev.c19
1 files changed, 18 insertions, 1 deletions
diff --git a/libevdev/libevdev.c b/libevdev/libevdev.c
index 561d0c5..2c5742e 100644
--- a/libevdev/libevdev.c
+++ b/libevdev/libevdev.c
@@ -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))