Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2017-07-18 17:00:07 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2017-07-18 17:11:33 +0300
commit8b2785bda5bd077548044acb307e17b376649051 (patch)
tree43038691ad6354bb352c8851accc82a80931f252
parent3cfb248bb6308b7b133956179c1422c0e433acae (diff)
Fix T49498: continuous grab issues on macOS, particularly with gaming mouses.
Change the implementation so it no longer takes over the mouse cursor motion from the OS, instead only move it when warping, similar to Windows and X11. Probably the reason it was not done this way originally is that you then get a 500ms delay after warping, but we can use a trick to avoid that and get much smoother mouse motion than before.
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.h5
-rw-r--r--intern/ghost/intern/GHOST_SystemCocoa.mm48
-rw-r--r--intern/ghost/intern/GHOST_WindowCocoa.mm4
3 files changed, 23 insertions, 34 deletions
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.h b/intern/ghost/intern/GHOST_SystemCocoa.h
index b142c2f7194..6802ad42c7b 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.h
+++ b/intern/ghost/intern/GHOST_SystemCocoa.h
@@ -292,11 +292,6 @@ protected:
/** Ignores window size messages (when window is dragged). */
bool m_ignoreWindowSizedMessages;
- /** Stores the mouse cursor delta due to setting a new cursor position
- * Needed because cocoa event delta cursor move takes setCursorPosition changes too.
- */
- GHOST_TInt32 m_cursorDelta_x, m_cursorDelta_y;
-
/** Temporarily ignore momentum scroll events */
bool m_ignoreMomentumScroll;
/** Is the scroll wheel event generated by a multitouch trackpad or mouse? */
diff --git a/intern/ghost/intern/GHOST_SystemCocoa.mm b/intern/ghost/intern/GHOST_SystemCocoa.mm
index 173f59c9c8f..4582dfb2a49 100644
--- a/intern/ghost/intern/GHOST_SystemCocoa.mm
+++ b/intern/ghost/intern/GHOST_SystemCocoa.mm
@@ -366,8 +366,6 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
char *rstring = NULL;
m_modifierMask =0;
- m_cursorDelta_x=0;
- m_cursorDelta_y=0;
m_outsideLoopEventProcessed = false;
m_needDelayedApplicationBecomeActiveEventProcessing = false;
m_displayManager = new GHOST_DisplayManagerCocoa ();
@@ -644,6 +642,13 @@ GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(GHOST_TInt32 x, GHOST_T
CGDisplayMoveCursorToPoint((CGDirectDisplayID)[[[windowScreen deviceDescription] objectForKey:@"NSScreenNumber"] unsignedIntValue], CGPointMake(xf, yf));
+ // See https://stackoverflow.com/a/17559012. By default, hardware events
+ // will be suppressed for 500ms after a synthetic mouse event. For unknown
+ // reasons CGEventSourceSetLocalEventsSuppressionInterval does not work,
+ // however calling CGAssociateMouseAndMouseCursorPosition also removes the
+ // delay, even if this is undocumented.
+ CGAssociateMouseAndMouseCursorPosition(true);
+
[pool drain];
return GHOST_kSuccess;
}
@@ -1354,9 +1359,8 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
case GHOST_kGrabWrap: //Wrap cursor at area/window boundaries
{
NSPoint mousePos = [cocoawindow mouseLocationOutsideOfEventStream];
- GHOST_TInt32 x_mouse= mousePos.x;
- GHOST_TInt32 y_mouse= mousePos.y;
- GHOST_TInt32 x_accum, y_accum, x_cur, y_cur, x, y;
+ GHOST_TInt32 x_mouse = mousePos.x;
+ GHOST_TInt32 y_mouse = mousePos.y;
GHOST_Rect bounds, windowBounds, correctedBounds;
/* fallback to window bounds */
@@ -1370,29 +1374,26 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
correctedBounds.m_b = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_b;
correctedBounds.m_t = (windowBounds.m_b - windowBounds.m_t) - correctedBounds.m_t;
- //Update accumulation counts
+ //Get accumulation from previous mouse warps
+ GHOST_TInt32 x_accum, y_accum;
window->getCursorGrabAccum(x_accum, y_accum);
- x_accum += [event deltaX]-m_cursorDelta_x;
- y_accum += -[event deltaY]-m_cursorDelta_y; //Strange Apple implementation (inverted coordinates for the deltaY) ...
- window->setCursorGrabAccum(x_accum, y_accum);
//Warp mouse cursor if needed
- x_mouse += [event deltaX]-m_cursorDelta_x;
- y_mouse += -[event deltaY]-m_cursorDelta_y;
- correctedBounds.wrapPoint(x_mouse, y_mouse, 2);
-
- //Compensate for mouse moved event taking cursor position set into account
- m_cursorDelta_x = x_mouse-mousePos.x;
- m_cursorDelta_y = y_mouse-mousePos.y;
+ GHOST_TInt32 warped_x_mouse = x_mouse;
+ GHOST_TInt32 warped_y_mouse = y_mouse;
+ correctedBounds.wrapPoint(warped_x_mouse, warped_y_mouse, 4);
//Set new cursor position
- window->clientToScreenIntern(x_mouse, y_mouse, x_cur, y_cur);
- setMouseCursorPosition(x_cur, y_cur); /* wrap */
+ if (x_mouse != warped_x_mouse || y_mouse != warped_y_mouse) {
+ GHOST_TInt32 warped_x, warped_y;
+ window->clientToScreenIntern(warped_x_mouse, warped_y_mouse, warped_x, warped_y);
+ setMouseCursorPosition(warped_x, warped_y); /* wrap */
+ window->setCursorGrabAccum(x_accum + (x_mouse - warped_x_mouse), y_accum + (y_mouse - warped_y_mouse));
+ }
- //Post event
- window->getCursorGrabInitPos(x_cur, y_cur);
- window->screenToClientIntern(x_cur, y_cur, x_cur, y_cur);
- window->clientToScreenIntern(x_cur + x_accum, y_cur + y_accum, x, y);
+ //Generate event
+ GHOST_TInt32 x, y;
+ window->clientToScreenIntern(x_mouse + x_accum, y_mouse + y_accum, x, y);
pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y));
break;
}
@@ -1404,9 +1405,6 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
window->clientToScreenIntern(mousePos.x, mousePos.y, x, y);
pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y));
-
- m_cursorDelta_x=0;
- m_cursorDelta_y=0; //Mouse motion occurred between two cursor warps, so we can reset the delta counter
break;
}
}
diff --git a/intern/ghost/intern/GHOST_WindowCocoa.mm b/intern/ghost/intern/GHOST_WindowCocoa.mm
index 97615dcea96..73c89f9d68d 100644
--- a/intern/ghost/intern/GHOST_WindowCocoa.mm
+++ b/intern/ghost/intern/GHOST_WindowCocoa.mm
@@ -1370,9 +1370,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode
//Make window key if it wasn't to get the mouse move events
[m_window makeKeyWindow];
- //Dissociate cursor position even for warp mode, to allow mouse acceleration to work even when warping the cursor
- err = CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
-
[pool drain];
}
}
@@ -1382,7 +1379,6 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode
setWindowCursorVisibility(true);
}
- err = CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
/* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
setCursorGrabAccum(0, 0);
m_cursorGrabBounds.m_l= m_cursorGrabBounds.m_r= -1; /* disable */