[PATCH] dix: make input clipping respect subpixels (#24187)

Peter Hutterer peter.hutterer at who-t.net
Wed Sep 30 22:07:51 PDT 2009


From: Simon Thum <simon.thum at gmx.de>

Make clipping of valuators respect subpixels. This is
needed for XI2 coords not to become negative.

The clipping rules intend to avoid enlarging the
valuator range by the remainder range, so assumptions
one may have made stay valid.

Clipping is performed in moveRelative() and moveAbsolute()
only - proper SP handling remains something TODO.

X.Org Bug 24187 <http://bugs.freedesktop.org/show_bug.cgi?id=24187>

Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
Simon: this is the latest patch you sent me, I just added the special case
for relative devices.

 dix/getevents.c |   69 +++++++++++++++++++++++++++++++++++++++++-------------
 1 files changed, 52 insertions(+), 17 deletions(-)

diff --git a/dix/getevents.c b/dix/getevents.c
index 5224d31..8f83984 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -576,7 +576,7 @@ GetMaximumEventsNum(void) {
  * InitValuatorAxisClassStruct.
  */
 static void
-clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
+clipAxis(DeviceIntPtr pDev, int axisNum, int *val, float* remainder)
 {
     AxisInfoPtr axis;
 
@@ -587,16 +587,41 @@ clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
 
     /* If a value range is defined, clip. If not, do nothing */
     if (axis->max_value <= axis->min_value)
-        return;
+    {
+        /* Special case: for relative devices with no valid axis range, we
+         * still need to clip off the remainder to avoid negative root
+         * coordinates. We do NOT set val to 0, otherwise we can't cross
+         * screens anymore. */
+        if (*val <= axis->min_value && remainder && (*remainder < 0.0f))
+            *remainder = 0.0f;
+	return;
+    }
 
-    if (*val < axis->min_value)
-        *val = axis->min_value;
-    if (*val > axis->max_value)
-        *val = axis->max_value;
+    if (*val < axis->min_value) {
+	*val = axis->min_value;
+	if (remainder)
+	    *remainder = 0.0f;
+	return;
+    }
+    if (*val == axis->min_value && remainder && (*remainder < 0.0f)) {
+	*remainder = 0.0f;
+	return;
+    }
+
+    if (*val > axis->max_value) {
+	*val = axis->max_value;
+	if (remainder)
+	    *remainder = 0.0f;
+	return;
+    }
+    if (*val == axis->max_value && remainder && (*remainder > 0.0f)) {
+	*remainder = 0.0f;
+    }
 }
 
 /**
  * Clip every axis in the list of valuators to its bounds.
+ * TODO: Does not handle sub-pixel remainder
  */
 static void
 clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
@@ -605,7 +630,7 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
     int i;
 
     for (i = 0; i < num_valuators; i++)
-        clipAxis(pDev, i + first_valuator, &(valuators[i]));
+        clipAxis(pDev, i + first_valuator, &(valuators[i]), NULL);
 }
 
 /**
@@ -667,14 +692,15 @@ moveAbsolute(DeviceIntPtr dev, int *x, int *y,
     else
         *y = dev->last.valuators[1];
 
-    clipAxis(dev, 0, x);
-    clipAxis(dev, 1, y);
+    clipAxis(dev, 0, x, &dev->last.remainder[0]);
+    clipAxis(dev, 1, y, &dev->last.remainder[1]);
 
     i = (first > 2) ? 0 : 2;
     for (; i < num; i++)
     {
         dev->last.valuators[i + first] = valuators[i];
-        clipAxis(dev, i, &dev->last.valuators[i + first]);
+        clipAxis(dev, i, &dev->last.valuators[i + first],
+                 &dev->last.remainder[i + first]);
     }
 }
 
@@ -708,8 +734,8 @@ moveRelative(DeviceIntPtr dev, int *x, int *y,
      * co-ord space limit). If it is attached, we need x/y to go over the
      * limits to be able to change screens. */
     if(dev->u.master) {
-        clipAxis(dev, 0, x);
-        clipAxis(dev, 1, y);
+        clipAxis(dev, 0, x, &dev->last.remainder[0]);
+        clipAxis(dev, 1, y, &dev->last.remainder[1]);
     }
 
     /* calc other axes, clip, drop back into valuators */
@@ -717,7 +743,8 @@ moveRelative(DeviceIntPtr dev, int *x, int *y,
     for (; i < num; i++)
     {
         dev->last.valuators[i + first] += valuators[i];
-        clipAxis(dev, i, &dev->last.valuators[i + first]);
+        clipAxis(dev, i, &dev->last.valuators[i + first],
+                 &dev->last.remainder[i + first]);
         valuators[i] = dev->last.valuators[i + first];
     }
 }
@@ -1052,15 +1079,23 @@ GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
         }
 
         moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators);
+        /* moveAbsolute() modifies the fractional part in-place, so we need
+         * to extract this information. But don't if they're already set.
+         * This assumes rescaleValuatorAxis won't violate ranges. */
+        if (!(flags & POINTER_SCREEN)) {
+	    x_frac = pDev->last.remainder[0];
+	    y_frac = pDev->last.remainder[1];
+        }
     } else {
         if (flags & POINTER_ACCELERATE) {
             accelPointer(pDev, first_valuator, num_valuators, valuators, 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);
+        /* The pointer acceleration code modifies the fractional part
+         * in-place, so we need to extract this information.
+         * Also, include moveRelative's clipping in the fractional part. */
+        x_frac = pDev->last.remainder[0];
+        y_frac = pDev->last.remainder[1];
     }
 
     set_raw_valuators(raw, first_valuator, num_valuators, valuators,
-- 
1.6.3.rc1.2.g0164.dirty


More information about the xorg-devel mailing list