aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBumjoon Park <bumjoon.park@qt.io>2022-10-21 17:36:14 +0900
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-10-28 09:20:14 +0000
commite9eb5b206bbb8cc3c85759bb8d0bce53adc21257 (patch)
tree691a02882a9d02468446da22c33c396cca96fec3
parent0c0abe8dffdd29725e0ef3175c834fd5eec49957 (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.cpp14
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp44
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"