From 0aea009425242417bffdb171c8eca02ff52f4a7b Mon Sep 17 00:00:00 2001 From: Andrew den Exter Date: Thu, 10 Mar 2016 13:28:06 +1000 Subject: Fix Flickable state being reset when it replays a delayed press. Ignore mouseUngrabEvents() triggered by giving mouse grab to a child item when replaying a delayed press event. Change-Id: I6c8db61167e21bf10d533b17f7cc65e4754bd432 Reviewed-by: Shawn Rutledge Reviewed-by: Martin Jones --- src/quick/items/qquickflickable.cpp | 5 +- .../qquickflickable/data/nestedStopAtBounds.qml | 4 + .../quick/qquickflickable/tst_qquickflickable.cpp | 98 ++++++++++++++++++---- 3 files changed, 88 insertions(+), 19 deletions(-) diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index 870a0268e1..c838eae3c7 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1539,11 +1539,11 @@ void QQuickFlickablePrivate::replayDelayedPress() // If we have the grab, release before delivering the event if (QQuickWindow *w = q->window()) { + replayingPressEvent = true; if (w->mouseGrabberItem() == q) q->ungrabMouse(); // Use the event handler that will take care of finding the proper item to propagate the event - replayingPressEvent = true; QCoreApplication::sendEvent(w, mouseEvent.data()); replayingPressEvent = false; } @@ -2199,7 +2199,8 @@ void QQuickFlickable::mouseUngrabEvent() Q_D(QQuickFlickable); // if our mouse grab has been removed (probably by another Flickable), // fix our state - d->cancelInteraction(); + if (!d->replayingPressEvent) + d->cancelInteraction(); } void QQuickFlickablePrivate::cancelInteraction() diff --git a/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml index 59318e5b95..81187f3c2f 100644 --- a/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml +++ b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml @@ -32,6 +32,10 @@ Flickable { anchors.margins: 100 color: "blue" } + MouseArea { + anchors.fill: parent + objectName: "mouseArea" + } } } } diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 96fe97f372..bbaccfe534 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include @@ -486,8 +487,20 @@ void tst_qquickflickable::nestedPressDelay() // QTRY_VERIFY() has 5sec timeout, so will timeout well within 10sec. QTRY_VERIFY(outer->property("pressed").toBool()); + QTest::mouseMove(window.data(), QPoint(130, 150)); + QTest::mouseMove(window.data(), QPoint(110, 150)); + QTest::mouseMove(window.data(), QPoint(90, 150)); + + QVERIFY(!outer->property("moving").toBool()); + QVERIFY(!outer->property("dragging").toBool()); + QVERIFY(inner->property("moving").toBool()); + QVERIFY(inner->property("dragging").toBool()); + QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(150, 150)); + QVERIFY(!inner->property("dragging").toBool()); + QTRY_VERIFY(!inner->property("moving").toBool()); + // Dragging inner Flickable should work moveAndPress(window.data(), QPoint(80, 150)); // the MouseArea is not pressed immediately @@ -499,10 +512,15 @@ void tst_qquickflickable::nestedPressDelay() QTest::mouseMove(window.data(), QPoint(20, 150)); QVERIFY(inner->property("moving").toBool()); + QVERIFY(inner->property("dragging").toBool()); QVERIFY(!outer->property("moving").toBool()); + QVERIFY(!outer->property("dragging").toBool()); QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(20, 150)); + QVERIFY(!inner->property("dragging").toBool()); + QTRY_VERIFY(!inner->property("moving").toBool()); + // Dragging the MouseArea in the inner Flickable should move the inner Flickable moveAndPress(window.data(), QPoint(150, 150)); // the MouseArea is not pressed immediately @@ -512,11 +530,15 @@ void tst_qquickflickable::nestedPressDelay() QTest::mouseMove(window.data(), QPoint(110, 150)); QTest::mouseMove(window.data(), QPoint(90, 150)); - QVERIFY(!outer->property("moving").toBool()); + QVERIFY(!outer->property("dragging").toBool()); QVERIFY(inner->property("moving").toBool()); + QVERIFY(inner->property("dragging").toBool()); QTest::mouseRelease(window.data(), Qt::LeftButton, 0, QPoint(90, 150)); + + QVERIFY(!inner->property("dragging").toBool()); + QTRY_VERIFY(!inner->property("moving").toBool()); } void tst_qquickflickable::filterReplayedPress() @@ -1472,20 +1494,26 @@ void tst_qquickflickable::nestedStopAtBounds_data() QTest::addColumn("invert"); QTest::addColumn("boundsBehavior"); QTest::addColumn("margin"); - - QTest::newRow("left,stop") << false << false << int(QQuickFlickable::StopAtBounds) << qreal(0); - QTest::newRow("right,stop") << false << true << int(QQuickFlickable::StopAtBounds) << qreal(0); - QTest::newRow("top,stop") << true << false << int(QQuickFlickable::StopAtBounds) << qreal(0); - QTest::newRow("bottom,stop") << true << true << int(QQuickFlickable::StopAtBounds) << qreal(0); - QTest::newRow("left,over") << false << false << int(QQuickFlickable::DragOverBounds) << qreal(0); - QTest::newRow("right,over") << false << true << int(QQuickFlickable::DragOverBounds) << qreal(0); - QTest::newRow("top,over") << true << false << int(QQuickFlickable::DragOverBounds) << qreal(0); - QTest::newRow("bottom,over") << true << true << int(QQuickFlickable::DragOverBounds) << qreal(0); - - QTest::newRow("left,stop,margin") << false << false << int(QQuickFlickable::StopAtBounds) << qreal(20); - QTest::newRow("right,stop,margin") << false << true << int(QQuickFlickable::StopAtBounds) << qreal(20); - QTest::newRow("top,stop,margin") << true << false << int(QQuickFlickable::StopAtBounds) << qreal(20); - QTest::newRow("bottom,stop,margin") << true << true << int(QQuickFlickable::StopAtBounds) << qreal(20); + QTest::addColumn("innerFiltering"); + QTest::addColumn("pressDelay"); + QTest::addColumn("waitForPressDelay"); + + QTest::newRow("left,stop") << false << false << int(QQuickFlickable::StopAtBounds) << qreal(0) << false << 0 << false; + QTest::newRow("right,stop") << false << true << int(QQuickFlickable::StopAtBounds) << qreal(0) << false << 0 << false; + QTest::newRow("top,stop") << true << false << int(QQuickFlickable::StopAtBounds) << qreal(0) << false << 0 << false; + QTest::newRow("bottom,stop") << true << true << int(QQuickFlickable::StopAtBounds) << qreal(0) << false << 0 << false; + QTest::newRow("left,over") << false << false << int(QQuickFlickable::DragOverBounds) << qreal(0) << false << 0 << false; + QTest::newRow("right,over") << false << true << int(QQuickFlickable::DragOverBounds) << qreal(0) << false << 0 << false; + QTest::newRow("top,over") << true << false << int(QQuickFlickable::DragOverBounds) << qreal(0) << false << 0 << false; + QTest::newRow("bottom,over") << true << true << int(QQuickFlickable::DragOverBounds) << qreal(0) << false << 0 << false; + + QTest::newRow("left,stop,margin") << false << false << int(QQuickFlickable::StopAtBounds) << qreal(20) << false << 0 << false; + QTest::newRow("right,stop,margin") << false << true << int(QQuickFlickable::StopAtBounds) << qreal(20) << false << 0 << false; + QTest::newRow("top,stop,margin") << true << false << int(QQuickFlickable::StopAtBounds) << qreal(20) << false << 0 << false; + QTest::newRow("bottom,stop,margin") << true << true << int(QQuickFlickable::StopAtBounds) << qreal(20) << false << 0 << false; + + QTest::newRow("left,stop,after press delay") << false << false << int(QQuickFlickable::StopAtBounds) << qreal(0) << true << 50 << true; + QTest::newRow("left,stop,before press delay") << false << false << int(QQuickFlickable::StopAtBounds) << qreal(0) << true << 50 << false; } void tst_qquickflickable::nestedStopAtBounds() @@ -1494,6 +1522,9 @@ void tst_qquickflickable::nestedStopAtBounds() QFETCH(bool, invert); QFETCH(int, boundsBehavior); QFETCH(qreal, margin); + QFETCH(bool, innerFiltering); + QFETCH(int, pressDelay); + QFETCH(bool, waitForPressDelay); QQuickView view; view.setSource(testFileUrl("nestedStopAtBounds.qml")); @@ -1526,6 +1557,12 @@ void tst_qquickflickable::nestedStopAtBounds() QCOMPARE(inner->isAtYBeginning(), invert); QCOMPARE(inner->isAtYEnd(), !invert); + inner->setPressDelay(pressDelay); + + QQuickMouseArea *mouseArea = inner->findChild("mouseArea"); + QVERIFY(mouseArea); + mouseArea->setEnabled(innerFiltering); + const int threshold = qApp->styleHints()->startDragDistance(); QPoint position(200, 200); @@ -1533,17 +1570,25 @@ void tst_qquickflickable::nestedStopAtBounds() // drag toward the aligned boundary. Outer flickable dragged. moveAndPress(&view, position); - QTest::qWait(10); + if (waitForPressDelay) { + QVERIFY(innerFiltering); // isPressed will never be true if the mouse area isn't enabled. + QTRY_VERIFY(mouseArea->pressed()); + } + axis += invert ? threshold * 2 : -threshold * 2; QTest::mouseMove(&view, position); axis += invert ? threshold : -threshold; QTest::mouseMove(&view, position); QCOMPARE(outer->isDragging(), true); + QCOMPARE(outer->isMoving(), true); QCOMPARE(inner->isDragging(), false); + QCOMPARE(inner->isMoving(), false); QTest::mouseRelease(&view, Qt::LeftButton, 0, position); QVERIFY(!outer->isDragging()); QTRY_VERIFY(!outer->isMoving()); + QVERIFY(!inner->isDragging()); + QVERIFY(!inner->isMoving()); axis = 200; outer->setContentX(50); @@ -1557,10 +1602,15 @@ void tst_qquickflickable::nestedStopAtBounds() axis += invert ? -threshold : threshold; QTest::mouseMove(&view, position); QCOMPARE(outer->isDragging(), false); + QCOMPARE(outer->isMoving(), false); QCOMPARE(inner->isDragging(), true); + QCOMPARE(inner->isMoving(), true); QTest::mouseRelease(&view, Qt::LeftButton, 0, position); - QTRY_VERIFY(!outer->isMoving()); + QVERIFY(!inner->isDragging()); + QTRY_VERIFY(!inner->isMoving()); + QVERIFY(!outer->isDragging()); + QVERIFY(!outer->isMoving()); axis = 200; inner->setContentX(-margin); @@ -1576,9 +1626,16 @@ void tst_qquickflickable::nestedStopAtBounds() axis += invert ? -threshold : threshold; QTest::mouseMove(&view, position); QCOMPARE(outer->isDragging(), true); + QCOMPARE(outer->isMoving(), true); QCOMPARE(inner->isDragging(), false); + QCOMPARE(inner->isMoving(), false); QTest::mouseRelease(&view, Qt::LeftButton, 0, position); + QVERIFY(!outer->isDragging()); + QTRY_VERIFY(!outer->isMoving()); + QVERIFY(!inner->isDragging()); + QVERIFY(!inner->isMoving()); + axis = 200; inner->setContentX(-margin); inner->setContentY(-margin); @@ -1593,8 +1650,15 @@ void tst_qquickflickable::nestedStopAtBounds() axis += invert ? -threshold : threshold; QTest::mouseMove(&view, position); QCOMPARE(outer->isDragging(), true); + QCOMPARE(outer->isMoving(), true); QCOMPARE(inner->isDragging(), false); + QCOMPARE(inner->isMoving(), false); QTest::mouseRelease(&view, Qt::LeftButton, 0, position); + + QVERIFY(!outer->isDragging()); + QTRY_VERIFY(!outer->isMoving()); + QVERIFY(!inner->isDragging()); + QVERIFY(!inner->isMoving()); } void tst_qquickflickable::stopAtBounds_data() -- cgit v1.2.3