diff options
author | Andrew den Exter <andrew.den.exter@jollamobile.com> | 2013-02-16 17:21:28 +1000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-02-22 10:03:20 +0100 |
commit | 6ad4a61d482d895d135a7a281115bf104e0b9a90 (patch) | |
tree | 29bc2ffc39092105efde3c21c3fa45f9187301ed | |
parent | 7a1282a9edd8afa4645d7d449ca2ed3746fb8d71 (diff) |
Flickable shouldn't grab the mouse until it starts an effective move.
If the boundBehavior prevents the flickable from moving its content
item in response to a drag it shouldn't grab the mouse as that will
prevent a parent MouseArea or Flickable from handling the drag.
Task-number: QTBUG-29718
Change-Id: I3a1be4ed0132b91dca2fb0387ecefd39275a52da
Reviewed-by: Alan Alpert <aalpert@rim.com>
5 files changed, 137 insertions, 34 deletions
diff --git a/src/quick/items/qquickflickable.cpp b/src/quick/items/qquickflickable.cpp index c1e8dd378c..3482db0dfe 100644 --- a/src/quick/items/qquickflickable.cpp +++ b/src/quick/items/qquickflickable.cpp @@ -1018,9 +1018,9 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event) if (q->yflick()) { qreal dy = event->localPos().y() - pressPos.y(); bool overThreshold = QQuickWindowPrivate::dragOverThreshold(dy, Qt::YAxis, event); + if (vData.dragStartOffset == 0) + vData.dragStartOffset = dy; if (overThreshold || elapsedSincePress > 200) { - if (!vMoved) - vData.dragStartOffset = dy; qreal newY = dy + vData.pressPos - vData.dragStartOffset; // Recalculate bounds in case margins have changed, but use the content // size estimate taken at the start of the drag in case the drag causes @@ -1031,23 +1031,20 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event) newY = minY + (newY - minY) / 2; if (newY < maxY && maxY - minY <= 0) newY = maxY + (newY - maxY) / 2; - if (boundsBehavior == QQuickFlickable::StopAtBounds && (newY > minY || newY < maxY)) { - rejectY = true; - if (newY < maxY) { - newY = maxY; - rejectY = false; - } - if (newY > minY) { - newY = minY; - rejectY = false; - } + if (boundsBehavior == QQuickFlickable::StopAtBounds && newY <= maxY) { + newY = maxY; + rejectY = vData.pressPos == maxY && dy < 0; + } + if (boundsBehavior == QQuickFlickable::StopAtBounds && newY >= minY) { + newY = minY; + rejectY = vData.pressPos == minY && dy > 0; } if (!rejectY && stealMouse && dy != 0.0) { clearTimeline(); vData.move.setValue(newY); vMoved = true; } - if (overThreshold) + if (!rejectY && overThreshold) stealY = true; } } @@ -1055,9 +1052,9 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event) if (q->xflick()) { qreal dx = event->localPos().x() - pressPos.x(); bool overThreshold = QQuickWindowPrivate::dragOverThreshold(dx, Qt::XAxis, event); + if (hData.dragStartOffset == 0) + hData.dragStartOffset = dx; if (overThreshold || elapsedSincePress > 200) { - if (!hMoved) - hData.dragStartOffset = dx; qreal newX = dx + hData.pressPos - hData.dragStartOffset; const qreal minX = hData.dragMinBound + hData.startMargin; const qreal maxX = hData.dragMaxBound - hData.endMargin; @@ -1065,24 +1062,22 @@ void QQuickFlickablePrivate::handleMouseMoveEvent(QMouseEvent *event) newX = minX + (newX - minX) / 2; if (newX < maxX && maxX - minX <= 0) newX = maxX + (newX - maxX) / 2; - if (boundsBehavior == QQuickFlickable::StopAtBounds && (newX > minX || newX < maxX)) { - rejectX = true; - if (newX < maxX) { - newX = maxX; - rejectX = false; - } - if (newX > minX) { - newX = minX; - rejectX = false; - } + if (boundsBehavior == QQuickFlickable::StopAtBounds && newX <= maxX) { + newX = maxX; + rejectX = hData.pressPos == maxX && dx < 0; + } + if (boundsBehavior == QQuickFlickable::StopAtBounds && newX >= minX) { + newX = minX; + rejectX = hData.pressPos == minX && dx > 0; } + if (!rejectX && stealMouse && dx != 0.0) { clearTimeline(); hData.move.setValue(newX); hMoved = true; } - if (overThreshold) + if (!rejectX && overThreshold) stealX = true; } } diff --git a/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml new file mode 100644 index 0000000000..59318e5b95 --- /dev/null +++ b/tests/auto/quick/qquickflickable/data/nestedStopAtBounds.qml @@ -0,0 +1,37 @@ +import QtQuick 2.0 + +Flickable { + id: outer + objectName: "outerFlickable" + width: 400 + height: 400 + contentX: 50 + contentY: 50 + contentWidth: 500 + contentHeight: 500 + flickableDirection: inner.flickableDirection + + Rectangle { + x: 100 + y: 100 + width: 300 + height: 300 + + color: "yellow" + Flickable { + id: inner + objectName: "innerFlickable" + anchors.fill: parent + contentX: 100 + contentY: 100 + contentWidth: 400 + contentHeight: 400 + boundsBehavior: Flickable.StopAtBounds + Rectangle { + anchors.fill: parent + anchors.margins: 100 + color: "blue" + } + } + } +} diff --git a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp index 784988b913..57c4c12264 100644 --- a/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp +++ b/tests/auto/quick/qquickflickable/tst_qquickflickable.cpp @@ -91,6 +91,8 @@ private slots: void cancelOnMouseGrab(); void clickAndDragWhenTransformed(); void flickTwiceUsingTouches(); + void nestedStopAtBounds(); + void nestedStopAtBounds_data(); private: void flickWithTouch(QWindow *window, QTouchDevice *touchDevice); @@ -1311,6 +1313,75 @@ void tst_qquickflickable::flickWithTouch(QWindow *window, QTouchDevice *touchDev QTest::qWait(1); } +void tst_qquickflickable::nestedStopAtBounds_data() +{ + QTest::addColumn<bool>("transpose"); + QTest::addColumn<bool>("invert"); + + QTest::newRow("left") << false << false; + QTest::newRow("right") << false << true; + QTest::newRow("top") << true << false; + QTest::newRow("bottom") << true << true; +} + +void tst_qquickflickable::nestedStopAtBounds() +{ + QFETCH(bool, transpose); + QFETCH(bool, invert); + + QQuickView view; + view.setSource(testFileUrl("nestedStopAtBounds.qml")); + view.show(); + view.requestActivate(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + QVERIFY(view.rootObject()); + + QQuickFlickable *outer = qobject_cast<QQuickFlickable*>(view.rootObject()); + QVERIFY(outer); + + QQuickFlickable *inner = outer->findChild<QQuickFlickable*>("innerFlickable"); + QVERIFY(inner); + inner->setFlickableDirection(transpose ? QQuickFlickable::VerticalFlick : QQuickFlickable::HorizontalFlick); + inner->setContentX(invert ? 0 : 100); + inner->setContentY(invert ? 0 : 100); + + const int threshold = qApp->styleHints()->startDragDistance(); + + QPoint position(200, 200); + int &axis = transpose ? position.ry() : position.rx(); + + // drag toward the aligned boundary. Outer flickable dragged. + QTest::mousePress(&view, Qt::LeftButton, 0, position); + QTest::qWait(10); + axis += invert ? threshold * 2 : -threshold * 2; + QTest::mouseMove(&view, position); + axis += invert ? threshold : -threshold; + QTest::mouseMove(&view, position); + QCOMPARE(outer->isDragging(), true); + QCOMPARE(inner->isDragging(), false); + QTest::mouseRelease(&view, Qt::LeftButton, 0, position); + + QVERIFY(!outer->isDragging()); + QTRY_VERIFY(!outer->isMoving()); + + axis = 200; + outer->setContentX(50); + outer->setContentY(50); + + // drag away from the aligned boundary. Inner flickable dragged. + QTest::mousePress(&view, Qt::LeftButton, 0, position); + QTest::qWait(10); + axis += invert ? -threshold * 2 : threshold * 2; + QTest::mouseMove(&view, position); + axis += invert ? -threshold : threshold; + QTest::mouseMove(&view, position); + QCOMPARE(outer->isDragging(), false); + QCOMPARE(inner->isDragging(), true); + QTest::mouseRelease(&view, Qt::LeftButton, 0, position); + + QTRY_VERIFY(!outer->isMoving()); +} + QTEST_MAIN(tst_qquickflickable) #include "tst_qquickflickable.moc" diff --git a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp index 802cc0a4c9..3c30f9e887 100644 --- a/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp +++ b/tests/auto/quick/qquickgridview/tst_qquickgridview.cpp @@ -4308,22 +4308,22 @@ void tst_QQuickGridView::snapOneRow_data() QTest::addColumn<qreal>("startExtent"); QTest::newRow("vertical, left to right") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange) - << QPoint(20, 200) << QPoint(20, 20) << 100.0 << 240.0 << 0.0; + << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 240.0 << 0.0; QTest::newRow("horizontal, left to right") << QQuickGridView::FlowTopToBottom << Qt::LeftToRight << int(QQuickItemView::NoHighlightRange) - << QPoint(200, 20) << QPoint(20, 20) << 100.0 << 240.0 << 0.0; + << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 240.0 << 0.0; QTest::newRow("horizontal, right to left") << QQuickGridView::FlowTopToBottom << Qt::RightToLeft << int(QQuickItemView::NoHighlightRange) - << QPoint(20, 20) << QPoint(200, 20) << -340.0 << -240.0 - 240.0 << -240.0; + << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 << -240.0; QTest::newRow("vertical, left to right, enforce range") << QQuickGridView::FlowLeftToRight << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange) - << QPoint(20, 200) << QPoint(20, 20) << 100.0 << 340.0 << -20.0; + << QPoint(20, 160) << QPoint(20, 20) << 100.0 << 340.0 << -20.0; QTest::newRow("horizontal, left to right, enforce range") << QQuickGridView::FlowTopToBottom << Qt::LeftToRight << int(QQuickItemView::StrictlyEnforceRange) - << QPoint(200, 20) << QPoint(20, 20) << 100.0 << 340.0 << -20.0; + << QPoint(160, 20) << QPoint(20, 20) << 100.0 << 340.0 << -20.0; QTest::newRow("horizontal, right to left, enforce range") << QQuickGridView::FlowTopToBottom << Qt::RightToLeft << int(QQuickItemView::StrictlyEnforceRange) - << QPoint(20, 20) << QPoint(200, 20) << -340.0 << -240.0 - 240.0 - 100.0 << -220.0; + << QPoint(20, 20) << QPoint(160, 20) << -340.0 << -240.0 - 240.0 - 100.0 << -220.0; } void tst_QQuickGridView::snapOneRow() diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index ef7dc72345..327abbebd5 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -805,8 +805,8 @@ void tst_QQuickMouseArea::preventStealing() // Flickable content should have moved. - QCOMPARE(flickable->contentX(), 11.); - QCOMPARE(flickable->contentY(), 11.); + QCOMPARE(flickable->contentX(), 22.); + QCOMPARE(flickable->contentY(), 22.); QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(50, 50)); |