diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-11-27 08:59:20 +0100 |
---|---|---|
committer | Shawn Rutledge <shawn.rutledge@qt.io> | 2020-11-30 18:16:26 +0100 |
commit | 1e1674849a89db54cdbcc4e995300e3ec1624c3a (patch) | |
tree | 535cf0bf75be5a75d40c3db518991e5fc38887b2 /tests/auto/quick/pointerhandlers | |
parent | e2a74579850d89d229dad918404a8d8ecebb80b3 (diff) |
Allow parent to filter out-of-bounds synth-mouse for grabbing handler
Consider
Flickable {
Text {
TapHandler { gesturePolicy: TapHandler.ReleaseWithinBounds }
}
}
On press, TapHandler gets the exclusive grab. Now drag vertically.
The Text is short in stature, so your finger soon strays out of bounds
of the Text, likely before you have dragged past the drag threshold.
In this case, we want Flickable to continue to filter the move events
because of the fact that TapHandler is the grabber. If it was a
MouseArea instead of a TapHandler, it already worked that way; so this
makes behavior of handlers more consistent with that.
More specifically: QQuickPointerTouchEvent::touchEventForItem() now
generates a touch event even if the touchpoint is not within the bounds
of the given item, but is grabbed by one of that item's handlers. Until
now, we had that exception only if it was grabbed by the item itself.
tst_FlickableInterop::touchAndDragHandlerOnFlickable now always drags
the delegate at index 2 (the third one) from its upper-right corner,
upwards and to the left. The first drag goes outside the delegate's
bounds, but the Flickable/ListView/TableView filters and takes over
anyway (on the next drag), to prove that it is correctly depending
on the grab that the TapHandler (or DragHandler) took on press.
Pick-to: 5.15
Pick-to: 6.0
Fixes: QTBUG-75223
Change-Id: Ie4e22c87be0af9aa3ff0146067b7705949b15c40
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'tests/auto/quick/pointerhandlers')
5 files changed, 54 insertions, 40 deletions
diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml index 92f3a45e7e..00f3d66049 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml +++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnList.qml @@ -64,7 +64,7 @@ ListView { id: buttonDrag objectName: "buttonDrag" } - Component.onCompleted: if (!root.buttonUnderTest) { + Component.onCompleted: if (!root.buttonUnderTest && index == 2) { root.buttonUnderTest = this root.delegateUnderTest = parent } diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml index 1726c1019a..ee63c1aa79 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml +++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/dragOnTable.qml @@ -68,7 +68,7 @@ TableView { id: buttonDrag objectName: "buttonDrag" } - Component.onCompleted: if (!root.buttonUnderTest) { + Component.onCompleted: if (!root.buttonUnderTest && index == 2) { root.buttonUnderTest = this root.delegateUnderTest = parent } diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml index aeab188e98..2ad92e8b71 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml +++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnList.qml @@ -48,11 +48,12 @@ ListView { } delegate: Rectangle { - objectName: "itemview delegate" + objectName: "itemview delegate " + index color: delegateTap.pressed ? "wheat" : "beige" width: parent.width; height: 140 + Text { text: index } Rectangle { - objectName: "button" + objectName: "button " + index anchors.centerIn: parent border.color: "tomato" border.width: 10 @@ -61,16 +62,16 @@ ListView { height: 100 TapHandler { id: innerTap - objectName: "buttonTap" + objectName: "buttonTap " + index } - Component.onCompleted: if (!root.buttonUnderTest) { + Component.onCompleted: if (!root.buttonUnderTest && index == 2) { root.buttonUnderTest = this root.delegateUnderTest = parent } } TapHandler { id: delegateTap - objectName: "delegateTap" + objectName: "delegateTap " + index } } diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml index e1ff75410f..46b01ee577 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml +++ b/tests/auto/quick/pointerhandlers/flickableinterop/data/tapOnTable.qml @@ -68,7 +68,7 @@ TableView { id: innerTap objectName: "buttonTap" } - Component.onCompleted: if (!root.buttonUnderTest) { + Component.onCompleted: if (!root.buttonUnderTest && index == 2) { root.buttonUnderTest = this root.delegateUnderTest = parent } diff --git a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp index 2cdbaf3bf6..869ba80658 100644 --- a/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp +++ b/tests/auto/quick/pointerhandlers/flickableinterop/tst_flickableinterop.cpp @@ -664,30 +664,36 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable_data() QTest::addColumn<QByteArray>("qmlFile"); QTest::addColumn<bool>("pressDelay"); QTest::addColumn<bool>("targetNull"); - QTest::newRow("tapOnFlickable") << QByteArray("tapOnFlickable.qml") << false << false; - QTest::newRow("tapOnList") << QByteArray("tapOnList.qml") << false << false; - QTest::newRow("tapOnTable") << QByteArray("tapOnTable.qml") << false << false; - QTest::newRow("dragOnFlickable") << QByteArray("dragOnFlickable.qml") << false << false; - QTest::newRow("dragOnList") << QByteArray("dragOnList.qml") << false << false; - QTest::newRow("dragOnTable") << QByteArray("dragOnTable.qml") << false << false; - QTest::newRow("tapDelayOnFlickable") << QByteArray("tapOnFlickable.qml") << true << false; - QTest::newRow("tapDelayOnList") << QByteArray("tapOnList.qml") << true << false; - QTest::newRow("tapDelayOnTable") << QByteArray("tapOnTable.qml") << true << false; - QTest::newRow("dragDelayOnFlickable") << QByteArray("dragOnFlickable.qml") << true << false; - QTest::newRow("dragDelayOnList") << QByteArray("dragOnList.qml") << true << false; - QTest::newRow("dragDelayOnTable") << QByteArray("dragOnTable.qml") << true << false; - QTest::newRow("tapOnFlickableWithNullTargets") << QByteArray("tapOnFlickable.qml") << false << true; - QTest::newRow("tapOnListWithNullTargets") << QByteArray("tapOnList.qml") << false << true; - QTest::newRow("tapOnTableWithNullTargets") << QByteArray("tapOnTable.qml") << false << true; - QTest::newRow("dragOnFlickableWithNullTargets") << QByteArray("dragOnFlickable.qml") << false << true; - QTest::newRow("dragOnListWithNullTargets") << QByteArray("dragOnList.qml") << false << true; - QTest::newRow("dragOnTableWithNullTargets") << QByteArray("dragOnTable.qml") << false << true; - QTest::newRow("tapDelayOnFlickableWithNullTargets") << QByteArray("tapOnFlickable.qml") << true << true; - QTest::newRow("tapDelayOnListWithNullTargets") << QByteArray("tapOnList.qml") << true << true; - QTest::newRow("tapDelayOnTableWithNullTargets") << QByteArray("tapOnTable.qml") << true << true; - QTest::newRow("dragDelayOnFlickableWithNullTargets") << QByteArray("dragOnFlickable.qml") << true << true; - QTest::newRow("dragDelayOnListWithNullTargets") << QByteArray("dragOnList.qml") << true << true; - QTest::newRow("dragDelayOnTableWithNullTargets") << QByteArray("dragOnTable.qml") << true << true; + QTest::addColumn<QQuickTapHandler::GesturePolicy>("tapGesturePolicy"); + QTest::newRow("tapOnFlickable") << QByteArray("tapOnFlickable.qml") << false << false << QQuickTapHandler::DragThreshold; + QTest::newRow("tapOnFlickable-excl") << QByteArray("tapOnFlickable.qml") << false << false << QQuickTapHandler::ReleaseWithinBounds; + QTest::newRow("tapOnList") << QByteArray("tapOnList.qml") << false << false << QQuickTapHandler::DragThreshold; + // QTBUG-75223 + QTest::newRow("tapOnList-excl") << QByteArray("tapOnList.qml") << false << false << QQuickTapHandler::ReleaseWithinBounds; + QTest::newRow("tapOnTable") << QByteArray("tapOnTable.qml") << false << false << QQuickTapHandler::DragThreshold; + QTest::newRow("dragOnFlickable") << QByteArray("dragOnFlickable.qml") << false << false << QQuickTapHandler::DragThreshold; + QTest::newRow("dragOnList") << QByteArray("dragOnList.qml") << false << false << QQuickTapHandler::DragThreshold; + QTest::newRow("dragOnTable") << QByteArray("dragOnTable.qml") << false << false << QQuickTapHandler::DragThreshold; + QTest::newRow("tapDelayOnFlickable") << QByteArray("tapOnFlickable.qml") << true << false << QQuickTapHandler::DragThreshold; + QTest::newRow("tapDelayOnFlickable-excl") << QByteArray("tapOnFlickable.qml") << true << false << QQuickTapHandler::ReleaseWithinBounds; + QTest::newRow("tapDelayOnList") << QByteArray("tapOnList.qml") << true << false << QQuickTapHandler::DragThreshold; + QTest::newRow("tapDelayOnList-excl") << QByteArray("tapOnList.qml") << true << false << QQuickTapHandler::ReleaseWithinBounds; + QTest::newRow("tapDelayOnTable") << QByteArray("tapOnTable.qml") << true << false << QQuickTapHandler::DragThreshold; + QTest::newRow("dragDelayOnFlickable") << QByteArray("dragOnFlickable.qml") << true << false << QQuickTapHandler::DragThreshold; + QTest::newRow("dragDelayOnList") << QByteArray("dragOnList.qml") << true << false << QQuickTapHandler::DragThreshold; + QTest::newRow("dragDelayOnTable") << QByteArray("dragOnTable.qml") << true << false << QQuickTapHandler::DragThreshold; + QTest::newRow("tapOnFlickableWithNullTargets") << QByteArray("tapOnFlickable.qml") << false << true << QQuickTapHandler::DragThreshold; + QTest::newRow("tapOnListWithNullTargets") << QByteArray("tapOnList.qml") << false << true << QQuickTapHandler::DragThreshold; + QTest::newRow("tapOnTableWithNullTargets") << QByteArray("tapOnTable.qml") << false << true << QQuickTapHandler::DragThreshold; + QTest::newRow("dragOnFlickableWithNullTargets") << QByteArray("dragOnFlickable.qml") << false << true << QQuickTapHandler::DragThreshold; + QTest::newRow("dragOnListWithNullTargets") << QByteArray("dragOnList.qml") << false << true << QQuickTapHandler::DragThreshold; + QTest::newRow("dragOnTableWithNullTargets") << QByteArray("dragOnTable.qml") << false << true << QQuickTapHandler::DragThreshold; + QTest::newRow("tapDelayOnFlickableWithNullTargets") << QByteArray("tapOnFlickable.qml") << true << true << QQuickTapHandler::DragThreshold; + QTest::newRow("tapDelayOnListWithNullTargets") << QByteArray("tapOnList.qml") << true << true << QQuickTapHandler::DragThreshold; + QTest::newRow("tapDelayOnTableWithNullTargets") << QByteArray("tapOnTable.qml") << true << true << QQuickTapHandler::DragThreshold; + QTest::newRow("dragDelayOnFlickableWithNullTargets") << QByteArray("dragOnFlickable.qml") << true << true << QQuickTapHandler::DragThreshold; + QTest::newRow("dragDelayOnListWithNullTargets") << QByteArray("dragOnList.qml") << true << true << QQuickTapHandler::DragThreshold; + QTest::newRow("dragDelayOnTableWithNullTargets") << QByteArray("dragOnTable.qml") << true << true << QQuickTapHandler::DragThreshold; } void tst_FlickableInterop::touchAndDragHandlerOnFlickable() @@ -695,6 +701,7 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable() QFETCH(QByteArray, qmlFile); QFETCH(bool, pressDelay); QFETCH(bool, targetNull); + QFETCH(QQuickTapHandler::GesturePolicy, tapGesturePolicy); const int dragThreshold = QGuiApplication::styleHints()->startDragDistance(); QScopedPointer<QQuickView> windowPtr; @@ -703,11 +710,7 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable() QQuickFlickable *flickable = qmlobject_cast<QQuickFlickable*>(window->rootObject()); QVERIFY(flickable); flickable->setPressDelay(pressDelay ? 5000 : 0); - QQuickItem *delegate = nullptr; - if (QQuickItemView *itemView = qmlobject_cast<QQuickItemView *>(flickable)) - delegate = itemView->currentItem(); - if (!delegate) - delegate = flickable->property("delegateUnderTest").value<QQuickItem*>(); + QQuickItem *delegate = flickable->property("delegateUnderTest").value<QQuickItem*>(); QQuickItem *button = delegate ? delegate->findChild<QQuickItem*>("button") : flickable->findChild<QQuickItem*>("button"); if (!button) @@ -716,8 +719,13 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable() QQuickPointerHandler *buttonHandler = button->findChild<QQuickPointerHandler*>(); QVERIFY(buttonHandler); QQuickTapHandler *buttonTapHandler = qmlobject_cast<QQuickTapHandler *>(buttonHandler); + if (buttonTapHandler) + buttonTapHandler->setGesturePolicy(tapGesturePolicy); QQuickDragHandler *buttonDragHandler = qmlobject_cast<QQuickDragHandler *>(buttonHandler); QQuickPointerHandler *delegateHandler = delegate ? delegate->findChild<QQuickPointerHandler*>() : nullptr; + QQuickTapHandler *delegateTapHandler = qmlobject_cast<QQuickTapHandler *>(delegateHandler); + if (delegateTapHandler) + delegateTapHandler->setGesturePolicy(tapGesturePolicy); QQuickPointerHandler *contentItemHandler = flickable->findChild<QQuickPointerHandler*>(); QVERIFY(contentItemHandler); // a handler declared directly in a Flickable (or item view) must actually be a child of the contentItem, @@ -730,9 +738,12 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable() contentItemHandler->setTarget(nullptr); } - // Drag one finger on the Flickable and make sure it flicks + // Drag one finger on the Flickable (between delegates) and make sure it flicks QTest::QTouchEventSequence touchSeq = QTest::touchEvent(window, touchDevice, false); QPoint p1(780, 460); + if (delegate) + p1 = delegate->mapToScene(delegate->clipRect().bottomRight()).toPoint() + QPoint(-1, 1); + qCDebug(lcPointerTests) << "drag between delegates starting @" << p1; touchSeq.press(1, p1, window).commit(); QQuickTouchUtils::flush(window); for (int i = 0; i < 4; ++i) { @@ -752,8 +763,8 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable() flickable->setContentY(0); QTRY_COMPARE(flickable->isMoving(), false); QVERIFY(delegateHandler); - QQuickTapHandler *delegateTapHandler = qmlobject_cast<QQuickTapHandler *>(delegateHandler); - p1 = button->mapToScene(button->clipRect().bottomRight()).toPoint() + QPoint(10, 0); + p1 = delegate->mapToScene(delegate->clipRect().topRight()).toPoint() + QPoint(-2, 2); + qCDebug(lcPointerTests) << "drag on delegate 2 starting @" << p1; touchSeq.press(1, p1, window).commit(); QQuickTouchUtils::flush(window); if (delegateTapHandler && !pressDelay) @@ -762,6 +773,8 @@ void tst_FlickableInterop::touchAndDragHandlerOnFlickable() p1 -= QPoint(dragThreshold, dragThreshold); touchSeq.move(1, p1, window).commit(); QQuickTouchUtils::flush(window); + qCDebug(lcPointerTests) << i << p1 << delegateHandler->objectName() + << "active" << delegateHandler->active() << "flickable moving" << flickable->isMoving(); if (i > 1) QTRY_VERIFY(delegateHandler->active() || flickable->isMoving()); } |