Evdev is a 100% stateful protocol. The following is correct, and
represents a double tap:

ABS_MT_SLOT             0       /* Set touch slot */
ABS_MT_TRACKING_ID      0       /* New touch with ID 0 in slot 0 */
ABS_MT_POSITION_X       500     /* Initial X position */
ABS_MT_POSITION_Y       500     /* Initial Y position */
SYNC                            /* End of frame */
ABS_MT_TRACKING_ID      -1      /* Touch in last slot (0) ended */
SYNC                            /* End of frame */
ABS_MT_TRACKING_ID      1       /* New touch in last slot (0) with ID 1 */
SYNC                            /* End of frame */
ABS_MT_TRACKING_ID      -1      /* Touch in last slot (0) ended */
SYNC                            /* End of frame */

Note that touch 1 has the same X and Y position as touch 0. This is
implied because no new value was emitted. In fact, evdev will not emit
an event with the same value as the previous event, even if the driver
reports the event, so we can only assume that all the MT valuators have
the same values as they were when they were last sent.

This change adds a new valuator mask to hold all the last valuator
values that came from evdev. When a new touch begins, all the last
values are copied into it.

Signed-off-by: Chase Douglas <[email protected]>
---
 src/evdev.c |   14 +++++++++-----
 src/evdev.h |    1 +
 2 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 82cdb00..0878716 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -760,13 +760,15 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct 
input_event *ev)
         if (pEvdev->slot_state == SLOTSTATE_EMPTY)
             pEvdev->slot_state = SLOTSTATE_UPDATE;
         if (ev->code == ABS_MT_TRACKING_ID) {
-        if (ev->value >= 0)
-            pEvdev->slot_state = SLOTSTATE_OPEN;
-        else
-            pEvdev->slot_state = SLOTSTATE_CLOSE;
+            if (ev->value >= 0) {
+                pEvdev->slot_state = SLOTSTATE_OPEN;
+                valuator_mask_copy(pEvdev->mt_mask, pEvdev->last_mt_vals);
+            } else
+                pEvdev->slot_state = SLOTSTATE_CLOSE;
         } else {
             map = pEvdev->axis_map[ev->code];
             valuator_mask_set(pEvdev->mt_mask, map, ev->value);
+            valuator_mask_set(pEvdev->last_mt_vals, map, ev->value);
         }
     }
 }
@@ -1250,7 +1252,8 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
 #ifdef MULTITOUCH
     if (num_mt_axes_total > 0) {
         pEvdev->mt_mask = valuator_mask_new(num_mt_axes_total);
-        if (!pEvdev->mt_mask) {
+        pEvdev->last_mt_vals = valuator_mask_new(num_mt_axes_total);
+        if (!pEvdev->mt_mask || !pEvdev->last_mt_vals) {
             xf86Msg(X_ERROR, "%s: failed to allocate MT valuator mask.\n",
                     device->name);
             goto out;
@@ -1428,6 +1431,7 @@ out:
     valuator_mask_free(&pEvdev->prox);
 #ifdef MULTITOUCH
     valuator_mask_free(&pEvdev->mt_mask);
+    valuator_mask_free(&pEvdev->last_mt_vals);
     for (i = 0; i < EVDEV_MAXQUEUE; i++)
         valuator_mask_free(&pEvdev->queue[i].touchMask);
 #endif
diff --git a/src/evdev.h b/src/evdev.h
index 1713b89..76043f9 100644
--- a/src/evdev.h
+++ b/src/evdev.h
@@ -158,6 +158,7 @@ typedef struct {
     ValuatorMask *old_vals; /* old values for calculating relative motion */
     ValuatorMask *prox;     /* last values set while not in proximity */
     ValuatorMask *mt_mask;
+    ValuatorMask *last_mt_vals;
     int cur_slot;
     enum SlotState slot_state;
 #ifdef MULTITOUCH
-- 
1.7.7.3

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to