summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChase Douglas <chase.douglas@canonical.com>2012-02-08 15:06:33 -0800
committerPeter Hutterer <peter.hutterer@who-t.net>2012-02-11 07:46:05 +1000
commit336f9a09d090a8c3a9c976ab04ffb17bcdc2c2ea (patch)
tree34c34d18b1b2373b5bcc8c95b384c300b43f36c6 /src
parent673c5fa14bff669d82f5711511a37bd3abe75471 (diff)
Move X touch event processing into synaptics.c
Signed-off-by: Chase Douglas <chase.douglas@canonical.com> Reviewed-by: Peter Hutterer <peter.hutterer@who-t.net> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'src')
-rw-r--r--src/eventcomm.c169
-rw-r--r--src/synaptics.c110
-rw-r--r--src/synapticsstr.h1
-rw-r--r--src/synproto.c19
-rw-r--r--src/synproto.h1
5 files changed, 148 insertions, 152 deletions
diff --git a/src/eventcomm.c b/src/eventcomm.c
index 92bf749..6ffe265 100644
--- a/src/eventcomm.c
+++ b/src/eventcomm.c
@@ -69,11 +69,7 @@ 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
};
@@ -85,21 +81,12 @@ EventProtoDataAlloc(void)
#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
@@ -111,15 +98,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;
@@ -149,19 +132,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)
{
@@ -171,7 +142,7 @@ InitializeTouch(InputInfoPtr pInfo)
return;
}
- for (i = 0; i < num_slots(proto_data); i++)
+ for (i = 0; i < priv->num_slots; i++)
{
int j;
@@ -191,8 +162,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
@@ -521,112 +490,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->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
@@ -638,33 +503,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);
@@ -706,12 +570,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);
@@ -792,7 +657,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 a4b1b35..0dd4fb2 100644
--- a/src/synaptics.c
+++ b/src/synaptics.c
@@ -1367,6 +1367,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;
@@ -1406,6 +1407,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);
@@ -2593,6 +2596,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
@@ -2761,6 +2869,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_ */