summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter.hutterer@who-t.net>2012-08-08 11:34:32 +1000
committerPeter Hutterer <peter.hutterer@who-t.net>2012-08-21 07:54:07 +1000
commitbafbd99080be49a17be97d2cc758fbe623369945 (patch)
treeafbd1a80abd99272b85d1e9855ae1ae4d558ac22
parent1ebba43052d68d874148e63c9ae38489ddfc5ec1 (diff)
dix: work around scaling issues during WarpPointer (#53037)
In WarpPointer calls, we get input in screen coordinates. They must be scaled to device coordinates, and then back to screen coordinates for screen crossing and root coordinates in events. The rounding errors introduced (and clipping in core/XI 1.x events) can lead to the actual position being different to the requested input coordinates. e.g. 200 scales to 199.9999, truncated to 199 in the event. Avoid this by simply overwriting the scaled screen coordinates with the input coordinates for the POINTER_SCREEN case. X.Org Bug 53037 <http://bugs.freedesktop.org/show_bug.cgi?id=53037> Signed-off-by: Peter Hutterer <peter.hutterer@who-t.net> Reviewed-by: Keith Packard <keithp@keithp.com>
-rw-r--r--dix/getevents.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/dix/getevents.c b/dix/getevents.c
index b3bb162ae..4e62507aa 100644
--- a/dix/getevents.c
+++ b/dix/getevents.c
@@ -1327,6 +1327,7 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
RawDeviceEvent *raw;
double screenx = 0.0, screeny = 0.0; /* desktop coordinate system */
double devx = 0.0, devy = 0.0; /* desktop-wide in device coords */
+ int sx, sy; /* for POINTER_SCREEN */
ValuatorMask mask;
ScreenPtr scr;
@@ -1369,8 +1370,11 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
/* valuators are in driver-native format (rel or abs) */
if (flags & POINTER_ABSOLUTE) {
- if (flags & POINTER_SCREEN) /* valuators are in screen coords */
+ if (flags & POINTER_SCREEN) { /* valuators are in screen coords */
+ sx = valuator_mask_get(&mask, 0);
+ sy = valuator_mask_get(&mask, 1);
scale_from_screen(pDev, &mask);
+ }
transformAbsolute(pDev, &mask);
clipAbsolute(pDev, &mask);
@@ -1388,6 +1392,18 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type,
/* valuators are in device coordinate system in absolute coordinates */
scale_to_desktop(pDev, &mask, &devx, &devy, &screenx, &screeny);
+
+ /* #53037 XWarpPointer's scaling back and forth between screen and
+ device may leave us with rounding errors. End result is that the
+ pointer doesn't end up on the pixel it should.
+ Avoid this by forcing screenx/screeny back to what the input
+ coordinates were.
+ */
+ if (flags & POINTER_SCREEN) {
+ screenx = sx;
+ screeny = sy;
+ }
+
scr = positionSprite(pDev, (flags & POINTER_ABSOLUTE) ? Absolute : Relative,
&mask, &devx, &devy, &screenx, &screeny);