[PATCH 2/6] Abstract valuator masks through a set of APIs.

Peter Hutterer peter.hutterer at who-t.net
Tue Oct 19 16:44:10 PDT 2010


This commit introduces an abstraction API for handling masked valuators. The
intent is that drivers just allocate a mask, set the data and pass the mask
to the server. The actual storage type of the mask is hidden from the
drivers.

The new calls for drivers are:
    valuator_mask_new()     /* to allocate a valuator mask */
    valuator_mask_zero()    /* to reset a mask to zero */
    valuator_mask_set()     /* to set a valuator value */

The new interface to the server is
    xf86PostMotionEventM()
    xf86PostButtonEventM()
    xf86PostKeyboardEventM()
    xf86PostProximityEventM()

all taking a mask instead of the valuator array.

The ValuatorMask is currently defined for MAX_VALUATORS fixed size due to
memory allocation restrictions in SIGIO handlers.

For easier review, a lot of the code still uses separate valuator arrays.
This will be fixed in a later patch.

This patch was initially written by Chase Douglas.

Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
Reviewed-by: Chase Douglas <chase.douglas at canonical.com>
---
 Xext/xtest.c                   |   10 +-
 dix/getevents.c                |  245 ++++++++++++++++++++++------------------
 dix/inpututils.c               |  139 +++++++++++++++++++++++
 hw/dmx/input/dmxevents.c       |   51 +++++----
 hw/kdrive/src/kinput.c         |    7 +-
 hw/xfree86/common/xf86Xinput.c |   91 +++++++++++----
 hw/xfree86/common/xf86Xinput.h |    8 ++
 hw/xnest/Events.c              |   14 ++-
 hw/xquartz/darwinEvents.c      |    9 +-
 hw/xwin/winmouse.c             |    8 +-
 include/Makefile.am            |    2 +-
 include/input.h                |   24 +++--
 include/inpututils.h           |   49 ++++++++
 mi/mipointer.c                 |    6 +-
 xkb/xkbActions.c               |   13 ++-
 15 files changed, 490 insertions(+), 186 deletions(-)
 create mode 100644 include/inpututils.h

diff --git a/Xext/xtest.c b/Xext/xtest.c
index d7d254c..b26bc33 100644
--- a/Xext/xtest.c
+++ b/Xext/xtest.c
@@ -52,6 +52,7 @@
 #include "mipointer.h"
 #include "xserver-properties.h"
 #include "exevents.h"
+#include "inpututils.h"
 
 #include "modinit.h"
 
@@ -153,6 +154,7 @@ ProcXTestFakeInput(ClientPtr client)
     WindowPtr root;
     Bool extension = FALSE;
     deviceValuator *dv = NULL;
+    ValuatorMask mask;
     int valuators[MAX_VALUATORS] = {0};
     int numValuators = 0;
     int firstValuator = 0;
@@ -413,14 +415,14 @@ ProcXTestFakeInput(ClientPtr client)
 
     switch(type) {
         case MotionNotify:
-            nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags,
-                            firstValuator, numValuators, valuators);
+            valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
+            nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags, &mask);
             break;
         case ButtonPress:
         case ButtonRelease:
+            valuator_mask_set_range(&mask, firstValuator, numValuators, valuators);
             nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail,
-                                       flags, firstValuator,
-                                       numValuators, valuators);
+                                       flags, &mask);
             break;
         case KeyPress:
         case KeyRelease:
diff --git a/dix/getevents.c b/dix/getevents.c
index 4d32ed3..d04feed 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -46,6 +46,7 @@
 #include "mipointer.h"
 #include "eventstr.h"
 #include "eventconvert.h"
+#include "inpututils.h"
 
 #include <X11/extensions/XKBproto.h>
 #include "xkbsrv.h"
@@ -184,34 +185,40 @@ init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
 }
 
 static void
-set_raw_valuators(RawDeviceEvent *event, int first, int num, int *valuators, int32_t* data)
+set_raw_valuators(RawDeviceEvent *event, ValuatorMask *mask, int *valuators,
+                  int32_t* data)
 {
     int i;
-    for (i = first; i < first + num; i++)
-        SetBit(event->valuators.mask, i);
 
-    memcpy(&data[first], valuators, num * sizeof(uint32_t));
+    for (i = 0; i < valuator_mask_size(mask); i++)
+    {
+        if (valuator_mask_isset(mask, i))
+        {
+            SetBit(event->valuators.mask, i);
+            data[i] = valuators[i];
+        }
+    }
 }
 
 
 static void
-set_valuators(DeviceIntPtr dev, DeviceEvent* event, int first_valuator,
-              int num_valuators, int *valuators)
+set_valuators(DeviceIntPtr dev, DeviceEvent* event, ValuatorMask *mask,
+              int *valuators)
 {
     int i;
 
-    for (i = first_valuator; i < first_valuator + num_valuators; i++)
+    for (i = 0; i < valuator_mask_size(mask); i++)
     {
-        SetBit(event->valuators.mask, i);
-        if (dev->valuator->mode == Absolute)
-            SetBit(event->valuators.mode, i);
-        event->valuators.data_frac[i] =
-            dev->last.remainder[i] * (1 << 16) * (1 << 16);
+        if (valuator_mask_isset(mask, i))
+        {
+            SetBit(event->valuators.mask, i);
+            if (dev->valuator->mode == Absolute)
+                SetBit(event->valuators.mode, i);
+            event->valuators.data[i] = valuators[i];
+            event->valuators.data_frac[i] =
+                dev->last.remainder[i] * (1 << 16) * (1 << 16);
+        }
     }
-
-    memcpy(&event->valuators.data[first_valuator],
-           valuators, num_valuators * sizeof(uint32_t));
-
 }
 
 void
@@ -524,12 +531,12 @@ GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
  *   for SDs: [time] [val0] [val1] ... [valn]
  *   for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
  *
- * For events that have some valuators unset (first_valuator > 0):
+ * For events that have some valuators unset:
  *      min_val == max_val == val == 0.
  */
 static void
-updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
-                    int num_valuators, int *valuators)
+updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, ValuatorMask *mask,
+                    int *valuators)
 {
     char *buff = (char *) pDev->valuator->motion;
     ValuatorClassPtr v;
@@ -548,17 +555,19 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
         buff += sizeof(Time);
 
         memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
-        buff += 3 * sizeof(INT32) * first_valuator;
 
-        for (i = first_valuator; i < first_valuator + num_valuators; i++)
+        for (i = 0; i < v->numAxes; i++)
         {
-            if (i >= v->numAxes)
-                break;
+            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
+            {
+                buff += 3 * sizeof(INT32);
+                continue;
+            }
             memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
             buff += sizeof(INT32);
             memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
             buff += sizeof(INT32);
-            memcpy(buff, &valuators[i - first_valuator], sizeof(INT32));
+            memcpy(buff, &valuators[i], sizeof(INT32));
             buff += sizeof(INT32);
         }
     } else
@@ -571,9 +580,17 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
         buff += sizeof(Time);
 
         memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
-        buff += sizeof(INT32) * first_valuator;
 
-        memcpy(buff, valuators, sizeof(INT32) * num_valuators);
+        for (i = 0; i < MAX_VALUATORS; i++)
+        {
+            if (valuator_mask_size(mask) <= i || !valuator_mask_isset(mask, i))
+            {
+                buff += sizeof(INT32);
+                continue;
+            }
+            memcpy(buff, &valuators[i], sizeof(INT32));
+            buff += sizeof(INT32);
+        }
     }
 
     pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
