diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-09-29 15:33:11 +0200 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-10-06 15:59:13 +0200 |
commit | 0305bfc2c686f1cd2394cd45784be47a4653680f (patch) | |
tree | 82b9c4489818de49c4ad2cd6c6b0e2aa97acf668 | |
parent | 873579d157984837ba09c002978499825f45b8b1 (diff) |
End touch->mouse synthesis when the chosen touchpoint is released
During delivery of a TouchBegin event, if no widget accepts it,
we begin treating the first touchpoint as a synth-mouse, as before.
If a second touchpoint is pressed or released in any order, it's
irrelevant: the fake mouse button is released as soon as the first
touchpoint is released. This fixes the bug that such a scenario
caused the mouse release not to be sent, so that a widget could get
"stuck" in pressed state.
Done-with: Tang Haixiang <tanghaixiang@uniontech.com>
Fixes: QTBUG-86253
Change-Id: I7fbbe120539d8ded8ef5e7cf712a27bd69391e02
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
(cherry picked from commit f51e6552e361c0716f6301b4c5b03b12e8bfe0fe)
Reviewed-by: Tor Arne Vestbø <tor.arne.vestbo@qt.io>
-rw-r--r-- | src/gui/kernel/qguiapplication.cpp | 48 | ||||
-rw-r--r-- | tests/auto/gui/kernel/qwindow/tst_qwindow.cpp | 24 |
2 files changed, 49 insertions, 23 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 72e1b16e55..a95331e246 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -201,7 +201,7 @@ static bool force_reverse = false; QGuiApplicationPrivate *QGuiApplicationPrivate::self = nullptr; QTouchDevice *QGuiApplicationPrivate::m_fakeTouchDevice = nullptr; -int QGuiApplicationPrivate::m_fakeMouseSourcePointId = 0; +int QGuiApplicationPrivate::m_fakeMouseSourcePointId = -1; #ifndef QT_NO_CLIPBOARD QClipboard *QGuiApplicationPrivate::qt_clipboard = nullptr; @@ -3057,32 +3057,32 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To if (!e->synthetic() && !touchEvent.isAccepted() && qApp->testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) { // exclude devices which generate their own mouse events if (!(touchEvent.device()->capabilities() & QTouchDevice::MouseEmulation)) { - - if (eventType == QEvent::TouchEnd) - self->synthesizedMousePoints.clear(); - const QList<QTouchEvent::TouchPoint> &touchPoints = touchEvent.touchPoints(); - if (eventType == QEvent::TouchBegin) + QEvent::Type mouseEventType = QEvent::MouseMove; + Qt::MouseButton button = Qt::NoButton; + Qt::MouseButtons buttons = Qt::LeftButton; + if (eventType == QEvent::TouchBegin && m_fakeMouseSourcePointId < 0) m_fakeMouseSourcePointId = touchPoints.first().id(); - - const QEvent::Type mouseType = [&]() { - switch (eventType) { - case QEvent::TouchBegin: return QEvent::MouseButtonPress; - case QEvent::TouchUpdate: return QEvent::MouseMove; - case QEvent::TouchEnd: return QEvent::MouseButtonRelease; - default: Q_UNREACHABLE(); - } - }(); - - Qt::MouseButton button = mouseType == QEvent::MouseMove ? Qt::NoButton : Qt::LeftButton; - Qt::MouseButtons buttons = mouseType == QEvent::MouseButtonRelease ? Qt::NoButton : Qt::LeftButton; - - for (int i = 0; i < touchPoints.count(); ++i) { - const QTouchEvent::TouchPoint &touchPoint = touchPoints.at(i); + for (const auto &touchPoint : touchPoints) { if (touchPoint.id() == m_fakeMouseSourcePointId) { - if (eventType != QEvent::TouchEnd) + switch (touchPoint.state()) { + case Qt::TouchPointPressed: + mouseEventType = QEvent::MouseButtonPress; + button = Qt::LeftButton; + break; + case Qt::TouchPointReleased: + mouseEventType = QEvent::MouseButtonRelease; + button = Qt::LeftButton; + buttons = Qt::NoButton; + m_fakeMouseSourcePointId = -1; + break; + default: + break; + } + if (touchPoint.state() != Qt::TouchPointReleased) { self->synthesizedMousePoints.insert(w, SynthesizedMouseData( touchPoint.pos(), touchPoint.screenPos(), w)); + } // All touch events that are not accepted by the application will be translated to // left mouse button events instead (see AA_SynthesizeMouseForUnhandledTouchEvents docs). QWindowSystemInterfacePrivate::MouseEvent fake(w, e->timestamp, @@ -3091,13 +3091,15 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To buttons, e->modifiers, button, - mouseType, + mouseEventType, Qt::MouseEventSynthesizedByQt); fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic; processMouseEvent(&fake); break; } } + if (eventType == QEvent::TouchEnd) + self->synthesizedMousePoints.clear(); } } } diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index 34de756ab5..2292462046 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -1176,6 +1176,30 @@ void tst_QWindow::touchToMouseTranslation() // mouse event synthesizing disabled QTRY_COMPARE(window.mousePressButton, 0); QTRY_COMPARE(window.mouseReleaseButton, 0); + + points.clear(); + points.append(tp2); + points[0].state = Qt::TouchPointPressed; + QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); + QCoreApplication::processEvents(); + points.clear(); + points.append(tp1); + points[0].state = Qt::TouchPointPressed; + QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); + QCoreApplication::processEvents(); + QTRY_COMPARE(window.mousePressButton, 1); + + points.clear(); + points.append(tp2); + points[0].state = Qt::TouchPointReleased; + QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); + QCoreApplication::processEvents(); + points.clear(); + points.append(tp1); + points[0].state = Qt::TouchPointReleased; + QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); + QCoreApplication::processEvents(); + QTRY_COMPARE(window.mouseReleaseButton, 1); } void tst_QWindow::touchToMouseTranslationForDevices() |