Ken Thomases : winemac: Prefer absolute mouse moves unless cursor is pinned by clipping or desktop edges .
Alexandre Julliard
julliard at winehq.org
Tue May 7 15:54:05 CDT 2013
Module: wine
Branch: master
Commit: 3e3d982185c62020b7478f433486ade19378ed6e
URL: http://source.winehq.org/git/wine.git/?a=commit;h=3e3d982185c62020b7478f433486ade19378ed6e
Author: Ken Thomases <ken at codeweavers.com>
Date: Tue May 7 03:00:49 2013 -0500
winemac: Prefer absolute mouse moves unless cursor is pinned by clipping or desktop edges.
This fixes an issue with sub-pixel-precise pointing devices on Lion and later.
Wine's notion of the cursor position would get out of sync with the actual position
because deltas don't convey the actual movement distance.
---
dlls/winemac.drv/cocoa_app.h | 1 +
dlls/winemac.drv/cocoa_app.m | 80 +++++++++++++++++++++++++++++++++++++++---
2 files changed, 76 insertions(+), 5 deletions(-)
diff --git a/dlls/winemac.drv/cocoa_app.h b/dlls/winemac.drv/cocoa_app.h
index 5e4d181..3ce8a83 100644
--- a/dlls/winemac.drv/cocoa_app.h
+++ b/dlls/winemac.drv/cocoa_app.h
@@ -57,6 +57,7 @@ enum {
CGFloat primaryScreenHeight;
BOOL primaryScreenHeightValid;
+ NSMutableData* screenFrameCGRects;
WineWindow* lastTargetWindow;
BOOL forceNextMouseMoveAbsolute;
diff --git a/dlls/winemac.drv/cocoa_app.m b/dlls/winemac.drv/cocoa_app.m
index e8cca28..b4e15d0 100644
--- a/dlls/winemac.drv/cocoa_app.m
+++ b/dlls/winemac.drv/cocoa_app.m
@@ -170,6 +170,7 @@ int macdrv_err_on;
- (void) dealloc
{
+ [screenFrameCGRects release];
[applicationIcon release];
[warpRecords release];
[cursorTimer release];
@@ -377,10 +378,29 @@ int macdrv_err_on;
if (!primaryScreenHeightValid)
{
NSArray* screens = [NSScreen screens];
- if ([screens count])
+ NSUInteger count = [screens count];
+ if (count)
{
+ NSUInteger size;
+ CGRect* rect;
+ NSScreen* screen;
+
primaryScreenHeight = NSHeight([[screens objectAtIndex:0] frame]);
primaryScreenHeightValid = TRUE;
+
+ size = count * sizeof(CGRect);
+ if (!screenFrameCGRects)
+ screenFrameCGRects = [[NSMutableData alloc] initWithLength:size];
+ else
+ [screenFrameCGRects setLength:size];
+
+ rect = [screenFrameCGRects mutableBytes];
+ for (screen in screens)
+ {
+ CGRect temp = NSRectToCGRect([screen frame]);
+ temp.origin.y = primaryScreenHeight - CGRectGetMaxY(temp);
+ *rect++ = temp;
+ }
}
else
return 1280; /* arbitrary value */
@@ -1157,9 +1177,9 @@ int macdrv_err_on;
if ([targetWindow isKindOfClass:[WineWindow class]])
{
+ CGPoint point = CGEventGetLocation([anEvent CGEvent]);
macdrv_event* event;
- BOOL absolute = forceNextMouseMoveAbsolute || (targetWindow != lastTargetWindow);
- forceNextMouseMoveAbsolute = FALSE;
+ BOOL absolute;
// If we recently warped the cursor (other than in our cursor-clipping
// event tap), discard mouse move events until we see an event which is
@@ -1170,13 +1190,63 @@ int macdrv_err_on;
return;
lastSetCursorPositionTime = 0;
+ forceNextMouseMoveAbsolute = TRUE;
+ }
+
+ if (forceNextMouseMoveAbsolute || targetWindow != lastTargetWindow)
+ {
absolute = TRUE;
+ forceNextMouseMoveAbsolute = FALSE;
+ }
+ else
+ {
+ // Send absolute move events if the cursor is in the interior of
+ // its range. Only send relative moves if the cursor is pinned to
+ // the boundaries of where it can go. We compute the position
+ // that's one additional point in the direction of movement. If
+ // that is outside of the clipping rect or desktop region (the
+ // union of the screen frames), then we figure the cursor would
+ // have moved outside if it could but it was pinned.
+ CGPoint computedPoint = point;
+ CGFloat deltaX = [anEvent deltaX];
+ CGFloat deltaY = [anEvent deltaY];
+
+ if (deltaX > 0.001)
+ computedPoint.x++;
+ else if (deltaX < -0.001)
+ computedPoint.x--;
+
+ if (deltaY > 0.001)
+ computedPoint.y++;
+ else if (deltaY < -0.001)
+ computedPoint.y--;
+
+ // Assume cursor is pinned for now
+ absolute = FALSE;
+ if (!clippingCursor || CGRectContainsPoint(cursorClipRect, computedPoint))
+ {
+ const CGRect* rects;
+ NSUInteger count, i;
+
+ // Caches screenFrameCGRects if necessary
+ [self primaryScreenHeight];
+
+ rects = [screenFrameCGRects bytes];
+ count = [screenFrameCGRects length] / sizeof(rects[0]);
+
+ for (i = 0; i < count; i++)
+ {
+ if (CGRectContainsPoint(rects[i], computedPoint))
+ {
+ absolute = TRUE;
+ break;
+ }
+ }
+ }
}
if (absolute)
{
- CGPoint point = CGEventGetLocation([anEvent CGEvent]);
-
if (clippingCursor)
[self clipCursorLocation:&point];
More information about the wine-cvs
mailing list