@@ -631,13 +648,13 @@ clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
  * Clip every axis in the list of valuators to its bounds.
  */
 static void
-clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
-              int *valuators)
+clipValuators(DeviceIntPtr pDev, ValuatorMask *mask, int *valuators)
 {
     int i;
 
-    for (i = 0; i < num_valuators; i++)
-        clipAxis(pDev, i + first_valuator, &(valuators[i]));
+    for (i = 0; i < valuator_mask_size(mask); i++)
+        if (valuator_mask_isset(mask, i))
+            clipAxis(pDev, i, &(valuators[i]));
 }
 
 /**
@@ -680,36 +697,36 @@ UpdateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_event
  * @param dev The device which's pointer is to be moved.
  * @param x Returns the x position of the pointer after the move.
  * @param y Returns the y position of the pointer after the move.
- * @param first The first valuator in @valuators
- * @param num Total number of valuators in @valuators.
+ * @param mask Bit mask of valid valuators.
  * @param valuators Valuator data for each axis between @first and
  *        @first+ at num.
  */
 static void
 moveAbsolute(DeviceIntPtr dev, int *x, int *y,
-             int first, int num, int *valuators)
+             const ValuatorMask *mask, int *valuators)
 {
     int i;
 
-
-    if (num >= 1 && first == 0)
+    if (valuator_mask_isset(mask, 0))
         *x = *(valuators + 0);
     else
         *x = dev->last.valuators[0];
 
-    if (first <= 1 && num >= (2 - first))
-        *y = *(valuators + 1 - first);
+    if (valuator_mask_isset(mask, 1))
+        *y = *(valuators + 1);
     else
         *y = dev->last.valuators[1];
 
     clipAxis(dev, 0, x);
     clipAxis(dev, 1, y);
 
-    i = (first > 2) ? 0 : 2;
-    for (; i < num; i++)
+    for (i = 2; i < valuator_mask_size(mask); i++)
     {
-        dev->last.valuators[i + first] = valuators[i];
-        clipAxis(dev, i, &dev->last.valuators[i + first]);
+        if (valuator_mask_isset(mask, i))
+        {
+            dev->last.valuators[i] = valuators[i];
+            clipAxis(dev, i, &dev->last.valuators[i]);
+        }
     }
 }
 
@@ -719,25 +736,24 @@ moveAbsolute(DeviceIntPtr dev, int *x, int *y,
  * @param dev The device which's pointer is to be moved.
  * @param x Returns the x position of the pointer after the move.
  * @param y Returns the y position of the pointer after the move.
- * @param first The first valuator in @valuators
- * @param num Total number of valuators in @valuators.
+ * @param mask Bit mask of valid valuators.
  * @param valuators Valuator data for each axis between @first and
  *        @first+ at num.
  */
 static void
 moveRelative(DeviceIntPtr dev, int *x, int *y,
-             int first, int num, int *valuators)
+             ValuatorMask *mask, int *valuators)
 {
     int i;
 
     *x = dev->last.valuators[0];
     *y = dev->last.valuators[1];
 
-    if (num >= 1 && first == 0)
+    if (valuator_mask_isset(mask, 0))
         *x += *(valuators +0);
 
-    if (first <= 1 && num >= (2 - first))
-        *y += *(valuators + 1 - first);
+    if (valuator_mask_bit_isset(mask, 1))
+        *y += *(valuators + 1);
 
     /* if attached, clip both x and y to the defined limits (usually
      * co-ord space limit). If it is attached, we need x/y to go over the
@@ -748,13 +764,15 @@ moveRelative(DeviceIntPtr dev, int *x, int *y,
     }
 
     /* calc other axes, clip, drop back into valuators */
-    i = (first > 2) ? 0 : 2;
-    for (; i < num; i++)
+    for (i = 2; i < valuator_mask_size(mask); i++)
     {
-        dev->last.valuators[i + first] += valuators[i];
-        if (dev->valuator->mode == Absolute)
-            clipAxis(dev, i, &dev->last.valuators[i + first]);
-        valuators[i] = dev->last.valuators[i + first];
+        if (valuator_mask_isset(mask, i))
+        {
+            dev->last.valuators[i] += valuators[i];
+            if (dev->valuator->mode == Absolute)
+                clipAxis(dev, i, &dev->last.valuators[i]);
+            valuators[i] = dev->last.valuators[i];
+        }
     }
 }
 
@@ -868,18 +886,18 @@ positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
  * Update the motion history for the device and (if appropriate) for its
  * master device.
  * @param dev Slave device to update.
- * @param first First valuator to append to history.
+ * @param mask Bit mask of valid valuators to append to history.
  * @param num Total number of valuators to append to history.
  * @param ms Current time
  */
 static void
-updateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms)
+updateHistory(DeviceIntPtr dev, ValuatorMask *mask, CARD32 ms)
 {
-    updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]);
+    updateMotionHistory(dev, ms, mask, dev->last.valuators);
     if (dev->u.master)
     {
         DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
-        updateMotionHistory(master, ms, first, num, &dev->last.valuators[first]);
+        updateMotionHistory(master, ms, mask, dev->last.valuators);
     }
 }
 
@@ -889,7 +907,10 @@ updateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms)
  */
 int
 GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
-    return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
+    ValuatorMask mask;
+
+    valuator_mask_zero(&mask);
+    return GetKeyboardValuatorEvents(events, pDev, type, key_code, &mask);
 }
 
 
@@ -911,12 +932,12 @@ GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code)
  */
 int
 GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
-                          int key_code, int first_valuator,
-                          int num_valuators, const int *valuators_in) {
+                          int key_code, const ValuatorMask *mask_in) {
     int num_events = 0;
     CARD32 ms = 0;
     DeviceEvent *event;
     RawDeviceEvent *raw;
+    ValuatorMask mask;
     int valuators[MAX_VALUATORS];
 
     /* refuse events from disabled devices */
@@ -924,7 +945,6 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
         return 0;
 
     if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
-        num_valuators > MAX_VALUATORS ||
        (type != KeyPress && type != KeyRelease) ||
        (key_code < 8 || key_code > 255))
         return 0;
@@ -949,17 +969,17 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
     events++;
     num_events++;
 
-    memcpy(valuators, valuators_in, num_valuators * sizeof(int));
+    valuator_mask_copy(&mask, mask_in);
+
+    if (valuator_mask_size(&mask) > 0)
+        valuator_mask_copy_valuators(&mask, valuators);
 
     init_raw(pDev, raw, ms, type, key_code);
-    set_raw_valuators(raw, first_valuator, num_valuators, valuators,
-                      raw->valuators.data_raw);
+    set_raw_valuators(raw, &mask, valuators, raw->valuators.data_raw);
 
-    if (num_valuators)
-        clipValuators(pDev, first_valuator, num_valuators, valuators);
+    clipValuators(pDev, &mask, valuators);
 
-    set_raw_valuators(raw, first_valuator, num_valuators, valuators,
-                      raw->valuators.data);
+    set_raw_valuators(raw, &mask, valuators, raw->valuators.data);
 
     event = (DeviceEvent*) events->event;
     init_event(pDev, event, ms);
@@ -974,10 +994,9 @@ GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
 	set_key_up(pDev, key_code, KEY_POSTED);
     }
 
