1 /****************************************************************************
3 ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
6 ** This file is part of the QtQml module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/contact-us.
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
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>
53 #include <qpa/qwindowsysteminterface.h>
55 #include <private/qquickwindow_p.h>
57 #include <QtQml/qqmlengine.h>
58 #include <QtQml/qqmlproperty.h>
60 #include "../../shared/util.h"
64 Event(QEvent::Type t, QPoint mouse, QPoint global)
65 :type(t), mousePos(mouse), mousePosGlobal(global)
68 Event(QEvent::Type t, QList<QTouchEvent::TouchPoint> touch)
69 :type(t), points(touch)
74 QPoint mousePosGlobal;
75 QList<QTouchEvent::TouchPoint> points;
78 class EventItem : public QQuickItem
82 EventItem(QQuickItem *parent = 0)
83 : QQuickItem(parent), acceptMouse(false), acceptTouch(false), filterTouch(false)
86 void touchEvent(QTouchEvent *event)
88 eventList.append(Event(event->type(), event->touchPoints()));
89 event->setAccepted(acceptTouch);
91 void mousePressEvent(QMouseEvent *event)
93 eventList.append(Event(event->type(), event->pos(), event->globalPos()));
94 event->setAccepted(acceptMouse);
96 void mouseMoveEvent(QMouseEvent *event)
98 eventList.append(Event(event->type(), event->pos(), event->globalPos()));
99 event->setAccepted(acceptMouse);
101 void mouseReleaseEvent(QMouseEvent *event)
103 eventList.append(Event(event->type(), event->pos(), event->globalPos()));
104 event->setAccepted(acceptMouse);
106 void mouseDoubleClickEvent(QMouseEvent *event)
108 eventList.append(Event(event->type(), event->pos(), event->globalPos()));
109 event->setAccepted(acceptMouse);
111 bool event(QEvent *event) {
112 if (event->type() == QEvent::UngrabMouse) {
113 eventList.append(Event(event->type(), QPoint(0,0), QPoint(0,0)));
115 return QQuickItem::event(event);
118 QList<Event> eventList;
121 bool filterTouch; // when used as event filter
123 bool eventFilter(QObject *, QEvent *event)
125 if (event->type() == QEvent::TouchBegin ||
126 event->type() == QEvent::TouchUpdate ||
127 event->type() == QEvent::TouchCancel ||
128 event->type() == QEvent::TouchEnd) {
129 QTouchEvent *touch = static_cast<QTouchEvent*>(event);
130 eventList.append(Event(event->type(), touch->touchPoints()));
139 class tst_TouchMouse : public QQmlDataTest
150 void simpleTouchEvent();
153 void touchOverMouse();
154 void mouseOverTouch();
156 void buttonOnFlickable();
157 void buttonOnTouch();
159 void pinchOnFlickable();
160 void flickableOnPinch();
161 void mouseOnFlickableOnPinch();
164 QQuickView *createView();
165 QTouchDevice *device;
168 QQuickView *tst_TouchMouse::createView()
170 QQuickView *window = new QQuickView(0);
171 window->setGeometry(0,0,240,320);
176 void tst_TouchMouse::initTestCase()
178 // This test assumes that we don't get synthesized mouse events from QGuiApplication
179 qApp->setAttribute(Qt::AA_SynthesizeMouseForUnhandledTouchEvents, false);
181 QQmlDataTest::initTestCase();
182 qmlRegisterType<EventItem>("Qt.test", 1, 0, "EventItem");
184 device = new QTouchDevice;
185 device->setType(QTouchDevice::TouchScreen);
186 QWindowSystemInterface::registerTouchDevice(device);
190 void tst_TouchMouse::simpleTouchEvent()
192 QQuickView *window = createView();
194 window->setSource(testFileUrl("singleitem.qml"));
196 window->requestActivateWindow();
197 QVERIFY(QTest::qWaitForWindowExposed(window));
198 QVERIFY(window->rootObject() != 0);
200 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
203 // Do not accept touch or mouse
206 QTest::touchEvent(window, device).press(0, p1, window);
207 QCOMPARE(eventItem1->eventList.size(), 1);
208 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
210 QTest::touchEvent(window, device).move(0, p1, window);
211 QCOMPARE(eventItem1->eventList.size(), 1);
212 QTest::touchEvent(window, device).release(0, p1, window);
213 QCOMPARE(eventItem1->eventList.size(), 1);
214 eventItem1->eventList.clear();
217 eventItem1->acceptTouch = true;
219 QTest::touchEvent(window, device).press(0, p1, window);
220 QCOMPARE(eventItem1->eventList.size(), 1);
222 QTest::touchEvent(window, device).move(0, p1, window);
223 QCOMPARE(eventItem1->eventList.size(), 2);
224 QTest::touchEvent(window, device).release(0, p1, window);
225 QCOMPARE(eventItem1->eventList.size(), 3);
226 eventItem1->eventList.clear();
228 // wait to avoid getting a double click event
229 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
232 eventItem1->acceptTouch = false;
233 eventItem1->acceptMouse = true;
234 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
236 QTest::touchEvent(window, device).press(0, p1, window);
237 QCOMPARE(eventItem1->eventList.size(), 2);
238 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
239 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
240 QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
241 QCOMPARE(windowPriv->mouseGrabberItem, eventItem1);
243 QPoint localPos = eventItem1->mapFromScene(p1).toPoint();
244 QPoint globalPos = window->mapToGlobal(p1);
245 QPoint scenePos = p1; // item is at 0,0
246 QCOMPARE(eventItem1->eventList.at(0).points.at(0).pos().toPoint(), localPos);
247 QCOMPARE(eventItem1->eventList.at(0).points.at(0).scenePos().toPoint(), scenePos);
248 QCOMPARE(eventItem1->eventList.at(0).points.at(0).screenPos().toPoint(), globalPos);
249 QCOMPARE(eventItem1->eventList.at(1).mousePos, localPos);
250 QCOMPARE(eventItem1->eventList.at(1).mousePosGlobal, globalPos);
253 QTest::touchEvent(window, device).move(0, p1, window);
254 QCOMPARE(eventItem1->eventList.size(), 4);
255 QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
256 QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
257 QTest::touchEvent(window, device).release(0, p1, window);
258 QCOMPARE(eventItem1->eventList.size(), 6);
259 QCOMPARE(eventItem1->eventList.at(4).type, QEvent::TouchEnd);
260 QCOMPARE(eventItem1->eventList.at(5).type, QEvent::MouseButtonRelease);
261 eventItem1->eventList.clear();
263 // wait to avoid getting a double click event
264 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
266 // Accept mouse buttons but not the event
267 eventItem1->acceptTouch = false;
268 eventItem1->acceptMouse = false;
269 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
271 QTest::touchEvent(window, device).press(0, p1, window);
272 QCOMPARE(eventItem1->eventList.size(), 2);
273 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
274 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
276 QTest::touchEvent(window, device).move(0, p1, window);
277 QCOMPARE(eventItem1->eventList.size(), 2);
278 QTest::touchEvent(window, device).release(0, p1, window);
279 QCOMPARE(eventItem1->eventList.size(), 2);
280 eventItem1->eventList.clear();
282 // wait to avoid getting a double click event
283 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
285 // Accept touch and mouse
286 eventItem1->acceptTouch = true;
287 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
289 QTest::touchEvent(window, device).press(0, p1, window);
290 QCOMPARE(eventItem1->eventList.size(), 1);
291 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
293 QTest::touchEvent(window, device).move(0, p1, window);
294 QCOMPARE(eventItem1->eventList.size(), 2);
295 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::TouchUpdate);
296 QTest::touchEvent(window, device).release(0, p1, window);
297 QCOMPARE(eventItem1->eventList.size(), 3);
298 QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
299 eventItem1->eventList.clear();
304 void tst_TouchMouse::eventFilter()
306 // // install event filter on item and see that it can grab events
307 // QQuickView *window = createView();
309 // window->setSource(testFileUrl("singleitem.qml"));
311 // window->requestActivateWindow();
312 // QVERIFY(window->rootObject() != 0);
314 // EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
315 // QVERIFY(eventItem1);
316 // eventItem1->acceptTouch = true;
318 // EventItem *filter = new EventItem;
319 // filter->filterTouch = true;
320 // eventItem1->installEventFilter(filter);
322 // QPoint p1 = QPoint(20, 20);
323 // QTest::touchEvent(window, device).press(0, p1, window);
324 // // QEXPECT_FAIL("", "We do not implement event filters correctly", Abort);
325 // QCOMPARE(eventItem1->eventList.size(), 0);
326 // QCOMPARE(filter->eventList.size(), 1);
327 // QTest::touchEvent(window, device).release(0, p1, window);
328 // QCOMPARE(eventItem1->eventList.size(), 0);
329 // QCOMPARE(filter->eventList.size(), 2);
335 void tst_TouchMouse::mouse()
340 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
341 QQuickView *window = createView();
343 window->setSource(testFileUrl("twoitems.qml"));
345 window->requestActivateWindow();
346 QVERIFY(window->rootObject() != 0);
348 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
350 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
352 QVERIFY(QTest::qWaitForWindowExposed(window));
354 // bottom item likes mouse, top likes touch
355 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
356 eventItem1->acceptMouse = true;
357 // item 2 doesn't accept anything, thus it sees a touch pass by
358 QPoint p1 = QPoint(30, 30);
359 QTest::touchEvent(window, device).press(0, p1, window);
361 QCOMPARE(eventItem1->eventList.size(), 2);
362 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
363 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
368 void tst_TouchMouse::touchOverMouse()
373 QQuickView *window = createView();
375 window->setSource(testFileUrl("twoitems.qml"));
377 window->requestActivateWindow();
378 QVERIFY(window->rootObject() != 0);
380 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
382 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
385 // bottom item likes mouse, top likes touch
386 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
387 eventItem2->acceptTouch = true;
389 QVERIFY(QTest::qWaitForWindowExposed(window));
391 QCOMPARE(eventItem1->eventList.size(), 0);
392 QPoint p1 = QPoint(20, 20);
393 QTest::touchEvent(window, device).press(0, p1, window);
394 QCOMPARE(eventItem1->eventList.size(), 0);
395 QCOMPARE(eventItem2->eventList.size(), 1);
396 QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
398 QTest::touchEvent(window, device).move(0, p1, window);
399 QCOMPARE(eventItem2->eventList.size(), 2);
400 QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchUpdate);
401 QTest::touchEvent(window, device).release(0, p1, window);
402 QCOMPARE(eventItem2->eventList.size(), 3);
403 QCOMPARE(eventItem2->eventList.at(2).type, QEvent::TouchEnd);
404 eventItem2->eventList.clear();
409 void tst_TouchMouse::mouseOverTouch()
414 QQuickView *window = createView();
416 window->setSource(testFileUrl("twoitems.qml"));
418 window->requestActivateWindow();
419 QVERIFY(window->rootObject() != 0);
421 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
423 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
426 // bottom item likes mouse, top likes touch
427 eventItem1->acceptTouch = true;
428 eventItem2->setAcceptedMouseButtons(Qt::LeftButton);
429 eventItem2->acceptMouse = true;
431 QVERIFY(QTest::qWaitForWindowExposed(window));
433 QPoint p1 = QPoint(20, 20);
434 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
435 QTest::touchEvent(window, device).press(0, p1, window);
436 QCOMPARE(eventItem1->eventList.size(), 0);
437 QCOMPARE(eventItem2->eventList.size(), 2);
438 QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
439 QCOMPARE(eventItem2->eventList.at(1).type, QEvent::MouseButtonPress);
442 // p1 += QPoint(10, 0);
443 // QTest::touchEvent(window, device).move(0, p1, window);
444 // QCOMPARE(eventItem2->eventList.size(), 1);
445 // QTest::touchEvent(window, device).release(0, p1, window);
446 // QCOMPARE(eventItem2->eventList.size(), 1);
447 // eventItem2->eventList.clear();
452 void tst_TouchMouse::buttonOnFlickable()
454 // flickable - height 500 / 1000
455 // - eventItem1 y: 100, height 100
456 // - eventItem2 y: 300, height 100
458 QQuickView *window = createView();
460 window->setSource(testFileUrl("buttononflickable.qml"));
462 window->requestActivateWindow();
463 QVERIFY(window->rootObject() != 0);
465 QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
468 // should a mouse area button be clickable on top of flickable? yes :)
469 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
471 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
472 eventItem1->acceptMouse = true;
474 // should a touch button be touchable on top of flickable? yes :)
475 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
477 QCOMPARE(eventItem2->eventList.size(), 0);
478 eventItem2->acceptTouch = true;
480 // wait to avoid getting a double click event
481 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
483 // check that buttons are clickable
485 QCOMPARE(eventItem1->eventList.size(), 0);
486 QPoint p1 = QPoint(20, 130);
487 QTest::touchEvent(window, device).press(0, p1, window);
488 QCOMPARE(eventItem1->eventList.size(), 2);
489 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
490 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
491 QTest::touchEvent(window, device).release(0, p1, window);
492 QCOMPARE(eventItem1->eventList.size(), 4);
493 QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
494 QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease);
495 eventItem1->eventList.clear();
498 p1 = QPoint(10, 310);
499 QTest::touchEvent(window, device).press(0, p1, window);
500 QCOMPARE(eventItem2->eventList.size(), 1);
501 QCOMPARE(eventItem2->eventList.at(0).type, QEvent::TouchBegin);
502 QTest::touchEvent(window, device).release(0, p1, window);
503 QCOMPARE(eventItem2->eventList.size(), 2);
504 QCOMPARE(eventItem2->eventList.at(1).type, QEvent::TouchEnd);
505 QCOMPARE(eventItem1->eventList.size(), 0);
506 eventItem2->eventList.clear();
508 // wait to avoid getting a double click event
509 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
511 // click above button, no events please
513 QTest::touchEvent(window, device).press(0, p1, window);
514 QCOMPARE(eventItem1->eventList.size(), 0);
515 QTest::touchEvent(window, device).release(0, p1, window);
516 QCOMPARE(eventItem1->eventList.size(), 0);
517 eventItem1->eventList.clear();
519 // wait to avoid getting a double click event
520 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
522 // check that flickable moves - mouse button
523 QCOMPARE(eventItem1->eventList.size(), 0);
524 p1 = QPoint(10, 110);
525 QTest::touchEvent(window, device).press(0, p1, window);
526 QCOMPARE(eventItem1->eventList.size(), 2);
527 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
528 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
530 QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
531 QCOMPARE(windowPriv->touchMouseId, 0);
532 QCOMPARE(windowPriv->itemForTouchPointId[0], eventItem1);
533 QCOMPARE(windowPriv->mouseGrabberItem, eventItem1);
535 p1 += QPoint(0, -10);
536 QPoint p2 = p1 + QPoint(0, -10);
537 QPoint p3 = p2 + QPoint(0, -10);
539 QTest::touchEvent(window, device).move(0, p1, window);
541 QTest::touchEvent(window, device).move(0, p2, window);
543 QTest::touchEvent(window, device).move(0, p3, window);
545 // we cannot really know when the events get grabbed away
546 QVERIFY(eventItem1->eventList.size() >= 4);
547 QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchUpdate);
548 QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseMove);
550 QCOMPARE(windowPriv->mouseGrabberItem, flickable);
551 QVERIFY(flickable->isMovingVertically());
553 QTest::touchEvent(window, device).release(0, p3, window);
557 void tst_TouchMouse::buttonOnTouch()
560 // PinchArea - height 400
561 // - eventItem1 y: 100, height 100
562 // - eventItem2 y: 300, height 100
563 // MultiPointTouchArea - height 400
564 // - eventItem1 y: 100, height 100
565 // - eventItem2 y: 300, height 100
567 QQuickView *window = createView();
568 window->setSource(testFileUrl("buttonontouch.qml"));
570 window->requestActivateWindow();
571 QVERIFY(window->rootObject() != 0);
573 QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
575 QQuickItem *button1 = window->rootObject()->findChild<QQuickItem*>("button1");
577 EventItem *eventItem1 = window->rootObject()->findChild<EventItem*>("eventItem1");
579 EventItem *eventItem2 = window->rootObject()->findChild<EventItem*>("eventItem2");
582 QQuickMultiPointTouchArea *touchArea = window->rootObject()->findChild<QQuickMultiPointTouchArea*>("toucharea");
584 EventItem *eventItem3 = window->rootObject()->findChild<EventItem*>("eventItem3");
586 EventItem *eventItem4 = window->rootObject()->findChild<EventItem*>("eventItem4");
590 // Test the common case of a mouse area on top of pinch
591 eventItem1->setAcceptedMouseButtons(Qt::LeftButton);
592 eventItem1->acceptMouse = true;
595 // wait to avoid getting a double click event
596 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
598 // Normal touch click
599 QPoint p1 = QPoint(10, 110);
600 QTest::touchEvent(window, device).press(0, p1, window);
601 QTest::touchEvent(window, device).release(0, p1, window);
602 QCOMPARE(eventItem1->eventList.size(), 4);
603 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
604 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
605 QCOMPARE(eventItem1->eventList.at(2).type, QEvent::TouchEnd);
606 QCOMPARE(eventItem1->eventList.at(3).type, QEvent::MouseButtonRelease);
607 eventItem1->eventList.clear();
609 // Normal mouse click
610 QTest::mouseClick(window, Qt::LeftButton, 0, p1);
611 QCOMPARE(eventItem1->eventList.size(), 2);
612 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::MouseButtonPress);
613 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonRelease);
614 eventItem1->eventList.clear();
616 // Pinch starting on the PinchArea should work
618 QPoint p2 = QPoint(60, 10);
620 // Start the events after each other
621 QTest::touchEvent(window, device).press(0, p1, window);
622 QTest::touchEvent(window, device).stationary(0).press(1, p2, window);
624 QCOMPARE(button1->scale(), 1.0);
626 // This event seems to be discarded, let's ignore it for now until someone digs into pincharea
629 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
633 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
634 // QCOMPARE(button1->scale(), 1.5);
635 qDebug() << "Button scale: " << button1->scale();
639 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
640 // QCOMPARE(button1->scale(), 2.0);
641 qDebug() << "Button scale: " << button1->scale();
643 QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
644 // QVERIFY(eventItem1->eventList.isEmpty());
645 // QCOMPARE(button1->scale(), 2.0);
646 qDebug() << "Button scale: " << button1->scale();
649 // wait to avoid getting a double click event
650 QTest::qWait(qApp->styleHints()->mouseDoubleClickInterval() + 10);
652 // Start pinching while on the button
653 button1->setScale(1.0);
654 p1 = QPoint(40, 110);
655 p2 = QPoint(60, 110);
656 QTest::touchEvent(window, device).press(0, p1, window).press(1, p2, window);
657 QCOMPARE(button1->scale(), 1.0);
658 QCOMPARE(eventItem1->eventList.count(), 2);
659 QCOMPARE(eventItem1->eventList.at(0).type, QEvent::TouchBegin);
660 QCOMPARE(eventItem1->eventList.at(1).type, QEvent::MouseButtonPress);
662 // This event seems to be discarded, let's ignore it for now until someone digs into pincharea
665 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
669 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
670 //QCOMPARE(button1->scale(), 1.5);
671 qDebug() << button1->scale();
675 QTest::touchEvent(window, device).move(0, p1, window).move(1, p2, window);
676 qDebug() << button1->scale();
677 //QCOMPARE(button1->scale(), 2.0);
679 QTest::touchEvent(window, device).release(0, p1, window).release(1, p2, window);
680 // QCOMPARE(eventItem1->eventList.size(), 99);
681 qDebug() << button1->scale();
682 //QCOMPARE(button1->scale(), 2.0);
687 void tst_TouchMouse::pinchOnFlickable()
689 QQuickView *window = createView();
690 window->setSource(testFileUrl("pinchonflickable.qml"));
692 window->requestActivateWindow();
693 QVERIFY(window->rootObject() != 0);
695 QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
697 QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
699 QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
702 // flickable - single touch point
703 QVERIFY(flickable->contentX() == 0.0);
704 QPoint p = QPoint(100, 100);
705 QTest::touchEvent(window, device).press(0, p, window);
706 QCOMPARE(rect->pos(), QPointF(200.0, 200.0));
708 QTest::touchEvent(window, device).move(0, p, window);
710 QTest::touchEvent(window, device).move(0, p, window);
713 QTest::touchEvent(window, device).move(0, p, window);
716 QTest::touchEvent(window, device).move(0, p, window);
717 QTest::touchEvent(window, device).release(0, p, window);
719 QGuiApplication::processEvents();
721 QVERIFY(!flickable->isAtXBeginning());
722 // wait until flicking is done
723 QTRY_VERIFY(!flickable->isFlicking());
726 QPoint p1 = QPoint(40, 20);
727 QPoint p2 = QPoint(60, 20);
729 QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
730 pinchSequence.press(0, p1, window).commit();
731 // In order for the stationary point to remember its previous position,
732 // we have to reuse the same pinchSequence object. Otherwise if we let it
733 // be destroyed and then start a new sequence, point 0 will default to being
734 // stationary at 0, 0, and PinchArea will filter out that touchpoint because
735 // it is outside its bounds.
736 pinchSequence.stationary(0).press(1, p2, window).commit();
739 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
740 QCOMPARE(rect->scale(), 1.0);
743 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
746 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
749 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
750 pinchSequence.release(0, p1, window).release(1, p2, window).commit();
751 QVERIFY(rect->scale() > 1.0);
754 void tst_TouchMouse::flickableOnPinch()
756 QQuickView *window = createView();
757 window->setSource(testFileUrl("flickableonpinch.qml"));
759 window->requestActivateWindow();
760 QVERIFY(window->rootObject() != 0);
762 QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
764 QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
766 QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
769 // flickable - single touch point
770 QVERIFY(flickable->contentX() == 0.0);
771 QPoint p = QPoint(100, 100);
772 QTest::touchEvent(window, device).press(0, p, window);
773 QCOMPARE(rect->pos(), QPointF(200.0, 200.0));
775 QTest::touchEvent(window, device).move(0, p, window);
777 QTest::touchEvent(window, device).move(0, p, window);
782 QTest::touchEvent(window, device).move(0, p, window);
783 QTest::touchEvent(window, device).release(0, p, window);
787 //QVERIFY(flickable->isMovingHorizontally());
788 qDebug() << "Pos: " << rect->pos();
789 // wait until flicking is done
790 QTRY_VERIFY(!flickable->isFlicking());
793 QPoint p1 = QPoint(40, 20);
794 QPoint p2 = QPoint(60, 20);
795 QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
796 pinchSequence.press(0, p1, window).commit();
797 // In order for the stationary point to remember its previous position,
798 // we have to reuse the same pinchSequence object. Otherwise if we let it
799 // be destroyed and then start a new sequence, point 0 will default to being
800 // stationary at 0, 0, and PinchArea will filter out that touchpoint because
801 // it is outside its bounds.
802 pinchSequence.stationary(0).press(1, p2, window).commit();
805 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
806 QCOMPARE(rect->scale(), 1.0);
809 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
812 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
815 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
816 pinchSequence.release(0, p1, window).release(1, p2, window).commit();
817 QVERIFY(rect->scale() > 1.0);
820 void tst_TouchMouse::mouseOnFlickableOnPinch()
822 QQuickView *window = createView();
823 window->setSource(testFileUrl("mouseonflickableonpinch.qml"));
825 window->requestActivateWindow();
826 QVERIFY(window->rootObject() != 0);
828 QQuickPinchArea *pinchArea = window->rootObject()->findChild<QQuickPinchArea*>("pincharea");
830 QQuickFlickable *flickable = window->rootObject()->findChild<QQuickFlickable*>("flickable");
832 QQuickItem *rect = window->rootObject()->findChild<QQuickItem*>("rect");
835 // flickable - single touch point
836 QVERIFY(flickable->contentX() == 0.0);
837 QPoint p = QPoint(100, 100);
838 QTest::touchEvent(window, device).press(0, p, window);
839 QCOMPARE(rect->pos(), QPointF(200.0, 200.0));
841 QTest::touchEvent(window, device).move(0, p, window);
843 QTest::touchEvent(window, device).move(0, p, window);
848 QTest::touchEvent(window, device).move(0, p, window);
849 QTest::touchEvent(window, device).release(0, p, window);
853 //QVERIFY(flickable->isMovingHorizontally());
854 qDebug() << "Pos: " << rect->pos();
857 QPoint p1 = QPoint(40, 20);
858 QPoint p2 = QPoint(60, 20);
859 QTest::QTouchEventSequence pinchSequence = QTest::touchEvent(window, device);
860 pinchSequence.press(0, p1, window).commit();
861 // In order for the stationary point to remember its previous position,
862 // we have to reuse the same pinchSequence object. Otherwise if we let it
863 // be destroyed and then start a new sequence, point 0 will default to being
864 // stationary at 0, 0, and PinchArea will filter out that touchpoint because
865 // it is outside its bounds.
866 pinchSequence.stationary(0).press(1, p2, window).commit();
869 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
870 QCOMPARE(rect->scale(), 1.0);
873 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
876 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
879 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
880 pinchSequence.release(0, p1, window).release(1, p2, window).commit();
881 QVERIFY(rect->scale() > 1.0);
883 // PinchArea should steal the event after flicking started
885 flickable->setContentX(0.0);
886 p = QPoint(100, 100);
887 pinchSequence.press(0, p, window).commit();
888 QCOMPARE(rect->pos(), QPointF(200.0, 200.0));
890 pinchSequence.move(0, p, window).commit();
892 pinchSequence.move(0, p, window).commit();
895 pinchSequence.move(0, p, window).commit();
897 QQuickWindowPrivate *windowPriv = QQuickWindowPrivate::get(window);
898 QCOMPARE(windowPriv->mouseGrabberItem, flickable);
899 qDebug() << "Mouse Grabber: " << windowPriv->mouseGrabberItem << " itemForTouchPointId: " << windowPriv->itemForTouchPointId;
901 // Add a second finger, this should lead to stealing
902 p1 = QPoint(40, 100);
903 p2 = QPoint(60, 100);
904 pinchSequence.stationary(0).press(1, p2, window).commit();
905 QCOMPARE(rect->scale(), 1.0);
909 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
912 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
915 pinchSequence.move(0, p1, window).move(1, p2, window).commit();
916 pinchSequence.release(0, p1, window).release(1, p2, window).commit();
917 QVERIFY(rect->scale() > 1.0);
918 pinchSequence.release(0, p, window).commit();
921 QTEST_MAIN(tst_TouchMouse)
923 #include "tst_touchmouse.moc"