[PATCH v2 xf86-input-evdev] Copy last valuator values into new touch valuator masks

Peter Hutterer peter.hutterer at who-t.net
Mon Jan 9 22:08:51 PST 2012


On Thu, Jan 05, 2012 at 01:28:43PM -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.
> 
> Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
> ---
> Changes since v1:
> * Hold the last values *per-slot* instead of globally
> 
>  src/evdev.c |   80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
>  src/evdev.h |    1 +
>  2 files changed, 77 insertions(+), 4 deletions(-)
> 
> diff --git a/src/evdev.c b/src/evdev.c
> index 82cdb00..ec6650e 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]);

please align with the opening (

> +                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);

fwiw, coding style in evdev is { on the next line (with a few
accidental/historical exceptions)

>          }
>      }
>  }
> @@ -1256,6 +1287,24 @@ EvdevAddAbsValuatorClass(DeviceIntPtr device)
>              goto out;
>          }
>  
> +        pEvdev->last_mt_vals = calloc(num_slots(pEvdev), sizeof(ValuatorMask *));
> +        if (!pEvdev->last_mt_vals) {
> +            xf86Msg(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]) {
> +                xf86Msg(X_ERROR,
> +                        "%s: failed to allocate MT last values mask.\n",
> +                        device->name);
> +                goto out;
> +            }

shouldn't these two use xf86IDrvMsg?

> +        }
> +
>          for (i = 0; i < EVDEV_MAXQUEUE; i++) {
>              pEvdev->queue[i].touchMask =
>                  valuator_mask_new(num_mt_axes_total);
> @@ -1318,6 +1367,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
>  
> @@ -1428,6 +1488,12 @@ out:
>      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
> @@ -1808,6 +1874,12 @@ EvdevProc(DeviceIntPtr device, int what)
>          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;
> +        }

this needs to be deduplicated first, or in a follow-up patch.

ack to the principle though.

Cheers,
  Peter

>          for (i = 0; i < EVDEV_MAXQUEUE; i++)
>              valuator_mask_free(&pEvdev->queue[i].touchMask);
>          if (pEvdev->mtdev)
> 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.7.3
> 


More information about the xorg-devel mailing list