Fix T84501: Wintab button lag.

Multiple Wintab tablets do not send relative button state when
configured to do so. This causes button events to be delayed until
processed as Win32 button events.

This commit fixes the issue by configuring Wintab to use absolute
button state and tracking changes manually.
This commit is contained in:
Nicholas Rishel 2021-01-10 21:13:44 -08:00
parent af88d23ffa
commit ab5986cf3a
Notes: blender-bot 2023-02-14 02:27:51 +01:00
Referenced by issue #84501, Grease Pencil Lag when using stylus in Sculpt mode
3 changed files with 49 additions and 17 deletions

View File

@ -1559,7 +1559,12 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
break;
case WT_PROXIMITY: {
if (window->useTabletAPI(GHOST_kTabletWintab)) {
window->m_tabletInRange = LOWORD(lParam);
if (LOWORD(lParam)) {
window->m_tabletInRange = true;
}
else {
window->processWintabLeave();
}
}
eventHandled = true;
break;

View File

@ -1155,16 +1155,21 @@ void GHOST_WindowWin32::setWintabOverlap(bool overlap)
/* If context is disabled, Windows Ink may be active and managing m_tabletInRange. Don't
* modify it. */
if (!(context.lcStatus & CXS_DISABLED)) {
/* Set tablet as not in range, proximity event may not occur. */
m_tabletInRange = false;
/* Clear the packet queue. */
m_wintab.packetsGet(m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data());
processWintabLeave();
}
}
}
}
}
void GHOST_WindowWin32::processWintabLeave()
{
m_tabletInRange = false;
m_wintab.buttons = 0;
/* Clear the packet queue. */
m_wintab.packetsGet(m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data());
}
void GHOST_WindowWin32::processWintabDisplayChangeEvent()
{
LOGCONTEXT lc_sys = {0}, lc_curr = {0};
@ -1327,17 +1332,32 @@ GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin3
out.tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
}
out.button = wintabMouseToGhost(pkt.pkCursor, LOWORD(pkt.pkButtons));
switch (HIWORD(pkt.pkButtons)) {
case TBN_NONE:
out.type = GHOST_kEventCursorMove;
break;
case TBN_DOWN:
out.type = GHOST_kEventButtonDown;
break;
case TBN_UP:
out.type = GHOST_kEventButtonUp;
break;
/* Some Wintab libraries don't handle relative button input, so we track button presses
* manually. */
out.button = GHOST_kButtonMaskNone;
out.type = GHOST_kEventCursorMove;
DWORD buttonsChanged = m_wintab.buttons ^ pkt.pkButtons;
if (buttonsChanged) {
/* Find the index for the changed button from the button map. */
WORD physicalButton = 0;
for (DWORD diff = (unsigned)buttonsChanged >> 1; diff > 0; diff = (unsigned)diff >> 1) {
physicalButton++;
}
out.button = wintabMouseToGhost(pkt.pkCursor, physicalButton);
if (out.button != GHOST_kButtonMaskNone) {
if (buttonsChanged & pkt.pkButtons) {
out.type = GHOST_kEventButtonDown;
}
else {
out.type = GHOST_kEventButtonUp;
}
}
/* Only update handled button, in case multiple button events arrived simultaneously. */
m_wintab.buttons ^= 1 << physicalButton;
}
out.time = system->tickCountToMillis(pkt.pkTime);

View File

@ -41,7 +41,7 @@
// PACKETDATA and PACKETMODE modify structs in pktdef.h, so make sure they come first
#define PACKETDATA \
(PK_BUTTONS | PK_NORMAL_PRESSURE | PK_ORIENTATION | PK_CURSOR | PK_X | PK_Y | PK_TIME)
#define PACKETMODE PK_BUTTONS
#define PACKETMODE 0
#include <pktdef.h>
class GHOST_SystemWin32;
@ -466,6 +466,11 @@ class GHOST_WindowWin32 : public GHOST_Window {
*/
void setWintabOverlap(bool overlap);
/**
* Resets Wintab state.
*/
void processWintabLeave();
/**
* Handle Wintab coordinate changes when DisplayChange events occur.
*/
@ -614,6 +619,8 @@ class GHOST_WindowWin32 : public GHOST_Window {
HCTX context = NULL;
/** Number of connected Wintab digitizers. */
UINT numDevices = 0;
/** Pressed button map. */
GHOST_TUns8 buttons = 0;
LONG maxPressure = 0;
LONG maxAzimuth = 0, maxAltitude = 0;
/** Reusable buffer to read in Wintab Packets. */