Commit: 85defa5e2c5d4ef15a1ade1d052fcded501fbc39 Author: Nicholas Rishel Date: Thu Mar 4 15:48:48 2021 -0800 Branches: wintab-high-frequency https://developer.blender.org/rB85defa5e2c5d4ef15a1ade1d052fcded501fbc39
Refactor of Wintab to use Wintab supplied mouse movement once verified against system input. Differential Revision: https://developer.blender.org/D11508 =================================================================== M intern/ghost/CMakeLists.txt 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 =================================================================== 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/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 c3a243cc22c..c06f46520b3 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -867,15 +867,135 @@ 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); + + bool mouseUpdated = wt->trustCoordinates(); + + for (auto info : wintabInfo) { + switch (info.type) { + case GHOST_kEventCursorMove: { + if (!wt->trustCoordinates()) { + 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: { + /* 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. */ + 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; + } + + MSG msg; + if (PeekMessage(&msg, window->getHWND(), message, message, PM_NOYIELD) && + WM_QUIT != msg.message) { + if (wt->testCoordinates(msg.pt.x, msg.pt.y, info.x, info.y)) { + 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)); + + mouseUpdated = true; + } + } + break; + } + case GHOST_kEventButtonUp: { + if (!wt->trustCoordinates()) { + 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. */ + 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; + } + + MSG msg; + if (PeekMessage(&msg, window->getHWND(), message, message, PM_REMOVE | PM_NOYIELD) && + WM_QUIT != msg.message) { + 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 mouse movement if Wintab provided coodinates are untrusted. */ + if (!mouseUpdated) { + 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( @@ -894,20 +1014,18 @@ 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)); + } break; case WM_POINTERDOWN: /* Move cursor to point of contact because GHOST_EventButton does not include position. */ @@ -924,18 +1042,6 @@ void GHOST_SystemWin32::processPointerEvent( pointerInfo[0].tabletData)); window->updateMouseCapture(MousePressed); break; - 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)); - } - break; case WM_POINTERUP: system->pushEvent(new GHOST_EventButton(pointerInfo[0].time, GHOST_kEventButtonUp, @@ -944,9 +1050,6 @@ void GHOST_SystemWin32::processPointerEvent( pointerInfo[0].tabletData)); window->updateMouseCapture(MouseReleased); break; - case WM_POINTERLEAVE: - window->m_tabletInRange = false; - break; default: break; } @@ -960,18 +1063,16 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind GHOST_TInt32 x_screen, y_screen; GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); - 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; - } + if (window->getTabletData().Active != GHOST_kTabletModeNone) { + /* Tablet input handled in WM_POINTER* eve @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org List details, subscription details or unsubscribe: https://lists.blender.org/mailman/listinfo/bf-blender-cvs