summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den.exter@jollamobile.com>2013-02-16 18:34:24 +1000
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-02-22 02:53:43 +0100
commite8ca72d484c0e56f030e4742bb5f92b6f0555146 (patch)
tree2b7c5a623af743d85fadd46855d9da9b0331320b
parent67db779665b1d95a20720c0dee058c47f7df8726 (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: 29718 Change-Id: Ief82ef7b898ea2581fd0b7e52548f451d887e2f1 Reviewed-by: Alan Alpert <aalpert@rim.com>
-rw-r--r--src/declarative/graphicsitems/qdeclarativeflickable.cpp46
-rw-r--r--tests/auto/declarative/qdeclarativeflickable/data/nestedStopAtBounds.qml38
-rw-r--r--tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp76
-rw-r--r--tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp4
4 files changed, 136 insertions, 28 deletions
diff --git a/src/declarative/graphicsitems/qdeclarativeflickable.cpp b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
index edbd9782..c0c7b2a0 100644
--- a/src/declarative/graphicsitems/qdeclarativeflickable.cpp
+++ b/src/declarative/graphicsitems/qdeclarativeflickable.cpp
@@ -789,9 +789,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;
@@ -799,31 +799,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;
@@ -831,23 +828,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 00000000..6b28edf5
--- /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 d36e96f9..b0fa7bd6 100644
--- a/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp
+++ b/tests/auto/declarative/qdeclarativeflickable/tst_qdeclarativeflickable.cpp
@@ -75,6 +75,8 @@ private slots:
void testQtQuick11Attributes_data();
void wheel();
void flickVelocity();
+ void nestedStopAtBounds();
+ void nestedStopAtBounds_data();
private:
QDeclarativeEngine engine;
@@ -524,6 +526,80 @@ void tst_qdeclarativeflickable::flick(QGraphicsView *canvas, const QPoint &from,
QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(to));
}
+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();
+ view.activateWindow();
+ QVERIFY(QTest::qWaitForWindowExposed(&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 855ad602..37e64d4d 100644
--- a/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp
+++ b/tests/auto/declarative/qdeclarativemousearea/tst_qdeclarativemousearea.cpp
@@ -597,8 +597,8 @@ void tst_QDeclarativeMouseArea::preventStealing()
QVERIFY(!mouseArea->pressed());
// Flickable content should have moved.
- QCOMPARE(flickable->contentX(), 15.);
- QCOMPARE(flickable->contentY(), 15.);
+ QCOMPARE(flickable->contentX(), 30.);
+ QCOMPARE(flickable->contentY(), 30.);
QTest::mouseRelease(canvas->viewport(), Qt::LeftButton, 0, canvas->mapFromScene(QPoint(50, 50)));