[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