MouseArea: use current value of drag.axis
authorAlberto Mardegan <info@mardy.it>
Thu, 5 Jul 2012 14:10:34 +0000 (18:10 +0400)
committerQt by Nokia <qt-info@nokia.com>
Mon, 16 Jul 2012 00:30:52 +0000 (02:30 +0200)
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 <damian.jansen@nokia.com>
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/quick/items/qquickmousearea.cpp
src/quick/items/qquickmousearea_p_p.h
tests/auto/quick/qquickmousearea/data/changeAxis.qml [new file with mode: 0644]
tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp

index a26c7c9..59da22b 100644 (file)
@@ -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;
             }
index aa28da8..743cf9e 100644 (file)
@@ -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 (file)
index 0000000..cf791df
--- /dev/null
@@ -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
+         }
+     }
+ }
index 7d42eb2..b2ef190 100644 (file)
@@ -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<QQuickMouseArea*>("mouseregion");
+    QQuickDrag *drag = mouseRegion->drag();
+    QVERIFY(mouseRegion != 0);
+    QVERIFY(drag != 0);
+
+    mouseRegion->setAcceptedButtons(Qt::LeftButton);
+
+    // target
+    QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("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"