EVENT_FILTER_DISCARD, /**< Discard current event */
};
+/* Keeps a record of touches during SYN_DROPPED */
+enum touch_state {
+ TOUCH_OFF,
+ TOUCH_STARTED, /* Started during SYN_DROPPED */
+ TOUCH_STOPPED, /* Stopped during SYN_DROPPED */
+ TOUCH_ONGOING, /* Existed before, still have same tracking ID */
+ TOUCH_CHANGED, /* Existed before but have new tracking ID now, so
+ stopped + started in that slot */
+};
+
+struct slot_change_state {
+ enum touch_state state;
+ unsigned long axes[NLONGS(ABS_CNT)]; /* bitmask for updated axes */
+};
+
static int sync_mt_state(struct libevdev *dev, int create_events);
static inline int*
struct input_absinfo abs_info;
int rc;
int last_reported_slot = 0;
- unsigned long slot_update[dev->num_slots][NLONGS(ABS_CNT)];
- unsigned long tracking_id_changes[NLONGS(dev->num_slots)];
-
+ struct slot_change_state changes[dev->num_slots];
int need_tracking_id_changes = 0;
- memset(slot_update, 0, sizeof(slot_update));
- memset(tracking_id_changes, 0, sizeof(tracking_id_changes));
+ memset(changes, 0, sizeof(changes));
for (int axis = ABS_MT_MIN; axis <= ABS_MT_MAX; axis++) {
/* EVIOCGMTSLOTS required format */
int val_before = *slot_value(dev, slot, axis),
val_after = mt_state.val[slot];
+ if (axis == ABS_MT_TRACKING_ID) {
+ if (val_before == -1 && val_after != -1) {
+ changes[slot].state = TOUCH_STARTED;
+ } else if (val_before != -1 && val_after == -1) {
+ changes[slot].state = TOUCH_STOPPED;
+ } else if (val_before != -1 && val_after != -1 &&
+ val_before == val_after) {
+ changes[slot].state = TOUCH_ONGOING;
+ } else if (val_before != -1 && val_after != -1 &&
+ val_before != val_after) {
+ changes[slot].state = TOUCH_CHANGED;
+ need_tracking_id_changes = 1;
+ } else {
+ changes[slot].state = TOUCH_OFF;
+ }
+ }
+
if (val_before == val_after)
continue;
- if (axis == ABS_MT_TRACKING_ID &&
- val_before != -1 && val_after != -1) {
- set_bit(tracking_id_changes, slot);
- need_tracking_id_changes = 1;
- }
-
*slot_value(dev, slot, axis) = val_after;
- set_bit(slot_update[slot], axis);
+ set_bit(changes[slot].axes, axis);
/* note that this slot has updates */
- set_bit(slot_update[slot], ABS_MT_SLOT);
+ set_bit(changes[slot].axes, ABS_MT_SLOT);
}
}
if (need_tracking_id_changes) {
for (int slot = 0; slot < dev->num_slots; slot++) {
- if (!bit_is_set(tracking_id_changes, slot))
+ if (changes[slot].state != TOUCH_CHANGED)
continue;
queue_push_event(dev, EV_ABS, ABS_MT_SLOT, slot);
}
for (int slot = 0; slot < dev->num_slots; slot++) {
- if (!bit_is_set(slot_update[slot], ABS_MT_SLOT))
+ if (!bit_is_set(changes[slot].axes, ABS_MT_SLOT))
continue;
queue_push_event(dev, EV_ABS, ABS_MT_SLOT, slot);
!libevdev_has_event_code(dev, EV_ABS, axis))
continue;
- if (bit_is_set(slot_update[slot], axis))
+ if (bit_is_set(changes[slot].axes, axis))
queue_push_event(dev, EV_ABS, axis,
*slot_value(dev, slot, axis));
}