[PATCH 2/2] Add support for per-axis valuator modes (Relative/Absolute)

Chase Douglas chase.douglas at canonical.com
Fri Jul 16 06:21:19 PDT 2010


The XI2 protocol supports per-axis modes, but the server so far does
not. This change adds support in the server.

A complication is the fact that XI1 does not support per-axis modes.
The solution provided here is to set a per-device mode that defines the
mode of at least the first two valuators (X and Y). The per-axis
valuator mode defaults to Relative, so any absolute axes must be
explicitly set. Note that initializing the first two axes to a different
mode than the device mode will fail.

For XI1 events, any axes following the first two that have the same mode
will be sent to clients, up to the first axis that has a different mode.
Thus, if a device has relative, then absolute, then relative mode axes,
only the first block of relative axes will be sent over XI1.

Since the XI2 protocol supports per-axis modes, all axes are sent to the
client.

Signed-off-by: Chase Douglas <chase.douglas at canonical.com>
---
 Xi/exevents.c            |    1 +
 Xi/xiquerydevice.c       |    2 +-
 dix/devices.c            |    3 +--
 dix/eventconvert.c       |   14 +++++++++++++-
 dix/getevents.c          |   23 ++++++++++++++++-------
 hw/dmx/input/dmxmotion.c |    7 +++----
 include/inputstr.h       |    1 +
 7 files changed, 36 insertions(+), 15 deletions(-)

diff --git a/Xi/exevents.c b/Xi/exevents.c
index e990aeb..26084f5 100644
--- a/Xi/exevents.c
+++ b/Xi/exevents.c
@@ -1145,6 +1145,7 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int
     ax->min_resolution = min_res;
     ax->max_resolution = max_res;
     ax->label = label;
+    ax->mode = dev->valuator->mode;
 }
 
 static void
diff --git a/Xi/xiquerydevice.c b/Xi/xiquerydevice.c
index 303c8b2..c8b3d7e 100644
--- a/Xi/xiquerydevice.c
+++ b/Xi/xiquerydevice.c
@@ -349,7 +349,7 @@ ListValuatorInfo(DeviceIntPtr dev, xXIValuatorInfo* info, int axisnumber,
     info->value.frac = (int)(v->axisVal[axisnumber] * (1 << 16) * (1 << 16));
     info->resolution = v->axes[axisnumber].resolution;
     info->number = axisnumber;
-    info->mode = v->mode; /* Server doesn't have per-axis mode yet */
+    info->mode = v->axes[axisnumber].mode;
     info->sourceid = v->sourceid;
 
     if (!reportState)
diff --git a/dix/devices.c b/dix/devices.c
index ac5806a..e4048e4 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -2366,8 +2366,7 @@ RecalculateMasterButtons(DeviceIntPtr slave)
                 event.valuators[i].min = master->valuator->axes[i].min_value;
                 event.valuators[i].max = master->valuator->axes[i].max_value;
                 event.valuators[i].resolution = master->valuator->axes[i].resolution;
-                /* This should, eventually, be a per-axis mode */
-                event.valuators[i].mode = master->valuator->mode;
+                event.valuators[i].mode = master->valuator->axes[i].mode;
                 event.valuators[i].name = master->valuator->axes[i].label;
             }
         }
diff --git a/dix/eventconvert.c b/dix/eventconvert.c
index 4e3de0b..991298e 100644
--- a/dix/eventconvert.c
+++ b/dix/eventconvert.c
@@ -252,6 +252,12 @@ eventToKeyButtonPointer(DeviceEvent *ev, xEvent **xi, int *count)
     }
 
     num_events = (countValuators(ev, &first) + 5)/6; /* valuator ev */
+    if (num_events <= 0)
+    {
+        *count = 0;
+        return BadMatch;
+    }
+
     num_events++; /* the actual event event */
 
     *xi = calloc(num_events, sizeof(xEvent));
