Commit: 8b2785bda5bd077548044acb307e17b376649051
Author: Brecht Van Lommel
Date:   Tue Jul 18 16:00:07 2017 +0200
Branches: master
https://developer.blender.org/rB8b2785bda5bd077548044acb307e17b376649051

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.

===================================================================

M       intern/ghost/intern/GHOST_SystemCocoa.h
M       intern/ghost/intern/GHOST_SystemCocoa.mm
M       intern/ghost/intern/GHOST_WindowCocoa.mm

===================================================================

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 
*/

_______________________________________________
Bf-blender-cvs mailing list
[email protected]
https://lists.blender.org/mailman/listinfo/bf-blender-cvs

Reply via email to