-    if (num_valuators)
-        clipValuators(pDev, first_valuator, num_valuators, valuators);
+    clipValuators(pDev, &mask, valuators);
 
-    set_valuators(pDev, event, first_valuator, num_valuators, valuators);
+    set_valuators(pDev, event, &mask, valuators);
 
     return num_events;
 }
@@ -1070,8 +1089,7 @@ transformAbsolute(DeviceIntPtr dev, int v[MAX_VALUATORS])
  */
 int
 GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
-                 int flags, int first_valuator, int num_valuators,
-                 const int *valuators_in) {
+                 int flags, const ValuatorMask *mask_in) {
     int num_events = 1;
     CARD32 ms;
     DeviceEvent *event;
@@ -1080,6 +1098,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         cx, cy; /* only screen coordinates */
     float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
     ScreenPtr scr = miPointerGetScreen(pDev);
+    ValuatorMask mask;
     int valuators[MAX_VALUATORS];
 
     /* refuse events from disabled devices */
@@ -1088,13 +1107,14 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
 
     ms = GetTimeInMillis(); /* before pointer update to help precision */
 
-    if (!scr || !pDev->valuator || first_valuator < 0 ||
-        num_valuators > MAX_VALUATORS ||
-        ((num_valuators + first_valuator) > pDev->valuator->numAxes) ||
+    if (!scr || !pDev->valuator ||
         (type != MotionNotify && type != ButtonPress && type != ButtonRelease) ||
         (type != MotionNotify && !pDev->button) ||
-        ((type == ButtonPress || type == ButtonRelease) && !buttons) ||
-        (type == MotionNotify && num_valuators <= 0))
+        ((type == ButtonPress || type == ButtonRelease) && !buttons))
+        return 0;
+
+    if (type == MotionNotify &&
+        (!mask_in || valuator_mask_num_valuators(mask_in) <= 0))
         return 0;
 
     events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
@@ -1103,54 +1123,62 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     events++;
     num_events++;
 
-    memcpy(valuators, valuators_in, num_valuators * sizeof(int));
+    valuator_mask_copy(&mask, mask_in);
+
+    if (valuator_mask_size(&mask) > 1)
+        valuator_mask_copy_valuators(&mask, valuators);
 
     init_raw(pDev, raw, ms, type, buttons);
-    set_raw_valuators(raw, first_valuator, num_valuators, valuators,
-                      raw->valuators.data_raw);
+    set_raw_valuators(raw, &mask, valuators, raw->valuators.data_raw);
 
     if (flags & POINTER_ABSOLUTE)
     {
         if (flags & POINTER_SCREEN) /* valuators are in screen coords */
         {
 
-            if (num_valuators >= 1 && first_valuator == 0)
+            if (valuator_mask_isset(&mask, 0))
                 valuators[0] = rescaleValuatorAxis(valuators[0], 0.0, &x_frac, NULL,
                         pDev->valuator->axes + 0,
                         scr->width);
-            if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-                valuators[1 - first_valuator] = rescaleValuatorAxis(valuators[1 - first_valuator], 0.0, &y_frac, NULL,
+            if (valuator_mask_isset(&mask, 1))
+                valuators[1] = rescaleValuatorAxis(valuators[1], 0.0, &y_frac, NULL,
                         pDev->valuator->axes + 1,
                         scr->height);
         }
 
         transformAbsolute(pDev, valuators);
-        moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators);
+        moveAbsolute(pDev, &x, &y, &mask, valuators);
     } else {
         if (flags & POINTER_ACCELERATE) {
-            accelPointer(pDev, first_valuator, num_valuators, valuators, ms);
+            /* FIXME: Pointer acceleration only requires X and Y values. This
+             * should be converted to masked valuators. */
+            int vals[2];
+            vals[0] = valuator_mask_isset(&mask, 0) ?
+                      valuators[0] : pDev->last.valuators[0];
+            vals[1] = valuator_mask_isset(&mask, 1) ?
+                      valuators[1] : pDev->last.valuators[1];
+            accelPointer(pDev, 0, 2, vals, ms);
+
             /* The pointer acceleration code modifies the fractional part
              * in-place, so we need to extract this information first */
             x_frac = pDev->last.remainder[0];
             y_frac = pDev->last.remainder[1];
         }
-        moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators);
+        moveRelative(pDev, &x, &y, &mask, valuators);
     }
 
-    set_raw_valuators(raw, first_valuator, num_valuators, valuators,
-            raw->valuators.data);
+    set_raw_valuators(raw, &mask, valuators, raw->valuators.data);
 
     positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
-    updateHistory(pDev, first_valuator, num_valuators, ms);
+    updateHistory(pDev, &mask, ms);
 
     /* Update the valuators with the true value sent to the client*/
-    if (num_valuators >= 1 && first_valuator == 0)
+    if (valuator_mask_isset(&mask, 0))
         valuators[0] = x;
-    if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
-        valuators[1 - first_valuator] = y;
+    if (valuator_mask_isset(&mask, 1))
+        valuators[1] = y;
 
-    if (num_valuators)
-        clipValuators(pDev, first_valuator, num_valuators, valuators);
+    clipValuators(pDev, &mask, valuators);
 
     event = (DeviceEvent*) events->event;
     init_event(pDev, event, ms);
@@ -1176,7 +1204,7 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
     event->root_x_frac = cx_frac;
     event->root_y_frac = cy_frac;
 
-    set_valuators(pDev, event, first_valuator, num_valuators, valuators);
+    set_valuators(pDev, event, &mask, valuators);
 
     return num_events;
 }
@@ -1190,11 +1218,11 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
  * place via GetMaximumEventsNum(), and for freeing it.
  */
 int
-GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
-                   int first_valuator, int num_valuators, const int *valuators_in)
+GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, const ValuatorMask *mask_in)
 {
     int num_events = 1;
     DeviceEvent *event;
+    ValuatorMask mask;
     int valuators[MAX_VALUATORS];
 
     /* refuse events from disabled devices */
@@ -1202,18 +1230,16 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
         return 0;
 
     /* Sanity checks. */
-    if (type != ProximityIn && type != ProximityOut)
+    if ((type != ProximityIn && type != ProximityOut) || !mask_in)
         return 0;
     if (!pDev->valuator)
         return 0;
+
+    valuator_mask_copy(&mask, mask_in);
+
     /* Do we need to send a DeviceValuator event? */
     if ((pDev->valuator->mode & 1) == Relative)
-        num_valuators = 0;
-
-    /* You fail. */
-    if (first_valuator < 0 || num_valuators > MAX_VALUATORS ||
-        (num_valuators + first_valuator) > pDev->valuator->numAxes)
-        return 0;
+        valuator_mask_zero(&mask);
 
     events = UpdateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
 
@@ -1221,12 +1247,11 @@ GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
     init_event(pDev, event, GetTimeInMillis());
     event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
 
-    if (num_valuators) {
-        memcpy(valuators, valuators_in, num_valuators * sizeof(int));
-        clipValuators(pDev, first_valuator, num_valuators, valuators);
-    }
+    if (valuator_mask_size(&mask) > 0)
+        valuator_mask_copy_valuators(&mask, valuators);
+    clipValuators(pDev, &mask, valuators);
 
-    set_valuators(pDev, event, first_valuator, num_valuators, valuators);
+    set_valuators(pDev, event, &mask, valuators);
 
     return num_events;
 }
