diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2012-02-07 02:51:08 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2012-02-07 02:51:08 +1000 |
commit | e4ee51e771a6da247362549044a076462791022b (patch) | |
tree | bdb8a66e115c2cf2dfca2d41eb5ed92b911f8cb7 /src/eventcomm.c | |
parent | da0d20d0fd5cce3707b54146e54e2df0c697e1b4 (diff) | |
parent | 6b808dc766a0d1e64e19e4d5fad5f8a1a4e0d62d (diff) |
Merge branch 'fixes' of git://people.freedesktop.org/~cndougla/xf86-input-synaptics
Diffstat (limited to 'src/eventcomm.c')
-rw-r--r-- | src/eventcomm.c | 107 |
1 files changed, 99 insertions, 8 deletions
diff --git a/src/eventcomm.c b/src/eventcomm.c index be0f4ee..ce26934 100644 --- a/src/eventcomm.c +++ b/src/eventcomm.c @@ -78,6 +78,8 @@ struct eventcomm_proto_data } slot_state; ValuatorMask *mt_mask; ValuatorMask **last_mt_vals; + unsigned int num_touches; + int *open_slots; #endif }; @@ -106,9 +108,12 @@ UninitializeTouch(InputInfoPtr pInfo) SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; struct eventcomm_proto_data *proto_data = (struct eventcomm_proto_data*)priv->proto_data; - if (!proto_data->mtdev) + 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) { @@ -131,6 +136,9 @@ InitializeTouch(InputInfoPtr pInfo) struct eventcomm_proto_data *proto_data = (struct eventcomm_proto_data*)priv->proto_data; int i; + if (!priv->has_touch) + return; + proto_data->mtdev = mtdev_new_open(pInfo->fd); if (!proto_data->mtdev) { @@ -183,6 +191,8 @@ 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 @@ -511,13 +521,82 @@ 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; - int type; if (proto_data->cur_slot < 0 || !priv->has_touch) return; @@ -529,19 +608,18 @@ EventProcessTouch(InputInfoPtr pInfo) switch (proto_data->slot_state) { case SLOTSTATE_CLOSE: - type = XI_TouchEnd; + EventEndTouches(pInfo); break; case SLOTSTATE_OPEN: - type = XI_TouchBegin; + EventBeginTouches(pInfo); break; default: - type = XI_TouchUpdate; + if (proto_data->num_touches >= 2) + xf86PostTouchEvent(pInfo->dev, proto_data->cur_slot, + XI_TouchUpdate, 0, proto_data->mt_mask); break; } - xf86PostTouchEvent(pInfo->dev, proto_data->cur_slot, type, 0, - proto_data->mt_mask); - proto_data->slot_state = SLOTSTATE_EMPTY; valuator_mask_zero(proto_data->mt_mask); #endif @@ -555,6 +633,9 @@ EventProcessTouchEvent(InputInfoPtr pInfo, struct CommData *comm, SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; struct eventcomm_proto_data *proto_data = priv->proto_data; + if (!priv->has_touch) + return; + if (ev->code == ABS_MT_SLOT) { EventProcessTouch(pInfo); @@ -731,10 +812,20 @@ event_query_touch(InputInfoPtr pInfo) struct eventcomm_proto_data *proto_data = priv->proto_data; struct mtdev *mtdev; int i; + int rc; + uint8_t prop; priv->num_touches = 0; priv->num_mt_axes = 0; + SYSCALL(rc = ioctl(pInfo->fd, EVIOCGPROP(sizeof(prop)), &prop)); + if (rc >= 0 && BitIsOn(&prop, INPUT_PROP_SEMI_MT)) + { + xf86IDrvMsg(pInfo, X_INFO, + "ignoring touch events for semi-multitouch device\n"); + return; + } + mtdev = mtdev_new_open(pInfo->fd); if (!mtdev) { |