Save Wintab packets to a local queue as WT_PACKET events arrive or when

handling mouse input. This Wintab to mouse synchronization issues, and
likely prevents queue exhaustion for some Wintab implmenetations.

Signed-off-by: Nicholas Rishel <rishel.nick@gmail.com>
This commit is contained in:
Nicholas Rishel 2020-05-25 20:45:26 -07:00
parent d58387cdda
commit efe3e4f023
4 changed files with 66 additions and 5 deletions

View File

@ -234,6 +234,11 @@ GHOST_SystemWin32::~GHOST_SystemWin32()
toggleConsole(1);
}
GHOST_TUns64 GHOST_SystemWin32::millisSinceStart(__int64 ms) const
{
return (GHOST_TUns64)(ms - m_start * 1000 / m_freq);
}
GHOST_TUns64 GHOST_SystemWin32::performanceCounterToMillis(__int64 perf_ticks) const
{
// Calculate the time passed since system initialization.
@ -1591,6 +1596,9 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
window->processWintabProximityEvent(inRange);
break;
}
case WT_PACKET:
window->updatePendingWintabEvents();
break;
////////////////////////////////////////////////////////////////////////
// Pointer events, processed
////////////////////////////////////////////////////////////////////////

View File

@ -64,6 +64,8 @@ class GHOST_SystemWin32 : public GHOST_System {
** Time(r) functionality
***************************************************************************************/
GHOST_TUns64 millisSinceStart(__int64 ms) const;
/**
* This method converts performance counter measurements into milliseconds since the start of the
* system process.

View File

@ -1045,6 +1045,7 @@ void GHOST_WindowWin32::initializeWintab()
lc.lcPktData = PACKETDATA;
lc.lcPktMode = PACKETMODE;
lc.lcMoveMask = PACKETDATA;
lc.lcOptions |= CXO_MESSAGES;
// Wacom maps y origin to the tablet's bottom
// Invert to match Windows y origin mapping to the screen top
lc.lcOutExtY = -lc.lcOutExtY;
@ -1298,12 +1299,16 @@ GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin3
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
const int numPackets = m_wintab.packetsGet(
m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data());
outWintabInfo.resize(numPackets);
updatePendingWintabEvents();
auto &pendingEvents = m_wintab.pendingEvents;
size_t pendingEventSize = pendingEvents.size();
outWintabInfo.resize(pendingEventSize);
for (int i = 0; i < pendingEventSize; i++) {
PACKET pkt = pendingEvents.front();
pendingEvents.pop();
for (int i = 0; i < numPackets; i++) {
PACKET pkt = m_wintab.pkts[i];
GHOST_TabletData tabletData = GHOST_TABLET_DATA_NONE;
switch (pkt.pkCursor % 3) { /* % 3 for multiple devices ("DualTrack") */
case 0:
@ -1390,6 +1395,46 @@ GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin3
return GHOST_kSuccess;
}
void GHOST_WindowWin32::updatePendingWintabEvents()
{
if (!(m_wintab.packetsGet && m_wintab.context)) {
return;
}
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
auto &pendingEvents = m_wintab.pendingEvents;
// Clear outdated events from queue.
GHOST_TUns64 currTime = system->getMilliSeconds();
GHOST_TUns64 timeout = 300;
while (!pendingEvents.empty()) {
GHOST_TUns64 pktTime = system->millisSinceStart(pendingEvents.front().pkTime);
if (currTime - pktTime > timeout) {
pendingEvents.pop();
}
else {
break;
}
}
// Get new packets.
const int numPackets = m_wintab.packetsGet(
m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data());
int i = 0;
// Don't queue outdated packets, such events can include packets that occurred before the current
// window lost and regained focus.
for (; i < numPackets; i++) {
GHOST_TUns64 pktTime = system->millisSinceStart(m_wintab.pkts[i].pkTime);
if (currTime - pktTime < timeout) {
break;
}
}
for (; i < numPackets; i++) {
pendingEvents.push(m_wintab.pkts[i]);
}
}
GHOST_TUns16 GHOST_WindowWin32::getDPIHint()
{
if (m_user32) {

View File

@ -35,6 +35,7 @@
#endif
#include <vector>
#include <queue>
#include <wintab.h>
// PACKETDATA and PACKETMODE modify structs in pktdef.h, so make sure they come first
@ -482,6 +483,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
*/
GHOST_TSuccess getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo);
/**
*/
void updatePendingWintabEvents();
GHOST_TSuccess beginFullScreen() const
{
return GHOST_kFailure;
@ -625,6 +630,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
LONG maxAzimuth = 0, maxAltitude = 0;
/* Queue size doesn't change once set, so reuse the same buffer */
std::vector<PACKET> pkts;
std::queue<PACKET> pendingEvents;
} m_wintab;
/**