[PATCH v2] dix: support the transformation matrix for relative devices.

Peter Hutterer peter.hutterer at who-t.net
Thu Feb 7 20:52:02 PST 2013


The transformation matrix we previously stored was a scaled matrix based on
the axis ranges of the device. For relative movements, the scaling is not
required (or desired).

Store two separate matrices, one as requested by the client, one as the
product of [scale . matrix . inv_scale]. Depending on the type of movement,
apply the respective matrix.

For relative movements, also drop the translation component since it doesn't
really make sense to use that bit.

Input ABI 19

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Changes to v1:
- ABI updated to 19
- save the relative_matrix (without translation component) so we can apply
  it directly 
- make sure both are initialised to the unity matrix (would've zombied
  RH#852841)
- make sure we use the scale matrix to undo transformation (would've
  zombied 49347)

 dix/devices.c                  | 21 ++++++++++++++-------
 dix/getevents.c                | 27 +++++++++++++++++++++++++--
 hw/xfree86/common/xf86Module.h |  2 +-
 include/inputstr.h             |  8 ++++++--
 4 files changed, 46 insertions(+), 12 deletions(-)

diff --git a/dix/devices.c b/dix/devices.c
index 3c7d480..2f77dbb 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -93,9 +93,10 @@ SOFTWARE.
 static void RecalculateMasterButtons(DeviceIntPtr slave);
 
 static void
-DeviceSetTransform(DeviceIntPtr dev, float *transform)
+DeviceSetTransform(DeviceIntPtr dev, float *transform_data)
 {
     struct pixman_f_transform scale;
+    struct pixman_f_transform transform;
     double sx, sy;
     int x, y;
 
@@ -122,16 +123,21 @@ DeviceSetTransform(DeviceIntPtr dev, float *transform)
     /* transform */
     for (y = 0; y < 3; y++)
         for (x = 0; x < 3; x++)
-            dev->transform.m[y][x] = *transform++;
+            transform.m[y][x] = *transform_data++;
 
-    pixman_f_transform_multiply(&dev->transform, &scale, &dev->transform);
+    pixman_f_transform_multiply(&dev->scale_and_transform, &scale, &transform);
 
     /* scale */
     pixman_f_transform_init_scale(&scale, 1.0 / sx, 1.0 / sy);
     scale.m[0][2] = -dev->valuator->axes[0].min_value / sx;
     scale.m[1][2] = -dev->valuator->axes[1].min_value / sy;
 
-    pixman_f_transform_multiply(&dev->transform, &dev->transform, &scale);
+    pixman_f_transform_multiply(&dev->scale_and_transform, &dev->scale_and_transform, &scale);
+
+    /* remove translation component for relative movements */
+    dev->relative_transform = transform;
+    dev->relative_transform.m[0][2] = 0;
+    dev->relative_transform.m[1][2] = 0;
 }
 
 /**
@@ -308,9 +314,10 @@ AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart)
     /* unity matrix */
     memset(transform, 0, sizeof(transform));
     transform[0] = transform[4] = transform[8] = 1.0f;
-    dev->transform.m[0][0] = 1.0;
-    dev->transform.m[1][1] = 1.0;
-    dev->transform.m[2][2] = 1.0;
+    dev->relative_transform.m[0][0] = 1.0;
+    dev->relative_transform.m[1][1] = 1.0;
+    dev->relative_transform.m[2][2] = 1.0;
+    dev->scale_and_transform = dev->relative_transform;
 
     XIChangeDeviceProperty(dev, XIGetKnownProperty(XI_PROP_TRANSFORM),
                            XIGetKnownProperty(XATOM_FLOAT), 32,
diff --git a/dix/getevents.c b/dix/getevents.c
index 3d41e1e..2ea5f68 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -1174,6 +1174,27 @@ transform(struct pixman_f_transform *m, double *x, double *y)
     *y = p.v[1];
 }
 
+static void
+transformRelative(DeviceIntPtr dev, ValuatorMask *mask)
+{
+    double x = 0, y = 0;
+
+    valuator_mask_fetch_double(mask, 0, &x);
+    valuator_mask_fetch_double(mask, 1, &y);
+
+    transform(&dev->relative_transform, &x, &y);
+
+    if (x)
+        valuator_mask_set_double(mask, 0, x);
+    else
+        valuator_mask_unset(mask, 0);
+
+    if (y)
+        valuator_mask_set_double(mask, 1, y);
+    else
+        valuator_mask_unset(mask, 1);
+}
+
 /**
  * Apply the device's transformation matrix to the valuator mask and replace
  * the scaled values in mask. This transformation only applies to valuators
@@ -1201,7 +1222,7 @@ transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
         ox = dev->last.valuators[0];
         oy = dev->last.valuators[1];
 
-        pixman_f_transform_invert(&invert, &dev->transform);
+        pixman_f_transform_invert(&invert, &dev->scale_and_transform);
         transform(&invert, &ox, &oy);
 
         x = ox;
@@ -1214,7 +1235,7 @@ transformAbsolute(DeviceIntPtr dev, ValuatorMask *mask)
     if (valuator_mask_isset(mask, 1))
         oy = y = valuator_mask_get_double(mask, 1);
 
-    transform(&dev->transform, &x, &y);
+    transform(&dev->scale_and_transform, &x, &y);
 
     if (valuator_mask_isset(mask, 0) || ox != x)
         valuator_mask_set_double(mask, 0, x);
@@ -1375,6 +1396,8 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
             set_raw_valuators(raw, &mask, raw->valuators.data);
     }
     else {
+        transformRelative(pDev, &mask);
+
         if (flags & POINTER_ACCELERATE)
             accelPointer(pDev, &mask, ms);
         if ((flags & POINTER_NORAW) == 0)
diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
index 1be7ba5..e545c14 100644
--- a/hw/xfree86/common/xf86Module.h
+++ b/hw/xfree86/common/xf86Module.h
@@ -81,7 +81,7 @@ typedef enum {
  */
 #define ABI_ANSIC_VERSION	SET_ABI_VERSION(0, 4)
 #define ABI_VIDEODRV_VERSION	SET_ABI_VERSION(14, 1)
-#define ABI_XINPUT_VERSION	SET_ABI_VERSION(18, 0)
+#define ABI_XINPUT_VERSION	SET_ABI_VERSION(19, 0)
 #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(7, 0)
 #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 6)
 
diff --git a/include/inputstr.h b/include/inputstr.h
index 17cee98..5eb194e 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -586,8 +586,12 @@ typedef struct _DeviceIntRec {
         XIPropertyHandlerPtr handlers;  /* NULL-terminated */
     } properties;
 
-    /* coordinate transformation matrix for absolute input devices */
-    struct pixman_f_transform transform;
+    /* coordinate transformation matrix for relative movement. Matrix with
+     * the translation component dropped */
+    struct pixman_f_transform relative_transform;
+    /* scale matrix for absolute devices, this is the combined matrix of
+       [1/scale] . [transform] . [scale]. See DeviceSetTransform */
+    struct pixman_f_transform scale_and_transform;
 
     /* XTest related master device id */
     int xtest_master_id;
-- 
1.8.1



More information about the xorg-devel mailing list