diff options
author | Campbell Barton <campbell@blender.org> | 2022-06-08 06:01:31 +0300 |
---|---|---|
committer | Campbell Barton <campbell@blender.org> | 2022-06-08 06:16:14 +0300 |
commit | a1d2efd190038c7615bd3bb459dc86c8b3a8ecdc (patch) | |
tree | 2f709a3566c84d45ccd352104573626a445cdb41 /intern | |
parent | b3e0101a35b2885212aa199335564dca98dc50cd (diff) |
GHOST/Wayland: draw a software-cursor when wrapping cursor motion
As Wayland doesn't support moving the cursor, draw a cross-hair cursor
at the location used by Blender.
Without this, the cursor was locked at the location where grab started,
making some actions unusable since the cursor location was invisible.
Resolves T77311.
Diffstat (limited to 'intern')
-rw-r--r-- | intern/ghost/GHOST_C-api.h | 9 | ||||
-rw-r--r-- | intern/ghost/GHOST_ISystem.h | 5 | ||||
-rw-r--r-- | intern/ghost/GHOST_IWindow.h | 4 | ||||
-rw-r--r-- | intern/ghost/GHOST_Types.h | 2 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_C-api.cpp | 23 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.cpp | 5 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_System.h | 3 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWayland.cpp | 10 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWayland.h | 2 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_Window.cpp | 23 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_Window.h | 2 |
11 files changed, 86 insertions, 2 deletions
diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h index ae749eb3b8c..57714083656 100644 --- a/intern/ghost/GHOST_C-api.h +++ b/intern/ghost/GHOST_C-api.h @@ -402,6 +402,10 @@ extern GHOST_TSuccess GHOST_SetCursorPosition(GHOST_SystemHandle systemhandle, int32_t x, int32_t y); +GHOST_TSuccess GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle, + GHOST_TAxisFlag *r_wrap_axis, + int r_bounds[4]); + /** * Grabs the cursor for a modal operation, to keep receiving * events when the mouse is outside the window. X11 only, others @@ -897,6 +901,11 @@ extern int setConsoleWindowState(GHOST_TConsoleWindowState action); extern int GHOST_UseNativePixels(void); /** + * Warp the cursor, if supported. + */ +extern int GHOST_SupportsCursorWarp(void); + +/** * Focus window after opening, or put them in the background. */ extern void GHOST_UseWindowFocus(int use_focus); diff --git a/intern/ghost/GHOST_ISystem.h b/intern/ghost/GHOST_ISystem.h index bb91abbadec..8a4412403f7 100644 --- a/intern/ghost/GHOST_ISystem.h +++ b/intern/ghost/GHOST_ISystem.h @@ -305,6 +305,11 @@ class GHOST_ISystem { virtual bool useNativePixel(void) = 0; /** + * Return true when warping the cursor is supported. + */ + virtual bool supportsCursorWarp() = 0; + + /** * Focus window after opening, or put them in the background. */ virtual void useWindowFocus(const bool use_focus) = 0; diff --git a/intern/ghost/GHOST_IWindow.h b/intern/ghost/GHOST_IWindow.h index 183e97a4b55..681ad9c5b07 100644 --- a/intern/ghost/GHOST_IWindow.h +++ b/intern/ghost/GHOST_IWindow.h @@ -254,6 +254,10 @@ class GHOST_IWindow { */ virtual GHOST_TSuccess setCursorShape(GHOST_TStandardCursor cursorShape) = 0; + virtual GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds) = 0; + + virtual GHOST_TSuccess getCursorGrabState(GHOST_TAxisFlag &axis_flag, GHOST_Rect &bounds) = 0; + /** * Test if the standard cursor shape is supported by current platform. * \return Indication of success. diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h index e2ed9830e4e..841c0c33ee1 100644 --- a/intern/ghost/GHOST_Types.h +++ b/intern/ghost/GHOST_Types.h @@ -403,6 +403,8 @@ typedef enum { GHOST_kGrabHide, } GHOST_TGrabCursorMode; +#define GHOST_GRAB_NEEDS_SOFTWARE_CURSOR_FOR_WARP(grab) ((grab) == GHOST_kGrabWrap) + typedef enum { /** Axis that cursor grab will wrap. */ GHOST_kGrabAxisNone = 0, diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp index 9374d087408..f4c978a88d4 100644 --- a/intern/ghost/intern/GHOST_C-api.cpp +++ b/intern/ghost/intern/GHOST_C-api.cpp @@ -376,6 +376,23 @@ GHOST_TSuccess GHOST_SetCursorGrab(GHOST_WindowHandle windowhandle, mode, wrap_axis, bounds ? &bounds_rect : nullptr, mouse_ungrab_xy ? mouse_xy : nullptr); } +GHOST_TSuccess GHOST_GetCursorGrabState(GHOST_WindowHandle windowhandle, + GHOST_TAxisFlag *r_axis_flag, + int r_bounds[4]) +{ + GHOST_IWindow *window = (GHOST_IWindow *)windowhandle; + GHOST_Rect bounds_rect; + if (!window->getCursorGrabState(*r_axis_flag, bounds_rect)) { + return GHOST_kFailure; + } + + r_bounds[0] = bounds_rect.m_l; + r_bounds[1] = bounds_rect.m_t; + r_bounds[2] = bounds_rect.m_r; + r_bounds[3] = bounds_rect.m_b; + return GHOST_kSuccess; +} + GHOST_TSuccess GHOST_GetModifierKeyState(GHOST_SystemHandle systemhandle, GHOST_TModifierKeyMask mask, int *isDown) @@ -815,6 +832,12 @@ int GHOST_UseNativePixels(void) return system->useNativePixel(); } +int GHOST_SupportsCursorWarp(void) +{ + GHOST_ISystem *system = GHOST_ISystem::getSystem(); + return system->supportsCursorWarp(); +} + void GHOST_UseWindowFocus(int use_focus) { GHOST_ISystem *system = GHOST_ISystem::getSystem(); diff --git a/intern/ghost/intern/GHOST_System.cpp b/intern/ghost/intern/GHOST_System.cpp index 1ddf884bbc5..2aad4f2ea29 100644 --- a/intern/ghost/intern/GHOST_System.cpp +++ b/intern/ghost/intern/GHOST_System.cpp @@ -390,6 +390,11 @@ void GHOST_System::useWindowFocus(const bool use_focus) m_windowFocus = use_focus; } +bool GHOST_System::supportsCursorWarp() +{ + return true; +} + void GHOST_System::initDebug(GHOST_Debug debug) { m_is_debug_enabled = debug.flags & GHOST_kDebugDefault; diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index 4a3cded1fbd..9f2fba1a2c6 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -151,10 +151,13 @@ class GHOST_System : public GHOST_ISystem { bool useNativePixel(void); bool m_nativePixel; + bool supportsCursorWarp(void); + /** * Focus window after opening, or put them in the background. */ void useWindowFocus(const bool use_focus); + bool m_windowFocus; /** diff --git a/intern/ghost/intern/GHOST_SystemWayland.cpp b/intern/ghost/intern/GHOST_SystemWayland.cpp index f6eabb60b05..7e471d5c7d4 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.cpp +++ b/intern/ghost/intern/GHOST_SystemWayland.cpp @@ -1920,6 +1920,11 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorVisibility(bool visible) return GHOST_kSuccess; } +bool GHOST_SystemWayland::supportsCursorWarp() +{ + return false; +} + GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mode, const GHOST_TGrabCursorMode mode_current, @@ -1948,8 +1953,9 @@ GHOST_TSuccess GHOST_SystemWayland::setCursorGrab(const GHOST_TGrabCursorMode mo const bool was_lock = MODE_NEEDS_LOCK(mode_current); const bool use_lock = MODE_NEEDS_LOCK(mode); - const bool was_hide = MODE_NEEDS_HIDE(mode_current); - const bool use_hide = MODE_NEEDS_HIDE(mode); + /* Check for wrap as #supportsCursorWarp isn't supproted. */ + const bool was_hide = MODE_NEEDS_HIDE(mode_current) || (mode_current == GHOST_kGrabWrap); + const bool use_hide = MODE_NEEDS_HIDE(mode) || (mode == GHOST_kGrabWrap); const bool was_confine = MODE_NEEDS_CONFINE(mode_current); const bool use_confine = MODE_NEEDS_CONFINE(mode); diff --git a/intern/ghost/intern/GHOST_SystemWayland.h b/intern/ghost/intern/GHOST_SystemWayland.h index eeb65eb4fc3..5b3e4f8ed75 100644 --- a/intern/ghost/intern/GHOST_SystemWayland.h +++ b/intern/ghost/intern/GHOST_SystemWayland.h @@ -103,6 +103,8 @@ class GHOST_SystemWayland : public GHOST_System { GHOST_TSuccess setCursorVisibility(bool visible); + bool supportsCursorWarp(); + GHOST_TSuccess setCursorGrab(const GHOST_TGrabCursorMode mode, const GHOST_TGrabCursorMode mode_current, wl_surface *surface); diff --git a/intern/ghost/intern/GHOST_Window.cpp b/intern/ghost/intern/GHOST_Window.cpp index 954f0bc244d..12963abf128 100644 --- a/intern/ghost/intern/GHOST_Window.cpp +++ b/intern/ghost/intern/GHOST_Window.cpp @@ -155,10 +155,33 @@ GHOST_TSuccess GHOST_Window::setCursorGrab(GHOST_TGrabCursorMode mode, GHOST_TSuccess GHOST_Window::getCursorGrabBounds(GHOST_Rect &bounds) { + if (m_cursorGrab != GHOST_kGrabWrap) { + return GHOST_kFailure; + } bounds = m_cursorGrabBounds; return (bounds.m_l == -1 && bounds.m_r == -1) ? GHOST_kFailure : GHOST_kSuccess; } +GHOST_TSuccess GHOST_Window::getCursorGrabState(GHOST_TAxisFlag &wrap_axis, GHOST_Rect &bounds) +{ + if (m_cursorGrab == GHOST_kGrabDisable) { + return GHOST_kFailure; + } + + if (m_cursorGrab == GHOST_kGrabWrap) { + bounds = m_cursorGrabBounds; + wrap_axis = m_cursorGrabAxis; + } + else { + bounds.m_l = -1; + bounds.m_r = -1; + bounds.m_t = -1; + bounds.m_b = -1; + wrap_axis = GHOST_kGrabAxisNone; + } + return GHOST_kSuccess; +} + 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 794e834d5c7..b0042a33a00 100644 --- a/intern/ghost/intern/GHOST_Window.h +++ b/intern/ghost/intern/GHOST_Window.h @@ -152,6 +152,8 @@ class GHOST_Window : public GHOST_IWindow { */ GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds); + GHOST_TSuccess getCursorGrabState(GHOST_TAxisFlag &axis_flag, GHOST_Rect &bounds); + /** * Sets the progress bar value displayed in the window/application icon * \param progress: The progress percentage (0.0 to 1.0). |