diff options
author | Peter Hutterer <peter.hutterer@who-t.net> | 2013-03-09 20:43:51 +1000 |
---|---|---|
committer | Peter Hutterer <peter.hutterer@who-t.net> | 2013-05-23 15:35:05 +1000 |
commit | 5cc2c96f824dbb28b9f8da61efc41596f8bd0561 (patch) | |
tree | 1fadf449dc8a094bed2b411dd694fb988f546af2 /dix | |
parent | 7e97166c4fc38076b6224e4dbdd632b43444149f (diff) |
dix: pre-scale x by the screen:device:resolution ratio
commit 61a99aff9d33728a0b67920254d2d4d79f80cf39
dix: pre-scale relative events from abs devices to desktop ratio (#31636)
added pre-scaling of relative coordinates coming from absolute devices to
undo uneven scaling based on the screen dimensions.
Devices have their own device width/height ratio as well (in a specific
resolution) and this must be applied for relative devices as well to avoid
scaling of the relative events into the device's ratio.
e.g. a Wacom Intuos4 6x9 is in 16:10 format with equal horiz/vert
resolution (dpi). A movement by 1000/1000 coordinates is a perfect diagonal
on the tablet and must be reflected as such on the screen.
However, we map the relative device-coordinate events to absolute screen
coordinates based on the axis ranges. This results in an effective scaling
of 1000/(1000 * 1.6) and thus an uneven x/y axis movement - the y
axis is always faster.
So we need to pre-scale not only by the desktop dimenstions but also by the
device width/height ratio _and_ the resolution ratio.
Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net>
Diffstat (limited to 'dix')
-rw-r--r-- | dix/getevents.c | 46 |
1 files changed, 28 insertions, 18 deletions
diff --git a/dix/getevents.c b/dix/getevents.c index 241c7ec0d..ac0ccb28f 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -770,6 +770,29 @@ add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, doubl } +static void +scale_for_device_resolution(DeviceIntPtr dev, ValuatorMask *mask) +{ + double x; + 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; + + double screen_ratio = 1.0 * screenInfo.width/screenInfo.height; + double device_ratio = 1.0 * xrange/yrange; + double resolution_ratio = 1.0; + double ratio; + + if (!valuator_mask_fetch_double(mask, 0, &x)) + return; + + if (v->axes[0].resolution != 0 && v->axes[1].resolution != 0) + resolution_ratio = 1.0 * v->axes[0].resolution/v->axes[1].resolution; + + ratio = device_ratio/resolution_ratio/screen_ratio; + valuator_mask_set_double(mask, 0, x * ratio); +} + /** * Move the device's pointer by the values given in @valuators. * @@ -781,27 +804,14 @@ moveRelative(DeviceIntPtr dev, int flags, ValuatorMask *mask) { int i; Bool clip_xy = IsMaster(dev) || !IsFloating(dev); + ValuatorClassPtr v = dev->valuator; /* 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); - } - } + if ((flags & POINTER_ABSOLUTE) == 0 && 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(dev, mask); } /* calc other axes, clip, drop back into valuators */ |