Experimental option to allow moving the mouse outside the view, "Continuous Grab...
authorCampbell Barton <ideasman42@gmail.com>
Wed, 7 Oct 2009 07:11:10 +0000 (07:11 +0000)
committerCampbell Barton <ideasman42@gmail.com>
Wed, 7 Oct 2009 07:11:10 +0000 (07:11 +0000)
- Useful for dragging buttons to the far right when theyd otherwise hit the screen edge.
- Useful for transform though probably NOT what you want when using the transform manipulator (should make an option).
- When enabled, number buttons use this as well as a different conversion of mouse movement
  float numbuts: mouse 1px == 1-clickstep
  int numbuts: 2px == 1 (tried 1:1 but its too jitter prone)

details...
- access as an option to GHOST_SetCursorGrab(grab, warp)
- Currently all operators that grab use this, could be made an operator flag
- only Ghost/X11 supported currently

15 files changed:
intern/ghost/GHOST_C-api.h
intern/ghost/GHOST_IWindow.h
intern/ghost/intern/GHOST_C-api.cpp
intern/ghost/intern/GHOST_SystemX11.cpp
intern/ghost/intern/GHOST_Window.cpp
intern/ghost/intern/GHOST_Window.h
intern/ghost/intern/GHOST_WindowX11.cpp
intern/ghost/intern/GHOST_WindowX11.h
release/scripts/ui/space_userpref.py
source/blender/editors/interface/interface_handlers.c
source/blender/makesdna/DNA_userdef_types.h
source/blender/makesrna/intern/rna_userdef.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_cursors.c
source/blender/windowmanager/intern/wm_event_system.c

index 9460fb504a9b3dca4d3519333b572e7c4f983f6a..35391d3f4cf94232f8fce4cfd46ae0ebbc9b75d1 100644 (file)
@@ -376,7 +376,7 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
  * @return     Indication of success.
  */
 extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
  * @return     Indication of success.
  */
 extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
-                                                                                 int grab);
+                                                                                 int grab, int warp);
 
 /***************************************************************************************
  ** Access to mouse button and keyboard states.
 
 /***************************************************************************************
  ** Access to mouse button and keyboard states.
index ff1484909b081e9720c87880dc1fe04ff55e6996..44ddf9a7cfb651a9e457009385a918fc0e4b055e 100644 (file)
@@ -271,7 +271,7 @@ public:
         * @param       grab The new grab state of the cursor.
         * @return      Indication of success.
         */
         * @param       grab The new grab state of the cursor.
         * @return      Indication of success.
         */
-       virtual GHOST_TSuccess setCursorGrab(bool grab) { return GHOST_kSuccess; };
+       virtual GHOST_TSuccess setCursorGrab(bool grab, bool warp) { return GHOST_kSuccess; };
 
 };
 
 
 };
 
index d14945d1bf8ca0910132faeb8f8c5cd8d306b68f..b86c4703ea2b2ede3f1c9dc0c211fada26456cfa 100644 (file)
@@ -355,11 +355,11 @@ GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
 
 
 GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
 
 
 GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
-                                                                  int grab)
+                                                                  int grab, int warp)
 {
        GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
        
 {
        GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
        
-       return window->setCursorGrab(grab?true:false);
+       return window->setCursorGrab(grab?true:false, warp?true:false);
 }
 
 
 }
 
 
index cdbdce9c2ca7647ad90db872468532bd7c44c0da..8c87abf16bc2e34d5897c7b6f24d0b3e25ec3468 100644 (file)
@@ -374,12 +374,12 @@ GHOST_SystemX11::processEvent(XEvent *xe)
                                // Only generate a single expose event
                                // per read of the event queue.
 
                                // Only generate a single expose event
                                // per read of the event queue.
 
-                               g_event = new 
+                               g_event = new
                                GHOST_Event(
                                        getMilliSeconds(),
                                        GHOST_kEventWindowUpdate,
                                        window
                                GHOST_Event(
                                        getMilliSeconds(),
                                        GHOST_kEventWindowUpdate,
                                        window
-                               );                      
+                               );
                        }
                        break;
                }
                        }
                        break;
                }
