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

Oliver McFadden oliver.mcfadden at nokia.com
Thu Jul 23 03:14:36 PDT 2009


On Thu, 2009-07-23 at 02:30 +0200, ext Peter Hutterer wrote:
> Thanks for the patch. it looks good, I have a few minor changes though,
> mostly style.

Ok, I'll send a new patch addressing these issues.

> 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