diff options
author | Chase Douglas <chase.douglas@canonical.com> | 2012-01-19 13:05:50 -0800 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2012-01-26 15:54:29 +1000 |
commit | d15c391544e9ba094b17c9217a837c58d88879f8 (patch) | |
tree | e8597f873357e6562e9e35bc8e39df0bcadc7754 | |
parent | efdc34859bdbcf0622e88aaf8af99944c1fc2141 (diff) |
eventcomm: Add touch event handling
Signed-off-by: Chase Douglas <chase.douglas@canonical.com>
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
-rw-r--r-- | src/eventcomm.c | 249 | ||||
-rw-r--r-- | test/fake-symbols.c | 31 |
2 files changed, 258 insertions, 22 deletions
diff --git a/src/eventcomm.c b/src/eventcomm.c index 43b8796..c323f8f 100644 --- a/src/eventcomm.c +++ b/src/eventcomm.c @@ -68,9 +68,124 @@ struct eventcomm_proto_data #ifdef HAVE_MTDEV struct mtdev *mtdev; int axis_map[MT_ABS_SIZE]; + int cur_slot; + enum + { + SLOTSTATE_OPEN = 0, + SLOTSTATE_CLOSE, + SLOTSTATE_UPDATE, + SLOTSTATE_EMPTY, + } slot_state; + ValuatorMask *mt_mask; + ValuatorMask **last_mt_vals; #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) +{ + int value = proto_data->cur_slot - proto_data->mtdev->caps.slot.minimum; + + return value < num_slots(proto_data) ? value : -1; +} + +static void +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) + return; + + valuator_mask_free(&proto_data->mt_mask); + if (proto_data->last_mt_vals) + { + int i; + + for (i = 0; i < num_slots(proto_data); i++) + valuator_mask_free(&proto_data->last_mt_vals[i]); + free(proto_data->last_mt_vals); + proto_data->last_mt_vals = NULL; + } + + mtdev_close(proto_data->mtdev); + proto_data->mtdev = NULL; +} + +static void +InitializeTouch(InputInfoPtr pInfo) +{ + SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; + struct eventcomm_proto_data *proto_data = (struct eventcomm_proto_data*)priv->proto_data; + int i; + + proto_data->mtdev = mtdev_new_open(pInfo->fd); + if (!proto_data->mtdev) + { + xf86IDrvMsg(pInfo, X_WARNING, + "failed to create mtdev instance, ignoring touch events\n"); + return; + } + + 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), + sizeof(ValuatorMask *)); + if (!proto_data->last_mt_vals) + { + xf86IDrvMsg(pInfo, X_WARNING, + "failed to allocate MT last values mask array\n"); + UninitializeTouch(pInfo); + return; + } + + for (i = 0; i < num_slots(proto_data); i++) + { + int j; + + proto_data->last_mt_vals[i] = valuator_mask_new(4 + priv->num_mt_axes); + if (!proto_data->last_mt_vals[i]) + { + xf86IDrvMsg(pInfo, X_WARNING, + "failed to allocate MT last values mask\n"); + UninitializeTouch(pInfo); + return; + } + + /* Axes 0-4 are for X, Y, and scrolling. num_mt_axes does not include X + * and Y. */ + valuator_mask_set(proto_data->last_mt_vals[i], 0, 0); + valuator_mask_set(proto_data->last_mt_vals[i], 1, 0); + for (j = 4; j < priv->num_mt_axes; j++) + valuator_mask_set(proto_data->last_mt_vals[i], j, 0); + } +} +#endif + static Bool EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters *para) { @@ -91,18 +206,22 @@ EventDeviceOnHook(InputInfoPtr pInfo, SynapticsParameters *para) proto_data->need_grab = FALSE; #ifdef HAVE_MTDEV - proto_data->mtdev = mtdev_new_open(pInfo->fd); - if (!proto_data->mtdev) - { - xf86IDrvMsg(pInfo, X_WARNING, - "failed to create mtdev instance, ignoring touch events\n"); - priv->has_touch = FALSE; - } + InitializeTouch(pInfo); #endif return TRUE; } +static Bool +EventDeviceOffHook(InputInfoPtr pInfo) +{ +#ifdef HAVE_MTDEV + UninitializeTouch(pInfo); +#endif + + return Success; +} + /** * Test if the device on the file descriptior is recognized as touchpad * device. Required bits for touchpad recognition are: @@ -392,6 +511,87 @@ SynapticsReadEvent(InputInfoPtr pInfo, struct input_event *ev) return rc; } +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; + + /* 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: + type = XI_TouchEnd; + break; + case SLOTSTATE_OPEN: + type = XI_TouchBegin; + break; + default: + type = XI_TouchUpdate; + 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 +} + +static void +EventProcessTouchEvent(InputInfoPtr pInfo, struct CommData *comm, + struct input_event *ev) +{ +#ifdef HAVE_MTDEV + SynapticsPrivate *priv = (SynapticsPrivate *)pInfo->private; + struct eventcomm_proto_data *proto_data = priv->proto_data; + + if (ev->code == ABS_MT_SLOT) + { + EventProcessTouch(pInfo); + proto_data->cur_slot = ev->value; + } else + { + int slot_index = last_mt_vals_slot(proto_data); + + if (proto_data->slot_state == SLOTSTATE_EMPTY) + proto_data->slot_state = SLOTSTATE_UPDATE; + if (ev->code == ABS_MT_TRACKING_ID) + { + if (ev->value >= 0) + { + proto_data->slot_state = SLOTSTATE_OPEN; + + if (slot_index >= 0) + valuator_mask_copy(proto_data->mt_mask, + 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; + } else + { + int map = proto_data->axis_map[ev->code - ABS_MT_TOUCH_MAJOR]; + valuator_mask_set(proto_data->mt_mask, map, ev->value); + if (slot_index >= 0) + valuator_mask_set(proto_data->last_mt_vals[slot_index], map, + ev->value); + } + } +#endif +} + /** * Count the number of fingers based on the CommData information. * The CommData struct contains the event information based on previous @@ -430,6 +630,7 @@ EventReadHwState(InputInfoPtr pInfo, 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; *hwRet = *hw; @@ -494,20 +695,23 @@ EventReadHwState(InputInfoPtr pInfo, } break; case EV_ABS: - switch (ev.code) { - case ABS_X: - hw->x = ev.value; - break; - case ABS_Y: - hw->y = ev.value; - break; - case ABS_PRESSURE: - hw->z = ev.value; - break; - case ABS_TOOL_WIDTH: - hw->fingerWidth = ev.value; - break; - } + if (ev.code < ABS_MT_SLOT) { + switch (ev.code) { + case ABS_X: + hw->x = ev.value; + break; + case ABS_Y: + hw->y = ev.value; + break; + case ABS_PRESSURE: + hw->z = ev.value; + break; + case ABS_TOOL_WIDTH: + hw->fingerWidth = ev.value; + break; + } + } else + EventProcessTouchEvent(pInfo, comm, &ev); break; } } @@ -651,6 +855,7 @@ EventReadDevDimensions(InputInfoPtr pInfo) #ifdef HAVE_MTDEV for (i = 0; i < MT_ABS_SIZE; i++) proto_data->axis_map[i] = -1; + proto_data->cur_slot = -1; #endif if (event_query_is_touchpad(pInfo->fd, (proto_data) ? proto_data->need_grab : TRUE)) @@ -736,7 +941,7 @@ EventAutoDevProbe(InputInfoPtr pInfo, const char *device) struct SynapticsProtocolOperations event_proto_operations = { EventDeviceOnHook, - NULL, + EventDeviceOffHook, EventQueryHardware, EventReadHwState, EventAutoDevProbe, diff --git a/test/fake-symbols.c b/test/fake-symbols.c index 2d94622..389c3c8 100644 --- a/test/fake-symbols.c +++ b/test/fake-symbols.c @@ -450,3 +450,34 @@ Bool QueueWorkProc ( { return FALSE; } + +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 12 +_X_EXPORT ValuatorMask *valuator_mask_new(int num_valuators) +{ + return NULL; +} + +_X_EXPORT void valuator_mask_free(ValuatorMask **mask) +{ +} + +_X_EXPORT void valuator_mask_set(ValuatorMask *mask, int valuator, int data) +{ +} + +_X_EXPORT void valuator_mask_zero(ValuatorMask *mask) +{ +} + +_X_EXPORT void valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src) +{ +} +#endif + +#if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 16 +_X_EXPORT void xf86PostTouchEvent(DeviceIntPtr dev, uint32_t touchid, + uint16_t type, uint32_t flags, + const ValuatorMask *mask) +{ +} +#endif |