summaryrefslogtreecommitdiffstats
path: root/src/gui/kernel/qguiapplication.cpp
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-02 14:17:44 +0200
commitf51e6552e361c0716f6301b4c5b03b12e8bfe0fe (patch)
treecf4f7e242ba4cebb600b91b7e4e8c7773e56ea48 /src/gui/kernel/qguiapplication.cpp
parentc3b0828e3bc60a621a7caf3c04eb790811a3dd1b (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 Pick-to: 5.15 Change-Id: I7fbbe120539d8ded8ef5e7cf712a27bd69391e02 Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/gui/kernel/qguiapplication.cpp')
-rw-r--r--src/gui/kernel/qguiapplication.cpp60
1 files changed, 33 insertions, 27 deletions
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index a022e9a151..627cf9dba1 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -189,7 +189,7 @@ static Qt::LayoutDirection layout_direction = Qt::LayoutDirectionAuto;
static bool force_reverse = false;
QGuiApplicationPrivate *QGuiApplicationPrivate::self = nullptr;
-int QGuiApplicationPrivate::m_fakeMouseSourcePointId = 0;
+int QGuiApplicationPrivate::m_fakeMouseSourcePointId = -1;
#ifndef QT_NO_CLIPBOARD
QClipboard *QGuiApplicationPrivate::qt_clipboard = nullptr;
@@ -2950,7 +2950,6 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
for (QMutableTouchEvent &touchEvent : touchEvents) {
QWindow *window = static_cast<QWindow *>(touchEvent.target());
- auto &points = touchEvent.points();
QEvent::Type eventType;
switch (touchEvent.touchPointStates()) {
@@ -2985,47 +2984,54 @@ void QGuiApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::To
// exclude devices which generate their own mouse events
if (!(touchEvent.device()->capabilities().testFlag(QInputDevice::Capability::MouseEmulation))) {
- if (eventType == QEvent::TouchEnd)
- self->synthesizedMousePoints.clear();
-
- 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 = touchEvent.point(0).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 (const QEventPoint &touchPoint : points) {
- if (touchPoint.id() == m_fakeMouseSourcePointId) {
- if (eventType != QEvent::TouchEnd)
+ qCDebug(lcPtrDispatch) << "synthesizing mouse events from touchpoint" << m_fakeMouseSourcePointId;
+ }
+ if (m_fakeMouseSourcePointId >= 0) {
+ const auto *touchPoint = touchEvent.pointById(m_fakeMouseSourcePointId);
+ if (touchPoint) {
+ switch (touchPoint->state()) {
+ case QEventPoint::State::Pressed:
+ mouseEventType = QEvent::MouseButtonPress;
+ button = Qt::LeftButton;
+ break;
+ case QEventPoint::State::Released:
+ mouseEventType = QEvent::MouseButtonRelease;
+ button = Qt::LeftButton;
+ buttons = Qt::NoButton;
+ Q_ASSERT(m_fakeMouseSourcePointId == touchPoint->id());
+ m_fakeMouseSourcePointId = -1;
+ break;
+ default:
+ break;
+ }
+ if (touchPoint->state() != QEventPoint::State::Released) {
self->synthesizedMousePoints.insert(window, SynthesizedMouseData(
- touchPoint.position(), touchPoint.globalPosition(), window));
+ touchPoint->position(), touchPoint->globalPosition(), window));
+ }
// All touch events that are not accepted by the application will be translated to
// left mouse button events instead (see AA_SynthesizeMouseForUnhandledTouchEvents docs).
// TODO why go through QPA? Why not just send a QMouseEvent right from here?
QWindowSystemInterfacePrivate::MouseEvent fake(window, e->timestamp,
- touchPoint.position(),
- touchPoint.globalPosition(),
+ touchPoint->position(),
+ touchPoint->globalPosition(),
buttons,
e->modifiers,
button,
- mouseType,
+ mouseEventType,
Qt::MouseEventSynthesizedByQt,
false,
device);
fake.flags |= QWindowSystemInterfacePrivate::WindowSystemEvent::Synthetic;
processMouseEvent(&fake);
- break;
}
}
+ if (eventType == QEvent::TouchEnd)
+ self->synthesizedMousePoints.clear();
}
}
}