[PATCH evdev 6/7] Process of MT events:

Benjamin Tissoires tissoire at cena.fr
Sat Dec 19 03:59:45 PST 2009


* at each MTSyncReport, copy the valuators into the EvdevDataMT (in pEvdev->vals_mt) tha has the same trackingID.
* when receiving the EV_SYNC, if there were some multitouch events and the multitouch is activated, the driver generates all the known touches through their own subdevices by duplicating their valuators into the main one and by calling again "EvdevProcessSyncEvent" without the mutlitouch flag

Signed-off-by: Benjamin Tissoires <tissoire at cena.fr>
---
 src/evdev.c |  221 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 210 insertions(+), 11 deletions(-)

diff --git a/src/evdev.c b/src/evdev.c
index 3722a1c..befb1d4 100644
--- a/src/evdev.c
+++ b/src/evdev.c
@@ -118,6 +118,10 @@ static const char *evdevDefaults[] = {
 static int EvdevOn(DeviceIntPtr);
 static int EvdevCacheCompare(InputInfoPtr pInfo, BOOL compare);
 static void EvdevKbdCtrl(DeviceIntPtr device, KeybdCtrl *ctrl);
+static void EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev);
+static void EvdevCopyFromData(InputInfoPtr pInfo, EvdevDataMTPtr pData);
+static void EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev);
+static void EvdevEndOfMultiTouch(InputInfoPtr pInfo,EvdevDataMTPtr pData);
 static void EvdevSetMultitouch(InputInfoPtr pInfo, int num_multitouch);
 
 #ifdef HAVE_PROPERTIES
@@ -337,6 +341,26 @@ EvdevQueueButtonClicks(InputInfoPtr pInfo, int button, int count)
     }
 }
 
+/**
+ * Timer called to know whether a touch is still alive.
+ */
+static CARD32
+EvdevSubdevTimer(OsTimerPtr timer, CARD32 time, pointer arg)
+{
+    InputInfoPtr pInfo = (InputInfoPtr)arg;
+    EvdevPtr pEvdev = pInfo->private;
+    int i;
+    
+    for (i=0;i<pEvdev->num_multitouch;i++) {
+        if (pEvdev->vals_mt[i].containsValues) {
+            EvdevEndOfMultiTouch(pInfo, &(pEvdev->vals_mt[i]));
+        }
+    }
+    
+    return 0;
+    //return pEvdev->timeout; /* come back in 100 ms */
+}
+
 #define ABS_X_VALUE 0x1
 #define ABS_Y_VALUE 0x2
 #define ABS_VALUE   0x4
@@ -466,6 +490,10 @@ EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
     if (EvdevWheelEmuFilterButton(pInfo, button, value))
         return;
 
+    /* if multitouch enabled, drop Buttons as they are treated by the tracking ID. */
+    if (pEvdev->num_multitouch)
+        return;
+    
     if (EvdevMBEmuFilterEvent(pInfo, button, value))
         return;
 
@@ -586,7 +614,7 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
 
         case BTN_TOUCH:
             pEvdev->tool = value ? ev->code : 0;
-            if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET)))
+            if (!(pEvdev->flags & (EVDEV_TOUCHSCREEN | EVDEV_TABLET | EVDEV_MULTITOUCH)))
                 break;
             /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
              * BTN_LEFT. */
@@ -599,6 +627,67 @@ EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
     }
 }
 
