1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtQml module of the Qt Toolkit.
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.
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.
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.
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.
40 ****************************************************************************/
43 #include <QtTest/QtTest>
45 #include <QtGui/qstylehints.h>
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>
54 #include <private/qquickwindow_p.h>
56 #include <QtQml/qqmlengine.h>
57 #include <QtQml/qqmlproperty.h>
59 #include "../../shared/util.h"
63 Event(QEvent::Type t, QPoint mouse, QPoint global)
64 :type(t), mousePos(mouse), mousePosGlobal(global)
67 Event(QEvent::Type t, QList<QTouchEvent::TouchPoint> touch)
68 :type(t), points(touch)
73 QPoint mousePosGlobal;
74 QList<QTouchEvent::TouchPoint> points;
77 class EventItem : public QQuickItem
81 EventItem(QQuickItem *parent = 0)
82 : QQuickItem(parent), acceptMouse(false), acceptTouch(false), filterTouch(false)
85 void touchEvent(QTouchEvent *event)
87 eventList.append(Event(event->type(), event->touchPoints()));
88 event->setAccepted(acceptTouch);
90 void mousePressEvent(QMouseEvent *event)
92 eventList.append(Event(event->type(), event->pos(), event->globalPos()));
93 event->setAccepted(acceptMouse);
95 void mouseMoveEvent(QMouseEvent *event)
97 eventList.append(Event(event->type(), event->pos(), event->globalPos()));
98 event->setAccepted(acceptMouse);
100 void mouseReleaseEvent(QMouseEvent *event)
102 eventList.append(Event(event->type(), event->pos(), event->globalPos()));
103 event->setAccepted(acceptMouse);
105 void mouseDoubleClickEvent(QMouseEvent *event)
107 eventList.append(Event(event->type(), event->pos(), event->globalPos()));
108 event->setAccepted(acceptMouse);
110 bool event(QEvent *event) {
111 if (event->type() == QEvent::UngrabMouse) {
112 eventList.append(Event(event->type(), QPoint(0,0), QPoint(0,0)));
114 return QQuickItem::event(event);
117 QList<Event> eventList;
120 bool filterTouch; // when used as event filter
122 bool eventFilter(QObject *, QEvent *event)
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()));
138 class tst_TouchMouse : public QQmlDataTest
149 void simpleTouchEvent();
152 void touchOverMouse();
153 void mouseOverTouch();
155 void buttonOnFlickable();
156 void buttonOnTouch();
158 void pinchOnFlickable();
159 void flickableOnPinch();
160 void mouseOnFlickableOnPinch();
163 QQuickView *createView();
164 QTouchDevice *device;
167 QQuickView *tst_TouchMouse::createView()
169 QQuickView *window = new QQuickView(0);
170 window->setGeometry(0,0,240,320);
175 void tst_TouchMouse::initTestCase()
177 // This test assumes that we don't get synthesized mouse events from QGuiApplication
178 qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
180 QQmlDataTest::initTestCase();
181 qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem");
183 device = new QTouchDevice;
184 device->setType(QTouchDevice::TouchScreen);
185 QWindowSystemInterface::registerTouchDevice(device);
189 void tst_TouchMouse::simpleTouchEvent()
191 QQuickView *window = createView();
193 window->setSource(testFileUrl("singleitem.qml"));
195 window->requestActivateWindow();
196 QTest::qWaitForWindowShown(window);
197 QVERIFY(window->rootObject() != 0);
199 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
202 // Do not accept touch or mouse
205 QTest::touchEvent(window, device).press(0, p1, window);
206 QCOMPARE(eventItem1->eventList.size(), 1);
207 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
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();
216 eventItem1->acceptTouch = true;
218 QTest::touchEvent(window, device).press(0, p1, window);
219 QCOMPARE(eventItem1->eventList.size(), 1);
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();
227 // wait to avoid getting a double click event
228 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
231 eventItem1->acceptTouch = false;
232 eventItem1->acceptMouse = true;
233 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
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);
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);
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();
262 // wait to avoid getting a double click event
263 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
265 // Accept mouse buttons but not the event
266 eventItem1->acceptTouch = false;
267 eventItem1->acceptMouse = false;
268 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
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);
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();
281 // wait to avoid getting a double click event
282 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
284 // Accept touch and mouse
285 eventItem1->acceptTouch = true;
286 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
288 QTest::touchEvent(window, device).press(0, p1, window);
289 QCOMPARE(eventItem1->eventList.size(), 1);
290 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
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();
303 void tst_TouchMouse::eventFilter()
305 // // install event filter on item and see that it can grab events
306 // QQuickView *window = createView();
308 // window->setSource(testFileUrl("singleitem.qml"));
310 // window->requestActivateWindow();
311 // QVERIFY(window->rootObject() != 0);
313 // EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
314 // QVERIFY(eventItem1);
315 // eventItem1->acceptTouch = true;
317 // EventItem *filter = new EventItem;
318 // filter->filterTouch = true;
319 // eventItem1->installEventFilter(filter);
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);
334 void tst_TouchMouse::mouse()
339 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
340 QQuickView *window = createView();
342 window->setSource(testFileUrl("twoitems.qml"));
344 window->requestActivateWindow();
345 QVERIFY(window->rootObject() != 0);
347 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
349 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
351 QTest::qWaitForWindowShown(window);
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);
360 QCOMPARE(eventItem1->eventList.size(), 2);
361 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
362 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
367 void tst_TouchMouse::touchOverMouse()
372 QQuickView *window = createView();
374 window->setSource(testFileUrl("twoitems.qml"));
376 window->requestActivateWindow();
377 QVERIFY(window->rootObject() != 0);
379 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
381 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
384 // bottom item likes mouse, top likes touch
385 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
386 eventItem2->acceptTouch = true;
388 QTest::qWaitForWindowShown(window);
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);
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();
408 void tst_TouchMouse::mouseOverTouch()
413 QQuickView *window = createView();
415 window->setSource(testFileUrl("twoitems.qml"));
417 window->requestActivateWindow();
418 QVERIFY(window->rootObject() != 0);
420 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
422 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
425 // bottom item likes mouse, top likes touch
426 eventItem1->acceptTouch = true;
427 eventItem2->setAcceptedMouseButtons(Qt::LeftButton);
428 eventItem2->acceptMouse = true;
430 QTest::qWaitForWindowShown(window);
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);
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();
451 void tst_TouchMouse::buttonOnFlickable()
453 // flickable - height 500 / 1000
454 // - eventItem1 y: 100, height 100
455 // - eventItem2 y: 300, height 100
457 QQuickView *window = createView();
459 window->setSource(testFileUrl("buttononflickable.qml"));
461 window->requestActivateWindow();
462 QVERIFY(window->rootObject() != 0);
464 QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
467 // should a mouse area button be clickable on top of flickable? yes :)
468 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
470 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
471 eventItem1->acceptMouse = true;
473 // should a touch button be touchable on top of flickable? yes :)
474 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
476 QCOMPARE(eventItem2->eventList.size(), 0);
477 eventItem2->acceptTouch = true;
479 // wait to avoid getting a double click event
480 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
482 // check that buttons are clickable
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();
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();
507 // wait to avoid getting a double click event
508 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
510 // click above button, no events please
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();
518 // wait to avoid getting a double click event
519 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
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);
529 QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
530 QCOMPARE(windowPriv->touchMouseId, 0);
531 QCOMPARE(windowPriv->itemForTouchPointId[0], eventItem1);
532 QCOMPARE(windowPriv->mouseGrabberItem, eventItem1);
534 p1 += QPoint(0, -10);
535 QPoint p2 = p1 + QPoint(0, -10);
536 QPoint p3 = p2 + QPoint(0, -10);
538 QTest::touchEvent(window, device).move(0, p1, window);
540 QTest::touchEvent(window, device).move(0, p2, window);
542 QTest::touchEvent(window, device).move(0, p3, window);
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);
549 QCOMPARE(windowPriv->mouseGrabberItem, flickable);
550 QVERIFY(flickable->isMovingVertically());
552 QTest::touchEvent(window, device).release(0, p3, window);
556 void tst_TouchMouse::buttonOnTouch()
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
566 QQuickView *window = createView();
567 window->setSource(testFileUrl("buttonontouch.qml"));
569 window->requestActivateWindow();
570 QVERIFY(window->rootObject() != 0);
572 QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
574 QQuickItem *button1 = window->rootObject()->findChild<QQuickItem*>("button1");
576 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
578 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
581 QQuickMultiPointTouchArea *touchArea = window->rootObject()->findChild<QQuickMultiPointTouchArea*>("toucharea");
583 EventItem *eventItem3 = window->rootObject()->findChild<EventItem*>("eventItem3");
585 EventItem *eventItem4 = window->rootObject()->findChild<EventItem*>("eventItem4");
589 // Test the common case of a mouse area on top of pinch
590 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
591 eventItem1->acceptMouse = true;
594 // wait to avoid getting a double click event
595 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
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();
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();
615 // Pinch starting on the PinchArea should work
617 QPoint p2 = QPoint(60, 10);
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);
623 QCOMPARE(button1->scale(), 1.0);
625 // This event seems to be discarded, let's ignore it for now until someone digs into pincharea
628 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
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();
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();
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();
648 // wait to avoid getting a double click event
649 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
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);
661 // This event seems to be discarded, let's ignore it for now until someone digs into pincharea
664 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
668 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
669 //QCOMPARE(button1->scale(), 1.5);
670 qDebug() << button1->scale();
674 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
675 qDebug() << button1->scale();
676 //QCOMPARE(button1->scale(), 2.0);
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);
686 void tst_TouchMouse::pinchOnFlickable()
688 QQuickView *window = createView();
689 window->setSource(testFileUrl("pinchonflickable.qml"));
691 window->requestActivateWindow();
692 QVERIFY(window->rootObject() != 0);
694 QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
696 QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
698 QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
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));
707 QTest::touchEvent(window, device).move(0, p, window);
709 QTest::touchEvent(window, device).move(0, p, window);
712 QTest::touchEvent(window, device).move(0, p, window);
715 QTest::touchEvent(window, device).move(0, p, window);
716 QTest::touchEvent(window, device).release(0, p, window);
718 QGuiApplication::processEvents();
720 QVERIFY(!flickable->isAtXBeginning());
721 // wait until flicking is done
722 QTRY_VERIFY(!flickable->isFlicking());
725 QPoint p1 = QPoint(40, 20);
726 QPoint p2 = QPoint(60, 20);
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();
738 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
739 QCOMPARE(rect->scale(), 1.0);
742 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
745 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
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);
753 void tst_TouchMouse::flickableOnPinch()
755 QQuickView *window = createView();
756 window->setSource(testFileUrl("flickableonpinch.qml"));
758 window->requestActivateWindow();
759 QVERIFY(window->rootObject() != 0);
761 QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
763 QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
765 QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
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));
774 QTest::touchEvent(window, device).move(0, p, window);
776 QTest::touchEvent(window, device).move(0, p, window);
781 QTest::touchEvent(window, device).move(0, p, window);
782 QTest::touchEvent(window, device).release(0, p, window);
786 //QVERIFY(flickable->isMovingHorizontally());
787 qDebug() << "Pos: " << rect->pos();
788 // wait until flicking is done
789 QTRY_VERIFY(!flickable->isFlicking());
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();
804 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
805 QCOMPARE(rect->scale(), 1.0);
808 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
811 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
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);
819 void tst_TouchMouse::mouseOnFlickableOnPinch()
821 QQuickView *window = createView();
822 window->setSource(testFileUrl("mouseonflickableonpinch.qml"));
824 window->requestActivateWindow();
825 QVERIFY(window->rootObject() != 0);
827 QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
829 QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
831 QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
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));
840 QTest::touchEvent(window, device).move(0, p, window);
842 QTest::touchEvent(window, device).move(0, p, window);
847 QTest::touchEvent(window, device).move(0, p, window);
848 QTest::touchEvent(window, device).release(0, p, window);
852 //QVERIFY(flickable->isMovingHorizontally());
853 qDebug() << "Pos: " << rect->pos();
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();
868 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
869 QCOMPARE(rect->scale(), 1.0);
872 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
875 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
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);
882 // PinchArea should steal the event after flicking started
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));
889 pinchSequence.move(0, p, window).commit();
891 pinchSequence.move(0, p, window).commit();
894 pinchSequence.move(0, p, window).commit();
896 QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
897 QCOMPARE(windowPriv->mouseGrabberItem, flickable);
898 qDebug() << "Mouse Grabber: " << windowPriv->mouseGrabberItem << " itemForTouchPointId: " << windowPriv->itemForTouchPointId;
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);
908 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
911 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
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();
920 QTEST_MAIN(tst_TouchMouse)
922 #include "tst_touchmouse.moc"