diff options
author | Nicholas Rishel <rishel.nick@gmail.com> | 2020-12-17 02:32:18 +0300 |
---|---|---|
committer | Nicholas Rishel <rishel.nick@gmail.com> | 2020-12-17 02:32:18 +0300 |
commit | 3a1d1aaa86d0d7cc6aaf0e6633d557bbcdd0b514 (patch) | |
tree | fa3aa8b33c299a792561bdec4da2dc33f62e1ac0 | |
parent | 9f588432e9dbf4dc8f0c822fdbad2f7dc4b5ca47 (diff) |
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.
-rw-r--r-- | intern/ghost/intern/GHOST_SystemWin32.cpp | 2 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.cpp | 69 | ||||
-rw-r--r-- | intern/ghost/intern/GHOST_WindowWin32.h | 14 |
3 files changed, 55 insertions, 30 deletions
diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp index d2aebab026f..2bf1d0c2d35 100644 --- a/intern/ghost/intern/GHOST_SystemWin32.cpp +++ b/intern/ghost/intern/GHOST_SystemWin32.cpp @@ -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 diff --git a/intern/ghost/intern/GHOST_WindowWin32.cpp b/intern/ghost/intern/GHOST_WindowWin32.cpp index af02663985d..a4cbf66b22d 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.cpp +++ b/intern/ghost/intern/GHOST_WindowWin32.cpp @@ -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() diff --git a/intern/ghost/intern/GHOST_WindowWin32.h b/intern/ghost/intern/GHOST_WindowWin32.h index a761d7d84dc..829bbdea051 100644 --- a/intern/ghost/intern/GHOST_WindowWin32.h +++ b/intern/ghost/intern/GHOST_WindowWin32.h @@ -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. |