@@ -388,14 +388,42 @@ GHOST_SystemX11::processEvent(XEvent *xe)
                {
                        XMotionEvent &xme = xe->xmotion;
                        
                {
                        XMotionEvent &xme = xe->xmotion;
                        
-                       g_event = new 
-                       GHOST_EventCursor(
-                               getMilliSeconds(),
-                               GHOST_kEventCursorMove,
-                               window,
-                               xme.x_root,
-                               xme.y_root
-                       );
+                       if(window->getCursorWarp()) {
+                               /* Calculate offscreen location and re-center the mouse */
+                               GHOST_TInt32 x_warp, y_warp,  x_new, y_new, x_accum, y_accum;
+
+                               window->getCursorWarpPos(x_warp, y_warp);
+                               getCursorPosition(x_new, y_new);
+
+                               if(x_warp != x_new || y_warp != y_new) {
+                                       window->getCursorWarpAccum(x_accum, y_accum);
+                                       x_accum += x_new - x_warp;
+                                       y_accum += y_new - y_warp;
+
+                                       window->setCursorWarpAccum(x_accum, y_accum);
+                                       setCursorPosition(x_warp, y_warp); /* reset */
+
+                                       g_event = new
+                                       GHOST_EventCursor(
+                                               getMilliSeconds(),
+                                               GHOST_kEventCursorMove,
+                                               window,
+                                               x_warp + x_accum,
+                                               y_warp + y_accum
+                                       );
+
+                               }
+                       }
+                       else {
+                               g_event = new
+                               GHOST_EventCursor(
+                                       getMilliSeconds(),
+                                       GHOST_kEventCursorMove,
+                                       window,
+                                       xme.x_root,
+                                       xme.y_root
+                               );
+                       }
                        break;
                }
 
                        break;
                }
 
index 34e9f519a07085945344fd8a4479febc53ce0a02..531674607d13dba6fd5d65d6c402a4e230be1778 100644 (file)
@@ -48,12 +48,16 @@ GHOST_Window::GHOST_Window(
 :
        m_drawingContextType(type),
        m_cursorVisible(true),
 :
        m_drawingContextType(type),
        m_cursorVisible(true),
-       m_cursorGrabbed(true),
+       m_cursorGrabbed(false),
+       m_cursorWarp(false),
        m_cursorShape(GHOST_kStandardCursorDefault),
        m_stereoVisual(stereoVisual)
 {
        m_isUnsavedChanges = false;
        
        m_cursorShape(GHOST_kStandardCursorDefault),
        m_stereoVisual(stereoVisual)
 {
        m_isUnsavedChanges = false;
        
+    m_cursorWarpAccumPos[0] = 0;
+    m_cursorWarpAccumPos[1] = 0;
+
     m_fullScreen = state == GHOST_kWindowStateFullScreen;
     if (m_fullScreen) {
         m_fullScreenWidth = width;
     m_fullScreen = state == GHOST_kWindowStateFullScreen;
     if (m_fullScreen) {
         m_fullScreenWidth = width;
@@ -94,12 +98,12 @@ GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible)
        }
 }
 
        }
 }
 
