From cfced5a235480eba14ae0e169b91b3cfa64e78dc Mon Sep 17 00:00:00 2001 From: Peter Hutterer Date: Wed, 8 Aug 2012 11:34:32 +1000 Subject: [PATCH] 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 Signed-off-by: Peter Hutterer --- dix/getevents.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/dix/getevents.c b/dix/getevents.c index b3bb162..b10be6e 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); @@ -1386,8 +1390,21 @@ fill_pointer_events(InternalEvent *events, DeviceIntPtr pDev, int type, moveRelative(pDev, &mask); } + /* 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); -- 1.7.11.2