From 8aeed99d77b8876d42e19be7123142e5fe2d2a78 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 13 Mar 2018 15:33:44 +0100 Subject: Windows QPA: Improve tablet mode detection Change the code to detect mouse mode only the first packet after receiving the enter proximity event, using the current tablet position. This should prevent mis-detecting mouse mode due to lags, etc. There is a theoretical chance of failing to detect mouse mode should the positions match resulting in differing speeds of mouse/tablet positions, but this seems to be a negligible risk. Task-number: QTBUG-36937 Task-number: QTBUG-64781 Change-Id: I27ca4a17786164dc8b25c4614a88672e150d5fe3 Reviewed-by: Shawn Rutledge --- .../platforms/windows/qwindowstabletsupport.cpp | 32 ++++++++++++++-------- .../platforms/windows/qwindowstabletsupport.h | 15 ++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.cpp b/src/plugins/platforms/windows/qwindowstabletsupport.cpp index dcad23e446..280519d39d 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.cpp +++ b/src/plugins/platforms/windows/qwindowstabletsupport.cpp @@ -406,6 +406,7 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L qCDebug(lcQpaTablet) << "leave proximity for device #" << m_currentDevice; if (m_currentDevice < 0 || m_currentDevice >= m_devices.size()) // QTBUG-65120, spurious leave observed return false; + m_state = PenUp; if (totalPacks > 0) { QWindowSystemInterface::handleTabletLeaveProximityEvent(proximityBuffer[0].pkTime, m_devices.at(m_currentDevice).currentDevice, @@ -438,6 +439,7 @@ bool QWindowsTabletSupport::translateTabletProximityEvent(WPARAM /* wParam */, L m_devices.push_back(tabletInit(uniqueId, cursorType)); } m_devices[m_currentDevice].currentPointerType = pointerType(currentCursor); + m_state = PenProximity; qCDebug(lcQpaTablet) << "enter proximity for device #" << m_currentDevice << m_devices.at(m_currentDevice); QWindowSystemInterface::handleTabletEnterProximityEvent(proximityBuffer[0].pkTime, @@ -458,7 +460,8 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() const int currentPointer = m_devices.at(m_currentDevice).currentPointerType; const qint64 uniqueId = m_devices.at(m_currentDevice).uniqueId; - // The tablet can be used in 2 different modes, depending on it settings: + // The tablet can be used in 2 different modes (reflected in enum Mode), + // depending on its settings: // 1) Absolute (pen) mode: // The coordinates are scaled to the virtual desktop (by default). The user // can also choose to scale to the monitor or a region of the screen. @@ -473,8 +476,11 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() const QRect virtualDesktopArea = QWindowsScreen::virtualGeometry(QGuiApplication::primaryScreen()->handle()); - qCDebug(lcQpaTablet) << __FUNCTION__ << "processing " << packetCount - << "target:" << QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target; + if (QWindowsContext::verbose > 1) { + qCDebug(lcQpaTablet) << __FUNCTION__ << "processing" << packetCount + << "mode=" << m_mode << "target:" + << QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target; + } const Qt::KeyboardModifiers keyboardModifiers = QWindowsKeyMapper::queryKeyboardModifiers(); @@ -485,20 +491,24 @@ bool QWindowsTabletSupport::translateTabletPacketEvent() // This code is to delay the tablet data one cycle to sync with the mouse location. QPointF globalPosF = m_oldGlobalPosF; - m_oldGlobalPosF = m_devices.at(m_currentDevice).scaleCoordinates(packet.pkX, packet.pkY, virtualDesktopArea); + const QPointF currentGlobalPosF = + m_devices.at(m_currentDevice).scaleCoordinates(packet.pkX, packet.pkY, virtualDesktopArea); + m_oldGlobalPosF = currentGlobalPosF; QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(uniqueId).target; // Pass to window that grabbed it. - QPoint globalPos = globalPosF.toPoint(); // Get Mouse Position and compare to tablet info const QPoint mouseLocation = QWindowsCursor::mousePosition(); - - // Positions should be almost the same if we are in absolute - // mode. If they are not, use the mouse location. - if ((mouseLocation - globalPos).manhattanLength() > m_absoluteRange) { - globalPos = mouseLocation; - globalPosF = globalPos; + if (m_state == PenProximity) { + m_state = PenDown; + m_mode = (mouseLocation - currentGlobalPosF).manhattanLength() > m_absoluteRange + ? MouseMode : PenMode; + qCDebug(lcQpaTablet) << __FUNCTION__ << "mode=" << m_mode << "pen:" + << currentGlobalPosF << "mouse:" << mouseLocation; } + if (m_mode == MouseMode) + globalPosF = mouseLocation; + const QPoint globalPos = globalPosF.toPoint(); if (!target) target = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT); diff --git a/src/plugins/platforms/windows/qwindowstabletsupport.h b/src/plugins/platforms/windows/qwindowstabletsupport.h index 7878e962e1..340818c3f7 100644 --- a/src/plugins/platforms/windows/qwindowstabletsupport.h +++ b/src/plugins/platforms/windows/qwindowstabletsupport.h @@ -112,6 +112,19 @@ class QWindowsTabletSupport explicit QWindowsTabletSupport(HWND window, HCTX context); public: + enum Mode + { + PenMode, + MouseMode + }; + + enum State + { + PenUp, + PenProximity, + PenDown + }; + ~QWindowsTabletSupport(); static QWindowsTabletSupport *create(); @@ -137,6 +150,8 @@ private: QVector m_devices; int m_currentDevice; QPointF m_oldGlobalPosF; + Mode m_mode = PenMode; + State m_state = PenUp; }; QT_END_NAMESPACE -- cgit v1.2.3