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

oliver.mcfadden at nokia.com oliver.mcfadden at nokia.com
Mon Jul 20 00:15:55 PDT 2009


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;
+    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,
+                "%s: dropping event due to full queue! (Consider increasing EVDEV_MAXQUEUE)\n",
+                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",
+                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;
+}
 
-            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;
+
+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



More information about the xorg-devel mailing list