-GHOST_TSuccess GHOST_Window::setCursorGrab(bool grab)
+GHOST_TSuccess GHOST_Window::setCursorGrab(bool grab, bool warp)
 {
        if(m_cursorGrabbed == grab)
                return GHOST_kSuccess;
 
 {
        if(m_cursorGrabbed == grab)
                return GHOST_kSuccess;
 
-       if (setWindowCursorGrab(grab)) {
+       if (setWindowCursorGrab(grab, warp)) {
                m_cursorGrabbed = grab;
                return GHOST_kSuccess;
        }
                m_cursorGrabbed = grab;
                return GHOST_kSuccess;
        }
@@ -150,4 +154,4 @@ GHOST_TSuccess GHOST_Window::setModifiedState(bool isUnsavedChanges)
 bool GHOST_Window::getModifiedState()
 {
        return m_isUnsavedChanges;
 bool GHOST_Window::getModifiedState()
 {
        return m_isUnsavedChanges;
-}
\ No newline at end of file
+}
index a2d1675f6abcf8861d56b0e0c73a8707763e95b1..36e4bac6dae1b54f0bcd9ed321ede74b84a83d8e 100644 (file)
@@ -158,6 +158,10 @@ public:
         * @return      The visibility state of the cursor.
         */
        inline virtual bool getCursorVisibility() const;
         * @return      The visibility state of the cursor.
         */
        inline virtual bool getCursorVisibility() const;
+       inline virtual bool getCursorWarp() const;
+       inline virtual bool getCursorWarpPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+       inline virtual bool getCursorWarpAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const;
+       inline virtual bool setCursorWarpAccum(GHOST_TInt32 x, GHOST_TInt32 y);
 
        /**
         * Shows or hides the cursor.
 
        /**
         * Shows or hides the cursor.
@@ -171,7 +175,7 @@ public:
         * @param       grab The new grab state of the cursor.
         * @return      Indication of success.
         */
         * @param       grab The new grab state of the cursor.
         * @return      Indication of success.
         */
-       virtual GHOST_TSuccess setCursorGrab(bool grab);
+       virtual GHOST_TSuccess setCursorGrab(bool grab, bool warp);
 
        /**
         * Sets the window "modified" status, indicating unsaved changes
 
        /**
         * Sets the window "modified" status, indicating unsaved changes
@@ -243,7 +247,7 @@ protected:
         * Sets the cursor grab on the window using
         * native window system calls.
         */
         * Sets the cursor grab on the window using
         * native window system calls.
         */
-       virtual GHOST_TSuccess setWindowCursorGrab(bool grab) { return GHOST_kSuccess; };
+       virtual GHOST_TSuccess setWindowCursorGrab(bool grab, bool warp) { return GHOST_kSuccess; };
        
        /**
         * Sets the cursor shape on the window using
        
        /**
         * Sets the cursor shape on the window using
@@ -272,6 +276,15 @@ protected:
        /** The current grabbed state of the cursor */
        bool m_cursorGrabbed;
        
        /** The current grabbed state of the cursor */
        bool m_cursorGrabbed;
        
+       /** The current warped state of the cursor */
+       bool m_cursorWarp;
+
+       /** Initial grab location. */
+       GHOST_TInt32 m_cursorWarpInitPos[2];
+
+       /** Accumulated offset from m_cursorWarpInitPos. */
+       GHOST_TInt32 m_cursorWarpAccumPos[2];
+
        /** The current shape of the cursor */
        GHOST_TStandardCursor m_cursorShape;
     
        /** The current shape of the cursor */
        GHOST_TStandardCursor m_cursorShape;
     
@@ -304,6 +317,42 @@ inline bool GHOST_Window::getCursorVisibility() const
        return m_cursorVisible;
 }
 
        return m_cursorVisible;
 }
 
