[PATCH v2 23/42] dix: add touch event history helper functions

walter harms wharms at bfs.de
Tue Dec 20 07:21:12 PST 2011



Am 20.12.2011 04:22, schrieb Peter Hutterer:
> If touch client has not registered for ownership events and a grab above
> that client is rejected, the client needs to receive the complete event
> history.
> 
> The history currently doesn't really do fancy overflow handling. We assume
> that the first TOUCH_HISTORY_SIZE events are the important ones and anything
> after that is dropped. If that is a problem, fix the client that takes > 100
> event to decide whether to accept or reject.
> 
> Events marked with TOUCH_CLIENT_ID or TOUCH_REPLAYING must not be stored in
> the history, they are events created by the DIX to comply with the protocol.
> Any such event should already be in the history anyway.
> 
> A fixme in this patch: we don't have a function to actually deliver the
> event yet.
> 
> Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
> ---
> Changes to v1:
> - add DebugF for history overflow
> 
>  dix/touch.c     |  109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/input.h |    4 ++
>  2 files changed, 113 insertions(+), 0 deletions(-)
> 
> diff --git a/dix/touch.c b/dix/touch.c
> index dfb7ff0..f741207 100644
> --- a/dix/touch.c
> +++ b/dix/touch.c
> @@ -35,6 +35,9 @@
>  #include "eventstr.h"
>  #include "exevents.h"
>  
> +#define TOUCH_HISTORY_SIZE 100
> +
> +
>  /* If a touch queue resize is needed, the device id's bit is set. */
>  static unsigned char resize_waiting[(MAXDEVICES + 7)/8];
>  
> @@ -394,6 +397,112 @@ TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti)
>      ti->num_grabs = 0;
>      ti->client_id = 0;
>  
> +    TouchEventHistoryFree(ti);
> +
>      valuator_mask_zero(ti->valuators);
>  }
>  
> +/**
> + * Allocate the event history for this touch pointer. Calling this on a
> + * touchpoint that already has an event history does nothing but counts as
> + * as success.
> + *
> + * @return TRUE on success, FALSE on allocation errors
> + */
> +Bool
> +TouchEventHistoryAllocate(TouchPointInfoPtr ti)
> +{
> +    if (ti->history)
> +        return TRUE;
> +
> +    ti->history = calloc(TOUCH_HISTORY_SIZE, sizeof(*ti->history));
> +    ti->history_elements = 0;
> +    if (ti->history)
> +        ti->history_size = TOUCH_HISTORY_SIZE;
> +    return ti->history != NULL;
> +}

just for the beauty of the code i would change the order a bit like:

 ti->history_elements = 0;
 ti->history_size = 0;
  ti->history = calloc(TOUCH_HISTORY_SIZE, sizeof(*ti->history));
   if (ti->history)
	ti->history_size = TOUCH_HISTORY_SIZE;
  return ti->history != NULL;
}

you could also make the code void * and return ti->history
(That is what i would expect from *alloc*() ).

btw:
Would it make sence to have a dynamical buffer in future ?
if yes you could add a second argument (TOUCH_HISTORY_SIZE)
and replace calloc with realloc().
(just an idea, i am not a big fan of #define something 100 because
things tend to change in future).

just my 2 cents,
re,
 wh

> +void
> +TouchEventHistoryFree(TouchPointInfoPtr ti)
> +{
> +    free(ti->history);
> +    ti->history = NULL;
> +    ti->history_size = 0;
> +    ti->history_elements = 0;
> +}
> +
> +/**
> + * Store the given event on the event history (if one exists)
> + * A touch event history consists of one TouchBegin and several TouchUpdate
> + * events (if applicable) but no TouchEnd event.
> + * If more than one TouchBegin is pushed onto the stack, the push is
> + * ignored, calling this function multiple times for the TouchBegin is
> + * valid.
> + */
> +void
> +TouchEventHistoryPush(TouchPointInfoPtr ti, const DeviceEvent *ev)
> +{
> +    if (!ti->history)
> +        return;
> +
> +    switch(ev->type)
> +    {
> +        case ET_TouchBegin:
> +            /* don't store the same touchbegin twice */
> +            if (ti->history_elements > 0)
> +                return;
> +            break;
> +        case ET_TouchUpdate:
> +            break;
> +        case ET_TouchEnd:
> +            return; /* no TouchEnd events in the history */
> +        default:
> +            return;
> +    }
> +
> +    /* We only store real events in the history */
> +    if (ev->flags & (TOUCH_CLIENT_ID|TOUCH_REPLAYING))
> +        return;
> +
> +    ti->history[ti->history_elements++] = *ev;
> +    /* FIXME: proper overflow fixes */
> +    if (ti->history_elements > ti->history_size - 1)
> +    {
> +        ti->history_elements = ti->history_size - 1;
> +        DebugF("source device %d: history size %d overflowing for touch %u\n",
> +                ti->sourceid, ti->history_size, ti->client_id);
> +    }
> +}
> +
> +void
> +TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource)
> +{
> +    InternalEvent *tel = InitEventList(GetMaximumEventsNum());
> +    ValuatorMask *mask = valuator_mask_new(0);
> +    int i, nev;
> +    int flags;
> +
> +    if (!ti->history)
> +        return;
> +
> +    valuator_mask_set_double(mask, 0, ti->history[0].valuators.data[0]);
> +    valuator_mask_set_double(mask, 1, ti->history[0].valuators.data[1]);
> +
> +    flags = TOUCH_CLIENT_ID|TOUCH_REPLAYING;
> +    if (ti->emulate_pointer)
> +        flags |= TOUCH_POINTER_EMULATED;
> +    /* send fake begin event to next owner */
> +    nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchBegin, flags, mask);
> +    /* FIXME: deliver the event */
> +
> +    valuator_mask_free(&mask);
> +    FreeEventList(tel, GetMaximumEventsNum());
> +
> +    /* First event was TouchBegin, already replayed that one */
> +    for (i = 1; i < ti->history_elements; i++)
> +    {
> +        DeviceEvent *ev = &ti->history[i];
> +        ev->flags |= TOUCH_REPLAYING;
> +        /* FIXME: deliver the event */
> +    }
> +}
> diff --git a/include/input.h b/include/input.h
> index 4d60792..8ce5f2b 100644
> --- a/include/input.h
> +++ b/include/input.h
> @@ -607,6 +607,10 @@ extern TouchPointInfoPtr TouchBeginTouch(DeviceIntPtr dev, int sourceid,
>  extern TouchPointInfoPtr TouchFindByClientID(DeviceIntPtr dev,
>                                               uint32_t client_id);
>  extern void TouchEndTouch(DeviceIntPtr dev, TouchPointInfoPtr ti);
> +extern Bool TouchEventHistoryAllocate(TouchPointInfoPtr ti);
> +extern void TouchEventHistoryFree(TouchPointInfoPtr ti);
> +extern void TouchEventHistoryPush(TouchPointInfoPtr ti, const DeviceEvent *ev);
> +extern void TouchEventHistoryReplay(TouchPointInfoPtr ti, DeviceIntPtr dev, XID resource);
>  
>  /* misc event helpers */
>  extern Mask GetEventMask(DeviceIntPtr dev, xEvent* ev, InputClientsPtr clients);


More information about the xorg-devel mailing list