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:
authorCampbell Barton <ideasman42@gmail.com>2009-10-07 11:11:10 +0400
committerCampbell Barton <ideasman42@gmail.com>2009-10-07 11:11:10 +0400
commit77476b294f8a7a74ee6f19ff8bfcbb3fb26e3bda (patch)
treed96b292248acdac14880309c1b3fa8976853b596
parent828395744ae9c70d3f69c923cd761aaf2f45abb9 (diff)
Experimental option to allow moving the mouse outside the view, "Continuous Grab" in the user-prefs.
- 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
-rw-r--r--intern/ghost/GHOST_C-api.h2
-rw-r--r--intern/ghost/GHOST_IWindow.h2
-rw-r--r--intern/ghost/intern/GHOST_C-api.cpp4
-rw-r--r--intern/ghost/intern/GHOST_SystemX11.cpp48
-rw-r--r--intern/ghost/intern/GHOST_Window.cpp12
-rw-r--r--intern/ghost/intern/GHOST_Window.h53
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.cpp23
-rw-r--r--intern/ghost/intern/GHOST_WindowX11.h3
-rw-r--r--release/scripts/ui/space_userpref.py4
-rw-r--r--source/blender/editors/interface/interface_handlers.c189
-rw-r--r--source/blender/makesdna/DNA_userdef_types.h1
-rw-r--r--source/blender/makesrna/intern/rna_userdef.c4
-rw-r--r--source/blender/windowmanager/WM_api.h2
-rw-r--r--source/blender/windowmanager/intern/wm_cursors.c4
-rw-r--r--source/blender/windowmanager/intern/wm_event_system.c6
15 files changed, 268 insertions, 89 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 9460fb504a9..35391d3f4cf 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -376,7 +376,7 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
* @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.
diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h
index ff1484909b0..44ddf9a7cfb 100644
--- a/intern/ghost/GHOST_IWindow.h
+++ b/intern/ghost/GHOST_IWindow.h
@@ -271,7 +271,7 @@ public:
* @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; };
};
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index d14945d1bf8..b86c4703ea2 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -355,11 +355,11 @@ GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle,
GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle,
- int grab)
+ int grab, int warp)
{
GHOST_IWindow* window = (GHOST_IWindow*) windowhandle;
- return window->setCursorGrab(grab?true:false);
+ return window->setCursorGrab(grab?true:false, warp?true:false);
}
diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp
index cdbdce9c2ca..8c87abf16bc 100644
--- a/intern/ghost/intern/GHOST_SystemX11.cpp
+++ b/intern/ghost/intern/GHOST_SystemX11.cpp
@@ -374,12 +374,12 @@ GHOST_SystemX11::processEvent(XEvent *xe)
// Only generate a single expose event
// per read of the event queue.
- g_event = new
+ g_event = new
GHOST_Event(
getMilliSeconds(),
GHOST_kEventWindowUpdate,
window
- );
+ );
}
break;
}
@@ -388,14 +388,42 @@ GHOST_SystemX11::processEvent(XEvent *xe)
{
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;
}
diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp
index 34e9f519a07..531674607d1 100644
--- a/intern/ghost/intern/GHOST_Window.cpp
+++ b/intern/ghost/intern/GHOST_Window.cpp
@@ -48,12 +48,16 @@ GHOST_Window::GHOST_Window(
:
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_cursorWarpAccumPos[0] = 0;
+ m_cursorWarpAccumPos[1] = 0;
+
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 (setWindowCursorGrab(grab)) {
+ if (setWindowCursorGrab(grab, warp)) {
m_cursorGrabbed = grab;
return GHOST_kSuccess;
}
@@ -150,4 +154,4 @@ GHOST_TSuccess GHOST_Window::setModifiedState(bool isUnsavedChanges)
bool GHOST_Window::getModifiedState()
{
return m_isUnsavedChanges;
-} \ No newline at end of file
+}
diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h
index a2d1675f6ab..36e4bac6dae 100644
--- a/intern/ghost/intern/GHOST_Window.h
+++ b/intern/ghost/intern/GHOST_Window.h
@@ -158,6 +158,10 @@ public:
* @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.
@@ -171,7 +175,7 @@ public:
* @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
@@ -243,7 +247,7 @@ protected:
* 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
@@ -272,6 +276,15 @@ protected:
/** 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;
@@ -304,6 +317,42 @@ inline bool GHOST_Window::getCursorVisibility() const
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;
diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp
index 060e9ca6f6c..c2dc1048ea0 100644
--- a/intern/ghost/intern/GHOST_WindowX11.cpp
+++ b/intern/ghost/intern/GHOST_WindowX11.cpp
@@ -1400,12 +1400,29 @@ setWindowCursorVisibility(
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);
- 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);
+ }
XFlush(m_display);
diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h
index 6f8940bdcbb..08fba3e2be8 100644
--- a/intern/ghost/intern/GHOST_WindowX11.h
+++ b/intern/ghost/intern/GHOST_WindowX11.h
@@ -252,10 +252,11 @@ protected:
/**
* 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(
- bool grab
+ bool grab, bool warp
);
/**
diff --git a/release/scripts/ui/space_userpref.py b/release/scripts/ui/space_userpref.py
index 15e6c7ee4be..ce8d03d3292 100644
--- a/release/scripts/ui/space_userpref.py
+++ b/release/scripts/ui/space_userpref.py
@@ -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.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")
diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c
index bbf8df00b88..385a0eec040 100644
--- a/source/blender/editors/interface/interface_handlers.c
+++ b/source/blender/editors/interface/interface_handlers.c
@@ -230,6 +230,15 @@ static uiBut *ui_but_last(uiBlock *block)
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};
@@ -1971,6 +1980,51 @@ static int ui_do_but_EXIT(bContext *C, uiBut *but, uiHandleButtonData *data, wmE
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;
@@ -1993,74 +2047,88 @@ static int ui_numedit_but_NUM(uiBut *but, uiHandleButtonData *data, float fac, i
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 {
- 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;
}
@@ -2071,7 +2139,10 @@ static int ui_do_but_NUM(bContext *C, uiBlock *block, uiBut *but, uiHandleButton
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.... */
@@ -3636,11 +3707,15 @@ static void button_activate_state(bContext *C, uiBut *but, uiHandleButtonState s
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);
- else if(data->state == BUTTON_STATE_NUM_EDITING)
+ } else if(data->state == BUTTON_STATE_NUM_EDITING) {
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);
diff --git a/source/blender/makesdna/DNA_userdef_types.h b/source/blender/makesdna/DNA_userdef_types.h
index 16ab3e1e9bd..edfc4999d80 100644
--- a/source/blender/makesdna/DNA_userdef_types.h
+++ b/source/blender/makesdna/DNA_userdef_types.h
@@ -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_CONTINUOUS_MOUSE (1 << 24)
/* Auto-Keying mode */
/* AUTOKEY_ON is a bitflag */
diff --git a/source/blender/makesrna/intern/rna_userdef.c b/source/blender/makesrna/intern/rna_userdef.c
index 25448d0c2de..1c6bd6515ff 100644
--- a/source/blender/makesrna/intern/rna_userdef.c
+++ b/source/blender/makesrna/intern/rna_userdef.c
@@ -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.");
+ 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.");
diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h
index 489f27990cd..321afec51b7 100644
--- a/source/blender/windowmanager/WM_api.h
+++ b/source/blender/windowmanager/WM_api.h
@@ -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_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);
diff --git a/source/blender/windowmanager/intern/wm_cursors.c b/source/blender/windowmanager/intern/wm_cursors.c
index 56a8d76d8bf..d14cde56083 100644
--- a/source/blender/windowmanager/intern/wm_cursors.c
+++ b/source/blender/windowmanager/intern/wm_cursors.c
@@ -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)
- GHOST_SetCursorGrab(win->ghostwin, val);
+ GHOST_SetCursorGrab(win->ghostwin, val, warp);
}
/* afer this you can call restore too */
diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index c15106e21c9..54841f0e063 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -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)
- 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);
@@ -637,8 +637,8 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers)
CTX_wm_region_set(C, region);
}
+ WM_cursor_grab(CTX_wm_window(C), 0, -1);
WM_operator_free(handler->op);
- WM_cursor_grab(CTX_wm_window(C), 0);
}
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)) {
- 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);