[xf86-input-synaptics v3 11/14] Move X touch event processing into synaptics.c

Chase Douglas chase.douglas at canonical.com
Fri Feb 10 11:56:55 PST 2012


Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
---
 src/eventcomm.c     |  169 +++++---------------------------------------------
 src/synaptics.c     |  110 +++++++++++++++++++++++++++++++++
 src/synapticsstr.h  |    1 +
 src/synproto.c      |   19 ++++++
 src/synproto.h      |    1 +
 test/fake-symbols.c |    9 +++
 6 files changed, 157 insertions(+), 152 deletions(-)

diff --git a/src/eventcomm.c b/src/eventcomm.c
index 9197d5d..7b9038e 100644
--- a/src/eventcomm.c
+++ b/src/eventcomm.c
@@ -69,31 +69,18 @@ struct eventcomm_proto_data
     struct mtdev *mtdev;
     int axis_map[MT_ABS_SIZE];
     int cur_slot;
-    enum SynapticsSlotState slot_state;
-    ValuatorMask *mt_mask;
     ValuatorMask **last_mt_vals;
-    unsigned int num_touches;
-    int *open_slots;
 #endif
 };
 
 #ifdef HAVE_MTDEV
 static int
-num_slots(const struct eventcomm_proto_data *proto_data)
-{
-    int value = proto_data->mtdev->caps.slot.maximum -
-                proto_data->mtdev->caps.slot.minimum + 1;
-
-    /* If we don't know how many slots there are, assume at least 10 */
-    return value > 1 ? value : 10;
-}
-
-static int
-last_mt_vals_slot(const struct eventcomm_proto_data *proto_data)
+last_mt_vals_slot(const SynapticsPrivate *priv)
 {
+    struct eventcomm_proto_data *proto_data = (struct eventcomm_proto_data*)priv->proto_data;
     int value = proto_data->cur_slot - proto_data->mtdev->caps.slot.minimum;
 
-    return value < num_slots(proto_data) ? value : -1;
+    return value < priv->num_slots ? value : -1;
 }
 
 static void
@@ -105,15 +92,11 @@ UninitializeTouch(InputInfoPtr pInfo)
     if (!priv->has_touch)
         return;
 
-    free(proto_data->open_slots);
-    proto_data->open_slots = NULL;
-
-    valuator_mask_free(&proto_data->mt_mask);
     if (proto_data->last_mt_vals)
     {
         int i;
 
-        for (i = 0; i < num_slots(proto_data); i++)
+        for (i = 0; i < priv->num_slots; i++)
             valuator_mask_free(&proto_data->last_mt_vals[i]);
         free(proto_data->last_mt_vals);
         proto_data->last_mt_vals = NULL;
@@ -143,19 +126,7 @@ InitializeTouch(InputInfoPtr pInfo)
 
     proto_data->cur_slot = proto_data->mtdev->caps.slot.value;
 
-    /* Axes 0-4 are for X, Y, and scrolling. num_mt_axes does not include X and
-     * Y. */
-    proto_data->mt_mask = valuator_mask_new(4 + priv->num_mt_axes);
-    if (!proto_data->mt_mask)
-    {
-        xf86IDrvMsg(pInfo, X_WARNING,
-                    "failed to create MT valuator mask, ignoring touch "
-                    "events\n");
-        UninitializeTouch(pInfo);
-        return;
-    }
-
-    proto_data->last_mt_vals = calloc(num_slots(proto_data),
+    proto_data->last_mt_vals = calloc(priv->num_slots,
                                       sizeof(ValuatorMask *));
     if (!proto_data->last_mt_vals)
     {
@@ -165,7 +136,7 @@ InitializeTouch(InputInfoPtr pInfo)
         return;
     }
 
-    for (i = 0; i < num_slots(proto_data); i++)
+    for (i = 0; i < priv->num_slots; i++)
     {
         int j;
 
@@ -185,8 +156,6 @@ InitializeTouch(InputInfoPtr pInfo)
         for (j = 0; j < priv->num_mt_axes; j++)
             valuator_mask_set(proto_data->last_mt_vals[i], 4 + j, 0);
     }
-
-    proto_data->open_slots = malloc(num_slots(proto_data) * sizeof(int));
 }
 #endif
 
@@ -515,112 +484,8 @@ SynapticsReadEvent(InputInfoPtr pInfo, struct input_event *ev)
     return rc;
 }
 