@@ -309,6 +315,12 @@ countValuators(DeviceEvent *ev, int *first)
 
     for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
     {
+        /* Assume mode of 0th valuator matches XI1 device mode. Stop when the
+         * event mode changes since XI1 can't handle mixed mode devices.
+         */
+        if (ev->valuators.mode[i] != ev->valuators.mode[0])
+            break;
+
         if (BitIsOn(ev->valuators.mask, i))
         {
             if (first_valuator == -1)
@@ -431,7 +443,7 @@ appendValuatorInfo(DeviceChangedEvent *dce, xXIValuatorInfo *info, int axisnumbe
     info->value.frac = 0;
     info->resolution = dce->valuators[axisnumber].resolution;
     info->number = axisnumber;
-    info->mode = dce->valuators[axisnumber].mode; /* Server doesn't have per-axis mode yet */
+    info->mode = dce->valuators[axisnumber].mode;
     info->sourceid = dce->sourceid;
 
     return info->length * 4;
diff --git a/dix/getevents.c b/dix/getevents.c
index 20cc79b..72daa16 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -208,7 +208,7 @@ set_valuators(DeviceIntPtr dev, DeviceEvent* event, uint8_t *mask,
         if (BitIsOn(mask, i))
         {
             SetBit(event->valuators.mask, i);
-            if (dev->valuator->mode == Absolute)
+            if (dev->valuator->axes[i].mode == Absolute)
                 SetBit(event->valuators.mode, i);
             event->valuators.data[i] = valuators[i];
             event->valuators.data_frac[i] =
@@ -253,8 +253,7 @@ CreateClassesChangedEvent(EventList* event,
             dce->valuators[i].min = slave->valuator->axes[i].min_value;
             dce->valuators[i].max = slave->valuator->axes[i].max_value;
             dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
-            /* This should, eventually, be a per-axis mode */
-            dce->valuators[i].mode = slave->valuator->mode;
+            dce->valuators[i].mode = slave->valuator->axes[i].mode;
             dce->valuators[i].name = slave->valuator->axes[i].label;
         }
     }
@@ -372,8 +371,15 @@ AllocateMotionHistory(DeviceIntPtr pDev)
      */
     if (IsMaster(pDev))
         size = sizeof(INT32) * 3 * MAX_VALUATORS;
-    else
-        size = sizeof(INT32) * pDev->valuator->numAxes;
+    else {
+        int numAxes;
+        /* XI1 doesn't understand mixed mode devices */
+        for (numAxes = 0; numAxes < pDev->valuator->numAxes; numAxes++)
+            if ((pDev->valuator->axes[numAxes].mode & DeviceMode) !=
+                (pDev->valuator->mode & DeviceMode))
+                break;
+        size = sizeof(INT32) * numAxes;
+    }
 
     size += sizeof(Time);
 
@@ -554,7 +560,10 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, uint8_t *mask,
 
         for (i = 0; i < MAX_VALUATORS; i++)
         {
-            if (i >= v->numAxes)
+            /* XI1 doesn't support mixed mode devices */
+            if (i >= v->numAxes ||
+                (pDev->valuator->axes[i].mode & DeviceMode) !=
+                (pDev->valuator->mode & DeviceMode))
                 break;
             if (!BitIsOn(mask, i))
             {
@@ -768,7 +777,7 @@ moveRelative(DeviceIntPtr dev, int *x, int *y,
         if (BitIsOn(mask, i))
         {
             dev->last.valuators[i] += valuators[i];
-            if (dev->valuator->mode == Absolute)
+            if (dev->valuator->axes[i].mode == Absolute)
                 clipAxis(dev, i, &dev->last.valuators[i]);
             valuators[i] = dev->last.valuators[i];
         }
diff --git a/hw/dmx/input/dmxmotion.c b/hw/dmx/input/dmxmotion.c
index a86b62e..1aae5fe 100644
--- a/hw/dmx/input/dmxmotion.c
+++ b/hw/dmx/input/dmxmotion.c
@@ -125,12 +125,11 @@ void dmxPointerPutMotionEvent(DeviceIntPtr pDevice,
                                 /* Initialize the data from the known
                                  * values (if Absolute) or to zero (if
                                  * Relative) */
-    if (pDevice->valuator->mode == Absolute) {
-        for (i = 0; i < numAxes; i++) 
+    for (i = 0; i < numAxes; i++) {
+        if (pDevice->valuator->axes[i].mode == Absolute)
             dmxLocal->history[OFFSET(dmxLocal->tail,i+1)]
                 = dmxLocal->valuators[i];
-    } else {
-        for (i = 0; i < numAxes; i++) 
+        else
             dmxLocal->history[OFFSET(dmxLocal->tail,i+1)] = 0;
     }
     
diff --git a/include/inputstr.h b/include/inputstr.h
index 1b504e9..d0e9f45 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -217,6 +217,7 @@ typedef struct _AxisInfo {
     int		min_value;
     int		max_value;
     Atom	label;
+    CARD8	mode;
 } AxisInfo, *AxisInfoPtr;
 
 typedef struct _ValuatorAccelerationRec {
-- 
1.7.0.4



More information about the xorg-devel mailing list