diff options
4 files changed, 134 insertions, 28 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp index 3817bc1..3edc62d 100644 --- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp +++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp @@ -788,9 +788,9 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent if (q->yflick()) { int dy = int(event->pos().y() - pressPos.y()); + if (vData.dragStartOffset == 0) + vData.dragStartOffset = dy; if (qAbs(dy) > QApplication::startDragDistance() || QDeclarativeItemPrivate::elapsed(pressTime) > 200) { - if (!vMoved) - vData.dragStartOffset = dy; qreal newY = dy + vData.pressPos - vData.dragStartOffset; const qreal minY = vData.dragMinBound; const qreal maxY = vData.dragMaxBound; @@ -798,31 +798,28 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent newY = minY + (newY - minY) / 2; if (newY < maxY && maxY - minY <= 0) newY = maxY + (newY - maxY) / 2; - if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && (newY > minY || newY < maxY)) { - rejectY = true; - if (newY < maxY) { - newY = maxY; - rejectY = false; - } - if (newY > minY) { - newY = minY; - rejectY = false; - } + if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && newY <= maxY) { + newY = maxY; + rejectY = vData.pressPos == maxY && dy < 0; + } + if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && newY >= minY) { + newY = minY; + rejectY = vData.pressPos == minY && dy > 0; } if (!rejectY && stealMouse && dy != 0) { vData.move.setValue(qRound(newY)); vMoved = true; } - if (qAbs(dy) > QApplication::startDragDistance()) + if (!rejectY && qAbs(dy) > QApplication::startDragDistance()) stealY = true; } } if (q->xflick()) { int dx = int(event->pos().x() - pressPos.x()); + if (hData.dragStartOffset == 0) + hData.dragStartOffset = dx; if (qAbs(dx) > QApplication::startDragDistance() || QDeclarativeItemPrivate::elapsed(pressTime) > 200) { - if (!hMoved) - hData.dragStartOffset = dx; qreal newX = dx + hData.pressPos - hData.dragStartOffset; const qreal minX = hData.dragMinBound; const qreal maxX = hData.dragMaxBound; @@ -830,23 +827,20 @@ void QDeclarativeFlickablePrivate::handleMouseMoveEvent(QGraphicsSceneMouseEvent newX = minX + (newX - minX) / 2; if (newX < maxX && maxX - minX <= 0) newX = maxX + (newX - maxX) / 2; - if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && (newX > minX || newX < maxX)) { - rejectX = true; - if (newX < maxX) { - newX = maxX; - rejectX = false; - } - if (newX > minX) { - newX = minX; - rejectX = false; - } + if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && newX <= maxX) { + newX = maxX; + rejectX = hData.pressPos == maxX && dx < 0; + } + if (boundsBehavior == QDeclarativeFlickable::StopAtBounds && newX >= minX) { + newX = minX; + rejectX = hData.pressPos == minX && dx > 0; } if (!rejectX && stealMouse && dx != 0) { hData.move.setValue(qRound(newX)); hMoved = true; } - if (qAbs(dx) > QApplication::startDragDistance()) + if (!rejectX && qAbs(dx) > QApplication::startDragDistance()) stealX = true; } } diff --git a/tests/auto/declarative/qdeclarativeflickable/data/nestedStopAtBounds.qml b/tests/auto/declarative/qdeclarativeflickable/data/nestedStopAtBounds.qml new file mode 100644 index 0000000..6b28edf --- /dev/null +++ b/tests/auto/declarative/qdeclarativeflickable/data/nestedStopAtBounds.qml @@ -0,0 +1,38 @@ +import QtQuick 1.1 + +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/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp index 73d7be5..01ab415 100644 --- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp +++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp @@ -80,6 +80,8 @@ private slots: void wheel(); void flickVelocity(); void disabled(); + void nestedStopAtBounds(); + void nestedStopAtBounds_data(); private: QDeclarativeEngine engine; @@ -574,6 +576,78 @@ void tst_qdeclarativeflickable::disabled() QVERIFY(clickedToBool == true); } +void tst_qdeclarativeflickable::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_qdeclarativeflickable::nestedStopAtBounds() +{ + QFETCH(bool, transpose); + QFETCH(bool, invert); + + QDeclarativeView view; + view.setSource(QUrl::fromLocalFile(SRCDIR "/data/nestedStopAtBounds.qml")); + view.show(); + QTest::qWaitForWindowShown(&view); + QVERIFY(view.rootObject()); + + QDeclarativeFlickable *outer = qobject_cast<QDeclarativeFlickable*>(view.rootObject()); + QVERIFY(outer); + + QDeclarativeFlickable *inner = outer->findChild<QDeclarativeFlickable*>("innerFlickable"); + QVERIFY(inner); + inner->setFlickableDirection(transpose ? QDeclarativeFlickable::VerticalFlick : QDeclarativeFlickable::HorizontalFlick); + inner->setContentX(invert ? 0 : 100); + inner->setContentY(invert ? 0 : 100); + + const int threshold = QApplication::startDragDistance(); + + QPoint position(200, 200); + int &axis = transpose ? position.ry() : position.rx(); + + QGraphicsSceneMouseEvent moveEvent(QEvent::GraphicsSceneMouseMove); + moveEvent.setButton(Qt::LeftButton); + moveEvent.setButtons(Qt::LeftButton); + + // drag toward the aligned boundary. Outer mouse area dragged. + QTest::mousePress(view.viewport(), Qt::LeftButton, 0, position); + QTest::qWait(10); + axis += invert ? threshold * 2 : -threshold * 2; + moveEvent.setScenePos(position); + QApplication::sendEvent(view.scene(), &moveEvent); + axis += invert ? threshold : -threshold; + moveEvent.setScenePos(position); + QApplication::sendEvent(view.scene(), &moveEvent); + QVERIFY(outer->contentX() != 50 || outer->contentY() != 50); + QVERIFY((inner->contentX() == 0 || inner->contentX() == 100) + && (inner->contentY() == 0 || inner->contentY() == 100)); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, position); + + axis = 200; + outer->setContentX(50); + outer->setContentY(50); + + // drag away from the aligned boundary. Inner mouse area dragged. + QTest::mousePress(view.viewport(), Qt::LeftButton, 0, position); + QTest::qWait(10); + axis += invert ? -threshold * 2 : threshold * 2; + moveEvent.setScenePos(position); + QApplication::sendEvent(view.scene(), &moveEvent); + axis += invert ? -threshold : threshold; + moveEvent.setScenePos(position); + QApplication::sendEvent(view.scene(), &moveEvent); + QVERIFY(outer->contentX() == 50 && outer->contentY() == 50); + QVERIFY((inner->contentX() != 0 && inner->contentX() != 100) + || (inner->contentY() != 0 && inner->contentY() != 100)); + QTest::mouseRelease(view.viewport(), Qt::LeftButton, 0, position); +} template<typename T> T *tst_qdeclarativeflickable::findItem(QGraphicsObject *parent, const QString &objectName) diff --git a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp index 41dcc81..9b4123f 100644 --- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp +++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp @@ -602,8 +602,8 @@ void tst_QDeclarativeMouseArea::preventStealing() QVERIFY(!mouseArea->pressed()); // Flickable content should have moved. - QCOMPARE(flickable->contentX(), 10.); - QCOMPARE(flickable->contentY(), 10.); + QCOMPARE(flickable->contentX(), 20.); + QCOMPARE(flickable->contentY(), 20.); QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50))); |