[Bf-blender-cvs] [8d02fdc7e02] master: WM_MOUSEMOVE cleanup.

Nicholas Rishel noreply at git.blender.org
Tue Feb 23 22:31:31 CET 2021


Commit: 8d02fdc7e02241ba2c47a8575651fab86c3e0a41
Author: Nicholas Rishel
Date:   Tue Feb 16 19:33:11 2021 -0800
Branches: master
https://developer.blender.org/rB8d02fdc7e02241ba2c47a8575651fab86c3e0a41

WM_MOUSEMOVE cleanup.

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

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

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

diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 1f85c7a4c5c..e0974373caf 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -1045,11 +1045,27 @@ void GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
   GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
   GHOST_TabletData td = window->getTabletData();
 
+  /* Window's mouse history function returns a history of up to 64 mouse moves, including those
+   * processed during previous mouse move events. This means we must track and filter out events we
+   * have already processed.
+   *
+   * The API accepts and returns 32 bit points, but error or fails when passed a negative number
+   * where the HIWORD is not zeroed, and will return a negative numbers with HIWORD zeroed.
+   * Therefore we must zero the HIWORD of points passed in and sign extend from the LOWORD of
+   * points received. Note: negative position values occur for multi-monitor systems whose primary
+   * display is not the top-leftmost display.
+   *
+   * Querying the mouse history with valid mouse positions sometimes fails, commonly at the screen
+   * edge. In these cases we fall back to using information provided by the event instead of the
+   * mouse event history.
+   *
+   * Further explanation - https://devblogs.microsoft.com/oldnewthing/20120314-00/?p=8103 */
+
   DWORD msgPos = ::GetMessagePos();
   LONG msgTime = ::GetMessageTime();
 
-  /* GetMessagePointsEx processes points as 16 bit integers and can fail or return erroneous values
-   * if negative input is not truncated. */
+  /* GetMessagePointsEx processes 32 bit points as 16 bit integers and can fail or return erroneous
+   * values if negative input's HIWORD is not zeroed. */
   int msgPosX = GET_X_LPARAM(msgPos) & 0x0000FFFF;
   int msgPosY = GET_Y_LPARAM(msgPos) & 0x0000FFFF;
 
@@ -1078,10 +1094,10 @@ void GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
       break;
     }
 
-    /* GetMouseMovePointsEx returns 16 bit number as 32 bit. If negative, we need to sign extend.
-     */
-    points[i].x = points[i].x > 32767 ? points[i].x | 0xFFFF0000 : points[i].x;
-    points[i].y = points[i].y > 32767 ? points[i].y | 0xFFFF0000 : points[i].y;
+    /* GetMouseMovePointsEx returns 16 bit number as 32 bit with HIWORD zeroed. If the signed
+     * LOWORD is negative, we need to sign extend. */
+    points[i].x = points[i].x & 0x8000 ? points[i].x | 0xFFFF0000 : points[i].x;
+    points[i].y = points[i].y & 0x8000 ? points[i].y | 0xFFFF0000 : points[i].y;
 
     if (points[i].time == system->m_mouseTimestamp && points[i].x == system->m_mousePosX &&
         points[i].y == system->m_mousePosY) {
@@ -1097,7 +1113,14 @@ void GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
                                             td));
   }
 
-  DWORD lastTimestamp = points[0].time;
+  /* Update last processed mouse position and time, checking for time overflow. If not overflown
+   * and the this event's time is less than the last, this mousemove event occurred before a cursor
+   * wrap so we should not update last mouse position and time. */
+  if (points[0].time >= system->m_mouseTimestamp || ::GetTickCount() < system->m_mouseTimestamp) {
+    system->m_mousePosX = points[0].x;
+    system->m_mousePosY = points[0].y;
+    system->m_mouseTimestamp = points[0].time;
+  }
 
   /* Check if we need to wrap the cursor. */
   if (window->getCursorGrabModeIsWarp() && !window->m_tabletInRange) {
@@ -1124,18 +1147,11 @@ void GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
       system->setCursorPosition(x_wrap, y_wrap);
       window->setCursorGrabAccum(x_accum + (x_current - x_wrap), y_accum + (y_current - y_wrap));
 
-      /* First message after SendInput wrap is invalid for unknown reasons, skip events until one
-       * tick after SendInput event time. */
-      lastTimestamp = ::GetTickCount() + 1;
+      /* Update the mouse timestamp so that mouse moves prior to wrap are skipped. This is a lower
+       * bound, the timestamp for the generated mouse move may be different. */
+      system->m_mouseTimestamp = ::GetTickCount();
     }
   }
-
-  system->m_mousePosX = points[0].x;
-  system->m_mousePosY = points[0].y;
-  /* Use latest time, checking for overflow. */
-  if (lastTimestamp > system->m_mouseTimestamp || ::GetTickCount() < system->m_mouseTimestamp) {
-    system->m_mouseTimestamp = lastTimestamp;
-  }
 }
 
 void GHOST_SystemWin32::processWheelEvent(GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam)
diff --git a/intern/ghost/intern/GHOST_SystemWin32.h b/intern/ghost/intern/GHOST_SystemWin32.h
index 86c443bb1c7..0d55188b325 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.h
+++ b/intern/ghost/intern/GHOST_SystemWin32.h
@@ -454,6 +454,10 @@ class GHOST_SystemWin32 : public GHOST_System {
   /** Wheel delta accumulator. */
   int m_wheelDeltaAccum;
 
+  /**
+   * Last mouse position and time values, used when inspecting mouse history to know what has
+   * already been processed.
+   */
   /** Last mouse x position. */
   int m_mousePosX;
   /** Last mouse y position. */



More information about the Bf-blender-cvs mailing list