#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;
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;
+}
+
+
/**
- * Set ev to the first element in the queue, shifting everything else
- * forward by one.
+ * Shift the first n elements into ev and return the number of elements
+ * shifted.
+ * ev must be large enough to store n elements.
*
- * @return 0 on success, 1 if the queue is empty.
+ * @param ev The buffer to copy into, or NULL
+ * @return The number of elements in ev.
*/
static inline int
-queue_shift(struct libevdev *dev, struct input_event *ev)
+queue_shift_multiple(struct libevdev *dev, int n, struct input_event *ev)
{
int i;
if (dev->queue_next == 0)
- return 1;
+ return 0;
- *ev = dev->queue[0];
+ n = min(n, dev->queue_next);
- for (i = 0; i < dev->queue_next - 1; i++)
- dev->queue[i] = dev->queue[i + 1];
+ if (ev) {
+ for (i = 0; i < n; i++)
+ ev[i] = dev->queue[i];
+ }
- dev->queue_next--;
+ for (i = 0; i < dev->queue_next - n; i++)
+ dev->queue[i] = dev->queue[n + i];
- return 0;
+ dev->queue_next -= n;
+ return n;
+}
+
+/**
+ * Set ev to the first element in the queue, shifting everything else
+ * forward by one.
+ *
+ * @return 0 on success, 1 if the queue is empty.
+ */
+static inline int
+queue_shift(struct libevdev *dev, struct input_event *ev)
+{
+ return queue_shift_multiple(dev, 1, ev) == 1 ? 0 : 1;
}
static inline int
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))