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
3 changed files with 49 additions and 17 deletions

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

@ -1155,14 +1155,19 @@ void GHOST_WindowWin32::setWintabOverlap(bool overlap)
/* If context is disabled, Windows Ink may be active and managing m_tabletInRange. Don't /* If context is disabled, Windows Ink may be active and managing m_tabletInRange. Don't
* modify it. */ * modify it. */
if (!(context.lcStatus & CXS_DISABLED)) { if (!(context.lcStatus & CXS_DISABLED)) {
/* Set tablet as not in range, proximity event may not occur. */ processWintabLeave();
}
}
}
}
}
void GHOST_WindowWin32::processWintabLeave()
{
m_tabletInRange = false; m_tabletInRange = false;
m_wintab.buttons = 0;
/* Clear the packet queue. */ /* Clear the packet queue. */
m_wintab.packetsGet(m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data()); m_wintab.packetsGet(m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data());
}
}
}
}
} }
void GHOST_WindowWin32::processWintabDisplayChangeEvent() void GHOST_WindowWin32::processWintabDisplayChangeEvent()
@ -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.tabletData.Ytilt = (float)(sin(M_PI / 2.0 - azmRad) * vecLen);
} }
out.button = wintabMouseToGhost(pkt.pkCursor, LOWORD(pkt.pkButtons)); /* Some Wintab libraries don't handle relative button input, so we track button presses
switch (HIWORD(pkt.pkButtons)) { * manually. */
case TBN_NONE: out.button = GHOST_kButtonMaskNone;
out.type = GHOST_kEventCursorMove; out.type = GHOST_kEventCursorMove;
break;
case TBN_DOWN: 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; out.type = GHOST_kEventButtonDown;
break; }
case TBN_UP: else {
out.type = GHOST_kEventButtonUp; out.type = GHOST_kEventButtonUp;
break; }
}
/* Only update handled button, in case multiple button events arrived simultaneously. */
m_wintab.buttons ^= 1 << physicalButton;
} }
out.time = system->tickCountToMillis(pkt.pkTime); out.time = system->tickCountToMillis(pkt.pkTime);

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