-#ifdef HAVE_MTDEV
 static void
-EventBeginTouches(InputInfoPtr pInfo)
-{
-    SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
-    struct eventcomm_proto_data *proto_data = priv->proto_data;
-    int first_slot;
-
-    proto_data->num_touches++;
-    proto_data->open_slots[proto_data->num_touches - 1] = proto_data->cur_slot;
-
-    /* Don't start a touch if it's the only one. */
-    if (proto_data->num_touches < 2)
-        return;
-
-    xf86PostTouchEvent(pInfo->dev, proto_data->cur_slot, XI_TouchBegin, 0,
-                       proto_data->mt_mask);
-
-    /* If this is the third or more touch, we've already begun the first touch.
-     */
-    if (proto_data->num_touches > 2)
-        return;
-
-    /* If this is the second touch, begin the first touch at this time. */
-    first_slot = proto_data->open_slots[0];
-    xf86PostTouchEvent(pInfo->dev, first_slot, XI_TouchBegin, 0,
-                       proto_data->last_mt_vals[first_slot]);
-}
-
-static void
-EventEndTouches(InputInfoPtr pInfo)
-{
-    SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
-    struct eventcomm_proto_data *proto_data = priv->proto_data;
-    int first_slot;
-    int i;
-    Bool found;
-
-    found = FALSE;
-    for (i = 0; i < proto_data->num_touches - 1; i++)
-    {
-        if (proto_data->open_slots[i] == proto_data->cur_slot)
-            found = TRUE;
-
-        if (found)
-            proto_data->open_slots[i] = proto_data->open_slots[i + 1];
-    }
-
-    proto_data->num_touches--;
-
-    /* If this was the only touch left on the device, don't send a touch end
-     * event because we are inhibiting its touch sequence. */
-    if (proto_data->num_touches == 0)
-        return;
-
-    xf86PostTouchEvent(pInfo->dev, proto_data->cur_slot, XI_TouchEnd, 0,
-                       proto_data->mt_mask);
-
-    /* If there is at least two other touches on the device, we don't need to
-     * end any more touches. */
-    if (proto_data->num_touches >= 2)
-        return;
-
-    /* We've gone down to one touch, so we must end the touch as well. */
-    first_slot = proto_data->open_slots[0];
-    xf86PostTouchEvent(pInfo->dev, first_slot, XI_TouchEnd, 0,
-                       proto_data->last_mt_vals[first_slot]);
-}
-#endif
-
-static void
-EventProcessTouch(InputInfoPtr pInfo)
-{
-#ifdef HAVE_MTDEV
-    SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
-    struct eventcomm_proto_data *proto_data = priv->proto_data;
-
-    if (!proto_data || proto_data->cur_slot < 0 || !priv->has_touch)
-        return;
-
-    /* If the ABS_MT_SLOT is the first event we get after EV_SYN, skip this */
-    if (proto_data->slot_state == SLOTSTATE_EMPTY)
-        return;
-
-    switch (proto_data->slot_state)
-    {
-        case SLOTSTATE_CLOSE:
-            EventEndTouches(pInfo);
-            break;
-        case SLOTSTATE_OPEN:
-            EventBeginTouches(pInfo);
-            break;
-        default:
-            if (proto_data->num_touches >= 2)
-                xf86PostTouchEvent(pInfo->dev, proto_data->cur_slot,
-                                   XI_TouchUpdate, 0, proto_data->mt_mask);
-            break;
-    }
-
-    proto_data->slot_state = SLOTSTATE_EMPTY;
-    valuator_mask_zero(proto_data->mt_mask);
-#endif
-}
-
-static void
-EventProcessTouchEvent(InputInfoPtr pInfo, struct CommData *comm,
+EventProcessTouchEvent(InputInfoPtr pInfo, struct SynapticsHwState *hw,
                        struct input_event *ev)
 {
 #ifdef HAVE_MTDEV
@@ -632,33 +497,32 @@ EventProcessTouchEvent(InputInfoPtr pInfo, struct CommData *comm,
 
     if (ev->code == ABS_MT_SLOT)
     {
-        EventProcessTouch(pInfo);
         proto_data->cur_slot = ev->value;
     } else
     {
-        int slot_index = last_mt_vals_slot(proto_data);
+        int slot_index = last_mt_vals_slot(priv);
 
-        if (proto_data->slot_state == SLOTSTATE_EMPTY)
-            proto_data->slot_state = SLOTSTATE_UPDATE;
+        if (hw->slot_state[slot_index] == SLOTSTATE_EMPTY)
+            hw->slot_state[slot_index] = SLOTSTATE_UPDATE;
         if (ev->code == ABS_MT_TRACKING_ID)
         {
             if (ev->value >= 0)
             {
-                proto_data->slot_state = SLOTSTATE_OPEN;
+                hw->slot_state[slot_index] = SLOTSTATE_OPEN;
 
                 if (slot_index >= 0)
-                    valuator_mask_copy(proto_data->mt_mask,
+                    valuator_mask_copy(hw->mt_mask[slot_index],
                                        proto_data->last_mt_vals[slot_index]);
                 else
                     xf86IDrvMsg(pInfo, X_WARNING,
                                 "Attempted to copy values from out-of-range "
                                 "slot, touch events may be incorrect.\n");
             } else
-                proto_data->slot_state = SLOTSTATE_CLOSE;
+                hw->slot_state[slot_index] = SLOTSTATE_CLOSE;
         } else
         {
             int map = proto_data->axis_map[ev->code - ABS_MT_TOUCH_MAJOR];
-            valuator_mask_set(proto_data->mt_mask, map, ev->value);
+            valuator_mask_set(hw->mt_mask[slot_index], map, ev->value);
             if (slot_index >= 0)
                 valuator_mask_set(proto_data->last_mt_vals[slot_index], map,
                                   ev->value);
@@ -700,12 +564,13 @@ EventReadHwState(InputInfoPtr pInfo,
     SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
     SynapticsParameters *para = &priv->synpara;
 
+    SynapticsResetTouchHwState(hw);
+
     while (SynapticsReadEvent(pInfo, &ev)) {
 	switch (ev.type) {
 	case EV_SYN:
 	    switch (ev.code) {
 	    case SYN_REPORT:
-		EventProcessTouch(pInfo);
 		hw->numFingers = count_fingers(comm);
 		hw->millis = 1000 * ev.time.tv_sec + ev.time.tv_usec / 1000;
 		SynapticsCopyHwState(hwRet, hw);
@@ -786,7 +651,7 @@ EventReadHwState(InputInfoPtr pInfo,
 		    break;
 		}
 	    } else
-		EventProcessTouchEvent(pInfo, comm, &ev);
+		EventProcessTouchEvent(pInfo, hw, &ev);
 	    break;
 	}
     }
diff --git a/src/synaptics.c b/src/synaptics.c
index c86351d..551c54b 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -1358,6 +1358,7 @@ timerFunc(OsTimerPtr timer, CARD32 now, pointer arg)
 
     priv->hwState->millis += now - priv->timer_time;
     SynapticsCopyHwState(hw, priv->hwState);
+    SynapticsResetTouchHwState(hw);
     delay = HandleState(pInfo, hw, hw->millis, TRUE);
 
     priv->timer_time = now;
@@ -1397,6 +1398,8 @@ ReadInput(InputInfoPtr pInfo)
     int delay = 0;
     Bool newDelay = FALSE;
 
+    SynapticsResetTouchHwState(hw);
+
     while (SynapticsGetHwState(pInfo, priv, hw)) {
 	SynapticsCopyHwState(priv->hwState, hw);
 	delay = HandleState(pInfo, hw, hw->millis, FALSE);
@@ -2584,6 +2587,111 @@ repeat_scrollbuttons(const InputInfoPtr pInfo,
     return delay;
 }
 
+static void
+HandleTouches(InputInfoPtr pInfo, struct SynapticsHwState *hw)
+{
+#ifdef HAVE_MULTITOUCH
+    SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private;
+    int new_active_touches = priv->num_active_touches;
+    Bool restart_touches = FALSE;
+    int i;
+
+    /* Count new number of active touches */
+    for (i = 0; i < hw->num_mt_mask; i++)
+    {
+        if (hw->slot_state[i] == SLOTSTATE_OPEN)
+            new_active_touches++;
+        else if (hw->slot_state[i] == SLOTSTATE_CLOSE)
+            new_active_touches--;
+    }
+
+    if (priv->num_active_touches < 2 && new_active_touches < 2)
+    {
+        /* We stayed below number of touches needed to send events */
+        goto out;
+    } else if (priv->num_active_touches >= 2 && new_active_touches < 2)
+    {
+        /* We are transitioning to less than the number of touches needed to
+         * send events. End all currently open touches. */
+        for (i = 0; i < priv->num_active_touches; i++)
+        {
+            int slot = priv->open_slots[i];
+            xf86PostTouchEvent(pInfo->dev, slot, XI_TouchEnd, 0,
+                               hw->mt_mask[slot]);
+        }
+
+        /* Don't send any more events */
+        goto out;
+    } else if (priv->num_active_touches < 2 && new_active_touches >= 2)
+    {
+        /* We are transitioning to more than the number of touches needed to
+         * send events. Begin all already open touches. */
+        restart_touches = TRUE;
+        for (i = 0; i < priv->num_active_touches; i++)
+        {
+            int slot = priv->open_slots[i];
+
+            xf86PostTouchEvent(pInfo->dev, slot, XI_TouchBegin, 0,
+                               hw->mt_mask[slot]);
+        }
+    }
+
+    /* Send touch begin events for all new touches */
+    for (i = 0; i < hw->num_mt_mask; i++)
+        if (hw->slot_state[i] == SLOTSTATE_OPEN)
+            xf86PostTouchEvent(pInfo->dev, i, XI_TouchBegin, 0,
+                               hw->mt_mask[i]);
+
+    /* Send touch update/end events for all the rest */
+    for (i = 0; i < priv->num_active_touches; i++)
+    {
+        int slot = priv->open_slots[i];
+
+        /* Don't send update event if we just reopened the touch above */
+        if (hw->slot_state[slot] == SLOTSTATE_UPDATE && !restart_touches)
+            xf86PostTouchEvent(pInfo->dev, slot, XI_TouchUpdate, 0,
+                               hw->mt_mask[slot]);
+        else if (hw->slot_state[slot] == SLOTSTATE_CLOSE)
+            xf86PostTouchEvent(pInfo->dev, slot, XI_TouchEnd, 0,
+                               hw->mt_mask[slot]);
+    }
+            
+out:
+    /* Update the open slots and number of active touches */
+    for (i = 0; i < hw->num_mt_mask; i++)
+    {
+        if (hw->slot_state[i] == SLOTSTATE_OPEN)
+        {
+            priv->open_slots[priv->num_active_touches] = i;
+            priv->num_active_touches++;
+        } else if (hw->slot_state[i] == SLOTSTATE_CLOSE)
+        {
+            Bool found = FALSE;
+            int j;
+
+            for (j = 0; j < priv->num_active_touches - 1; j++)
+            {
+                if (priv->open_slots[j] == i)
+                    found = TRUE;
+
+                if (found)
+                    priv->open_slots[j] = priv->open_slots[j + 1];
+            }
+
+            priv->num_active_touches--;
+        }
+    }
+
+    /* We calculated the value twice, might as well double check our math */
+    if (priv->num_active_touches != new_active_touches)
+        xf86IDrvMsg(pInfo, X_WARNING,
+                    "calculated wrong number of active touches (%d vs %d)\n",
+                    priv->num_active_touches, new_active_touches);
+
+    SynapticsResetTouchHwState(hw);
+#endif
+}
+
 /*
  * React on changes in the hardware state. This function is called every time
  * the hardware state changes. The return value is used to specify how many
@@ -2752,6 +2860,8 @@ HandleState(InputInfoPtr pInfo, struct SynapticsHwState *hw, CARD32 now,
 	post_button_click(pInfo, 1);
     }
 
+    HandleTouches(pInfo, hw);
+
     /* Save old values of some state variables */
     priv->finger_state = finger;
     priv->lastButtons = buttons;
diff --git a/src/synapticsstr.h b/src/synapticsstr.h
index aeaf906..ba1eb13 100644
--- a/src/synapticsstr.h
+++ b/src/synapticsstr.h
@@ -283,6 +283,7 @@ typedef struct _SynapticsPrivateRec
     SynapticsTouchAxisRec *touch_axes;  /* Touch axis information other than X, Y */
     int num_slots;                      /* Number of touch slots allocated */
     int *open_slots;                    /* Array of currently open touch slots */
+    int num_active_touches;             /* Number of active touches on device */
 #endif
 } SynapticsPrivate;
 
diff --git a/src/synproto.c b/src/synproto.c
index 49d333d..0426e8f 100644
--- a/src/synproto.c
+++ b/src/synproto.c
@@ -135,3 +135,22 @@ SynapticsCopyHwState(struct SynapticsHwState *dst,
            dst->num_mt_mask * sizeof(enum SynapticsSlotState));
 #endif
 }
+
+void
+SynapticsResetTouchHwState(struct SynapticsHwState *hw)
+{
+#ifdef HAVE_MULTITOUCH
+    int i;
+
+    for (i = 0; i < hw->num_mt_mask; i++)
+    {
+        int j;
+
+        /* Leave x and y valuators in case we need to restart touch */
+        for (j = 2; j < valuator_mask_num_valuators(hw->mt_mask[i]); j++)
+            valuator_mask_unset(hw->mt_mask[i], j);
+
+        hw->slot_state[i] = SLOTSTATE_EMPTY;
+    }
+#endif
+}
diff --git a/src/synproto.h b/src/synproto.h
index 7ebca59..89392ac 100644
--- a/src/synproto.h
+++ b/src/synproto.h
@@ -113,5 +113,6 @@ extern struct SynapticsHwState *SynapticsHwStateAlloc(SynapticsPrivate *priv);
 extern void SynapticsHwStateFree(struct SynapticsHwState **hw);
 extern void SynapticsCopyHwState(struct SynapticsHwState *dst,
                                  const struct SynapticsHwState *src);
+extern void SynapticsResetTouchHwState(struct SynapticsHwState *hw);
 
 #endif /* _SYNPROTO_H_ */
diff --git a/test/fake-symbols.c b/test/fake-symbols.c
index 389c3c8..7f3f0ac 100644
--- a/test/fake-symbols.c
+++ b/test/fake-symbols.c
@@ -465,6 +465,15 @@ _X_EXPORT void valuator_mask_set(ValuatorMask *mask, int valuator, int data)
 {
 }
 
+extern _X_EXPORT void valuator_mask_unset(ValuatorMask *mask, int bit)
+{
+}
+
+_X_EXPORT int valuator_mask_num_valuators(const ValuatorMask *mask)
+{
+    return 0;
+}
+
 _X_EXPORT void valuator_mask_zero(ValuatorMask *mask)
 {
 }
-- 
1.7.8.3



More information about the xorg-devel mailing list