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.
This commit is contained in:
parent
1c4d8938ec
commit
3e3d982185
|
@ -57,6 +57,7 @@ @interface WineApplicationController : NSObject <NSApplicationDelegate>
|
|||
|
||||
CGFloat primaryScreenHeight;
|
||||
BOOL primaryScreenHeightValid;
|
||||
NSMutableData* screenFrameCGRects;
|
||||
|
||||
WineWindow* lastTargetWindow;
|
||||
BOOL forceNextMouseMoveAbsolute;
|
||||
|
|
|
@ -170,6 +170,7 @@ - (id) init
|
|||
|
||||
- (void) dealloc
|
||||
{
|
||||
[screenFrameCGRects release];
|
||||
[applicationIcon release];
|
||||
[warpRecords release];
|
||||
[cursorTimer release];
|
||||
|
@ -377,10 +378,29 @@ - (CGFloat) primaryScreenHeight
|
|||
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 @@ - (void) handleMouseMove:(NSEvent*)anEvent
|
|||
|
||||
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 @@ - (void) handleMouseMove:(NSEvent*)anEvent
|
|||
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];
|
||||
|
||||
|
|
Loading…
Reference in New Issue