From 80dd824864df17bb1293a4438325f2b20306861b Mon Sep 17 00:00:00 2001 From: Alberto Mardegan Date: Thu, 5 Jul 2012 18:10:34 +0400 Subject: [PATCH] MouseArea: use current value of drag.axis If the drag.axis is changed while a drag operation is in progress, put it into action immediately. This allows, for example, start a dragging operation out of an item in a scrollable ListView to anywhere on the screen. See the linked bug number for an example. Task-number: QTBUG-26440 Change-Id: Id4219d44d1066dd962319086ac1f2a2a75bb2525 Reviewed-by: Damian Jansen Reviewed-by: Martin Jones --- src/quick/items/qquickmousearea.cpp | 22 +++---- src/quick/items/qquickmousearea_p_p.h | 2 - .../auto/quick/qquickmousearea/data/changeAxis.qml | 22 +++++++ .../quick/qquickmousearea/tst_qquickmousearea.cpp | 63 ++++++++++++++++++++ 4 files changed, 94 insertions(+), 15 deletions(-) create mode 100644 tests/auto/quick/qquickmousearea/data/changeAxis.qml diff --git a/src/quick/items/qquickmousearea.cpp b/src/quick/items/qquickmousearea.cpp index a26c7c9..59da22b 100644 --- a/src/quick/items/qquickmousearea.cpp +++ b/src/quick/items/qquickmousearea.cpp @@ -194,7 +194,7 @@ QQuickDragAttached *QQuickDrag::qmlAttachedProperties(QObject *obj) QQuickMouseAreaPrivate::QQuickMouseAreaPrivate() : enabled(true), hovered(false), longPress(false), - moved(false), dragX(true), dragY(true), stealMouse(false), doubleClick(false), preventStealing(false), + moved(false), stealMouse(false), doubleClick(false), preventStealing(false), propagateComposedEvents(false), pressed(0) #ifndef QT_NO_DRAGANDDROP , drag(0) @@ -722,13 +722,6 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event) d->pressAndHoldTimer.start(PressAndHoldDelay, this); setKeepMouseGrab(d->stealMouse); event->setAccepted(setPressed(event->button(), true)); - -#ifndef QT_NO_DRAGANDDROP - if (d->drag) { - d->dragX = drag()->axis() & QQuickDrag::XAxis; - d->dragY = drag()->axis() & QQuickDrag::YAxis; - } -#endif } } @@ -780,7 +773,10 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) QPointF dragPos = d->drag->target()->pos(); - if (d->dragX && d->drag->active()) { + 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(); @@ -788,7 +784,7 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) x = drag()->xmax(); dragPos.setX(x); } - if (d->dragY && d->drag->active()) { + if (dragY && d->drag->active()) { qreal y = (curLocalPos.y() - startLocalPos.y()) + startPos.y(); if (y < drag()->ymin()) y = drag()->ymin(); @@ -801,9 +797,9 @@ void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event) if (!keepMouseGrab()) { bool xDragged = QQuickCanvasPrivate::dragOverThreshold(dx, Qt::XAxis, event); bool yDragged = QQuickCanvasPrivate::dragOverThreshold(dy, Qt::YAxis, event); - if ((!d->dragY && !yDragged && d->dragX && xDragged) - || (!d->dragX && !xDragged && d->dragY && yDragged) - || (d->dragX && d->dragY && (xDragged || yDragged))) { + if ((!dragY && !yDragged && dragX && xDragged) + || (!dragX && !xDragged && dragY && yDragged) + || (dragX && dragY && (xDragged || yDragged))) { setKeepMouseGrab(true); d->stealMouse = true; } diff --git a/src/quick/items/qquickmousearea_p_p.h b/src/quick/items/qquickmousearea_p_p.h index aa28da8..743cf9e 100644 --- a/src/quick/items/qquickmousearea_p_p.h +++ b/src/quick/items/qquickmousearea_p_p.h @@ -89,8 +89,6 @@ public: bool hovered : 1; bool longPress : 1; bool moved : 1; - bool dragX : 1; - bool dragY : 1; bool stealMouse : 1; bool doubleClick : 1; bool preventStealing : 1; diff --git a/tests/auto/quick/qquickmousearea/data/changeAxis.qml b/tests/auto/quick/qquickmousearea/data/changeAxis.qml new file mode 100644 index 0000000..cf791df --- /dev/null +++ b/tests/auto/quick/qquickmousearea/data/changeAxis.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 +Rectangle { + id: whiteRect + width: 200 + height: 200 + color: "white" + Rectangle { + id: blackRect + objectName: "blackrect" + color: "black" + y: 50 + x: 50 + width: 100 + height: 100 + MouseArea { + objectName: "mouseregion" + anchors.fill: parent + drag.target: blackRect + drag.axis: blackRect.x <= 75 ? Drag.XandYAxis : Drag.YAxis + } + } + } diff --git a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp index 7d42eb2..b2ef190 100644 --- a/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp +++ b/tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp @@ -84,6 +84,7 @@ private slots: void transformedMouseArea(); void pressedMultipleButtons_data(); void pressedMultipleButtons(); + void changeAxis(); private: void acceptedButton_data(); @@ -1303,6 +1304,68 @@ void tst_QQuickMouseArea::pressedMultipleButtons() delete canvas; } +void tst_QQuickMouseArea::changeAxis() +{ + QQuickView *canvas = createView(); + + canvas->setSource(testFileUrl("changeAxis.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QTRY_VERIFY(canvas->rootObject() != 0); + + QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild("mouseregion"); + QQuickDrag *drag = mouseRegion->drag(); + QVERIFY(mouseRegion != 0); + QVERIFY(drag != 0); + + mouseRegion->setAcceptedButtons(Qt::LeftButton); + + // target + QQuickItem *blackRect = canvas->rootObject()->findChild("blackrect"); + QVERIFY(blackRect != 0); + QVERIFY(blackRect == drag->target()); + + QVERIFY(!drag->active()); + + // Start a diagonal drag + QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100, 100)); + + QVERIFY(!drag->active()); + QCOMPARE(blackRect->x(), 50.0); + QCOMPARE(blackRect->y(), 50.0); + + QTest::mouseMove(canvas, QPoint(111, 111)); + QTest::qWait(50); + QTest::mouseMove(canvas, QPoint(122, 122)); + + QTRY_VERIFY(drag->active()); + QCOMPARE(blackRect->x(), 72.0); + QCOMPARE(blackRect->y(), 72.0); + QCOMPARE(drag->axis(), QQuickDrag::XandYAxis); + + /* When blackRect.x becomes bigger than 75, the drag axis is changed to + * Drag.YAxis by the QML code. Verify that this happens, and that the drag + * movement is effectively constrained to the Y axis. */ + QTest::mouseMove(canvas, QPoint(133, 133)); + + QTRY_COMPARE(blackRect->x(), 83.0); + QTRY_COMPARE(blackRect->y(), 83.0); + QTRY_COMPARE(drag->axis(), QQuickDrag::YAxis); + + QTest::mouseMove(canvas, QPoint(144, 144)); + + QTRY_COMPARE(blackRect->y(), 94.0); + QCOMPARE(blackRect->x(), 83.0); + + QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(144, 144)); + + QTRY_VERIFY(!drag->active()); + QCOMPARE(blackRect->x(), 83.0); + QCOMPARE(blackRect->y(), 94.0); + + delete canvas; +} + QTEST_MAIN(tst_QQuickMouseArea) #include "tst_qquickmousearea.moc" -- 1.7.2.5