+static void
+EvdevEndOfMultiTouch(InputInfoPtr pInfo,EvdevDataMTPtr pData)
+{
+    InputInfoPtr pSubdev = pData->pInfo;
+    EvdevPtr pEvdevSubdev = pSubdev->private;
+    pEvdevSubdev->id = -1;
+    XIChangeDeviceProperty(pSubdev->dev, prop_tracking_id, XA_INTEGER, 32,
+        PropModeReplace, 1, &(pEvdevSubdev->id), TRUE);
+    
+    pData->containsValues = FALSE;
+    pData->id = -1;
+}
+
+/**
+ * Post the multitouch motion events.
+ */
+static void
+EvdevPostMTMotionEvents(InputInfoPtr pInfo,struct input_event *ev)
+{
+    EvdevPtr pEvdev = pInfo->private, pEvdevSubdev;
+    EvdevDataMTPtr pData;
+    InputInfoPtr pSubdev;
+    Time currentTime = GetTimeInMillis();
+    int i;
+
+    for (i=0;i<pEvdev->num_multitouch;++i) {
+        pData = &(pEvdev->vals_mt[i]);
+        if (!pData->containsValues) {
+            continue;
+        }
+        pSubdev = pData->pInfo;
+        if (!pSubdev)
+            continue;
+
+
+        if (currentTime > pData->expires) {
+            /* the MT-touch has ended, destroy the subdevice. */
+            EvdevEndOfMultiTouch(pInfo, pData);
+            continue;
+        }
+        
+        EvdevCopyFromData(pSubdev, pData);
+        pEvdevSubdev = pSubdev->private;
+        if (pEvdevSubdev->id != pData->id) {
+            pEvdevSubdev->id = pData->id;
+            XIChangeDeviceProperty(pSubdev->dev, prop_tracking_id, XA_INTEGER, 32,
+            PropModeReplace, 1, &(pEvdevSubdev->id), TRUE);
+        }
+        pEvdevSubdev->mt = 0;
+        pEvdevSubdev->abs = 1;
+        pEvdevSubdev->rel = 0;
+        pEvdevSubdev->tool = 1;
+        /* droping of the pressed/released events */
+        memset(pEvdevSubdev->queue, 0, sizeof(pEvdevSubdev->queue));
+        pEvdevSubdev->num_queue = 0;
+        EvdevProcessSyncEvent(pSubdev, ev);
+        
+    }
+    pEvdev->subdevice_timer = TimerSet(pEvdev->subdevice_timer, 0, pEvdev->timeout, EvdevSubdevTimer, pInfo);
+}
+
 /**
  * Post the relative motion events.
  */
@@ -661,6 +750,109 @@ static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
         }
     }
 }
