Fix T44605: OS X continuous grab issues.
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 3 Oct 2015 01:37:41 +0000 (03:37 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Sat, 3 Oct 2015 11:08:37 +0000 (13:08 +0200)
intern/ghost/intern/GHOST_C-api.cpp
intern/ghost/intern/GHOST_SystemCocoa.mm
intern/ghost/intern/GHOST_WindowCocoa.mm
source/blender/windowmanager/intern/wm_cursors.c
source/blender/windowmanager/intern/wm_window.c
source/blender/windowmanager/wm_window.h

index af992bf5a3c1d2eb04f6cf659b13ae5af921ca3f..9baa66abad934b5d9719c816c45e6959f4d22872 100644 (file)
@@ -358,27 +358,20 @@ GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
                                    int bounds[4], const int mouse_ungrab_xy[2])
 {
        GHOST_IWindow *window = (GHOST_IWindow *) windowhandle;
-       GHOST_Rect bounds_rect, bounds_win;
-       GHOST_TInt32 mouse_ungrab_xy_global[2];
+       GHOST_Rect bounds_rect;
+       GHOST_TInt32 mouse_xy[2];
 
        if (bounds) {
-               /* if this is X11 specific we need a function that converts */
-               window->getClientBounds(bounds_win);
-               window->clientToScreen(bounds[0], bounds_win.getHeight() - bounds[1], bounds_rect.m_l, bounds_rect.m_t);
-               window->clientToScreen(bounds[2], bounds_win.getHeight() - bounds[3], bounds_rect.m_r, bounds_rect.m_b);
-
+               bounds_rect = GHOST_Rect(bounds[0], bounds[1], bounds[2], bounds[3]);
        }
-       
        if (mouse_ungrab_xy) {
-               if (bounds == NULL)
-                       window->getClientBounds(bounds_win);
-               window->clientToScreen(mouse_ungrab_xy[0], bounds_win.getHeight() - mouse_ungrab_xy[1],
-                                      mouse_ungrab_xy_global[0], mouse_ungrab_xy_global[1]);
+               mouse_xy[0] = mouse_ungrab_xy[0];
+               mouse_xy[1] = mouse_ungrab_xy[1];
        }
 
        return window->setCursorGrab(mode,
                                     bounds ? &bounds_rect : NULL,
-                                    mouse_ungrab_xy ? mouse_ungrab_xy_global : NULL);
+                                    mouse_ungrab_xy ? mouse_xy : NULL);
 }
 
 
index b9686e5af9bac3ee41a0501b9c26b059aa4f6a21..37c2ac12315279f93e5d64fbfd215c17f4e2ff22 100644 (file)
@@ -1317,6 +1317,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
                                                GHOST_TInt32 x_warp, y_warp, x_accum, y_accum, x, y;
                                                
                                                window->getCursorGrabInitPos(x_warp, y_warp);
+                                               window->screenToClientIntern(x_warp, y_warp, x_warp, y_warp);
                                                
                                                window->getCursorGrabAccum(x_accum, y_accum);
                                                x_accum += [event deltaX];
@@ -1368,6 +1369,7 @@ GHOST_TSuccess GHOST_SystemCocoa::handleMouseEvent(void *eventPtr)
                                                
                                                //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);
                                                pushEvent(new GHOST_EventCursor([event timestamp] * 1000, GHOST_kEventCursorMove, window, x, y));
                                                break;