+inline bool GHOST_Window::getCursorWarp() const
+{
+       return m_cursorWarp;
+}
+
+inline bool GHOST_Window::getCursorWarpPos(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+{
+       if(m_cursorWarp==false)
+               return GHOST_kFailure;
+
+       x= m_cursorWarpInitPos[0];
+       y= m_cursorWarpInitPos[1];
+       return GHOST_kSuccess;
+}
+
+inline bool GHOST_Window::getCursorWarpAccum(GHOST_TInt32 &x, GHOST_TInt32 &y) const
+{
+       if(m_cursorWarp==false)
+               return GHOST_kFailure;
+
+       x= m_cursorWarpAccumPos[0];
+       y= m_cursorWarpAccumPos[1];
+       return GHOST_kSuccess;
+}
+
+inline bool GHOST_Window::setCursorWarpAccum(GHOST_TInt32 x, GHOST_TInt32 y)
+{
+       if(m_cursorWarp==false)
+               return GHOST_kFailure;
+
+       m_cursorWarpAccumPos[0]= x;
+       m_cursorWarpAccumPos[1]= y;
+
+       return GHOST_kSuccess;
+}
+
 inline GHOST_TStandardCursor GHOST_Window::getCursorShape() const
 {
        return m_cursorShape;
 inline GHOST_TStandardCursor GHOST_Window::getCursorShape() const
 {
        return m_cursorShape;
index 060e9ca6f6cf275bf23845d6b9a4c42b738fa03b..c2dc1048ea0db362f1d9db5f67ababe2ef25caca 100644 (file)
@@ -1400,12 +1400,29 @@ setWindowCursorVisibility(
        GHOST_TSuccess
 GHOST_WindowX11::
 setWindowCursorGrab(
        GHOST_TSuccess
 GHOST_WindowX11::
 setWindowCursorGrab(
-       bool grab
+       bool grab, bool warp
 ){
 ){
-       if(grab)
+       if(grab) {
+               if(warp) {
+                       m_system->getCursorPosition(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
+
+                       setCursorWarpAccum(0, 0);
+                       setWindowCursorVisibility(false);
+                       m_cursorWarp= true;
+               }
                XGrabPointer(m_display, m_window, True, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
                XGrabPointer(m_display, m_window, True, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime);
-       else
+       }
+       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 */
+                       m_system->setCursorPosition(m_cursorWarpInitPos[0], m_cursorWarpInitPos[1]);
+
+                       setCursorWarpAccum(0, 0);
+                       m_cursorWarp= false;
+               }
                XUngrabPointer(m_display, CurrentTime);
                XUngrabPointer(m_display, CurrentTime);
+       }
 
        XFlush(m_display);
        
 
        XFlush(m_display);
        
index 6f8940bdcbbfdcd014cb7ef759ab22e55392ff93..08fba3e2be8a15ae525fa879fda213cbce5ec7e6 100644 (file)
@@ -252,10 +252,11 @@ protected:
        /**
         * Sets the cursor grab on the window using
         * native window system calls.
        /**
         * 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.
         */
                GHOST_TSuccess 
        setWindowCursorGrab(
         */
                GHOST_TSuccess 
        setWindowCursorGrab(
-               bool grab
+               bool grab, bool warp
        );
 
        /**
        );
 
        /**
index 15e6c7ee4be2f299379167c95fdeda1d4b69ddf4..ce8d03d3292000058a70d1cdce1fc390ce08dccb 100644 (file)
@@ -109,8 +109,8 @@ class USERPREF_PT_view(bpy.types.Panel):
                sub1.itemL(text="Mouse Wheel:")
                sub1.itemR(view, "wheel_invert_zoom", text="Invert Zoom")
                sub1.itemR(view, "wheel_scroll_lines", text="Scroll Lines")
                sub1.itemL(text="Mouse Wheel:")
                sub1.itemR(view, "wheel_invert_zoom", text="Invert Zoom")
                sub1.itemR(view, "wheel_scroll_lines", text="Scroll Lines")
-               sub1.itemS()
-               sub1.itemS()
+               sub1.itemL(text="Mouse Motion:")
+               sub1.itemR(view, "continuous_mouse", text="Continuous Grab")
                sub1.itemS()
                sub1.itemL(text="Menus:")
                sub1.itemR(view, "open_mouse_over")
                sub1.itemS()
                sub1.itemL(text="Menus:")
                sub1.itemR(view, "open_mouse_over")
index bbf8df00b88ed63d89c948e8a05c61803f9102ef..385a0eec0403a183160179bd5b6e03aec8fe7b26 100644 (file)
@@ -230,6 +230,15 @@ static uiBut *ui_but_last(uiBlock *block)
        return NULL;
 }
 
        return NULL;
 }
 
+static int ui_is_a_warp_but(uiBut *but)
+{
+       if(U.uiflag & USER_CONTINUOUS_MOUSE)
+               if(ELEM(but->type, NUM, NUMABS))
+                       return TRUE;
+
+       return FALSE;
+}
+
 /* ********************** button apply/revert ************************/
 
 static ListBase UIAfterFuncs = {NULL, NULL};
 /* ********************** button apply/revert ************************/
 
 static ListBase UIAfterFuncs = {NULL, NULL};
@@ -1971,6 +1980,51 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmE
        return WM_UI_HANDLER_CONTINUE;
 }
 
        return WM_UI_HANDLER_CONTINUE;
 }
 
+/* var names match ui_numedit_but_NUM */
+static float ui_numedit_apply_snapf(float tempf, float softmin, float softmax, float softrange, int snap)
+{
+       if(tempf==softmin || tempf==softmax)
+               return tempf;
+
+       switch(snap) {
+       case 0:
+               break;
+       case 1:
+               if(tempf==softmin || tempf==softmax) { }
+               else if(softrange < 2.10) tempf= 0.1*floor(10*tempf);
+               else if(softrange < 21.0) tempf= floor(tempf);
+               else tempf= 10.0*floor(tempf/10.0);
+               break;
+       case 2:
+               if(tempf==softmin || tempf==softmax) { }
+               else if(softrange < 2.10) tempf= 0.01*floor(100.0*tempf);
+               else if(softrange < 21.0) tempf= 0.1*floor(10.0*tempf);
+               else tempf= floor(tempf);
+               break;
+       }
+
+       return tempf;
+}
+
+static float ui_numedit_apply_snap(int temp, float softmin, float softmax, int snap)
+{
+       if(temp==softmin || temp==softmax)
+               return temp;
+
+       switch(snap) {
+       case 0:
+               break;
+       case 1:
+               temp= 10*(temp/10);
+               break;
+       case 2:
+               temp= 100*(temp/100);
+               break;
+       }
+
+       return temp;
+}
+
 static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, int snap, int mx)
 {
        float deler, tempf, softmin, softmax, softrange;
 static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, int snap, int mx)
 {
        float deler, tempf, softmin, softmax, softrange;
@@ -1993,74 +2047,88 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
        softmax= but->softmax;
        softrange= softmax - softmin;
 
        softmax= but->softmax;
        softrange= softmax - softmin;
 
-       deler= 500;
-       if(!ui_is_but_float(but)) {
-               if((softrange)<100) deler= 200.0;
-               if((softrange)<25) deler= 50.0;
-       }
-       deler /= fac;
 
 
-       if(ui_is_but_float(but) && softrange > 11) {
-               /* non linear change in mouse input- good for high precicsion */
-               data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.002);
-       } else if (!ui_is_but_float(but) && softrange > 129) { /* only scale large int buttons */
-               /* non linear change in mouse input- good for high precicsionm ints need less fine tuning */
-               data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.004);
-       } else {
-               /*no scaling */
-               data->dragf+= ((float)(mx-data->draglastx))/deler ;
-       }
+       if(ui_is_a_warp_but(but)) {
+               /* Mouse location isn't screen clamped to the screen so use a linear mapping
+                * 2px == 1-int, or 1px == 1-ClickStep */
+               if(ui_is_but_float(but)) {
+                       tempf = data->startvalue + ((mx - data->dragstartx) * fac * 0.01*but->a1);
+                       tempf= ui_numedit_apply_snapf(tempf, softmin, softmax, softrange, snap);
+                       CLAMP(tempf, softmin, softmax);
 
 
-       if(data->dragf>1.0) data->dragf= 1.0;
-       if(data->dragf<0.0) data->dragf= 0.0;
-       data->draglastx= mx;
-       tempf= (softmin + data->dragf*softrange);
-       
-       if(!ui_is_but_float(but)) {
-               temp= floor(tempf+.5);
-               
-               if(tempf==softmin || tempf==softmax);
-               else if(snap) {
-                       if(snap == 2) temp= 100*(temp/100);
-                       else temp= 10*(temp/10);
+                       if(tempf != data->value) {
+                               data->dragchange= 1;
+                               data->value= tempf;
+                               changed= 1;
+                       }
                }
                }
+               else {
+                       temp= data->startvalue + (mx - data->dragstartx)/2; /* simple 2px == 1 */
+                       temp= ui_numedit_apply_snap(temp, softmin, softmax, snap);
+                       CLAMP(temp, softmin, softmax);
 
 
-               CLAMP(temp, softmin, softmax);
-               lvalue= (int)data->value;
-                       
-               if(temp != lvalue) {
-                       data->dragchange= 1;
-                       data->value= (double)temp;
-                       changed= 1;
+                       if(temp != data->value) {
+                               data->dragchange= 1;
+                               data->value= temp;
+                               changed= 1;
+                       }
                }
        }
        else {
                }
        }
        else {
-               temp= 0;
+               /* Use a non-linear mapping of the mouse drag especially for large floats (normal behavior) */
+               deler= 500;
+               if(!ui_is_but_float(but)) {
+                       if((softrange)<100) deler= 200.0;
+                       if((softrange)<25) deler= 50.0;
+               }
+               deler /= fac;
 
 
-               if(snap) {
-                       if(snap == 2) {
-                               if(tempf==softmin || tempf==softmax);
-                               else if(softrange < 2.10) tempf= 0.01*floor(100.0*tempf);
-                               else if(softrange < 21.0) tempf= 0.1*floor(10.0*tempf);
-                               else tempf= floor(tempf);
-                       }
-                       else {
-                               if(tempf==softmin || tempf==softmax);
-                               else if(softrange < 2.10) tempf= 0.1*floor(10*tempf);
-                               else if(softrange < 21.0) tempf= floor(tempf);
-                               else tempf= 10.0*floor(tempf/10.0);
+               if(ui_is_but_float(but) && softrange > 11) {
+                       /* non linear change in mouse input- good for high precicsion */
+                       data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.002);
+               } else if (!ui_is_but_float(but) && softrange > 129) { /* only scale large int buttons */
+                       /* non linear change in mouse input- good for high precicsionm ints need less fine tuning */
+                       data->dragf+= (((float)(mx-data->draglastx))/deler) * (fabs(data->dragstartx-mx)*0.004);
+               } else {
+                       /*no scaling */
+                       data->dragf+= ((float)(mx-data->draglastx))/deler ;
+               }
+       
+               if(data->dragf>1.0) data->dragf= 1.0;
+               if(data->dragf<0.0) data->dragf= 0.0;
+               data->draglastx= mx;
+               tempf= (softmin + data->dragf*softrange);
+
+
+               if(!ui_is_but_float(but)) {
+                       temp= floor(tempf+.5);
+
+                       temp= ui_numedit_apply_snap(temp, softmin, softmax, snap);
+
+                       CLAMP(temp, softmin, softmax);
+                       lvalue= (int)data->value;
+
+                       if(temp != lvalue) {
+                               data->dragchange= 1;
+                               data->value= (double)temp;
+                               changed= 1;
                        }
                }
                        }
                }
+               else {
+                       temp= 0;
+                       tempf= ui_numedit_apply_snapf(tempf, softmin, softmax, softrange, snap);
 
 
-               CLAMP(tempf, softmin, softmax);
+                       CLAMP(tempf, softmin, softmax);
 
 
-               if(tempf != data->value) {
-                       data->dragchange= 1;
-                       data->value= tempf;
-                       changed= 1;
+                       if(tempf != data->value) {
+                               data->dragchange= 1;
+                               data->value= tempf;
+                               changed= 1;
+                       }
                }
        }
 
                }
        }
 
+
        return changed;
 }
 
        return changed;
 }
 
