dix: pre-scale relative events from abs devices to desktop ratio (#31636)
Absolute devices may send relative events depending on the mode (synaptics by default, wacom per option). The relative events are added to the previous position, converted into device coordinates and then scaled into desktop coordinates for pointer movement. Because the device range must be mapped into the desktop coordinate range, this results in uneven scaling depending dimensions, e.g. on a setup with width == 2 * height, a relative movement of 10/10 in device coordinates results in a cursor movement of 20/10 (+ acceleration) Other commonly user-visible results: * the touchpad changing acceleration once an external monitor as added. * drawing a circle on a wacom tablet in relative mode gives an ellipsis in the same ratio as the desktop dimensions. Solution: pre-scale the incoming relative x/y coordinates by width/height ratio of the total desktop size. Then add them to the previous coordinates and scale back with the previous mapping, which will undo the pre-scaling and give us the right movement. X.Org Bug 31636 <http://bugs.freedesktop.org/show_bug.cgi?id=31636> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
parent
a6ba2b79ae
commit
61a99aff9d
|
@ -776,11 +776,33 @@ add_to_scroll_valuator(DeviceIntPtr dev, ValuatorMask *mask, int valuator, doubl
|
|||
* @param[in,out] mask Valuator data for this event, modified in-place.
|
||||
*/
|
||||
static void
|
||||
moveRelative(DeviceIntPtr dev, ValuatorMask *mask)
|
||||
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];
|
||||
|
@ -1380,7 +1402,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
|
|||
if ((flags & POINTER_NORAW) == 0)
|
||||
set_raw_valuators(raw, &mask, raw->valuators.data);
|
||||
|
||||
moveRelative(pDev, &mask);
|
||||
moveRelative(pDev, flags, &mask);
|
||||
}
|
||||
|
||||
/* valuators are in device coordinate system in absolute coordinates */
|
||||
|
|
Loading…
Reference in New Issue
Block a user