aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew den Exter <andrew.den.exter@jollamobile.com>2013-02-15 21:29:32 +1000
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-02-22 02:10:21 +0100
commit7a1282a9edd8afa4645d7d449ca2ed3746fb8d71 (patch)
tree5c6c9f1dd46bfbd55ad8c508581ae631e3ecce22
parentb939bc6300d79862340ff35dc8910663bda5744f (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.cpp49
-rw-r--r--tests/auto/quick/qquickmousearea/data/nestedStopAtBounds.qml44
-rw-r--r--tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp68
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"