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

Peter Hutterer peter.hutterer at who-t.net
Tue Jan 15 21:47:07 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.

This changes the DeviceIntRec ABI

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Biggest issue here: we drop the translation for relative events because it
just doesn't make sense. Realistically, the matrix on relative devices is
likely only used for rotation, but if a device has a matrix set with a
scaling component (because it is mapped to a screen) that component will
apply to relative events as well.
the two options here:
1) make the relative matrix completely independent of the normal matrix
2) rely on clients to update the matrix if they switch the device from one
  mode into anther.

I'm tempted to say 2) but I do wonder if there are corner cases where this
will break.

Note: I sent this patch out in june 2011, but we didn't have a few of the things
in place that we have now (specifically - valuator masks with doubles).
http://lists.x.org/archives/xorg-devel/2011-June/022952.html

This patch is largely the same, with a few minor changes only.

 dix/devices.c      |  4 ++--
 dix/getevents.c    | 30 +++++++++++++++++++++++++++++-
 include/inputstr.h |  5 ++++-
 3 files changed, 35 insertions(+), 4 deletions(-)

diff --git a/dix/devices.c b/dix/devices.c
index 3c7d480..e51ebaf 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -124,14 +124,14 @@ DeviceSetTransform(DeviceIntPtr dev, float *transform)
         for (x = 0; x < 3; x++)
             dev->transform.m[y][x] = *transform++;
 
-    pixman_f_transform_multiply(&dev->transform, &scale, &dev->transform);
+    pixman_f_transform_multiply(&dev->scale_and_transform, &scale, &dev->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);
 }
 
 /**
diff --git a/dix/getevents.c b/dix/getevents.c
index 3d41e1e..75504e3 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -1174,6 +1174,32 @@ 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;
+    struct pixman_f_transform rotation_only = dev->transform;
+
+    /* drop the translation component for rel movements */
+    rotation_only.m[0][2] = 0;
+    rotation_only.m[1][2] = 0;
+
+    valuator_mask_fetch_double(mask, 0, &x);
+    valuator_mask_fetch_double(mask, 1, &y);
+
+    transform(&rotation_only, &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
@@ -1214,7 +1240,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 +1401,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/include/inputstr.h b/include/inputstr.h
index 17cee98..4f42507 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -586,8 +586,11 @@ typedef struct _DeviceIntRec {
         XIPropertyHandlerPtr handlers;  /* NULL-terminated */
     } properties;
 
-    /* coordinate transformation matrix for absolute input devices */
+    /* coordinate transformation matrix */
     struct pixman_f_transform 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