Handle MouseArea.enabled = false after mouse is pressed.
authorMartin Jones <martin.jones@nokia.com>
Mon, 5 Mar 2012 05:07:27 +0000 (15:07 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 5 Mar 2012 22:31:48 +0000 (23:31 +0100)
Currently this leaves the MouseArea in a broken state,
i.e. still in pressed state, and the next press after
it is re-enabled is ignored.

In this case we now allow subsequent mouse move or
release events to continue. Following the release,
no further press will be accepted.

Change-Id: I65a890da90e2166ad568505fffdbd3db6c97165b
Reviewed-by: Andrew den Exter <andrew.den-exter@nokia.com>
src/quick/items/qquickmousearea.cpp
tests/auto/quick/qquickmousearea/tst_qquickmousearea.cpp

index ec2c980..ef57242 100644 (file)
@@ -697,7 +697,7 @@ void QQuickMouseArea::mousePressEvent(QMouseEvent *event)
 void QQuickMouseArea::mouseMoveEvent(QMouseEvent *event)
 {
     Q_D(QQuickMouseArea);
-    if (!d->absorb) {
+    if (!d->absorb && !d->pressed) {
         QQuickItem::mouseMoveEvent(event);
         return;
     }
@@ -783,7 +783,7 @@ void QQuickMouseArea::mouseReleaseEvent(QMouseEvent *event)
 {
     Q_D(QQuickMouseArea);
     d->stealMouse = false;
-    if (!d->absorb) {
+    if (!d->absorb && !d->pressed) {
         QQuickItem::mouseReleaseEvent(event);
     } else {
         d->saveEvent(event);
@@ -820,7 +820,7 @@ void QQuickMouseArea::mouseDoubleClickEvent(QMouseEvent *event)
 void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
 {
     Q_D(QQuickMouseArea);
-    if (!d->absorb) {
+    if (!d->absorb && !d->pressed) {
         QQuickItem::hoverEnterEvent(event);
     } else {
         d->lastPos = event->posF();
@@ -837,7 +837,7 @@ void QQuickMouseArea::hoverEnterEvent(QHoverEvent *event)
 void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
 {
     Q_D(QQuickMouseArea);
-    if (!d->absorb) {
+    if (!d->absorb && !d->pressed) {
         QQuickItem::hoverMoveEvent(event);
     } else {
         d->lastPos = event->posF();
@@ -854,7 +854,7 @@ void QQuickMouseArea::hoverMoveEvent(QHoverEvent *event)
 void QQuickMouseArea::hoverLeaveEvent(QHoverEvent *event)
 {
     Q_D(QQuickMouseArea);
-    if (!d->absorb)
+    if (!d->absorb && !d->pressed)
         QQuickItem::hoverLeaveEvent(event);
     else
         setHovered(false);
@@ -935,7 +935,7 @@ bool QQuickMouseArea::sendMouseEvent(QMouseEvent *event)
 bool QQuickMouseArea::childMouseEventFilter(QQuickItem *i, QEvent *e)
 {
     Q_D(QQuickMouseArea);
-    if (!d->absorb || !isVisible() || !d->drag || !d->drag->filterChildren())
+    if (!d->pressed && (!d->absorb || !isVisible() || !d->drag || !d->drag->filterChildren()))
         return QQuickItem::childMouseEventFilter(i, e);
     switch (e->type()) {
     case QEvent::MouseButtonPress:
index 0fb82a6..4375e83 100644 (file)
@@ -72,6 +72,7 @@ private slots:
     void hoverPosition();
     void hoverPropagation();
     void hoverVisible();
+    void disableAfterPress();
 
 private:
     QQuickView *createView();
@@ -801,6 +802,110 @@ void tst_QQuickMouseArea::hoverVisible()
     delete canvas;
 }
 
+void tst_QQuickMouseArea::disableAfterPress()
+{
+    QQuickView *canvas = createView();
+    canvas->setSource(testFileUrl("dragging.qml"));
+    canvas->show();
+    canvas->requestActivateWindow();
+    QTest::qWait(20);
+    QVERIFY(canvas->rootObject() != 0);
+
+    QQuickMouseArea *mouseArea = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
+    QQuickDrag *drag = mouseArea->drag();
+    QVERIFY(mouseArea != 0);
+    QVERIFY(drag != 0);
+
+    QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
+    QSignalSpy mousePressSpy(mouseArea, SIGNAL(pressed(QQuickMouseEvent*)));
+    QSignalSpy mouseReleaseSpy(mouseArea, SIGNAL(released(QQuickMouseEvent*)));
+
+    // target
+    QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
+    QVERIFY(blackRect != 0);
+    QVERIFY(blackRect == drag->target());
+
+    QVERIFY(!drag->active());
+
+    QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+
+    QTRY_COMPARE(mousePressSpy.count(), 1);
+
+    QVERIFY(!drag->active());
+    QCOMPARE(blackRect->x(), 50.0);
+    QCOMPARE(blackRect->y(), 50.0);
+
+    // First move event triggers drag, second is acted upon.
+    // This is due to possibility of higher stacked area taking precedence.
+
+    QTest::mouseMove(canvas, QPoint(111,111));
+    QTest::qWait(50);
+    QTest::mouseMove(canvas, QPoint(122,122));
+
+    QTRY_COMPARE(mousePositionSpy.count(), 2);
+
+    QVERIFY(drag->active());
+    QCOMPARE(blackRect->x(), 72.0);
+    QCOMPARE(blackRect->y(), 72.0);
+
+    mouseArea->setEnabled(false);
+
+    // move should still be acted upon
+    QTest::mouseMove(canvas, QPoint(133,133));
+    QTest::qWait(50);
+    QTest::mouseMove(canvas, QPoint(144,144));
+
+    QTRY_COMPARE(mousePositionSpy.count(), 4);
+
+    QVERIFY(drag->active());
+    QCOMPARE(blackRect->x(), 94.0);
+    QCOMPARE(blackRect->y(), 94.0);
+
+    QVERIFY(mouseArea->pressed());
+    QVERIFY(mouseArea->hovered());
+
+    QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(144,144));
+
+    QTRY_COMPARE(mouseReleaseSpy.count(), 1);
+
+    QVERIFY(!drag->active());
+    QCOMPARE(blackRect->x(), 94.0);
+    QCOMPARE(blackRect->y(), 94.0);
+
+    QVERIFY(!mouseArea->pressed());
+    QVERIFY(!mouseArea->hovered()); // since hover is not enabled
+
+    // Next press will be ignored
+    blackRect->setX(50);
+    blackRect->setY(50);
+
+    mousePressSpy.clear();
+    mousePositionSpy.clear();
+    mouseReleaseSpy.clear();
+
+    QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
+    QTest::qWait(50);
+    QCOMPARE(mousePressSpy.count(), 0);
+
+    QTest::mouseMove(canvas, QPoint(111,111));
+    QTest::qWait(50);
+    QTest::mouseMove(canvas, QPoint(122,122));
+    QTest::qWait(50);
+
+    QCOMPARE(mousePositionSpy.count(), 0);
+
+    QVERIFY(!drag->active());
+    QCOMPARE(blackRect->x(), 50.0);
+    QCOMPARE(blackRect->y(), 50.0);
+
+    QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(122,122));
+    QTest::qWait(50);
+
+    QCOMPARE(mouseReleaseSpy.count(), 0);
+
+    delete canvas;
+}
+
 QTEST_MAIN(tst_QQuickMouseArea)
 
 #include "tst_qquickmousearea.moc"