Fix resolution of cursor when items are overlapping.
[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 class tst_QQuickMouseArea: public QQmlDataTest
54 {
55     Q_OBJECT
56 private slots:
57     void dragProperties();
58     void resetDrag();
59     void dragging_data() { acceptedButton_data(); }
60     void dragging();
61     void invalidDrag_data() { rejectedButton_data(); }
62     void invalidDrag();
63     void setDragOnPressed();
64     void updateMouseAreaPosOnClick();
65     void updateMouseAreaPosOnResize();
66     void noOnClickedWithPressAndHold();
67     void onMousePressRejected();
68     void pressedCanceledOnWindowDeactivate();
69     void doubleClick_data() { acceptedButton_data(); }
70     void doubleClick();
71     void clickTwice_data() { acceptedButton_data(); }
72     void clickTwice();
73     void invalidClick_data() { rejectedButton_data(); }
74     void invalidClick();
75     void pressedOrdering();
76     void preventStealing();
77     void clickThrough();
78     void hoverPosition();
79     void hoverPropagation();
80     void hoverVisible();
81     void disableAfterPress();
82     void onWheel();
83     void transformedMouseArea_data();
84     void transformedMouseArea();
85     void pressedMultipleButtons_data();
86     void pressedMultipleButtons();
87     void changeAxis();
88 #ifndef QT_NO_CURSOR
89     void cursorShape();
90 #endif
91
92 private:
93     void acceptedButton_data();
94     void rejectedButton_data();
95
96     QQuickView *createView();
97 };
98
99 Q_DECLARE_METATYPE(Qt::MouseButton)
100 Q_DECLARE_METATYPE(Qt::MouseButtons)
101
102 void tst_QQuickMouseArea::acceptedButton_data()
103 {
104     QTest::addColumn<Qt::MouseButtons>("acceptedButtons");
105     QTest::addColumn<Qt::MouseButton>("button");
106
107     QTest::newRow("left") << Qt::MouseButtons(Qt::LeftButton) << Qt::LeftButton;
108     QTest::newRow("right") << Qt::MouseButtons(Qt::RightButton) << Qt::RightButton;
109     QTest::newRow("middle") << Qt::MouseButtons(Qt::MiddleButton) << Qt::MiddleButton;
110
111     QTest::newRow("left (left|right)") << Qt::MouseButtons(Qt::LeftButton | Qt::RightButton) << Qt::LeftButton;
112     QTest::newRow("right (right|middle)") << Qt::MouseButtons(Qt::RightButton | Qt::MiddleButton) << Qt::RightButton;
113     QTest::newRow("middle (left|middle)") << Qt::MouseButtons(Qt::LeftButton | Qt::MiddleButton) << Qt::MiddleButton;
114 }
115
116 void tst_QQuickMouseArea::rejectedButton_data()
117 {
118     QTest::addColumn<Qt::MouseButtons>("acceptedButtons");
119     QTest::addColumn<Qt::MouseButton>("button");
120
121     QTest::newRow("middle (left|right)") << Qt::MouseButtons(Qt::LeftButton | Qt::RightButton) << Qt::MiddleButton;
122     QTest::newRow("left (right|middle)") << Qt::MouseButtons(Qt::RightButton | Qt::MiddleButton) << Qt::LeftButton;
123     QTest::newRow("right (left|middle)") << Qt::MouseButtons(Qt::LeftButton | Qt::MiddleButton) << Qt::RightButton;
124 }
125
126 void tst_QQuickMouseArea::dragProperties()
127 {
128     QQuickView *window = createView();
129
130     window->setSource(testFileUrl("dragproperties.qml"));
131     window->show();
132     window->requestActivateWindow();
133     QVERIFY(window->rootObject() != 0);
134
135     QQuickMouseArea *mouseRegion = window->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
136     QQuickDrag *drag = mouseRegion->drag();
137     QVERIFY(mouseRegion != 0);
138     QVERIFY(drag != 0);
139
140     // target
141     QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
142     QVERIFY(blackRect != 0);
143     QVERIFY(blackRect == drag->target());
144     QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
145     QVERIFY(rootItem != 0);
146     QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
147     drag->setTarget(rootItem);
148     QCOMPARE(targetSpy.count(),1);
149     drag->setTarget(rootItem);
150     QCOMPARE(targetSpy.count(),1);
151
152     // axis
153     QCOMPARE(drag->axis(), QQuickDrag::XandYAxis);
154     QSignalSpy axisSpy(drag, SIGNAL(axisChanged()));
155     drag->setAxis(QQuickDrag::XAxis);
156     QCOMPARE(drag->axis(), QQuickDrag::XAxis);
157     QCOMPARE(axisSpy.count(),1);
158     drag->setAxis(QQuickDrag::XAxis);
159     QCOMPARE(axisSpy.count(),1);
160
161     // minimum and maximum properties
162     QSignalSpy xminSpy(drag, SIGNAL(minimumXChanged()));
163     QSignalSpy xmaxSpy(drag, SIGNAL(maximumXChanged()));
164     QSignalSpy yminSpy(drag, SIGNAL(minimumYChanged()));
165     QSignalSpy ymaxSpy(drag, SIGNAL(maximumYChanged()));
166
167     QCOMPARE(drag->xmin(), 0.0);
168     QCOMPARE(drag->xmax(), rootItem->width()-blackRect->width());
169     QCOMPARE(drag->ymin(), 0.0);
170     QCOMPARE(drag->ymax(), rootItem->height()-blackRect->height());
171
172     drag->setXmin(10);
173     drag->setXmax(10);
174     drag->setYmin(10);
175     drag->setYmax(10);
176
177     QCOMPARE(drag->xmin(), 10.0);
178     QCOMPARE(drag->xmax(), 10.0);
179     QCOMPARE(drag->ymin(), 10.0);
180     QCOMPARE(drag->ymax(), 10.0);
181
182     QCOMPARE(xminSpy.count(),1);
183     QCOMPARE(xmaxSpy.count(),1);
184     QCOMPARE(yminSpy.count(),1);
185     QCOMPARE(ymaxSpy.count(),1);
186
187     drag->setXmin(10);
188     drag->setXmax(10);
189     drag->setYmin(10);
190     drag->setYmax(10);
191
192     QCOMPARE(xminSpy.count(),1);
193     QCOMPARE(xmaxSpy.count(),1);
194     QCOMPARE(yminSpy.count(),1);
195     QCOMPARE(ymaxSpy.count(),1);
196
197     // filterChildren
198     QSignalSpy filterChildrenSpy(drag, SIGNAL(filterChildrenChanged()));
199
200     drag->setFilterChildren(true);
201
202     QVERIFY(drag->filterChildren());
203     QCOMPARE(filterChildrenSpy.count(), 1);
204
205     drag->setFilterChildren(true);
206     QCOMPARE(filterChildrenSpy.count(), 1);
207
208     delete window;
209 }
210
211 void tst_QQuickMouseArea::resetDrag()
212 {
213     QQuickView *window = createView();
214
215     window->rootContext()->setContextProperty("haveTarget", QVariant(true));
216     window->setSource(testFileUrl("dragreset.qml"));
217     window->show();
218     window->requestActivateWindow();
219     QVERIFY(window->rootObject() != 0);
220
221     QQuickMouseArea *mouseRegion = window->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
222     QQuickDrag *drag = mouseRegion->drag();
223     QVERIFY(mouseRegion != 0);
224     QVERIFY(drag != 0);
225
226     // target
227     QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
228     QVERIFY(blackRect != 0);
229     QVERIFY(blackRect == drag->target());
230     QQuickItem *rootItem = qobject_cast<QQuickItem*>(window->rootObject());
231     QVERIFY(rootItem != 0);
232     QSignalSpy targetSpy(drag, SIGNAL(targetChanged()));
233     QVERIFY(drag->target() != 0);
234     window->rootContext()->setContextProperty("haveTarget", QVariant(false));
235     QCOMPARE(targetSpy.count(),1);
236     QVERIFY(drag->target() == 0);
237
238     delete window;
239 }
240
241 void tst_QQuickMouseArea::dragging()
242 {
243     QFETCH(Qt::MouseButtons, acceptedButtons);
244     QFETCH(Qt::MouseButton, button);
245
246     QQuickView *window = createView();
247
248     window->setSource(testFileUrl("dragging.qml"));
249     window->show();
250     window->requestActivateWindow();
251     QTest::qWait(20);
252     QVERIFY(window->rootObject() != 0);
253
254     QQuickMouseArea *mouseRegion = window->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
255     QQuickDrag *drag = mouseRegion->drag();
256     QVERIFY(mouseRegion != 0);
257     QVERIFY(drag != 0);
258
259     mouseRegion->setAcceptedButtons(acceptedButtons);
260
261     // target
262     QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
263     QVERIFY(blackRect != 0);
264     QVERIFY(blackRect == drag->target());
265
266     QVERIFY(!drag->active());
267
268     QTest::mousePress(window, button, 0, QPoint(100,100));
269
270     QVERIFY(!drag->active());
271     QCOMPARE(blackRect->x(), 50.0);
272     QCOMPARE(blackRect->y(), 50.0);
273
274     // First move event triggers drag, second is acted upon.
275     // This is due to possibility of higher stacked area taking precedence.
276
277     QTest::mouseMove(window, QPoint(111,111));
278     QTest::qWait(50);
279     QTest::mouseMove(window, QPoint(122,122));
280     QTest::qWait(50);
281
282     QVERIFY(drag->active());
283     QCOMPARE(blackRect->x(), 72.0);
284     QCOMPARE(blackRect->y(), 72.0);
285
286     QTest::mouseRelease(window, button, 0, QPoint(122,122));
287     QTest::qWait(50);
288
289     QVERIFY(!drag->active());
290     QCOMPARE(blackRect->x(), 72.0);
291     QCOMPARE(blackRect->y(), 72.0);
292
293     delete window;
294 }
295
296 void tst_QQuickMouseArea::invalidDrag()
297 {
298     QFETCH(Qt::MouseButtons, acceptedButtons);
299     QFETCH(Qt::MouseButton, button);
300
301     QQuickView *window = createView();
302
303     window->setSource(testFileUrl("dragging.qml"));
304     window->show();
305     window->requestActivateWindow();
306     QTest::qWait(20);
307     QVERIFY(window->rootObject() != 0);
308
309     QQuickMouseArea *mouseRegion = window->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
310     QQuickDrag *drag = mouseRegion->drag();
311     QVERIFY(mouseRegion != 0);
312     QVERIFY(drag != 0);
313
314     mouseRegion->setAcceptedButtons(acceptedButtons);
315
316     // target
317     QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
318     QVERIFY(blackRect != 0);
319     QVERIFY(blackRect == drag->target());
320
321     QVERIFY(!drag->active());
322
323     QTest::mousePress(window, button, 0, QPoint(100,100));
324
325     QVERIFY(!drag->active());
326     QCOMPARE(blackRect->x(), 50.0);
327     QCOMPARE(blackRect->y(), 50.0);
328
329     // First move event triggers drag, second is acted upon.
330     // This is due to possibility of higher stacked area taking precedence.
331
332     QTest::mouseMove(window, QPoint(111,111));
333     QTest::qWait(50);
334     QTest::mouseMove(window, QPoint(122,122));
335     QTest::qWait(50);
336
337     QVERIFY(!drag->active());
338     QCOMPARE(blackRect->x(), 50.0);
339     QCOMPARE(blackRect->y(), 50.0);
340
341     QTest::mouseRelease(window, button, 0, QPoint(122,122));
342     QTest::qWait(50);
343
344     QVERIFY(!drag->active());
345     QCOMPARE(blackRect->x(), 50.0);
346     QCOMPARE(blackRect->y(), 50.0);
347
348     delete window;
349 }
350
351 void tst_QQuickMouseArea::setDragOnPressed()
352 {
353     QQuickView *window = createView();
354
355     window->setSource(testFileUrl("setDragOnPressed.qml"));
356     window->show();
357     window->requestActivateWindow();
358     QTest::qWait(20);
359     QVERIFY(window->rootObject() != 0);
360
361     QQuickMouseArea *mouseArea = qobject_cast<QQuickMouseArea *>(window->rootObject());
362     QVERIFY(mouseArea);
363
364     // target
365     QQuickItem *target = mouseArea->findChild<QQuickItem*>("target");
366     QVERIFY(target);
367
368     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
369
370     QQuickDrag *drag = mouseArea->drag();
371     QVERIFY(drag);
372     QVERIFY(!drag->active());
373
374     QCOMPARE(target->x(), 50.0);
375     QCOMPARE(target->y(), 50.0);
376
377     // First move event triggers drag, second is acted upon.
378     // This is due to possibility of higher stacked area taking precedence.
379
380     QTest::mouseMove(window, QPoint(111,102));
381     QTest::qWait(50);
382     QTest::mouseMove(window, QPoint(122,122));
383     QTest::qWait(50);
384
385     QVERIFY(drag->active());
386     QCOMPARE(target->x(), 72.0);
387     QCOMPARE(target->y(), 50.0);
388
389     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(122,122));
390     QTest::qWait(50);
391
392     QVERIFY(!drag->active());
393     QCOMPARE(target->x(), 72.0);
394     QCOMPARE(target->y(), 50.0);
395
396     delete window;
397 }
398
399 QQuickView *tst_QQuickMouseArea::createView()
400 {
401     QQuickView *window = new QQuickView(0);
402     window->setBaseSize(QSize(240,320));
403
404     return window;
405 }
406
407 void tst_QQuickMouseArea::updateMouseAreaPosOnClick()
408 {
409     QQuickView *window = createView();
410     window->setSource(testFileUrl("updateMousePosOnClick.qml"));
411     window->show();
412     window->requestActivateWindow();
413     QVERIFY(window->rootObject() != 0);
414
415     QQuickMouseArea *mouseRegion = window->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
416     QVERIFY(mouseRegion != 0);
417
418     QQuickRectangle *rect = window->rootObject()->findChild<QQuickRectangle*>("ball");
419     QVERIFY(rect != 0);
420
421     QCOMPARE(mouseRegion->mouseX(), rect->x());
422     QCOMPARE(mouseRegion->mouseY(), rect->y());
423
424     QMouseEvent event(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
425     QGuiApplication::sendEvent(window, &event);
426
427     QCOMPARE(mouseRegion->mouseX(), 100.0);
428     QCOMPARE(mouseRegion->mouseY(), 100.0);
429
430     QCOMPARE(mouseRegion->mouseX(), rect->x());
431     QCOMPARE(mouseRegion->mouseY(), rect->y());
432
433     delete window;
434 }
435
436 void tst_QQuickMouseArea::updateMouseAreaPosOnResize()
437 {
438     QQuickView *window = createView();
439     window->setSource(testFileUrl("updateMousePosOnResize.qml"));
440     window->show();
441     window->requestActivateWindow();
442     QVERIFY(window->rootObject() != 0);
443
444     QQuickMouseArea *mouseRegion = window->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
445     QVERIFY(mouseRegion != 0);
446
447     QQuickRectangle *rect = window->rootObject()->findChild<QQuickRectangle*>("brother");
448     QVERIFY(rect != 0);
449
450     QCOMPARE(mouseRegion->mouseX(), 0.0);
451     QCOMPARE(mouseRegion->mouseY(), 0.0);
452
453     QMouseEvent event(QEvent::MouseButtonPress, rect->pos().toPoint(), Qt::LeftButton, Qt::LeftButton, 0);
454     QGuiApplication::sendEvent(window, &event);
455
456     QVERIFY(!mouseRegion->property("emitPositionChanged").toBool());
457     QVERIFY(mouseRegion->property("mouseMatchesPos").toBool());
458
459     QCOMPARE(mouseRegion->property("x1").toReal(), 0.0);
460     QCOMPARE(mouseRegion->property("y1").toReal(), 0.0);
461
462     QCOMPARE(mouseRegion->property("x2").toReal(), rect->x());
463     QCOMPARE(mouseRegion->property("y2").toReal(), rect->y());
464
465     QCOMPARE(mouseRegion->mouseX(), rect->x());
466     QCOMPARE(mouseRegion->mouseY(), rect->y());
467
468     delete window;
469 }
470
471 void tst_QQuickMouseArea::noOnClickedWithPressAndHold()
472 {
473     {
474         // We handle onPressAndHold, therefore no onClicked
475         QQuickView *window = createView();
476         window->setSource(testFileUrl("clickandhold.qml"));
477         window->show();
478         window->requestActivateWindow();
479         QVERIFY(window->rootObject() != 0);
480
481         QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
482         QGuiApplication::sendEvent(window, &pressEvent);
483
484         QVERIFY(!window->rootObject()->property("clicked").toBool());
485         QVERIFY(!window->rootObject()->property("held").toBool());
486
487         QTest::qWait(1000);
488
489         QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
490         QGuiApplication::sendEvent(window, &releaseEvent);
491
492         QVERIFY(!window->rootObject()->property("clicked").toBool());
493         QVERIFY(window->rootObject()->property("held").toBool());
494
495         delete window;
496     }
497
498     {
499         // We do not handle onPressAndHold, therefore we get onClicked
500         QQuickView *window = createView();
501         window->setSource(testFileUrl("noclickandhold.qml"));
502         window->show();
503         window->requestActivateWindow();
504         QVERIFY(window->rootObject() != 0);
505
506         QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
507         QGuiApplication::sendEvent(window, &pressEvent);
508
509         QVERIFY(!window->rootObject()->property("clicked").toBool());
510
511         QTest::qWait(1000);
512
513         QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
514         QGuiApplication::sendEvent(window, &releaseEvent);
515
516         QVERIFY(window->rootObject()->property("clicked").toBool());
517
518         delete window;
519     }
520 }
521
522 void tst_QQuickMouseArea::onMousePressRejected()
523 {
524     QQuickView *window = createView();
525     window->setSource(testFileUrl("rejectEvent.qml"));
526     window->show();
527     window->requestActivateWindow();
528     QVERIFY(window->rootObject() != 0);
529     QVERIFY(window->rootObject()->property("enabled").toBool());
530
531     QVERIFY(!window->rootObject()->property("mr1_pressed").toBool());
532     QVERIFY(!window->rootObject()->property("mr1_released").toBool());
533     QVERIFY(!window->rootObject()->property("mr1_canceled").toBool());
534     QVERIFY(!window->rootObject()->property("mr2_pressed").toBool());
535     QVERIFY(!window->rootObject()->property("mr2_released").toBool());
536     QVERIFY(!window->rootObject()->property("mr2_canceled").toBool());
537
538     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
539     QGuiApplication::sendEvent(window, &pressEvent);
540
541     QVERIFY(window->rootObject()->property("mr1_pressed").toBool());
542     QVERIFY(!window->rootObject()->property("mr1_released").toBool());
543     QVERIFY(!window->rootObject()->property("mr1_canceled").toBool());
544     QVERIFY(window->rootObject()->property("mr2_pressed").toBool());
545     QVERIFY(!window->rootObject()->property("mr2_released").toBool());
546     QVERIFY(window->rootObject()->property("mr2_canceled").toBool());
547
548     QTest::qWait(200);
549
550     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
551     QGuiApplication::sendEvent(window, &releaseEvent);
552
553     QVERIFY(window->rootObject()->property("mr1_released").toBool());
554     QVERIFY(!window->rootObject()->property("mr1_canceled").toBool());
555     QVERIFY(!window->rootObject()->property("mr2_released").toBool());
556
557     delete window;
558 }
559 void tst_QQuickMouseArea::pressedCanceledOnWindowDeactivate()
560 {
561     QQuickView *window = createView();
562     window->setSource(testFileUrl("pressedCanceled.qml"));
563     window->show();
564     window->requestActivateWindow();
565     QVERIFY(window->rootObject() != 0);
566     QVERIFY(!window->rootObject()->property("pressed").toBool());
567     QVERIFY(!window->rootObject()->property("canceled").toBool());
568     QVERIFY(!window->rootObject()->property("released").toBool());
569
570     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
571     QGuiApplication::sendEvent(window, &pressEvent);
572
573     QVERIFY(window->rootObject()->property("pressed").toBool());
574     QVERIFY(!window->rootObject()->property("canceled").toBool());
575     QVERIFY(!window->rootObject()->property("released").toBool());
576
577     QTest::qWait(200);
578
579     QEvent windowDeactivateEvent(QEvent::WindowDeactivate);
580     QGuiApplication::sendEvent(window, &windowDeactivateEvent);
581     QVERIFY(!window->rootObject()->property("pressed").toBool());
582     QVERIFY(window->rootObject()->property("canceled").toBool());
583     QVERIFY(!window->rootObject()->property("released").toBool());
584
585     QTest::qWait(200);
586
587     //press again
588     QGuiApplication::sendEvent(window, &pressEvent);
589     QVERIFY(window->rootObject()->property("pressed").toBool());
590     QVERIFY(!window->rootObject()->property("canceled").toBool());
591     QVERIFY(!window->rootObject()->property("released").toBool());
592
593     QTest::qWait(200);
594
595     //release
596     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
597     QGuiApplication::sendEvent(window, &releaseEvent);
598     QVERIFY(!window->rootObject()->property("pressed").toBool());
599     QVERIFY(!window->rootObject()->property("canceled").toBool());
600     QVERIFY(window->rootObject()->property("released").toBool());
601
602     delete window;
603 }
604
605 void tst_QQuickMouseArea::doubleClick()
606 {
607     QFETCH(Qt::MouseButtons, acceptedButtons);
608     QFETCH(Qt::MouseButton, button);
609
610     QQuickView *window = createView();
611     window->setSource(testFileUrl("doubleclick.qml"));
612     window->show();
613     window->requestActivateWindow();
614     QVERIFY(window->rootObject() != 0);
615
616     QQuickMouseArea *mouseArea = window->rootObject()->findChild<QQuickMouseArea *>("mousearea");
617     QVERIFY(mouseArea);
618     mouseArea->setAcceptedButtons(acceptedButtons);
619
620     // The sequence for a double click is:
621     // press, release, (click), press, double click, release
622     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, 0);
623     QGuiApplication::sendEvent(window, &pressEvent);
624
625     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, 0);
626     QGuiApplication::sendEvent(window, &releaseEvent);
627
628     QCOMPARE(window->rootObject()->property("released").toInt(), 1);
629
630     QGuiApplication::sendEvent(window, &pressEvent);
631     pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, 0);
632     QGuiApplication::sendEvent(window, &pressEvent);
633     QGuiApplication::sendEvent(window, &releaseEvent);
634
635     QCOMPARE(window->rootObject()->property("clicked").toInt(), 1);
636     QCOMPARE(window->rootObject()->property("doubleClicked").toInt(), 1);
637     QCOMPARE(window->rootObject()->property("released").toInt(), 2);
638
639     delete window;
640 }
641
642 // QTBUG-14832
643 void tst_QQuickMouseArea::clickTwice()
644 {
645     QFETCH(Qt::MouseButtons, acceptedButtons);
646     QFETCH(Qt::MouseButton, button);
647
648     QQuickView *window = createView();
649     window->setSource(testFileUrl("clicktwice.qml"));
650     window->show();
651     window->requestActivateWindow();
652     QVERIFY(window->rootObject() != 0);
653
654     QQuickMouseArea *mouseArea = window->rootObject()->findChild<QQuickMouseArea *>("mousearea");
655     QVERIFY(mouseArea);
656     mouseArea->setAcceptedButtons(acceptedButtons);
657
658     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, 0);
659     QGuiApplication::sendEvent(window, &pressEvent);
660
661     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, 0);
662     QGuiApplication::sendEvent(window, &releaseEvent);
663
664     QCOMPARE(window->rootObject()->property("pressed").toInt(), 1);
665     QCOMPARE(window->rootObject()->property("released").toInt(), 1);
666     QCOMPARE(window->rootObject()->property("clicked").toInt(), 1);
667
668     QGuiApplication::sendEvent(window, &pressEvent);
669     pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, 0);
670     QGuiApplication::sendEvent(window, &pressEvent);
671     QGuiApplication::sendEvent(window, &releaseEvent);
672
673     QCOMPARE(window->rootObject()->property("pressed").toInt(), 2);
674     QCOMPARE(window->rootObject()->property("released").toInt(), 2);
675     QCOMPARE(window->rootObject()->property("clicked").toInt(), 2);
676
677     delete window;
678 }
679
680 void tst_QQuickMouseArea::invalidClick()
681 {
682     QFETCH(Qt::MouseButtons, acceptedButtons);
683     QFETCH(Qt::MouseButton, button);
684
685     QQuickView *window = createView();
686     window->setSource(testFileUrl("doubleclick.qml"));
687     window->show();
688     window->requestActivateWindow();
689     QVERIFY(window->rootObject() != 0);
690
691     QQuickMouseArea *mouseArea = window->rootObject()->findChild<QQuickMouseArea *>("mousearea");
692     QVERIFY(mouseArea);
693     mouseArea->setAcceptedButtons(acceptedButtons);
694
695     // The sequence for a double click is:
696     // press, release, (click), press, double click, release
697     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), button, button, 0);
698     QGuiApplication::sendEvent(window, &pressEvent);
699
700     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), button, button, 0);
701     QGuiApplication::sendEvent(window, &releaseEvent);
702
703     QCOMPARE(window->rootObject()->property("released").toInt(), 0);
704
705     QGuiApplication::sendEvent(window, &pressEvent);
706     pressEvent = QMouseEvent(QEvent::MouseButtonDblClick, QPoint(100, 100), button, button, 0);
707     QGuiApplication::sendEvent(window, &pressEvent);
708     QGuiApplication::sendEvent(window, &releaseEvent);
709
710     QCOMPARE(window->rootObject()->property("clicked").toInt(), 0);
711     QCOMPARE(window->rootObject()->property("doubleClicked").toInt(), 0);
712     QCOMPARE(window->rootObject()->property("released").toInt(), 0);
713
714     delete window;
715 }
716
717 void tst_QQuickMouseArea::pressedOrdering()
718 {
719     QQuickView *window = createView();
720     window->setSource(testFileUrl("pressedOrdering.qml"));
721     window->show();
722     window->requestActivateWindow();
723     QVERIFY(window->rootObject() != 0);
724
725     QCOMPARE(window->rootObject()->property("value").toString(), QLatin1String("base"));
726
727     QMouseEvent pressEvent(QEvent::MouseButtonPress, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
728     QGuiApplication::sendEvent(window, &pressEvent);
729
730     QCOMPARE(window->rootObject()->property("value").toString(), QLatin1String("pressed"));
731
732     QMouseEvent releaseEvent(QEvent::MouseButtonRelease, QPoint(100, 100), Qt::LeftButton, Qt::LeftButton, 0);
733     QGuiApplication::sendEvent(window, &releaseEvent);
734
735     QCOMPARE(window->rootObject()->property("value").toString(), QLatin1String("toggled"));
736
737     QGuiApplication::sendEvent(window, &pressEvent);
738
739     QCOMPARE(window->rootObject()->property("value").toString(), QLatin1String("pressed"));
740
741     delete window;
742 }
743
744 void tst_QQuickMouseArea::preventStealing()
745 {
746     QQuickView *window = createView();
747
748     window->setSource(testFileUrl("preventstealing.qml"));
749     window->show();
750     window->requestActivateWindow();
751     QVERIFY(window->rootObject() != 0);
752
753     QQuickFlickable *flickable = qobject_cast<QQuickFlickable*>(window->rootObject());
754     QVERIFY(flickable != 0);
755
756     QQuickMouseArea *mouseArea = window->rootObject()->findChild<QQuickMouseArea*>("mousearea");
757     QVERIFY(mouseArea != 0);
758
759     QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
760
761     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(80, 80));
762
763     // Without preventStealing, mouse movement over MouseArea would
764     // cause the Flickable to steal mouse and trigger content movement.
765
766     QTest::mouseMove(window,QPoint(69,69));
767     QTest::mouseMove(window,QPoint(58,58));
768     QTest::mouseMove(window,QPoint(47,47));
769
770     // We should have received all three move events
771     QCOMPARE(mousePositionSpy.count(), 3);
772     QVERIFY(mouseArea->pressed());
773
774     // Flickable content should not have moved.
775     QCOMPARE(flickable->contentX(), 0.);
776     QCOMPARE(flickable->contentY(), 0.);
777
778     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(47, 47));
779
780     // Now allow stealing and confirm Flickable does its thing.
781     window->rootObject()->setProperty("stealing", false);
782
783     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(80, 80));
784
785     // Without preventStealing, mouse movement over MouseArea would
786     // cause the Flickable to steal mouse and trigger content movement.
787
788     QTest::mouseMove(window,QPoint(69,69));
789     QTest::mouseMove(window,QPoint(58,58));
790     QTest::mouseMove(window,QPoint(47,47));
791
792     // We should only have received the first move event
793     QCOMPARE(mousePositionSpy.count(), 4);
794     // Our press should be taken away
795     QVERIFY(!mouseArea->pressed());
796
797     // Flickable content should have moved.
798
799     QCOMPARE(flickable->contentX(), 11.);
800     QCOMPARE(flickable->contentY(), 11.);
801
802     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(50, 50));
803
804     delete window;
805 }
806
807 void tst_QQuickMouseArea::clickThrough()
808 {
809     QSKIP("QTBUG-23976 Unstable");
810     //With no handlers defined click, doubleClick and PressAndHold should propagate to those with handlers
811     QQuickView *window = createView();
812     window->setSource(testFileUrl("clickThrough.qml"));
813     window->show();
814     window->requestActivateWindow();
815     QVERIFY(window->rootObject() != 0);
816
817     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
818     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(100,100));
819
820     QTRY_COMPARE(window->rootObject()->property("presses").toInt(), 0);
821     QTRY_COMPARE(window->rootObject()->property("clicks").toInt(), 1);
822
823     // to avoid generating a double click.
824     int doubleClickInterval = qApp->styleHints()->mouseDoubleClickInterval() + 10;
825     QTest::qWait(doubleClickInterval);
826
827     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
828     QTest::qWait(1000);
829     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(100,100));
830
831     QTRY_COMPARE(window->rootObject()->property("presses").toInt(), 0);
832     QTRY_COMPARE(window->rootObject()->property("clicks").toInt(), 1);
833     QTRY_COMPARE(window->rootObject()->property("pressAndHolds").toInt(), 1);
834
835     QTest::mouseDClick(window, Qt::LeftButton, 0, QPoint(100,100));
836     QTest::qWait(100);
837
838     QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
839     QTRY_COMPARE(window->rootObject()->property("clicks").toInt(), 2);
840     QTRY_COMPARE(window->rootObject()->property("doubleClicks").toInt(), 1);
841     QCOMPARE(window->rootObject()->property("pressAndHolds").toInt(), 1);
842
843     delete window;
844
845     //With handlers defined click, doubleClick and PressAndHold should propagate only when explicitly ignored
846     window = createView();
847     window->setSource(testFileUrl("clickThrough2.qml"));
848     window->show();
849     window->requestActivateWindow();
850     QVERIFY(window->rootObject() != 0);
851
852     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
853     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(100,100));
854
855     QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
856     QCOMPARE(window->rootObject()->property("clicks").toInt(), 0);
857
858     QTest::qWait(doubleClickInterval); // to avoid generating a double click.
859
860     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
861     QTest::qWait(1000);
862     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(100,100));
863     QTest::qWait(100);
864
865     QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
866     QCOMPARE(window->rootObject()->property("clicks").toInt(), 0);
867     QCOMPARE(window->rootObject()->property("pressAndHolds").toInt(), 0);
868
869     QTest::mouseDClick(window, Qt::LeftButton, 0, QPoint(100,100));
870     QTest::qWait(100);
871
872     QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
873     QCOMPARE(window->rootObject()->property("clicks").toInt(), 0);
874     QCOMPARE(window->rootObject()->property("doubleClicks").toInt(), 0);
875     QCOMPARE(window->rootObject()->property("pressAndHolds").toInt(), 0);
876
877     window->rootObject()->setProperty("letThrough", QVariant(true));
878
879     QTest::qWait(doubleClickInterval); // to avoid generating a double click.
880     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
881     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(100,100));
882
883     QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
884     QTRY_COMPARE(window->rootObject()->property("clicks").toInt(), 1);
885
886     QTest::qWait(doubleClickInterval); // to avoid generating a double click.
887     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
888     QTest::qWait(1000);
889     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(100,100));
890     QTest::qWait(100);
891
892     QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
893     QCOMPARE(window->rootObject()->property("clicks").toInt(), 1);
894     QCOMPARE(window->rootObject()->property("pressAndHolds").toInt(), 1);
895
896     QTest::mouseDClick(window, Qt::LeftButton, 0, QPoint(100,100));
897     QTest::qWait(100);
898
899     QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
900     QTRY_COMPARE(window->rootObject()->property("clicks").toInt(), 2);
901     QCOMPARE(window->rootObject()->property("doubleClicks").toInt(), 1);
902     QCOMPARE(window->rootObject()->property("pressAndHolds").toInt(), 1);
903
904     window->rootObject()->setProperty("noPropagation", QVariant(true));
905
906     QTest::qWait(doubleClickInterval); // to avoid generating a double click.
907     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
908     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(100,100));
909
910     QTest::qWait(doubleClickInterval); // to avoid generating a double click.
911     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
912     QTest::qWait(1000);
913     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(100,100));
914     QTest::qWait(100);
915
916     QTest::mouseDClick(window, Qt::LeftButton, 0, QPoint(100,100));
917     QTest::qWait(100);
918
919     QCOMPARE(window->rootObject()->property("presses").toInt(), 0);
920     QTRY_COMPARE(window->rootObject()->property("clicks").toInt(), 2);
921     QCOMPARE(window->rootObject()->property("doubleClicks").toInt(), 1);
922     QCOMPARE(window->rootObject()->property("pressAndHolds").toInt(), 1);
923
924     delete window;
925 }
926
927 void tst_QQuickMouseArea::hoverPosition()
928 {
929     QQuickView *window = createView();
930     window->setSource(testFileUrl("hoverPosition.qml"));
931
932     QQuickItem *root = window->rootObject();
933     QVERIFY(root != 0);
934
935     QCOMPARE(root->property("mouseX").toReal(), qreal(0));
936     QCOMPARE(root->property("mouseY").toReal(), qreal(0));
937
938     QTest::mouseMove(window,QPoint(10,32));
939
940
941     QCOMPARE(root->property("mouseX").toReal(), qreal(10));
942     QCOMPARE(root->property("mouseY").toReal(), qreal(32));
943
944     delete window;
945 }
946
947 void tst_QQuickMouseArea::hoverPropagation()
948 {
949     //QTBUG-18175, to behave like GV did.
950     QQuickView *window = createView();
951     window->setSource(testFileUrl("hoverPropagation.qml"));
952
953     QQuickItem *root = window->rootObject();
954     QVERIFY(root != 0);
955
956     QCOMPARE(root->property("point1").toBool(), false);
957     QCOMPARE(root->property("point2").toBool(), false);
958
959     QMouseEvent moveEvent(QEvent::MouseMove, QPoint(32, 32), Qt::NoButton, Qt::NoButton, 0);
960     QGuiApplication::sendEvent(window, &moveEvent);
961
962     QCOMPARE(root->property("point1").toBool(), true);
963     QCOMPARE(root->property("point2").toBool(), false);
964
965     QMouseEvent moveEvent2(QEvent::MouseMove, QPoint(232, 32), Qt::NoButton, Qt::NoButton, 0);
966     QGuiApplication::sendEvent(window, &moveEvent2);
967     QCOMPARE(root->property("point1").toBool(), false);
968     QCOMPARE(root->property("point2").toBool(), true);
969
970     delete window;
971 }
972
973 void tst_QQuickMouseArea::hoverVisible()
974 {
975     QQuickView *window = createView();
976     window->setSource(testFileUrl("hoverVisible.qml"));
977
978     QQuickItem *root = window->rootObject();
979     QVERIFY(root != 0);
980
981     QQuickMouseArea *mouseTracker = window->rootObject()->findChild<QQuickMouseArea*>("mousetracker");
982     QVERIFY(mouseTracker != 0);
983
984     QSignalSpy enteredSpy(mouseTracker, SIGNAL(entered()));
985
986     // Note: We need to use a position that is different from the position in the last event
987     // generated in the previous test case. Otherwise it is not interpreted as a move.
988     QTest::mouseMove(window,QPoint(11,33));
989
990     QCOMPARE(mouseTracker->hovered(), false);
991     QCOMPARE(enteredSpy.count(), 0);
992
993     mouseTracker->setVisible(true);
994
995     QCOMPARE(mouseTracker->hovered(), true);
996     QCOMPARE(enteredSpy.count(), 1);
997
998     QCOMPARE(QPointF(mouseTracker->mouseX(), mouseTracker->mouseY()), QPointF(11,33));
999
1000     delete window;
1001 }
1002
1003 void tst_QQuickMouseArea::disableAfterPress()
1004 {
1005     QQuickView *window = createView();
1006     window->setSource(testFileUrl("dragging.qml"));
1007     window->show();
1008     window->requestActivateWindow();
1009     QTest::qWait(20);
1010     QVERIFY(window->rootObject() != 0);
1011
1012     QQuickMouseArea *mouseArea = window->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
1013     QQuickDrag *drag = mouseArea->drag();
1014     QVERIFY(mouseArea != 0);
1015     QVERIFY(drag != 0);
1016
1017     QSignalSpy mousePositionSpy(mouseArea, SIGNAL(positionChanged(QQuickMouseEvent*)));
1018     QSignalSpy mousePressSpy(mouseArea, SIGNAL(pressed(QQuickMouseEvent*)));
1019     QSignalSpy mouseReleaseSpy(mouseArea, SIGNAL(released(QQuickMouseEvent*)));
1020
1021     // target
1022     QQuickItem *blackRect = window->rootObject()->findChild<QQuickItem*>("blackrect");
1023     QVERIFY(blackRect != 0);
1024     QVERIFY(blackRect == drag->target());
1025
1026     QVERIFY(!drag->active());
1027
1028     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
1029
1030     QTRY_COMPARE(mousePressSpy.count(), 1);
1031
1032     QVERIFY(!drag->active());
1033     QCOMPARE(blackRect->x(), 50.0);
1034     QCOMPARE(blackRect->y(), 50.0);
1035
1036     // First move event triggers drag, second is acted upon.
1037     // This is due to possibility of higher stacked area taking precedence.
1038
1039     QTest::mouseMove(window, QPoint(111,111));
1040     QTest::qWait(50);
1041     QTest::mouseMove(window, QPoint(122,122));
1042
1043     QTRY_COMPARE(mousePositionSpy.count(), 2);
1044
1045     QVERIFY(drag->active());
1046     QCOMPARE(blackRect->x(), 72.0);
1047     QCOMPARE(blackRect->y(), 72.0);
1048
1049     mouseArea->setEnabled(false);
1050
1051     // move should still be acted upon
1052     QTest::mouseMove(window, QPoint(133,133));
1053     QTest::qWait(50);
1054     QTest::mouseMove(window, QPoint(144,144));
1055
1056     QTRY_COMPARE(mousePositionSpy.count(), 4);
1057
1058     QVERIFY(drag->active());
1059     QCOMPARE(blackRect->x(), 94.0);
1060     QCOMPARE(blackRect->y(), 94.0);
1061
1062     QVERIFY(mouseArea->pressed());
1063     QVERIFY(mouseArea->hovered());
1064
1065     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(144,144));
1066
1067     QTRY_COMPARE(mouseReleaseSpy.count(), 1);
1068
1069     QVERIFY(!drag->active());
1070     QCOMPARE(blackRect->x(), 94.0);
1071     QCOMPARE(blackRect->y(), 94.0);
1072
1073     QVERIFY(!mouseArea->pressed());
1074     QVERIFY(!mouseArea->hovered()); // since hover is not enabled
1075
1076     // Next press will be ignored
1077     blackRect->setX(50);
1078     blackRect->setY(50);
1079
1080     mousePressSpy.clear();
1081     mousePositionSpy.clear();
1082     mouseReleaseSpy.clear();
1083
1084     QTest::mousePress(window, Qt::LeftButton, 0, QPoint(100,100));
1085     QTest::qWait(50);
1086     QCOMPARE(mousePressSpy.count(), 0);
1087
1088     QTest::mouseMove(window, QPoint(111,111));
1089     QTest::qWait(50);
1090     QTest::mouseMove(window, QPoint(122,122));
1091     QTest::qWait(50);
1092
1093     QCOMPARE(mousePositionSpy.count(), 0);
1094
1095     QVERIFY(!drag->active());
1096     QCOMPARE(blackRect->x(), 50.0);
1097     QCOMPARE(blackRect->y(), 50.0);
1098
1099     QTest::mouseRelease(window, Qt::LeftButton, 0, QPoint(122,122));
1100     QTest::qWait(50);
1101
1102     QCOMPARE(mouseReleaseSpy.count(), 0);
1103
1104     delete window;
1105 }
1106
1107 void tst_QQuickMouseArea::onWheel()
1108 {
1109     QQuickView *window = createView();
1110     window->setSource(testFileUrl("wheel.qml"));
1111
1112     QQuickItem *root = window->rootObject();
1113     QVERIFY(root != 0);
1114
1115     QWheelEvent wheelEvent(QPoint(10, 32), QPoint(10, 32), QPoint(60, 20), QPoint(0, 120),
1116                            0, Qt::Vertical,Qt::NoButton, Qt::ControlModifier);
1117     QGuiApplication::sendEvent(window, &wheelEvent);
1118
1119     QCOMPARE(root->property("angleDeltaY").toInt(), 120);
1120     QCOMPARE(root->property("mouseX").toReal(), qreal(10));
1121     QCOMPARE(root->property("mouseY").toReal(), qreal(32));
1122     QCOMPARE(root->property("controlPressed").toBool(), true);
1123
1124     delete window;
1125 }
1126
1127 void tst_QQuickMouseArea::transformedMouseArea_data()
1128 {
1129     QTest::addColumn<bool>("insideTarget");
1130     QTest::addColumn<QList<QPoint> >("points");
1131
1132     QList<QPoint> pointsInside;
1133     pointsInside << QPoint(200, 140)
1134                  << QPoint(140, 200)
1135                  << QPoint(200, 200)
1136                  << QPoint(260, 200)
1137                  << QPoint(200, 260);
1138     QTest::newRow("checking points inside") << true << pointsInside;
1139
1140     QList<QPoint> pointsOutside;
1141     pointsOutside << QPoint(140, 140)
1142                   << QPoint(260, 140)
1143                   << QPoint(120, 200)
1144                   << QPoint(280, 200)
1145                   << QPoint(140, 260)
1146                   << QPoint(260, 260);
1147     QTest::newRow("checking points outside") << false << pointsOutside;
1148 }
1149
1150 void tst_QQuickMouseArea::transformedMouseArea()
1151 {
1152     QFETCH(bool, insideTarget);
1153     QFETCH(QList<QPoint>, points);
1154
1155     QQuickView *window = createView();
1156     window->setSource(testFileUrl("transformedMouseArea.qml"));
1157     window->show();
1158     window->requestActivateWindow();
1159     QVERIFY(window->rootObject() != 0);
1160
1161     QQuickMouseArea *mouseArea = window->rootObject()->findChild<QQuickMouseArea *>("mouseArea");
1162     QVERIFY(mouseArea != 0);
1163
1164     foreach (const QPoint &point, points) {
1165         // check hover
1166         QTest::mouseMove(window, point);
1167         QTest::qWait(10);
1168         QCOMPARE(mouseArea->property("containsMouse").toBool(), insideTarget);
1169
1170         // check mouse press
1171         QTest::mousePress(window, Qt::LeftButton, 0, point);
1172         QTest::qWait(10);
1173         QCOMPARE(mouseArea->property("pressed").toBool(), insideTarget);
1174
1175         // check mouse release
1176         QTest::mouseRelease(window, Qt::LeftButton, 0, point);
1177         QTest::qWait(10);
1178         QCOMPARE(mouseArea->property("pressed").toBool(), false);
1179     }
1180
1181     delete window;
1182 }
1183
1184 void tst_QQuickMouseArea::pressedMultipleButtons_data()
1185 {
1186     QTest::addColumn<Qt::MouseButtons>("accepted");
1187     QTest::addColumn<QList<Qt::MouseButtons> >("buttons");
1188     QTest::addColumn<QList<bool> >("pressed");
1189     QTest::addColumn<QList<Qt::MouseButtons> >("pressedButtons");
1190     QTest::addColumn<int>("changeCount");
1191
1192     QList<Qt::MouseButtons> buttons;
1193     QList<bool> pressed;
1194     QList<Qt::MouseButtons> pressedButtons;
1195     buttons << Qt::LeftButton
1196             << (Qt::LeftButton | Qt::RightButton)
1197             << Qt::LeftButton
1198             << 0;
1199     pressed << true
1200             << true
1201             << true
1202             << false;
1203     pressedButtons << Qt::LeftButton
1204             << Qt::LeftButton
1205             << Qt::LeftButton
1206             << 0;
1207     QTest::newRow("Accept Left - Press left, Press Right, Release Right")
1208             << Qt::MouseButtons(Qt::LeftButton) << buttons << pressed << pressedButtons << 2;
1209
1210     buttons.clear();
1211     pressed.clear();
1212     pressedButtons.clear();
1213     buttons << Qt::LeftButton
1214             << (Qt::LeftButton | Qt::RightButton)
1215             << Qt::RightButton
1216             << 0;
1217     pressed << true
1218             << true
1219             << false
1220             << false;
1221     pressedButtons << Qt::LeftButton
1222             << Qt::LeftButton
1223             << 0
1224             << 0;
1225     QTest::newRow("Accept Left - Press left, Press Right, Release Left")
1226             << Qt::MouseButtons(Qt::LeftButton) << buttons << pressed << pressedButtons << 2;
1227
1228     buttons.clear();
1229     pressed.clear();
1230     pressedButtons.clear();
1231     buttons << Qt::LeftButton
1232             << (Qt::LeftButton | Qt::RightButton)
1233             << Qt::LeftButton
1234             << 0;
1235     pressed << true
1236             << true
1237             << true
1238             << false;
1239     pressedButtons << Qt::LeftButton
1240             << (Qt::LeftButton | Qt::RightButton)
1241             << Qt::LeftButton
1242             << 0;
1243     QTest::newRow("Accept Left|Right - Press left, Press Right, Release Right")
1244         << (Qt::LeftButton | Qt::RightButton) << buttons << pressed << pressedButtons << 4;
1245
1246     buttons.clear();
1247     pressed.clear();
1248     pressedButtons.clear();
1249     buttons << Qt::RightButton
1250             << (Qt::LeftButton | Qt::RightButton)
1251             << Qt::LeftButton
1252             << 0;
1253     pressed << true
1254             << true
1255             << false
1256             << false;
1257     pressedButtons << Qt::RightButton
1258             << Qt::RightButton
1259             << 0
1260             << 0;
1261     QTest::newRow("Accept Right - Press Right, Press Left, Release Right")
1262             << Qt::MouseButtons(Qt::RightButton) << buttons << pressed << pressedButtons << 2;
1263 }
1264
1265 void tst_QQuickMouseArea::pressedMultipleButtons()
1266 {
1267     QFETCH(Qt::MouseButtons, accepted);
1268     QFETCH(QList<Qt::MouseButtons>, buttons);
1269     QFETCH(QList<bool>, pressed);
1270     QFETCH(QList<Qt::MouseButtons>, pressedButtons);
1271     QFETCH(int, changeCount);
1272
1273     QQuickView *view = createView();
1274     view->setSource(testFileUrl("simple.qml"));
1275     view->show();
1276     view->requestActivateWindow();
1277     QVERIFY(view->rootObject() != 0);
1278
1279     QQuickMouseArea *mouseArea = view->rootObject()->findChild<QQuickMouseArea *>("mousearea");
1280     QVERIFY(mouseArea != 0);
1281
1282     QSignalSpy pressedSpy(mouseArea, SIGNAL(pressedChanged()));
1283     QSignalSpy pressedButtonsSpy(mouseArea, SIGNAL(pressedButtonsChanged()));
1284     mouseArea->setAcceptedMouseButtons(accepted);
1285
1286     QPoint point(10,10);
1287
1288     int prevButtons = 0;
1289     for (int i = 0; i < buttons.count(); ++i) {
1290         int btns = buttons.at(i);
1291
1292         // The windowsysteminterface takes care of sending releases
1293         QTest::mousePress(view, (Qt::MouseButton)btns, 0, point);
1294
1295         QCOMPARE(mouseArea->pressed(), pressed.at(i));
1296         QCOMPARE(mouseArea->pressedButtons(), pressedButtons.at(i));
1297
1298         prevButtons = buttons.at(i);
1299     }
1300
1301     QTest::mousePress(view, Qt::NoButton, 0, point);
1302     QCOMPARE(mouseArea->pressed(), false);
1303
1304     QCOMPARE(pressedSpy.count(), 2);
1305     QCOMPARE(pressedButtonsSpy.count(), changeCount);
1306
1307     delete view;
1308 }
1309
1310 void tst_QQuickMouseArea::changeAxis()
1311 {
1312     QQuickView *view = createView();
1313
1314     view->setSource(testFileUrl("changeAxis.qml"));
1315     view->show();
1316     view->requestActivateWindow();
1317     QTRY_VERIFY(view->rootObject() != 0);
1318
1319     QQuickMouseArea *mouseRegion = view->rootObject()->findChild<QQuickMouseArea*>("mouseregion");
1320     QQuickDrag *drag = mouseRegion->drag();
1321     QVERIFY(mouseRegion != 0);
1322     QVERIFY(drag != 0);
1323
1324     mouseRegion->setAcceptedButtons(Qt::LeftButton);
1325
1326     // target
1327     QQuickItem *blackRect = view->rootObject()->findChild<QQuickItem*>("blackrect");
1328     QVERIFY(blackRect != 0);
1329     QVERIFY(blackRect == drag->target());
1330
1331     QVERIFY(!drag->active());
1332
1333     // Start a diagonal drag
1334     QTest::mousePress(view, Qt::LeftButton, 0, QPoint(100, 100));
1335
1336     QVERIFY(!drag->active());
1337     QCOMPARE(blackRect->x(), 50.0);
1338     QCOMPARE(blackRect->y(), 50.0);
1339
1340     QTest::mouseMove(view, QPoint(111, 111));
1341     QTest::qWait(50);
1342     QTest::mouseMove(view, QPoint(122, 122));
1343
1344     QTRY_VERIFY(drag->active());
1345     QCOMPARE(blackRect->x(), 72.0);
1346     QCOMPARE(blackRect->y(), 72.0);
1347     QCOMPARE(drag->axis(), QQuickDrag::XandYAxis);
1348
1349     /* When blackRect.x becomes bigger than 75, the drag axis is changed to
1350      * Drag.YAxis by the QML code. Verify that this happens, and that the drag
1351      * movement is effectively constrained to the Y axis. */
1352     QTest::mouseMove(view, QPoint(133, 133));
1353
1354     QTRY_COMPARE(blackRect->x(), 83.0);
1355     QTRY_COMPARE(blackRect->y(), 83.0);
1356     QTRY_COMPARE(drag->axis(), QQuickDrag::YAxis);
1357
1358     QTest::mouseMove(view, QPoint(144, 144));
1359
1360     QTRY_COMPARE(blackRect->y(), 94.0);
1361     QCOMPARE(blackRect->x(), 83.0);
1362
1363     QTest::mouseRelease(view, Qt::LeftButton, 0, QPoint(144, 144));
1364
1365     QTRY_VERIFY(!drag->active());
1366     QCOMPARE(blackRect->x(), 83.0);
1367     QCOMPARE(blackRect->y(), 94.0);
1368
1369     delete view;
1370 }
1371
1372 #ifndef QT_NO_CURSOR
1373 void tst_QQuickMouseArea::cursorShape()
1374 {
1375     QQmlEngine engine;
1376     QQmlComponent component(&engine);
1377     component.setData("import QtQuick 2.0\n MouseArea {}", QUrl());
1378     QScopedPointer<QObject> object(component.create());
1379     QQuickMouseArea *mouseArea = qobject_cast<QQuickMouseArea *>(object.data());
1380     QVERIFY(mouseArea);
1381
1382     QSignalSpy spy(mouseArea, SIGNAL(cursorShapeChanged()));
1383
1384     QCOMPARE(mouseArea->cursorShape(), Qt::ArrowCursor);
1385     QCOMPARE(mouseArea->cursor().shape(), Qt::ArrowCursor);
1386
1387     mouseArea->setCursorShape(Qt::IBeamCursor);
1388     QCOMPARE(mouseArea->cursorShape(), Qt::IBeamCursor);
1389     QCOMPARE(mouseArea->cursor().shape(), Qt::IBeamCursor);
1390     QCOMPARE(spy.count(), 1);
1391
1392     mouseArea->setCursorShape(Qt::IBeamCursor);
1393     QCOMPARE(spy.count(), 1);
1394
1395     mouseArea->setCursorShape(Qt::WaitCursor);
1396     QCOMPARE(mouseArea->cursorShape(), Qt::WaitCursor);
1397     QCOMPARE(mouseArea->cursor().shape(), Qt::WaitCursor);
1398     QCOMPARE(spy.count(), 2);
1399 }
1400 #endif
1401
1402 QTEST_MAIN(tst_QQuickMouseArea)
1403
1404 #include "tst_qquickmousearea.moc"