diff options
author | Shawn Rutledge <shawn.rutledge@qt.io> | 2022-06-28 21:49:59 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2022-07-04 11:05:28 +0000 |
commit | e73c94dcb112707b619ca3b1880cc98ed064a6ef (patch) | |
tree | aadb13e63949e809330a2776d5ef5cbf829cec26 /tests | |
parent | c425e94ad8f6b30f826b7d9964b6ff142164c864 (diff) |
Flickable: don't grab on press if already moving
9f9ea6e1837620a0ff4b98e262cba2df44215967 was too drastic: we cannot
simply avoid calling filterPointerEvent() on press, because it calls
handlePressEvent() which calls maybeBeginDrag() which sets pressPos,
among other things. Failing to set pressPos caused a regression:
flicking a second time while the flickable is already moving caused it
to "start over" as if it was flicking from the top again. So now we
revert that fix, and instead avoid setting stealMouse to true in
handlePressEvent(). This makes the second flick more like the first:
it waits for move events before taking the exclusive grab; so it's ok
for a delegate (such as a Button or MouseArea) to detect the press and
take a grab in the meantime. Flickable does not need to grab on press
during filtering: it's not a lost opportunity, because it keeps
filtering its children's events later on anyway.
The flickDuringFlicking() test is added for this scenario. For the same
reason as tapDelegateDuringFlicking(), this is also likely to fail on
Android for now.
This could have some impact on d7b5a485583004ad6a1374a50b7c3f6cab00aca3
but it seems the test that was added there still passes.
Fixes: QTBUG-103832
Task-number: QTBUG-38765
Task-number: QTBUG-74842
Task-number: QTBUG-104471
Change-Id: Icb45fcd94847051121ee78a970fbd5f5dc8a42a4
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Antti Määttä <antti.maatta@qt.io>
Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io>
Reviewed-by: Oliver Eftevaag <oliver.eftevaag@qt.io>
(cherry picked from commit bb337a0e1c22896984438cbd51ab7473807f017c)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/quick/qquicklistview2/BLACKLIST | 4 | ||||
-rw-r--r-- | tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp | 64 |
2 files changed, 67 insertions, 1 deletions
diff --git a/tests/auto/quick/qquicklistview2/BLACKLIST b/tests/auto/quick/qquicklistview2/BLACKLIST index b61ef889c0..8ecf16f118 100644 --- a/tests/auto/quick/qquicklistview2/BLACKLIST +++ b/tests/auto/quick/qquicklistview2/BLACKLIST @@ -1,3 +1,5 @@ [tapDelegateDuringFlicking] -android +android # QTBUG-104471 +[flickDuringFlicking] +android # QTBUG-104471 diff --git a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp index 7749e83b47..0cb88c501d 100644 --- a/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp +++ b/tests/auto/quick/qquicklistview2/tst_qquicklistview2.cpp @@ -64,6 +64,8 @@ private slots: void noCrashOnIndexChange(); void tapDelegateDuringFlicking_data(); void tapDelegateDuringFlicking(); + void flickDuringFlicking_data(); + void flickDuringFlicking(); private: void flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to); @@ -380,6 +382,68 @@ void tst_QQuickListView2::tapDelegateDuringFlicking() // QTBUG-103832 QCOMPARE(canceledDelegates.count(), 1); // only the first press was canceled, not the second } +void tst_QQuickListView2::flickDuringFlicking_data() +{ + QTest::addColumn<QByteArray>("qmlFile"); + QTest::addColumn<QQuickFlickable::BoundsBehavior>("boundsBehavior"); + + QTest::newRow("Button StopAtBounds") << QByteArray("buttonDelegate.qml") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds); + QTest::newRow("MouseArea StopAtBounds") << QByteArray("mouseAreaDelegate.qml") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::StopAtBounds); + QTest::newRow("Button DragOverBounds") << QByteArray("buttonDelegate.qml") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds); + QTest::newRow("MouseArea DragOverBounds") << QByteArray("mouseAreaDelegate.qml") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragOverBounds); + QTest::newRow("Button OvershootBounds") << QByteArray("buttonDelegate.qml") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds); + QTest::newRow("MouseArea OvershootBounds") << QByteArray("mouseAreaDelegate.qml") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::OvershootBounds); + QTest::newRow("Button DragAndOvershootBounds") << QByteArray("buttonDelegate.qml") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds); + QTest::newRow("MouseArea DragAndOvershootBounds") << QByteArray("mouseAreaDelegate.qml") + << QQuickFlickable::BoundsBehavior(QQuickFlickable::DragAndOvershootBounds); +} + +void tst_QQuickListView2::flickDuringFlicking() // QTBUG-103832 +{ + QFETCH(QByteArray, qmlFile); + QFETCH(QQuickFlickable::BoundsBehavior, boundsBehavior); + + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl(qmlFile.constData()))); + QQuickListView *listView = qobject_cast<QQuickListView*>(window.rootObject()); + QVERIFY(listView); + listView->setBoundsBehavior(boundsBehavior); + + flickWithTouch(&window, {100, 400}, {100, 100}); + QTRY_VERIFY(listView->contentY() > 1000); // let it flick some distance + QVERIFY(listView->isFlicking()); // we want to test the case when it's moving and then we flick again + const qreal posBeforeSecondFlick = listView->contentY(); + + // flick again during flicking, and make sure that it doesn't jump back to the first delegate, + // but flicks incrementally further from the position at that time + QTest::touchEvent(&window, touchDevice.data()).press(0, {100, 400}); + QQuickTouchUtils::flush(&window); + qCDebug(lcTests) << "second press: contentY" << posBeforeSecondFlick << "->" << listView->contentY(); + qCDebug(lcTests) << "pressed delegates" << listView->property("pressedDelegates").toList(); + QVERIFY(listView->contentY() >= posBeforeSecondFlick); + + QTest::qWait(20); + QTest::touchEvent(&window, touchDevice.data()).move(0, {100, 300}); + QQuickTouchUtils::flush(&window); + qCDebug(lcTests) << "first move after second press: contentY" << posBeforeSecondFlick << "->" << listView->contentY(); + QVERIFY(listView->contentY() >= posBeforeSecondFlick); + + QTest::qWait(20); + QTest::touchEvent(&window, touchDevice.data()).move(0, {100, 200}); + QQuickTouchUtils::flush(&window); + qCDebug(lcTests) << "second move after second press: contentY" << posBeforeSecondFlick << "->" << listView->contentY(); + QVERIFY(listView->contentY() >= posBeforeSecondFlick + 100); + + QTest::touchEvent(&window, touchDevice.data()).release(0, {100, 100}); +} + void tst_QQuickListView2::flickWithTouch(QQuickWindow *window, const QPoint &from, const QPoint &to) { QTest::touchEvent(window, touchDevice.data()).press(0, from, window); |