@@ -2071,7 +2139,10 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
        
        mx= event->x;
        my= event->y;
        
        mx= event->x;
        my= event->y;
-       ui_window_to_block(data->region, block, &mx, &my);
+
+       if(!ui_is_a_warp_but(but)) {
+               ui_window_to_block(data->region, block, &mx, &my);
+       }
 
        if(data->state == BUTTON_STATE_HIGHLIGHT) {
                /* XXX hardcoded keymap check.... */
 
        if(data->state == BUTTON_STATE_HIGHLIGHT) {
                /* XXX hardcoded keymap check.... */
@@ -3636,11 +3707,15 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
                ui_textedit_end(C, but, data);
        
        /* number editing */
                ui_textedit_end(C, but, data);
        
        /* number editing */
-       if(state == BUTTON_STATE_NUM_EDITING)
+       if(state == BUTTON_STATE_NUM_EDITING) {
+               if(ui_is_a_warp_but(but))
+                       WM_cursor_grab(CTX_wm_window(C), 1, 1);
                ui_numedit_begin(but, data);
                ui_numedit_begin(but, data);
-       else if(data->state == BUTTON_STATE_NUM_EDITING)
+       } else if(data->state == BUTTON_STATE_NUM_EDITING) {
                ui_numedit_end(but, data);
                ui_numedit_end(but, data);
-
+               if(ui_is_a_warp_but(but))
+                       WM_cursor_grab(CTX_wm_window(C), 0, -1);
+       }
        /* menu open */
        if(state == BUTTON_STATE_MENU_OPEN)
                ui_blockopen_begin(C, but, data);
        /* menu open */
        if(state == BUTTON_STATE_MENU_OPEN)
                ui_blockopen_begin(C, but, data);
index 16ab3e1e9bd01bfe2790aff3b96cc051a8b7a8ed..edfc4999d80a49554a899836d0842cbe4355327a 100644 (file)
@@ -402,6 +402,7 @@ extern UserDef U; /* from blenkernel blender.c */
 #define USER_SHOW_FPS                  (1 << 21)
 #define USER_MMB_PASTE                 (1 << 22)
 #define USER_MENUFIXEDORDER            (1 << 23)
 #define USER_SHOW_FPS                  (1 << 21)
 #define USER_MMB_PASTE                 (1 << 22)
 #define USER_MENUFIXEDORDER            (1 << 23)
+#define USER_CONTINUOUS_MOUSE          (1 << 24)
 
 /* Auto-Keying mode */
        /* AUTOKEY_ON is a bitflag */
 
 /* Auto-Keying mode */
        /* AUTOKEY_ON is a bitflag */
index 25448d0c2dee96c6fae29e9aeb2dadc4c32cc983..1c6bd6515ff680c08758f590232147652315580d 100644 (file)
@@ -1655,6 +1655,10 @@ static void rna_def_userdef_view(BlenderRNA *brna)
        RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_MENUFIXEDORDER);
        RNA_def_property_ui_text(prop, "Contents Follow Opening Direction", "Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction.");
 
        RNA_def_property_boolean_negative_sdna(prop, NULL, "uiflag", USER_MENUFIXEDORDER);
        RNA_def_property_ui_text(prop, "Contents Follow Opening Direction", "Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction.");
 
+       prop= RNA_def_property(srna, "continuous_mouse", PROP_BOOLEAN, PROP_NONE);
+       RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_CONTINUOUS_MOUSE);
+       RNA_def_property_ui_text(prop, "Contents Follow Opening Direction", "Otherwise menus, etc will always be top to bottom, left to right, no matter opening direction.");
+
        prop= RNA_def_property(srna, "global_pivot", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_LOCKAROUND);
        RNA_def_property_ui_text(prop, "Global Pivot", "Lock the same rotation/scaling pivot in all 3D Views.");
        prop= RNA_def_property(srna, "global_pivot", PROP_BOOLEAN, PROP_NONE);
        RNA_def_property_boolean_sdna(prop, NULL, "uiflag", USER_LOCKAROUND);
        RNA_def_property_ui_text(prop, "Global Pivot", "Lock the same rotation/scaling pivot in all 3D Views.");
