diff options
Diffstat (limited to 'tests')
-rw-r--r-- | tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp | 229 | ||||
-rw-r--r-- | tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp | 14 | ||||
-rw-r--r-- | tests/auto/quick/qquickpincharea/data/pinchproperties.qml | 3 | ||||
-rw-r--r-- | tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp | 156 | ||||
-rw-r--r-- | tests/auto/quick/quick.pro | 1 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/data/buttononflickable.qml | 42 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/data/buttonontouch.qml | 100 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/data/flickableonpinch.qml | 37 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/data/mouseonflickableonpinch.qml | 47 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/data/pinchonflickable.qml | 35 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/data/singleitem.qml | 18 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/data/twoitems.qml | 22 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/touchmouse.pro | 17 | ||||
-rw-r--r-- | tests/auto/quick/touchmouse/tst_touchmouse.cpp | 923 |
14 files changed, 1543 insertions, 101 deletions
diff --git a/tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp b/tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp index ed3dceb403..82af3678da 100644 --- a/tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp +++ b/tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp @@ -51,6 +51,7 @@ #include "../../shared/util.h" #include <QSignalSpy> #include <private/qquickcanvas_p.h> +#include <private/qguiapplication_p.h> struct TouchEventData { QEvent::Type type; @@ -144,7 +145,8 @@ class TestTouchItem : public QQuickRectangle Q_OBJECT public: TestTouchItem(QQuickItem *parent = 0) - : QQuickRectangle(parent), acceptEvents(true), mousePressId(0), + : QQuickRectangle(parent), acceptTouchEvents(true), acceptMouseEvents(true), + mousePressId(0), spinLoopWhenPressed(false), touchEventCount(0) { border()->setWidth(1); @@ -153,16 +155,20 @@ public: } void reset() { - acceptEvents = true; + acceptTouchEvents = acceptMouseEvents = true; setEnabled(true); setOpacity(1.0); lastEvent = makeTouchData(QEvent::None, canvas(), 0, QList<QTouchEvent::TouchPoint>());//CHECK_VALID + + lastVelocity = lastVelocityFromMouseMove = QVector2D(); + lastMousePos = QPointF(); + lastMouseCapabilityFlags = 0; } static void clearMousePressCounter() { - mousePressNum = 0; + mousePressNum = mouseMoveNum = mouseReleaseNum = 0; } void clearTouchEventCounter() @@ -170,40 +176,78 @@ public: touchEventCount = 0; } - bool acceptEvents; + bool acceptTouchEvents; + bool acceptMouseEvents; TouchEventData lastEvent; int mousePressId; bool spinLoopWhenPressed; int touchEventCount; + QVector2D lastVelocity; + QVector2D lastVelocityFromMouseMove; + QPointF lastMousePos; + int lastMouseCapabilityFlags; -protected: - virtual void touchEvent(QTouchEvent *event) { - if (!acceptEvents) { + void touchEvent(QTouchEvent *event) { + if (!acceptTouchEvents) { event->ignore(); return; } ++touchEventCount; lastEvent = makeTouchData(event->type(), event->window(), event->touchPointStates(), event->touchPoints()); - event->accept(); + if (event->device()->capabilities().testFlag(QTouchDevice::Velocity) && !event->touchPoints().isEmpty()) { + lastVelocity = event->touchPoints().first().velocity(); + } else { + lastVelocity = QVector2D(); + } if (spinLoopWhenPressed && event->touchPointStates().testFlag(Qt::TouchPointPressed)) { QCoreApplication::processEvents(); } } - virtual void mousePressEvent(QMouseEvent *) { + void mousePressEvent(QMouseEvent *e) { + if (!acceptMouseEvents) { + e->ignore(); + return; + } mousePressId = ++mousePressNum; + lastMousePos = e->pos(); + lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e); + } + + void mouseMoveEvent(QMouseEvent *e) { + if (!acceptMouseEvents) { + e->ignore(); + return; + } + ++mouseMoveNum; + lastVelocityFromMouseMove = QGuiApplicationPrivate::mouseEventVelocity(e); + lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e); + lastMousePos = e->pos(); + } + + void mouseReleaseEvent(QMouseEvent *e) { + if (!acceptMouseEvents) { + e->ignore(); + return; + } + ++mouseReleaseNum; + lastMousePos = e->pos(); + lastMouseCapabilityFlags = QGuiApplicationPrivate::mouseEventCaps(e); } bool childMouseEventFilter(QQuickItem *, QEvent *event) { + // TODO Is it a bug if a QTouchEvent comes here? if (event->type() == QEvent::MouseButtonPress) mousePressId = ++mousePressNum; return false; } - static int mousePressNum; + static int mousePressNum, mouseMoveNum, mouseReleaseNum; }; int TestTouchItem::mousePressNum = 0; +int TestTouchItem::mouseMoveNum = 0; +int TestTouchItem::mouseReleaseNum = 0; class ConstantUpdateItem : public QQuickItem { @@ -229,9 +273,13 @@ private slots: void initTestCase() { QQmlDataTest::initTestCase(); - touchDevice = new QTouchDevice(); + touchDevice = new QTouchDevice; touchDevice->setType(QTouchDevice::TouchScreen); QWindowSystemInterface::registerTouchDevice(touchDevice); + touchDeviceWithVelocity = new QTouchDevice; + touchDeviceWithVelocity->setType(QTouchDevice::TouchScreen); + touchDeviceWithVelocity->setCapabilities(QTouchDevice::Position | QTouchDevice::Velocity); + QWindowSystemInterface::registerTouchDevice(touchDeviceWithVelocity); } @@ -244,6 +292,9 @@ private slots: void touchEvent_propagation_data(); void touchEvent_cancel(); void touchEvent_reentrant(); + void touchEvent_velocity(); + + void mouseFromTouch_basic(); void clearCanvas(); @@ -262,6 +313,7 @@ private slots: void ownershipRootItem(); private: QTouchDevice *touchDevice; + QTouchDevice *touchDeviceWithVelocity; }; //If the item calls update inside updatePaintNode, it should schedule another update @@ -282,6 +334,7 @@ void tst_qquickcanvas::touchEvent_basic() canvas->resize(250, 250); canvas->setPos(100, 100); canvas->show(); + QTest::qWaitForWindowShown(canvas); TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem()); bottomItem->setObjectName("Bottom Item"); @@ -307,7 +360,8 @@ void tst_qquickcanvas::touchEvent_basic() QVERIFY(middleItem->lastEvent.touchPoints.isEmpty()); QVERIFY(bottomItem->lastEvent.touchPoints.isEmpty()); - TouchEventData d = makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem,pos)); + // At one point this was failing with kwin (KDE window manager) because canvas->setPos(100, 100) + // would put the decorated window at that position rather than the canvas itself. COMPARE_TOUCH_DATA(topItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(topItem, pos))); topItem->reset(); @@ -356,6 +410,10 @@ void tst_qquickcanvas::touchEvent_basic() COMPARE_TOUCH_DATA(bottomItem->lastEvent, makeTouchData(QEvent::TouchBegin, canvas, Qt::TouchPointPressed, makeTouchPoint(bottomItem, pos))); topItem->reset(); bottomItem->reset(); + // cleanup: what is pressed must be released + // Otherwise you will get an assertion failure: + // ASSERT: "itemForTouchPointId.isEmpty()" in file items/qquickcanvas.cpp + QTest::touchEvent(canvas, touchDevice).release(0, pos.toPoint(), canvas).release(1, pos.toPoint(), canvas); // move touch point from top item to bottom, and release QTest::touchEvent(canvas, touchDevice).press(0, topItem->mapToScene(pos).toPoint(),canvas); @@ -395,7 +453,8 @@ void tst_qquickcanvas::touchEvent_propagation() { TestTouchItem::clearMousePressCounter(); - QFETCH(bool, acceptEvents); + QFETCH(bool, acceptTouchEvents); + QFETCH(bool, acceptMouseEvents); QFETCH(bool, enableItem); QFETCH(qreal, itemOpacity); @@ -403,6 +462,7 @@ void tst_qquickcanvas::touchEvent_propagation() canvas->resize(250, 250); canvas->setPos(100, 100); canvas->show(); + QTest::qWaitForWindowShown(canvas); TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem()); bottomItem->setObjectName("Bottom Item"); @@ -424,7 +484,8 @@ void tst_qquickcanvas::touchEvent_propagation() QPoint pointInTopItem = topItem->mapToScene(pos).toPoint(); // (110, 110) overlaps with bottom & top items // disable topItem - topItem->acceptEvents = acceptEvents; + topItem->acceptTouchEvents = acceptTouchEvents; + topItem->acceptMouseEvents = acceptMouseEvents; topItem->setEnabled(enableItem); topItem->setOpacity(itemOpacity); @@ -450,7 +511,8 @@ void tst_qquickcanvas::touchEvent_propagation() middleItem->reset(); // disable middleItem as well - middleItem->acceptEvents = acceptEvents; + middleItem->acceptTouchEvents = acceptTouchEvents; + middleItem->acceptMouseEvents = acceptMouseEvents; middleItem->setEnabled(enableItem); middleItem->setOpacity(itemOpacity); @@ -467,7 +529,7 @@ void tst_qquickcanvas::touchEvent_propagation() bottomItem->reset(); // disable bottom item as well - bottomItem->acceptEvents = acceptEvents; + bottomItem->acceptTouchEvents = acceptTouchEvents; bottomItem->setEnabled(enableItem); bottomItem->setOpacity(itemOpacity); @@ -485,7 +547,7 @@ void tst_qquickcanvas::touchEvent_propagation() bottomItem->reset(); // disable middle item, touch on top item - middleItem->acceptEvents = acceptEvents; + middleItem->acceptTouchEvents = acceptTouchEvents; middleItem->setEnabled(enableItem); middleItem->setOpacity(itemOpacity); QTest::touchEvent(canvas, touchDevice).press(0, pointInTopItem, canvas); @@ -514,13 +576,14 @@ void tst_qquickcanvas::touchEvent_propagation() void tst_qquickcanvas::touchEvent_propagation_data() { - QTest::addColumn<bool>("acceptEvents"); + QTest::addColumn<bool>("acceptTouchEvents"); + QTest::addColumn<bool>("acceptMouseEvents"); QTest::addColumn<bool>("enableItem"); QTest::addColumn<qreal>("itemOpacity"); - QTest::newRow("disable events") << false << true << 1.0; - QTest::newRow("disable item") << true << false << 1.0; - QTest::newRow("opacity of 0") << true << true << 0.0; + QTest::newRow("disable events") << false << false << true << 1.0; + QTest::newRow("disable item") << true << true << false << 1.0; + QTest::newRow("opacity of 0") << true << true << true << 0.0; } void tst_qquickcanvas::touchEvent_cancel() @@ -531,6 +594,7 @@ void tst_qquickcanvas::touchEvent_cancel() canvas->resize(250, 250); canvas->setPos(100, 100); canvas->show(); + QTest::qWaitForWindowShown(canvas); TestTouchItem *item = new TestTouchItem(canvas->rootItem()); item->setPos(QPointF(50, 50)); @@ -562,6 +626,7 @@ void tst_qquickcanvas::touchEvent_reentrant() canvas->resize(250, 250); canvas->setPos(100, 100); canvas->show(); + QTest::qWaitForWindowShown(canvas); TestTouchItem *item = new TestTouchItem(canvas->rootItem()); @@ -590,6 +655,126 @@ void tst_qquickcanvas::touchEvent_reentrant() delete canvas; } +void tst_qquickcanvas::touchEvent_velocity() +{ + TestTouchItem::clearMousePressCounter(); + + QQuickCanvas *canvas = new QQuickCanvas; + canvas->resize(250, 250); + canvas->setPos(100, 100); + canvas->show(); + QTest::qWaitForWindowShown(canvas); + QTest::qWait(10); + + TestTouchItem *item = new TestTouchItem(canvas->rootItem()); + item->setPos(QPointF(50, 50)); + item->setSize(QSizeF(150, 150)); + + QList<QWindowSystemInterface::TouchPoint> points; + QWindowSystemInterface::TouchPoint tp; + tp.id = 1; + tp.state = Qt::TouchPointPressed; + QPoint pos = canvas->mapToGlobal(item->mapToScene(QPointF(10, 10)).toPoint()); + tp.area = QRectF(pos, QSizeF(4, 4)); + points << tp; + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + points[0].state = Qt::TouchPointMoved; + points[0].area.adjust(5, 5, 5, 5); + QVector2D velocity(1.5, 2.5); + points[0].velocity = velocity; + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + QCoreApplication::processEvents(); + QCOMPARE(item->touchEventCount, 2); + QCOMPARE(item->lastEvent.touchPoints.count(), 1); + QCOMPARE(item->lastVelocity, velocity); + + // Now have a transformation on the item and check if velocity and position are transformed accordingly. + item->setRotation(90); // clockwise + QMatrix4x4 transformMatrix; + transformMatrix.rotate(-90, 0, 0, 1); // counterclockwise + QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D(); + points[0].area.adjust(5, 5, 5, 5); + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + QCoreApplication::processEvents(); + QCOMPARE(item->lastVelocity, transformedVelocity); + QPoint itemLocalPos = item->mapFromScene(canvas->mapFromGlobal(points[0].area.center().toPoint())).toPoint(); + QPoint itemLocalPosFromEvent = item->lastEvent.touchPoints[0].pos().toPoint(); + QCOMPARE(itemLocalPos, itemLocalPosFromEvent); + + points[0].state = Qt::TouchPointReleased; + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + QCoreApplication::processEvents(); + delete item; + delete canvas; +} + +void tst_qquickcanvas::mouseFromTouch_basic() +{ + // Turn off accepting touch events with acceptTouchEvents. This + // should result in sending mouse events generated from the touch + // with the new event propagation system. + + TestTouchItem::clearMousePressCounter(); + QQuickCanvas *canvas = new QQuickCanvas; + canvas->resize(250, 250); + canvas->setPos(100, 100); + canvas->show(); + QTest::qWaitForWindowShown(canvas); + QTest::qWait(10); + + TestTouchItem *item = new TestTouchItem(canvas->rootItem()); + item->setPos(QPointF(50, 50)); + item->setSize(QSizeF(150, 150)); + item->acceptTouchEvents = false; + + QList<QWindowSystemInterface::TouchPoint> points; + QWindowSystemInterface::TouchPoint tp; + tp.id = 1; + tp.state = Qt::TouchPointPressed; + QPoint pos = canvas->mapToGlobal(item->mapToScene(QPointF(10, 10)).toPoint()); + tp.area = QRectF(pos, QSizeF(4, 4)); + points << tp; + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + points[0].state = Qt::TouchPointMoved; + points[0].area.adjust(5, 5, 5, 5); + QVector2D velocity(1.5, 2.5); + points[0].velocity = velocity; + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + points[0].state = Qt::TouchPointReleased; + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + QCoreApplication::processEvents(); + + // The item should have received a mouse press, move, and release. + QCOMPARE(item->mousePressNum, 1); + QCOMPARE(item->mouseMoveNum, 1); + QCOMPARE(item->mouseReleaseNum, 1); + QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(canvas->mapFromGlobal(points[0].area.center().toPoint())).toPoint()); + QCOMPARE(item->lastVelocityFromMouseMove, velocity); + QVERIFY((item->lastMouseCapabilityFlags & QTouchDevice::Velocity) != 0); + + // Now the same with a transformation. + item->setRotation(90); // clockwise + QMatrix4x4 transformMatrix; + transformMatrix.rotate(-90, 0, 0, 1); // counterclockwise + QVector2D transformedVelocity = transformMatrix.mapVector(velocity).toVector2D(); + points[0].state = Qt::TouchPointPressed; + points[0].velocity = velocity; + points[0].area = QRectF(pos, QSizeF(4, 4)); + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + points[0].state = Qt::TouchPointMoved; + points[0].area.adjust(5, 5, 5, 5); + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + QCoreApplication::processEvents(); + QCOMPARE(item->lastMousePos.toPoint(), item->mapFromScene(canvas->mapFromGlobal(points[0].area.center().toPoint())).toPoint()); + QCOMPARE(item->lastVelocityFromMouseMove, transformedVelocity); + + points[0].state = Qt::TouchPointReleased; + QWindowSystemInterface::handleTouchEvent(canvas, touchDeviceWithVelocity, points); + QCoreApplication::processEvents(); + delete item; + delete canvas; +} + void tst_qquickcanvas::clearCanvas() { QQuickCanvas *canvas = new QQuickCanvas; @@ -613,6 +798,7 @@ void tst_qquickcanvas::mouseFiltering() canvas->resize(250, 250); canvas->setPos(100, 100); canvas->show(); + QTest::qWaitForWindowShown(canvas); TestTouchItem *bottomItem = new TestTouchItem(canvas->rootItem()); bottomItem->setObjectName("Bottom Item"); @@ -820,6 +1006,7 @@ void tst_qquickcanvas::ignoreUnhandledMouseEvents() QQuickCanvas* canvas = new QQuickCanvas; canvas->resize(100, 100); canvas->show(); + QTest::qWaitForWindowShown(canvas); QQuickItem* item = new QQuickItem; item->setSize(QSizeF(100, 100)); diff --git a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp index c5ede2629e..9745e20d10 100644 --- a/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp +++ b/tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp @@ -570,30 +570,24 @@ void tst_QQuickMultiPointTouchArea::inFlickable() //moving one point vertically QTest::touchEvent(canvas, device).press(0, p1); - QTest::mousePress(canvas, Qt::LeftButton, 0, p1); p1 += QPoint(0,15); QTest::touchEvent(canvas, device).move(0, p1); - QTest::mouseMove(canvas, p1); p1 += QPoint(0,15); QTest::touchEvent(canvas, device).move(0, p1); - QTest::mouseMove(canvas, p1); p1 += QPoint(0,15); QTest::touchEvent(canvas, device).move(0, p1); - QTest::mouseMove(canvas, p1); p1 += QPoint(0,15); QTest::touchEvent(canvas, device).move(0, p1); - QTest::mouseMove(canvas, p1); QVERIFY(flickable->contentY() < 0); QCOMPARE(point11->pressed(), false); QCOMPARE(point12->pressed(), false); QTest::touchEvent(canvas, device).release(0, p1); - QTest::mouseRelease(canvas,Qt::LeftButton, 0, p1); QTest::qWait(50); QTRY_VERIFY(!flickable->isMoving()); @@ -736,32 +730,26 @@ void tst_QQuickMultiPointTouchArea::inFlickable2() // Check that we can still move the Flickable p1 = QPoint(50,100); QTest::touchEvent(canvas, device).press(0, p1); - QTest::mousePress(canvas, Qt::LeftButton, 0, p1); QCOMPARE(point11->pressed(), true); p1 += QPoint(0,15); QTest::touchEvent(canvas, device).move(0, p1); - QTest::mouseMove(canvas, p1); p1 += QPoint(0,15); QTest::touchEvent(canvas, device).move(0, p1); - QTest::mouseMove(canvas, p1); p1 += QPoint(0,15); QTest::touchEvent(canvas, device).move(0, p1); - QTest::mouseMove(canvas, p1); p1 += QPoint(0,15); QTest::touchEvent(canvas, device).move(0, p1); - QTest::mouseMove(canvas, p1); QVERIFY(flickable->contentY() < 0); QVERIFY(flickable->isMoving()); - QCOMPARE(point11->pressed(), false); + QCOMPARE(point11->pressed(), true); QTest::touchEvent(canvas, device).release(0, p1); - QTest::mouseRelease(canvas,Qt::LeftButton, 0, p1); QTest::qWait(50); QTRY_VERIFY(!flickable->isMoving()); diff --git a/tests/auto/quick/qquickpincharea/data/pinchproperties.qml b/tests/auto/quick/qquickpincharea/data/pinchproperties.qml index 44d116184e..6665e2f597 100644 --- a/tests/auto/quick/qquickpincharea/data/pinchproperties.qml +++ b/tests/auto/quick/qquickpincharea/data/pinchproperties.qml @@ -4,6 +4,7 @@ Rectangle { property variant center property real scale property int pointCount: 0 + property bool pinchActive: false width: 240; height: 320 color: "white" Rectangle { @@ -34,6 +35,7 @@ Rectangle { whiteRect.center = pinch.center whiteRect.scale = pinch.scale whiteRect.pointCount = pinch.pointCount; + whiteRect.pinchActive = true; } onPinchUpdated: { whiteRect.center = pinch.center @@ -44,6 +46,7 @@ Rectangle { whiteRect.center = pinch.center whiteRect.scale = pinch.scale whiteRect.pointCount = pinch.pointCount; + whiteRect.pinchActive = false; } } } diff --git a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp index 27efdf7e28..e0e4b6c4d8 100644 --- a/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp +++ b/tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp @@ -229,31 +229,41 @@ void tst_QQuickPinchArea::scale() QPoint p1(80, 80); QPoint p2(100, 100); - - QTest::touchEvent(canvas, device).press(0, p1, canvas); - QTest::touchEvent(canvas, device).stationary(0).press(1, p2, canvas); - p1 -= QPoint(10,10); - p2 += QPoint(10,10); - QTest::touchEvent(canvas, device).move(0, p1,canvas).move(1, p2,canvas); - - QCOMPARE(root->property("scale").toReal(), 1.0); - - p1 -= QPoint(10,10); - p2 += QPoint(10,10); - QTest::touchEvent(canvas, device).move(0, p1,canvas).move(1, p2,canvas); - - QCOMPARE(root->property("scale").toReal(), 1.5); - QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 - QCOMPARE(blackRect->scale(), 1.5); + { + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(canvas, device); + pinchSequence.press(0, p1, canvas).commit(); + // In order for the stationary point to remember its previous position, + // we have to reuse the same pinchSequence object. Otherwise if we let it + // be destroyed and then start a new sequence, point 0 will default to being + // stationary at 0, 0, and PinchArea will filter out that touchpoint because + // it is outside its bounds. + pinchSequence.stationary(0).press(1, p2, canvas).commit(); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1,canvas).move(1, p2,canvas).commit(); + + QCOMPARE(root->property("scale").toReal(), 1.0); + QVERIFY(root->property("pinchActive").toBool()); + + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1,canvas).move(1, p2,canvas).commit(); + + QCOMPARE(root->property("scale").toReal(), 1.5); + QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 + QCOMPARE(blackRect->scale(), 1.5); + } // scale beyond bound p1 -= QPoint(50,50); p2 += QPoint(50,50); - QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); - - QCOMPARE(blackRect->scale(), 2.0); - - QTest::touchEvent(canvas, device).release(0, p1, canvas).release(1, p2, canvas); + { + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(canvas, device); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + QCOMPARE(blackRect->scale(), 2.0); + pinchSequence.release(0, p1, canvas).release(1, p2, canvas).commit(); + } + QVERIFY(!root->property("pinchActive").toBool()); delete canvas; } @@ -282,21 +292,25 @@ void tst_QQuickPinchArea::pan() QPoint p1(80, 80); QPoint p2(100, 100); - - QTest::touchEvent(canvas, device).press(0, p1, canvas); - QTest::touchEvent(canvas, device).stationary(0).press(1, p2, canvas); - p1 += QPoint(10,10); - p2 += QPoint(10,10); - QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); - - QCOMPARE(root->property("scale").toReal(), 1.0); - - p1 += QPoint(10,10); - p2 += QPoint(10,10); - QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); + { + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(canvas, device); + pinchSequence.press(0, p1, canvas).commit(); + // In order for the stationary point to remember its previous position, + // we have to reuse the same pinchSequence object. + pinchSequence.stationary(0).press(1, p2, canvas).commit(); + p1 += QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1,canvas).move(1, p2,canvas).commit(); + + QCOMPARE(root->property("scale").toReal(), 1.0); + QVERIFY(root->property("pinchActive").toBool()); + + p1 += QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1,canvas).move(1, p2,canvas).commit(); + } QCOMPARE(root->property("center").toPointF(), QPointF(60, 60)); // blackrect is at 50,50 - QCOMPARE(blackRect->x(), 60.0); QCOMPARE(blackRect->y(), 60.0); @@ -309,6 +323,7 @@ void tst_QQuickPinchArea::pan() QCOMPARE(blackRect->y(), 160.0); QTest::touchEvent(canvas, device).release(0, p1, canvas).release(1, p2, canvas); + QVERIFY(!root->property("pinchActive").toBool()); delete canvas; } @@ -341,57 +356,64 @@ void tst_QQuickPinchArea::retouch() QPoint p1(80, 80); QPoint p2(100, 100); + { + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(canvas, device); + pinchSequence.press(0, p1, canvas).commit(); + // In order for the stationary point to remember its previous position, + // we have to reuse the same pinchSequence object. + pinchSequence.stationary(0).press(1, p2, canvas).commit(); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1,canvas).move(1, p2,canvas).commit(); - QTest::touchEvent(canvas, device).press(0, p1, canvas); - QTest::touchEvent(canvas, device).stationary(0).press(1, p2, canvas); - p1 -= QPoint(10,10); - p2 += QPoint(10,10); - QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); - - QCOMPARE(root->property("scale").toReal(), 1.0); + QCOMPARE(root->property("scale").toReal(), 1.0); + QVERIFY(root->property("pinchActive").toBool()); - p1 -= QPoint(10,10); - p2 += QPoint(10,10); - QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1,canvas).move(1, p2,canvas).commit(); - QCOMPARE(startedSpy.count(), 1); + QCOMPARE(startedSpy.count(), 1); - QCOMPARE(root->property("scale").toReal(), 1.5); - QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 - QCOMPARE(blackRect->scale(), 1.5); + QCOMPARE(root->property("scale").toReal(), 1.5); + QCOMPARE(root->property("center").toPointF(), QPointF(40, 40)); // blackrect is at 50,50 + QCOMPARE(blackRect->scale(), 1.5); - QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 2); + QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 2); - QCOMPARE(startedSpy.count(), 1); - QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(startedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 0); - QTest::touchEvent(canvas, device).stationary(0).release(1, p2, canvas); + // Hold down the first finger but release the second one + pinchSequence.stationary(0).release(1, p2, canvas).commit(); - QCOMPARE(startedSpy.count(), 1); - QCOMPARE(finishedSpy.count(), 0); + QCOMPARE(startedSpy.count(), 1); + QCOMPARE(finishedSpy.count(), 0); - QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 1); + QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 1); - QTest::touchEvent(canvas, device).stationary(0).press(1, p2, canvas); - p1 -= QPoint(10,10); - p2 += QPoint(10,10); - QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); + // Keep holding down the first finger and re-touch the second one, then move them both + pinchSequence.stationary(0).press(1, p2, canvas).commit(); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); - // Lifting and retouching results in onPinchStarted being called again - QCOMPARE(startedSpy.count(), 2); - QCOMPARE(finishedSpy.count(), 0); + // Lifting and retouching results in onPinchStarted being called again + QCOMPARE(startedSpy.count(), 2); + QCOMPARE(finishedSpy.count(), 0); - QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 2); + QCOMPARE(canvas->rootObject()->property("pointCount").toInt(), 2); - QTest::touchEvent(canvas, device).release(0, p1, canvas).release(1, p2, canvas); + pinchSequence.release(0, p1, canvas).release(1, p2, canvas).commit(); - QCOMPARE(startedSpy.count(), 2); - QCOMPARE(finishedSpy.count(), 1); + QVERIFY(!root->property("pinchActive").toBool()); + QCOMPARE(startedSpy.count(), 2); + QCOMPARE(finishedSpy.count(), 1); + } delete canvas; } - QQuickView *tst_QQuickPinchArea::createView() { QQuickView *canvas = new QQuickView(0); diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro index 2ef6dc0357..fd78da2746 100644 --- a/tests/auto/quick/quick.pro +++ b/tests/auto/quick/quick.pro @@ -70,6 +70,7 @@ QUICKTESTS = \ qquickview \ qquickcanvasitem \ qquickscreen \ + touchmouse \ SUBDIRS += $$PUBLICTESTS diff --git a/tests/auto/quick/touchmouse/data/buttononflickable.qml b/tests/auto/quick/touchmouse/data/buttononflickable.qml new file mode 100644 index 0000000000..95a993f806 --- /dev/null +++ b/tests/auto/quick/touchmouse/data/buttononflickable.qml @@ -0,0 +1,42 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Rectangle { + id: root + width: 300 + height: 500 + color: "green" + + Flickable { + objectName: "flickable" + anchors.fill: parent + contentHeight: 1000 + + Rectangle { + objectName: "button" + y: 100 + height: 100 + width: parent.width + + EventItem { + objectName: "eventItem1" + height: 100 + width: 300 + } + } + + Rectangle { + objectName: "button2" + y: 300 + height: 100 + width: parent.width + + EventItem { + objectName: "eventItem2" + height: 100 + width: 300 + } + } + } +} + diff --git a/tests/auto/quick/touchmouse/data/buttonontouch.qml b/tests/auto/quick/touchmouse/data/buttonontouch.qml new file mode 100644 index 0000000000..dcd2573f2e --- /dev/null +++ b/tests/auto/quick/touchmouse/data/buttonontouch.qml @@ -0,0 +1,100 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Rectangle { + id: root + width: 300 + height: 800 + color: "green" + + Rectangle { + color: "blue" + height: 400 + width: parent.width + + + PinchArea { + pinch.target: button1 + objectName: "pincharea" + anchors.fill: parent + + pinch.minimumScale: 0.1 + pinch.maximumScale: 10.0 + } + + Rectangle { + + id: button1 + objectName: "button1" + y: 100 + height: 100 + width: parent.width + Text { text: "Button 1" } + + EventItem { + objectName: "eventItem1" + height: 100 + width: 300 + } + } + + Rectangle { + objectName: "button2" + y: 300 + height: 100 + width: parent.width + Text { text: "Button 2" } + + EventItem { + objectName: "eventItem2" + height: 100 + width: 300 + } + } + } + + Rectangle { + y: 400 + width: parent.width + height: parent.height + color: "red" + + MultiPointTouchArea { + objectName: "toucharea" + anchors.fill: parent + + y: 400 + height: 400 + + Rectangle { + objectName: "button3" + y: 100 + height: 100 + width: parent.width + Text { text: "Button 3" } + + EventItem { + objectName: "eventItem3" + height: 100 + width: 300 + } + } + + Rectangle { + objectName: "button4" + y: 300 + height: 100 + width: parent.width + Text { text: "Button 4" } + + EventItem { + objectName: "eventItem4" + height: 100 + width: 300 + } + } + + } + } +} + diff --git a/tests/auto/quick/touchmouse/data/flickableonpinch.qml b/tests/auto/quick/touchmouse/data/flickableonpinch.qml new file mode 100644 index 0000000000..9c9a197d66 --- /dev/null +++ b/tests/auto/quick/touchmouse/data/flickableonpinch.qml @@ -0,0 +1,37 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Rectangle { + id: root + width: 600 + height: 600 + color: "green" + + PinchArea { + objectName: "pincharea" + pinch.target: rect + anchors.fill: parent + + pinch.minimumScale: 1.0 + pinch.maximumScale: 10.0 + + Flickable { + objectName: "flickable" + anchors.fill: parent + contentHeight: 1000 + contentWidth: 1000 + + Rectangle { + objectName: "rect" + id: rect + color: "blue" + x: 200 + y: 200 + width: 400 + height: 400 + } + } + } + +} + diff --git a/tests/auto/quick/touchmouse/data/mouseonflickableonpinch.qml b/tests/auto/quick/touchmouse/data/mouseonflickableonpinch.qml new file mode 100644 index 0000000000..015391f291 --- /dev/null +++ b/tests/auto/quick/touchmouse/data/mouseonflickableonpinch.qml @@ -0,0 +1,47 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Rectangle { + id: root + width: 600 + height: 600 + color: "green" + + PinchArea { + objectName: "pincharea" + pinch.target: rect + anchors.fill: parent + + pinch.minimumScale: 1.0 + pinch.maximumScale: 10.0 + + Flickable { + objectName: "flickable" + anchors.fill: parent + contentHeight: 1000 + contentWidth: 1000 + + MouseArea { + anchors.fill: parent + onClicked: { + if (rect.color == "#000000") + rect.color = "#00ff00" + else + rect.color = "#000000" + } + } + + Rectangle { + objectName: "rect" + id: rect + color: "blue" + x: 200 + y: 200 + width: 400 + height: 400 + } + } + } + +} + diff --git a/tests/auto/quick/touchmouse/data/pinchonflickable.qml b/tests/auto/quick/touchmouse/data/pinchonflickable.qml new file mode 100644 index 0000000000..2a7a91006e --- /dev/null +++ b/tests/auto/quick/touchmouse/data/pinchonflickable.qml @@ -0,0 +1,35 @@ +import QtQuick 2.0 +//import Qt.test 1.0 + +Rectangle { + id: root + width: 600 + height: 600 + color: "green" + + Flickable { + objectName: "flickable" + anchors.fill: parent + contentHeight: 1000 + contentWidth: 1000 + + Rectangle { + objectName: "rect" + id: rect + color: "blue" + x: 200 + y: 200 + width: 400 + height: 400 + } + PinchArea { + objectName: "pincharea" + pinch.target: rect + anchors.fill: parent + + pinch.minimumScale: 1.0 + pinch.maximumScale: 10.0 + } + } +} + diff --git a/tests/auto/quick/touchmouse/data/singleitem.qml b/tests/auto/quick/touchmouse/data/singleitem.qml new file mode 100644 index 0000000000..76d3a51da9 --- /dev/null +++ b/tests/auto/quick/touchmouse/data/singleitem.qml @@ -0,0 +1,18 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Rectangle { + id: root + width: 320 + height: 480 + color: "green" + + EventItem { + objectName: "eventItem1" + x: 5 + y: 5 + height: 30 + width: 30 + } +} + diff --git a/tests/auto/quick/touchmouse/data/twoitems.qml b/tests/auto/quick/touchmouse/data/twoitems.qml new file mode 100644 index 0000000000..afbf35fe1a --- /dev/null +++ b/tests/auto/quick/touchmouse/data/twoitems.qml @@ -0,0 +1,22 @@ +import QtQuick 2.0 +import Qt.test 1.0 + +Rectangle { + id: root + width: 320 + height: 480 + color: "green" + + EventItem { + objectName: "eventItem1" + height: 200 + width: 100 + + EventItem { + objectName: "eventItem2" + height: 100 + width: 100 + } + } +} + diff --git a/tests/auto/quick/touchmouse/touchmouse.pro b/tests/auto/quick/touchmouse/touchmouse.pro new file mode 100644 index 0000000000..d0b0fa79f2 --- /dev/null +++ b/tests/auto/quick/touchmouse/touchmouse.pro @@ -0,0 +1,17 @@ +CONFIG += testcase + +TARGET = tst_touchmouse +QT += core-private gui-private qml-private quick-private v8-private testlib + +macx:CONFIG -= app_bundle + +SOURCES += tst_touchmouse.cpp + +include (../../shared/util.pri) + +TESTDATA = data/* + +# OTHER_FILES += data/foo.qml + +CONFIG += parallel_test + diff --git a/tests/auto/quick/touchmouse/tst_touchmouse.cpp b/tests/auto/quick/touchmouse/tst_touchmouse.cpp new file mode 100644 index 0000000000..7ab9387ea7 --- /dev/null +++ b/tests/auto/quick/touchmouse/tst_touchmouse.cpp @@ -0,0 +1,923 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the QtQml module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include <QtTest/QtTest> + +#include <QtGui/qstylehints.h> + +#include <QtQuick/qquickview.h> +#include <QtQuick/qquickitem.h> +#include <QtQuick/private/qquickmousearea_p.h> +#include <QtQuick/private/qquickmultipointtoucharea_p.h> +#include <QtQuick/private/qquickpincharea_p.h> +#include <QtQuick/private/qquickflickable_p.h> + +#include <private/qquickcanvas_p.h> + +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlproperty.h> + +#include "../../shared/util.h" + +struct Event +{ + Event(QEvent::Type t, QPoint mouse, QPoint global) + :type(t), mousePos(mouse), mousePosGlobal(global) + {} + + Event(QEvent::Type t, QList<QTouchEvent::TouchPoint> touch) + :type(t), points(touch) + {} + + QEvent::Type type; + QPoint mousePos; + QPoint mousePosGlobal; + QList<QTouchEvent::TouchPoint> points; +}; + +class EventItem : public QQuickItem +{ + Q_OBJECT +public: + EventItem(QQuickItem *parent = 0) + : QQuickItem(parent), acceptMouse(false), acceptTouch(false), filterTouch(false) + {} + + void touchEvent(QTouchEvent *event) + { + eventList.append(Event(event->type(), event->touchPoints())); + event->setAccepted(acceptTouch); + } + void mousePressEvent(QMouseEvent *event) + { + eventList.append(Event(event->type(), event->pos(), event->globalPos())); + event->setAccepted(acceptMouse); + } + void mouseMoveEvent(QMouseEvent *event) + { + eventList.append(Event(event->type(), event->pos(), event->globalPos())); + event->setAccepted(acceptMouse); + } + void mouseReleaseEvent(QMouseEvent *event) + { + eventList.append(Event(event->type(), event->pos(), event->globalPos())); + event->setAccepted(acceptMouse); + } + void mouseDoubleClickEvent(QMouseEvent *event) + { + eventList.append(Event(event->type(), event->pos(), event->globalPos())); + event->setAccepted(acceptMouse); + } + bool event(QEvent *event) { + if (event->type() == QEvent::UngrabMouse) { + eventList.append(Event(event->type(), QPoint(0,0), QPoint(0,0))); + } + return QQuickItem::event(event); + } + + QList<Event> eventList; + bool acceptMouse; + bool acceptTouch; + bool filterTouch; // when used as event filter + + bool eventFilter(QObject *, QEvent *event) + { + if (event->type() == QEvent::TouchBegin || + event->type() == QEvent::TouchUpdate || + event->type() == QEvent::TouchCancel || + event->type() == QEvent::TouchEnd) { + QTouchEvent *touch = static_cast<QTouchEvent*>(event); + eventList.append(Event(event->type(), touch->touchPoints())); + if (filterTouch) + event->accept(); + return true; + } + return false; + } +}; + +class tst_TouchMouse : public QQmlDataTest +{ + Q_OBJECT +public: + tst_TouchMouse() + :device(0) + {} + +private slots: + void initTestCase(); + + void simpleTouchEvent(); + void eventFilter(); + void mouse(); + void touchOverMouse(); + void mouseOverTouch(); + + void buttonOnFlickable(); + void buttonOnTouch(); + + void pinchOnFlickable(); + void flickableOnPinch(); + void mouseOnFlickableOnPinch(); + +private: + QQuickView *createView(); + QTouchDevice *device; +}; + +QQuickView *tst_TouchMouse::createView() +{ + QQuickView *canvas = new QQuickView(0); + canvas->setGeometry(0,0,240,320); + + return canvas; +} + +void tst_TouchMouse::initTestCase() +{ + // This test assumes that we don't get synthesized mouse events from QGuiApplication + qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false); + + QQmlDataTest::initTestCase(); + qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem"); + if (!device) { + device = new QTouchDevice; + device->setType(QTouchDevice::TouchScreen); + QWindowSystemInterface::registerTouchDevice(device); + } +} + +void tst_TouchMouse::simpleTouchEvent() +{ + QQuickView *canvas = createView(); + + canvas->setSource(testFileUrl("singleitem.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QTest::qWaitForWindowShown(canvas); + QVERIFY(canvas->rootObject() != 0); + + EventItem *eventItem1 = canvas->rootObject()->findChild<EventItem*>("eventItem1"); + QVERIFY(eventItem1); + + // Do not accept touch or mouse + QPoint p1; + p1 = QPoint(20, 20); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 1); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); + p1 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 1); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 1); + eventItem1->eventList.clear(); + + // Accept touch + eventItem1->acceptTouch = true; + p1 = QPoint(20, 20); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 1); + p1 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 2); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 3); + eventItem1->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Accept mouse + eventItem1->acceptTouch = false; + eventItem1->acceptMouse = true; + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + p1 = QPoint(20, 20); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas); + QCOMPARE(canvasPriv->mouseGrabberItem, eventItem1); + + QPoint localPos = eventItem1->mapFromScene(p1).toPoint(); + QPoint globalPos = canvas->mapToGlobal(p1); + QPoint scenePos = p1; // item is at 0,0 + QCOMPARE(eventItem1->eventList.at(0).points.at(0).pos().toPoint(), localPos); + QCOMPARE(eventItem1->eventList.at(0).points.at(0).scenePos().toPoint(), scenePos); + QCOMPARE(eventItem1->eventList.at(0).points.at(0).screenPos().toPoint(), globalPos); + QCOMPARE(eventItem1->eventList.at(1).mousePos, localPos); + QCOMPARE(eventItem1->eventList.at(1).mousePosGlobal, globalPos); + + p1 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 6); + QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd); + QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease); + eventItem1->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Accept mouse buttons but not the event + eventItem1->acceptTouch = false; + eventItem1->acceptMouse = false; + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + p1 = QPoint(20, 20); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + p1 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 2); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 2); + eventItem1->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Accept touch and mouse + eventItem1->acceptTouch = true; + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + p1 = QPoint(20, 20); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 1); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); + p1 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchUpdate); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 3); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd); + eventItem1->eventList.clear(); + + delete canvas; +} + +void tst_TouchMouse::eventFilter() +{ +// // install event filter on item and see that it can grab events +// QQuickView *canvas = createView(); + +// canvas->setSource(testFileUrl("singleitem.qml")); +// canvas->show(); +// canvas->requestActivateWindow(); +// QVERIFY(canvas->rootObject() != 0); + +// EventItem *eventItem1 = canvas->rootObject()->findChild<EventItem*>("eventItem1"); +// QVERIFY(eventItem1); +// eventItem1->acceptTouch = true; + +// EventItem *filter = new EventItem; +// filter->filterTouch = true; +// eventItem1->installEventFilter(filter); + +// QPoint p1 = QPoint(20, 20); +// QTest::touchEvent(canvas, device).press(0, p1, canvas); +// // QEXPECT_FAIL("", "We do not implement event filters correctly", Abort); +// QCOMPARE(eventItem1->eventList.size(), 0); +// QCOMPARE(filter->eventList.size(), 1); +// QTest::touchEvent(canvas, device).release(0, p1, canvas); +// QCOMPARE(eventItem1->eventList.size(), 0); +// QCOMPARE(filter->eventList.size(), 2); + +// delete filter; +// delete canvas; +} + +void tst_TouchMouse::mouse() +{ + // eventItem1 + // - eventItem2 + + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + QQuickView *canvas = createView(); + + canvas->setSource(testFileUrl("twoitems.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + EventItem *eventItem1 = canvas->rootObject()->findChild<EventItem*>("eventItem1"); + QVERIFY(eventItem1); + EventItem *eventItem2 = canvas->rootObject()->findChild<EventItem*>("eventItem2"); + QVERIFY(eventItem2); + QTest::qWaitForWindowShown(canvas); + + // bottom item likes mouse, top likes touch + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + eventItem1->acceptMouse = true; + // item 2 doesn't accept anything, thus it sees a touch pass by + QPoint p1 = QPoint(30, 30); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + + delete canvas; +} + +void tst_TouchMouse::touchOverMouse() +{ + // eventItem1 + // - eventItem2 + + QQuickView *canvas = createView(); + + canvas->setSource(testFileUrl("twoitems.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + EventItem *eventItem1 = canvas->rootObject()->findChild<EventItem*>("eventItem1"); + QVERIFY(eventItem1); + EventItem *eventItem2 = canvas->rootObject()->findChild<EventItem*>("eventItem2"); + QVERIFY(eventItem2); + + // bottom item likes mouse, top likes touch + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + eventItem2->acceptTouch = true; + + QTest::qWaitForWindowShown(canvas); + + QCOMPARE(eventItem1->eventList.size(), 0); + QPoint p1 = QPoint(20, 20); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 0); + QCOMPARE(eventItem2->eventList.size(), 1); + QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin); + p1 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas); + QCOMPARE(eventItem2->eventList.size(), 2); + QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem2->eventList.size(), 3); + QCOMPARE(eventItem2->eventList.at(2).type, QEvent::TouchEnd); + eventItem2->eventList.clear(); + + delete canvas; +} + +void tst_TouchMouse::mouseOverTouch() +{ + // eventItem1 + // - eventItem2 + + QQuickView *canvas = createView(); + + canvas->setSource(testFileUrl("twoitems.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + EventItem *eventItem1 = canvas->rootObject()->findChild<EventItem*>("eventItem1"); + QVERIFY(eventItem1); + EventItem *eventItem2 = canvas->rootObject()->findChild<EventItem*>("eventItem2"); + QVERIFY(eventItem2); + + // bottom item likes mouse, top likes touch + eventItem1->acceptTouch = true; + eventItem2->setAcceptedMouseButtons(Qt::LeftButton); + eventItem2->acceptMouse = true; + + QTest::qWaitForWindowShown(canvas); + + QPoint p1 = QPoint(20, 20); + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 0); + QCOMPARE(eventItem2->eventList.size(), 2); + QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin); + QCOMPARE(eventItem2->eventList.at(1).type, QEvent::MouseButtonPress); + + +// p1 += QPoint(10, 0); +// QTest::touchEvent(canvas, device).move(0, p1, canvas); +// QCOMPARE(eventItem2->eventList.size(), 1); +// QTest::touchEvent(canvas, device).release(0, p1, canvas); +// QCOMPARE(eventItem2->eventList.size(), 1); +// eventItem2->eventList.clear(); + + delete canvas; +} + +void tst_TouchMouse::buttonOnFlickable() +{ + // flickable - height 500 / 1000 + // - eventItem1 y: 100, height 100 + // - eventItem2 y: 300, height 100 + + QQuickView *canvas = createView(); + + canvas->setSource(testFileUrl("buttononflickable.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + QQuickFlickable *flickable = canvas->rootObject()->findChild<QQuickFlickable*>("flickable"); + QVERIFY(flickable); + + // should a mouse area button be clickable on top of flickable? yes :) + EventItem *eventItem1 = canvas->rootObject()->findChild<EventItem*>("eventItem1"); + QVERIFY(eventItem1); + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + eventItem1->acceptMouse = true; + + // should a touch button be touchable on top of flickable? yes :) + EventItem *eventItem2 = canvas->rootObject()->findChild<EventItem*>("eventItem2"); + QVERIFY(eventItem2); + QCOMPARE(eventItem2->eventList.size(), 0); + eventItem2->acceptTouch = true; + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // check that buttons are clickable + // mouse button + QCOMPARE(eventItem1->eventList.size(), 0); + QPoint p1 = QPoint(20, 130); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease); + eventItem1->eventList.clear(); + + // touch button + p1 = QPoint(10, 310); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem2->eventList.size(), 1); + QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem2->eventList.size(), 2); + QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchEnd); + QCOMPARE(eventItem1->eventList.size(), 0); + eventItem2->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // click above button, no events please + p1 = QPoint(10, 90); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 0); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 0); + eventItem1->eventList.clear(); + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // check that flickable moves - mouse button + QCOMPARE(eventItem1->eventList.size(), 0); + p1 = QPoint(10, 110); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + + QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas); + QCOMPARE(canvasPriv->touchMouseId, 0); + QCOMPARE(canvasPriv->itemForTouchPointId[0], eventItem1); + QCOMPARE(canvasPriv->mouseGrabberItem, eventItem1); + + p1 += QPoint(0, -10); + QPoint p2 = p1 + QPoint(0, -10); + QPoint p3 = p2 + QPoint(0, -10); + QTest::qWait(10); + QTest::touchEvent(canvas, device).move(0, p1, canvas); + QTest::qWait(10); + QTest::touchEvent(canvas, device).move(0, p2, canvas); + QTest::qWait(10); + QTest::touchEvent(canvas, device).move(0, p3, canvas); + + // we cannot really know when the events get grabbed away + QVERIFY(eventItem1->eventList.size() >= 4); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove); + + QCOMPARE(canvasPriv->mouseGrabberItem, flickable); + QVERIFY(flickable->isMovingVertically()); + + QTest::touchEvent(canvas, device).release(0, p3, canvas); + delete canvas; +} + +void tst_TouchMouse::buttonOnTouch() +{ + // 400x800 + // PinchArea - height 400 + // - eventItem1 y: 100, height 100 + // - eventItem2 y: 300, height 100 + // MultiPointTouchArea - height 400 + // - eventItem1 y: 100, height 100 + // - eventItem2 y: 300, height 100 + + QQuickView *canvas = createView(); + canvas->setSource(testFileUrl("buttonontouch.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea"); + QVERIFY(pinchArea); + QQuickItem *button1 = canvas->rootObject()->findChild<QQuickItem*>("button1"); + QVERIFY(button1); + EventItem *eventItem1 = canvas->rootObject()->findChild<EventItem*>("eventItem1"); + QVERIFY(eventItem1); + EventItem *eventItem2 = canvas->rootObject()->findChild<EventItem*>("eventItem2"); + QVERIFY(eventItem2); + + QQuickMultiPointTouchArea *touchArea = canvas->rootObject()->findChild<QQuickMultiPointTouchArea*>("toucharea"); + QVERIFY(touchArea); + EventItem *eventItem3 = canvas->rootObject()->findChild<EventItem*>("eventItem3"); + QVERIFY(eventItem3); + EventItem *eventItem4 = canvas->rootObject()->findChild<EventItem*>("eventItem4"); + QVERIFY(eventItem4); + + + // Test the common case of a mouse area on top of pinch + eventItem1->setAcceptedMouseButtons(Qt::LeftButton); + eventItem1->acceptMouse = true; + + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Normal touch click + QPoint p1 = QPoint(10, 110); + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QTest::touchEvent(canvas, device).release(0, p1, canvas); + QCOMPARE(eventItem1->eventList.size(), 4); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd); + QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease); + eventItem1->eventList.clear(); + + // Normal mouse click + QTest::mouseClick(canvas, Qt::LeftButton, 0, p1); + QCOMPARE(eventItem1->eventList.size(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease); + eventItem1->eventList.clear(); + + // Pinch starting on the PinchArea should work + p1 = QPoint(40, 10); + QPoint p2 = QPoint(60, 10); + + // Start the events after each other + QTest::touchEvent(canvas, device).press(0, p1, canvas); + QTest::touchEvent(canvas, device).stationary(0).press(1, p2, canvas); + + QCOMPARE(button1->scale(), 1.0); + + // This event seems to be discarded, let's ignore it for now until someone digs into pincharea + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); + + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); +// QCOMPARE(button1->scale(), 1.5); + qDebug() << "Button scale: " << button1->scale(); + + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); +// QCOMPARE(button1->scale(), 2.0); + qDebug() << "Button scale: " << button1->scale(); + + QTest::touchEvent(canvas, device).release(0, p1, canvas).release(1, p2, canvas); +// QVERIFY(eventItem1->eventList.isEmpty()); +// QCOMPARE(button1->scale(), 2.0); + qDebug() << "Button scale: " << button1->scale(); + + + // wait to avoid getting a double click event + QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10); + + // Start pinching while on the button + button1->setScale(1.0); + p1 = QPoint(40, 110); + p2 = QPoint(60, 110); + QTest::touchEvent(canvas, device).press(0, p1, canvas).press(1, p2, canvas); + QCOMPARE(button1->scale(), 1.0); + QCOMPARE(eventItem1->eventList.count(), 2); + QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin); + QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress); + + // This event seems to be discarded, let's ignore it for now until someone digs into pincharea + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); + + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); + //QCOMPARE(button1->scale(), 1.5); + qDebug() << button1->scale(); + + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p1, canvas).move(1, p2, canvas); + qDebug() << button1->scale(); + //QCOMPARE(button1->scale(), 2.0); + + QTest::touchEvent(canvas, device).release(0, p1, canvas).release(1, p2, canvas); +// QCOMPARE(eventItem1->eventList.size(), 99); + qDebug() << button1->scale(); + //QCOMPARE(button1->scale(), 2.0); + + delete canvas; +} + +void tst_TouchMouse::pinchOnFlickable() +{ + QQuickView *canvas = createView(); + canvas->setSource(testFileUrl("pinchonflickable.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea"); + QVERIFY(pinchArea); + QQuickFlickable *flickable = canvas->rootObject()->findChild<QQuickFlickable*>("flickable"); + QVERIFY(flickable); + QQuickItem *rect = canvas->rootObject()->findChild<QQuickItem*>("rect"); + QVERIFY(rect); + + // flickable - single touch point + QVERIFY(flickable->contentX() == 0.0); + QPoint p = QPoint(100, 100); + QTest::touchEvent(canvas, device).press(0, p, canvas); + QCOMPARE(rect->pos(), QPointF(200.0, 200.0)); + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + QTest::qWait(10); + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + QTest::qWait(10); + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + QTest::touchEvent(canvas, device).release(0, p, canvas); + + QGuiApplication::processEvents(); + QTest::qWait(10); + QVERIFY(!flickable->isAtXBeginning()); + // wait until flicking is done + QTRY_VERIFY(!flickable->isFlicking()); + + // pinch + QPoint p1 = QPoint(40, 20); + QPoint p2 = QPoint(60, 20); + + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(canvas, device); + pinchSequence.press(0, p1, canvas).commit(); + // In order for the stationary point to remember its previous position, + // we have to reuse the same pinchSequence object. Otherwise if we let it + // be destroyed and then start a new sequence, point 0 will default to being + // stationary at 0, 0, and PinchArea will filter out that touchpoint because + // it is outside its bounds. + pinchSequence.stationary(0).press(1, p2, canvas).commit(); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + QCOMPARE(rect->scale(), 1.0); + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + pinchSequence.release(0, p1, canvas).release(1, p2, canvas).commit(); + QVERIFY(rect->scale() > 1.0); +} + +void tst_TouchMouse::flickableOnPinch() +{ + QQuickView *canvas = createView(); + canvas->setSource(testFileUrl("flickableonpinch.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea"); + QVERIFY(pinchArea); + QQuickFlickable *flickable = canvas->rootObject()->findChild<QQuickFlickable*>("flickable"); + QVERIFY(flickable); + QQuickItem *rect = canvas->rootObject()->findChild<QQuickItem*>("rect"); + QVERIFY(rect); + + // flickable - single touch point + QVERIFY(flickable->contentX() == 0.0); + QPoint p = QPoint(100, 100); + QTest::touchEvent(canvas, device).press(0, p, canvas); + QCOMPARE(rect->pos(), QPointF(200.0, 200.0)); + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + + QTest::qWait(1000); + + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + QTest::touchEvent(canvas, device).release(0, p, canvas); + + QTest::qWait(1000); + + //QVERIFY(flickable->isMovingHorizontally()); + qDebug() << "Pos: " << rect->pos(); + // wait until flicking is done + QTRY_VERIFY(!flickable->isFlicking()); + + // pinch + QPoint p1 = QPoint(40, 20); + QPoint p2 = QPoint(60, 20); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(canvas, device); + pinchSequence.press(0, p1, canvas).commit(); + // In order for the stationary point to remember its previous position, + // we have to reuse the same pinchSequence object. Otherwise if we let it + // be destroyed and then start a new sequence, point 0 will default to being + // stationary at 0, 0, and PinchArea will filter out that touchpoint because + // it is outside its bounds. + pinchSequence.stationary(0).press(1, p2, canvas).commit(); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + QCOMPARE(rect->scale(), 1.0); + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + pinchSequence.release(0, p1, canvas).release(1, p2, canvas).commit(); + QVERIFY(rect->scale() > 1.0); +} + +void tst_TouchMouse::mouseOnFlickableOnPinch() +{ + QQuickView *canvas = createView(); + canvas->setSource(testFileUrl("mouseonflickableonpinch.qml")); + canvas->show(); + canvas->requestActivateWindow(); + QVERIFY(canvas->rootObject() != 0); + + QQuickPinchArea *pinchArea = canvas->rootObject()->findChild<QQuickPinchArea*>("pincharea"); + QVERIFY(pinchArea); + QQuickFlickable *flickable = canvas->rootObject()->findChild<QQuickFlickable*>("flickable"); + QVERIFY(flickable); + QQuickItem *rect = canvas->rootObject()->findChild<QQuickItem*>("rect"); + QVERIFY(rect); + + // flickable - single touch point + QVERIFY(flickable->contentX() == 0.0); + QPoint p = QPoint(100, 100); + QTest::touchEvent(canvas, device).press(0, p, canvas); + QCOMPARE(rect->pos(), QPointF(200.0, 200.0)); + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + + QTest::qWait(1000); + + p -= QPoint(10, 0); + QTest::touchEvent(canvas, device).move(0, p, canvas); + QTest::touchEvent(canvas, device).release(0, p, canvas); + + QTest::qWait(1000); + + //QVERIFY(flickable->isMovingHorizontally()); + qDebug() << "Pos: " << rect->pos(); + + // pinch + QPoint p1 = QPoint(40, 20); + QPoint p2 = QPoint(60, 20); + QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(canvas, device); + pinchSequence.press(0, p1, canvas).commit(); + // In order for the stationary point to remember its previous position, + // we have to reuse the same pinchSequence object. Otherwise if we let it + // be destroyed and then start a new sequence, point 0 will default to being + // stationary at 0, 0, and PinchArea will filter out that touchpoint because + // it is outside its bounds. + pinchSequence.stationary(0).press(1, p2, canvas).commit(); + p1 -= QPoint(10,10); + p2 += QPoint(10,10); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + QCOMPARE(rect->scale(), 1.0); + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + p1 -= QPoint(10, 0); + p2 += QPoint(10, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + pinchSequence.release(0, p1, canvas).release(1, p2, canvas).commit(); + QVERIFY(rect->scale() > 1.0); + + // PinchArea should steal the event after flicking started + rect->setScale(1.0); + flickable->setContentX(0.0); + p = QPoint(100, 100); + pinchSequence.press(0, p, canvas).commit(); + QCOMPARE(rect->pos(), QPointF(200.0, 200.0)); + p -= QPoint(10, 0); + pinchSequence.move(0, p, canvas).commit(); + p -= QPoint(10, 0); + pinchSequence.move(0, p, canvas).commit(); + QTest::qWait(1000); + p -= QPoint(10, 0); + pinchSequence.move(0, p, canvas).commit(); + + QQuickCanvasPrivate *canvasPriv = QQuickCanvasPrivate::get(canvas); + QCOMPARE(canvasPriv->mouseGrabberItem, flickable); + qDebug() << "Mouse Grabber: " << canvasPriv->mouseGrabberItem << " itemForTouchPointId: " << canvasPriv->itemForTouchPointId; + + // Add a second finger, this should lead to stealing + p1 = QPoint(40, 100); + p2 = QPoint(60, 100); + pinchSequence.stationary(0).press(1, p2, canvas).commit(); + QCOMPARE(rect->scale(), 1.0); + + p1 -= QPoint(5, 0); + p2 += QPoint(5, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + p1 -= QPoint(5, 0); + p2 += QPoint(5, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + p1 -= QPoint(5, 0); + p2 += QPoint(5, 0); + pinchSequence.move(0, p1, canvas).move(1, p2, canvas).commit(); + pinchSequence.release(0, p1, canvas).release(1, p2, canvas).commit(); + QVERIFY(rect->scale() > 1.0); + pinchSequence.release(0, p, canvas).commit(); +} + +QTEST_MAIN(tst_TouchMouse) + +#include "tst_touchmouse.moc" + |