aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorShawn Rutledge <shawn.rutledge@nokia.com>2012-06-26 18:00:59 +0200
committerQt by Nokia <qt-info@nokia.com>2012-06-28 16:47:42 +0200
commit468626e99a90d6ac21cb311cde05c658ccb3b781 (patch)
tree7ac0039994e4489ea19e27cb0840dfa000486cbb /tests
parent4c1addd2c3b019d66b5c19fcd8ba9e0918e92978 (diff)
Propagate synthesized mouse events in parallel with touch.
The old way of event propagation inside QQuickCanvas was to send the touch event through all elements, and if it was accepted along the way, stop. Otherwise generate a mouse event and propagate it through the items in the same way. With this patch the behavior is changed instead to do the propagation in parallel. The idea is to first send a touch, then a mouse event to each QML item (in paint order) that can potentially handle the events. When items filter their child elements, the same logic applies. Other changes/clarifications: - mouse events no longer get synthesized for more than one touch point - TouchPoints can be distributed to multiple Items - if an item accepts a touch point, it always gets updates, even if the point is stationary - events containing only stationary TouchPoints are discarded - PinchArea must accept any initial single TouchPoint in order to receive subsequent updates, even though it's not pinching yet. This means if PA is on top, items underneath don't get touches. New unit tests showing this behavior were added. This patch was written by Frederik Gladhorn, Laszlo Agocs and Shawn Rutledge. Due to the complexity of the logic some refactoring was done. QQuickMouseEventEx has been removed because it inherently relied on using the QEvent d pointer. Change-Id: If19ef687d7602e83cc11b18d2fecfbbdb4e44f5c Reviewed-by: Frederik Gladhorn <frederik.gladhorn@nokia.com>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/quick/qquickcanvas/tst_qquickcanvas.cpp229
-rw-r--r--tests/auto/quick/qquickmultipointtoucharea/tst_qquickmultipointtoucharea.cpp14
-rw-r--r--tests/auto/quick/qquickpincharea/data/pinchproperties.qml3
-rw-r--r--tests/auto/quick/qquickpincharea/tst_qquickpincharea.cpp156
-rw-r--r--tests/auto/quick/quick.pro1
-rw-r--r--tests/auto/quick/touchmouse/data/buttononflickable.qml42
-rw-r--r--tests/auto/quick/touchmouse/data/buttonontouch.qml100
-rw-r--r--tests/auto/quick/touchmouse/data/flickableonpinch.qml37
-rw-r--r--tests/auto/quick/touchmouse/data/mouseonflickableonpinch.qml47
-rw-r--r--tests/auto/quick/touchmouse/data/pinchonflickable.qml35
-rw-r--r--tests/auto/quick/touchmouse/data/singleitem.qml18
-rw-r--r--tests/auto/quick/touchmouse/data/twoitems.qml22
-rw-r--r--tests/auto/quick/touchmouse/touchmouse.pro17
-rw-r--r--tests/auto/quick/touchmouse/tst_touchmouse.cpp923
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"
+