[xorg-x11-server/f20] Fix coordinate scaling so we're independent of the screen res (#1104789)

Peter Hutterer whot at fedoraproject.org
Mon Jun 23 01:59:05 UTC 2014


commit 2911c9e382d03d3743171ffbacddef17bc8e01a5
Author: Peter Hutterer <peter.hutterer at who-t.net>
Date:   Mon Jun 23 11:11:38 2014 +1000

    Fix coordinate scaling so we're independent of the screen res (#1104789)

 ...coordinate-scaling-when-external-monitors.patch |  173 ++++++++++++++++++++
 ...le-x-by-the-screen-device-resolution-rati.patch |  103 ------------
 ...-back-instead-of-x-up-when-pre-scaling-co.patch |   74 ---------
 xorg-x11-server.spec                               |   11 +-
 4 files changed, 179 insertions(+), 182 deletions(-)
---
diff --git a/0001-dix-fix-up-coordinate-scaling-when-external-monitors.patch b/0001-dix-fix-up-coordinate-scaling-when-external-monitors.patch
new file mode 100644
index 0000000..0d9f401
--- /dev/null
+++ b/0001-dix-fix-up-coordinate-scaling-when-external-monitors.patch
@@ -0,0 +1,173 @@
+From e3006a9654c8ef3f59ff40d5f3e5fde232ec2d08 Mon Sep 17 00:00:00 2001
+From: Peter Hutterer <peter.hutterer at who-t.net>
+Date: Fri, 30 May 2014 09:56:37 +1000
+Subject: [PATCH] dix: fix up coordinate scaling when external monitors are
+ present
+
+The goal of all this is to get an x/y motion reflecting the motion
+on the device, i.e. a circle on the device is a circle on the screen.
+
+This is currently done by scaling the y coordinate depending on the screen
+ratio vs device ratio. Depending on that ratio the movement on the y axis may
+be accelerated (ratio < 1) or slowed (ratio > 1). This leads to the weird
+effect that changing the screen ratio by plugging a new monitor changes the
+speed of the touchpad.
+
+Use a different algorithm: calculate the physical movement on the device, map
+that to the same-ish distance on the screen, then convert that back into a
+device-specific vector. This way we get the same mapping regardless of the
+current screen dimensions.
+
+Since the pointer accel code doesn't take device resolution into account, make
+sure we apply our crazy mapping before we accelerate. This way we accelerate
+resolution-independent.
+
+Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
+Reviewed-by: Hans de Goede <hdegoede at redhat.com>
+
+[Fedora: dropped the previous patches, but add the input ABI bump anyway]
+
+Conflicts:
+	dix/getevents.c
+---
+ dix/getevents.c | 93 +++++++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 71 insertions(+), 22 deletions(-)
+
+diff --git a/dix/getevents.c b/dix/getevents.c
+index dd1b253..fcc7133 100644
+--- a/dix/getevents.c
++++ b/dix/getevents.c
+@@ -769,6 +769,66 @@ add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, doubl
+     valuator_mask_set_double(mask, valuator, v);
+ }
+ 
++/* FIXME: relative events from devices with absolute axis ranges is
++   fundamentally broken. We map the device coordinate range into the screen
++   range, but don't really account for device resolution in that.
++
++   what we do here is a hack to make touchpads usable. for a given relative
++   motion vector in device coordinates:
++   1. calculate physical movement on the device in metres
++   2. calculate pixel vector that is the same physical movement on the
++      screen (times some magic number to provide sensible base speed)
++   3. calculate what percentage this vector is of the current screen
++      width/height
++   4. calculate equivalent vector in % on the device's min/max axis range
++   5. Use that device vector as the actual motion vector
++
++   e.g. 10/50mm on the device, 10/50mm on the screen are 30/100 pixels,
++   30/100 pixels are 1/3% of the width, 1/3% of the device is a vector of
++   20/80 -> use 20/80 as dx/dy.
++
++   dx/dy is then applied to the current position in device coordinates,
++   mapped to screen coordinates and thus the movement on the screen reflects
++   the motion direction on the device.
++ */
++static void
++scale_for_device_resolution(DeviceIntPtr dev, ValuatorMask *mask)
++{
++    double x, y;
++    ValuatorClassPtr v = dev->valuator;
++    int xrange = v->axes[0].max_value - v->axes[0].min_value + 1;
++    int yrange = v->axes[1].max_value - v->axes[1].min_value + 1;
++
++    /* Assume 100 units/m for devices without resolution */
++    int xres = 100000, yres = 100000;
++
++    /* If we have multiple screens with different dpi, it gets complicated:
++       we have to map which screen we're on and then take the dpi of that
++       screen to be somewhat accurate.  */
++    const ScreenPtr s = screenInfo.screens[0];
++    const double screen_res = 1000.0 * s->width/s->mmWidth; /* units/m */
++
++    /* some magic multiplier, so unaccelerated movement of x mm on the
++       device reflects x * magic mm on the screen */
++    const double magic = 4;
++
++    if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0) {
++        xres = v->axes[0].resolution;
++        yres = v->axes[1].resolution;
++    }
++
++    if (valuator_mask_isset(mask, 0)) {
++        x = valuator_mask_get_double(mask, 0);
++        x = magic * x/xres * screen_res/screenInfo.width * xrange;
++        valuator_mask_set_double(mask, 0, x);
++    }
++
++    if (valuator_mask_isset(mask, 1)) {
++        y = valuator_mask_get_double(mask, 1);
++        y = magic * y/yres * screen_res/screenInfo.height * yrange;
++        valuator_mask_set_double(mask, 1, y);
++    }
++}
+ 
+ /**
+  * Move the device's pointer by the values given in @valuators.
+@@ -782,28 +842,6 @@ moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask)
+     int i;
+     Bool clip_xy = IsMaster(dev) || !IsFloating(dev);
+ 
+-    /* for abs devices in relative mode, we've just scaled wrong, since we
+-       mapped the device's shape into the screen shape. Undo this. */
+-    if ((flags & POINTER_ABSOLUTE) == 0 && dev->valuator &&
+-        dev->valuator->axes[0].min_value < dev->valuator->axes[0].max_value) {
+-
+-        double ratio = 1.0 * screenInfo.width/screenInfo.height;
+-
+-        if (ratio > 1.0) {
+-            double y;
+-            if (valuator_mask_fetch_double(mask, 1, &y)) {
+-                y *= ratio;
+-                valuator_mask_set_double(mask, 1, y);
+-            }
+-        } else {
+-            double x;
+-            if (valuator_mask_fetch_double(mask, 0, &x)) {
+-                x *= ratio;
+-                valuator_mask_set_double(mask, 0, x);
+-            }
+-        }
+-    }
+-
+     /* calc other axes, clip, drop back into valuators */
+     for (i = 0; i < valuator_mask_size(mask); i++) {
+         double val = dev->last.valuators[i];
+@@ -1431,10 +1469,21 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
+             set_raw_valuators(raw, &mask, raw->valuators.data);
+     }
+     else {
++        ValuatorClassPtr v = pDev->valuator;
++
+         transformRelative(pDev, &mask);
+ 
++        /* for abs devices in relative mode, we've just scaled wrong, since we
++           mapped the device's shape into the screen shape. Undo this. */
++        if (v && v->numAxes > 1 &&
++            v->axes[0].min_value < v->axes[0].max_value &&
++            v->axes[1].min_value < v->axes[1].max_value) {
++            scale_for_device_resolution(pDev, &mask);
++        }
++
+         if (flags & POINTER_ACCELERATE)
+             accelPointer(pDev, &mask, ms);
++
+         if ((flags & POINTER_NORAW) == 0)
+             set_raw_valuators(raw, &mask, raw->valuators.data);
+ 
+-- 
+1.9.3
+
+diff --git a/hw/xfree86/common/xf86Module.h b/hw/xfree86/common/xf86Module.h
+index 1393427..e0cec05 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(19, 1)
++#define ABI_XINPUT_VERSION	SET_ABI_VERSION(19, 2)
+ #define ABI_EXTENSION_VERSION	SET_ABI_VERSION(7, 0)
+ #define ABI_FONT_VERSION	SET_ABI_VERSION(0, 6)
+ 
diff --git a/xorg-x11-server.spec b/xorg-x11-server.spec
index 3c6b23e..bb88810 100644
--- a/xorg-x11-server.spec
+++ b/xorg-x11-server.spec
@@ -42,7 +42,7 @@
 Summary:   X.Org X11 X server
 Name:      xorg-x11-server
 Version:   1.14.4
-Release:   9%{?gitdate:.%{gitdate}}%{dist}
+Release:   10%{?gitdate:.%{gitdate}}%{dist}
 URL:       http://www.x.org
 License:   MIT
 Group:     User Interface/X
@@ -109,10 +109,6 @@ Patch7052: 0001-xf86-return-NULL-for-compat-output-if-no-outputs.patch
 # mustard: make the default queue length bigger to calm abrt down
 Patch7064: 0001-mieq-Bump-default-queue-size-to-512.patch
 
-# scale events from abs devices in relative mode to something useful
-Patch8003: 0004-dix-pre-scale-x-by-the-screen-device-resolution-rati.patch
-Patch8004: 0005-dix-scale-y-back-instead-of-x-up-when-pre-scaling-co.patch
-
 # Bug 962572 - X-sandboxes are not resizeable
 Patch8038: 0001-ephyr-Add-resizeable-option.patch
 
@@ -174,6 +170,8 @@ Patch9050: 0001-xfree86-Prefer-fbdev-to-vesa.patch
 Patch9051: 0001-dix-fix-button-state-check-before-changing-a-button-.patch
 
 Patch9052: 0001-config-search-for-PnPID-on-all-parents-75513.patch
+# Bug 1104789 - Touchpad sensitivity changes dramatically when I plug in an external monitor
+Patch9053: 0001-dix-fix-up-coordinate-scaling-when-external-monitors.patch
 
 %global moduledir	%{_libdir}/xorg/modules
 %global drimoduledir	%{_libdir}/dri
@@ -653,6 +651,9 @@ rm -rf $RPM_BUILD_ROOT
 %{xserver_source_dir}
 
 %changelog
+* Mon Jun 23 2014 Peter Hutterer <peter.hutterer at redhat.com> 1.14.4-10
+- Fix coordinate scaling so we're independent of the screen res (#1104789)
+
 * Wed May 14 2014 Peter Hutterer <peter.hutterer at redhat.com> 1.14.4-9
 - Revert button mapping for Evoluent Vertical mouse, the default mapping
   matches the manufacturer's documentation (#612140)


More information about the scm-commits mailing list