[Bf-blender-cvs] [a1d2efd1900] master: GHOST/Wayland: draw a software-cursor when wrapping cursor motion

Campbell Barton noreply at git.blender.org
Wed Jun 8 05:17:08 CEST 2022


Commit: a1d2efd190038c7615bd3bb459dc86c8b3a8ecdc
Author: Campbell Barton
Date:   Wed Jun 8 13:01:31 2022 +1000
Branches: master
https://developer.blender.org/rBa1d2efd190038c7615bd3bb459dc86c8b3a8ecdc

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.

===================================================================

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_ISystem.h
M	intern/ghost/GHOST_IWindow.h
M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	intern/ghost/intern/GHOST_System.cpp
M	intern/ghost/intern/GHOST_System.h
M	intern/ghost/intern/GHOST_SystemWayland.cpp
M	intern/ghost/intern/GHOST_SystemWayland.h
M	intern/ghost/intern/GHOST_Window.cpp
M	intern/ghost/intern/GHOST_Window.h
M	source/blender/windowmanager/intern/wm_draw.c

===================================================================

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
@@ -896,6 +900,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.
  */
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
@@ -304,6 +304,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.
    */
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).
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index d2ade7b0376..810cc9001fe 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -118,6 +118,113 @@ static void wm_paintcursor_draw(bContext *C, ScrArea *area, ARegion *region)
 
 /** \} */
 
+/* -------------------------------------------------------------------- */
+/** \name Draw Software Cursor
+ *
+ * Draw the cursor instead of relying on the graphical environment.
+ * Needed when setting the cursor position (warping) isn't supported (GHOST/WAYLAND).
+ * \{ */
+
+/**
+ * Track the state of the last drawn cursor.
+ */
+static struct {
+  int8_t enabled;
+  int winid;
+  int xy[2];
+} g_software_cursor = {
+    .enabled = -1,
+    .winid = -1,
+};
+
+static bool wm_software_cursor_needed(void)
+{
+  if (UNLIKELY(g_software_cursor.enabled == -1)) {
+    g_software_cursor.enabled = !GHOST_SupportsCursorWarp();
+  }
+  return g_software_cursor.enabled;
+}
+
+static bool wm_software_cursor_needed_for_window(const wmWindow *win)
+{
+  BLI_assert(wm_software_cursor_needed());
+  return (win->grabcursor == GHOST_kGrabWrap) && GHOST_GetCursorVisibility(win->ghostwin);
+}
+
+static bool wm_software_cursor_motion_test(const wmWindow *win)
+{
+  return (g_software_cursor.winid != win->winid) ||
+         (g_software_cursor.xy[0] != win->eventstate->xy[0]) ||
+         (g_software_cursor.xy[1] != win->eventstate->xy[1]);
+}
+
+static void wm_software_cursor_motion_update(const wmWindow *win)
+{
+
+

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list