2.5: X11
authorBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 9 Jul 2009 16:05:01 +0000 (16:05 +0000)
committerBrecht Van Lommel <brechtvanlommel@pandora.be>
Thu, 9 Jul 2009 16:05:01 +0000 (16:05 +0000)
* Pass on mouse location on window leave/enter too, fixing some
  issues with button highlights and tooltips.
* When a modal operator runs, grab the mouse cursor so that for
  example transform still works when you move your mouse outside
  of the window, previously it would just stop then. This is
  automatic now for all modal ops, perhaps not always needed?
* Fix for a trailing button highlight issue.

12 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
source/blender/editors/interface/interface_handlers.c
source/blender/windowmanager/WM_api.h
source/blender/windowmanager/intern/wm_cursors.c
source/blender/windowmanager/intern/wm_event_system.c

index c3158214830833e574e0101770aa41d73409a20c..c0b7077fb538c771b1666cd864471fe355c88b83 100644 (file)
@@ -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.
  ***************************************************************************************/
index 0861d8b8946fe393b0d453fe189cc3aeac6f498c..a05e014dc4ffb77d53bc0d1cfbdeb0ee85024888 100644 (file)
@@ -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_
index 401dba8d240799aa465ee9a61e39101296d6a7eb..5c23b6c42a379f421b6b421e461ae9cfb4f72691 100644 (file)
@@ -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,
index a975322e9cef1b5a286f17e7368bccf8d67c2655..fcf78d9ad200df42c059426525d2dbebd4e4f832 100644 (file)
@@ -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:
index a35680d1586ade48c6dfc11b2ceaba434252b55c..dee890830a188cbb06d3a605afcdf761384a0729 100644 (file)
@@ -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)) {
index 06318613b14119510fe3bdd612e0d205064ee7c6..43744b70be22cd309ddc3be5c4b58ab73ce05895 100644 (file)
@@ -166,6 +166,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;
index 2cc30aaa5bc11a0fe3d30e767597783f99c7b4f6..1525b4eb16dc53479e31df0752fac5f6691c2c6d 100644 (file)
@@ -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
 ){
index 1392e2c19a608dae889ff00cd8f5782199be59b2..6f8940bdcbbfdcd014cb7ef759ab22e55392ff93 100644 (file)
@@ -249,6 +249,15 @@ protected:
                bool visible
        );
        
+       /**
+        * 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.
index 7ad422ef3b5e6e29177d395a7dbf2a96f6102863..ee86b612332ad152629e0cc26b77665c1dc2bbe9 100644 (file)
@@ -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);
                        }
index ff3a2feb521a420d5e16dda8948db5d0e6eede6c..7fe98488ec014f5b3d0a6f6d8bb0433bc49b88b3 100644 (file)
@@ -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);
index 9b64ad6d38c2989d58a3d6b1ed52fc87b9657bf3..5ddd8f5a1a9b1b26927df18276e893ea116b98fe 100644 (file)
@@ -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)
 {
index b5d51ef650b61d717e15c29833df94f5f36007e1..5bcbf5264602c7a3c6ae393f15f0f49f312930df 100644 (file)
@@ -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);