QQuickCanvas renames
[profile/ivi/qtdeclarative.git] / tests / auto / quick / touchmouse / tst_touchmouse.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42
43 #include <QtTest/QtTest>
44
45 #include <QtGui/qstylehints.h>
46
47 #include <QtQuick/qquickview.h>
48 #include <QtQuick/qquickitem.h>
49 #include <QtQuick/private/qquickmousearea_p.h>
50 #include <QtQuick/private/qquickmultipointtoucharea_p.h>
51 #include <QtQuick/private/qquickpincharea_p.h>
52 #include <QtQuick/private/qquickflickable_p.h>
53
54 #include <private/qquickwindow_p.h>
55
56 #include <QtQml/qqmlengine.h>
57 #include <QtQml/qqmlproperty.h>
58
59 #include "../../shared/util.h"
60
61 struct Event
62 {
63     Event(QEvent::Type t, QPoint mouse, QPoint global)
64         :type(t), mousePos(mouse), mousePosGlobal(global)
65     {}
66
67     Event(QEvent::Type t, QList<QTouchEvent::TouchPoint> touch)
68         :type(t), points(touch)
69     {}
70
71     QEvent::Type type;
72     QPoint mousePos;
73     QPoint mousePosGlobal;
74     QList<QTouchEvent::TouchPoint> points;
75 };
76
77 class EventItem : public QQuickItem
78 {
79     Q_OBJECT
80 public:
81     EventItem(QQuickItem *parent = 0)
82         : QQuickItem(parent), acceptMouse(false), acceptTouch(false), filterTouch(false)
83     {}
84
85     void touchEvent(QTouchEvent *event)
86     {
87         eventList.append(Event(event->type(), event->touchPoints()));
88         event->setAccepted(acceptTouch);
89     }
90     void mousePressEvent(QMouseEvent *event)
91     {
92         eventList.append(Event(event->type(), event->pos(), event->globalPos()));
93         event->setAccepted(acceptMouse);
94     }
95     void mouseMoveEvent(QMouseEvent *event)
96     {
97         eventList.append(Event(event->type(), event->pos(), event->globalPos()));
98         event->setAccepted(acceptMouse);
99     }
100     void mouseReleaseEvent(QMouseEvent *event)
101     {
102         eventList.append(Event(event->type(), event->pos(), event->globalPos()));
103         event->setAccepted(acceptMouse);
104     }
105     void mouseDoubleClickEvent(QMouseEvent *event)
106     {
107         eventList.append(Event(event->type(), event->pos(), event->globalPos()));
108         event->setAccepted(acceptMouse);
109     }
110     bool event(QEvent *event) {
111         if (event->type() == QEvent::UngrabMouse) {
112             eventList.append(Event(event->type(), QPoint(0,0), QPoint(0,0)));
113         }
114         return QQuickItem::event(event);
115     }
116
117     QList<Event> eventList;
118     bool acceptMouse;
119     bool acceptTouch;
120     bool filterTouch; // when used as event filter
121
122     bool eventFilter(QObject *, QEvent *event)
123     {
124         if (event->type() == QEvent::TouchBegin ||
125                 event->type() == QEvent::TouchUpdate ||
126                 event->type() == QEvent::TouchCancel ||
127                 event->type() == QEvent::TouchEnd) {
128             QTouchEvent *touch = static_cast<QTouchEvent*>(event);
129             eventList.append(Event(event->type(), touch->touchPoints()));
130             if (filterTouch)
131                 event->accept();
132             return true;
133         }
134         return false;
135     }
136 };
137
138 class tst_TouchMouse : public QQmlDataTest
139 {
140     Q_OBJECT
141 public:
142     tst_TouchMouse()
143         :device(0)
144     {}
145
146 private slots:
147     void initTestCase();
148
149     void simpleTouchEvent();
150     void eventFilter();
151     void mouse();
152     void touchOverMouse();
153     void mouseOverTouch();
154
155     void buttonOnFlickable();
156     void buttonOnTouch();
157
158     void pinchOnFlickable();
159     void flickableOnPinch();
160     void mouseOnFlickableOnPinch();
161
162 private:
163     QQuickView *createView();
164     QTouchDevice *device;
165 };
166
167 QQuickView *tst_TouchMouse::createView()
168 {
169     QQuickView *window = new QQuickView(0);
170     window->setGeometry(0,0,240,320);
171
172     return window;
173 }
174
175 void tst_TouchMouse::initTestCase()
176 {
177     // This test assumes that we don't get synthesized mouse events from QGuiApplication
178     qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
179
180     QQmlDataTest::initTestCase();
181     qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem");
182     if (!device) {
183         device = new QTouchDevice;
184         device->setType(QTouchDevice::TouchScreen);
185         QWindowSystemInterface::registerTouchDevice(device);
186     }
187 }
188
189 void tst_TouchMouse::simpleTouchEvent()
190 {
191     QQuickView *window = createView();
192
193     window->setSource(testFileUrl("singleitem.qml"));
194     window->show();
195     window->requestActivateWindow();
196     QTest::qWaitForWindowShown(window);
197     QVERIFY(window->rootObject() != 0);
198
199     EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
200     QVERIFY(eventItem1);
201
202     // Do not accept touch or mouse
203     QPoint p1;
204     p1 = QPoint(20, 20);
205     QTest::touchEvent(window, device).press(0, p1, window);
206     QCOMPARE(eventItem1->eventList.size(), 1);
207     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
208     p1 += QPoint(10, 0);
209     QTest::touchEvent(window, device).move(0, p1, window);
210     QCOMPARE(eventItem1->eventList.size(), 1);
211     QTest::touchEvent(window, device).release(0, p1, window);
212     QCOMPARE(eventItem1->eventList.size(), 1);
213     eventItem1->eventList.clear();
214
215     // Accept touch
216     eventItem1->acceptTouch = true;
217     p1 = QPoint(20, 20);
218     QTest::touchEvent(window, device).press(0, p1, window);
219     QCOMPARE(eventItem1->eventList.size(), 1);
220     p1 += QPoint(10, 0);
221     QTest::touchEvent(window, device).move(0, p1, window);
222     QCOMPARE(eventItem1->eventList.size(), 2);
223     QTest::touchEvent(window, device).release(0, p1, window);
224     QCOMPARE(eventItem1->eventList.size(), 3);
225     eventItem1->eventList.clear();
226
227     // wait to avoid getting a double click event
228     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
229
230     // Accept mouse
231     eventItem1->acceptTouch = false;
232     eventItem1->acceptMouse = true;
233     eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
234     p1 = QPoint(20, 20);
235     QTest::touchEvent(window, device).press(0, p1, window);
236     QCOMPARE(eventItem1->eventList.size(), 2);
237     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
238     QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
239     QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
240     QCOMPARE(windowPriv->mouseGrabberItem, eventItem1);
241
242     QPoint localPos = eventItem1->mapFromScene(p1).toPoint();
243     QPoint globalPos = window->mapToGlobal(p1);
244     QPoint scenePos = p1; // item is at 0,0
245     QCOMPARE(eventItem1->eventList.at(0).points.at(0).pos().toPoint(), localPos);
246     QCOMPARE(eventItem1->eventList.at(0).points.at(0).scenePos().toPoint(), scenePos);
247     QCOMPARE(eventItem1->eventList.at(0).points.at(0).screenPos().toPoint(), globalPos);
248     QCOMPARE(eventItem1->eventList.at(1).mousePos, localPos);
249     QCOMPARE(eventItem1->eventList.at(1).mousePosGlobal, globalPos);
250
251     p1 += QPoint(10, 0);
252     QTest::touchEvent(window, device).move(0, p1, window);
253     QCOMPARE(eventItem1->eventList.size(), 4);
254     QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
255     QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
256     QTest::touchEvent(window, device).release(0, p1, window);
257     QCOMPARE(eventItem1->eventList.size(), 6);
258     QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd);
259     QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease);
260     eventItem1->eventList.clear();
261
262     // wait to avoid getting a double click event
263     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
264
265     // Accept mouse buttons but not the event
266     eventItem1->acceptTouch = false;
267     eventItem1->acceptMouse = false;
268     eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
269     p1 = QPoint(20, 20);
270     QTest::touchEvent(window, device).press(0, p1, window);
271     QCOMPARE(eventItem1->eventList.size(), 2);
272     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
273     QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
274     p1 += QPoint(10, 0);
275     QTest::touchEvent(window, device).move(0, p1, window);
276     QCOMPARE(eventItem1->eventList.size(), 2);
277     QTest::touchEvent(window, device).release(0, p1, window);
278     QCOMPARE(eventItem1->eventList.size(), 2);
279     eventItem1->eventList.clear();
280
281     // wait to avoid getting a double click event
282     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
283
284     // Accept touch and mouse
285     eventItem1->acceptTouch = true;
286     eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
287     p1 = QPoint(20, 20);
288     QTest::touchEvent(window, device).press(0, p1, window);
289     QCOMPARE(eventItem1->eventList.size(), 1);
290     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
291     p1 += QPoint(10, 0);
292     QTest::touchEvent(window, device).move(0, p1, window);
293     QCOMPARE(eventItem1->eventList.size(), 2);
294     QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchUpdate);
295     QTest::touchEvent(window, device).release(0, p1, window);
296     QCOMPARE(eventItem1->eventList.size(), 3);
297     QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
298     eventItem1->eventList.clear();
299
300     delete window;
301 }
302
303 void tst_TouchMouse::eventFilter()
304 {
305 //    // install event filter on item and see that it can grab events
306 //    QQuickView *window = createView();
307
308 //    window->setSource(testFileUrl("singleitem.qml"));
309 //    window->show();
310 //    window->requestActivateWindow();
311 //    QVERIFY(window->rootObject() != 0);
312
313 //    EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
314 //    QVERIFY(eventItem1);
315 //    eventItem1->acceptTouch = true;
316
317 //    EventItem *filter = new EventItem;
318 //    filter->filterTouch = true;
319 //    eventItem1->installEventFilter(filter);
320
321 //    QPoint p1 = QPoint(20, 20);
322 //    QTest::touchEvent(window, device).press(0, p1, window);
323 //    // QEXPECT_FAIL("", "We do not implement event filters correctly", Abort);
324 //    QCOMPARE(eventItem1->eventList.size(), 0);
325 //    QCOMPARE(filter->eventList.size(), 1);
326 //    QTest::touchEvent(window, device).release(0, p1, window);
327 //    QCOMPARE(eventItem1->eventList.size(), 0);
328 //    QCOMPARE(filter->eventList.size(), 2);
329
330 //    delete filter;
331 //    delete window;
332 }
333
334 void tst_TouchMouse::mouse()
335 {
336     // eventItem1
337     //   - eventItem2
338
339     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
340     QQuickView *window = createView();
341
342     window->setSource(testFileUrl("twoitems.qml"));
343     window->show();
344     window->requestActivateWindow();
345     QVERIFY(window->rootObject() != 0);
346
347     EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
348     QVERIFY(eventItem1);
349     EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
350     QVERIFY(eventItem2);
351     QTest::qWaitForWindowShown(window);
352
353     // bottom item likes mouse, top likes touch
354     eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
355     eventItem1->acceptMouse = true;
356     // item 2 doesn't accept anything, thus it sees a touch pass by
357     QPoint p1 = QPoint(30, 30);
358     QTest::touchEvent(window, device).press(0, p1, window);
359
360     QCOMPARE(eventItem1->eventList.size(), 2);
361     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
362     QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
363
364     delete window;
365 }
366
367 void tst_TouchMouse::touchOverMouse()
368 {
369     // eventItem1
370     //   - eventItem2
371
372     QQuickView *window = createView();
373
374     window->setSource(testFileUrl("twoitems.qml"));
375     window->show();
376     window->requestActivateWindow();
377     QVERIFY(window->rootObject() != 0);
378
379     EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
380     QVERIFY(eventItem1);
381     EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
382     QVERIFY(eventItem2);
383
384     // bottom item likes mouse, top likes touch
385     eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
386     eventItem2->acceptTouch = true;
387
388     QTest::qWaitForWindowShown(window);
389
390     QCOMPARE(eventItem1->eventList.size(), 0);
391     QPoint p1 = QPoint(20, 20);
392     QTest::touchEvent(window, device).press(0, p1, window);
393     QCOMPARE(eventItem1->eventList.size(), 0);
394     QCOMPARE(eventItem2->eventList.size(), 1);
395     QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
396     p1 += QPoint(10, 0);
397     QTest::touchEvent(window, device).move(0, p1, window);
398     QCOMPARE(eventItem2->eventList.size(), 2);
399     QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
400     QTest::touchEvent(window, device).release(0, p1, window);
401     QCOMPARE(eventItem2->eventList.size(), 3);
402     QCOMPARE(eventItem2->eventList.at(2).type, QEvent::TouchEnd);
403     eventItem2->eventList.clear();
404
405     delete window;
406 }
407
408 void tst_TouchMouse::mouseOverTouch()
409 {
410     // eventItem1
411     //   - eventItem2
412
413     QQuickView *window = createView();
414
415     window->setSource(testFileUrl("twoitems.qml"));
416     window->show();
417     window->requestActivateWindow();
418     QVERIFY(window->rootObject() != 0);
419
420     EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
421     QVERIFY(eventItem1);
422     EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
423     QVERIFY(eventItem2);
424
425     // bottom item likes mouse, top likes touch
426     eventItem1->acceptTouch = true;
427     eventItem2->setAcceptedMouseButtons(Qt::LeftButton);
428     eventItem2->acceptMouse = true;
429
430     QTest::qWaitForWindowShown(window);
431
432     QPoint p1 = QPoint(20, 20);
433     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
434     QTest::touchEvent(window, device).press(0, p1, window);
435     QCOMPARE(eventItem1->eventList.size(), 0);
436     QCOMPARE(eventItem2->eventList.size(), 2);
437     QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
438     QCOMPARE(eventItem2->eventList.at(1).type, QEvent::MouseButtonPress);
439
440
441 //    p1 += QPoint(10, 0);
442 //    QTest::touchEvent(window, device).move(0, p1, window);
443 //    QCOMPARE(eventItem2->eventList.size(), 1);
444 //    QTest::touchEvent(window, device).release(0, p1, window);
445 //    QCOMPARE(eventItem2->eventList.size(), 1);
446 //    eventItem2->eventList.clear();
447
448     delete window;
449 }
450
451 void tst_TouchMouse::buttonOnFlickable()
452 {
453     // flickable - height 500 / 1000
454     //   - eventItem1 y: 100, height 100
455     //   - eventItem2 y: 300, height 100
456
457     QQuickView *window = createView();
458
459     window->setSource(testFileUrl("buttononflickable.qml"));
460     window->show();
461     window->requestActivateWindow();
462     QVERIFY(window->rootObject() != 0);
463
464     QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
465     QVERIFY(flickable);
466
467     // should a mouse area button be clickable on top of flickable? yes :)
468     EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
469     QVERIFY(eventItem1);
470     eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
471     eventItem1->acceptMouse = true;
472
473     // should a touch button be touchable on top of flickable? yes :)
474     EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
475     QVERIFY(eventItem2);
476     QCOMPARE(eventItem2->eventList.size(), 0);
477     eventItem2->acceptTouch = true;
478
479     // wait to avoid getting a double click event
480     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
481
482     // check that buttons are clickable
483     // mouse button
484     QCOMPARE(eventItem1->eventList.size(), 0);
485     QPoint p1 = QPoint(20, 130);
486     QTest::touchEvent(window, device).press(0, p1, window);
487     QCOMPARE(eventItem1->eventList.size(), 2);
488     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
489     QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
490     QTest::touchEvent(window, device).release(0, p1, window);
491     QCOMPARE(eventItem1->eventList.size(), 4);
492     QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
493     QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease);
494     eventItem1->eventList.clear();
495
496     // touch button
497     p1 = QPoint(10, 310);
498     QTest::touchEvent(window, device).press(0, p1, window);
499     QCOMPARE(eventItem2->eventList.size(), 1);
500     QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
501     QTest::touchEvent(window, device).release(0, p1, window);
502     QCOMPARE(eventItem2->eventList.size(), 2);
503     QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchEnd);
504     QCOMPARE(eventItem1->eventList.size(), 0);
505     eventItem2->eventList.clear();
506
507     // wait to avoid getting a double click event
508     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
509
510     // click above button, no events please
511     p1 = QPoint(10, 90);
512     QTest::touchEvent(window, device).press(0, p1, window);
513     QCOMPARE(eventItem1->eventList.size(), 0);
514     QTest::touchEvent(window, device).release(0, p1, window);
515     QCOMPARE(eventItem1->eventList.size(), 0);
516     eventItem1->eventList.clear();
517
518     // wait to avoid getting a double click event
519     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
520
521     // check that flickable moves - mouse button
522     QCOMPARE(eventItem1->eventList.size(), 0);
523     p1 = QPoint(10, 110);
524     QTest::touchEvent(window, device).press(0, p1, window);
525     QCOMPARE(eventItem1->eventList.size(), 2);
526     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
527     QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
528
529     QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
530     QCOMPARE(windowPriv->touchMouseId, 0);
531     QCOMPARE(windowPriv->itemForTouchPointId[0], eventItem1);
532     QCOMPARE(windowPriv->mouseGrabberItem, eventItem1);
533
534     p1 += QPoint(0, -10);
535     QPoint p2 = p1 + QPoint(0, -10);
536     QPoint p3 = p2 + QPoint(0, -10);
537     QTest::qWait(10);
538     QTest::touchEvent(window, device).move(0, p1, window);
539     QTest::qWait(10);
540     QTest::touchEvent(window, device).move(0, p2, window);
541     QTest::qWait(10);
542     QTest::touchEvent(window, device).move(0, p3, window);
543
544     // we cannot really know when the events get grabbed away
545     QVERIFY(eventItem1->eventList.size() >= 4);
546     QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
547     QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
548
549     QCOMPARE(windowPriv->mouseGrabberItem, flickable);
550     QVERIFY(flickable->isMovingVertically());
551
552     QTest::touchEvent(window, device).release(0, p3, window);
553     delete window;
554 }
555
556 void tst_TouchMouse::buttonOnTouch()
557 {
558     // 400x800
559     //   PinchArea - height 400
560     //     - eventItem1 y: 100, height 100
561     //     - eventItem2 y: 300, height 100
562     //   MultiPointTouchArea - height 400
563     //     - eventItem1 y: 100, height 100
564     //     - eventItem2 y: 300, height 100
565
566     QQuickView *window = createView();
567     window->setSource(testFileUrl("buttonontouch.qml"));
568     window->show();
569     window->requestActivateWindow();
570     QVERIFY(window->rootObject() != 0);
571
572     QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
573     QVERIFY(pinchArea);
574     QQuickItem *button1 = window->rootObject()->findChild<QQuickItem*>("button1");
575     QVERIFY(button1);
576     EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
577     QVERIFY(eventItem1);
578     EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
579     QVERIFY(eventItem2);
580
581     QQuickMultiPointTouchArea *touchArea = window->rootObject()->findChild<QQuickMultiPointTouchArea*>("toucharea");
582     QVERIFY(touchArea);
583     EventItem *eventItem3 = window->rootObject()->findChild<EventItem*>("eventItem3");
584     QVERIFY(eventItem3);
585     EventItem *eventItem4 = window->rootObject()->findChild<EventItem*>("eventItem4");
586     QVERIFY(eventItem4);
587
588
589     // Test the common case of a mouse area on top of pinch
590     eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
591     eventItem1->acceptMouse = true;
592
593
594     // wait to avoid getting a double click event
595     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
596
597     // Normal touch click
598     QPoint p1 = QPoint(10, 110);
599     QTest::touchEvent(window, device).press(0, p1, window);
600     QTest::touchEvent(window, device).release(0, p1, window);
601     QCOMPARE(eventItem1->eventList.size(), 4);
602     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
603     QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
604     QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
605     QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease);
606     eventItem1->eventList.clear();
607
608     // Normal mouse click
609     QTest::mouseClick(window, Qt::LeftButton, 0, p1);
610     QCOMPARE(eventItem1->eventList.size(), 2);
611     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
612     QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease);
613     eventItem1->eventList.clear();
614
615     // Pinch starting on the PinchArea should work
616     p1 = QPoint(40, 10);
617     QPoint p2 = QPoint(60, 10);
618
619     // Start the events after each other
620     QTest::touchEvent(window, device).press(0, p1, window);
621     QTest::touchEvent(window, device).stationary(0).press(1, p2, window);
622
623     QCOMPARE(button1->scale(), 1.0);
624
625     // This event seems to be discarded, let's ignore it for now until someone digs into pincharea
626     p1 -= QPoint(10, 0);
627     p2 += QPoint(10, 0);
628     QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
629
630     p1 -= QPoint(10, 0);
631     p2 += QPoint(10, 0);
632     QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
633 //    QCOMPARE(button1->scale(), 1.5);
634     qDebug() << "Button scale: " << button1->scale();
635
636     p1 -= QPoint(10, 0);
637     p2 += QPoint(10, 0);
638     QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
639 //    QCOMPARE(button1->scale(), 2.0);
640     qDebug() << "Button scale: " << button1->scale();
641
642     QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
643 //    QVERIFY(eventItem1->eventList.isEmpty());
644 //    QCOMPARE(button1->scale(), 2.0);
645     qDebug() << "Button scale: " << button1->scale();
646
647
648     // wait to avoid getting a double click event
649     QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
650
651     // Start pinching while on the button
652     button1->setScale(1.0);
653     p1 = QPoint(40, 110);
654     p2 = QPoint(60, 110);
655     QTest::touchEvent(window, device).press(0, p1, window).press(1, p2, window);
656     QCOMPARE(button1->scale(), 1.0);
657     QCOMPARE(eventItem1->eventList.count(), 2);
658     QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
659     QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
660
661     // This event seems to be discarded, let's ignore it for now until someone digs into pincharea
662     p1 -= QPoint(10, 0);
663     p2 += QPoint(10, 0);
664     QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
665
666     p1 -= QPoint(10, 0);
667     p2 += QPoint(10, 0);
668     QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
669     //QCOMPARE(button1->scale(), 1.5);
670     qDebug() << button1->scale();
671
672     p1 -= QPoint(10, 0);
673     p2 += QPoint(10, 0);
674     QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
675     qDebug() << button1->scale();
676     //QCOMPARE(button1->scale(), 2.0);
677
678     QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
679 //    QCOMPARE(eventItem1->eventList.size(), 99);
680     qDebug() << button1->scale();
681     //QCOMPARE(button1->scale(), 2.0);
682
683     delete window;
684 }
685
686 void tst_TouchMouse::pinchOnFlickable()
687 {
688     QQuickView *window = createView();
689     window->setSource(testFileUrl("pinchonflickable.qml"));
690     window->show();
691     window->requestActivateWindow();
692     QVERIFY(window->rootObject() != 0);
693
694     QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
695     QVERIFY(pinchArea);
696     QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
697     QVERIFY(flickable);
698     QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
699     QVERIFY(rect);
700
701     // flickable - single touch point
702     QVERIFY(flickable->contentX() == 0.0);
703     QPoint p = QPoint(100, 100);
704     QTest::touchEvent(window, device).press(0, p, window);
705     QCOMPARE(rect->pos(), QPointF(200.0, 200.0));
706     p -= QPoint(10, 0);
707     QTest::touchEvent(window, device).move(0, p, window);
708     p -= QPoint(10, 0);
709     QTest::touchEvent(window, device).move(0, p, window);
710     QTest::qWait(10);
711     p -= QPoint(10, 0);
712     QTest::touchEvent(window, device).move(0, p, window);
713     QTest::qWait(10);
714     p -= QPoint(10, 0);
715     QTest::touchEvent(window, device).move(0, p, window);
716     QTest::touchEvent(window, device).release(0, p, window);
717
718     QGuiApplication::processEvents();
719     QTest::qWait(10);
720     QVERIFY(!flickable->isAtXBeginning());
721     // wait until flicking is done
722     QTRY_VERIFY(!flickable->isFlicking());
723
724     // pinch
725     QPoint p1 = QPoint(40, 20);
726     QPoint p2 = QPoint(60, 20);
727
728     QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
729     pinchSequence.press(0, p1, window).commit();
730     // In order for the stationary point to remember its previous position,
731     // we have to reuse the same pinchSequence object.  Otherwise if we let it
732     // be destroyed and then start a new sequence, point 0 will default to being
733     // stationary at 0, 0, and PinchArea will filter out that touchpoint because
734     // it is outside its bounds.
735     pinchSequence.stationary(0).press(1, p2, window).commit();
736     p1 -= QPoint(10,10);
737     p2 += QPoint(10,10);
738     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
739     QCOMPARE(rect->scale(), 1.0);
740     p1 -= QPoint(10, 0);
741     p2 += QPoint(10, 0);
742     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
743     p1 -= QPoint(10, 0);
744     p2 += QPoint(10, 0);
745     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
746     p1 -= QPoint(10, 0);
747     p2 += QPoint(10, 0);
748     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
749     pinchSequence.release(0, p1, window).release(1, p2, window).commit();
750     QVERIFY(rect->scale() > 1.0);
751 }
752
753 void tst_TouchMouse::flickableOnPinch()
754 {
755     QQuickView *window = createView();
756     window->setSource(testFileUrl("flickableonpinch.qml"));
757     window->show();
758     window->requestActivateWindow();
759     QVERIFY(window->rootObject() != 0);
760
761     QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
762     QVERIFY(pinchArea);
763     QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
764     QVERIFY(flickable);
765     QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
766     QVERIFY(rect);
767
768     // flickable - single touch point
769     QVERIFY(flickable->contentX() == 0.0);
770     QPoint p = QPoint(100, 100);
771     QTest::touchEvent(window, device).press(0, p, window);
772     QCOMPARE(rect->pos(), QPointF(200.0, 200.0));
773     p -= QPoint(10, 0);
774     QTest::touchEvent(window, device).move(0, p, window);
775     p -= QPoint(10, 0);
776     QTest::touchEvent(window, device).move(0, p, window);
777
778     QTest::qWait(1000);
779
780     p -= QPoint(10, 0);
781     QTest::touchEvent(window, device).move(0, p, window);
782     QTest::touchEvent(window, device).release(0, p, window);
783
784     QTest::qWait(1000);
785
786     //QVERIFY(flickable->isMovingHorizontally());
787     qDebug() << "Pos: " << rect->pos();
788     // wait until flicking is done
789     QTRY_VERIFY(!flickable->isFlicking());
790
791     // pinch
792     QPoint p1 = QPoint(40, 20);
793     QPoint p2 = QPoint(60, 20);
794     QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
795     pinchSequence.press(0, p1, window).commit();
796     // In order for the stationary point to remember its previous position,
797     // we have to reuse the same pinchSequence object.  Otherwise if we let it
798     // be destroyed and then start a new sequence, point 0 will default to being
799     // stationary at 0, 0, and PinchArea will filter out that touchpoint because
800     // it is outside its bounds.
801     pinchSequence.stationary(0).press(1, p2, window).commit();
802     p1 -= QPoint(10,10);
803     p2 += QPoint(10,10);
804     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
805     QCOMPARE(rect->scale(), 1.0);
806     p1 -= QPoint(10, 0);
807     p2 += QPoint(10, 0);
808     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
809     p1 -= QPoint(10, 0);
810     p2 += QPoint(10, 0);
811     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
812     p1 -= QPoint(10, 0);
813     p2 += QPoint(10, 0);
814     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
815     pinchSequence.release(0, p1, window).release(1, p2, window).commit();
816     QVERIFY(rect->scale() > 1.0);
817 }
818
819 void tst_TouchMouse::mouseOnFlickableOnPinch()
820 {
821     QQuickView *window = createView();
822     window->setSource(testFileUrl("mouseonflickableonpinch.qml"));
823     window->show();
824     window->requestActivateWindow();
825     QVERIFY(window->rootObject() != 0);
826
827     QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
828     QVERIFY(pinchArea);
829     QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
830     QVERIFY(flickable);
831     QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
832     QVERIFY(rect);
833
834     // flickable - single touch point
835     QVERIFY(flickable->contentX() == 0.0);
836     QPoint p = QPoint(100, 100);
837     QTest::touchEvent(window, device).press(0, p, window);
838     QCOMPARE(rect->pos(), QPointF(200.0, 200.0));
839     p -= QPoint(10, 0);
840     QTest::touchEvent(window, device).move(0, p, window);
841     p -= QPoint(10, 0);
842     QTest::touchEvent(window, device).move(0, p, window);
843
844     QTest::qWait(1000);
845
846     p -= QPoint(10, 0);
847     QTest::touchEvent(window, device).move(0, p, window);
848     QTest::touchEvent(window, device).release(0, p, window);
849
850     QTest::qWait(1000);
851
852     //QVERIFY(flickable->isMovingHorizontally());
853     qDebug() << "Pos: " << rect->pos();
854
855     // pinch
856     QPoint p1 = QPoint(40, 20);
857     QPoint p2 = QPoint(60, 20);
858     QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
859     pinchSequence.press(0, p1, window).commit();
860     // In order for the stationary point to remember its previous position,
861     // we have to reuse the same pinchSequence object.  Otherwise if we let it
862     // be destroyed and then start a new sequence, point 0 will default to being
863     // stationary at 0, 0, and PinchArea will filter out that touchpoint because
864     // it is outside its bounds.
865     pinchSequence.stationary(0).press(1, p2, window).commit();
866     p1 -= QPoint(10,10);
867     p2 += QPoint(10,10);
868     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
869     QCOMPARE(rect->scale(), 1.0);
870     p1 -= QPoint(10, 0);
871     p2 += QPoint(10, 0);
872     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
873     p1 -= QPoint(10, 0);
874     p2 += QPoint(10, 0);
875     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
876     p1 -= QPoint(10, 0);
877     p2 += QPoint(10, 0);
878     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
879     pinchSequence.release(0, p1, window).release(1, p2, window).commit();
880     QVERIFY(rect->scale() > 1.0);
881
882     // PinchArea should steal the event after flicking started
883     rect->setScale(1.0);
884     flickable->setContentX(0.0);
885     p = QPoint(100, 100);
886     pinchSequence.press(0, p, window).commit();
887     QCOMPARE(rect->pos(), QPointF(200.0, 200.0));
888     p -= QPoint(10, 0);
889     pinchSequence.move(0, p, window).commit();
890     p -= QPoint(10, 0);
891     pinchSequence.move(0, p, window).commit();
892     QTest::qWait(1000);
893     p -= QPoint(10, 0);
894     pinchSequence.move(0, p, window).commit();
895
896     QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
897     QCOMPARE(windowPriv->mouseGrabberItem, flickable);
898     qDebug() << "Mouse Grabber: " << windowPriv->mouseGrabberItem << " itemForTouchPointId: " << windowPriv->itemForTouchPointId;
899
900     // Add a second finger, this should lead to stealing
901     p1 = QPoint(40, 100);
902     p2 = QPoint(60, 100);
903     pinchSequence.stationary(0).press(1, p2, window).commit();
904     QCOMPARE(rect->scale(), 1.0);
905
906     p1 -= QPoint(5, 0);
907     p2 += QPoint(5, 0);
908     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
909     p1 -= QPoint(5, 0);
910     p2 += QPoint(5, 0);
911     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
912     p1 -= QPoint(5, 0);
913     p2 += QPoint(5, 0);
914     pinchSequence.move(0, p1, window).move(1, p2, window).commit();
915     pinchSequence.release(0, p1, window).release(1, p2, window).commit();
916     QVERIFY(rect->scale() > 1.0);
917     pinchSequence.release(0, p, window).commit();
918 }
919
920 QTEST_MAIN(tst_TouchMouse)
921
922 #include "tst_touchmouse.moc"
923