diff options
author | Chase Douglas <chase.douglas@canonical.com> | 2012-02-08 15:06:33 -0800 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2012-02-11 07:46:05 +1000 |
commit | 336f9a09d090a8c3a9c976ab04ffb17bcdc2c2ea (patch) | |
tree | 34c34d18b1b2373b5bcc8c95b384c300b43f36c6 /src | |
parent | 673c5fa14bff669d82f5711511a37bd3abe75471 (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.c | 169 | ||||
-rw-r--r-- | src/synaptics.c | 110 | ||||
-rw-r--r-- | src/synapticsstr.h | 1 | ||||
-rw-r--r-- | src/synproto.c | 19 | ||||
-rw-r--r-- | src/synproto.h | 1 |
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_ */ |