diff options
author | Bumjoon Park <bumjoon.park@qt.io> | 2022-10-21 17:36:14 +0900 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-10-28 09:20:14 +0000 |
commit | e9eb5b206bbb8cc3c85759bb8d0bce53adc21257 (patch) | |
tree | 691a02882a9d02468446da22c33c396cca96fec3 | |
parent | 0c0abe8dffdd29725e0ef3175c834fd5eec49957 (diff) |
Don't accept all QTouchEvent::points unless the item accepts touch
An items that handles touch events can accept multiple touchpoints; but
after visiting an item that does not handle events at all, or that
relies on synth-mouse events, let the remaining touchpoints continue
propagating. Do not automatically accept all touchpoints just because
an item accepted a synth-mouse event, and do not auto-grab other
touchpoints besides the touchmouse point.
Done-with: Shawn Rutledge
Fixes: QTBUG-107867
Change-Id: I6c342487a4f8bacbd84e6d7e0e7c00884791a610
Reviewed-by: Shawn Rutledge <shawn.rutledge@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
(cherry picked from commit 5ced8ec177fd730676eb854aea559a5f324a39b6)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r-- | src/quick/util/qquickdeliveryagent.cpp | 14 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/tst_touchmouse.cpp | 44 |
2 files changed, 50 insertions, 8 deletions
diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp index ba16b4ab61..90d154ff5d 100644 --- a/src/quick/util/qquickdeliveryagent.cpp +++ b/src/quick/util/qquickdeliveryagent.cpp @@ -2147,18 +2147,16 @@ void QQuickDeliveryAgentPrivate::deliverMatchingPointsToItem(QQuickItem *item, b qCDebug(lcTouch) << "actually delivering" << &touchEvent << " to " << item; QCoreApplication::sendEvent(item, &touchEvent); eventAccepted = touchEvent.isAccepted(); - } else if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents))) { + } else { // If the touch event wasn't accepted, synthesize a mouse event and see if the item wants it. - if (!eventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) { - // send mouse event - if (deliverTouchAsMouse(item, &touchEvent)) - eventAccepted = true; - } + if (Q_LIKELY(QCoreApplication::testAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents)) && + !eventAccepted && (itemPrivate->acceptedMouseButtons() & Qt::LeftButton)) + deliverTouchAsMouse(item, &touchEvent); + return; } + Q_ASSERT(item->acceptTouchEvents()); // else we would've returned early above if (eventAccepted) { - // If the touch was accepted (regardless by whom or in what form), - // update accepted new points. bool isPressOrRelease = pointerEvent->isBeginEvent() || pointerEvent->isEndEvent(); for (int i = 0; i < touchEvent.pointCount(); ++i) { auto &point = touchEvent.point(i); diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp index e595175fee..f03af6660d 100644 --- a/tests/auto/quick/touchmouse/tst_touchmouse.cpp +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -166,12 +166,14 @@ class GrabMonitor : public QObject { public: QObject *exclusiveGrabber = nullptr; + int transitionCount = 0; bool fromMouseEvent = false; bool canceled = false; void onGrabChanged(QObject *grabber, QPointingDevice::GrabTransition transition, const QPointerEvent *event, const QEventPoint &point) { qCDebug(lcTests) << grabber << transition << event << point << point.device(); + ++transitionCount; switch (transition) { case QPointingDevice::GrabTransition::GrabExclusive: exclusiveGrabber = grabber; @@ -232,6 +234,8 @@ private slots: void oneTouchInsideAndOneOutside(); + void strayTouchDoesntAutograb(); + protected: bool eventFilter(QObject *, QEvent *event) override { @@ -1600,6 +1604,46 @@ void tst_TouchMouse::oneTouchInsideAndOneOutside() // QTBUG-102996 QQuickTouchUtils::flush(&window); } +void tst_TouchMouse::strayTouchDoesntAutograb() // QTBUG-107867 +{ + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("singleitem.qml"))); + QQuickItem *root = window.rootObject(); + QVERIFY(root); + EventItem *eventItem = root->findChild<EventItem*>(); + QVERIFY(eventItem); + // This item accepts (synth-)mouse events but NOT touch + eventItem->acceptMouse = true; + QCOMPARE(eventItem->acceptTouchEvents(), false); // the default in Qt 6 + QPoint p1(6, 6); + + // Begin a new touch, that gets converted to a mouse press + QTest::touchEvent(&window, device).press(0, p1); + QQuickTouchUtils::flush(&window); + qCDebug(lcTests) << "after touch press:" << eventItem->eventList; + QCOMPARE(eventItem->eventList.size(), 1); + QCOMPARE(eventItem->eventList.at(0).type, QEvent::MouseButtonPress); + QCOMPARE(grabMonitor.exclusiveGrabber, eventItem); + + // Drag + for (int i = 0; i < 3; ++i) { + QTest::touchEvent(&window, device).move(0, p1 + QPoint(i * 5, i * 5), &window); + QQuickTouchUtils::flush(&window); + QCOMPARE(grabMonitor.transitionCount, 1); // no new grab + QCOMPARE(eventItem->eventList.size(), i + 2); + QCOMPARE(eventItem->eventList.last().type, QEvent::MouseMove); + } + + // Press an extra point: EventItem should see nothing + QTest::touchEvent(&window, device).stationary(0).press(1, p1); + QQuickTouchUtils::flush(&window); + qCDebug(lcTests) << "after press of second touchpoint:" << eventItem->eventList; + QCOMPARE(eventItem->eventList.size(), 4); + QCOMPARE(grabMonitor.transitionCount, 1); // no new grab + + QTest::touchEvent(&window, device).release(0, p1).release(1, p1); +} + QTEST_MAIN(tst_TouchMouse) #include "tst_touchmouse.moc" |