[Bf-blender-cvs] [d571d615a59] master: Windows: support high resolution tablet pen events for Windows Ink

Nicholas Rishel noreply at git.blender.org
Wed Apr 8 12:28:22 CEST 2020


Commit: d571d615a59a40f1d313121cf07fe6e17461e8f0
Author: Nicholas Rishel
Date:   Fri Mar 27 18:31:09 2020 +0100
Branches: master
https://developer.blender.org/rBd571d615a59a40f1d313121cf07fe6e17461e8f0

Windows: support high resolution tablet pen events for Windows Ink

Rather than using the last state of the tablet, we now query the history of
pointer events so strokes can follow the pen even if Blender does not handle
events at the same rate.

Differential Revision: https://developer.blender.org/D6675

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

M	intern/ghost/GHOST_Types.h
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/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 8126c2299c6..b8de31df6c6 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -118,7 +118,7 @@ typedef struct GHOST_TabletData {
 } GHOST_TabletData;
 
 static const GHOST_TabletData GHOST_TABLET_DATA_NONE = {
-    GHOST_kTabletModeNone, /* No tablet connected. */
+    GHOST_kTabletModeNone, /* No cursor in range */
     1.0f,                  /* Pressure */
     0.0f,                  /* Xtilt */
     0.0f};                 /* Ytilt */
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index ad53afd9555..fdd022e44ac 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -115,12 +115,22 @@
 #  define WM_DPICHANGED 0x02E0
 #endif  // WM_DPICHANGED
 
+// WM_POINTER API messages minimum Windows 7
+#ifndef WM_POINTERENTER
+#  define WM_POINTERENTER 0x0249
+#endif  // WM_POINTERENTER
+#ifndef WM_POINTERDOWN
+#  define WM_POINTERDOWN 0x0246
+#endif  // WM_POINTERDOWN
 #ifndef WM_POINTERUPDATE
 #  define WM_POINTERUPDATE 0x0245
 #endif  // WM_POINTERUPDATE
-
-#define WM_POINTERDOWN 0x0246
-#define WM_POINTERUP 0x0247
+#ifndef WM_POINTERUP
+#  define WM_POINTERUP 0x0247
+#endif  // WM_POINTERUP
+#ifndef WM_POINTERLEAVE
+#  define WM_POINTERLEAVE 0x024A
+#endif  // WM_POINTERLEAVE
 
 /* Workaround for some laptop touchpads, some of which seems to
  * have driver issues which makes it so window function receives
@@ -928,9 +938,13 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
     window->updateMouseCapture(MouseReleased);
   }
 
-  if (window->useTabletAPI(GHOST_kTabletNative)) {
-    window->setTabletData(NULL);
+  if (window->m_tabletInRange) {
+    if (window->useTabletAPI(GHOST_kTabletNative)) {
+      // Win32 Pointer processing handles input while in-range and in-contact events.
+      return NULL;
+    }
   }
+
   return new GHOST_EventButton(
       system->getMilliSeconds(), type, window, mask, window->getTabletData());
 }
@@ -938,57 +952,81 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
 void GHOST_SystemWin32::processPointerEvents(
     UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventHandled)
 {
-  GHOST_PointerInfoWin32 pointerInfo;
+  std::vector<GHOST_PointerInfoWin32> pointerInfo;
   GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
 
   if (!window->useTabletAPI(GHOST_kTabletNative)) {
     return;
   }
 
-  if (window->getPointerInfo(&pointerInfo, wParam, lParam) != GHOST_kSuccess) {
+  if (window->getPointerInfo(pointerInfo, wParam, lParam) != GHOST_kSuccess) {
     return;
   }
 
-  if (!pointerInfo.isPrimary) {
+  if (!pointerInfo[0].isPrimary) {
     eventHandled = true;
     return;  // For multi-touch displays we ignore these events
   }
 
-  system->setCursorPosition(pointerInfo.pixelLocation.x, pointerInfo.pixelLocation.y);
-
   switch (type) {
+    case WM_POINTERENTER:
+      window->m_tabletInRange = true;
+      system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time,
+                                              GHOST_kEventCursorMove,
+                                              window,
+                                              pointerInfo[0].pixelLocation.x,
+                                              pointerInfo[0].pixelLocation.y,
+                                              pointerInfo[0].tabletData));
+      break;
     case WM_POINTERDOWN:
-      /* Update window tablet data to be included in event. */
-      window->setTabletData(&pointerInfo.tabletData);
-      system->pushEvent(new GHOST_EventButton(system->getMilliSeconds(),
+      // Move cursor to point of contact because GHOST_EventButton does not include position.
+      system->pushEvent(new GHOST_EventCursor(pointerInfo[0].time,
+                                              GHOST_kEventCursorMove,
+                                              window,
+                                              pointerInfo[0].pixelLocation.x,
+                                              pointerInfo[0].pixelLocation.y,
+                                              pointerInfo[0].tabletData));
+      system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
                                               GHOST_kEventButtonDown,
                                               window,
-                                              pointerInfo.buttonMask,
-                                              pointerInfo.tabletData));
+                                              pointerInfo[0].buttonMask,
+                                              pointerInfo[0].tabletData));
       window->updateMouseCapture(MousePressed);
       break;
     case WM_POINTERUPDATE:
-      /* Update window tablet data to be included in event. */
-      system->pushEvent(GHOST_EventCursor(system->getMilliSeconds(),
-                                          GHOST_kEventCursorMove,
-                                          window,
-                                          pointerInfo.pixelLocation.x,
-                                          pointerInfo.pixelLocation.y,
-                                          pointerInfo.tabletData));
+      // Coalesced pointer events are reverse chronological order, reorder chronologically.
+      // Only contiguous move events are coalesced.
+      for (GHOST_TUns32 i = pointerInfo.size(); i-- > 0;) {
+        system->pushEvent(new GHOST_EventCursor(pointerInfo[i].time,
+                                                GHOST_kEventCursorMove,
+                                                window,
+                                                pointerInfo[i].pixelLocation.x,
+                                                pointerInfo[i].pixelLocation.y,
+                                                pointerInfo[i].tabletData));
+      }
       break;
     case WM_POINTERUP:
-      system->pushEvent(new GHOST_EventButton(system->getMilliSeconds(),
+      system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
                                               GHOST_kEventButtonUp,
                                               window,
-                                              pointerInfo.buttonMask,
-                                              window->getTabletData()));
+                                              pointerInfo[0].buttonMask,
+                                              pointerInfo[0].tabletData));
       window->updateMouseCapture(MouseReleased);
       break;
+    case WM_POINTERLEAVE:
+      window->m_tabletInRange = false;
+      system->pushEvent(new GHOST_EventButton(pointerInfo[0].time,
+                                              GHOST_kEventCursorMove,
+                                              window,
+                                              pointerInfo[0].buttonMask,
+                                              pointerInfo[0].tabletData));
+      break;
     default:
       break;
   }
 
   eventHandled = true;
+  system->setCursorPosition(pointerInfo[0].pixelLocation.x, pointerInfo[0].pixelLocation.y);
 }
 
 GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *window)
@@ -996,12 +1034,18 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind
   GHOST_TInt32 x_screen, y_screen;
   GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
 
-  system->getCursorPosition(x_screen, y_screen);
+  if (window->m_tabletInRange) {
+    if (window->useTabletAPI(GHOST_kTabletNative)) {
+      // Tablet input handled in WM_POINTER* events. WM_MOUSEMOVE events in response to tablet
+      // input aren't normally generated when using WM_POINTER events, but manually moving the
+      // system cursor as we do in WM_POINTER handling does.
+      return NULL;
+    }
+  }
 
-  /* TODO: CHECK IF THIS IS A TABLET EVENT */
-  bool is_tablet = false;
+  system->getCursorPosition(x_screen, y_screen);
 
-  if (is_tablet == false && window->getCursorGrabModeIsWarp()) {
+  if (window->getCursorGrabModeIsWarp() && !window->m_tabletInRange) {
     GHOST_TInt32 x_new = x_screen;
     GHOST_TInt32 y_new = y_screen;
     GHOST_TInt32 x_accum, y_accum;
@@ -1424,9 +1468,11 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
         ////////////////////////////////////////////////////////////////////////
         // Pointer events, processed
         ////////////////////////////////////////////////////////////////////////
+        case WM_POINTERENTER:
         case WM_POINTERDOWN:
         case WM_POINTERUPDATE:
         case WM_POINTERUP:
+        case WM_POINTERLEAVE:
           processPointerEvents(msg, window, wParam, lParam, eventHandled);
           break;
         ////////////////////////////////////////////////////////////////////////
diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp
index 9d957da61cd..b0ba7b6befb 100644
--- a/intern/ghost/intern/GHOST_WindowWin32.cpp
+++ b/intern/ghost/intern/GHOST_WindowWin32.cpp
@@ -82,11 +82,12 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
       m_wantAlphaBackground(alphaBackground),
       m_normal_state(GHOST_kWindowStateNormal),
       m_user32(NULL),
-      m_fpGetPointerInfo(NULL),
-      m_fpGetPointerPenInfo(NULL),
-      m_fpGetPointerTouchInfo(NULL),
+      m_fpGetPointerInfoHistory(NULL),
+      m_fpGetPointerPenInfoHistory(NULL),
+      m_fpGetPointerTouchInfoHistory(NULL),
       m_parentWindowHwnd(parentwindow ? parentwindow->m_hWnd : NULL),
-      m_debug_context(is_debug)
+      m_debug_context(is_debug),
+      m_tabletInRange(false)
 {
   // Initialize tablet variables
   memset(&m_wintab, 0, sizeof(m_wintab));
@@ -288,11 +289,12 @@ GHOST_WindowWin32::GHOST_WindowWin32(GHOST_SystemWin32 *system,
 
   // Initialize Windows Ink
   if (m_user32) {
-    m_fpGetPointerInfo = (GHOST_WIN32_GetPointerInfo)::GetProcAddress(m_user32, "GetPointerInfo");
-    m_fpGetPointerPenInfo = (GHOST_WIN32_GetPointerPenInfo)::GetProcAddress(m_user32,
-                                                         

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list