diff --git a/dix/inpututils.c b/dix/inpututils.c
index 9738033..0e24792 100644
--- a/dix/inpututils.c
+++ b/dix/inpututils.c
@@ -35,6 +35,7 @@
 #include "xace.h"
 #include "xkbsrv.h"
 #include "xkbstr.h"
+#include "inpututils.h"
 
 /* Check if a button map change is okay with the device.
  * Returns -1 for BadValue, as it collides with MappingBusy. */
@@ -418,6 +419,144 @@ FreeInputAttributes(InputAttributes *attrs)
     free(attrs);
 }
 
+/**
+ * Alloc a valuator mask large enough for num_valuators.
+ */
+ValuatorMask*
+valuator_mask_new(int num_valuators)
+{
+    ValuatorMask *mask = calloc(1, sizeof(ValuatorMask));
+    mask->last_bit = -1;
+    return mask;
+}
+
+/**
+ * Sets a range of valuators between first_valuator and num_valuators with
+ * the data in the valuators array. All other values are set to 0.
+ */
+void
+valuator_mask_set_range(ValuatorMask *mask, int first_valuator, int num_valuators,
+                        const int* valuators)
+{
+    int i;
+
+    valuator_mask_zero(mask);
+
+    for (i = first_valuator; i < min(first_valuator + num_valuators, MAX_VALUATORS); i++)
+        valuator_mask_set(mask, i, valuators[i - first_valuator]);
+}
+
+/**
+ * Reset mask to zero.
+ */
+void
+valuator_mask_zero(ValuatorMask *mask)
+{
+    memset(mask, 0, sizeof(*mask));
+    mask->last_bit = -1;
+}
+
+/**
+ * Returns the current size of the mask (i.e. the highest number of
+ * valuators currently set + 1).
+ */
+int
+valuator_mask_size(const ValuatorMask *mask)
+{
+    return mask->last_bit + 1;
+}
+
+/**
+ * Returns the number of valuators set in the given mask.
+ */
+int
+valuator_mask_num_valuators(const ValuatorMask *mask)
+{
+    return CountBits(mask->mask, min(mask->last_bit + 1, MAX_VALUATORS));
+}
+
+/**
+ * Return true if the valuator is set in the mask, or false otherwise.
+ */
+int
+valuator_mask_isset(const ValuatorMask *mask, int valuator)
+{
+    return mask->last_bit >= valuator && BitIsOn(mask->mask, valuator);
+}
+
+/**
+ * Set the valuator to the given data.
+ */
+void
+valuator_mask_set(ValuatorMask *mask, int valuator, int data)
+{
+    mask->last_bit = max(valuator, mask->last_bit);
+    SetBit(mask->mask, valuator);
+    mask->valuators[valuator] = data;
+}
+
+/**
+ * Return the requested valuator value. If the mask bit is not set for the
+ * given valuator, the returned value is undefined.
+ */
+int
+valuator_mask_get(const ValuatorMask *mask, int valuator)
+{
+    return mask->valuators[valuator];
+}
+
+/**
+ * Remove the valuator from the mask.
+ */
+void
+valuator_mask_unset(ValuatorMask *mask, int valuator)
+{
+    if (mask->last_bit >= valuator) {
+        int i, lastbit = -1;
+
+        ClearBit(mask->mask, valuator);
+        mask->valuators[valuator] = 0;
+
+        for (i = 0; i <= mask->last_bit; i++)
+            if (valuator_mask_isset(mask, i))
+                lastbit = max(lastbit, i);
+        mask->last_bit = lastbit;
+    }
+}
+
+
+/**
+ * Copy the valuator data from the given mask and return it as one closed
+ * array (i.e., with holes where the masks are unset.
+ * If valuators_in is not NULL, the valuator data will be copied into
+ * valuators_in. The caller is responsible to allocate enough memory.
+ *
+ * Otherwise, memory is allocated and returned.
+ */
+int*
+valuator_mask_copy_valuators(const ValuatorMask *mask, int *valuators_in)
+{
+    int *valuators;
+
+    if (!valuators_in)
+        valuators = calloc(valuator_mask_size(mask), sizeof(int));
+    else
+        valuators = valuators_in;
+
+    memcpy(valuators, mask->valuators,
+           valuator_mask_size(mask) * sizeof(int));
+
+    return valuators;
+}
+
+void
+valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src)
+{
+    if (src)
+        memcpy(dest, src, sizeof(*dest));
+    else
+        valuator_mask_zero(dest);
+}
 
 int
 CountBits(const uint8_t *mask, int len)
diff --git a/hw/dmx/input/dmxevents.c b/hw/dmx/input/dmxevents.c
index dfa6bda..d22cf06 100644
--- a/hw/dmx/input/dmxevents.c
+++ b/hw/dmx/input/dmxevents.c
@@ -53,6 +53,7 @@
 #include <X11/keysym.h>
 #include "opaque.h"
 #include "inputstr.h"
+#include "inpututils.h"
 #include "mipointer.h"
 #include "mi.h"
 #include "exglobals.h"
@@ -178,12 +179,14 @@ static void enqueueMotion(DevicePtr pDev, int x, int y)
     int i, nevents, valuators[3];
     EventListPtr events;
     int detail = 0;  /* XXX should this be mask of pressed buttons? */
+    ValuatorMask mask;
     valuators[0] = x;
     valuators[1] = y;
 
+    valuator_mask_set_range(&mask, 0, 2, valuators);
     GetEventList(&events);
     nevents = GetPointerEvents(events, p, MotionNotify, detail,
-                               POINTER_ABSOLUTE | POINTER_SCREEN, 0, 2, valuators);
+                               POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
     for (i = 0; i < nevents; i++)
        mieqEnqueue(p, (InternalEvent*)(events + i)->event);
     return;
@@ -292,6 +295,7 @@ static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,
     int                    count;
     EventListPtr           events;
     int                    nevents;
+    ValuatorMask           mask;
 
     memset(xE, 0, sizeof(xE));
 
