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 test suite 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 ****************************************************************************/
42 #include <QtTest/QtTest>
43 #include <QtTest/QSignalSpy>
44 #include <QtQuick/private/qquickmousearea_p.h>
45 #include <QtQuick/private/qquickrectangle_p.h>
46 #include <private/qquickflickable_p.h>
47 #include <QtQuick/qquickview.h>
48 #include <QtQml/qqmlcontext.h>
49 #include <QtQml/qqmlengine.h>
50 #include "../../shared/util.h"
51 #include <QtGui/qstylehints.h>
55 class tst_QQuickMouseArea: public QQmlDataTest
59 void dragProperties();
62 void updateMouseAreaPosOnClick();
63 void updateMouseAreaPosOnResize();
64 void noOnClickedWithPressAndHold();
65 void onMousePressRejected();
66 void pressedCanceledOnWindowDeactivate();
69 void pressedOrdering();
70 void preventStealing();
73 void hoverPropagation();
75 void disableAfterPress();
79 QQuickView *createView();
82 void tst_QQuickMouseArea::dragProperties()
84 QQuickView *canvas = createView();
86 canvas->setSource(testFileUrl("dragproperties.qml"));
88 canvas->requestActivateWindow();
89 QVERIFY(canvas->rootObject() != 0);
91 QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
92 QQuickDrag *drag = mouseRegion->drag();
93 QVERIFY(mouseRegion != 0);
97 QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
98 QVERIFY(blackRect != 0);
99 QVERIFY(blackRect == drag->target());
100 QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
101 QVERIFY(rootItem != 0);
102 QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
103 drag->setTarget(rootItem);
104 QCOMPARE(targetSpy.count(),1);
105 drag->setTarget(rootItem);
106 QCOMPARE(targetSpy.count(),1);
109 QCOMPARE(drag->axis(), QQuickDrag::XandYAxis);
110 QSignalSpy axisSpy(drag, SIGNAL(axisChanged()));
111 drag->setAxis(QQuickDrag::XAxis);
112 QCOMPARE(drag->axis(), QQuickDrag::XAxis);
113 QCOMPARE(axisSpy.count(),1);
114 drag->setAxis(QQuickDrag::XAxis);
115 QCOMPARE(axisSpy.count(),1);
117 // minimum and maximum properties
118 QSignalSpy xminSpy(drag, SIGNAL(minimumXChanged()));
119 QSignalSpy xmaxSpy(drag, SIGNAL(maximumXChanged()));
120 QSignalSpy yminSpy(drag, SIGNAL(minimumYChanged()));
121 QSignalSpy ymaxSpy(drag, SIGNAL(maximumYChanged()));
123 QCOMPARE(drag->xmin(), 0.0);
124 QCOMPARE(drag->xmax(), rootItem->width()-blackRect->width());
125 QCOMPARE(drag->ymin(), 0.0);
126 QCOMPARE(drag->ymax(), rootItem->height()-blackRect->height());
133 QCOMPARE(drag->xmin(), 10.0);
134 QCOMPARE(drag->xmax(), 10.0);
135 QCOMPARE(drag->ymin(), 10.0);
136 QCOMPARE(drag->ymax(), 10.0);
138 QCOMPARE(xminSpy.count(),1);
139 QCOMPARE(xmaxSpy.count(),1);
140 QCOMPARE(yminSpy.count(),1);
141 QCOMPARE(ymaxSpy.count(),1);
148 QCOMPARE(xminSpy.count(),1);
149 QCOMPARE(xmaxSpy.count(),1);
150 QCOMPARE(yminSpy.count(),1);
151 QCOMPARE(ymaxSpy.count(),1);
154 QSignalSpy filterChildrenSpy(drag, SIGNAL(filterChildrenChanged()));
156 drag->setFilterChildren(true);
158 QVERIFY(drag->filterChildren());
159 QCOMPARE(filterChildrenSpy.count(), 1);
161 drag->setFilterChildren(true);
162 QCOMPARE(filterChildrenSpy.count(), 1);
167 void tst_QQuickMouseArea::resetDrag()
169 QQuickView *canvas = createView();
171 canvas->rootContext()->setContextProperty("haveTarget", QVariant(true));
172 canvas->setSource(testFileUrl("dragreset.qml"));
174 canvas->requestActivateWindow();
175 QVERIFY(canvas->rootObject() != 0);
177 QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
178 QQuickDrag *drag = mouseRegion->drag();
179 QVERIFY(mouseRegion != 0);
183 QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
184 QVERIFY(blackRect != 0);
185 QVERIFY(blackRect == drag->target());
186 QQuickItem *rootItem = qobject_cast<QQuickItem*>(canvas->rootObject());
187 QVERIFY(rootItem != 0);
188 QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
189 QVERIFY(drag->target() != 0);
190 canvas->rootContext()->setContextProperty("haveTarget", QVariant(false));
191 QCOMPARE(targetSpy.count(),1);
192 QVERIFY(drag->target() == 0);
198 void tst_QQuickMouseArea::dragging()
200 QQuickView *canvas = createView();
202 canvas->setSource(testFileUrl("dragging.qml"));
204 canvas->requestActivateWindow();
206 QVERIFY(canvas->rootObject() != 0);
208 QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
209 QQuickDrag *drag = mouseRegion->drag();
210 QVERIFY(mouseRegion != 0);
214 QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
215 QVERIFY(blackRect != 0);
216 QVERIFY(blackRect == drag->target());
218 QVERIFY(!drag->active());
221 QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
222 QGuiApplication::sendEvent(canvas, &pressEvent);
224 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
227 QVERIFY(!drag->active());
228 QCOMPARE(blackRect->x(), 50.0);
229 QCOMPARE(blackRect->y(), 50.0);
231 // First move event triggers drag, second is acted upon.
232 // This is due to possibility of higher stacked area taking precedence.
234 QTest::mouseMove(canvas, QPoint(111,111));
236 QTest::mouseMove(canvas, QPoint(122,122));
239 QVERIFY(drag->active());
240 QCOMPARE(blackRect->x(), 72.0);
241 QCOMPARE(blackRect->y(), 72.0);
244 QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
245 QGuiApplication::sendEvent(canvas, &releaseEvent);
247 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(122,122));
251 QVERIFY(!drag->active());
252 QCOMPARE(blackRect->x(), 72.0);
253 QCOMPARE(blackRect->y(), 72.0);
258 QQuickView *tst_QQuickMouseArea::createView()
260 QQuickView *canvas = new QQuickView(0);
261 canvas->setBaseSize(QSize(240,320));
266 void tst_QQuickMouseArea::updateMouseAreaPosOnClick()
268 QQuickView *canvas = createView();
269 canvas->setSource(testFileUrl("updateMousePosOnClick.qml"));
271 canvas->requestActivateWindow();
272 QVERIFY(canvas->rootObject() != 0);
274 QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
275 QVERIFY(mouseRegion != 0);
277 QQuickRectangle *rect = canvas->rootObject()->findChild<QQuickRectangle*>("ball");
280 QCOMPARE(mouseRegion->mouseX(), rect->x());
281 QCOMPARE(mouseRegion->mouseY(), rect->y());
283 QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
284 QGuiApplication::sendEvent(canvas, &event);
286 QCOMPARE(mouseRegion->mouseX(), 100.0);
287 QCOMPARE(mouseRegion->mouseY(), 100.0);
289 QCOMPARE(mouseRegion->mouseX(), rect->x());
290 QCOMPARE(mouseRegion->mouseY(), rect->y());
295 void tst_QQuickMouseArea::updateMouseAreaPosOnResize()
297 QQuickView *canvas = createView();
298 canvas->setSource(testFileUrl("updateMousePosOnResize.qml"));
300 canvas->requestActivateWindow();
301 QVERIFY(canvas->rootObject() != 0);
303 QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
304 QVERIFY(mouseRegion != 0);
306 QQuickRectangle *rect = canvas->rootObject()->findChild<QQuickRectangle*>("brother");
309 QCOMPARE(mouseRegion->mouseX(), 0.0);
310 QCOMPARE(mouseRegion->mouseY(), 0.0);
312 QMouseEvent event(QEvent::MouseButtonPress, rect->pos().toPoint(), Qt::LeftButton, Qt::LeftButton, 0);
313 QGuiApplication::sendEvent(canvas, &event);
315 QVERIFY(!mouseRegion->property("emitPositionChanged").toBool());
316 QVERIFY(mouseRegion->property("mouseMatchesPos").toBool());
318 QCOMPARE(mouseRegion->property("x1").toReal(), 0.0);
319 QCOMPARE(mouseRegion->property("y1").toReal(), 0.0);
321 QCOMPARE(mouseRegion->property("x2").toReal(), rect->x());
322 QCOMPARE(mouseRegion->property("y2").toReal(), rect->y());
324 QCOMPARE(mouseRegion->mouseX(), rect->x());
325 QCOMPARE(mouseRegion->mouseY(), rect->y());
330 void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
333 // We handle onPressAndHold, therefore no onClicked
334 QQuickView *canvas = createView();
335 canvas->setSource(testFileUrl("clickandhold.qml"));
337 canvas->requestActivateWindow();
338 QVERIFY(canvas->rootObject() != 0);
340 QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
341 QGuiApplication::sendEvent(canvas, &pressEvent);
343 QVERIFY(!canvas->rootObject()->property("clicked").toBool());
344 QVERIFY(!canvas->rootObject()->property("held").toBool());
348 QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
349 QGuiApplication::sendEvent(canvas, &releaseEvent);
351 QVERIFY(!canvas->rootObject()->property("clicked").toBool());
352 QVERIFY(canvas->rootObject()->property("held").toBool());
358 // We do not handle onPressAndHold, therefore we get onClicked
359 QQuickView *canvas = createView();
360 canvas->setSource(testFileUrl("noclickandhold.qml"));
362 canvas->requestActivateWindow();
363 QVERIFY(canvas->rootObject() != 0);
365 QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
366 QGuiApplication::sendEvent(canvas, &pressEvent);
368 QVERIFY(!canvas->rootObject()->property("clicked").toBool());
372 QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
373 QGuiApplication::sendEvent(canvas, &releaseEvent);
375 QVERIFY(canvas->rootObject()->property("clicked").toBool());
381 void tst_QQuickMouseArea::onMousePressRejected()
383 QQuickView *canvas = createView();
384 canvas->setSource(testFileUrl("rejectEvent.qml"));
386 canvas->requestActivateWindow();
387 QVERIFY(canvas->rootObject() != 0);
388 QVERIFY(canvas->rootObject()->property("enabled").toBool());
390 QVERIFY(!canvas->rootObject()->property("mr1_pressed").toBool());
391 QVERIFY(!canvas->rootObject()->property("mr1_released").toBool());
392 QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
393 QVERIFY(!canvas->rootObject()->property("mr2_pressed").toBool());
394 QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
395 QVERIFY(!canvas->rootObject()->property("mr2_canceled").toBool());
397 QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
398 QGuiApplication::sendEvent(canvas, &pressEvent);
400 QVERIFY(canvas->rootObject()->property("mr1_pressed").toBool());
401 QVERIFY(!canvas->rootObject()->property("mr1_released").toBool());
402 QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
403 QVERIFY(canvas->rootObject()->property("mr2_pressed").toBool());
404 QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
405 QVERIFY(canvas->rootObject()->property("mr2_canceled").toBool());
409 QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
410 QGuiApplication::sendEvent(canvas, &releaseEvent);
412 QVERIFY(canvas->rootObject()->property("mr1_released").toBool());
413 QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
414 QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
418 void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
420 QQuickView *canvas = createView();
421 canvas->setSource(testFileUrl("pressedCanceled.qml"));
423 canvas->requestActivateWindow();
424 QVERIFY(canvas->rootObject() != 0);
425 QVERIFY(!canvas->rootObject()->property("pressed").toBool());
426 QVERIFY(!canvas->rootObject()->property("canceled").toBool());
427 QVERIFY(!canvas->rootObject()->property("released").toBool());
429 QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
430 QGuiApplication::sendEvent(canvas, &pressEvent);
432 QVERIFY(canvas->rootObject()->property("pressed").toBool());
433 QVERIFY(!canvas->rootObject()->property("canceled").toBool());
434 QVERIFY(!canvas->rootObject()->property("released").toBool());
438 QEvent windowDeactivateEvent(QEvent::WindowDeactivate);
439 QGuiApplication::sendEvent(canvas, &windowDeactivateEvent);
440 QVERIFY(!canvas->rootObject()->property("pressed").toBool());
441 QVERIFY(canvas->rootObject()->property("canceled").toBool());
442 QVERIFY(!canvas->rootObject()->property("released").toBool());
447 QGuiApplication::sendEvent(canvas, &pressEvent);
448 QVERIFY(canvas->rootObject()->property("pressed").toBool());
449 QVERIFY(!canvas->rootObject()->property("canceled").toBool());
450 QVERIFY(!canvas->rootObject()->property("released").toBool());
455 QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
456 QGuiApplication::sendEvent(canvas, &releaseEvent);
457 QVERIFY(!canvas->rootObject()->property("pressed").toBool());
458 QVERIFY(!canvas->rootObject()->property("canceled").toBool());
459 QVERIFY(canvas->rootObject()->property("released").toBool());
463 void tst_QQuickMouseArea::doubleClick()
465 QQuickView *canvas = createView();
466 canvas->setSource(testFileUrl("doubleclick.qml"));
468 canvas->requestActivateWindow();
469 QVERIFY(canvas->rootObject() != 0);
471 // The sequence for a double click is:
472 // press, release, (click), press, double click, release
473 QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
474 QGuiApplication::sendEvent(canvas, &pressEvent);
476 QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
477 QGuiApplication::sendEvent(canvas, &releaseEvent);
479 QCOMPARE(canvas->rootObject()->property("released").toInt(), 1);
481 QGuiApplication::sendEvent(canvas, &pressEvent);
482 pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
483 QGuiApplication::sendEvent(canvas, &pressEvent);
484 QGuiApplication::sendEvent(canvas, &releaseEvent);
486 QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 1);
487 QCOMPARE(canvas->rootObject()->property("doubleClicked").toInt(), 1);
488 QCOMPARE(canvas->rootObject()->property("released").toInt(), 2);
494 void tst_QQuickMouseArea::clickTwice()
496 QQuickView *canvas = createView();
497 canvas->setSource(testFileUrl("clicktwice.qml"));
499 canvas->requestActivateWindow();
500 QVERIFY(canvas->rootObject() != 0);
502 QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
503 QGuiApplication::sendEvent(canvas, &pressEvent);
505 QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
506 QGuiApplication::sendEvent(canvas, &releaseEvent);
508 QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 1);
509 QCOMPARE(canvas->rootObject()->property("released").toInt(), 1);
510 QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 1);
512 QGuiApplication::sendEvent(canvas, &pressEvent);
513 pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
514 QGuiApplication::sendEvent(canvas, &pressEvent);
515 QGuiApplication::sendEvent(canvas, &releaseEvent);
517 QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 2);
518 QCOMPARE(canvas->rootObject()->property("released").toInt(), 2);
519 QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 2);
524 void tst_QQuickMouseArea::pressedOrdering()
526 QQuickView *canvas = createView();
527 canvas->setSource(testFileUrl("pressedOrdering.qml"));
529 canvas->requestActivateWindow();
530 QVERIFY(canvas->rootObject() != 0);
532 QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("base"));
534 QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
535 QGuiApplication::sendEvent(canvas, &pressEvent);
537 QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed"));
539 QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
540 QGuiApplication::sendEvent(canvas, &releaseEvent);
542 QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("toggled"));
544 QGuiApplication::sendEvent(canvas, &pressEvent);
546 QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed"));
551 void tst_QQuickMouseArea::preventStealing()
553 QQuickView *canvas = createView();
555 canvas->setSource(testFileUrl("preventstealing.qml"));
557 canvas->requestActivateWindow();
558 QVERIFY(canvas->rootObject() != 0);
560 QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
561 QVERIFY(flickable != 0);
563 QQuickMouseArea *mouseArea = canvas->rootObject()->findChild<QQuickMouseArea*>("mousearea");
564 QVERIFY(mouseArea != 0);
566 QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
568 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(80, 80));
570 // Without preventStealing, mouse movement over MouseArea would
571 // cause the Flickable to steal mouse and trigger content movement.
573 QTest::mouseMove(canvas,QPoint(69,69));
574 QTest::mouseMove(canvas,QPoint(58,58));
575 QTest::mouseMove(canvas,QPoint(47,47));
577 // We should have received all three move events
578 QCOMPARE(mousePositionSpy.count(), 3);
579 QVERIFY(mouseArea->pressed());
581 // Flickable content should not have moved.
582 QCOMPARE(flickable->contentX(), 0.);
583 QCOMPARE(flickable->contentY(), 0.);
585 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(47, 47));
587 // Now allow stealing and confirm Flickable does its thing.
588 canvas->rootObject()->setProperty("stealing", false);
590 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(80, 80));
592 // Without preventStealing, mouse movement over MouseArea would
593 // cause the Flickable to steal mouse and trigger content movement.
595 QTest::mouseMove(canvas,QPoint(69,69));
596 QTest::mouseMove(canvas,QPoint(58,58));
597 QTest::mouseMove(canvas,QPoint(47,47));
599 // We should only have received the first move event
600 QCOMPARE(mousePositionSpy.count(), 4);
601 // Our press should be taken away
602 QVERIFY(!mouseArea->pressed());
604 // Flickable content should have moved.
606 QCOMPARE(flickable->contentX(), 11.);
607 QCOMPARE(flickable->contentY(), 11.);
609 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 50));
614 void tst_QQuickMouseArea::clickThrough()
616 QSKIP("QTBUG-23976 Unstable");
617 //With no handlers defined click, doubleClick and PressAndHold should propagate to those with handlers
618 QQuickView *canvas = createView();
619 canvas->setSource(testFileUrl("clickThrough.qml"));
621 canvas->requestActivateWindow();
622 QVERIFY(canvas->rootObject() != 0);
624 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
625 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
627 QTRY_COMPARE(canvas->rootObject()->property("presses").toInt(), 0);
628 QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
630 // to avoid generating a double click.
631 int doubleClickInterval = qApp->styleHints()->mouseDoubleClickInterval() + 10;
632 QTest::qWait(doubleClickInterval);
634 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
636 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
638 QTRY_COMPARE(canvas->rootObject()->property("presses").toInt(), 0);
639 QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
640 QTRY_COMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
642 QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
645 QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
646 QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 2);
647 QTRY_COMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 1);
648 QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
652 //With handlers defined click, doubleClick and PressAndHold should propagate only when explicitly ignored
653 canvas = createView();
654 canvas->setSource(testFileUrl("clickThrough2.qml"));
656 canvas->requestActivateWindow();
657 QVERIFY(canvas->rootObject() != 0);
659 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
660 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
662 QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
663 QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
665 QTest::qWait(doubleClickInterval); // to avoid generating a double click.
667 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
669 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
672 QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
673 QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
674 QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 0);
676 QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
679 QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
680 QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
681 QCOMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 0);
682 QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 0);
684 canvas->rootObject()->setProperty("letThrough", QVariant(true));
686 QTest::qWait(doubleClickInterval); // to avoid generating a double click.
687 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
688 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
690 QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
691 QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
693 QTest::qWait(doubleClickInterval); // to avoid generating a double click.
694 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
696 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
699 QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
700 QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
701 QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
703 QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
706 QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
707 QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 2);
708 QCOMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 1);
709 QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
711 canvas->rootObject()->setProperty("noPropagation", QVariant(true));
713 QTest::qWait(doubleClickInterval); // to avoid generating a double click.
714 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
715 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
717 QTest::qWait(doubleClickInterval); // to avoid generating a double click.
718 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
720 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
723 QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
726 QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
727 QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 2);
728 QCOMPARE(canvas->rootObject()->property("doubleClicks").toInt(), 1);
729 QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
734 void tst_QQuickMouseArea::hoverPosition()
736 QQuickView *canvas = createView();
737 canvas->setSource(testFileUrl("hoverPosition.qml"));
739 QQuickItem *root = canvas->rootObject();
742 QCOMPARE(root->property("mouseX").toReal(), qreal(0));
743 QCOMPARE(root->property("mouseY").toReal(), qreal(0));
745 QTest::mouseMove(canvas,QPoint(10,32));
748 QCOMPARE(root->property("mouseX").toReal(), qreal(10));
749 QCOMPARE(root->property("mouseY").toReal(), qreal(32));
754 void tst_QQuickMouseArea::hoverPropagation()
756 //QTBUG-18175, to behave like GV did.
757 QQuickView *canvas = createView();
758 canvas->setSource(testFileUrl("hoverPropagation.qml"));
760 QQuickItem *root = canvas->rootObject();
763 QCOMPARE(root->property("point1").toBool(), false);
764 QCOMPARE(root->property("point2").toBool(), false);
766 QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, 0);
767 QGuiApplication::sendEvent(canvas, &moveEvent);
769 QCOMPARE(root->property("point1").toBool(), true);
770 QCOMPARE(root->property("point2").toBool(), false);
772 QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, 0);
773 QGuiApplication::sendEvent(canvas, &moveEvent2);
774 QCOMPARE(root->property("point1").toBool(), false);
775 QCOMPARE(root->property("point2").toBool(), true);
780 void tst_QQuickMouseArea::hoverVisible()
782 QQuickView *canvas = createView();
783 canvas->setSource(testFileUrl("hoverVisible.qml"));
785 QQuickItem *root = canvas->rootObject();
788 QQuickMouseArea *mouseTracker = canvas->rootObject()->findChild<QQuickMouseArea*>("mousetracker");
789 QVERIFY(mouseTracker != 0);
791 QSignalSpy enteredSpy(mouseTracker, SIGNAL(entered()));
793 // Note: We need to use a position that is different from the position in the last event
794 // generated in the previous test case. Otherwise it is not interpreted as a move.
795 QTest::mouseMove(canvas,QPoint(11,33));
797 QCOMPARE(mouseTracker->hovered(), false);
798 QCOMPARE(enteredSpy.count(), 0);
800 mouseTracker->setVisible(true);
802 QCOMPARE(mouseTracker->hovered(), true);
803 QCOMPARE(enteredSpy.count(), 1);
805 QEXPECT_FAIL("", "QTBUG-24282", Continue);
806 QCOMPARE(QPointF(mouseTracker->mouseX(), mouseTracker->mouseY()), QPointF(11,33));
811 void tst_QQuickMouseArea::disableAfterPress()
813 QQuickView *canvas = createView();
814 canvas->setSource(testFileUrl("dragging.qml"));
816 canvas->requestActivateWindow();
818 QVERIFY(canvas->rootObject() != 0);
820 QQuickMouseArea *mouseArea = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
821 QQuickDrag *drag = mouseArea->drag();
822 QVERIFY(mouseArea != 0);
825 QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
826 QSignalSpy mousePressSpy(mouseArea, SIGNAL(pressed(QQuickMouseEvent*)));
827 QSignalSpy mouseReleaseSpy(mouseArea, SIGNAL(released(QQuickMouseEvent*)));
830 QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
831 QVERIFY(blackRect != 0);
832 QVERIFY(blackRect == drag->target());
834 QVERIFY(!drag->active());
836 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
838 QTRY_COMPARE(mousePressSpy.count(), 1);
840 QVERIFY(!drag->active());
841 QCOMPARE(blackRect->x(), 50.0);
842 QCOMPARE(blackRect->y(), 50.0);
844 // First move event triggers drag, second is acted upon.
845 // This is due to possibility of higher stacked area taking precedence.
847 QTest::mouseMove(canvas, QPoint(111,111));
849 QTest::mouseMove(canvas, QPoint(122,122));
851 QTRY_COMPARE(mousePositionSpy.count(), 2);
853 QVERIFY(drag->active());
854 QCOMPARE(blackRect->x(), 72.0);
855 QCOMPARE(blackRect->y(), 72.0);
857 mouseArea->setEnabled(false);
859 // move should still be acted upon
860 QTest::mouseMove(canvas, QPoint(133,133));
862 QTest::mouseMove(canvas, QPoint(144,144));
864 QTRY_COMPARE(mousePositionSpy.count(), 4);
866 QVERIFY(drag->active());
867 QCOMPARE(blackRect->x(), 94.0);
868 QCOMPARE(blackRect->y(), 94.0);
870 QVERIFY(mouseArea->pressed());
871 QVERIFY(mouseArea->hovered());
873 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(144,144));
875 QTRY_COMPARE(mouseReleaseSpy.count(), 1);
877 QVERIFY(!drag->active());
878 QCOMPARE(blackRect->x(), 94.0);
879 QCOMPARE(blackRect->y(), 94.0);
881 QVERIFY(!mouseArea->pressed());
882 QVERIFY(!mouseArea->hovered()); // since hover is not enabled
884 // Next press will be ignored
888 mousePressSpy.clear();
889 mousePositionSpy.clear();
890 mouseReleaseSpy.clear();
892 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
894 QCOMPARE(mousePressSpy.count(), 0);
896 QTest::mouseMove(canvas, QPoint(111,111));
898 QTest::mouseMove(canvas, QPoint(122,122));
901 QCOMPARE(mousePositionSpy.count(), 0);
903 QVERIFY(!drag->active());
904 QCOMPARE(blackRect->x(), 50.0);
905 QCOMPARE(blackRect->y(), 50.0);
907 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(122,122));
910 QCOMPARE(mouseReleaseSpy.count(), 0);
915 void tst_QQuickMouseArea::onWheel()
917 QQuickView *canvas = createView();
918 canvas->setSource(testFileUrl("wheel.qml"));
920 QQuickItem *root = canvas->rootObject();
923 QWheelEvent wheelEvent(QPoint(10, 32), QPoint(10, 32), QPoint(60, 20), QPoint(0, 120),
924 0, Qt::Vertical,Qt::NoButton, Qt::ControlModifier);
925 QGuiApplication::sendEvent(canvas, &wheelEvent);
927 QCOMPARE(root->property("angleDeltaY").toInt(), 120);
928 QCOMPARE(root->property("mouseX").toReal(), qreal(10));
929 QCOMPARE(root->property("mouseY").toReal(), qreal(32));
930 QCOMPARE(root->property("controlPressed").toBool(), true);
935 QTEST_MAIN(tst_QQuickMouseArea)
937 #include "tst_qquickmousearea.moc"