Fix order of QSGItem mouse filtering.
authorMartin Jones <martin.jones@nokia.com>
Mon, 3 Oct 2011 00:59:16 +0000 (10:59 +1000)
committerQt by Nokia <qt-info@nokia.com>
Mon, 3 Oct 2011 02:44:51 +0000 (04:44 +0200)
QGraphicsView filtered child items beginning with the item's
parent, grandparent, greatgrandparent... QSGCanvas did the
opposite, which breaks the QML mouse handling element filtering logic.

Task-number: QTBUG-21446
Change-Id: I18e125305eef536237195895a7f41f88b532d4aa
Reviewed-on: http://codereview.qt-project.org/5819
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Bea Lam <bea.lam@nokia.com>
src/declarative/items/qsgcanvas.cpp
tests/auto/declarative/qsgcanvas/tst_qsgcanvas.cpp

index 2ced204..d4a74cd 100644 (file)
@@ -1439,14 +1439,14 @@ bool QSGCanvasPrivate::sendFilteredMouseEvent(QSGItem *target, QSGItem *item, QM
     if (!target)
         return false;
 
-    if (sendFilteredMouseEvent(target->parentItem(), item, event))
-        return true;
-
     QSGItemPrivate *targetPrivate = QSGItemPrivate::get(target);
     if (targetPrivate->filtersChildMouseEvents)
         if (target->childMouseEventFilter(item, event))
             return true;
 
+    if (sendFilteredMouseEvent(target->parentItem(), item, event))
+        return true;
+
     return false;
 }
 
index 32271b0..a504de8 100644 (file)
@@ -121,9 +121,11 @@ class TestTouchItem : public QSGRectangle
     Q_OBJECT
 public:
     TestTouchItem(QSGItem *parent = 0)
-        : QSGRectangle(parent), acceptEvents(true)
+        : QSGRectangle(parent), acceptEvents(true), mousePressId(0)
     {
         border()->setWidth(1);
+        setAcceptedMouseButtons(Qt::LeftButton);
+        setFiltersChildMouseEvents(true);
     }
 
     void reset() {
@@ -136,6 +138,7 @@ public:
 
     bool acceptEvents;
     TouchEventData lastEvent;
+    int mousePressId;
 
 protected:
     virtual void touchEvent(QTouchEvent *event) {
@@ -146,8 +149,20 @@ protected:
         lastEvent = makeTouchData(event->type(), event->widget(), event->touchPointStates(), event->touchPoints());
         event->accept();
     }
+
+    virtual void mousePressEvent(QMouseEvent *event) {
+        mousePressId = ++mousePressNum;
+    }
+
+    bool childMouseEventFilter(QSGItem *, QEvent *) {
+        mousePressId = ++mousePressNum;
+        return false;
+    }
+
+    static int mousePressNum;
 };
 
+int TestTouchItem::mousePressNum = 0;
 
 class ConstantUpdateItem : public QSGItem
 {
@@ -181,6 +196,7 @@ private slots:
     void touchEvent_propagation_data();
 
     void clearCanvas();
+    void mouseFiltering();
 };
 
 tst_qsgcanvas::tst_qsgcanvas()
@@ -464,6 +480,41 @@ void tst_qsgcanvas::clearCanvas()
     delete item;
 }
 
+void tst_qsgcanvas::mouseFiltering()
+{
+    QSGCanvas *canvas = new QSGCanvas;
+    canvas->resize(250, 250);
+    canvas->move(100, 100);
+    canvas->show();
+
+    TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem());
+    bottomItem->setObjectName("Bottom Item");
+    bottomItem->setSize(QSizeF(150, 150));
+
+    TestTouchItem *middleItem = new TestTouchItem(bottomItem);
+    middleItem->setObjectName("Middle Item");
+    middleItem->setPos(QPointF(50, 50));
+    middleItem->setSize(QSizeF(150, 150));
+
+    TestTouchItem *topItem = new TestTouchItem(middleItem);
+    topItem->setObjectName("Top Item");
+    topItem->setPos(QPointF(50, 50));
+    topItem->setSize(QSizeF(150, 150));
+
+    QPoint pos(100, 100);
+
+    QTest::mousePress(canvas, Qt::LeftButton, 0, pos);
+    QTest::qWait(50);
+
+    // Mouse filtering propagates down the stack, so the
+    // correct order is
+    // 1. middleItem filters event
+    // 2. bottomItem filters event
+    // 3. topItem receives event
+    QCOMPARE(middleItem->mousePressId, 1);
+    QCOMPARE(bottomItem->mousePressId, 2);
+    QCOMPARE(topItem->mousePressId, 3);
+}
 
 
 QTEST_MAIN(tst_qsgcanvas)