@@ -370,9 +374,10 @@ static void dmxExtMotion(DMXLocalInputInfoPtr dmxLocal,
 
     if (block)
         dmxSigioBlock();
+    valuator_mask_set_range(&mask, firstAxis, axesCount, v);
     GetEventList(&events);
-    nevents = GetPointerEvents(events, pDevice, MotionNotify, 0, POINTER_ABSOLUTE,
-                               firstAxis, axesCount, v);
+    nevents = GetPointerEvents(events, pDevice, MotionNotify, 0,
+                               POINTER_ABSOLUTE, &mask);
     for (i = 0; i < nevents; i++)
         mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
 
@@ -388,13 +393,14 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
     XDeviceKeyEvent        *ke     = (XDeviceKeyEvent *)e;
     XDeviceMotionEvent     *me     = (XDeviceMotionEvent *)e;
     DeviceIntPtr           pDevice = dmxLocal->pDevice;
-    int                    valuators[6];
+    int                    valuators[MAX_VALUATORS];
     EventListPtr           events;
     int                    nevents, i;
+    ValuatorMask           mask;
 
     if (!e)
         return -1;          /* No extended event passed, cannot handle */
-    
+
     if ((XID)dmxLocal->deviceId != ke->deviceid) {
                                 /* Search for the correct dmxLocal,
                                  * since backend and console events are
@@ -432,23 +438,23 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
     }
 
 #define EXTRACT_VALUATORS(ke, valuators) \
-        valuators[0]       = ke->axis_data[0]; \
-        valuators[1]       = ke->axis_data[1]; \
-        valuators[2]       = ke->axis_data[2]; \
-        valuators[3]       = ke->axis_data[3]; \
-        valuators[4]       = ke->axis_data[4]; \
-        valuators[5]       = ke->axis_data[5]; \
+        valuators[0] = ke->axis_data[0]; \
+        valuators[1] = ke->axis_data[1]; \
+        valuators[2] = ke->axis_data[2]; \
+        valuators[3] = ke->axis_data[3]; \
+        valuators[4] = ke->axis_data[4]; \
+        valuators[5] = ke->axis_data[5]; \
 
     switch (type) {
     case XI_DeviceKeyPress:
     case XI_DeviceKeyRelease:
         EXTRACT_VALUATORS(ke, valuators);
+        valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators);
         if (block)
             dmxSigioBlock();
         GetEventList(&events);
         nevents = GetKeyboardValuatorEvents(events, pDevice, event,
-                                            ke->keycode, ke->first_axis,
-                                            ke->axes_count, valuators);
+                                            ke->keycode, &mask);
         for (i = 0; i < nevents; i++)
             mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
 
@@ -458,12 +464,12 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
     case XI_DeviceButtonPress:
     case XI_DeviceButtonRelease:
         EXTRACT_VALUATORS(ke, valuators);
+        valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators);
         if (block)
             dmxSigioBlock();
         GetEventList(&events);
         nevents = GetPointerEvents(events, pDevice, event, ke->keycode,
-                                   POINTER_ABSOLUTE, ke->first_axis,
-                                   ke->axes_count, valuators);
+                                   POINTER_ABSOLUTE, &mask);
         for (i = 0; i < nevents; i++)
             mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
 
@@ -473,12 +479,11 @@ static int dmxTranslateAndEnqueueExtEvent(DMXLocalInputInfoPtr dmxLocal,
     case XI_ProximityIn:
     case XI_ProximityOut:
         EXTRACT_VALUATORS(ke, valuators);
+        valuator_mask_set_range(&mask, ke->first_axis, ke->axes_count, valuators);
         if (block)
             dmxSigioBlock();
         GetEventList(&events);
-        nevents = GetProximityEvents(events, pDevice, event,
-                                     ke->first_axis, ke->axes_count,
-                                     valuators);
+        nevents = GetProximityEvents(events, pDevice, event, &mask);
         for (i = 0; i < nevents; i++)
             mieqEnqueue(pDevice, (InternalEvent*)(events + i)->event);
 
@@ -664,6 +669,7 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
     DeviceIntPtr p = dmxLocal->pDevice;
     int i, nevents, valuators[3];
     EventListPtr events;
+    ValuatorMask mask;
 
     DMXDBG2("dmxEnqueue: Enqueuing type=%d detail=0x%0x\n", type, detail);
 
@@ -687,12 +693,10 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
     case ButtonPress:
     case ButtonRelease:
         detail = dmxGetButtonMapping(dmxLocal, detail);
+        valuator_mask_zero(&mask);
         GetEventList(&events);
         nevents = GetPointerEvents(events, p, type, detail,
-                                   POINTER_ABSOLUTE | POINTER_SCREEN,
-                                   0,   /* first_valuator = 0 */
-                                   0,   /* num_valuators = 0 */
-                                   valuators);
+                                   POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
         for (i = 0; i < nevents; i++)
             mieqEnqueue(p, (InternalEvent*)(events + i)->event);
         return;
@@ -702,8 +706,9 @@ void dmxEnqueue(DevicePtr pDev, int type, int detail, KeySym keySym,
         valuators[0] = e->xmotion.x;
         valuators[1] = e->xmotion.y;
         valuators[2] = e->xmotion.state; /* FIXME: WTF?? */
+        valuator_mask_set_range(&mask, 0, 3, valuators);
         nevents = GetPointerEvents(events, p, type, detail, 
-                                   POINTER_ABSOLUTE | POINTER_SCREEN, 0, 3, valuators);
+                                   POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
         for (i = 0; i < nevents; i++)
             mieqEnqueue(p, (InternalEvent*)(events + i)->event);
         return;
diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c
index 61ee163..608f3a7 100644
--- a/hw/kdrive/src/kinput.c
+++ b/hw/kdrive/src/kinput.c
@@ -48,6 +48,7 @@
 #include "exglobals.h"
 #include "eventstr.h"
 #include "xserver-properties.h"
+#include "inpututils.h"
 
 #define AtomFromName(x) MakeAtom(x, strlen(x), 1)
 
@@ -1967,14 +1968,16 @@ _KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z,
 {
     int nEvents = 0, i = 0;
     int valuators[3] = { x, y, z };
+    ValuatorMask mask;
 
     /* TRUE from KdHandlePointerEvent, means 'we swallowed the event'. */
     if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel))
         return;
 
+    valuator_mask_set_range(&mask, 0, 3, valuators);
+
     GetEventList(&kdEvents);
-    nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel,
-                               0, 3, valuators);
+    nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel, &mask);
     for (i = 0; i < nEvents; i++)
         KdQueueEvent(pi->dixdev, (InternalEvent *)((kdEvents + i)->event));
 }
diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c
index 67587ca..cf54fd2 100644
--- a/hw/xfree86/common/xf86Xinput.c
+++ b/hw/xfree86/common/xf86Xinput.c
@@ -67,6 +67,7 @@
 #include "exevents.h"	/* AddInputDevice */
 #include "exglobals.h"
 #include "eventstr.h"
+#include "inpututils.h"
 
 #include <string.h>     /* InputClassMatches */
 #ifdef HAVE_FNMATCH_H
@@ -98,7 +99,6 @@
 		return;								\
 	}
 
-
 EventListPtr xf86Events = NULL;
 
 static int
