diff options
author | Andrew den Exter <andrew.den.exter@jollamobile.com> | 2013-02-15 21:29:32 +1000 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-02-22 02:10:21 +0100 |
commit | 7a1282a9edd8afa4645d7d449ca2ed3746fb8d71 (patch) | |
tree | 5c6c9f1dd46bfbd55ad8c508581ae631e3ecce22 | |
parent | b939bc6300d79862340ff35dc8910663bda5744f (diff) |
MouseArea shouldn't grab the mouse until there is an effective drag.
A MouseArea shouldn't prevent a parent MouseArea or Flickable from
handling a drag event unless it is going to do something useful with
it.
Task-number: 29717
Change-Id: I24016994f6cf9116382ef7faeb50b10e5716e10e
Reviewed-by: Alan Alpert <aalpert@rim.com>
-rw-r--r-- | src/quick/items/qquickmousearea.cpp | 49 | ||||
-rw-r--r-- | tests/auto/quick/qquickmousearea/data/nestedStopAtBounds.qml | 44 | ||||
-rw-r--r-- | tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp | 68 |
3 files changed, 131 insertions, 30 deletions
diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index e75a60181f..2fa52d9ed2 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -797,9 +797,6 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) curLocalPos = event->windowPos(); } - qreal dx = qAbs(curLocalPos.x() - startLocalPos.x()); - qreal dy = qAbs(curLocalPos.y() - startLocalPos.y()); - if (keepMouseGrab() && d->stealMouse && !d->drag->active()) d->drag->setActive(true); @@ -807,38 +804,30 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) ? d->drag->target()->parentItem()->mapFromScene(d->targetStartPos) : d->targetStartPos; - QPointF dragPos = d->drag->target()->position(); - bool dragX = drag()->axis() & QQuickDrag::XAxis; bool dragY = drag()->axis() & QQuickDrag::YAxis; - if (dragX && d->drag->active()) { - qreal x = (curLocalPos.x() - startLocalPos.x()) + startPos.x(); - if (x < drag()->xmin()) - x = drag()->xmin(); - else if (x > drag()->xmax()) - x = drag()->xmax(); - dragPos.setX(x); + QPointF dragPos = d->drag->target()->position(); + if (dragX) { + dragPos.setX(qBound( + d->drag->xmin(), + startPos.x() + curLocalPos.x() - startLocalPos.x(), + d->drag->xmax())); } - if (dragY && d->drag->active()) { - qreal y = (curLocalPos.y() - startLocalPos.y()) + startPos.y(); - if (y < drag()->ymin()) - y = drag()->ymin(); - else if (y > drag()->ymax()) - y = drag()->ymax(); - dragPos.setY(y); + if (dragY) { + dragPos.setY(qBound( + d->drag->ymin(), + startPos.y() + curLocalPos.y() - startLocalPos.y(), + d->drag->ymax())); } - d->drag->target()->setPosition(dragPos); - - if (!keepMouseGrab()) { - bool xDragged = QQuickWindowPrivate::dragOverThreshold(dx, Qt::XAxis, event); - bool yDragged = QQuickWindowPrivate::dragOverThreshold(dy, Qt::YAxis, event); - if ((!dragY && !yDragged && dragX && xDragged) - || (!dragX && !xDragged && dragY && yDragged) - || (dragX && dragY && (xDragged || yDragged))) { - setKeepMouseGrab(true); - d->stealMouse = true; - } + if (d->drag->active()) + d->drag->target()->setPosition(dragPos); + + if (!keepMouseGrab() + && (QQuickWindowPrivate::dragOverThreshold(dragPos.x() - startPos.x(), Qt::XAxis, event) + || QQuickWindowPrivate::dragOverThreshold(dragPos.y() - startPos.y(), Qt::YAxis, event))) { + setKeepMouseGrab(true); + d->stealMouse = true; } d->moved = true; diff --git a/tests/auto/quick/qquickmousearea/data/nestedStopAtBounds.qml b/tests/auto/quick/qquickmousearea/data/nestedStopAtBounds.qml new file mode 100644 index 0000000000..1fd39bb321 --- /dev/null +++ b/tests/auto/quick/qquickmousearea/data/nestedStopAtBounds.qml @@ -0,0 +1,44 @@ +import QtQuick 2.0 + +Rectangle { + width: 400 + height: 400 + + MouseArea { + id: outer + objectName: "outer" + x: 50 + y: 50 + width: 300 + height: 300 + + drag.target: outer + drag.filterChildren: true + + Rectangle { + anchors.fill: parent + color: "yellow" + } + + MouseArea { + id: inner + objectName: "inner" + + x: 0 + y: 0 + width: 200 + height: 200 + + drag.target: inner + drag.minimumX: 0 + drag.maximumX: 100 + drag.minimumY: 0 + drag.maximumY: 100 + + Rectangle { + anchors.fill: parent + color: "blue" + } + } + } +} diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index 37ce0fd394..ef7dc72345 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -89,6 +89,8 @@ private slots: void cursorShape(); #endif void moveAndReleaseWithoutPress(); + void nestedStopAtBounds(); + void nestedStopAtBounds_data(); private: void acceptedButton_data(); @@ -1426,6 +1428,72 @@ void tst_QQuickMouseArea::moveAndReleaseWithoutPress() delete window; } +void tst_QQuickMouseArea::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_QQuickMouseArea::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()); + + QQuickMouseArea *outer = view.rootObject()->findChild<QQuickMouseArea*>("outer"); + QVERIFY(outer); + + QQuickMouseArea *inner = outer->findChild<QQuickMouseArea*>("inner"); + QVERIFY(inner); + inner->drag()->setAxis(transpose ? QQuickDrag::YAxis : QQuickDrag::XAxis); + inner->setX(invert ? 100 : 0); + inner->setY(invert ? 100 : 0); + + const int threshold = qApp->styleHints()->startDragDistance(); + + QPoint position(200, 200); + int &axis = transpose ? position.ry() : position.rx(); + + // drag toward the aligned boundary. Outer mouse area 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->drag()->active(), true); + QCOMPARE(inner->drag()->active(), false); + QTest::mouseRelease(&view, Qt::LeftButton, 0, position); + + QVERIFY(!outer->drag()->active()); + + axis = 200; + outer->setX(50); + outer->setY(50); + + // drag away from the aligned boundary. Inner mouse area 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->drag()->active(), false); + QCOMPARE(inner->drag()->active(), true); + QTest::mouseRelease(&view, Qt::LeftButton, 0, position); +} + QTEST_MAIN(tst_QQuickMouseArea) #include "tst_qquickmousearea.moc" |