index 489f27990cda756526904f1ad9de09deb9eec319..321afec51b72d83d95a831b83ed194dad2e5c98f 100644 (file)
@@ -75,7 +75,7 @@ void          WM_cursor_set           (struct wmWindow *win, int curs);
 void           WM_cursor_modal         (struct wmWindow *win, int curs);
 void           WM_cursor_restore       (struct wmWindow *win);
 void           WM_cursor_wait          (int val);
 void           WM_cursor_modal         (struct wmWindow *win, int curs);
 void           WM_cursor_restore       (struct wmWindow *win);
 void           WM_cursor_wait          (int val);
-void           WM_cursor_grab          (struct wmWindow *win, int val);
+void           WM_cursor_grab          (struct wmWindow *win, int val, int warp);
 void           WM_timecursor           (struct wmWindow *win, int nr);
 
 void           *WM_paint_cursor_activate(struct wmWindowManager *wm, int (*poll)(struct bContext *C), void (*draw)(struct bContext *C, int, int, void *customdata), void *customdata);
 void           WM_timecursor           (struct wmWindow *win, int nr);
 
 void           *WM_paint_cursor_activate(struct wmWindowManager *wm, int (*poll)(struct bContext *C), void (*draw)(struct bContext *C, int, int, void *customdata), void *customdata);
