Cocoa :
authorDamien Plisson <damien.plisson@yahoo.fr>
Fri, 9 Oct 2009 14:42:36 +0000 (14:42 +0000)
committerDamien Plisson <damien.plisson@yahoo.fr>
Fri, 9 Oct 2009 14:42:36 +0000 (14:42 +0000)
Implement OS X support for Campbell's new continuous grab feature

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

index 481dd7052656a7c43cf0db5e13fa6676bce20159..2dfdcf7bcec69236deabfa48cd55b17651fd7b40 100644 (file)
@@ -798,7 +798,7 @@ GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt3
 {
     NSPoint mouseLoc = [NSEvent mouseLocation];
        
-    // Convert the coordinates to screen coordinates
+    // Returns the mouse location in screen coordinates
     x = (GHOST_TInt32)mouseLoc.x;
     y = (GHOST_TInt32)mouseLoc.y;
     return GHOST_kSuccess;
@@ -808,7 +808,10 @@ GHOST_TSuccess GHOST_SystemCocoa::getCursorPosition(GHOST_TInt32& x, GHOST_TInt3
 GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(GHOST_TInt32 x, GHOST_TInt32 y) const
 {
        float xf=(float)x, yf=(float)y;
-
+       
+       //Quartz Display Services uses the old coordinates (top left origin)
+       yf = [[NSScreen mainScreen] frame].size.height -yf;
+       
        CGAssociateMouseAndMouseCursorPosition(false);
        CGWarpMouseCursorPosition(CGPointMake(xf, yf));
        CGAssociateMouseAndMouseCursorPosition(true);
@@ -1080,7 +1083,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleTabletEvent(void *eventPtr, short eventT
 GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
 {
        NSEvent *event = (NSEvent *)eventPtr;
-    GHOST_IWindow* window = m_windowManager->getActiveWindow();
+    GHOST_Window* window = (GHOST_Window*)m_windowManager->getActiveWindow();
        
        if (!window) {
                return GHOST_kFailure;
@@ -1141,8 +1144,22 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
                        }
                case NSMouseMoved:
                        {
-                               NSPoint mousePos = [event locationInWindow];
-                               pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
+                               if(window->getCursorWarp()) {
+                                       GHOST_TInt32 x_warp, y_warp, x_accum, y_accum;
+                                       
+                                       window->getCursorWarpPos(x_warp, y_warp);
+                                       
+                                       window->getCursorWarpAccum(x_accum, y_accum);
+                                       x_accum += [event deltaX];
+                                       y_accum += [event deltaY];
+                                       window->setCursorWarpAccum(x_accum, y_accum);
+                                       
+                                       pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, x_warp+x_accum, y_warp+y_accum));
+                               } 
+                               else { //Normal cursor operation: send mouse position in window
+                                       NSPoint mousePos = [event locationInWindow];
+                                       pushEvent(new GHOST_EventCursor([event timestamp], GHOST_kEventCursorMove, window, mousePos.x, mousePos.y));
+                               }
                                break;
                        }
                        
index 8c2919d1ce2d61e56c01fa67767df7db9440fad7..7a39d9ab54a77977335e7254b4ffa668d627fd67 100644 (file)
@@ -236,6 +236,13 @@ protected:
         */
        virtual GHOST_TSuccess setWindowCursorVisibility(bool visible);
        
+       /**
+        * Sets the cursor grab on the window using
+        * native window system calls.
+        * @param warp  Only used when grab is enabled, hides the mouse and allows gragging outside the screen.
+        */
+       virtual GHOST_TSuccess setWindowCursorGrab(bool grab, bool warp, bool restore);
+       
        /**
         * Sets the cursor shape on the window using
         * native window system calls.
index f4c9172c6684404c87424c6e2b4d19a14b1e40a5..1d604553cc1371db92a33ca041a0e4dbb4f2ee2b 100644 (file)
@@ -711,6 +711,56 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorVisibility(bool visible)
        
        return GHOST_kSuccess;
 }
+
+GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(bool grab, bool warp, bool restore)
+{
+       if (grab)
+       {
+               if(warp) {
+                       m_systemCocoa->getCursorPosition(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
+                       
+                       setCursorWarpAccum(0, 0);
+                       setWindowCursorVisibility(false);
+                       m_cursorWarp= true;
+               }
+               return CGAssociateMouseAndMouseCursorPosition(false) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
+       }
+       else {
+               if(m_cursorWarp)
+               {/* are we exiting warp */
+                       setWindowCursorVisibility(true);
+                       /* Almost works without but important otherwise the mouse GHOST location can be incorrect on exit */
+                       if(restore) {
+                               GHOST_Rect bounds;
+                               GHOST_TInt32 x_new, y_new, x_rel, y_rel;
+                               
+                               getClientBounds(bounds);
+                               printf("\ncursor ungrab with restore");
+                               x_new= m_cursorWarpInitPos[0]+m_cursorWarpAccumPos[0];
+                               y_new= m_cursorWarpInitPos[1]+m_cursorWarpAccumPos[1];
+                               
+                               screenToClient(x_new, y_new, x_rel, y_rel);
+                               
+                               if(x_rel < 0)           x_new = (x_new-x_rel) + 2;
+                               if(y_rel < 0)           y_new = (y_new-y_rel) + 2;
+                               if(x_rel > bounds.getWidth())   x_new -= (x_rel-bounds.getWidth()) + 2;
+                               if(y_rel > bounds.getHeight())  y_new -= (y_rel-bounds.getHeight()) + 2;
+                               
+                               clientToScreen(x_new, y_new, x_rel, y_rel);
+                               m_systemCocoa->setCursorPosition(x_rel, y_rel);
+                               
+                       }
+                       else {
+                               m_systemCocoa->setCursorPosition(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
+                       }
+                       
+                       setCursorWarpAccum(0, 0);
+                       m_cursorWarp= false;
+               }
+               return CGAssociateMouseAndMouseCursorPosition(true) == kCGErrorSuccess ? GHOST_kSuccess : GHOST_kFailure;
+       }
+       
+}
        
 GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorShape(GHOST_TStandardCursor shape)
 {