[Bf-blender-cvs] [6f158f834dc] master: Refactor of Wintab to use Wintab supplied mouse movement once verified against system input.
Nicholas Rishel
noreply at git.blender.org
Mon Jun 21 23:40:09 CEST 2021
Commit: 6f158f834dcfa638639391f37afcb2ca8457cb45
Author: Nicholas Rishel
Date: Thu Mar 4 15:48:48 2021 -0800
Branches: master
https://developer.blender.org/rB6f158f834dcfa638639391f37afcb2ca8457cb45
Refactor of Wintab to use Wintab supplied mouse movement once verified against system input.
Reviewed By: brecht, LazyDodo
Maniphest Tasks: T88852
Differential Revision: https://developer.blender.org/D11508
===================================================================
M intern/ghost/CMakeLists.txt
M intern/ghost/GHOST_Types.h
M intern/ghost/intern/GHOST_System.h
M intern/ghost/intern/GHOST_SystemWin32.cpp
M intern/ghost/intern/GHOST_SystemWin32.h
M intern/ghost/intern/GHOST_WindowWin32.cpp
M intern/ghost/intern/GHOST_WindowWin32.h
A intern/ghost/intern/GHOST_Wintab.cpp
A intern/ghost/intern/GHOST_Wintab.h
M source/blender/windowmanager/intern/wm_window.c
===================================================================
diff --git a/intern/ghost/CMakeLists.txt b/intern/ghost/CMakeLists.txt
index 1b5cdb3cda0..40d78a22e6f 100644
--- a/intern/ghost/CMakeLists.txt
+++ b/intern/ghost/CMakeLists.txt
@@ -370,6 +370,7 @@ elseif(WIN32)
intern/GHOST_DropTargetWin32.cpp
intern/GHOST_SystemWin32.cpp
intern/GHOST_WindowWin32.cpp
+ intern/GHOST_Wintab.cpp
intern/GHOST_ContextD3D.h
intern/GHOST_DisplayManagerWin32.h
@@ -377,6 +378,7 @@ elseif(WIN32)
intern/GHOST_SystemWin32.h
intern/GHOST_TaskbarWin32.h
intern/GHOST_WindowWin32.h
+ intern/GHOST_Wintab.h
)
if(NOT WITH_GL_EGL)
diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index 3a8d0fbfecf..f18e6f03ede 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -105,7 +105,9 @@ typedef enum {
typedef enum {
GHOST_kTabletAutomatic = 0,
- GHOST_kTabletNative,
+ /* Show as Windows Ink to users to match "Use Windows Ink" in tablet utilities, but we use the
+ dependent Windows Pointer API. */
+ GHOST_kTabletWinPointer,
GHOST_kTabletWintab,
} GHOST_TTabletAPI;
diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h
index 2a7123b293e..9915520691f 100644
--- a/intern/ghost/intern/GHOST_System.h
+++ b/intern/ghost/intern/GHOST_System.h
@@ -239,7 +239,7 @@ class GHOST_System : public GHOST_ISystem {
* Set which tablet API to use. Only affects Windows, other platforms have a single API.
* \param api: Enum indicating which API to use.
*/
- void setTabletAPI(GHOST_TTabletAPI api);
+ virtual void setTabletAPI(GHOST_TTabletAPI api) override;
GHOST_TTabletAPI getTabletAPI(void);
#ifdef WITH_INPUT_NDOF
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index 45b9e88f884..09cfa30eca5 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -866,15 +866,151 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type,
{
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
- if (type == GHOST_kEventButtonDown) {
- window->updateMouseCapture(MousePressed);
+ GHOST_TabletData td = window->getTabletData();
+
+ /* Move mouse to button event position. */
+ if (window->getTabletData().Active != GHOST_kTabletModeNone) {
+ /* Tablet should be handling inbetween mouse moves, only move to event position. */
+ DWORD msgPos = ::GetMessagePos();
+ int msgPosX = GET_X_LPARAM(msgPos);
+ int msgPosY = GET_Y_LPARAM(msgPos);
+ system->pushEvent(new GHOST_EventCursor(
+ ::GetMessageTime(), GHOST_kEventCursorMove, window, msgPosX, msgPosY, td));
}
- else if (type == GHOST_kEventButtonUp) {
- window->updateMouseCapture(MouseReleased);
+
+ window->updateMouseCapture(type == GHOST_kEventButtonDown ? MousePressed : MouseReleased);
+ return new GHOST_EventButton(system->getMilliSeconds(), type, window, mask, td);
+}
+
+void GHOST_SystemWin32::processWintabEvent(GHOST_WindowWin32 *window)
+{
+ GHOST_Wintab *wt = window->getWintab();
+ if (!wt) {
+ return;
+ }
+
+ GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem();
+
+ std::vector<GHOST_WintabInfoWin32> wintabInfo;
+ wt->getInput(wintabInfo);
+
+ /* Wintab provided coordinates are untrusted until a Wintab and Win32 button down event match.
+ * This is checked on every button down event, and revoked if there is a mismatch. This can
+ * happen when Wintab incorrectly scales cursor position or is in mouse mode.
+ *
+ * If Wintab was never trusted while processing this Win32 event, a fallback Ghost cursor move
+ * event is created at the position of the Win32 WT_PACKET event. */
+ bool mouseMoveHandled;
+ bool useWintabPos;
+ mouseMoveHandled = useWintabPos = wt->trustCoordinates();
+
+ for (GHOST_WintabInfoWin32 &info : wintabInfo) {
+ switch (info.type) {
+ case GHOST_kEventCursorMove: {
+ if (!useWintabPos) {
+ continue;
+ }
+
+ wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
+ system->pushEvent(new GHOST_EventCursor(
+ info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
+
+ break;
+ }
+ case GHOST_kEventButtonDown: {
+ UINT message;
+ switch (info.button) {
+ case GHOST_kButtonMaskLeft:
+ message = WM_LBUTTONDOWN;
+ break;
+ case GHOST_kButtonMaskRight:
+ message = WM_RBUTTONDOWN;
+ break;
+ case GHOST_kButtonMaskMiddle:
+ message = WM_MBUTTONDOWN;
+ break;
+ default:
+ continue;
+ }
+
+ /* Wintab buttons are modal, but the API does not inform us what mode a pressed button is
+ * in. Only issue button events if we can steal an equivalent Win32 button event from the
+ * event queue. */
+ MSG msg;
+ if (PeekMessage(&msg, window->getHWND(), message, message, PM_NOYIELD) &&
+ msg.message != WM_QUIT) {
+
+ /* Test for Win32/Wintab button down match. */
+ useWintabPos = wt->testCoordinates(msg.pt.x, msg.pt.y, info.x, info.y);
+ if (!useWintabPos) {
+ continue;
+ }
+
+ /* Steal the Win32 event which was previously peeked. */
+ PeekMessage(&msg, window->getHWND(), message, message, PM_REMOVE | PM_NOYIELD);
+
+ /* Move cursor to button location, to prevent incorrect cursor position when
+ * transitioning from unsynchronized Win32 to Wintab cursor control. */
+ wt->mapWintabToSysCoordinates(info.x, info.y, info.x, info.y);
+ system->pushEvent(new GHOST_EventCursor(
+ info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData));
+
+ window->updateMouseCapture(MousePressed);
+ system->pushEvent(
+ new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
+
+ mouseMoveHandled = true;
+ break;
+ }
+ }
+ case GHOST_kEventButtonUp: {
+ if (!useWintabPos) {
+ continue;
+ }
+
+ UINT message;
+ switch (info.button) {
+ case GHOST_kButtonMaskLeft:
+ message = WM_LBUTTONUP;
+ break;
+ case GHOST_kButtonMaskRight:
+ message = WM_RBUTTONUP;
+ break;
+ case GHOST_kButtonMaskMiddle:
+ message = WM_MBUTTONUP;
+ break;
+ default:
+ continue;
+ }
+
+ /* Wintab buttons are modal, but the API does not inform us what mode a pressed button is
+ * in. Only issue button events if we can steal an equivalent Win32 button event from the
+ * event queue. */
+ MSG msg;
+ if (PeekMessage(&msg, window->getHWND(), message, message, PM_REMOVE | PM_NOYIELD) &&
+ msg.message != WM_QUIT) {
+
+ window->updateMouseCapture(MouseReleased);
+ system->pushEvent(
+ new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData));
+ }
+ break;
+ }
+ default:
+ break;
+ }
}
- return new GHOST_EventButton(
- system->getMilliSeconds(), type, window, mask, window->getTabletData());
+ /* Fallback cursor movement if Wintab position were never trusted while processing this event. */
+ if (!mouseMoveHandled) {
+ DWORD pos = GetMessagePos();
+ int x = GET_X_LPARAM(pos);
+ int y = GET_Y_LPARAM(pos);
+
+ /* TODO supply tablet data */
+ system->pushEvent(new GHOST_EventCursor(
+ system->getMilliSeconds(), GHOST_kEventCursorMove, window, x, y, GHOST_TABLET_DATA_NONE));
+ }
}
void GHOST_SystemWin32::processPointerEvent(
@@ -882,7 +1018,7 @@ void GHOST_SystemWin32::processPointerEvent(
{
/* Pointer events might fire when changing windows for a device which is set to use Wintab, even
* when when Wintab is left enabled but set to the bottom of Wintab overlap order. */
- if (!window->useTabletAPI(GHOST_kTabletNative)) {
+ if (!window->usingTabletAPI(GHOST_kTabletWinPointer)) {
return;
}
@@ -893,20 +1029,21 @@ void GHOST_SystemWin32::processPointerEvent(
return;
}
- if (!pointerInfo[0].isPrimary) {
- eventHandled = true;
- return; // For multi-touch displays we ignore these events
- }
-
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));
+ case WM_POINTERUPDATE:
+ /* 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));
+ }
+
+ /* Leave event unhandled so that system cursor is moved. */
+
break;
case WM_POINTERDOWN:
/* Move cursor to point of contact because GHOST_EventButton does not include position. */
@@ -922,18 +1059,10 @@ void GHOST_SystemWin32::processPointerEvent(
pointerInfo[0].buttonMask,
pointerInfo[0].tabletData));
window->updateMouseCapture(MousePressed);
- break;
- case WM_POINTERUPDATE:
- /* Coalesced pointer events are reverse chronological order, reorder chronologically.
-
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list