index 56a8d76d8bfe1126cc21f5df45fc83058d2fd7a0..d14cde56083edfa32ae30037e3716736b75855ce 100644 (file)
@@ -163,10 +163,10 @@ void WM_cursor_wait(int val)
        }
 }
 
        }
 }
 
-void WM_cursor_grab(wmWindow *win, int val)
+void WM_cursor_grab(wmWindow *win, int val, int warp)
 {
        if(win)
 {
        if(win)
-               GHOST_SetCursorGrab(win->ghostwin, val);
+               GHOST_SetCursorGrab(win->ghostwin, val, warp);
 }
 
 /* afer this you can call restore too */
 }
 
 /* afer this you can call restore too */
index c15106e21c9d87805548f256641c5e5eeff50d2d..54841f0e06342fad63bd815775c76608b8a69f2d 100644 (file)
@@ -442,7 +442,7 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P
                else if(retval & OPERATOR_RUNNING_MODAL) {
                        /* grab cursor during blocking modal ops (X11) */
                        if(ot->flag & OPTYPE_BLOCKING)
                else if(retval & OPERATOR_RUNNING_MODAL) {
                        /* grab cursor during blocking modal ops (X11) */
                        if(ot->flag & OPTYPE_BLOCKING)
-                               WM_cursor_grab(CTX_wm_window(C), 1);
+                               WM_cursor_grab(CTX_wm_window(C), 1, (U.uiflag & USER_CONTINUOUS_MOUSE));
                }
                else
                        WM_operator_free(op);
                }
                else
                        WM_operator_free(op);
