[PATCH] evdev: Only send the events at synchronization time.

Peter Hutterer peter.hutterer at who-t.net
Wed Jul 22 17:30:39 PDT 2009


Thanks for the patch. it looks good, I have a few minor changes though,
mostly style.

On Mon, Jul 20, 2009 at 10:15:55AM +0300, oliver.mcfadden at nokia.com wrote:
> From: Oliver McFadden <oliver.mcfadden at nokia.com>
> 
> Instead of just posting the button/key press/release events to the
> server as soon as they arrive, add them to an internal queue and post
> them once we receive an EV_SYN synchronization event.
> 
> The motion events are always sent first, followed by the queued events.
> There will be one motion event and possibly many queued button/key
> events posted every EV_SYN event.
> 
> Note that the size of the event queue (EVDEV_MAXQUEUE) is arbitrary and
> you may change it. If we receive more events than the queue can handle,
> those events are dropped and a warning message printed.
> 
> Tested on my Lenovo T400 using evdev for all input devices; keyboard,
> touchpad, and trackpoint.
> ---
>  src/evdev.c |  563 +++++++++++++++++++++++++++++++++++++++--------------------
>  src/evdev.h |   17 ++
>  2 files changed, 389 insertions(+), 191 deletions(-)
> 
> diff --git a/src/evdev.c b/src/evdev.c
> index ecca94a..2b1d3d8 100644
> --- a/src/evdev.c
> +++ b/src/evdev.c
> @@ -249,21 +249,12 @@ static int wheel_left_button = 6;
>  static int wheel_right_button = 7;
>  
>  static void
> -PostButtonClicks(InputInfoPtr pInfo, int button, int count)
> -{
> -    int i;
> -
> -    for (i = 0; i < count; i++) {
> -        xf86PostButtonEvent(pInfo->dev, 0, button, 1, 0, 0);
> -        xf86PostButtonEvent(pInfo->dev, 0, button, 0, 0, 0);
> -    }
> -}
> -
> -static void
>  PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
>  {
>      int code = ev->code + MIN_KEYCODE;
>      static char warned[KEY_CNT];
> +    EventQueuePtr event;

the word 'event' is a bit overloaded, especially here where you have an
input_event and a EventQueuePtr. I'd prefer something like "eq" or
"queue_event". Looks awkward, but at least it's more obvious. Better naming
suggestions are welcome.

> +    EvdevPtr pEvdev = pInfo->private;
>  
>      /* Filter all repeated events from device.
>         We'll do softrepeat in the server, but only since 1.6 */
> @@ -292,7 +283,51 @@ PostKbdEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
>          return;
>      }
>  
> -    xf86PostKeyboardEvent(pInfo->dev, code, value);
> +    if (pEvdev->num_queue >= EVDEV_MAXQUEUE)
> +    {
> +        xf86Msg(X_WARNING,
We can't use X_WARNING here. the server may allocate memory for anything but
X_NONE and this is called in the signal handler. This has been fixed in the
server, but for now it's better to use X_NONE.

> +                "%s: dropping event due to full queue! (Consider increasing EVDEV_MAXQUEUE)\n",

Remove the (Consider ...) stuff. It becomes obvious when looking at the code
and there's no reason to have that in the log.


> +                pInfo->name);
> +        return;
> +    }
> +
> +    event = &pEvdev->queue[pEvdev->num_queue];
> +    event->type = EV_QUEUE_KEY;
> +    event->key = code;
> +    event->val = value;
> +    pEvdev->num_queue++;
> +}
> +
> +static void
> +PostButtonEvent(InputInfoPtr pInfo, struct input_event *ev, int value)
> +{
> +    EventQueuePtr event;
> +    EvdevPtr pEvdev = pInfo->private;
> +
> +    if (pEvdev->num_queue >= EVDEV_MAXQUEUE)
> +    {
> +        xf86Msg(X_WARNING,
> +                "%s: dropping event due to full queue! (Consider increasing EVDEV_MAXQUEUE)\n",

same as above, X_NONE, drop the (...).

> +                pInfo->name);
> +        return;
> +    }
> +
> +    event = &pEvdev->queue[pEvdev->num_queue];
> +    event->type = EV_QUEUE_BTN;
> +    event->key = EvdevUtilButtonEventToButtonNumber(pEvdev, ev->code);
> +    event->val = value;
> +    pEvdev->num_queue++;
> +}
> +
> +static void
> +PostButtonClicks(InputInfoPtr pInfo, struct input_event *ev, int button, int count)
> +{
> +    int i;
> +
> +    for (i = 0; i < count; i++) {
> +        PostButtonEvent(pInfo, ev, 1);
> +        PostButtonEvent(pInfo, ev, 0);
> +    }
>  }
>  
>  /**
> @@ -349,212 +384,358 @@ EvdevReopenTimer(OsTimerPtr timer, CARD32 time, pointer arg)
>  #define ABS_Y_VALUE 0x2
>  #define ABS_VALUE   0x4
>  /**
> - * Take one input event and process it accordingly.
> + * Take the valuators and process them accordingly.
>   */
>  static void
> -EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
> +EvdevProcessValuators(InputInfoPtr pInfo, int v[MAX_VALUATORS], int *num_v,
> +                      int *first_v)
> +{
> +    int tmp;
> +    EvdevPtr pEvdev = pInfo->private;
> +
> +    *num_v = *first_v = 0;
> +
> +    /* convert to relative motion for touchpads */
> +    if (pEvdev->abs && (pEvdev->flags & EVDEV_TOUCHPAD)) {
> +        if (pEvdev->tool) { /* meaning, touch is active */
> +            if (pEvdev->old_vals[0] != -1)
> +                pEvdev->delta[REL_X] = pEvdev->vals[0] - pEvdev->old_vals[0];
> +            if (pEvdev->old_vals[1] != -1)
> +                pEvdev->delta[REL_Y] = pEvdev->vals[1] - pEvdev->old_vals[1];
> +            if (pEvdev->abs & ABS_X_VALUE)
> +                pEvdev->old_vals[0] = pEvdev->vals[0];
> +            if (pEvdev->abs & ABS_Y_VALUE)
> +                pEvdev->old_vals[1] = pEvdev->vals[1];
> +        } else {
> +            pEvdev->old_vals[0] = pEvdev->old_vals[1] = -1;
> +        }
> +        pEvdev->abs = 0;
> +        pEvdev->rel = 1;
> +    }
> +
> +    if (pEvdev->rel) {
> +        int first = REL_CNT, last = 0;
> +        int i;
> +
> +        if (pEvdev->swap_axes) {
> +            tmp = pEvdev->delta[REL_X];
> +            pEvdev->delta[REL_X] = pEvdev->delta[REL_Y];
> +            pEvdev->delta[REL_Y] = tmp;
> +        }
> +        if (pEvdev->invert_x)
> +            pEvdev->delta[REL_X] *= -1;
> +        if (pEvdev->invert_y)
> +            pEvdev->delta[REL_Y] *= -1;
> +
> +        for (i = 0; i < REL_CNT; i++)
> +        {
> +            int map = pEvdev->axis_map[i];
> +            if (pEvdev->delta[i] && map != -1)
> +            {
> +                v[map] = pEvdev->delta[i];
> +                if (map < first)
> +                    first = map;
> +                if (map > last)
> +                    last = map;
> +            }
> +        }
> +
> +        *num_v = (last - first + 1);
> +        *first_v = first;
> +    }
> +    /*
> +     * Some devices only generate valid abs coords when BTN_DIGI is
> +     * pressed.  On wacom tablets, this means that the pen is in
> +     * proximity of the tablet.  After the pen is removed, BTN_DIGI is
> +     * released, and a (0, 0) absolute event is generated.  Checking
> +     * pEvdev->digi here, lets us ignore that event.  pEvdev is
> +     * initialized to 1 so devices that doesn't use this scheme still
> +     * just works.
> +     */
> +    else if (pEvdev->abs && pEvdev->tool) {
> +        memcpy(v, pEvdev->vals, sizeof(int) * pEvdev->num_vals);
> +        if (pEvdev->flags & EVDEV_CALIBRATED)
> +        {
> +            v[0] = xf86ScaleAxis(v[0],
> +                    pEvdev->absinfo[ABS_X].maximum,
> +                    pEvdev->absinfo[ABS_X].minimum,
> +                    pEvdev->calibration.max_x, pEvdev->calibration.min_x);
> +            v[1] = xf86ScaleAxis(v[1],
> +                    pEvdev->absinfo[ABS_Y].maximum,
> +                    pEvdev->absinfo[ABS_Y].minimum,
> +                    pEvdev->calibration.max_y, pEvdev->calibration.min_y);
> +        }
> +
> +        if (pEvdev->swap_axes) {
> +            int tmp = v[0];
> +            v[0] = v[1];
> +            v[1] = tmp;
> +        }
> +
> +        if (pEvdev->invert_x)
> +            v[0] = (pEvdev->absinfo[ABS_X].maximum - v[0] +
> +                    pEvdev->absinfo[ABS_X].minimum);
> +        if (pEvdev->invert_y)
> +            v[1] = (pEvdev->absinfo[ABS_Y].maximum - v[1] +
> +                    pEvdev->absinfo[ABS_Y].minimum);
> +
> +        *num_v = pEvdev->num_vals;
> +        *first_v = 0;
> +    }
> +}
> +
> +/**
> + * Take a button input event and process it accordingly.
> + */
> +static void
> +EvdevProcessButtonEvent(InputInfoPtr pInfo, struct input_event *ev)
>  {
> -    static int delta[REL_CNT];
> -    static int tmp, value;
> -    static unsigned int abs, rel;
>      unsigned int button;
> +    int value;
>      EvdevPtr pEvdev = pInfo->private;
>  
> +    button = EvdevUtilButtonEventToButtonNumber(pEvdev, ev->code);
> +
>      /* Get the signed value, earlier kernels had this as unsigned */
>      value = ev->value;
>  
> -    switch (ev->type) {
> -        case EV_REL:
> -            /* Ignore EV_REL events if we never set up for them. */
> -            if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS))
> -                break;
> +    /* Handle drag lock */
> +    if (EvdevDragLockFilterEvent(pInfo, button, value))
> +        return;
>  
> -            /* Handle mouse wheel emulation */
> -            if (EvdevWheelEmuFilterMotion(pInfo, ev))
> -                break;
> +    if (EvdevWheelEmuFilterButton(pInfo, button, value))
> +        return;
>  
> -            rel = 1;
> -
> -            switch (ev->code) {
> -                case REL_WHEEL:
> -                    if (value > 0)
> -                        PostButtonClicks(pInfo, wheel_up_button, value);
> -                    else if (value < 0)
> -                        PostButtonClicks(pInfo, wheel_down_button, -value);
> -                    break;
> -
> -                case REL_DIAL:
> -                case REL_HWHEEL:
> -                    if (value > 0)
> -                        PostButtonClicks(pInfo, wheel_right_button, value);
> -                    else if (value < 0)
> -                        PostButtonClicks(pInfo, wheel_left_button, -value);
> -                    break;
> -
> -                /* We don't post wheel events as axis motion. */
> -                default:
> -                    delta[ev->code] += value;
> -                    break;
> -            }
> +    if (EvdevMBEmuFilterEvent(pInfo, button, value))
> +        return;
> +
> +    if (button)
> +        PostButtonEvent(pInfo, ev, value);
> +    else
> +        PostKbdEvent(pInfo, ev, value);
> +}
> +
> +/**
> + * Take the relative motion input event and process it accordingly.
> + */
> +static void
> +EvdevProcessRelativeMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
> +{
> +    static int value;
> +    EvdevPtr pEvdev = pInfo->private;
> +
> +    /* Get the signed value, earlier kernels had this as unsigned */
> +    value = ev->value;
> +
> +    /* Ignore EV_REL events if we never set up for them. */
> +    if (!(pEvdev->flags & EVDEV_RELATIVE_EVENTS))
> +        return;
> +
> +    /* Handle mouse wheel emulation */
> +    if (EvdevWheelEmuFilterMotion(pInfo, ev))
> +        return;
> +
> +    pEvdev->rel = 1;
> +
> +    switch (ev->code) {
> +        case REL_WHEEL:
> +            if (value > 0)
> +                PostButtonClicks(pInfo, ev, wheel_up_button, value);
> +            else if (value < 0)
> +                PostButtonClicks(pInfo, ev, wheel_down_button, -value);
>              break;
>  
> -        case EV_ABS:
> -            /* Ignore EV_ABS events if we never set up for them. */
> -            if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
> -                break;
> +        case REL_DIAL:
> +        case REL_HWHEEL:
> +            if (value > 0)
> +                PostButtonClicks(pInfo, ev, wheel_right_button, value);
> +            else if (value < 0)
> +                PostButtonClicks(pInfo, ev, wheel_left_button, -value);
> +            break;
>  
> -            if (ev->code > ABS_MAX)
> -                break;
> -            pEvdev->vals[pEvdev->axis_map[ev->code]] = value;
> -            if (ev->code == ABS_X)
> -                abs |= ABS_X_VALUE;
> -            else if (ev->code == ABS_Y)
> -                abs |= ABS_Y_VALUE;
> -            else
> -                abs |= ABS_VALUE;
> +        /* We don't post wheel events as axis motion. */
> +        default:
> +            pEvdev->delta[ev->code] += value;
>              break;
> +    }
> +}
>  
> -        case EV_KEY:
> -            /* don't repeat mouse buttons */
> -            if (ev->code >= BTN_MOUSE && ev->code < KEY_OK)
> -                if (value == 2)
> -                    break;
> -
> -            switch (ev->code) {
> -                case BTN_TOUCH:
> -                case BTN_TOOL_PEN:
> -                case BTN_TOOL_RUBBER:
> -                case BTN_TOOL_BRUSH:
> -                case BTN_TOOL_PENCIL:
> -                case BTN_TOOL_AIRBRUSH:
> -                case BTN_TOOL_FINGER:
> -                case BTN_TOOL_MOUSE:
> -                case BTN_TOOL_LENS:
> -                    pEvdev->tool = value ? ev->code : 0;
> -                    if (!(pEvdev->flags & EVDEV_TOUCHSCREEN))
> -                        break;
> -                    /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
> -                     * BTN_LEFT. */
> -                    ev->code = BTN_LEFT;
> -                    /* Intentional fallthrough! */
> -
> -                default:
> -                    button = EvdevUtilButtonEventToButtonNumber(pEvdev, ev->code);
> -
> -                    /* Handle drag lock */
> -                    if (EvdevDragLockFilterEvent(pInfo, button, value))
> -                        break;
> -
> -                    if (EvdevWheelEmuFilterButton(pInfo, button, value))
> -                        break;
> -
> -                    if (EvdevMBEmuFilterEvent(pInfo, button, value))
> -                        break;
> -
> -                    if (button)
> -                        xf86PostButtonEvent(pInfo->dev, 0, button, value, 0, 0);
> -                    else
> -                        PostKbdEvent(pInfo, ev, value);
> -                    break;
> -            }
> +/**
> + * Take the absolute motion input event and process it accordingly.
> + */
> +static void
> +EvdevProcessAbsoluteMotionEvent(InputInfoPtr pInfo, struct input_event *ev)
> +{
> +    static int value;
> +    EvdevPtr pEvdev = pInfo->private;
> +
> +    /* Get the signed value, earlier kernels had this as unsigned */
> +    value = ev->value;
> +
> +    /* Ignore EV_ABS events if we never set up for them. */
> +    if (!(pEvdev->flags & EVDEV_ABSOLUTE_EVENTS))
> +        return;
> +
> +    if (ev->code > ABS_MAX)
> +        return;
> +
> +    pEvdev->vals[pEvdev->axis_map[ev->code]] = value;
> +    if (ev->code == ABS_X)
> +        pEvdev->abs |= ABS_X_VALUE;
> +    else if (ev->code == ABS_Y)
> +        pEvdev->abs |= ABS_Y_VALUE;
> +    else
> +        pEvdev->abs |= ABS_VALUE;
> +}
> +
> +/**
> + * Take the key press/release input event and process it accordingly.
> + */
> +static void
> +EvdevProcessKeyEvent(InputInfoPtr pInfo, struct input_event *ev)
> +{
> +    static int value;
> +    EvdevPtr pEvdev = pInfo->private;
> +
> +    /* Get the signed value, earlier kernels had this as unsigned */
> +    value = ev->value;
> +
> +    /* don't repeat mouse buttons */
> +    if (ev->code >= BTN_MOUSE && ev->code < KEY_OK)
> +        if (value == 2)
> +            return;
> +
> +    switch (ev->code) {
> +        case BTN_TOUCH:
> +        case BTN_TOOL_PEN:
> +        case BTN_TOOL_RUBBER:
> +        case BTN_TOOL_BRUSH:
> +        case BTN_TOOL_PENCIL:
> +        case BTN_TOOL_AIRBRUSH:
> +        case BTN_TOOL_FINGER:
> +        case BTN_TOOL_MOUSE:
> +        case BTN_TOOL_LENS:
> +            pEvdev->tool = value ? ev->code : 0;
> +            if (!(pEvdev->flags & EVDEV_TOUCHSCREEN))
> +                break;
> +            /* Treat BTN_TOUCH from devices that only have BTN_TOUCH as
> +             * BTN_LEFT. */
> +            ev->code = BTN_LEFT;
> +            /* Intentional fallthrough! */
> +
> +        default:
> +            EvdevProcessButtonEvent(pInfo, ev);
>              break;
> +    }
> +}
>  
> -        case EV_SYN:
> -            /* convert to relative motion for touchpads */
> -            if (abs && (pEvdev->flags & EVDEV_TOUCHPAD)) {
> -                if (pEvdev->tool) { /* meaning, touch is active */
> -                    if (pEvdev->old_vals[0] != -1)
> -                        delta[REL_X] = pEvdev->vals[0] - pEvdev->old_vals[0];
> -                    if (pEvdev->old_vals[1] != -1)
> -                        delta[REL_Y] = pEvdev->vals[1] - pEvdev->old_vals[1];
> -                    if (abs & ABS_X_VALUE)
> -                        pEvdev->old_vals[0] = pEvdev->vals[0];
> -                    if (abs & ABS_Y_VALUE)
> -                        pEvdev->old_vals[1] = pEvdev->vals[1];
> -                } else {
> -                    pEvdev->old_vals[0] = pEvdev->old_vals[1] = -1;
> -                }
> -                abs = 0;
> -                rel = 1;
> -            }
> +/**
> + * Post the relative motion events.
> + */
> +static void
> +EvdevPostRelativeMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
> +                              int v[MAX_VALUATORS])
> +{
> +    EvdevPtr pEvdev = pInfo->private;
>  
> -            if (rel) {
> -                int post_deltas[REL_CNT] = {0}; /* axis-mapped deltas */
> -                int first = REL_CNT, last = 0;
> -                int i;
> +    if (pEvdev->rel) {
> +        xf86PostMotionEventP(pInfo->dev, FALSE, *first_v, *num_v, v + *first_v);
> +    }
> +}
>  
> -                if (pEvdev->swap_axes) {
> -                    tmp = delta[REL_X];
> -                    delta[REL_X] = delta[REL_Y];
> -                    delta[REL_Y] = tmp;
> -                }
> -                if (pEvdev->invert_x)
> -                    delta[REL_X] *= -1;
> -                if (pEvdev->invert_y)
> -                    delta[REL_Y] *= -1;
> +/**
> + * Post the absolute motion events.
> + */
> +static void
> +EvdevPostAbsoluteMotionEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
> +                              int v[MAX_VALUATORS])
> +{
> +    EvdevPtr pEvdev = pInfo->private;
>  
> -                for (i = 0; i < REL_CNT; i++)
> -                {
> -                    int map = pEvdev->axis_map[i];
> -                    if (delta[i] && map != -1)
> -                    {
> -                        post_deltas[map] = delta[i];
> -                        if (map < first)
> -                            first = map;
> -                        if (map > last)
> -                            last = map;
> -                    }
> -                }
> +    /*
> +     * Some devices only generate valid abs coords when BTN_DIGI is
> +     * pressed.  On wacom tablets, this means that the pen is in
> +     * proximity of the tablet.  After the pen is removed, BTN_DIGI is
> +     * released, and a (0, 0) absolute event is generated.  Checking
> +     * pEvdev->digi here, lets us ignore that event.  pEvdev is
> +     * initialized to 1 so devices that doesn't use this scheme still
> +     * just works.
> +     */
> +    if (pEvdev->abs && pEvdev->tool) {
> +        xf86PostMotionEventP(pInfo->dev, TRUE, *first_v, *num_v, v);
> +    }
> +}
>  
> -                xf86PostMotionEventP(pInfo->dev, FALSE, first,
> -                                     (last - first + 1), &post_deltas[first]);
> -            }
> +/**
> + * Post the queued key/button events.
> + */
> +static void EvdevPostQueuedEvents(InputInfoPtr pInfo, int *num_v, int *first_v,
> +                                  int v[MAX_VALUATORS])
> +{
> +    int i;
> +    EvdevPtr pEvdev = pInfo->private;
>  
> -            /*
> -             * Some devices only generate valid abs coords when BTN_DIGI is
> -             * pressed.  On wacom tablets, this means that the pen is in
> -             * proximity of the tablet.  After the pen is removed, BTN_DIGI is
> -             * released, and a (0, 0) absolute event is generated.  Checking
> -             * pEvdev->digi here, lets us ignore that event.  pEvdev is
> -             * initialized to 1 so devices that doesn't use this scheme still
> -             * just works.
> -             */
> -            if (abs && pEvdev->tool) {
> -                int v[MAX_VALUATORS];
> -
> -                memcpy(v, pEvdev->vals, sizeof(int) * pEvdev->num_vals);
> -                if (pEvdev->flags & EVDEV_CALIBRATED)
> -                {
> -                    v[0] = xf86ScaleAxis(v[0],
> -                            pEvdev->absinfo[ABS_X].maximum,
> -                            pEvdev->absinfo[ABS_X].minimum,
> -                            pEvdev->calibration.max_x, pEvdev->calibration.min_x);
> -                    v[1] = xf86ScaleAxis(v[1],
> -                            pEvdev->absinfo[ABS_Y].maximum,
> -                            pEvdev->absinfo[ABS_Y].minimum,
> -                            pEvdev->calibration.max_y, pEvdev->calibration.min_y);
> -                }
> +    for (i = 0; i < pEvdev->num_queue; i++) {
> +        switch (pEvdev->queue[i].type) {
> +        case EV_QUEUE_KEY:
> +            xf86PostKeyboardEvent(pInfo->dev, pEvdev->queue[i].key,
> +                                  pEvdev->queue[i].val);
> +            break;
> +        case EV_QUEUE_BTN:
> +            /* FIXME: Add xf86PostButtonEventP to the X server so that we may
> +             * pass the valuators on ButtonPress/Release events, too.  Currently
> +             * only MotionNotify events contain the pointer position. */
> +            xf86PostButtonEvent(pInfo->dev, 0, pEvdev->queue[i].key,
> +                                pEvdev->queue[i].val, 0, 0);
> +            break;
> +        }
> +    }
> +}
>  
> -                if (pEvdev->swap_axes) {
> -                    int tmp = v[0];
> -                    v[0] = v[1];
> -                    v[1] = tmp;
> -                }
> +/**
> + * Take the synchronization input event and process it accordingly; the motion
> + * notify events are sent first, then any button/key press/release events.
> + */
> +static void
> +EvdevProcessSyncEvent(InputInfoPtr pInfo, struct input_event *ev)
> +{
> +    int num_v = 0, first_v = 0;
> +    int v[MAX_VALUATORS];
> +    EvdevPtr pEvdev = pInfo->private;
>  
> -                if (pEvdev->invert_x)
> -                    v[0] = (pEvdev->absinfo[ABS_X].maximum - v[0] +
> -                            pEvdev->absinfo[ABS_X].minimum);
> -                if (pEvdev->invert_y)
> -                    v[1] = (pEvdev->absinfo[ABS_Y].maximum - v[1] +
> -                            pEvdev->absinfo[ABS_Y].minimum);
> +    EvdevProcessValuators(pInfo, v, &num_v, &first_v);
>  
> -                xf86PostMotionEventP(pInfo->dev, TRUE, 0, pEvdev->num_vals, v);
> -            }
> +    EvdevPostRelativeMotionEvents(pInfo, &num_v, &first_v, v);
> +    EvdevPostAbsoluteMotionEvents(pInfo, &num_v, &first_v, v);
> +    EvdevPostQueuedEvents(pInfo, &num_v, &first_v, v);
> +
> +    memset(pEvdev->delta, 0, sizeof(pEvdev->delta));
> +    memset(pEvdev->queue, 0, sizeof(pEvdev->queue));
> +    pEvdev->abs = 0;
> +    pEvdev->rel = 0;
> +    pEvdev->num_queue = 0;

nitpick: it's good practice to group the memset for pEvdev->queue and
pEvdev->num_queue together. Just move it up by two lines and that'll do.

> +}
>  
> -            memset(delta, 0, sizeof(delta));
> -            tmp = 0;
> -            abs = 0;
> -            rel = 0;
> +/**
> + * Process the events from the server; nothing is actually posted to the server
> + * until an EV_SYN event is received.
> + */
> +static void
> +EvdevProcessEvent(InputInfoPtr pInfo, struct input_event *ev)
> +{
> +    switch (ev->type) {
> +        case EV_REL:
> +            EvdevProcessRelativeMotionEvent(pInfo, ev);
> +            break;
> +        case EV_ABS:
> +            EvdevProcessAbsoluteMotionEvent(pInfo, ev);
> +            break;
> +        case EV_KEY:
> +            EvdevProcessKeyEvent(pInfo, ev);
> +            break;
> +        case EV_SYN:
> +            EvdevProcessSyncEvent(pInfo, ev);
> +            break;
>      }
>  }
>  
> diff --git a/src/evdev.h b/src/evdev.h
> index 5b95369..4cf0be6 100644
> --- a/src/evdev.h
> +++ b/src/evdev.h
> @@ -54,6 +54,7 @@
>  #endif
>  
>  #define EVDEV_MAXBUTTONS 32
> +#define EVDEV_MAXQUEUE 32
>  
>  #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) >= 3
>  #define HAVE_PROPERTIES 1
> @@ -88,6 +89,15 @@ typedef struct {
>  } WheelAxis, *WheelAxisPtr;
>  
>  typedef struct {
> +    enum {
> +        EV_QUEUE_KEY,	/* xf86PostKeyboardEvent() */
> +        EV_QUEUE_BTN,	/* xf86PostButtonEvent() */
> +    } type;
> +    int key;
> +    int val;
> +} EventQueueRec, *EventQueuePtr;
> +

please add a description of the EQ and how it is used in the driver. I want
to be able to look at the EventQueueRec and immediately understand what it
is used for.

> +typedef struct {
>      const char *device;
>      int grabDevice;         /* grab the event device? */
>  
> @@ -103,6 +113,9 @@ typedef struct {
>      BOOL invert_x;
>      BOOL invert_y;
>  
> +    int delta[REL_CNT];
> +    unsigned int abs, rel;
> +
>      /* XKB stuff has to be per-device rather than per-driver */
>  #if GET_ABI_MAJOR(ABI_XINPUT_VERSION) < 5
>      XkbComponentNamesRec    xkbnames;
> @@ -159,6 +172,10 @@ typedef struct {
>  
>      /* minor/major number */
>      dev_t min_maj;
> +
> +    /* event queue used for button/key events between EV_SYN events */
> +    int                     num_queue;
> +    EventQueueRec           queue[EVDEV_MAXQUEUE];
>  } EvdevRec, *EvdevPtr;
>  
>  unsigned int EvdevUtilButtonEventToButtonNumber(EvdevPtr pEvdev, int code);
> -- 
> 1.6.1
 
Cheers,
  Peter


More information about the xorg-devel mailing list