Commit: abbdfc8bf71f779a4c34a22a1df7bc37ae14fd4c Author: Nicholas Rishel Date: Mon Apr 20 18:46:57 2020 -0700 Branches: master https://developer.blender.org/rBabbdfc8bf71f779a4c34a22a1df7bc37ae14fd4c
Revert "Revert "Windows: support high resolution tablet pen events for Wintab"" This reverts commit e90d8422d0ed38743390f2184fde27550d7b48a7. =================================================================== 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 =================================================================== diff --git a/intern/ghost/intern/GHOST_System.h b/intern/ghost/intern/GHOST_System.h index d5b23d76016..a0d8b720ce1 100644 --- a/intern/ghost/intern/GHOST_System.h +++ b/intern/ghost/intern/GHOST_System.h @@ -237,7 +237,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); 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 08df56d295b..558143a2ead 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -941,15 +941,100 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, window->updateMouseCapture(MouseReleased); } - if (window->m_tabletInRange) { - if (window->useTabletAPI(GHOST_kTabletNative)) { + /* Check for active Wintab mouse emulation in addition to a tablet in range because a proximity + * leave event might have fired before the Windows mouse up event, thus there are still tablet + * events to grab. The described behavior was observed in a Wacom Bamboo CTE-450. + */ + if (window->m_tabletInRange || window->wintabSysButPressed()) { + if (window->useTabletAPI(GHOST_kTabletWintab) && processWintabEvents(type, window)) { + // Wintab processing only handles in-contact events. + return NULL; + } + else if (window->useTabletAPI(GHOST_kTabletNative)) { // Win32 Pointer processing handles input while in-range and in-contact events. return NULL; } + + // If using Wintab and this was a button down event but no button event was queued while + // processing Wintab packets, fall through to create a button event. } return new GHOST_EventButton( - system->getMilliSeconds(), type, window, mask, window->getTabletData()); + system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE); +} + +GHOST_TSuccess GHOST_SystemWin32::processWintabEvents(GHOST_TEventType type, + GHOST_WindowWin32 *window) +{ + GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); + + /* Only process Wintab packets if we can correlate them to a Window's mouse button event. When a + * button event associated to a mouse button by Wintab occurs outside of WM_*BUTTON events, + * there's no way to tell if other simultaneously pressed non-mouse mapped buttons are associated + * to a modifier key (shift, alt, ctrl) or a system event (scroll, etc.) and thus it is not + * possible to determine if a mouse click event should occur. + */ + if (!window->getMousePressed() && !window->wintabSysButPressed()) { + return GHOST_kFailure; + } + + std::vector<GHOST_WintabInfoWin32> wintabInfo; + if (!window->getWintabInfo(wintabInfo)) { + return GHOST_kFailure; + } + + auto wtiIter = wintabInfo.begin(); + + /* We only process events that correlate to a mouse button events, so there may exist Wintab + * button down events that were instead mapped to e.g. scroll still in the queue. We need to + * skip those and find the last button down mapped to mouse buttons. + */ + if (!window->wintabSysButPressed()) { + for (auto it = wtiIter; it != wintabInfo.end(); it++) { + if (it->type == GHOST_kEventButtonDown) { + wtiIter = it; + } + } + } + + for (; wtiIter != wintabInfo.end(); wtiIter++) { + auto info = *wtiIter; + + switch (info.type) { + case GHOST_kEventButtonDown: { + /* While changing windows with a tablet, Window's mouse button events normally occur before + * tablet proximity events, so a button up event can't be differentiated as occurring from + * a Wintab tablet or a normal mouse and a Ghost button event will always be generated. + * + * If we were called during a button down event create a ghost button down event, otherwise + * don't duplicate the prior button down as it interrupts drawing immediately after + * changing a window. + */ + if (type == GHOST_kEventButtonDown) { + // Move cursor to point of contact because GHOST_EventButton does not include position. + system->pushEvent(new GHOST_EventCursor( + info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData)); + system->pushEvent( + new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData)); + } + window->updateWintabSysBut(MousePressed); + break; + } + case GHOST_kEventCursorMove: + system->pushEvent(new GHOST_EventCursor( + info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData)); + break; + case GHOST_kEventButtonUp: + system->pushEvent( + new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData)); + window->updateWintabSysBut(MouseReleased); + break; + default: + break; + } + } + + return GHOST_kSuccess; } void GHOST_SystemWin32::processPointerEvents( @@ -1037,13 +1122,19 @@ 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)) { + if (window->m_tabletInRange || window->wintabSysButPressed()) { + if (window->useTabletAPI(GHOST_kTabletWintab) && + processWintabEvents(GHOST_kEventCursorMove, window)) { + return NULL; + } + else 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 using Wintab but no button event is currently active, fall through to default handling } system->getCursorPosition(x_screen, y_screen); @@ -1076,7 +1167,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind window, x_screen + x_accum, y_screen + y_accum, - window->getTabletData()); + GHOST_TABLET_DATA_NONE); } } else { @@ -1085,7 +1176,7 @@ GHOST_EventCursor *GHOST_SystemWin32::processCursorEvent(GHOST_WindowWin32 *wind window, x_screen, y_screen, - window->getTabletData()); + GHOST_TABLET_DATA_NONE); } return NULL; } @@ -1202,7 +1293,6 @@ GHOST_Event *GHOST_SystemWin32::processWindowEvent(GHOST_TEventType type, if (type == GHOST_kEventWindowActivate) { system->getWindowManager()->setActiveWindow(window); - window->bringTabletContextToFront(); } return new GHOST_Event(system->getMilliSeconds(), type, window); @@ -1230,6 +1320,19 @@ GHOST_TSuccess GHOST_SystemWin32::pushDragDropEvent(GHOST_TEventType eventType, system->getMilliSeconds(), eventType, draggedObjectType, window, mouseX, mouseY, data)); } +void GHOST_SystemWin32::setTabletAPI(GHOST_TTabletAPI api) +{ + GHOST_System::setTabletAPI(api); + + GHOST_WindowManager *wm = getWindowManager(); + GHOST_WindowWin32 *activeWindow = (GHOST_WindowWin32 *)wm->getActiveWindow(); + + for (GHOST_IWindow *win : wm->getWindows()) { + GHOST_WindowWin32 *windowsWindow = (GHOST_WindowWin32 *)win; + windowsWindow->updateWintab(windowsWindow == activeWindow); + } +} + void GHOST_SystemWin32::processMinMaxInfo(MINMAXINFO *minmax) { minmax->ptMinTrackSize.x = 320; @@ -1467,15 +1570,17 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, } break; //////////////////////////////////////////////////////////////////////// - // Tablet events, processed + // Wintab events, processed //////////////////////////////////////////////////////////////////////// - case WT_PACKET: - window->processWin32TabletEvent(wParam, lParam); + case WT_INFOCHANGE: { + window->processWintabInfoChangeEvent(lParam); break; - case WT_CSRCHANGE: - case WT_PROXIMITY: - window->processWin32TabletInitEvent(); + } + case WT_PROXIMITY: { + bool inRange = LOWORD(lParam); + window->processWintabProximityEvent(inRange); break; + } //////////////////////////////////////////////////////////////////////// // Pointer events, processed //////////////////////////////////////////////////////////////////////// @@ -1614,7 +1719,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, * will not be dispatched to OUR active window if we minimize one of OUR windows. */ if (LOWORD(wParam) == WA_INACTIVE) window->lostMouseCapture(); - window->processWin32TabletActivateEvent(GET_WM_ACTIVATE_STATE(wParam, lParam)); + + window->updateWintab(LOWORD(wParam) != WA_INACTIVE); + lResult = ::DefWindowProc(hwnd, msg, wParam, lParam); break; } @@ -1672,6 +1779,11 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam, else { event = processWindowEvent(GHOST_kEventWindowSize, window); } + + if (msg == WM_SIZE && wParam == SIZE_MINIMIZED) { + window->updateWintab(false); + } + break; case WM_CAPTURECHANGED: window->lostMouseCapture(); @@ -1722,6 +1834,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwn @@ Diff output truncated at 10240 characters. @@ _______________________________________________ Bf-blender-cvs mailing list Bf-blender-cvs@blender.org https://lists.blender.org/mailman/listinfo/bf-blender-cvs