[PATCH xf86-input-evdev v4] Copy last valuator values into new touch valuator masks
Peter Hutterer
peter.hutterer at who-t.net
Mon Jan 23 19:20:31 PST 2012
On Thu, Jan 19, 2012 at 02:17:34PM -0800, Chase Douglas wrote:
> Evdev is a 100% stateful protocol. The following represents three
> touches. Two touches begin and end at the same time at (500, 500) and
> (1000, 1000). The third touch begins after the first two end, and is at
> (500, 500).
>
> ABS_MT_SLOT 0 /* Set touch slot */
> ABS_MT_TRACKING_ID 0 /* New touch with ID 0 in slot 0 */
> ABS_MT_POSITION_X 500 /* Initial X position */
> ABS_MT_POSITION_Y 500 /* Initial Y position */
> ABS_MT_SLOT 1 /* Set touch slot */
> ABS_MT_TRACKING_ID 1 /* New touch with ID 1 in slot 1 */
> ABS_MT_POSITION_X 1000 /* Initial X position */
> ABS_MT_POSITION_Y 1000 /* Initial Y position */
> SYNC /* End of frame */
> ABS_MT_SLOT 0 /* Go back to slot 0 */
> ABS_MT_TRACKING_ID -1 /* Touch in slot 0 ended */
> ABS_MT_SLOT 1 /* Go to slot 1 */
> ABS_MT_TRACKING_ID -1 /* Touch in slot 1 ended */
> SYNC /* End of frame */
> ABS_MT_SLOT 0 /* Go back to slot 0 */
> ABS_MT_TRACKING_ID 2 /* New touch in slot 0 with ID 2 */
> SYNC /* End of frame */
> ABS_MT_TRACKING_ID -1 /* Touch in last slot (0) ended */
> SYNC /* End of frame */
>
> Note that touch 2 has the same X and Y position as touch 0. This is
> implied because no new value was emitted for slot 0. In fact, Linux will
> not emit an event in the same slot with the same event type and code
> unless the value has changed. Thus, we can only assume that all the MT
> valuators have the same values as they were when they were last sent for
> the given slot.
>
> This change adds an array of valuator mask to hold all the last valuator
> values that came from evdev for each slot. When a new touch begins, all
> the last values are copied into it.
>
> This patch assumes initial axis values of 0 in each slot. Linux and
> mtdev do not provide a facility to query the current values of axes in
> each slot yet. This may cause spurious incorrect touch valuator values
> at the beginning of an X session, but there's nothing we can do about it
> right now.
we could ignore events until we have a definitive coordinate for a slot, but
that's low priority. thanks, pushed
9d9c987..bc2f01a master -> master
Cheers,
Peter
> ---
> Changes from v3:
> * Rebase on top of master, dropping re-indent changes
> * Don't set masks to NULL in EvdevFreeMasks, valuator_mask_free does that for us
>
> src/evdev.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++-------------
> src/evdev.h | 1 +
> 2 files changed, 89 insertions(+), 25 deletions(-)
>
> diff --git a/src/evdev.c b/src/evdev.c
> index 1cdba41..32fe38b 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -746,6 +746,24 @@ EvdevProcessTouch(InputInfoPtr pInfo)
> valuator_mask_zero(pEvdev->mt_mask);
> }
>
> +static int
> +num_slots(EvdevPtr pEvdev)
> +{
> + int value = pEvdev->absinfo[ABS_MT_SLOT].maximum -
> + pEvdev->absinfo[ABS_MT_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(EvdevPtr pEvdev)
> +{
> + int value = pEvdev->cur_slot - pEvdev->absinfo[ABS_MT_SLOT].minimum;
> +
> + return value < num_slots(pEvdev) ? value : -1;
> +}
> +
> static void
> EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
> {
> @@ -757,16 +775,29 @@ EvdevProcessTouchEvent(InputInfoPtr pInfo, struct input_event *ev)
> pEvdev->cur_slot = ev->value;
> } else
> {
> + int slot_index = last_mt_vals_slot(pEvdev);
> +
> if (pEvdev->slot_state == SLOTSTATE_EMPTY)
> pEvdev->slot_state = SLOTSTATE_UPDATE;
> if (ev->code == ABS_MT_TRACKING_ID) {
> - if (ev->value >= 0)
> - pEvdev->slot_state = SLOTSTATE_OPEN;
> - else
> - pEvdev->slot_state = SLOTSTATE_CLOSE;
> + if (ev->value >= 0) {
> + pEvdev->slot_state = SLOTSTATE_OPEN;
> +
> + if (slot_index >= 0)
> + valuator_mask_copy(pEvdev->mt_mask,
> + pEvdev->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
> + pEvdev->slot_state = SLOTSTATE_CLOSE;
> } else {
> map = pEvdev->axis_map[ev->code];
> valuator_mask_set(pEvdev->mt_mask, map, ev->value);
> + if (slot_index >= 0)
> + valuator_mask_set(pEvdev->last_mt_vals[slot_index], map,
> + ev->value);
> }
> }
> }
> @@ -1027,6 +1058,28 @@ EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
> #undef ABS_Y_VALUE
> #undef ABS_VALUE
>
> +static void
> +EvdevFreeMasks(EvdevPtr pEvdev)
> +{
> + int i;
> +
> + valuator_mask_free(&pEvdev->vals);
> + valuator_mask_free(&pEvdev->old_vals);
> + valuator_mask_free(&pEvdev->prox);
> +#ifdef MULTITOUCH
> + valuator_mask_free(&pEvdev->mt_mask);
> + if (pEvdev->last_mt_vals)
> + {
> + for (i = 0; i < num_slots(pEvdev); i++)
> + valuator_mask_free(&pEvdev->last_mt_vals[i]);
> + free(pEvdev->last_mt_vals);
> + pEvdev->last_mt_vals = NULL;
> + }
> + for (i = 0; i < EVDEV_MAXQUEUE; i++)
> + valuator_mask_free(&pEvdev->queue[i].touchMask);
> +#endif
> +}
> +
> /* just a magic number to reduce the number of reads */
> #define NUM_EVENTS 16
>
> @@ -1258,6 +1311,24 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
> goto out;
> }
>
> + pEvdev->last_mt_vals = calloc(num_slots(pEvdev), sizeof(ValuatorMask *));
> + if (!pEvdev->last_mt_vals) {
> + xf86IDrvMsg(pInfo, X_ERROR,
> + "%s: failed to allocate MT last values mask array.\n",
> + device->name);
> + goto out;
> + }
> +
> + for (i = 0; i < num_slots(pEvdev); i++) {
> + pEvdev->last_mt_vals[i] = valuator_mask_new(num_mt_axes_total);
> + if (!pEvdev->last_mt_vals[i]) {
> + xf86IDrvMsg(pInfo, X_ERROR,
> + "%s: failed to allocate MT last values mask.\n",
> + device->name);
> + goto out;
> + }
> + }
> +
> for (i = 0; i < EVDEV_MAXQUEUE; i++) {
> pEvdev->queue[i].touchMask =
> valuator_mask_new(num_mt_axes_total);
> @@ -1321,6 +1392,17 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
> device->name);
> goto out;
> }
> +
> + for (i = 0; i < num_slots(pEvdev); i++) {
> + for (axis = ABS_MT_TOUCH_MAJOR; axis < ABS_MAX; axis++) {
> + if (pEvdev->axis_map[axis] >= 0) {
> + /* XXX: read initial values from mtdev when it adds support
> + * for doing so. */
> + valuator_mask_set(pEvdev->last_mt_vals[i],
> + pEvdev->axis_map[axis], 0);
> + }
> + }
> + }
> }
> #endif
>
> @@ -1426,14 +1508,7 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
> return Success;
>
> out:
> - valuator_mask_free(&pEvdev->vals);
> - valuator_mask_free(&pEvdev->old_vals);
> - valuator_mask_free(&pEvdev->prox);
> -#ifdef MULTITOUCH
> - valuator_mask_free(&pEvdev->mt_mask);
> - for (i = 0; i < EVDEV_MAXQUEUE; i++)
> - valuator_mask_free(&pEvdev->queue[i].touchMask);
> -#endif
> + EvdevFreeMasks(pEvdev);
> return !Success;
> }
>
> @@ -1767,9 +1842,6 @@ EvdevProc(DeviceIntPtr device, int what)
> {
> InputInfoPtr pInfo;
> EvdevPtr pEvdev;
> -#ifdef MULTITOUCH
> - int i;
> -#endif
>
> pInfo = device->public.devicePrivate;
> pEvdev = pInfo->private;
> @@ -1806,16 +1878,7 @@ EvdevProc(DeviceIntPtr device, int what)
> close(pInfo->fd);
> pInfo->fd = -1;
> }
> - valuator_mask_free(&pEvdev->vals);
> - valuator_mask_free(&pEvdev->old_vals);
> - valuator_mask_free(&pEvdev->prox);
> -#ifdef MULTITOUCH
> - valuator_mask_free(&pEvdev->mt_mask);
> - for (i = 0; i < EVDEV_MAXQUEUE; i++)
> - valuator_mask_free(&pEvdev->queue[i].touchMask);
> - if (pEvdev->mtdev)
> - mtdev_close(pEvdev->mtdev);
> -#endif
> + EvdevFreeMasks(pEvdev);
> EvdevRemoveDevice(pInfo);
> pEvdev->min_maj = 0;
> break;
> diff --git a/src/evdev.h b/src/evdev.h
> index 1713b89..309b215 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -158,6 +158,7 @@ typedef struct {
> ValuatorMask *old_vals; /* old values for calculating relative motion */
> ValuatorMask *prox; /* last values set while not in proximity */
> ValuatorMask *mt_mask;
> + ValuatorMask **last_mt_vals;
> int cur_slot;
> enum SlotState slot_state;
> #ifdef MULTITOUCH
> --
> 1.7.8.3
>
More information about the xorg-devel
mailing list