Improve test to use actual double click timeout.
[profile/ivi/qtdeclarative.git] / tests / auto / quick / qquickmousearea / tst_qquickmousearea.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 test suite 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 #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>
52
53 //#define OLDWAY
54
55 class tst_QQuickMouseArea: public QQmlDataTest
56 {
57     Q_OBJECT
58 private slots:
59     void dragProperties();
60     void resetDrag();
61     void dragging();
62     void updateMouseAreaPosOnClick();
63     void updateMouseAreaPosOnResize();
64     void noOnClickedWithPressAndHold();
65     void onMousePressRejected();
66     void pressedCanceledOnWindowDeactivate();
67     void doubleClick();
68     void clickTwice();
69     void pressedOrdering();
70     void preventStealing();
71     void clickThrough();
72     void hoverPosition();
73     void hoverPropagation();
74     void hoverVisible();
75     void disableAfterPress();
76     void onWheel();
77
78 private:
79     QQuickView *createView();
80 };
81
82 void tst_QQuickMouseArea::dragProperties()
83 {
84     QQuickView *canvas = createView();
85
86     canvas->setSource(testFileUrl("dragproperties.qml"));
87     canvas->show();
88     canvas->requestActivateWindow();
89     QVERIFY(canvas->rootObject() != 0);
90
91     QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
92     QQuickDrag *drag = mouseRegion->drag();
93     QVERIFY(mouseRegion != 0);
94     QVERIFY(drag != 0);
95
96     // target
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);
107
108     // axis
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);
116
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()));
122
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());
127
128     drag->setXmin(10);
129     drag->setXmax(10);
130     drag->setYmin(10);
131     drag->setYmax(10);
132
133     QCOMPARE(drag->xmin(), 10.0);
134     QCOMPARE(drag->xmax(), 10.0);
135     QCOMPARE(drag->ymin(), 10.0);
136     QCOMPARE(drag->ymax(), 10.0);
137
138     QCOMPARE(xminSpy.count(),1);
139     QCOMPARE(xmaxSpy.count(),1);
140     QCOMPARE(yminSpy.count(),1);
141     QCOMPARE(ymaxSpy.count(),1);
142
143     drag->setXmin(10);
144     drag->setXmax(10);
145     drag->setYmin(10);
146     drag->setYmax(10);
147
148     QCOMPARE(xminSpy.count(),1);
149     QCOMPARE(xmaxSpy.count(),1);
150     QCOMPARE(yminSpy.count(),1);
151     QCOMPARE(ymaxSpy.count(),1);
152
153     // filterChildren
154     QSignalSpy filterChildrenSpy(drag, SIGNAL(filterChildrenChanged()));
155
156     drag->setFilterChildren(true);
157
158     QVERIFY(drag->filterChildren());
159     QCOMPARE(filterChildrenSpy.count(), 1);
160
161     drag->setFilterChildren(true);
162     QCOMPARE(filterChildrenSpy.count(), 1);
163
164     delete canvas;
165 }
166
167 void tst_QQuickMouseArea::resetDrag()
168 {
169     QQuickView *canvas = createView();
170
171     canvas->rootContext()->setContextProperty("haveTarget", QVariant(true));
172     canvas->setSource(testFileUrl("dragreset.qml"));
173     canvas->show();
174     canvas->requestActivateWindow();
175     QVERIFY(canvas->rootObject() != 0);
176
177     QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
178     QQuickDrag *drag = mouseRegion->drag();
179     QVERIFY(mouseRegion != 0);
180     QVERIFY(drag != 0);
181
182     // target
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);
193
194     delete canvas;
195 }
196
197
198 void tst_QQuickMouseArea::dragging()
199 {
200     QQuickView *canvas = createView();
201
202     canvas->setSource(testFileUrl("dragging.qml"));
203     canvas->show();
204     canvas->requestActivateWindow();
205     QTest::qWait(20);
206     QVERIFY(canvas->rootObject() != 0);
207
208     QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
209     QQuickDrag *drag = mouseRegion->drag();
210     QVERIFY(mouseRegion != 0);
211     QVERIFY(drag != 0);
212
213     // target
214     QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
215     QVERIFY(blackRect != 0);
216     QVERIFY(blackRect == drag->target());
217
218     QVERIFY(!drag->active());
219
220 #ifdef OLDWAY
221     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
222     QGuiApplication::sendEvent(canvas, &pressEvent);
223 #else
224     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
225 #endif
226
227     QVERIFY(!drag->active());
228     QCOMPARE(blackRect->x(), 50.0);
229     QCOMPARE(blackRect->y(), 50.0);
230
231     // First move event triggers drag, second is acted upon.
232     // This is due to possibility of higher stacked area taking precedence.
233
234     QTest::mouseMove(canvas, QPoint(111,111));
235     QTest::qWait(50);
236     QTest::mouseMove(canvas, QPoint(122,122));
237     QTest::qWait(50);
238
239     QVERIFY(drag->active());
240     QCOMPARE(blackRect->x(), 72.0);
241     QCOMPARE(blackRect->y(), 72.0);
242
243 #ifdef OLDWAY
244     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
245     QGuiApplication::sendEvent(canvas, &releaseEvent);
246 #else
247     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(122,122));
248     QTest::qWait(50);
249 #endif
250
251     QVERIFY(!drag->active());
252     QCOMPARE(blackRect->x(), 72.0);
253     QCOMPARE(blackRect->y(), 72.0);
254
255     delete canvas;
256 }
257
258 QQuickView *tst_QQuickMouseArea::createView()
259 {
260     QQuickView *canvas = new QQuickView(0);
261     canvas->setBaseSize(QSize(240,320));
262
263     return canvas;
264 }
265
266 void tst_QQuickMouseArea::updateMouseAreaPosOnClick()
267 {
268     QQuickView *canvas = createView();
269     canvas->setSource(testFileUrl("updateMousePosOnClick.qml"));
270     canvas->show();
271     canvas->requestActivateWindow();
272     QVERIFY(canvas->rootObject() != 0);
273
274     QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
275     QVERIFY(mouseRegion != 0);
276
277     QQuickRectangle *rect = canvas->rootObject()->findChild<QQuickRectangle*>("ball");
278     QVERIFY(rect != 0);
279
280     QCOMPARE(mouseRegion->mouseX(), rect->x());
281     QCOMPARE(mouseRegion->mouseY(), rect->y());
282
283     QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
284     QGuiApplication::sendEvent(canvas, &event);
285
286     QCOMPARE(mouseRegion->mouseX(), 100.0);
287     QCOMPARE(mouseRegion->mouseY(), 100.0);
288
289     QCOMPARE(mouseRegion->mouseX(), rect->x());
290     QCOMPARE(mouseRegion->mouseY(), rect->y());
291
292     delete canvas;
293 }
294
295 void tst_QQuickMouseArea::updateMouseAreaPosOnResize()
296 {
297     QQuickView *canvas = createView();
298     canvas->setSource(testFileUrl("updateMousePosOnResize.qml"));
299     canvas->show();
300     canvas->requestActivateWindow();
301     QVERIFY(canvas->rootObject() != 0);
302
303     QQuickMouseArea *mouseRegion = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
304     QVERIFY(mouseRegion != 0);
305
306     QQuickRectangle *rect = canvas->rootObject()->findChild<QQuickRectangle*>("brother");
307     QVERIFY(rect != 0);
308
309     QCOMPARE(mouseRegion->mouseX(), 0.0);
310     QCOMPARE(mouseRegion->mouseY(), 0.0);
311
312     QMouseEvent event(QEvent::MouseButtonPress, rect->pos().toPoint(), Qt::LeftButton, Qt::LeftButton, 0);
313     QGuiApplication::sendEvent(canvas, &event);
314
315     QVERIFY(!mouseRegion->property("emitPositionChanged").toBool());
316     QVERIFY(mouseRegion->property("mouseMatchesPos").toBool());
317
318     QCOMPARE(mouseRegion->property("x1").toReal(), 0.0);
319     QCOMPARE(mouseRegion->property("y1").toReal(), 0.0);
320
321     QCOMPARE(mouseRegion->property("x2").toReal(), rect->x());
322     QCOMPARE(mouseRegion->property("y2").toReal(), rect->y());
323
324     QCOMPARE(mouseRegion->mouseX(), rect->x());
325     QCOMPARE(mouseRegion->mouseY(), rect->y());
326
327     delete canvas;
328 }
329
330 void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
331 {
332     {
333         // We handle onPressAndHold, therefore no onClicked
334         QQuickView *canvas = createView();
335         canvas->setSource(testFileUrl("clickandhold.qml"));
336         canvas->show();
337         canvas->requestActivateWindow();
338         QVERIFY(canvas->rootObject() != 0);
339
340         QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
341         QGuiApplication::sendEvent(canvas, &pressEvent);
342
343         QVERIFY(!canvas->rootObject()->property("clicked").toBool());
344         QVERIFY(!canvas->rootObject()->property("held").toBool());
345
346         QTest::qWait(1000);
347
348         QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
349         QGuiApplication::sendEvent(canvas, &releaseEvent);
350
351         QVERIFY(!canvas->rootObject()->property("clicked").toBool());
352         QVERIFY(canvas->rootObject()->property("held").toBool());
353
354         delete canvas;
355     }
356
357     {
358         // We do not handle onPressAndHold, therefore we get onClicked
359         QQuickView *canvas = createView();
360         canvas->setSource(testFileUrl("noclickandhold.qml"));
361         canvas->show();
362         canvas->requestActivateWindow();
363         QVERIFY(canvas->rootObject() != 0);
364
365         QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
366         QGuiApplication::sendEvent(canvas, &pressEvent);
367
368         QVERIFY(!canvas->rootObject()->property("clicked").toBool());
369
370         QTest::qWait(1000);
371
372         QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
373         QGuiApplication::sendEvent(canvas, &releaseEvent);
374
375         QVERIFY(canvas->rootObject()->property("clicked").toBool());
376
377         delete canvas;
378     }
379 }
380
381 void tst_QQuickMouseArea::onMousePressRejected()
382 {
383     QQuickView *canvas = createView();
384     canvas->setSource(testFileUrl("rejectEvent.qml"));
385     canvas->show();
386     canvas->requestActivateWindow();
387     QVERIFY(canvas->rootObject() != 0);
388     QVERIFY(canvas->rootObject()->property("enabled").toBool());
389
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());
396
397     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
398     QGuiApplication::sendEvent(canvas, &pressEvent);
399
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());
406
407     QTest::qWait(200);
408
409     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
410     QGuiApplication::sendEvent(canvas, &releaseEvent);
411
412     QVERIFY(canvas->rootObject()->property("mr1_released").toBool());
413     QVERIFY(!canvas->rootObject()->property("mr1_canceled").toBool());
414     QVERIFY(!canvas->rootObject()->property("mr2_released").toBool());
415
416     delete canvas;
417 }
418 void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
419 {
420     QQuickView *canvas = createView();
421     canvas->setSource(testFileUrl("pressedCanceled.qml"));
422     canvas->show();
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());
428
429     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
430     QGuiApplication::sendEvent(canvas, &pressEvent);
431
432     QVERIFY(canvas->rootObject()->property("pressed").toBool());
433     QVERIFY(!canvas->rootObject()->property("canceled").toBool());
434     QVERIFY(!canvas->rootObject()->property("released").toBool());
435
436     QTest::qWait(200);
437
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());
443
444     QTest::qWait(200);
445
446     //press again
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());
451
452     QTest::qWait(200);
453
454     //release
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());
460
461     delete canvas;
462 }
463 void tst_QQuickMouseArea::doubleClick()
464 {
465     QQuickView *canvas = createView();
466     canvas->setSource(testFileUrl("doubleclick.qml"));
467     canvas->show();
468     canvas->requestActivateWindow();
469     QVERIFY(canvas->rootObject() != 0);
470
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);
475
476     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
477     QGuiApplication::sendEvent(canvas, &releaseEvent);
478
479     QCOMPARE(canvas->rootObject()->property("released").toInt(), 1);
480
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);
485
486     QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 1);
487     QCOMPARE(canvas->rootObject()->property("doubleClicked").toInt(), 1);
488     QCOMPARE(canvas->rootObject()->property("released").toInt(), 2);
489
490     delete canvas;
491 }
492
493 // QTBUG-14832
494 void tst_QQuickMouseArea::clickTwice()
495 {
496     QQuickView *canvas = createView();
497     canvas->setSource(testFileUrl("clicktwice.qml"));
498     canvas->show();
499     canvas->requestActivateWindow();
500     QVERIFY(canvas->rootObject() != 0);
501
502     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
503     QGuiApplication::sendEvent(canvas, &pressEvent);
504
505     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
506     QGuiApplication::sendEvent(canvas, &releaseEvent);
507
508     QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 1);
509     QCOMPARE(canvas->rootObject()->property("released").toInt(), 1);
510     QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 1);
511
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);
516
517     QCOMPARE(canvas->rootObject()->property("pressed").toInt(), 2);
518     QCOMPARE(canvas->rootObject()->property("released").toInt(), 2);
519     QCOMPARE(canvas->rootObject()->property("clicked").toInt(), 2);
520
521     delete canvas;
522 }
523
524 void tst_QQuickMouseArea::pressedOrdering()
525 {
526     QQuickView *canvas = createView();
527     canvas->setSource(testFileUrl("pressedOrdering.qml"));
528     canvas->show();
529     canvas->requestActivateWindow();
530     QVERIFY(canvas->rootObject() != 0);
531
532     QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("base"));
533
534     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
535     QGuiApplication::sendEvent(canvas, &pressEvent);
536
537     QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed"));
538
539     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
540     QGuiApplication::sendEvent(canvas, &releaseEvent);
541
542     QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("toggled"));
543
544     QGuiApplication::sendEvent(canvas, &pressEvent);
545
546     QCOMPARE(canvas->rootObject()->property("value").toString(), QLatin1String("pressed"));
547
548     delete canvas;
549 }
550
551 void tst_QQuickMouseArea::preventStealing()
552 {
553     QQuickView *canvas = createView();
554
555     canvas->setSource(testFileUrl("preventstealing.qml"));
556     canvas->show();
557     canvas->requestActivateWindow();
558     QVERIFY(canvas->rootObject() != 0);
559
560     QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(canvas->rootObject());
561     QVERIFY(flickable != 0);
562
563     QQuickMouseArea *mouseArea = canvas->rootObject()->findChild<QQuickMouseArea*>("mousearea");
564     QVERIFY(mouseArea != 0);
565
566     QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
567
568     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(80, 80));
569
570     // Without preventStealing, mouse movement over MouseArea would
571     // cause the Flickable to steal mouse and trigger content movement.
572
573     QTest::mouseMove(canvas,QPoint(69,69));
574     QTest::mouseMove(canvas,QPoint(58,58));
575     QTest::mouseMove(canvas,QPoint(47,47));
576
577     // We should have received all three move events
578     QCOMPARE(mousePositionSpy.count(), 3);
579     QVERIFY(mouseArea->pressed());
580
581     // Flickable content should not have moved.
582     QCOMPARE(flickable->contentX(), 0.);
583     QCOMPARE(flickable->contentY(), 0.);
584
585     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(47, 47));
586
587     // Now allow stealing and confirm Flickable does its thing.
588     canvas->rootObject()->setProperty("stealing", false);
589
590     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(80, 80));
591
592     // Without preventStealing, mouse movement over MouseArea would
593     // cause the Flickable to steal mouse and trigger content movement.
594
595     QTest::mouseMove(canvas,QPoint(69,69));
596     QTest::mouseMove(canvas,QPoint(58,58));
597     QTest::mouseMove(canvas,QPoint(47,47));
598
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());
603
604     // Flickable content should have moved.
605
606     QCOMPARE(flickable->contentX(), 11.);
607     QCOMPARE(flickable->contentY(), 11.);
608
609     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50, 50));
610
611     delete canvas;
612 }
613
614 void tst_QQuickMouseArea::clickThrough()
615 {
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"));
620     canvas->show();
621     canvas->requestActivateWindow();
622     QVERIFY(canvas->rootObject() != 0);
623
624     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
625     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
626
627     QTRY_COMPARE(canvas->rootObject()->property("presses").toInt(), 0);
628     QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
629
630     // to avoid generating a double click.
631     int doubleClickInterval = qApp->styleHints()->mouseDoubleClickInterval() + 10;
632     QTest::qWait(doubleClickInterval);
633
634     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
635     QTest::qWait(1000);
636     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
637
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);
641
642     QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
643     QTest::qWait(100);
644
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);
649
650     delete canvas;
651
652     //With handlers defined click, doubleClick and PressAndHold should propagate only when explicitly ignored
653     canvas = createView();
654     canvas->setSource(testFileUrl("clickThrough2.qml"));
655     canvas->show();
656     canvas->requestActivateWindow();
657     QVERIFY(canvas->rootObject() != 0);
658
659     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
660     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
661
662     QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
663     QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
664
665     QTest::qWait(doubleClickInterval); // to avoid generating a double click.
666
667     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
668     QTest::qWait(1000);
669     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
670     QTest::qWait(100);
671
672     QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
673     QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 0);
674     QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 0);
675
676     QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
677     QTest::qWait(100);
678
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);
683
684     canvas->rootObject()->setProperty("letThrough", QVariant(true));
685
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));
689
690     QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
691     QTRY_COMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
692
693     QTest::qWait(doubleClickInterval); // to avoid generating a double click.
694     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
695     QTest::qWait(1000);
696     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
697     QTest::qWait(100);
698
699     QCOMPARE(canvas->rootObject()->property("presses").toInt(), 0);
700     QCOMPARE(canvas->rootObject()->property("clicks").toInt(), 1);
701     QCOMPARE(canvas->rootObject()->property("pressAndHolds").toInt(), 1);
702
703     QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
704     QTest::qWait(100);
705
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);
710
711     canvas->rootObject()->setProperty("noPropagation", QVariant(true));
712
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));
716
717     QTest::qWait(doubleClickInterval); // to avoid generating a double click.
718     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
719     QTest::qWait(1000);
720     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(100,100));
721     QTest::qWait(100);
722
723     QTest::mouseDClick(canvas, Qt::LeftButton, 0, QPoint(100,100));
724     QTest::qWait(100);
725
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);
730
731     delete canvas;
732 }
733
734 void tst_QQuickMouseArea::hoverPosition()
735 {
736     QQuickView *canvas = createView();
737     canvas->setSource(testFileUrl("hoverPosition.qml"));
738
739     QQuickItem *root = canvas->rootObject();
740     QVERIFY(root != 0);
741
742     QCOMPARE(root->property("mouseX").toReal(), qreal(0));
743     QCOMPARE(root->property("mouseY").toReal(), qreal(0));
744
745     QTest::mouseMove(canvas,QPoint(10,32));
746
747
748     QCOMPARE(root->property("mouseX").toReal(), qreal(10));
749     QCOMPARE(root->property("mouseY").toReal(), qreal(32));
750
751     delete canvas;
752 }
753
754 void tst_QQuickMouseArea::hoverPropagation()
755 {
756     //QTBUG-18175, to behave like GV did.
757     QQuickView *canvas = createView();
758     canvas->setSource(testFileUrl("hoverPropagation.qml"));
759
760     QQuickItem *root = canvas->rootObject();
761     QVERIFY(root != 0);
762
763     QCOMPARE(root->property("point1").toBool(), false);
764     QCOMPARE(root->property("point2").toBool(), false);
765
766     QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, 0);
767     QGuiApplication::sendEvent(canvas, &moveEvent);
768
769     QCOMPARE(root->property("point1").toBool(), true);
770     QCOMPARE(root->property("point2").toBool(), false);
771
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);
776
777     delete canvas;
778 }
779
780 void tst_QQuickMouseArea::hoverVisible()
781 {
782     QQuickView *canvas = createView();
783     canvas->setSource(testFileUrl("hoverVisible.qml"));
784
785     QQuickItem *root = canvas->rootObject();
786     QVERIFY(root != 0);
787
788     QQuickMouseArea *mouseTracker = canvas->rootObject()->findChild<QQuickMouseArea*>("mousetracker");
789     QVERIFY(mouseTracker != 0);
790
791     QSignalSpy enteredSpy(mouseTracker, SIGNAL(entered()));
792
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));
796
797     QCOMPARE(mouseTracker->hovered(), false);
798     QCOMPARE(enteredSpy.count(), 0);
799
800     mouseTracker->setVisible(true);
801
802     QCOMPARE(mouseTracker->hovered(), true);
803     QCOMPARE(enteredSpy.count(), 1);
804
805     QEXPECT_FAIL("", "QTBUG-24282", Continue);
806     QCOMPARE(QPointF(mouseTracker->mouseX(), mouseTracker->mouseY()), QPointF(11,33));
807
808     delete canvas;
809 }
810
811 void tst_QQuickMouseArea::disableAfterPress()
812 {
813     QQuickView *canvas = createView();
814     canvas->setSource(testFileUrl("dragging.qml"));
815     canvas->show();
816     canvas->requestActivateWindow();
817     QTest::qWait(20);
818     QVERIFY(canvas->rootObject() != 0);
819
820     QQuickMouseArea *mouseArea = canvas->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
821     QQuickDrag *drag = mouseArea->drag();
822     QVERIFY(mouseArea != 0);
823     QVERIFY(drag != 0);
824
825     QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
826     QSignalSpy mousePressSpy(mouseArea, SIGNAL(pressed(QQuickMouseEvent*)));
827     QSignalSpy mouseReleaseSpy(mouseArea, SIGNAL(released(QQuickMouseEvent*)));
828
829     // target
830     QQuickItem *blackRect = canvas->rootObject()->findChild<QQuickItem*>("blackrect");
831     QVERIFY(blackRect != 0);
832     QVERIFY(blackRect == drag->target());
833
834     QVERIFY(!drag->active());
835
836     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
837
838     QTRY_COMPARE(mousePressSpy.count(), 1);
839
840     QVERIFY(!drag->active());
841     QCOMPARE(blackRect->x(), 50.0);
842     QCOMPARE(blackRect->y(), 50.0);
843
844     // First move event triggers drag, second is acted upon.
845     // This is due to possibility of higher stacked area taking precedence.
846
847     QTest::mouseMove(canvas, QPoint(111,111));
848     QTest::qWait(50);
849     QTest::mouseMove(canvas, QPoint(122,122));
850
851     QTRY_COMPARE(mousePositionSpy.count(), 2);
852
853     QVERIFY(drag->active());
854     QCOMPARE(blackRect->x(), 72.0);
855     QCOMPARE(blackRect->y(), 72.0);
856
857     mouseArea->setEnabled(false);
858
859     // move should still be acted upon
860     QTest::mouseMove(canvas, QPoint(133,133));
861     QTest::qWait(50);
862     QTest::mouseMove(canvas, QPoint(144,144));
863
864     QTRY_COMPARE(mousePositionSpy.count(), 4);
865
866     QVERIFY(drag->active());
867     QCOMPARE(blackRect->x(), 94.0);
868     QCOMPARE(blackRect->y(), 94.0);
869
870     QVERIFY(mouseArea->pressed());
871     QVERIFY(mouseArea->hovered());
872
873     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(144,144));
874
875     QTRY_COMPARE(mouseReleaseSpy.count(), 1);
876
877     QVERIFY(!drag->active());
878     QCOMPARE(blackRect->x(), 94.0);
879     QCOMPARE(blackRect->y(), 94.0);
880
881     QVERIFY(!mouseArea->pressed());
882     QVERIFY(!mouseArea->hovered()); // since hover is not enabled
883
884     // Next press will be ignored
885     blackRect->setX(50);
886     blackRect->setY(50);
887
888     mousePressSpy.clear();
889     mousePositionSpy.clear();
890     mouseReleaseSpy.clear();
891
892     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(100,100));
893     QTest::qWait(50);
894     QCOMPARE(mousePressSpy.count(), 0);
895
896     QTest::mouseMove(canvas, QPoint(111,111));
897     QTest::qWait(50);
898     QTest::mouseMove(canvas, QPoint(122,122));
899     QTest::qWait(50);
900
901     QCOMPARE(mousePositionSpy.count(), 0);
902
903     QVERIFY(!drag->active());
904     QCOMPARE(blackRect->x(), 50.0);
905     QCOMPARE(blackRect->y(), 50.0);
906
907     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(122,122));
908     QTest::qWait(50);
909
910     QCOMPARE(mouseReleaseSpy.count(), 0);
911
912     delete canvas;
913 }
914
915 void tst_QQuickMouseArea::onWheel()
916 {
917     QQuickView *canvas = createView();
918     canvas->setSource(testFileUrl("wheel.qml"));
919
920     QQuickItem *root = canvas->rootObject();
921     QVERIFY(root != 0);
922
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);
926
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);
931
932     delete canvas;
933 }
934
935 QTEST_MAIN(tst_QQuickMouseArea)
936
937 #include "tst_qquickmousearea.moc"