index 9c7b5c3fee7eccfdb445856d2a5354e4c0e90520..204d61de3dfc30a44a96fde1d0b50aedc37eacbe 100644 (file)
@@ -1463,12 +1463,9 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode
        if (mode != GHOST_kGrabDisable) {
                //No need to perform grab without warp as it is always on in OS X
                if (mode != GHOST_kGrabNormal) {
-                       GHOST_TInt32 x_old,y_old;
                        NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 
-                       m_systemCocoa->getCursorPosition(x_old,y_old);
-                       screenToClientIntern(x_old, y_old, m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
-                       //Warp position is stored in client (window base) coordinates
+                       m_systemCocoa->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
                        setCursorGrabAccum(0, 0);
                        
                        if (mode == GHOST_kGrabHide) {
@@ -1486,7 +1483,7 @@ GHOST_TSuccess GHOST_WindowCocoa::setWindowCursorGrab(GHOST_TGrabCursorMode mode
        }
        else {
                if (m_cursorGrab==GHOST_kGrabHide) {
-                       //No need to set again cursor position, as it has not changed for Cocoa
+                       m_systemCocoa->setCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
                        setWindowCursorVisibility(true);
                }
                
index d84b65847ca919eb0014b36a2071e8830587b2a8..d9466cbd035a815fd76afdcdd14504c4512afe65 100644 (file)
@@ -199,14 +199,10 @@ void WM_cursor_grab_enable(wmWindow *win, bool wrap, bool hide, int bounds[4])
         * It helps not to get a stuck WM when hitting a breakpoint  
         * */
        GHOST_TGrabCursorMode mode = GHOST_kGrabNormal;
-       float fac = GHOST_GetNativePixelSize(win->ghostwin);
 
-       /* in case pixel coords differ from window/mouse coords */
        if (bounds) {
-               bounds[0] /= fac;
-               bounds[1] /= fac;
-               bounds[2] /= fac;
-               bounds[3] /= fac;
+               wm_cursor_position_to_ghost(win, &bounds[0], &bounds[1]);
+               wm_cursor_position_to_ghost(win, &bounds[2], &bounds[3]);
        }
        
        if (hide) {
@@ -234,7 +230,15 @@ void WM_cursor_grab_disable(wmWindow *win, const int mouse_ungrab_xy[2])
 {
        if ((G.debug & G_DEBUG) == 0) {
                if (win && win->ghostwin) {
-                       GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, mouse_ungrab_xy);
+                       if (mouse_ungrab_xy) {
+                               int mouse_xy[2] = {mouse_ungrab_xy[0], mouse_ungrab_xy[1]};
+                               wm_cursor_position_to_ghost(win, &mouse_xy[0], &mouse_xy[1]);
+                               GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, mouse_xy);
+                       }
+                       else {
+                               GHOST_SetCursorGrab(win->ghostwin, GHOST_kGrabDisable, NULL, NULL);
+                       }
+
                        win->grabcursor = GHOST_kGrabDisable;
                }
        }
index 0b0cedf5825e8133d696fe0b3a2c17bdf7d9eaa1..030399a9c7d85adea7630e88e198888229c8a904 100644 (file)
@@ -676,7 +676,7 @@ int wm_window_fullscreen_toggle_exec(bContext *C, wmOperator *UNUSED(op))
 
 /* ************ events *************** */
 
-static void wm_convert_cursor_position(wmWindow *win, int *x, int *y)
+void wm_cursor_position_from_ghost(wmWindow *win, int *x, int *y)
 {
        float fac = GHOST_GetNativePixelSize(win->ghostwin);
        
@@ -687,11 +687,21 @@ static void wm_convert_cursor_position(wmWindow *win, int *x, int *y)
        *y *= fac;
 }
 
+void wm_cursor_position_to_ghost(wmWindow *win, int *x, int *y)
+{
+       float fac = GHOST_GetNativePixelSize(win->ghostwin);
+
+       *x /= fac;
+       *y /= fac;
+       *y = win->sizey - *y - 1;
+
+       GHOST_ClientToScreen(win->ghostwin, *x, *y, x, y);
+}
 
 void wm_get_cursor_position(wmWindow *win, int *x, int *y)
 {
        GHOST_GetCursorPosition(g_system, x, y);
-       wm_convert_cursor_position(win, x, y);
+       wm_cursor_position_from_ghost(win, x, y);
 }
 
 typedef enum {
@@ -1118,7 +1128,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
                        {
                                GHOST_TEventTrackpadData *pd = data;
                                
-                               wm_convert_cursor_position(win, &pd->x, &pd->y);
+                               wm_cursor_position_from_ghost(win, &pd->x, &pd->y);
                                wm_event_add_ghostevent(wm, win, type, time, data);
                                break;
                        }
@@ -1126,7 +1136,7 @@ static int ghost_event_proc(GHOST_EventHandle evt, GHOST_TUserDataPtr C_void_ptr
                        {
                                GHOST_TEventCursorData *cd = data;
                                
-                               wm_convert_cursor_position(win, &cd->x, &cd->y);
+                               wm_cursor_position_from_ghost(win, &cd->x, &cd->y);
                                wm_event_add_ghostevent(wm, win, type, time, data);
                                break;
                        }
@@ -1541,14 +1551,9 @@ void WM_init_native_pixels(bool do_it)
 void WM_cursor_warp(wmWindow *win, int x, int y)
 {
        if (win && win->ghostwin) {
-               float f = GHOST_GetNativePixelSize(win->ghostwin);
                int oldx = x, oldy = y;
 
-               x = x / f;
-               y = y / f;
-               y = win->sizey - y - 1;
-
-               GHOST_ClientToScreen(win->ghostwin, x, y, &x, &y);
+               wm_cursor_position_to_ghost(win, &x, &y);
                GHOST_SetCursorPosition(g_system, x, y);
 
                win->eventstate->prevx = oldx;
index a104f6aba3955bcea1ee8da77f572529b4bd8faa..8633f297ddad2be19f85216a207f318d11e38187 100644 (file)
@@ -64,7 +64,9 @@ bool          wm_window_get_swap_interval(wmWindow *win, int *intervalOut);
 
 float          wm_window_pixelsize(wmWindow *win);
 
-void           wm_get_cursor_position  (wmWindow *win, int *x, int *y);
+void           wm_get_cursor_position                  (wmWindow *win, int *x, int *y);
+void           wm_cursor_position_from_ghost   (wmWindow *win, int *x, int *y);
+void           wm_cursor_position_to_ghost             (wmWindow *win, int *x, int *y);
 
 void           wm_window_testbreak             (void);