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