aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@qt.io>2022-10-19 22:18:37 +0200
committerShawn Rutledge <shawn.rutledge@qt.io>2022-10-27 00:19:04 +0200
commit8a3c523dd9aea6c55db4b479de566624e2692435 (patch)
tree5c6cbe17bd39dc360b0a2c320fd0f6b9dcffe476 /tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
parent99e4a2e3c5e8e0f43b601857878867561602490d (diff)
Ensure Flickable.flickEnded signal is emitted after flick-then-drag
hData and vData's flicking flags could get set to false in two places: movementEnding(), which would also emit flickEnded(); or in maybeBeginDrag(), which did not emit flickEnded(). So if the user did a quick flick-flick-flick sequence, usually the flick would be restarted, and movementEnding would emit the signal after motion stopped. But if the user dragged too slowly the final time, the flick would not be restarted, and movementEnding() did not emit flickEnded() because the two flicking flags were already false. At the time the final drag starts, we don't know if the user is going to drag fast enough to qualify as a flick, so that's probably why maybeBeginDrag() doesn't emit flickEnded(). But information is lost by setting the flicking flags to false there. So to make the flickStarted() and flickEnded() signals more symmetric, we also need flags to remember that when the drag began, there was residual momentum (it was already flicking). Then movementEnding() can emit flickEnded() after movement has stopped, which is more consistent with what the user should expect: all's well that ends well, even if it started more than once. It seems the intention was always that flickEnded() means the whole sequence of flicks and drags had ended; so give a hint in the docs. Declare the wasFlicking locals const, as a drive-by. The bool bitfields in AxisData are converted to uint for proper packing on MSVC. Fixes: QTBUG-103620 Change-Id: I363aa3a0d95e1fff21b4b09f22e88e51b88c7c16 Reviewed-by: Richard Moe Gustavsen <richard.gustavsen@qt.io> (cherry picked from commit c9b8acba0e49a4d461183d069d12cbf18dfebe41) Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'tests/auto/quick/qquickflickable/tst_qquickflickable.cpp')
-rw-r--r--tests/auto/quick/qquickflickable/tst_qquickflickable.cpp75
1 files changed, 75 insertions, 0 deletions
diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
index c088be4566..a6fb0fcb59 100644
--- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
+++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp
@@ -207,6 +207,7 @@ private slots:
void movingAndDragging_data();
void flickOnRelease();
void pressWhileFlicking();
+ void dragWhileFlicking();
void disabled();
void flickVelocity();
void margins();
@@ -1483,6 +1484,8 @@ void tst_qquickflickable::pressWhileFlicking()
QSignalSpy hFlickSpy(flickable, SIGNAL(flickingHorizontallyChanged()));
QSignalSpy vFlickSpy(flickable, SIGNAL(flickingVerticallyChanged()));
QSignalSpy flickSpy(flickable, SIGNAL(flickingChanged()));
+ QSignalSpy flickStartSpy(flickable, &QQuickFlickable::flickStarted);
+ QSignalSpy flickEndSpy(flickable, &QQuickFlickable::flickEnded);
// flick then press while it is still moving
// flicking == false, moving == true;
@@ -1500,6 +1503,8 @@ void tst_qquickflickable::pressWhileFlicking()
QCOMPARE(vFlickSpy.count(), 1);
QCOMPARE(hFlickSpy.count(), 0);
QCOMPARE(flickSpy.count(), 1);
+ QCOMPARE(flickStartSpy.count(), 1);
+ QCOMPARE(flickEndSpy.count(), 0);
QTest::mousePress(window.data(), Qt::LeftButton, Qt::NoModifier, QPoint(20, 50));
QTRY_VERIFY(!flickable->isFlicking());
@@ -1512,6 +1517,76 @@ void tst_qquickflickable::pressWhileFlicking()
QVERIFY(!flickable->isFlickingVertically());
QTRY_VERIFY(!flickable->isMoving());
QVERIFY(!flickable->isMovingVertically());
+ QCOMPARE(flickStartSpy.size(), 1);
+ QCOMPARE(flickEndSpy.size(), 1);
+ // Stop on a full pixel after user interaction
+ QCOMPARE(flickable->contentX(), (qreal)qRound(flickable->contentX()));
+}
+
+void tst_qquickflickable::dragWhileFlicking()
+{
+ QQuickView window;
+ QVERIFY(QQuickTest::showView(window, testFileUrl("flickable03.qml")));
+
+ QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window.rootObject());
+ QVERIFY(flickable != nullptr);
+
+ QSignalSpy vMoveSpy(flickable, &QQuickFlickable::movingVerticallyChanged);
+ QSignalSpy hMoveSpy(flickable, &QQuickFlickable::movingHorizontallyChanged);
+ QSignalSpy moveSpy(flickable, &QQuickFlickable::movingChanged);
+ QSignalSpy hFlickSpy(flickable, &QQuickFlickable::flickingHorizontallyChanged);
+ QSignalSpy vFlickSpy(flickable, &QQuickFlickable::flickingVerticallyChanged);
+ QSignalSpy flickSpy(flickable, &QQuickFlickable::flickingChanged);
+ QSignalSpy flickStartSpy(flickable, &QQuickFlickable::flickStarted);
+ QSignalSpy flickEndSpy(flickable, &QQuickFlickable::flickEnded);
+
+ // flick first, let it keep moving
+ flick(&window, QPoint(20,190), QPoint(20, 50), 200);
+ QVERIFY(flickable->verticalVelocity() > 0.0);
+ QTRY_VERIFY(flickable->isFlicking());
+ QVERIFY(flickable->isFlickingVertically());
+ QCOMPARE(flickable->isFlickingHorizontally(), false);
+ QVERIFY(flickable->isMoving());
+ QVERIFY(flickable->isMovingVertically());
+ QCOMPARE(flickable->isMovingHorizontally(), false);
+ QCOMPARE(vMoveSpy.size(), 1);
+ QCOMPARE(hMoveSpy.size(), 0);
+ QCOMPARE(moveSpy.size(), 1);
+ QCOMPARE(vFlickSpy.size(), 1);
+ QCOMPARE(hFlickSpy.size(), 0);
+ QCOMPARE(flickSpy.size(), 1);
+ QCOMPARE(flickStartSpy.size(), 1);
+ QCOMPARE(flickEndSpy.size(), 0);
+
+ // then drag slowly while it's still flicking and moving
+ const int dragStepDelay = 100;
+ QTest::mousePress(&window, Qt::LeftButton, Qt::NoModifier, QPoint(20, 70));
+ QTRY_COMPARE(flickable->isFlicking(), false);
+ QCOMPARE(flickable->isFlickingVertically(), false);
+ QVERIFY(flickable->isMoving());
+ QVERIFY(flickable->isMovingVertically());
+
+ for (int y = 70; y > 50; y -= 5) {
+ QTest::mouseMove(&window, QPoint(20, y), dragStepDelay);
+ QVERIFY(flickable->isMoving());
+ QVERIFY(flickable->isMovingVertically());
+ // Flickable's timeline is real-time, so spoofing timestamps isn't enough
+ QTest::qWait(dragStepDelay);
+ }
+
+ QTest::mouseRelease(&window, Qt::LeftButton, Qt::NoModifier, QPoint(20, 50), dragStepDelay);
+
+ QCOMPARE(flickable->isFlicking(), false);
+ QCOMPARE(flickable->isFlickingVertically(), false);
+ QTRY_COMPARE(flickable->isMoving(), false);
+ QCOMPARE(flickable->isMovingVertically(), false);
+ QCOMPARE(flickStartSpy.size(), 1);
+ QCOMPARE(flickEndSpy.size(), 1);
+ QCOMPARE(vMoveSpy.size(), 2);
+ QCOMPARE(hMoveSpy.size(), 0);
+ QCOMPARE(moveSpy.size(), 2);
+ QCOMPARE(vFlickSpy.size(), 2);
+ QCOMPARE(hFlickSpy.size(), 0);
// Stop on a full pixel after user interaction
QCOMPARE(flickable->contentX(), (qreal)qRound(flickable->contentX()));
}