Add basic TouchCancel handling to canvas.
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>
Fri, 10 Feb 2012 11:43:00 +0000 (13:43 +0200)
committerQt by Nokia <qt-info@nokia.com>
Mon, 13 Feb 2012 08:19:40 +0000 (09:19 +0100)
This makes sure that touchEvent() is properly called for all items in
the scene that have an active touch. It does not handle the cancel
event in any other special way.

Change-Id: Id66527ced8cb63d0b29f25f37c139e6d6aec9ba0
Reviewed-by: Michael Brasser <michael.brasser@nokia.com>
Reviewed-by: Martin Jones <martin.jones@nokia.com>
src/quick/items/qquickcanvas.cpp
tests/auto/qtquick2/qquickcanvas/tst_qquickcanvas.cpp

index 52344d6..cb60a23 100644 (file)
@@ -824,6 +824,7 @@ bool QQuickCanvas::event(QEvent *e)
     case QEvent::TouchBegin:
     case QEvent::TouchUpdate:
     case QEvent::TouchEnd:
+    case QEvent::TouchCancel:
     {
         QTouchEvent *touch = static_cast<QTouchEvent *>(e);
         d->translateTouchEvent(touch);
@@ -1165,8 +1166,12 @@ bool QQuickCanvasPrivate::deliverTouchEvent(QTouchEvent *event)
         qWarning("touchUpdateEvent");
     else if (event->type() == QEvent::TouchEnd)
         qWarning("touchEndEvent");
+    else if (event->type() == QEvent::TouchCancel)
+        qWarning("touchCancelEvent");
 #endif
 
+    Q_Q(QQuickCanvas);
+
     QHash<QQuickItem *, QList<QTouchEvent::TouchPoint> > updatedPoints;
 
     if (event->type() == QTouchEvent::TouchBegin) {     // all points are new touch points
@@ -1179,6 +1184,21 @@ bool QQuickCanvasPrivate::deliverTouchEvent(QTouchEvent *event)
         return event->isAccepted();
     }
 
+    if (event->type() == QTouchEvent::TouchCancel) {
+        // A TouchCancel event will typically not contain any points.
+        // Deliver it to all items that have active touches.
+        QSet<QQuickItem *> cancelDelivered;
+        foreach (QQuickItem *item, itemForTouchPointId) {
+            if (cancelDelivered.contains(item))
+                continue;
+            cancelDelivered.insert(item);
+            q->sendEvent(item, event);
+        }
+        // The next touch event can only be a TouchBegin so clean up.
+        itemForTouchPointId.clear();
+        return true;
+    }
+
     const QList<QTouchEvent::TouchPoint> &touchPoints = event->touchPoints();
     QList<QTouchEvent::TouchPoint> newPoints;
     QQuickItem *item = 0;
@@ -1497,6 +1517,7 @@ bool QQuickCanvas::sendEvent(QQuickItem *item, QEvent *e)
     case QEvent::TouchBegin:
     case QEvent::TouchUpdate:
     case QEvent::TouchEnd:
+    case QEvent::TouchCancel:
         // XXX todo - should sendEvent be doing this?  how does it relate to forwarded events?
         if (!d->sendFilteredMouseEvent(item->parentItem(), item, e)) {
             e->accept();
index 4a23842..eac0d85 100644 (file)
@@ -74,7 +74,8 @@ static QTouchEvent::TouchPoint makeTouchPoint(QQuickItem *item, const QPointF &p
     return tp;
 }
 
-static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states, const QList<QTouchEvent::TouchPoint>& touchPoints)
+static TouchEventData makeTouchData(QEvent::Type type, QWindow *w, Qt::TouchPointStates states = 0,
+                                    const QList<QTouchEvent::TouchPoint>& touchPoints = QList<QTouchEvent::TouchPoint>())
 {
     TouchEventData d = { type, 0, w, states, touchPoints };
     return d;
@@ -197,6 +198,7 @@ private slots:
     void touchEvent_basic();
     void touchEvent_propagation();
     void touchEvent_propagation_data();
+    void touchEvent_cancel();
 
     void clearCanvas();
 
@@ -475,6 +477,37 @@ void tst_qquickcanvas::touchEvent_propagation_data()
     QTest::newRow("opacity of 0") << true << true << 0.0;
 }
 
+void tst_qquickcanvas::touchEvent_cancel()
+{
+    TestTouchItem::clearMousePressCounter();
+
+    QQuickCanvas *canvas = new QQuickCanvas;
+    canvas->resize(250, 250);
+    canvas->move(100, 100);
+    canvas->show();
+
+    TestTouchItem *item = new TestTouchItem(canvas->rootItem());
+    item->setPos(QPointF(50, 50));
+    item->setSize(QSizeF(150, 150));
+
+    QPointF pos(10, 10);
+    QTest::touchEvent(canvas, touchDevice).press(0, item->mapToScene(pos).toPoint(),canvas);
+    QCoreApplication::processEvents();
+
+    QTRY_COMPARE(item->lastEvent.touchPoints.count(), 1);
+    TouchEventData d = makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(item,pos));
+    COMPARE_TOUCH_DATA(item->lastEvent, d);
+    item->reset();
+
+    QWindowSystemInterface::handleTouchCancelEvent(0, touchDevice);
+    QCoreApplication::processEvents();
+    d = makeTouchData(QEvent::TouchCancel, canvas);
+    COMPARE_TOUCH_DATA(item->lastEvent, d);
+
+    delete item;
+    delete canvas;
+}
+
 void tst_qquickcanvas::clearCanvas()
 {
     QQuickCanvas *canvas = new QQuickCanvas;