@@ -637,8 +637,8 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
                                CTX_wm_region_set(C, region);
                        }
 
                                CTX_wm_region_set(C, region);
                        }
 
+                       WM_cursor_grab(CTX_wm_window(C), 0, -1);
                        WM_operator_free(handler->op);
                        WM_operator_free(handler->op);
-                       WM_cursor_grab(CTX_wm_window(C), 0);
                }
                else if(handler->ui_remove) {
                        ScrArea *area= CTX_wm_area(C);
                }
                else if(handler->ui_remove) {
                        ScrArea *area= CTX_wm_area(C);
@@ -835,7 +835,7 @@ static int wm_handler_operator_call(bContext *C, ListBase *handlers, wmEventHand
                        
                        /* remove modal handler, operator itself should have been cancelled and freed */
                        if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
                        
                        /* remove modal handler, operator itself should have been cancelled and freed */
                        if(retval & (OPERATOR_CANCELLED|OPERATOR_FINISHED)) {
-                               WM_cursor_grab(CTX_wm_window(C), 0);
+                               WM_cursor_grab(CTX_wm_window(C), 0, -1);
 
                                BLI_remlink(handlers, handler);
                                wm_event_free_handler(handler);
 
                                BLI_remlink(handlers, handler);
                                wm_event_free_handler(handler);