[PATCH evdev 8/8] handle multitouch events whithin proximity

Benjamin Tissoires benjamin.tissoires at gmail.com
Wed Jan 9 10:21:22 PST 2013


ABS_MT_DISTANCE controls whether the finger is touching the sensor or not.

When the slot is opened, if the device reports ABS_MT_DISTANCE, we should
rely on it to set the right value of touch. If not, then the creation of
the slot means that the touch began.

Signed-off-by: Benjamin Tissoires <benjamin.tissoires at gmail.com>
---
 src/evdev.c | 38 +++++++++++++++++++++++++++++++-------
 1 file changed, 31 insertions(+), 7 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 256037c..c84b2ac 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -734,7 +734,7 @@ static void
 EvdevProcessTouch(InputInfoPtr pInfo)
 {
     EvdevPtr pEvdev = pInfo->private;
-    int type;
+    int type, map;
     int slot_index = last_mt_vals_slot(pEvdev);
     EvdevMTState *mt_state;
 
@@ -748,9 +748,21 @@ EvdevProcessTouch(InputInfoPtr pInfo)
         return;
 
     if (pEvdev->slot_state == SLOTSTATE_CLOSE)
+        /* in any cases, release the touch when closing the slot */
         mt_state->touch = FALSE;
-    else if (pEvdev->slot_state == SLOTSTATE_OPEN)
-        mt_state->touch = TRUE;
+    else if (pEvdev->slot_state == SLOTSTATE_OPEN) {
+        map = pEvdev->axis_map[ABS_MT_DISTANCE];
+        if (!map)
+            /* The device does not support distance:
+             * getting a new slot means the begining of the touch */
+            mt_state->touch = TRUE;
+        else
+            mt_state->touch = !valuator_mask_get(mt_state->last_vals, map);
+    }
+
+    /* If there is no touch, ignore events within proximity */
+    if (!mt_state->touch && !mt_state->touch_state)
+        return;
 
     type = XI_TouchUpdate;
 
@@ -830,14 +842,21 @@ 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) {
+
+        switch (ev->code) {
+        case ABS_MT_TRACKING_ID:
+            /* open/close the slot => finger getting in/out proximity */
             if (ev->value >= 0) {
                 pEvdev->slot_state = SLOTSTATE_OPEN;
                 valuator_mask_copy(pEvdev->mt_mask,
                                    mt_state->last_vals);
             } else
                 pEvdev->slot_state = SLOTSTATE_CLOSE;
-        } else {
+            break;
+        case ABS_MT_DISTANCE:
+            mt_state->touch = !ev->value;
+            /* intentional fallback */
+        default:
             map = pEvdev->axis_map[ev->code];
             valuator_mask_set(pEvdev->mt_mask, map, ev->value);
             valuator_mask_set(mt_state->last_vals, map, ev->value);
@@ -1453,10 +1472,15 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
                         xf86IDrvMsg(pInfo, X_ERROR, "ioctl EVIOCGMTSLOTS failed: %s\n",
                                     strerror(errno));
                 }
-                for (i = 0; i < num_touches; i++)
-                    valuator_mask_set(pEvdev->mt_state[i].last_vals,
+                for (i = 0; i < num_touches; i++) {
+                    EvdevMTState *mt_state = &pEvdev->mt_state[i];
+                    valuator_mask_set(mt_state->last_vals,
                                       pEvdev->axis_map[axis],
                                       mt_request_data[i]);
+
+                    if (axis == ABS_MT_DISTANCE)
+                        mt_state->touch = !mt_request_data[i];
+                }
             }
         }
 
-- 
1.8.0.2



More information about the xorg-devel mailing list