Synchronize Wintab and Win32 time.
Time is synchronized by the difference between the WT_PACKET receive time and the last received PACKET's pkTime. This is used to prevent Wintab packets from being prematurely expired.
This commit is contained in:
@@ -1614,7 +1614,7 @@ LRESULT WINAPI GHOST_SystemWin32::s_wndProc(HWND hwnd, UINT msg, WPARAM wParam,
|
||||
break;
|
||||
}
|
||||
case WT_PACKET:
|
||||
window->updatePendingWintabEvents();
|
||||
window->updateWintabEventsSyncTime();
|
||||
break;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Pointer events, processed
|
||||
|
||||
@@ -1292,7 +1292,7 @@ GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin3
|
||||
|
||||
GHOST_SystemWin32 *system = (GHOST_SystemWin32 *)GHOST_System::getSystem();
|
||||
|
||||
updatePendingWintabEvents();
|
||||
updateWintabEvents();
|
||||
|
||||
auto &pendingEvents = m_wintab.pendingEvents;
|
||||
size_t pendingEventSize = pendingEvents.size();
|
||||
@@ -1388,6 +1388,44 @@ GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin3
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::updateWintabEvents()
|
||||
{
|
||||
readWintabEvents();
|
||||
// When a Wintab device is used to leave window focus, some of it's packets are periodically not
|
||||
// queued in time to be flushed. Reading packets needs to occur before expiring packets to clear
|
||||
// these from the queue.
|
||||
expireWintabEvents();
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::updateWintabEventsSyncTime()
|
||||
{
|
||||
readWintabEvents();
|
||||
|
||||
if (!m_wintab.pendingEvents.empty()) {
|
||||
auto lastEvent = m_wintab.pendingEvents.back();
|
||||
m_wintab.sysTimeOffset = ::GetTickCount() - lastEvent.pkTime;
|
||||
}
|
||||
|
||||
expireWintabEvents();
|
||||
}
|
||||
|
||||
void GHOST_WindowWin32::readWintabEvents()
|
||||
{
|
||||
if (!(m_wintab.packetsGet && m_wintab.context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &pendingEvents = m_wintab.pendingEvents;
|
||||
|
||||
/* Get new packets. */
|
||||
const int numPackets = m_wintab.packetsGet(
|
||||
m_wintab.context, m_wintab.pkts.size(), m_wintab.pkts.data());
|
||||
|
||||
for (int i = 0; i < numPackets; i++) {
|
||||
pendingEvents.push(m_wintab.pkts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Wintab (per documentation but may vary with implementation) does not update when its event
|
||||
* buffer is full. This is an issue because we need some synchronization point between Wintab
|
||||
* events and Win32 events, so we can't drain and process the queue immediately. We need to
|
||||
@@ -1396,17 +1434,12 @@ GHOST_TSuccess GHOST_WindowWin32::getWintabInfo(std::vector<GHOST_WintabInfoWin3
|
||||
* mode from the Wintab API alone. There is no guaranteed ordering between Wintab and Win32 mouse
|
||||
* events and no documented time stamp shared between the two, so we synchronize on mouse button
|
||||
* events. */
|
||||
void GHOST_WindowWin32::updatePendingWintabEvents()
|
||||
void GHOST_WindowWin32::expireWintabEvents()
|
||||
{
|
||||
if (!(m_wintab.packetsGet && m_wintab.context)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto &pendingEvents = m_wintab.pendingEvents;
|
||||
|
||||
/* Clear outdated events from queue. */
|
||||
DWORD currTime = ::GetTickCount();
|
||||
DWORD millisTimeout = 500;
|
||||
DWORD currTime = ::GetTickCount() - m_wintab.sysTimeOffset;
|
||||
DWORD millisTimeout = 300;
|
||||
while (!pendingEvents.empty()) {
|
||||
DWORD pkTime = pendingEvents.front().pkTime;
|
||||
|
||||
@@ -1417,24 +1450,6 @@ void GHOST_WindowWin32::updatePendingWintabEvents()
|
||||
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++) {
|
||||
DWORD pkTime = m_wintab.pkts[i].pkTime;
|
||||
|
||||
if (currTime < pkTime + millisTimeout) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
for (; i < numPackets; i++) {
|
||||
pendingEvents.push(m_wintab.pkts[i]);
|
||||
}
|
||||
}
|
||||
|
||||
GHOST_TUns16 GHOST_WindowWin32::getDPIHint()
|
||||
|
||||
@@ -486,9 +486,14 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
||||
GHOST_TSuccess getWintabInfo(std::vector<GHOST_WintabInfoWin32> &outWintabInfo);
|
||||
|
||||
/**
|
||||
* Updates stored pending Wintab events.
|
||||
* Updates pending Wintab events and syncs Wintab time with OS time.
|
||||
*/
|
||||
void updatePendingWintabEvents();
|
||||
void updateWintabEventsSyncTime();
|
||||
|
||||
/**
|
||||
* Updates pending Wintab events.
|
||||
*/
|
||||
void updateWintabEvents();
|
||||
|
||||
GHOST_TSuccess beginFullScreen() const
|
||||
{
|
||||
@@ -629,6 +634,7 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
||||
GHOST_TUns8 numSysButtons = 0;
|
||||
/** Cursors currently in contact mapped to system buttons */
|
||||
DWORD sysButtonsPressed = 0;
|
||||
DWORD sysTimeOffset = 0;
|
||||
LONG maxPressure = 0;
|
||||
LONG maxAzimuth = 0, maxAltitude = 0;
|
||||
/** Reusable buffer to read in Wintab Packets. */
|
||||
@@ -642,6 +648,10 @@ class GHOST_WindowWin32 : public GHOST_Window {
|
||||
*/
|
||||
void initializeWintab();
|
||||
|
||||
void readWintabEvents();
|
||||
|
||||
void expireWintabEvents();
|
||||
|
||||
/**
|
||||
* Convert Wintab system mapped (mouse) buttons into Ghost button mask.
|
||||
* \param cursor: The Wintab cursor associated to the button.
|
||||
|
||||
Reference in New Issue
Block a user