summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2020-09-29 15:33:11 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2020-10-06 15:59:13 +0200
commit0305bfc2c686f1cd2394cd45784be47a4653680f (patch)
tree82b9c4489818de49c4ad2cd6c6b0e2aa97acf668
parent873579d157984837ba09c002978499825f45b8b1 (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.cpp48
-rw-r--r--tests/auto/gui/kernel/qwindow/tst_qwindow.cpp24
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()