Commit: 565ea3df6077a1af5995b9b4defec9b03f3c6c29 Author: Nicholas Rishel Date: Thu Dec 24 16:25:07 2020 -0800 Branches: master https://developer.blender.org/rB565ea3df6077a1af5995b9b4defec9b03f3c6c29
Simplification of Wintab event handling. Previously Wintab packets were added to a local queue to be processed during Win32 mouse events, in order to correlate Wintab to Win32 mouse buttons. Wintab packets before Win32 mouse down events were expired on a timer. This commit drives mouse events during Wintab events when a device is in range. When a Wintab button is found it is dispatched if an equivalent event can be popped from the Win32 event queue. If a Win32 mouse button event is not associated with a Wintab event, it falls through to WM_BUTTON handling. All Wintab packets are handled as they are received. Reviewed By: brecht Differential Revision: https://developer.blender.org/D9908 =================================================================== 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_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index 7e800619dda..d1822fe46fd 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -569,13 +569,13 @@ GHOST_TSuccess GHOST_SystemWin32::getButtons(GHOST_Buttons &buttons) const */ bool swapped = ::GetSystemMetrics(SM_SWAPBUTTON) == TRUE; - bool down = HIBYTE(::GetKeyState(VK_LBUTTON)) != 0; + bool down = HIBYTE(::GetAsyncKeyState(VK_LBUTTON)) != 0; buttons.set(swapped ? GHOST_kButtonMaskRight : GHOST_kButtonMaskLeft, down); - down = HIBYTE(::GetKeyState(VK_MBUTTON)) != 0; + down = HIBYTE(::GetAsyncKeyState(VK_MBUTTON)) != 0; buttons.set(GHOST_kButtonMaskMiddle, down); - down = HIBYTE(::GetKeyState(VK_RBUTTON)) != 0; + down = HIBYTE(::GetAsyncKeyState(VK_RBUTTON)) != 0; buttons.set(swapped ? GHOST_kButtonMaskLeft : GHOST_kButtonMaskRight, down); return GHOST_kSuccess; } @@ -939,148 +939,106 @@ GHOST_EventButton *GHOST_SystemWin32::processButtonEvent(GHOST_TEventType type, { GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); - if (type == GHOST_kEventButtonDown) { - window->updateMouseCapture(MousePressed); - } - else if (type == GHOST_kEventButtonUp) { - window->updateMouseCapture(MouseReleased); - } + GHOST_TabletData td = window->m_tabletInRange ? window->getLastTabletData() : + GHOST_TABLET_DATA_NONE; - /* 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->useTabletAPI(GHOST_kTabletWintab) && - (window->m_tabletInRange || window->wintabSysButPressed()) && - processWintabEvent(type, window, mask, window->getMousePressed())) { - /* Wintab processing only handles in-contact events. */ - return NULL; - } + /* Ensure button click occurs at its intended position. */ + DWORD msgPos = ::GetMessagePos(); + GHOST_TInt32 x_screen = GET_X_LPARAM(msgPos), y_screen = GET_Y_LPARAM(msgPos); + system->pushEvent(new GHOST_EventCursor( + system->getMilliSeconds(), GHOST_kEventCursorMove, window, x_screen, y_screen, td)); - return new GHOST_EventButton( - system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE); + window->updateMouseCapture(type == GHOST_kEventButtonDown ? MousePressed : MouseReleased); + return new GHOST_EventButton(system->getMilliSeconds(), type, window, mask, td); } -GHOST_TSuccess GHOST_SystemWin32::processWintabEvent(GHOST_TEventType type, - GHOST_WindowWin32 *window, - GHOST_TButtonMask mask, - bool mousePressed) +void GHOST_SystemWin32::processWintabEvent(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 (!mousePressed && !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()) { - /* Assume there may be no button down event currently in the queue. */ - wtiIter = wintabInfo.end(); - - for (auto it = wintabInfo.begin(); it != wintabInfo.end(); it++) { - if (it->type == GHOST_kEventButtonDown) { - wtiIter = it; - } - } + return; } - bool unhandledButton = type != GHOST_kEventCursorMove; - - for (; wtiIter != wintabInfo.end(); wtiIter++) { - auto info = *wtiIter; - + for (auto info : wintabInfo) { switch (info.type) { + case GHOST_kEventCursorMove: { + system->pushEvent(new GHOST_EventCursor( + info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData)); + break; + } 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. */ system->pushEvent(new GHOST_EventCursor( info.time, GHOST_kEventCursorMove, window, info.x, info.y, info.tabletData)); - if (type == GHOST_kEventButtonDown && mask == info.button) { + + 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_REMOVE | PM_NOYIELD) && + WM_QUIT != msg.message) { + window->updateMouseCapture(MousePressed); system->pushEvent( new GHOST_EventButton(info.time, info.type, window, info.button, info.tabletData)); - unhandledButton = false; } - 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)); - if (type == GHOST_kEventButtonUp && mask == info.button) { - unhandledButton = false; + case GHOST_kEventButtonUp: { + 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)); } - window->updateWintabSysBut(MouseReleased); break; + } default: break; } } - - /* No Wintab button found correlating to the system button event, handle it too. - * - * Wintab button up events may be handled during WM_MOUSEMOVE, before their corresponding - * WM_*BUTTONUP event has fired, which results in two GHOST Button up events for a single Wintab - * associated button event. Alternatively this Windows button up event may have been generated - * from a non-stylus device such as a button on the tablet pad and needs to be handled for some - * workflows. - * - * The ambiguity introduced by Windows and Wintab buttons being asynchronous and having no - * definitive way to associate each, and that the Wintab API does not provide enough information - * to differentiate whether the stylus down is or is not modified by another button to a - * non-mouse mapping, means that we must pessimistically generate mouse up events when we are - * unsure of an association to prevent the mouse locking into a down state. */ - if (unhandledButton) { - if (!window->wintabSysButPressed()) { - GHOST_TInt32 x, y; - system->getCursorPosition(x, y); - system->pushEvent(new GHOST_EventCursor(system->getMilliSeconds(), - GHOST_kEventCursorMove, - window, - x, - y, - GHOST_TABLET_DATA_NONE)); - } - system->pushEvent(new GHOST_EventButton( - system->getMilliSeconds(), type, window, mask, GHOST_TABLET_DATA_NONE)); - } - - return GHOST_kSuccess; } void GHOST_SystemWin32::processPointerEvent( UINT type, GHOST_WindowWin32 *window, WPARAM wParam, LPARAM lParam, bool &eventHandled) { - std::vector<GHOST_PointerInfoWin32> pointerInfo; - GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); - /* 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)) { return; } + GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)getSystem(); + std::vector<GHOST_PointerInfoWin32> pointerInfo; + if (window->getPointerInfo(pointerInfo, wParam, lParam) != GHOST_kSuccess) { retu @@ 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