+static void
+EvdevCopyFromData(InputInfoPtr pInfo, EvdevDataMTPtr pData)
+{
+    EvdevPtr pEvdev = pInfo->private;
+    memcpy(pEvdev->vals, pData->vals, MAX_VALUATORS * sizeof(int));
+    /* we drop the buttons/key events */
+}
+
+static void
+EvdevStoreMTData(InputInfoPtr pInfo, EvdevDataMTPtr pData)
+{
+    EvdevPtr pEvdev = pInfo->private;
+    int id,x,y;
+    Time currentTime = GetTimeInMillis();
+
+    id = pEvdev->current_id;
+    x = pEvdev->vals[pEvdev->axis_map[ABS_MT_POSITION_X]];
+    y = pEvdev->vals[pEvdev->axis_map[ABS_MT_POSITION_Y]];
+
+
+
+    pData->id = id;
+    memcpy(pData->vals, pEvdev->vals, MAX_VALUATORS * sizeof(int));
+    pData->vals[pEvdev->axis_map[ABS_X]] = x;
+    pData->vals[pEvdev->axis_map[ABS_Y]] = y;
+    pData->containsValues = TRUE;
+    pData->expires = currentTime + pEvdev->timeout;
+}
+
+/**
+ * Reset the pEvdev with all values at 0.
+ */
+static void
+EvdevReinitPEvdev(InputInfoPtr pInfo)
+{
+    EvdevPtr pEvdev = pInfo->private;
+    memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
+    memset(pEvdev->queue, 0, sizeof(pEvdev->queue));
+    pEvdev->num_queue = 0;
+    pEvdev->abs = 0;
+    pEvdev->rel = 0;
+    pEvdev->mt = 0;
+    pEvdev->num_mt = 0;
+    pEvdev->current_id = -1;
+}
+
+/**
+ * Take the mt-synchronization input event and process it accordingly.
+ */
+static void
+EvdevProcessMTSyncReport(InputInfoPtr pInfo, struct input_event *ev)
+{
+    EvdevPtr pEvdev = pInfo->private;
+    BOOL found = FALSE;
+    int id;
+    int i;
+    
+    if (!pEvdev->num_multitouch)
+        return;
+
+
+    id = pEvdev->current_id;
+    
+    // ntrig doesn't gives the trackID, generating one
+    if (id < 0) {
+        id = pEvdev->num_mt++;
+        pEvdev->current_id = id;
+    }
+    
+    if (id >= 0) { // the trackID is given by the device
+        /* find the previously associated pData */
+        i = 0;
+        while (i < pEvdev->num_multitouch && pEvdev->vals_mt[i].id != id) {
+
+            ++i;
+        }
+        if (i < pEvdev->num_multitouch) {
+
+            found = TRUE;
+        }
+    }
+
+    if (!found) {
+        /* not found : find the first available pData */
+        i = 0;
+        while (i < pEvdev->num_multitouch && pEvdev->vals_mt[i].containsValues ) {
+            ++i;
+        }
+        if (i < pEvdev->num_multitouch) {
+
+            found = TRUE;
+        }
+    }
+    
+    if (found) {
+        EvdevStoreMTData(pInfo, &(pEvdev->vals_mt[i]));
+    /* commented out to avoid a lot of log. */
+    //} else {
+    //    xf86Msg(X_WARNING, "%s: ignoring event {id=%d} : not enough space to store it. %s:%d\n", pInfo->name,id,__FILE__,__LINE__);
+    }
+    EvdevReinitPEvdev(pInfo);
+    pEvdev->mt = 1;
+}
 
 /**
  * Take the synchronization input event and process it accordingly; the motion
@@ -672,18 +864,24 @@ EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
     int num_v = 0, first_v = 0;
     int v[MAX_VALUATORS];
     EvdevPtr pEvdev = pInfo->private;
+    
+    if (ev->code == SYN_MT_REPORT) {
+        EvdevProcessMTSyncReport(pInfo, ev);
+        return;
+    }
+    
 
-    EvdevProcessValuators(pInfo, v, &num_v, &first_v);
-
-    EvdevPostRelativeMotionEvents(pInfo, &num_v, &first_v, v);
-    EvdevPostAbsoluteMotionEvents(pInfo, &num_v, &first_v, v);
-    EvdevPostQueuedEvents(pInfo, &num_v, &first_v, v);
+    if (pEvdev->mt) {
+        EvdevPostMTMotionEvents(pInfo, ev);
+    } else {
+        EvdevProcessValuators(pInfo, v, &num_v, &first_v);
 
-    memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
-    memset(pEvdev->queue, 0, sizeof(pEvdev->queue));
-    pEvdev->num_queue = 0;
-    pEvdev->abs = 0;
-    pEvdev->rel = 0;
+        EvdevPostRelativeMotionEvents(pInfo, &num_v, &first_v, v);
+        EvdevPostAbsoluteMotionEvents(pInfo, &num_v, &first_v, v);
+        EvdevPostQueuedEvents(pInfo, &num_v, &first_v, v);
+    }
+    
+    EvdevReinitPEvdev(pInfo);
 }
 
 /**
@@ -2142,6 +2340,7 @@ EvdevPreInit(InputDriverPtr drv, IDevPtr dev, int flags)
     /* mt initializations. */
     pEvdev->id = -1;
     pEvdev->core_device = pInfo;
+    pEvdev->num_multitouch = 0;
 
     /*
      * We initialize pEvdev->tool to 1 so that device that doesn't use
-- 
1.6.5.2


--------------090208080606020807080800--


More information about the xorg-devel mailing list