[Bf-blender-cvs] [dc2736a7dcf] grab_walk_fix: Fix Windows cursor wrap jumps.

Nicholas Rishel noreply at git.blender.org
Sat Jul 24 00:27:51 CEST 2021


Commit: dc2736a7dcf11ef393ff78c76d61608fa9bd2f47
Author: Nicholas Rishel
Date:   Fri Jul 16 15:08:48 2021 -0700
Branches: grab_walk_fix
https://developer.blender.org/rBdc2736a7dcf11ef393ff78c76d61608fa9bd2f47

Fix Windows cursor wrap jumps.

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

M	intern/ghost/intern/GHOST_SystemWin32.cpp
M	intern/ghost/intern/GHOST_WindowWin32.cpp
M	intern/ghost/intern/GHOST_WindowWin32.h

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

diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index d0ca53e593b..65b7380c959 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -1094,10 +1094,12 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
 
   system->getCursorPosition(x_screen, y_screen);
 
+  int32_t x_accum = 0;
+  int32_t y_accum = 0;
+
   if (window->getCursorGrabModeIsWarp()) {
     int32_t x_new = x_screen;
     int32_t y_new = y_screen;
-    int32_t x_accum, y_accum;
     GHOST_Rect bounds;
 
     /* Fallback to window bounds. */
@@ -1111,29 +1113,41 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
 
     window->getCursorGrabAccum(x_accum, y_accum);
     if (x_new != x_screen || y_new != y_screen) {
-      /* When wrapping we don't need to add an event because the setCursorPosition call will cause
-       * a new event after. */
       system->setCursorPosition(x_new, y_new); /* wrap */
-      window->setCursorGrabAccum(x_accum + (x_screen - x_new), y_accum + (y_screen - y_new));
+
+      /* We may be in an event before cursor wrap has taken effect */
+      if (window->m_activeWarpX >= 0 && x_new - x_screen < 0 ||
+          window->m_activeWarpX <= 0 && x_new - x_screen > 0) {
+        x_accum = x_accum + (x_screen - x_new);
+      }
+
+      if (window->m_activeWarpY >= 0 && y_new - y_screen < 0 ||
+          window->m_activeWarpY <= 0 && y_new - y_screen > 0) {
+        y_accum = y_accum + (y_screen - y_new);
+      }
+
+      window->setCursorGrabAccum(x_accum, y_accum);
+
+      window->m_activeWarpX = x_new - x_screen;
+      window->m_activeWarpY = y_new - y_screen;
+
+      /* When wrapping we don't need to add an event because the setCursorPosition call will cause
+       * a new event after. We also need to skip outdated messages while warp is active to prevent
+       * applying cursor accumulation to old coordinates. */
+      return NULL;
     }
     else {
-      return new GHOST_EventCursor(system->getMilliSeconds(),
-                                   GHOST_kEventCursorMove,
-                                   window,
-                                   x_screen + x_accum,
-                                   y_screen + y_accum,
-                                   GHOST_TABLET_DATA_NONE);
+      window->m_activeWarpX = 0;
+      window->m_activeWarpY = 0;
     }
   }
-  else {
-    return new GHOST_EventCursor(system->getMilliSeconds(),
-                                 GHOST_kEventCursorMove,
-                                 window,
-                                 x_screen,
-                                 y_screen,
-                                 GHOST_TABLET_DATA_NONE);
-  }
-  return NULL;
+
+  return new GHOST_EventCursor(system->getMilliSeconds(),
+                               GHOST_kEventCursorMove,
+                               window,
+                               x_screen + x_accum,
+                               y_screen + y_accum,
+                               GHOST_TABLET_DATA_NONE);
 }
 
 void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index b5d0fd8e6db..084b9677fab 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -75,6 +75,8 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
       m_isDialog(dialog),
       m_hasMouseCaptured(false),
       m_hasGrabMouse(false),
+      m_activeWarpX(0),
+      m_activeWarpY(0),
       m_nPressedButtons(0),
       m_customCursor(0),
       m_wantAlphaBackground(alphaBackground),
@@ -820,6 +822,8 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode
     if (mode != GHOST_kGrabNormal) {
       m_system->getCursorPosition(m_cursorGrabInitPos[0], m_cursorGrabInitPos[1]);
       setCursorGrabAccum(0, 0);
+      m_activeWarpX = 0;
+      m_activeWarpY = 0;
 
       if (mode == GHOST_kGrabHide)
         setWindowCursorVisibility(false);
@@ -843,6 +847,8 @@ GHOST_TSuccess GHOST_WindowWin32::setWindowCursorGrab(GHOST_TGrabCursorMode mode
     /* Almost works without but important otherwise the mouse GHOST location
      * can be incorrect on exit. */
     setCursorGrabAccum(0, 0);
+    m_activeWarpX = 0;
+    m_activeWarpY = 0;
     m_cursorGrabBounds.m_l = m_cursorGrabBounds.m_r = -1; /* disable */
     updateMouseCapture(OperatorUngrab);
   }
diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h
index ed5292f1712..306398618cd 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.h
+++ b/intern/ghost/intern/GHOST_WindowWin32.h
@@ -307,6 +307,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
 
   /** True if the mouse is either over or captured by the window. */
   bool m_mousePresent;
+  /** Active cursor warp in x axis. */
+  int32_t m_activeWarpX;
+  /** Active cursor warp in y axis. */
+  int32_t m_activeWarpY;
 
   /** True if the window currently resizing. */
   bool m_inLiveResize;



More information about the Bf-blender-cvs mailing list