diff options
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 11 | ||||
-rw-r--r-- | intern/ghost/GHOST_IWindow.h | 8 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 8 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemX11.cpp | 15 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_Window.cpp | 15 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_Window.h | 16 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.cpp | 15 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowX11.h | 9 | ||||
-rw-r--r-- | source/blender/editors/interface/interface_handlers.c | 3 | ||||
-rw-r--r-- | source/blender/windowmanager/WM_api.h | 1 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_cursors.c | 5 | ||||
-rw-r--r-- | source/blender/windowmanager/intern/wm_event_system.c | 10 |
12 files changed, 112 insertions, 4 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index c3158214830..c0b7077fb53 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -367,6 +367,17 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, GHOST_TInt32 x, GHOST_TInt32 y); +/** + * Grabs the cursor for a modal operation, to keep receiving + * events when the mouse is outside the window. X11 only, others + * do this automatically. + * @param windowhandle The handle to the window + * @param grab The new grab state of the cursor. + * @return Indication of success. + */ +extern GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, + int grab); + /*************************************************************************************** ** Access to mouse button and keyboard states. ***************************************************************************************/ diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 0861d8b8946..a05e014dc4f 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -252,6 +252,14 @@ public: * @return Indication of success. */ virtual GHOST_TSuccess setCursorVisibility(bool visible) = 0; + + /** + * Grabs the cursor for a modal operation. + * @param grab The new grab state of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorGrab(bool grab) { printf("?! grab\n"); return GHOST_kSuccess; }; + }; #endif // _GHOST_IWINDOW_H_ diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 401dba8d240..5c23b6c42a3 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -354,6 +354,14 @@ GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, } +GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, + int grab) +{ + GHOST_IWindow* window = (GHOST_IWindow*) windowhandle; + + return window->setCursorGrab(grab?true:false); +} + GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, GHOST_TModifierKeyMask mask, diff --git a/intern/ghost/intern/GHOST_SystemX11.cpp b/intern/ghost/intern/GHOST_SystemX11.cpp index a975322e9ce..fcf78d9ad20 100644 --- a/intern/ghost/intern/GHOST_SystemX11.cpp +++ b/intern/ghost/intern/GHOST_SystemX11.cpp @@ -550,11 +550,26 @@ GHOST_SystemX11::processEvent(XEvent *xe) // We're not interested in the following things.(yet...) case NoExpose : case GraphicsExpose : + break; case EnterNotify: case LeaveNotify: + { // XCrossingEvents pointer leave enter window. + // also do cursor move here, MotionNotify only + // happens when motion starts & ends inside window + XCrossingEvent &xce = xe->xcrossing; + + g_event = new + GHOST_EventCursor( + getMilliSeconds(), + GHOST_kEventCursorMove, + window, + xce.x_root, + xce.y_root + ); break; + } case MapNotify: /* * From ICCCM: diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index a35680d1586..dee890830a1 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -50,6 +50,7 @@ GHOST_Window::GHOST_Window( : m_drawingContextType(type), m_cursorVisible(true), + m_cursorGrabbed(true), m_cursorShape(GHOST_kStandardCursorDefault), m_stereoVisual(stereoVisual) { @@ -93,6 +94,20 @@ GHOST_TSuccess GHOST_Window::setCursorVisibility(bool visible) } } +GHOST_TSuccess GHOST_Window::setCursorGrab(bool grab) +{ + if(m_cursorGrabbed == grab) + return GHOST_kSuccess; + + if (setWindowCursorGrab(grab)) { + m_cursorGrabbed = grab; + return GHOST_kSuccess; + } + else { + return GHOST_kFailure; + } +} + GHOST_TSuccess GHOST_Window::setCursorShape(GHOST_TStandardCursor cursorShape) { if (setWindowCursorShape(cursorShape)) { diff --git a/intern/ghost/intern/GHOST_Window.h b/intern/ghost/intern/GHOST_Window.h index 06318613b14..43744b70be2 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -167,6 +167,13 @@ public: virtual GHOST_TSuccess setCursorVisibility(bool visible); /** + * Sets the cursor grab. + * @param grab The new grab state of the cursor. + * @return Indication of success. + */ + virtual GHOST_TSuccess setCursorGrab(bool grab); + + /** * Returns the type of drawing context used in this window. * @return The current type of drawing context. */ @@ -218,6 +225,12 @@ protected: * native window system calls. */ virtual GHOST_TSuccess setWindowCursorVisibility(bool visible) = 0; + + /** + * Sets the cursor grab on the window using + * native window system calls. + */ + virtual GHOST_TSuccess setWindowCursorGrab(bool grab) = 0; /** * Sets the cursor shape on the window using @@ -242,6 +255,9 @@ protected: /** The current visibility of the cursor */ bool m_cursorVisible; + + /** The current grabbed state of the cursor */ + bool m_cursorGrabbed; /** The current shape of the cursor */ GHOST_TStandardCursor m_cursorShape; diff --git a/intern/ghost/intern/GHOST_WindowX11.cpp b/intern/ghost/intern/GHOST_WindowX11.cpp index 2cc30aaa5bc..1525b4eb16d 100644 --- a/intern/ghost/intern/GHOST_WindowX11.cpp +++ b/intern/ghost/intern/GHOST_WindowX11.cpp @@ -1271,6 +1271,21 @@ setWindowCursorVisibility( GHOST_TSuccess GHOST_WindowX11:: +setWindowCursorGrab( + bool grab +){ + if(grab) + XGrabPointer(m_display, m_window, True, ButtonPressMask| ButtonReleaseMask|PointerMotionMask, GrabModeAsync, GrabModeAsync, None, None, CurrentTime); + else + XUngrabPointer(m_display, CurrentTime); + + XFlush(m_display); + + return GHOST_kSuccess; +} + + GHOST_TSuccess +GHOST_WindowX11:: setWindowCursorShape( GHOST_TStandardCursor shape ){ diff --git a/intern/ghost/intern/GHOST_WindowX11.h b/intern/ghost/intern/GHOST_WindowX11.h index 1392e2c19a6..6f8940bdcbb 100644 --- a/intern/ghost/intern/GHOST_WindowX11.h +++ b/intern/ghost/intern/GHOST_WindowX11.h @@ -250,6 +250,15 @@ protected: ); /** + * Sets the cursor grab on the window using + * native window system calls. + */ + GHOST_TSuccess + setWindowCursorGrab( + bool grab + ); + + /** * Sets the cursor shape on the window using * native window system calls. */ diff --git a/source/blender/editors/interface/interface_handlers.c b/source/blender/editors/interface/interface_handlers.c index 7ad422ef3b5..ee86b612332 100644 --- a/source/blender/editors/interface/interface_handlers.c +++ b/source/blender/editors/interface/interface_handlers.c @@ -3775,8 +3775,7 @@ static void ui_handle_button_return_submenu(bContext *C, wmEvent *event, uiBut * button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); } else { - but= ui_but_find_activated(data->region); - if(but) { + if(event->type != MOUSEMOVE) { but->active->used_mouse= 0; button_activate_state(C, but, BUTTON_STATE_HIGHLIGHT); } diff --git a/source/blender/windowmanager/WM_api.h b/source/blender/windowmanager/WM_api.h index ff3a2feb521..7fe98488ec0 100644 --- a/source/blender/windowmanager/WM_api.h +++ b/source/blender/windowmanager/WM_api.h @@ -65,6 +65,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_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 9b64ad6d38c..5ddd8f5a1a9 100644 --- a/source/blender/windowmanager/intern/wm_cursors.c +++ b/source/blender/windowmanager/intern/wm_cursors.c @@ -156,6 +156,11 @@ void WM_cursor_wait(int val) } } +void WM_cursor_grab(wmWindow *win, int val) +{ + GHOST_SetCursorGrab(win->ghostwin, val); +} + /* afer this you can call restore too */ void WM_timecursor(wmWindow *win, int nr) { diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c index b5d51ef650b..5bcbf526460 100644 --- a/source/blender/windowmanager/intern/wm_event_system.c +++ b/source/blender/windowmanager/intern/wm_event_system.c @@ -378,9 +378,12 @@ static int wm_operator_invoke(bContext *C, wmOperatorType *ot, wmEvent *event, P else WM_operator_free(op); } - else if(!(retval & OPERATOR_RUNNING_MODAL)) { - WM_operator_free(op); + else if(retval & OPERATOR_RUNNING_MODAL) { + /* automatically grab cursor during modal ops (X11) */ + WM_cursor_grab(CTX_wm_window(C), 1); } + else + WM_operator_free(op); } return retval; @@ -548,6 +551,7 @@ void WM_event_remove_handlers(bContext *C, ListBase *handlers) } WM_operator_free(handler->op); + WM_cursor_grab(CTX_wm_window(C), 0); } else if(handler->ui_remove) { ScrArea *area= CTX_wm_area(C); @@ -704,6 +708,8 @@ 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); + BLI_remlink(handlers, handler); wm_event_free_handler(handler); |