@@ -991,6 +991,19 @@ xf86PostMotionEventP(DeviceIntPtr	device,
                     int			num_valuators,
                     const int		*valuators)
 {
+    ValuatorMask mask;
+
+    XI_VERIFY_VALUATORS(num_valuators);
+
+    valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
+    xf86PostMotionEventM(device, is_absolute, &mask);
+}
+
+void
+xf86PostMotionEventM(DeviceIntPtr	device,
+                     int		is_absolute,
+                     const ValuatorMask	*mask)
+{
     int i = 0, nevents = 0;
     DeviceEvent *event;
     int flags = 0;
@@ -1000,8 +1013,6 @@ xf86PostMotionEventP(DeviceIntPtr	device,
     int dx = 0, dy = 0;
 #endif
 
-    XI_VERIFY_VALUATORS(num_valuators);
-
     if (is_absolute)
         flags = POINTER_ABSOLUTE;
     else
@@ -1009,19 +1020,20 @@ xf86PostMotionEventP(DeviceIntPtr	device,
 
 #if XFreeXDGA
     /* The evdev driver may not always send all axes across. */
-    if (num_valuators >= 1 && first_valuator <= 1) {
+    if (valuator_mask_isset(mask, 0) ||
+        valuator_mask_isset(mask, 1))
         if (miPointerGetScreen(device)) {
             index = miPointerGetScreen(device)->myNum;
-            if (first_valuator == 0)
+            if (valuator_mask_isset(mask, 0))
             {
-                dx = valuators[0];
+                dx = valuator_mask_get(mask, 0);
                 if (is_absolute)
                     dx -= device->last.valuators[0];
             }
 
-            if (first_valuator == 1 || num_valuators >= 2)
+            if (valuator_mask_isset(mask, 1))
             {
-                dy = valuators[1 - first_valuator];
+                dy = valuator_mask_get(mask, 1);
                 if (is_absolute)
                     dy -= device->last.valuators[1];
             }
@@ -1029,12 +1041,9 @@ xf86PostMotionEventP(DeviceIntPtr	device,
             if (DGAStealMotionEvent(device, index, dx, dy))
                 return;
         }
-    }
 #endif
 
-    nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0,
-                               flags, first_valuator, num_valuators,
-                               valuators);
+    nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, mask);
 
     for (i = 0; i < nevents; i++) {
         event = (DeviceEvent*)((xf86Events + i)->event);
@@ -1072,13 +1081,23 @@ xf86PostProximityEventP(DeviceIntPtr	device,
                         int		num_valuators,
                         const int	*valuators)
 {
-    int i, nevents;
+    ValuatorMask mask;
 
     XI_VERIFY_VALUATORS(num_valuators);
 
+    valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
+    xf86PostProximityEventM(device, is_in, &mask);
+}
+
+void
+xf86PostProximityEventM(DeviceIntPtr	device,
+                        int		is_in,
+                        const ValuatorMask *mask)
+{
+    int i, nevents;
+
     nevents = GetProximityEvents(xf86Events, device,
-                                 is_in ? ProximityIn : ProximityOut, 
-                                 first_valuator, num_valuators, valuators);
+                                 is_in ? ProximityIn : ProximityOut, mask);
     for (i = 0; i < nevents; i++)
         mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event));
 
@@ -1118,6 +1137,21 @@ xf86PostButtonEventP(DeviceIntPtr	device,
                      int		num_valuators,
                      const int		*valuators)
 {
+    ValuatorMask mask;
+
+    XI_VERIFY_VALUATORS(num_valuators);
+
+    valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
+    xf86PostButtonEventM(device, is_absolute, button, is_down, &mask);
+}
+
+void
+xf86PostButtonEventM(DeviceIntPtr	device,
+                     int		is_absolute,
+                     int		button,
+                     int		is_down,
+                     const ValuatorMask	*mask)
+{
     int i = 0, nevents = 0;
     int flags = 0;
 
@@ -1125,8 +1159,6 @@ xf86PostButtonEventP(DeviceIntPtr	device,
     int index;
 #endif
 
-    XI_VERIFY_VALUATORS(num_valuators);
-
     if (is_absolute)
         flags = POINTER_ABSOLUTE;
     else
@@ -1142,7 +1174,7 @@ xf86PostButtonEventP(DeviceIntPtr	device,
 
     nevents = GetPointerEvents(xf86Events, device,
                                is_down ? ButtonPress : ButtonRelease, button,
-                               flags, first_valuator, num_valuators, valuators);
+                               flags, mask);
 
     for (i = 0; i < nevents; i++)
         mieqEnqueue(device, (InternalEvent*)((xf86Events + i)->event));
@@ -1183,15 +1215,27 @@ xf86PostKeyEventP(DeviceIntPtr	device,
                   int		num_valuators,
                   const int	*valuators)
 {
-    int i = 0, nevents = 0;
+    ValuatorMask mask;
 
     XI_VERIFY_VALUATORS(num_valuators);
 
+    valuator_mask_set_range(&mask, first_valuator, num_valuators, valuators);
+    xf86PostKeyEventM(device, key_code, is_down, is_absolute, &mask);
+}
+
+void
+xf86PostKeyEventM(DeviceIntPtr	device,
+                  unsigned int	key_code,
+                  int		is_down,
+                  int		is_absolute,
+                  const ValuatorMask *mask)
+{
+    int i = 0, nevents = 0;
+
     if (is_absolute) {
         nevents = GetKeyboardValuatorEvents(xf86Events, device,
                                             is_down ? KeyPress : KeyRelease,
-                                            key_code, first_valuator,
-                                            num_valuators, valuators);
+                                            key_code, mask);
     }
     else {
         nevents = GetKeyboardEvents(xf86Events, device,
@@ -1208,7 +1252,10 @@ xf86PostKeyboardEvent(DeviceIntPtr      device,
                       unsigned int      key_code,
                       int               is_down)
 {
-    xf86PostKeyEventP(device, key_code, is_down, 0, 0, 0, NULL);
+    ValuatorMask mask;
+
+    valuator_mask_zero(&mask);
+    xf86PostKeyEventM(device, key_code, is_down, 0, &mask);
 }
 
 InputInfoPtr
diff --git a/hw/xfree86/common/xf86Xinput.h b/hw/xfree86/common/xf86Xinput.h
index 5aa4509..829bf78 100644
--- a/hw/xfree86/common/xf86Xinput.h
+++ b/hw/xfree86/common/xf86Xinput.h
@@ -115,19 +115,27 @@ extern _X_EXPORT void xf86PostMotionEvent(DeviceIntPtr device, int is_absolute,
 			 int first_valuator, int num_valuators, ...);
 extern _X_EXPORT void xf86PostMotionEventP(DeviceIntPtr device, int is_absolute,
 			 int first_valuator, int num_valuators, const int *valuators);
+extern _X_EXPORT void xf86PostMotionEventM(DeviceIntPtr device, int is_absolute,
+			 const ValuatorMask *mask);
 extern _X_EXPORT void xf86PostProximityEvent(DeviceIntPtr device, int is_in,
 			    int first_valuator, int num_valuators, ...);
 extern _X_EXPORT void xf86PostProximityEventP(DeviceIntPtr device, int is_in, int first_valuator,
 			     int num_valuators, const int *valuators);
+extern _X_EXPORT void xf86PostProximityEventM(DeviceIntPtr device, int is_in,
+			 const ValuatorMask *mask);
 extern _X_EXPORT void xf86PostButtonEvent(DeviceIntPtr device, int is_absolute, int button,
 		    	 int is_down, int first_valuator, int num_valuators,
 			 ...);
 extern _X_EXPORT void xf86PostButtonEventP(DeviceIntPtr device, int is_absolute, int button,
 			  int is_down, int first_valuator, int num_valuators,
 			  const int *valuators);
+extern _X_EXPORT void xf86PostButtonEventM(DeviceIntPtr device, int is_absolute, int button,
+			  int is_down, const ValuatorMask *mask);
 extern _X_EXPORT void xf86PostKeyEvent(DeviceIntPtr device, unsigned int key_code, int is_down,
 		      int is_absolute, int first_valuator, int num_valuators,
 		      ...);
+extern _X_EXPORT void xf86PostKeyEventM(DeviceIntPtr device, unsigned int key_code, int is_down,
+		       int is_absolute, const ValuatorMask *mask);
 extern _X_EXPORT void xf86PostKeyEventP(DeviceIntPtr device, unsigned int key_code, int is_down,
 		       int is_absolute, int first_valuator, int num_valuators,
 		       const int *valuators);
diff --git a/hw/xnest/Events.c b/hw/xnest/Events.c
index 62e17cb..5ff6d21 100644
--- a/hw/xnest/Events.c
+++ b/hw/xnest/Events.c
@@ -25,6 +25,7 @@ is" without express or implied warranty.
 #include "windowstr.h"
 #include "servermd.h"
 #include "inputstr.h"
+#include "inpututils.h"
 
 #include "mi.h"
 
@@ -117,6 +118,7 @@ xnestCollectEvents(void)
 {
   XEvent X;
   int i, n, valuators[2];
+  ValuatorMask mask;
   ScreenPtr pScreen;
   GetEventList(&xnestEvents);
 
@@ -133,19 +135,21 @@ xnestCollectEvents(void)
       break;
       
     case ButtonPress:
+      valuator_mask_set_range(&mask, 0, 0, NULL);
       xnestUpdateModifierState(X.xkey.state);
       lastEventTime = GetTimeInMillis();
       n = GetPointerEvents(xnestEvents, xnestPointerDevice, ButtonPress,
-                           X.xbutton.button, POINTER_RELATIVE, 0, 0, NULL);
+                           X.xbutton.button, POINTER_RELATIVE, &mask);
       for (i = 0; i < n; i++)
         mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
       break;
       
     case ButtonRelease:
+      valuator_mask_set_range(&mask, 0, 0, NULL);
       xnestUpdateModifierState(X.xkey.state);
       lastEventTime = GetTimeInMillis();
       n = GetPointerEvents(xnestEvents, xnestPointerDevice, ButtonRelease,
-                           X.xbutton.button, POINTER_RELATIVE, 0, 0, NULL);
+                           X.xbutton.button, POINTER_RELATIVE, &mask);
       for (i = 0; i < n; i++)
         mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
       break;
@@ -153,9 +157,10 @@ xnestCollectEvents(void)
     case MotionNotify:
       valuators[0] = X.xmotion.x;
       valuators[1] = X.xmotion.y;
+      valuator_mask_set_range(&mask, 0, 2, valuators);
       lastEventTime = GetTimeInMillis();
       n = GetPointerEvents(xnestEvents, xnestPointerDevice, MotionNotify,
-                           0, POINTER_ABSOLUTE, 0, 2, valuators);
+                           0, POINTER_ABSOLUTE, &mask);
       for (i = 0; i < n; i++)
         mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
       break;
@@ -186,9 +191,10 @@ xnestCollectEvents(void)
 	  NewCurrentScreen(inputInfo.pointer, pScreen, X.xcrossing.x, X.xcrossing.y);
           valuators[0] = X.xcrossing.x;
           valuators[1] = X.xcrossing.y;
+          valuator_mask_set_range(&mask, 0, 2, valuators);
           lastEventTime = GetTimeInMillis();
           n = GetPointerEvents(xnestEvents, xnestPointerDevice, MotionNotify,
-                               0, POINTER_ABSOLUTE, 0, 2, valuators);
+                               0, POINTER_ABSOLUTE, &mask);
           for (i = 0; i < n; i++)
             mieqEnqueue(xnestPointerDevice, (InternalEvent*)(xnestEvents + i)->event);
 	  xnestDirectInstallColormaps(pScreen);
diff --git a/hw/xquartz/darwinEvents.c b/hw/xquartz/darwinEvents.c
index 74fadf4..672d768 100644
--- a/hw/xquartz/darwinEvents.c
+++ b/hw/xquartz/darwinEvents.c
@@ -414,6 +414,7 @@ void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, floa
 			     float pressure, float tilt_x, float tilt_y) {
 	static int darwinFakeMouseButtonDown = 0;
 	int i, num_events;
+    ValuatorMask mask;
     ScreenPtr screen;
     int valuators[5];
 	
@@ -464,8 +465,9 @@ void DarwinSendPointerEvents(DeviceIntPtr pDev, int ev_type, int ev_button, floa
 
     DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, pressure, tilt_x, tilt_y);
     darwinEvents_lock(); {
+        valuator_mask_set_range(&mask, 0, (pDev == darwinTabletCurrent) ? 5 : 2, valuators);
         num_events = GetPointerEvents(darwinEvents, pDev, ev_type, ev_button, 
-                                      POINTER_ABSOLUTE, 0, pDev==darwinTabletCurrent?5:2, valuators);
+                                      POINTER_ABSOLUTE, 0, &mask);
         for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
         if(num_events > 0) DarwinPokeEQ();
     } darwinEvents_unlock();
@@ -491,6 +493,7 @@ void DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) {
     ScreenPtr screen;
     DeviceIntPtr pDev = darwinTabletCurrent;
     int valuators[5];
+    ValuatorMask mask;
 
 	DEBUG_LOG("DarwinSendProximityEvents(%d, %f, %f)\n", ev_type, pointer_x, pointer_y);
 
@@ -507,8 +510,8 @@ void DarwinSendProximityEvents(int ev_type, float pointer_x, float pointer_y) {
 
     DarwinPrepareValuators(pDev, valuators, screen, pointer_x, pointer_y, 0.0f, 0.0f, 0.0f);
     darwinEvents_lock(); {
-        num_events = GetProximityEvents(darwinEvents, pDev, ev_type,
-                                        0, 5, valuators);
+        valuator_mask_set_range(&mask, 0, 5, valuators);
+        num_events = GetProximityEvents(darwinEvents, pDev, ev_type, &mask);
         for(i=0; i<num_events; i++) mieqEnqueue (pDev, (InternalEvent*)darwinEvents[i].event);
         if(num_events > 0) DarwinPokeEQ();
     } darwinEvents_unlock();
diff --git a/hw/xwin/winmouse.c b/hw/xwin/winmouse.c
index 342f20d..e645d7e 100644
--- a/hw/xwin/winmouse.c
+++ b/hw/xwin/winmouse.c
@@ -240,15 +240,17 @@ winMouseButtonsSendEvent (int iEventType, int iButton)
 {
   EventListPtr events;
   int i, nevents;
+  ValuatorMask mask;
 
 #if defined(XFree86Server)
   if (g_winMouseButtonMap)
     iButton = g_winMouseButtonMap[iButton];
 #endif
 
+  valuator_mask_zero(&mask);
   GetEventList(&events);
   nevents = GetPointerEvents(events, g_pwinPointer, iEventType, iButton,
-			     POINTER_RELATIVE, 0, 0, NULL);
+			     POINTER_RELATIVE, &mask);
 
   for (i = 0; i < nevents; i++)
     mieqEnqueue(g_pwinPointer, events[i].event);
@@ -373,15 +375,17 @@ void winEnqueueMotion(int x, int y)
 {
   int i, nevents;
   int valuators[2];
+  ValuatorMask mask;
   EventListPtr events;
 
   miPointerSetPosition(g_pwinPointer, &x, &y);
   valuators[0] = x;
   valuators[1] = y;
 
+  valuator_mask_set_range(&mask, 0, 2, valuators);
   GetEventList(&events);
   nevents = GetPointerEvents(events, g_pwinPointer, MotionNotify, 0,
-			     POINTER_ABSOLUTE | POINTER_SCREEN, 0, 2, valuators);
+			     POINTER_ABSOLUTE | POINTER_SCREEN, &mask);
 
   for (i = 0; i < nevents; i++)
     mieqEnqueue(g_pwinPointer, events[i].event);
diff --git a/include/Makefile.am b/include/Makefile.am
index e76de05..eb0e3a7 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -67,6 +67,6 @@ AM_CFLAGS = $(DIX_CFLAGS)
 
 EXTRA_DIST = 	\
 	dix-config-apple-verbatim.h \
-	eventconvert.h eventstr.h \
+	eventconvert.h eventstr.h inpututils.h \
 	protocol-versions.h \
 	xsha1.h
diff --git a/include/input.h b/include/input.h
index 36ce4c9..76df4ff 100644
--- a/include/input.h
+++ b/include/input.h
@@ -157,6 +157,8 @@ typedef struct _DeviceRec {
     Bool	on;			/* used by DDX to keep state */
 } DeviceRec, *DevicePtr;
 
+typedef struct _ValuatorMask ValuatorMask;
+
 typedef struct {
     int			click, bell, bell_pitch, bell_duration;
     Bool		autoRepeat;
@@ -445,9 +447,7 @@ extern _X_EXPORT int GetPointerEvents(
     int type,
     int buttons,
     int flags,
-    int first_valuator,
-    int num_valuators,
-    const int *valuators);
+    const ValuatorMask *mask);
 
 extern _X_EXPORT int GetKeyboardEvents(
     EventListPtr events,
@@ -460,17 +460,13 @@ extern int GetKeyboardValuatorEvents(
     DeviceIntPtr pDev,
     int type,
     int key_code,
-    int first_valuator,
-    int num_valuator,
-    const int *valuators);
+    const ValuatorMask *mask);
 
 extern int GetProximityEvents(
     EventListPtr events,
     DeviceIntPtr pDev,
     int type,
-    int first_valuator,
-    int num_valuators,
-    const int *valuators);
+    const ValuatorMask *mask);
 
 extern void PostSyntheticMotion(
     DeviceIntPtr pDev,
@@ -554,4 +550,14 @@ extern _X_EXPORT void DDXRingBell(
    xfixes/cursor.c uses it to determine if the cursor is enabled */
 extern Bool EnableCursor;
 
+/* For server-internal functions, see inpututil.h */
+extern _X_EXPORT ValuatorMask  *valuator_mask_new(int num_valuators);
+extern _X_EXPORT void valuator_mask_set_range(ValuatorMask *mask,
+                                       int first_valuator, int num_valuators,
+                                       const int* valuators);
+extern _X_EXPORT void valuator_mask_set(ValuatorMask *mask,
+                                        int valuator,
+                                        int data);
+extern _X_EXPORT void valuator_mask_zero(ValuatorMask *mask);
+
 #endif /* INPUT_H */
diff --git a/include/inpututils.h b/include/inpututils.h
new file mode 100644
index 0000000..56bb75d
--- /dev/null
+++ b/include/inpututils.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright © 2010 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include "dix-config.h"
+#endif
+
+#ifndef INPUTUTILS_H
+#define INPUTUTILS_H
+
+#include "input.h"
+
+struct _ValuatorMask {
+    int8_t      last_bit; /* highest bit set in mask */
+    uint8_t     mask[(MAX_VALUATORS + 7)/8];
+    int         valuators[MAX_VALUATORS]; /* valuator data */
+};
+
+/* server-internal */
+extern _X_HIDDEN int valuator_mask_size(const ValuatorMask *mask);
+extern _X_HIDDEN int valuator_mask_isset(const ValuatorMask *mask, int bit);
+extern _X_HIDDEN void valuator_mask_unset(ValuatorMask *mask, int bit);
+extern _X_HIDDEN int* valuator_mask_copy_valuators(const ValuatorMask *mask, int *valuators_in);
+extern _X_HIDDEN int valuator_mask_num_valuators(const ValuatorMask *mask);
+extern _X_HIDDEN void valuator_mask_copy(ValuatorMask *dest, const ValuatorMask *src);
+extern _X_HIDDEN int valuator_mask_get(const ValuatorMask *mask, int valnum);
+
+#endif
diff --git a/mi/mipointer.c b/mi/mipointer.c
index d8aaf8c..554397a 100644
--- a/mi/mipointer.c
+++ b/mi/mipointer.c
@@ -39,6 +39,7 @@ in this Software without prior written authorization from The Open Group.
 # include   "cursorstr.h"
 # include   "dixstruct.h"
 # include   "inputstr.h"
+# include   "inpututils.h"
 
 DevPrivateKeyRec miPointerScreenKeyRec;
 
@@ -553,6 +554,7 @@ miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
 {
     int i, nevents;
     int valuators[2];
+    ValuatorMask mask;
 
     miPointerMoveNoEvent(pDev, pScreen, x, y);
 
@@ -571,7 +573,9 @@ miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
         }
     }
 
-    nevents = GetPointerEvents(events, pDev, MotionNotify, 0, POINTER_SCREEN | POINTER_ABSOLUTE, 0, 2, valuators);
+    valuator_mask_set_range(&mask, 0, 2, valuators);
+    nevents = GetPointerEvents(events, pDev, MotionNotify, 0,
+                               POINTER_SCREEN | POINTER_ABSOLUTE, &mask);
 
     OsBlockSignals();
 #ifdef XQUARTZ
diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c
index c020444..8d7c124 100644
--- a/xkb/xkbActions.c
+++ b/xkb/xkbActions.c
@@ -42,6 +42,7 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
 #include <ctype.h>
 #include "mi.h"
 #include "mipointer.h"
+#include "inpututils.h"
 #define EXTENSION_EVENT_BASE 64
 
 DevPrivateKeyRec xkbDevicePrivateKeyRec;
@@ -1354,7 +1355,7 @@ xkbStateNotify	sn;
  * First one on drinking island wins!
  */
 static void
-InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, int num_valuators, int *valuators)
+InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, ValuatorMask *mask)
 {
     ScreenPtr           pScreen;
     EventListPtr        events;
@@ -1376,8 +1377,7 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, int nu
     OsBlockSignals();
     pScreen = miPointerGetScreen(ptr);
     saveWait = miPointerSetWaitForUpdate(pScreen, FALSE);
-    nevents = GetPointerEvents(events, ptr, type, button, flags, 0,
-                               num_valuators, valuators);
+    nevents = GetPointerEvents(events, ptr, type, button, flags, mask);
     if (IsMaster(dev) && (lastSlave && lastSlave != ptr))
         UpdateFromMaster(&events[nevents], lastSlave, DEVCHANGE_POINTER_EVENT, &nevents);
     miPointerSetWaitForUpdate(pScreen, saveWait);
@@ -1393,6 +1393,7 @@ InjectPointerKeyEvents(DeviceIntPtr dev, int type, int button, int flags, int nu
 static void
 XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
 {
+    ValuatorMask        mask;
     int                 gpe_flags = 0;
 
     /* ignore attached SDs */
@@ -1404,7 +1405,9 @@ XkbFakePointerMotion(DeviceIntPtr dev, unsigned flags,int x,int y)
     else
         gpe_flags = POINTER_RELATIVE;
 
-    InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, 2, (int[]){x, y});
+    valuator_mask_set_range(&mask, 0, 2, (int[]){x, y});
+
+    InjectPointerKeyEvents(dev, MotionNotify, 0, gpe_flags, &mask);
 }
 
 void
@@ -1434,5 +1437,5 @@ XkbFakeDeviceButton(DeviceIntPtr dev,Bool press,int button)
         return;
 
     InjectPointerKeyEvents(dev, press ? ButtonPress : ButtonRelease,
-                           button, 0, 0, NULL);
+                           button, 0, NULL);
 }
-- 
1.7.2.3



More information about the xorg-devel mailing list