6a13f41ba4e28b5cf101e63179f80403402ac3bd
[profile/ivi/qtdeclarative.git] / tests / auto / quick / qquickitem / tst_qquickitem.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 <qtest.h>
43
44 #include <QtQuick/qquickitem.h>
45 #include <QtQuick/qquickcanvas.h>
46 #include <QtQuick/qquickview.h>
47 #include <QtWidgets/QGraphicsSceneMouseEvent>
48 #include "private/qquickfocusscope_p.h"
49 #include "private/qquickitem_p.h"
50 #include <QDebug>
51 #include <QTimer>
52 #include "../../shared/util.h"
53
54 class TestItem : public QQuickItem
55 {
56 Q_OBJECT
57 public:
58     TestItem(QQuickItem *parent = 0)
59         : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0)
60         , wheelCount(0), acceptIncomingTouchEvents(true)
61         , touchEventReached(false) {}
62
63     bool focused;
64     int pressCount;
65     int releaseCount;
66     int wheelCount;
67     bool acceptIncomingTouchEvents;
68     bool touchEventReached;
69 protected:
70     virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
71     virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
72     virtual void mousePressEvent(QMouseEvent *event) { event->accept(); ++pressCount; }
73     virtual void mouseReleaseEvent(QMouseEvent *event) { event->accept(); ++releaseCount; }
74     virtual void touchEvent(QTouchEvent *event) {
75         touchEventReached = true;
76         event->setAccepted(acceptIncomingTouchEvents);
77     }
78     virtual void wheelEvent(QWheelEvent *event) { event->accept(); ++wheelCount; }
79 };
80
81 class TestCanvas: public QQuickCanvas
82 {
83 public:
84     TestCanvas()
85         : QQuickCanvas()
86     {}
87
88     virtual bool event(QEvent *event)
89     {
90         return QQuickCanvas::event(event);
91     }
92 };
93
94 class TestPolishItem : public QQuickItem
95 {
96 Q_OBJECT
97 public:
98     TestPolishItem(QQuickItem *parent = 0)
99     : QQuickItem(parent), wasPolished(false) {
100
101     }
102
103     bool wasPolished;
104
105 protected:
106     virtual void updatePolish() {
107         wasPolished = true;
108     }
109
110 public slots:
111     void doPolish() {
112         polish();
113     }
114 };
115
116 class TestFocusScope : public QQuickFocusScope
117 {
118 Q_OBJECT
119 public:
120     TestFocusScope(QQuickItem *parent = 0) : QQuickFocusScope(parent), focused(false) {}
121
122     bool focused;
123 protected:
124     virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
125     virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
126 };
127
128 class tst_qquickitem : public QQmlDataTest
129 {
130     Q_OBJECT
131 public:
132
133 private slots:
134     void initTestCase();
135
136     void noCanvas();
137     void simpleFocus();
138     void scopedFocus();
139     void addedToCanvas();
140     void changeParent();
141     void multipleFocusClears();
142     void focusSubItemInNonFocusScope();
143     void parentItemWithFocus();
144     void reparentFocusedItem();
145
146     void constructor();
147     void setParentItem();
148
149     void visible();
150     void enabled();
151     void enabledFocus();
152
153     void mouseGrab();
154     void touchEventAcceptIgnore_data();
155     void touchEventAcceptIgnore();
156     void polishOutsideAnimation();
157     void polishOnCompleted();
158
159     void wheelEvent_data();
160     void wheelEvent();
161     void hoverEvent_data();
162     void hoverEvent();
163     void hoverEventInParent();
164
165     void paintOrder_data();
166     void paintOrder();
167
168     void acceptedMouseButtons();
169
170 private:
171
172     enum PaintOrderOp {
173         NoOp, Append, Remove, StackBefore, StackAfter, SetZ
174     };
175
176     void ensureFocus(QWindow *w) {
177         w->show();
178         w->requestActivateWindow();
179         QTest::qWaitForWindowActive(w);
180     }
181 };
182
183 void tst_qquickitem::initTestCase()
184 {
185     QQmlDataTest::initTestCase();
186     qmlRegisterType<TestPolishItem>("Qt.test", 1, 0, "TestPolishItem");
187 }
188
189 // Focus still updates when outside a canvas
190 void tst_qquickitem::noCanvas()
191 {
192     QQuickItem *root = new TestItem;
193     QQuickItem *child = new TestItem(root);
194     QQuickItem *scope = new TestItem(root);
195     QQuickFocusScope *scopedChild = new TestFocusScope(scope);
196     QQuickFocusScope *scopedChild2 = new TestFocusScope(scope);
197
198     QCOMPARE(root->hasFocus(), false);
199     QCOMPARE(child->hasFocus(), false);
200     QCOMPARE(scope->hasFocus(), false);
201     QCOMPARE(scopedChild->hasFocus(), false);
202     QCOMPARE(scopedChild2->hasFocus(), false);
203
204     root->setFocus(true);
205     scope->setFocus(true);
206     scopedChild2->setFocus(true);
207     QCOMPARE(root->hasFocus(), false);
208     QCOMPARE(child->hasFocus(), false);
209     QCOMPARE(scope->hasFocus(), false);
210     QCOMPARE(scopedChild->hasFocus(), false);
211     QCOMPARE(scopedChild2->hasFocus(), true);
212
213     root->setFocus(false);
214     child->setFocus(true);
215     scopedChild->setFocus(true);
216     scope->setFocus(false);
217     QCOMPARE(root->hasFocus(), false);
218     QCOMPARE(child->hasFocus(), false);
219     QCOMPARE(scope->hasFocus(), false);
220     QCOMPARE(scopedChild->hasFocus(), true);
221     QCOMPARE(scopedChild2->hasFocus(), false);
222
223     delete root;
224 }
225
226 struct FocusData {
227     FocusData() : focus(false), activeFocus(false) {}
228
229     void set(bool f, bool af) { focus = f; activeFocus = af; }
230     bool focus;
231     bool activeFocus;
232 };
233 struct FocusState : public QHash<QQuickItem *, FocusData>
234 {
235     FocusState() : activeFocusItem(0) {}
236     FocusState &operator<<(QQuickItem *item) {
237         insert(item, FocusData());
238         return *this;
239     }
240
241     void active(QQuickItem *i) {
242         activeFocusItem = i;
243     }
244     QQuickItem *activeFocusItem;
245 };
246
247 #define FVERIFY() \
248     do { \
249         if (focusState.activeFocusItem) { \
250             QCOMPARE(canvas.activeFocusItem(), focusState.activeFocusItem); \
251             if (qobject_cast<TestItem *>(canvas.activeFocusItem())) \
252                 QCOMPARE(qobject_cast<TestItem *>(canvas.activeFocusItem())->focused, true); \
253             else if (qobject_cast<TestFocusScope *>(canvas.activeFocusItem())) \
254                 QCOMPARE(qobject_cast<TestFocusScope *>(canvas.activeFocusItem())->focused, true); \
255         } else { \
256             QCOMPARE(canvas.activeFocusItem(), canvas.rootItem()); \
257         } \
258         for (QHash<QQuickItem *, FocusData>::Iterator iter = focusState.begin(); \
259             iter != focusState.end(); \
260             iter++) { \
261             QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \
262             QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \
263         } \
264     } while (false)
265
266 // Tests a simple set of top-level scoped items
267 void tst_qquickitem::simpleFocus()
268 {
269     QQuickCanvas canvas;
270     ensureFocus(&canvas);
271
272 #ifdef Q_OS_MAC
273     QSKIP("QTBUG-24094: fails on Mac OS X 10.7");
274 #endif
275
276     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
277
278     QQuickItem *l1c1 = new TestItem(canvas.rootItem());
279     QQuickItem *l1c2 = new TestItem(canvas.rootItem());
280     QQuickItem *l1c3 = new TestItem(canvas.rootItem());
281
282     QQuickItem *l2c1 = new TestItem(l1c1);
283     QQuickItem *l2c2 = new TestItem(l1c1);
284     QQuickItem *l2c3 = new TestItem(l1c3);
285
286     FocusState focusState;
287     focusState << l1c1 << l1c2 << l1c3
288                << l2c1 << l2c2 << l2c3;
289     FVERIFY();
290
291     l1c1->setFocus(true);
292     focusState[l1c1].set(true, true);
293     focusState.active(l1c1);
294     FVERIFY();
295
296     l2c3->setFocus(true);
297     focusState[l1c1].set(false, false);
298     focusState[l2c3].set(true, true);
299     focusState.active(l2c3);
300     FVERIFY();
301
302     l1c3->setFocus(true);
303     focusState[l2c3].set(false, false);
304     focusState[l1c3].set(true, true);
305     focusState.active(l1c3);
306     FVERIFY();
307
308     l1c2->setFocus(false);
309     FVERIFY();
310
311     l1c3->setFocus(false);
312     focusState[l1c3].set(false, false);
313     focusState.active(0);
314     FVERIFY();
315
316     l2c1->setFocus(true);
317     focusState[l2c1].set(true, true);
318     focusState.active(l2c1);
319     FVERIFY();
320 }
321
322 // Items with a focus scope
323 void tst_qquickitem::scopedFocus()
324 {
325     QQuickCanvas canvas;
326     ensureFocus(&canvas);
327     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
328
329     QQuickItem *l1c1 = new TestItem(canvas.rootItem());
330     QQuickItem *l1c2 = new TestItem(canvas.rootItem());
331     QQuickItem *l1c3 = new TestItem(canvas.rootItem());
332
333     QQuickItem *l2c1 = new TestItem(l1c1);
334     QQuickItem *l2c2 = new TestItem(l1c1);
335     QQuickItem *l2c3 = new TestFocusScope(l1c3);
336
337     QQuickItem *l3c1 = new TestItem(l2c3);
338     QQuickItem *l3c2 = new TestFocusScope(l2c3);
339
340     QQuickItem *l4c1 = new TestItem(l3c2);
341     QQuickItem *l4c2 = new TestItem(l3c2);
342
343     FocusState focusState;
344     focusState << l1c1 << l1c2 << l1c3
345                << l2c1 << l2c2 << l2c3
346                << l3c1 << l3c2
347                << l4c1 << l4c2;
348     FVERIFY();
349
350     l4c2->setFocus(true);
351     focusState[l4c2].set(true, false);
352     FVERIFY();
353
354     l4c1->setFocus(true);
355     focusState[l4c2].set(false, false);
356     focusState[l4c1].set(true, false);
357     FVERIFY();
358
359     l1c1->setFocus(true);
360     focusState[l1c1].set(true, true);
361     focusState.active(l1c1);
362     FVERIFY();
363
364     l3c2->setFocus(true);
365     focusState[l3c2].set(true, false);
366     FVERIFY();
367
368     l2c3->setFocus(true);
369     focusState[l1c1].set(false, false);
370     focusState[l2c3].set(true, true);
371     focusState[l3c2].set(true, true);
372     focusState[l4c1].set(true, true);
373     focusState.active(l4c1);
374     FVERIFY();
375
376     l3c2->setFocus(false);
377     focusState[l3c2].set(false, false);
378     focusState[l4c1].set(true, false);
379     focusState.active(l2c3);
380     FVERIFY();
381
382     l3c2->setFocus(true);
383     focusState[l3c2].set(true, true);
384     focusState[l4c1].set(true, true);
385     focusState.active(l4c1);
386     FVERIFY();
387
388     l4c1->setFocus(false);
389     focusState[l4c1].set(false, false);
390     focusState.active(l3c2);
391     FVERIFY();
392
393     l1c3->setFocus(true);
394     focusState[l1c3].set(true, true);
395     focusState[l2c3].set(false, false);
396     focusState[l3c2].set(true, false);
397     focusState.active(l1c3);
398     FVERIFY();
399 }
400
401 // Tests focus corrects itself when a tree is added to a canvas for the first time
402 void tst_qquickitem::addedToCanvas()
403 {
404     {
405     QQuickCanvas canvas;
406     ensureFocus(&canvas);
407     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
408
409     QQuickItem *item = new TestItem;
410
411     FocusState focusState;
412     focusState << item;
413
414     item->setFocus(true);
415     focusState[item].set(true, false);
416     FVERIFY();
417
418     item->setParentItem(canvas.rootItem());
419     focusState[item].set(true, true);
420     focusState.active(item);
421     FVERIFY();
422     }
423
424     {
425     QQuickCanvas canvas;
426     ensureFocus(&canvas);
427     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
428
429     QQuickItem *item = new TestItem(canvas.rootItem());
430
431     QQuickItem *tree = new TestItem;
432     QQuickItem *c1 = new TestItem(tree);
433     QQuickItem *c2 = new TestItem(tree);
434
435     FocusState focusState;
436     focusState << item << tree << c1 << c2;
437
438     item->setFocus(true);
439     c1->setFocus(true);
440     c2->setFocus(true);
441     focusState[item].set(true, true);
442     focusState[c1].set(false, false);
443     focusState[c2].set(true, false);
444     focusState.active(item);
445     FVERIFY();
446
447     tree->setParentItem(item);
448     focusState[c1].set(false, false);
449     focusState[c2].set(false, false);
450     FVERIFY();
451     }
452
453     {
454     QQuickCanvas canvas;
455     ensureFocus(&canvas);
456     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
457
458     QQuickItem *tree = new TestItem;
459     QQuickItem *c1 = new TestItem(tree);
460     QQuickItem *c2 = new TestItem(tree);
461
462     FocusState focusState;
463     focusState << tree << c1 << c2;
464     c1->setFocus(true);
465     c2->setFocus(true);
466     focusState[c1].set(false, false);
467     focusState[c2].set(true, false);
468     FVERIFY();
469
470     tree->setParentItem(canvas.rootItem());
471     focusState[c1].set(false, false);
472     focusState[c2].set(true, true);
473     focusState.active(c2);
474     FVERIFY();
475     }
476
477     {
478     QQuickCanvas canvas;
479     ensureFocus(&canvas);
480     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
481     QQuickItem *tree = new TestFocusScope;
482     QQuickItem *c1 = new TestItem(tree);
483     QQuickItem *c2 = new TestItem(tree);
484
485     FocusState focusState;
486     focusState << tree << c1 << c2;
487     c1->setFocus(true);
488     c2->setFocus(true);
489     focusState[c1].set(false, false);
490     focusState[c2].set(true, false);
491     FVERIFY();
492
493     tree->setParentItem(canvas.rootItem());
494     focusState[c1].set(false, false);
495     focusState[c2].set(true, false);
496     FVERIFY();
497
498     tree->setFocus(true);
499     focusState[tree].set(true, true);
500     focusState[c2].set(true, true);
501     focusState.active(c2);
502     FVERIFY();
503     }
504
505     {
506     QQuickCanvas canvas;
507     ensureFocus(&canvas);
508     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
509     QQuickItem *tree = new TestFocusScope;
510     QQuickItem *c1 = new TestItem(tree);
511     QQuickItem *c2 = new TestItem(tree);
512
513     FocusState focusState;
514     focusState << tree << c1 << c2;
515     tree->setFocus(true);
516     c1->setFocus(true);
517     c2->setFocus(true);
518     focusState[tree].set(true, false);
519     focusState[c1].set(false, false);
520     focusState[c2].set(true, false);
521     FVERIFY();
522
523     tree->setParentItem(canvas.rootItem());
524     focusState[tree].set(true, true);
525     focusState[c1].set(false, false);
526     focusState[c2].set(true, true);
527     focusState.active(c2);
528     FVERIFY();
529     }
530
531     {
532     QQuickCanvas canvas;
533     ensureFocus(&canvas);
534     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
535     QQuickItem *child = new TestItem(canvas.rootItem());
536     QQuickItem *tree = new TestFocusScope;
537     QQuickItem *c1 = new TestItem(tree);
538     QQuickItem *c2 = new TestItem(tree);
539
540     FocusState focusState;
541     focusState << child << tree << c1 << c2;
542     child->setFocus(true);
543     tree->setFocus(true);
544     c1->setFocus(true);
545     c2->setFocus(true);
546     focusState[child].set(true, true);
547     focusState[tree].set(true, false);
548     focusState[c1].set(false, false);
549     focusState[c2].set(true, false);
550     focusState.active(child);
551     FVERIFY();
552
553     tree->setParentItem(canvas.rootItem());
554     focusState[tree].set(false, false);
555     focusState[c1].set(false, false);
556     focusState[c2].set(true, false);
557     FVERIFY();
558
559     tree->setFocus(true);
560     focusState[child].set(false, false);
561     focusState[tree].set(true, true);
562     focusState[c2].set(true, true);
563     focusState.active(c2);
564     FVERIFY();
565     }
566 }
567
568 void tst_qquickitem::changeParent()
569 {
570     // Parent to no parent
571     {
572     QQuickCanvas canvas;
573     ensureFocus(&canvas);
574     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
575     QQuickItem *child = new TestItem(canvas.rootItem());
576
577     FocusState focusState;
578     focusState << child;
579     FVERIFY();
580
581     child->setFocus(true);
582     focusState[child].set(true, true);
583     focusState.active(child);
584     FVERIFY();
585
586     child->setParentItem(0);
587     focusState[child].set(true, false);
588     focusState.active(0);
589     FVERIFY();
590     }
591
592     // Different parent, same focus scope
593     {
594     QQuickCanvas canvas;
595     ensureFocus(&canvas);
596     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
597     QQuickItem *child = new TestItem(canvas.rootItem());
598     QQuickItem *child2 = new TestItem(canvas.rootItem());
599
600     FocusState focusState;
601     focusState << child << child2;
602     FVERIFY();
603
604     child->setFocus(true);
605     focusState[child].set(true, true);
606     focusState.active(child);
607     FVERIFY();
608
609     child->setParentItem(child2);
610     FVERIFY();
611     }
612
613     // Different parent, different focus scope
614     {
615     QQuickCanvas canvas;
616     ensureFocus(&canvas);
617     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
618     QQuickItem *child = new TestItem(canvas.rootItem());
619     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
620     QQuickItem *item = new TestItem(child);
621
622     FocusState focusState;
623     focusState << child << child2 << item;
624     FVERIFY();
625
626     item->setFocus(true);
627     focusState[item].set(true, true);
628     focusState.active(item);
629     FVERIFY();
630
631     item->setParentItem(child2);
632     focusState[item].set(true, false);
633     focusState.active(0);
634     FVERIFY();
635     }
636     {
637     QQuickCanvas canvas;
638     ensureFocus(&canvas);
639     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
640     QQuickItem *child = new TestItem(canvas.rootItem());
641     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
642     QQuickItem *item = new TestItem(child2);
643
644     FocusState focusState;
645     focusState << child << child2 << item;
646     FVERIFY();
647
648     item->setFocus(true);
649     focusState[item].set(true, false);
650     focusState.active(0);
651     FVERIFY();
652
653     item->setParentItem(child);
654     focusState[item].set(true, true);
655     focusState.active(item);
656     FVERIFY();
657     }
658     {
659     QQuickCanvas canvas;
660     ensureFocus(&canvas);
661     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
662     QQuickItem *child = new TestItem(canvas.rootItem());
663     QQuickItem *child2 = new TestFocusScope(canvas.rootItem());
664     QQuickItem *item = new TestItem(child2);
665
666     FocusState focusState;
667     focusState << child << child2 << item;
668     FVERIFY();
669
670     child->setFocus(true);
671     item->setFocus(true);
672     focusState[child].set(true, true);
673     focusState[item].set(true, false);
674     focusState.active(child);
675     FVERIFY();
676
677     item->setParentItem(child);
678     focusState[item].set(false, false);
679     FVERIFY();
680     }
681
682     // child has active focus, then its fs parent changes parent to 0, then
683     // child is deleted, then its parent changes again to a valid parent
684     {
685     QQuickCanvas canvas;
686     ensureFocus(&canvas);
687     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
688     QQuickItem *item = new TestFocusScope(canvas.rootItem());
689     QQuickItem *child = new TestItem(item);
690     QQuickItem *child2 = new TestItem;
691
692     FocusState focusState;
693     focusState << item << child;
694     FVERIFY();
695
696     item->setFocus(true);
697     child->setFocus(true);
698     focusState[child].set(true, true);
699     focusState[item].set(true, true);
700     focusState.active(child);
701     FVERIFY();
702
703     item->setParentItem(0);
704     focusState[child].set(true, false);
705     focusState[item].set(true, false);
706     focusState.active(0);
707     FVERIFY();
708
709     focusState.remove(child);
710     delete child;
711     item->setParentItem(canvas.rootItem());
712     focusState[item].set(true, true);
713     focusState.active(item);
714     FVERIFY();
715     delete child2;
716     }
717 }
718
719 void tst_qquickitem::multipleFocusClears()
720 {
721     //Multiple clears of focus inside a focus scope shouldn't crash. QTBUG-24714
722     QQuickView *view = new QQuickView;
723     view->setSource(testFileUrl("multipleFocusClears.qml"));
724     view->show();
725     ensureFocus(view);
726     QTRY_VERIFY(QGuiApplication::focusWindow() == view);
727 }
728
729 void tst_qquickitem::focusSubItemInNonFocusScope()
730 {
731     QQuickView *view = new QQuickView;
732     view->setSource(testFileUrl("focusSubItemInNonFocusScope.qml"));
733     view->show();
734     qApp->processEvents();
735
736     QQuickItem *dummyItem = view->rootObject()->findChild<QQuickItem *>("dummyItem");
737     QVERIFY(dummyItem);
738
739     QQuickItem *textInput = view->rootObject()->findChild<QQuickItem *>("textInput");
740     QVERIFY(textInput);
741
742     QVERIFY(dummyItem->hasFocus());
743     QVERIFY(!textInput->hasFocus());
744     QVERIFY(dummyItem->hasActiveFocus());
745
746     QVERIFY(QMetaObject::invokeMethod(textInput, "forceActiveFocus"));
747
748     QVERIFY(!dummyItem->hasFocus());
749     QVERIFY(textInput->hasFocus());
750     QVERIFY(textInput->hasActiveFocus());
751
752     delete view;
753 }
754
755 void tst_qquickitem::parentItemWithFocus()
756 {
757     QQuickCanvas canvas;
758     ensureFocus(&canvas);
759     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
760     {
761     QQuickItem parent;
762     QQuickItem child;
763
764     FocusState focusState;
765     focusState << &parent << &child;
766     FVERIFY();
767
768     parent.setFocus(true);
769     child.setFocus(true);
770     focusState[&parent].set(true, false);
771     focusState[&child].set(true, false);
772     FVERIFY();
773
774     child.setParentItem(&parent);
775     focusState[&parent].set(true, false);
776     focusState[&child].set(false, false);
777     FVERIFY();
778
779     parent.setParentItem(canvas.rootItem());
780     focusState[&parent].set(true, true);
781     focusState[&child].set(false, false);
782     focusState.active(&parent);
783     FVERIFY();
784
785     child.forceActiveFocus();
786     focusState[&parent].set(false, false);
787     focusState[&child].set(true, true);
788     focusState.active(&child);
789     FVERIFY();
790     } {
791     QQuickItem parent;
792     QQuickItem child;
793     QQuickItem grandchild(&child);
794
795     FocusState focusState;
796     focusState << &parent << &child << &grandchild;
797     FVERIFY();
798
799     parent.setFocus(true);
800     grandchild.setFocus(true);
801     focusState[&parent].set(true, false);
802     focusState[&child].set(false, false);
803     focusState[&grandchild].set(true, false);
804     FVERIFY();
805
806     child.setParentItem(&parent);
807     focusState[&parent].set(true, false);
808     focusState[&child].set(false, false);
809     focusState[&grandchild].set(false, false);
810     FVERIFY();
811
812     parent.setParentItem(canvas.rootItem());
813     focusState[&parent].set(true, true);
814     focusState[&child].set(false, false);
815     focusState[&grandchild].set(false, false);
816     focusState.active(&parent);
817     FVERIFY();
818
819     grandchild.forceActiveFocus();
820     focusState[&parent].set(false, false);
821     focusState[&child].set(false, false);
822     focusState[&grandchild].set(true, true);
823     focusState.active(&grandchild);
824     FVERIFY();
825     }
826
827     {
828     QQuickItem parent;
829     QQuickItem child1;
830     QQuickItem child2;
831
832     FocusState focusState;
833     focusState << &parent << &child1 << &child2;
834     parent.setFocus(true);
835     child1.setParentItem(&parent);
836     child2.setParentItem(&parent);
837     focusState[&parent].set(true, false);
838     focusState[&child1].set(false, false);
839     focusState[&child2].set(false, false);
840     FVERIFY();
841
842     child1.setFocus(true);
843     focusState[&parent].set(false, false);
844     focusState[&child1].set(true, false);
845     FVERIFY();
846
847     parent.setFocus(true);
848     focusState[&parent].set(true, false);
849     focusState[&child1].set(false, false);
850     FVERIFY();
851     }
852 }
853
854 void tst_qquickitem::reparentFocusedItem()
855 {
856     QQuickCanvas canvas;
857     ensureFocus(&canvas);
858     QTRY_VERIFY(QGuiApplication::focusWindow() == &canvas);
859
860     QQuickItem parent(canvas.rootItem());
861     QQuickItem child(&parent);
862     QQuickItem sibling(&parent);
863     QQuickItem grandchild(&child);
864
865     FocusState focusState;
866     focusState << &parent << &child << &sibling << &grandchild;
867     FVERIFY();
868
869     grandchild.setFocus(true);
870     focusState[&parent].set(false, false);
871     focusState[&child].set(false, false);
872     focusState[&sibling].set(false, false);
873     focusState[&grandchild].set(true, true);
874     focusState.active(&grandchild);
875     FVERIFY();
876
877     // Parenting the item to another item within the same focus scope shouldn't change it's focus.
878     child.setParentItem(&sibling);
879     FVERIFY();
880 }
881
882 void tst_qquickitem::constructor()
883 {
884     QQuickItem *root = new QQuickItem;
885     QVERIFY(root->parent() == 0);
886     QVERIFY(root->parentItem() == 0);
887
888     QQuickItem *child1 = new QQuickItem(root);
889     QVERIFY(child1->parent() == root);
890     QVERIFY(child1->parentItem() == root);
891     QCOMPARE(root->childItems().count(), 1);
892     QCOMPARE(root->childItems().at(0), child1);
893
894     QQuickItem *child2 = new QQuickItem(root);
895     QVERIFY(child2->parent() == root);
896     QVERIFY(child2->parentItem() == root);
897     QCOMPARE(root->childItems().count(), 2);
898     QCOMPARE(root->childItems().at(0), child1);
899     QCOMPARE(root->childItems().at(1), child2);
900
901     delete root;
902 }
903
904 void tst_qquickitem::setParentItem()
905 {
906     QQuickItem *root = new QQuickItem;
907     QVERIFY(root->parent() == 0);
908     QVERIFY(root->parentItem() == 0);
909
910     QQuickItem *child1 = new QQuickItem;
911     QVERIFY(child1->parent() == 0);
912     QVERIFY(child1->parentItem() == 0);
913
914     child1->setParentItem(root);
915     QVERIFY(child1->parent() == 0);
916     QVERIFY(child1->parentItem() == root);
917     QCOMPARE(root->childItems().count(), 1);
918     QCOMPARE(root->childItems().at(0), child1);
919
920     QQuickItem *child2 = new QQuickItem;
921     QVERIFY(child2->parent() == 0);
922     QVERIFY(child2->parentItem() == 0);
923     child2->setParentItem(root);
924     QVERIFY(child2->parent() == 0);
925     QVERIFY(child2->parentItem() == root);
926     QCOMPARE(root->childItems().count(), 2);
927     QCOMPARE(root->childItems().at(0), child1);
928     QCOMPARE(root->childItems().at(1), child2);
929
930     child1->setParentItem(0);
931     QVERIFY(child1->parent() == 0);
932     QVERIFY(child1->parentItem() == 0);
933     QCOMPARE(root->childItems().count(), 1);
934     QCOMPARE(root->childItems().at(0), child2);
935
936     delete root;
937
938     QVERIFY(child1->parent() == 0);
939     QVERIFY(child1->parentItem() == 0);
940     QVERIFY(child2->parent() == 0);
941     QVERIFY(child2->parentItem() == 0);
942
943     delete child1;
944     delete child2;
945 }
946
947 void tst_qquickitem::visible()
948 {
949     QQuickItem *root = new QQuickItem;
950
951     QQuickItem *child1 = new QQuickItem;
952     child1->setParentItem(root);
953
954     QQuickItem *child2 = new QQuickItem;
955     child2->setParentItem(root);
956
957     QVERIFY(child1->isVisible());
958     QVERIFY(child2->isVisible());
959
960     root->setVisible(false);
961     QVERIFY(!child1->isVisible());
962     QVERIFY(!child2->isVisible());
963
964     root->setVisible(true);
965     QVERIFY(child1->isVisible());
966     QVERIFY(child2->isVisible());
967
968     child1->setVisible(false);
969     QVERIFY(!child1->isVisible());
970     QVERIFY(child2->isVisible());
971
972     child2->setParentItem(child1);
973     QVERIFY(!child1->isVisible());
974     QVERIFY(!child2->isVisible());
975
976     child2->setParentItem(root);
977     QVERIFY(!child1->isVisible());
978     QVERIFY(child2->isVisible());
979
980     delete root;
981     delete child1;
982     delete child2;
983 }
984
985 void tst_qquickitem::enabled()
986 {
987     QQuickItem *root = new QQuickItem;
988
989     QQuickItem *child1 = new QQuickItem;
990     child1->setParentItem(root);
991
992     QQuickItem *child2 = new QQuickItem;
993     child2->setParentItem(root);
994
995     QVERIFY(child1->isEnabled());
996     QVERIFY(child2->isEnabled());
997
998     root->setEnabled(false);
999     QVERIFY(!child1->isEnabled());
1000     QVERIFY(!child2->isEnabled());
1001
1002     root->setEnabled(true);
1003     QVERIFY(child1->isEnabled());
1004     QVERIFY(child2->isEnabled());
1005
1006     child1->setEnabled(false);
1007     QVERIFY(!child1->isEnabled());
1008     QVERIFY(child2->isEnabled());
1009
1010     child2->setParentItem(child1);
1011     QVERIFY(!child1->isEnabled());
1012     QVERIFY(!child2->isEnabled());
1013
1014     child2->setParentItem(root);
1015     QVERIFY(!child1->isEnabled());
1016     QVERIFY(child2->isEnabled());
1017
1018     delete root;
1019     delete child1;
1020     delete child2;
1021 }
1022
1023 void tst_qquickitem::enabledFocus()
1024 {
1025     QQuickCanvas canvas;
1026     ensureFocus(&canvas);
1027
1028     QQuickFocusScope root;
1029
1030     root.setFocus(true);
1031     root.setEnabled(false);
1032
1033     QCOMPARE(root.isEnabled(), false);
1034     QCOMPARE(root.hasFocus(), true);
1035     QCOMPARE(root.hasActiveFocus(), false);
1036
1037     root.setParentItem(canvas.rootItem());
1038
1039     QCOMPARE(root.isEnabled(), false);
1040     QCOMPARE(root.hasFocus(), true);
1041     QCOMPARE(root.hasActiveFocus(), false);
1042     QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
1043
1044     root.setEnabled(true);
1045     QCOMPARE(root.isEnabled(), true);
1046     QCOMPARE(root.hasFocus(), true);
1047     QCOMPARE(root.hasActiveFocus(), true);
1048     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
1049
1050     QQuickItem child1;
1051     child1.setParentItem(&root);
1052
1053     QCOMPARE(child1.isEnabled(), true);
1054     QCOMPARE(child1.hasFocus(), false);
1055     QCOMPARE(child1.hasActiveFocus(), false);
1056     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
1057
1058     QQuickItem child2;
1059     child2.setFocus(true);
1060     child2.setParentItem(&root);
1061
1062     QCOMPARE(root.isEnabled(), true);
1063     QCOMPARE(root.hasFocus(), true);
1064     QCOMPARE(root.hasActiveFocus(), true);
1065     QCOMPARE(child2.isEnabled(), true);
1066     QCOMPARE(child2.hasFocus(), true);
1067     QCOMPARE(child2.hasActiveFocus(), true);
1068     QCOMPARE(canvas.activeFocusItem(), &child2);
1069
1070     child2.setEnabled(false);
1071
1072     QCOMPARE(root.isEnabled(), true);
1073     QCOMPARE(root.hasFocus(), true);
1074     QCOMPARE(root.hasActiveFocus(), true);
1075     QCOMPARE(child1.isEnabled(), true);
1076     QCOMPARE(child1.hasFocus(), false);
1077     QCOMPARE(child1.hasActiveFocus(), false);
1078     QCOMPARE(child2.isEnabled(), false);
1079     QCOMPARE(child2.hasFocus(), true);
1080     QCOMPARE(child2.hasActiveFocus(), false);
1081     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
1082
1083     child1.setEnabled(false);
1084     QCOMPARE(child1.isEnabled(), false);
1085     QCOMPARE(child1.hasFocus(), false);
1086     QCOMPARE(child1.hasActiveFocus(), false);
1087
1088     child1.setFocus(true);
1089     QCOMPARE(child1.isEnabled(), false);
1090     QCOMPARE(child1.hasFocus(), true);
1091     QCOMPARE(child1.hasActiveFocus(), false);
1092     QCOMPARE(child2.isEnabled(), false);
1093     QCOMPARE(child2.hasFocus(), false);
1094     QCOMPARE(child2.hasActiveFocus(), false);
1095     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
1096
1097     child1.setEnabled(true);
1098     QCOMPARE(child1.isEnabled(), true);
1099     QCOMPARE(child1.hasFocus(), true);
1100     QCOMPARE(child1.hasActiveFocus(), true);
1101     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&child1));
1102
1103     root.setFocus(false);
1104     QCOMPARE(root.isEnabled(), true);
1105     QCOMPARE(root.hasFocus(), false);
1106     QCOMPARE(root.hasActiveFocus(), false);
1107     QCOMPARE(child1.isEnabled(), true);
1108     QCOMPARE(child1.hasFocus(), true);
1109     QCOMPARE(child1.hasActiveFocus(), false);
1110     QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
1111
1112     child2.forceActiveFocus();
1113     QCOMPARE(root.isEnabled(), true);
1114     QCOMPARE(root.hasFocus(), true);
1115     QCOMPARE(root.hasActiveFocus(), true);
1116     QCOMPARE(child1.isEnabled(), true);
1117     QCOMPARE(child1.hasFocus(), false);
1118     QCOMPARE(child1.hasActiveFocus(), false);
1119     QCOMPARE(child2.isEnabled(), false);
1120     QCOMPARE(child2.hasFocus(), true);
1121     QCOMPARE(child2.hasActiveFocus(), false);
1122     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&root));
1123
1124     root.setEnabled(false);
1125     QCOMPARE(root.isEnabled(), false);
1126     QCOMPARE(root.hasFocus(), true);
1127     QCOMPARE(root.hasActiveFocus(), false);
1128     QCOMPARE(child1.isEnabled(), false);
1129     QCOMPARE(child1.hasFocus(), false);
1130     QCOMPARE(child1.hasActiveFocus(), false);
1131     QCOMPARE(child2.isEnabled(), false);
1132     QCOMPARE(child2.hasFocus(), true);
1133     QCOMPARE(child2.hasActiveFocus(), false);
1134     QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
1135
1136     child1.forceActiveFocus();
1137     QCOMPARE(root.isEnabled(), false);
1138     QCOMPARE(root.hasFocus(), true);
1139     QCOMPARE(root.hasActiveFocus(), false);
1140     QCOMPARE(child1.isEnabled(), false);
1141     QCOMPARE(child1.hasFocus(), true);
1142     QCOMPARE(child1.hasActiveFocus(), false);
1143     QCOMPARE(child2.isEnabled(), false);
1144     QCOMPARE(child2.hasFocus(), false);
1145     QCOMPARE(child2.hasActiveFocus(), false);
1146     QCOMPARE(canvas.activeFocusItem(), canvas.rootItem());
1147
1148     root.setEnabled(true);
1149     QCOMPARE(root.isEnabled(), true);
1150     QCOMPARE(root.hasFocus(), true);
1151     QCOMPARE(root.hasActiveFocus(), true);
1152     QCOMPARE(child1.isEnabled(), true);
1153     QCOMPARE(child1.hasFocus(), true);
1154     QCOMPARE(child1.hasActiveFocus(), true);
1155     QCOMPARE(child2.isEnabled(), false);
1156     QCOMPARE(child2.hasFocus(), false);
1157     QCOMPARE(child2.hasActiveFocus(), false);
1158     QCOMPARE(canvas.activeFocusItem(), static_cast<QQuickItem *>(&child1));
1159 }
1160
1161 void tst_qquickitem::mouseGrab()
1162 {
1163     QQuickCanvas *canvas = new QQuickCanvas;
1164     canvas->resize(200, 200);
1165     canvas->show();
1166
1167     TestItem *child1 = new TestItem;
1168     child1->setAcceptedMouseButtons(Qt::LeftButton);
1169     child1->setSize(QSizeF(200, 100));
1170     child1->setParentItem(canvas->rootItem());
1171
1172     TestItem *child2 = new TestItem;
1173     child2->setAcceptedMouseButtons(Qt::LeftButton);
1174     child2->setY(51);
1175     child2->setSize(QSizeF(200, 100));
1176     child2->setParentItem(canvas->rootItem());
1177
1178     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
1179     QTest::qWait(100);
1180     QVERIFY(canvas->mouseGrabberItem() == child1);
1181     QTest::qWait(100);
1182
1183     QCOMPARE(child1->pressCount, 1);
1184     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
1185     QTest::qWait(50);
1186     QVERIFY(canvas->mouseGrabberItem() == 0);
1187     QCOMPARE(child1->releaseCount, 1);
1188
1189     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
1190     QTest::qWait(50);
1191     QVERIFY(canvas->mouseGrabberItem() == child1);
1192     QCOMPARE(child1->pressCount, 2);
1193     child1->setEnabled(false);
1194     QVERIFY(canvas->mouseGrabberItem() == 0);
1195     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
1196     QTest::qWait(50);
1197     QCOMPARE(child1->releaseCount, 1);
1198     child1->setEnabled(true);
1199
1200     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
1201     QTest::qWait(50);
1202     QVERIFY(canvas->mouseGrabberItem() == child1);
1203     QCOMPARE(child1->pressCount, 3);
1204     child1->setVisible(false);
1205     QVERIFY(canvas->mouseGrabberItem() == 0);
1206     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
1207     QCOMPARE(child1->releaseCount, 1);
1208     child1->setVisible(true);
1209
1210     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
1211     QTest::qWait(50);
1212     QVERIFY(canvas->mouseGrabberItem() == child1);
1213     QCOMPARE(child1->pressCount, 4);
1214     child2->grabMouse();
1215     QVERIFY(canvas->mouseGrabberItem() == child2);
1216     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
1217     QTest::qWait(50);
1218     QCOMPARE(child1->releaseCount, 1);
1219     QCOMPARE(child2->releaseCount, 1);
1220
1221     child2->grabMouse();
1222     QVERIFY(canvas->mouseGrabberItem() == child2);
1223     QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
1224     QTest::qWait(50);
1225     QCOMPARE(child1->pressCount, 4);
1226     QCOMPARE(child2->pressCount, 1);
1227     QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
1228     QTest::qWait(50);
1229     QCOMPARE(child1->releaseCount, 1);
1230     QCOMPARE(child2->releaseCount, 2);
1231
1232     delete child1;
1233     delete child2;
1234     delete canvas;
1235 }
1236
1237 void tst_qquickitem::touchEventAcceptIgnore_data()
1238 {
1239     QTest::addColumn<bool>("itemSupportsTouch");
1240
1241     QTest::newRow("with touch") << true;
1242     QTest::newRow("without touch") << false;
1243 }
1244
1245 void tst_qquickitem::touchEventAcceptIgnore()
1246 {
1247     QFETCH(bool, itemSupportsTouch);
1248
1249     TestCanvas *canvas = new TestCanvas;
1250     canvas->resize(100, 100);
1251     canvas->show();
1252
1253     TestItem *item = new TestItem;
1254     item->setSize(QSizeF(100, 100));
1255     item->setParentItem(canvas->rootItem());
1256     item->acceptIncomingTouchEvents = itemSupportsTouch;
1257
1258     static QTouchDevice* device = 0;
1259     if (!device) {
1260         device =new QTouchDevice;
1261         device->setType(QTouchDevice::TouchScreen);
1262         QWindowSystemInterface::registerTouchDevice(device);
1263     }
1264
1265     // Send Begin, Update & End touch sequence
1266     {
1267         QTouchEvent::TouchPoint point;
1268         point.setId(1);
1269         point.setPos(QPointF(50, 50));
1270         point.setScreenPos(point.pos());
1271         point.setState(Qt::TouchPointPressed);
1272
1273         QTouchEvent event(QEvent::TouchBegin, device,
1274                           Qt::NoModifier,
1275                           Qt::TouchPointPressed,
1276                           QList<QTouchEvent::TouchPoint>() << point);
1277         event.setAccepted(true);
1278
1279         item->touchEventReached = false;
1280
1281         bool accepted = canvas->event(&event);
1282
1283         QVERIFY(item->touchEventReached);
1284         QCOMPARE(accepted && event.isAccepted(), itemSupportsTouch);
1285     }
1286     {
1287         QTouchEvent::TouchPoint point;
1288         point.setId(1);
1289         point.setPos(QPointF(60, 60));
1290         point.setScreenPos(point.pos());
1291         point.setState(Qt::TouchPointMoved);
1292
1293         QTouchEvent event(QEvent::TouchUpdate, device,
1294                           Qt::NoModifier,
1295                           Qt::TouchPointMoved,
1296                           QList<QTouchEvent::TouchPoint>() << point);
1297         event.setAccepted(true);
1298
1299         item->touchEventReached = false;
1300
1301         bool accepted = canvas->event(&event);
1302
1303         QCOMPARE(item->touchEventReached, itemSupportsTouch);
1304         QCOMPARE(accepted && event.isAccepted(), itemSupportsTouch);
1305     }
1306     {
1307         QTouchEvent::TouchPoint point;
1308         point.setId(1);
1309         point.setPos(QPointF(60, 60));
1310         point.setScreenPos(point.pos());
1311         point.setState(Qt::TouchPointReleased);
1312
1313         QTouchEvent event(QEvent::TouchEnd, device,
1314                           Qt::NoModifier,
1315                           Qt::TouchPointReleased,
1316                           QList<QTouchEvent::TouchPoint>() << point);
1317         event.setAccepted(true);
1318
1319         item->touchEventReached = false;
1320
1321         bool accepted = canvas->event(&event);
1322
1323         QCOMPARE(item->touchEventReached, itemSupportsTouch);
1324         QCOMPARE(accepted && event.isAccepted(), itemSupportsTouch);
1325     }
1326
1327     delete item;
1328     delete canvas;
1329 }
1330
1331 void tst_qquickitem::polishOutsideAnimation()
1332 {
1333     QQuickCanvas *canvas = new QQuickCanvas;
1334     canvas->resize(200, 200);
1335     canvas->show();
1336
1337     TestPolishItem *item = new TestPolishItem(canvas->rootItem());
1338     item->setSize(QSizeF(200, 100));
1339     QTest::qWait(50);
1340
1341     QTimer::singleShot(10, item, SLOT(doPolish()));
1342     QTRY_VERIFY(item->wasPolished);
1343
1344     delete item;
1345     delete canvas;
1346 }
1347
1348 void tst_qquickitem::polishOnCompleted()
1349 {
1350     QQuickView *view = new QQuickView;
1351     view->setSource(testFileUrl("polishOnCompleted.qml"));
1352     view->show();
1353
1354     TestPolishItem *item = qobject_cast<TestPolishItem*>(view->rootObject());
1355     QVERIFY(item);
1356
1357     QTRY_VERIFY(item->wasPolished);
1358
1359     delete view;
1360 }
1361
1362 void tst_qquickitem::wheelEvent_data()
1363 {
1364     QTest::addColumn<bool>("visible");
1365     QTest::addColumn<bool>("enabled");
1366
1367     QTest::newRow("visible and enabled") << true << true;
1368     QTest::newRow("visible and disabled") << true << false;
1369     QTest::newRow("invisible and enabled") << false << true;
1370     QTest::newRow("invisible and disabled") << false << false;
1371 }
1372
1373 void tst_qquickitem::wheelEvent()
1374 {
1375     QFETCH(bool, visible);
1376     QFETCH(bool, enabled);
1377
1378     const bool shouldReceiveWheelEvents = visible && enabled;
1379
1380     QQuickCanvas *canvas = new QQuickCanvas;
1381     canvas->resize(200, 200);
1382     canvas->show();
1383
1384     TestItem *item = new TestItem;
1385     item->setSize(QSizeF(200, 100));
1386     item->setParentItem(canvas->rootItem());
1387
1388     item->setEnabled(enabled);
1389     item->setVisible(visible);
1390
1391     QWheelEvent event(QPoint(100, 50), -120, Qt::NoButton, Qt::NoModifier, Qt::Vertical);
1392     event.setAccepted(false);
1393     QGuiApplication::sendEvent(canvas, &event);
1394
1395     if (shouldReceiveWheelEvents) {
1396         QVERIFY(event.isAccepted());
1397         QCOMPARE(item->wheelCount, 1);
1398     } else {
1399         QVERIFY(!event.isAccepted());
1400         QCOMPARE(item->wheelCount, 0);
1401     }
1402
1403     delete canvas;
1404 }
1405
1406 class HoverItem : public QQuickItem
1407 {
1408 Q_OBJECT
1409 public:
1410     HoverItem(QQuickItem *parent = 0)
1411         : QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0)
1412     { }
1413     void resetCounters() {
1414         hoverEnterCount = 0;
1415         hoverMoveCount = 0;
1416         hoverLeaveCount = 0;
1417     }
1418     int hoverEnterCount;
1419     int hoverMoveCount;
1420     int hoverLeaveCount;
1421 protected:
1422     virtual void hoverEnterEvent(QHoverEvent *event) {
1423         event->accept();
1424         ++hoverEnterCount;
1425     }
1426     virtual void hoverMoveEvent(QHoverEvent *event) {
1427         event->accept();
1428         ++hoverMoveCount;
1429     }
1430     virtual void hoverLeaveEvent(QHoverEvent *event) {
1431         event->accept();
1432         ++hoverLeaveCount;
1433     }
1434 };
1435
1436 void tst_qquickitem::hoverEvent_data()
1437 {
1438     QTest::addColumn<bool>("visible");
1439     QTest::addColumn<bool>("enabled");
1440     QTest::addColumn<bool>("acceptHoverEvents");
1441
1442     QTest::newRow("visible, enabled, accept hover") << true << true << true;
1443     QTest::newRow("visible, disabled, accept hover") << true << false << true;
1444     QTest::newRow("invisible, enabled, accept hover") << false << true << true;
1445     QTest::newRow("invisible, disabled, accept hover") << false << false << true;
1446
1447     QTest::newRow("visible, enabled, not accept hover") << true << true << false;
1448     QTest::newRow("visible, disabled, not accept hover") << true << false << false;
1449     QTest::newRow("invisible, enabled, not accept hover") << false << true << false;
1450     QTest::newRow("invisible, disabled, not accept hover") << false << false << false;
1451 }
1452
1453 // ### For some unknown reason QTest::mouseMove() isn't working correctly.
1454 static void sendMouseMove(QObject *object, const QPoint &position)
1455 {
1456     QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, 0);
1457     QGuiApplication::sendEvent(object, &moveEvent);
1458 }
1459
1460 void tst_qquickitem::hoverEvent()
1461 {
1462     QFETCH(bool, visible);
1463     QFETCH(bool, enabled);
1464     QFETCH(bool, acceptHoverEvents);
1465
1466     QQuickCanvas *canvas = new QQuickCanvas();
1467     canvas->resize(200, 200);
1468     canvas->show();
1469
1470     HoverItem *item = new HoverItem;
1471     item->setSize(QSizeF(100, 100));
1472     item->setParentItem(canvas->rootItem());
1473
1474     item->setEnabled(enabled);
1475     item->setVisible(visible);
1476     item->setAcceptHoverEvents(acceptHoverEvents);
1477
1478     const QPoint outside(150, 150);
1479     const QPoint inside(50, 50);
1480     const QPoint anotherInside(51, 51);
1481
1482     sendMouseMove(canvas, outside);
1483     item->resetCounters();
1484
1485     // Enter, then move twice inside, then leave.
1486     sendMouseMove(canvas, inside);
1487     sendMouseMove(canvas, anotherInside);
1488     sendMouseMove(canvas, inside);
1489     sendMouseMove(canvas, outside);
1490
1491     const bool shouldReceiveHoverEvents = visible && enabled && acceptHoverEvents;
1492     if (shouldReceiveHoverEvents) {
1493         QCOMPARE(item->hoverEnterCount, 1);
1494         QCOMPARE(item->hoverMoveCount, 2);
1495         QCOMPARE(item->hoverLeaveCount, 1);
1496     } else {
1497         QCOMPARE(item->hoverEnterCount, 0);
1498         QCOMPARE(item->hoverMoveCount, 0);
1499         QCOMPARE(item->hoverLeaveCount, 0);
1500     }
1501
1502     delete canvas;
1503 }
1504
1505 void tst_qquickitem::hoverEventInParent()
1506 {
1507     QQuickCanvas *canvas = new QQuickCanvas();
1508     canvas->resize(200, 200);
1509     canvas->show();
1510
1511     HoverItem *parentItem = new HoverItem(canvas->rootItem());
1512     parentItem->setSize(QSizeF(200, 200));
1513     parentItem->setAcceptHoverEvents(true);
1514
1515     HoverItem *leftItem = new HoverItem(parentItem);
1516     leftItem->setSize(QSizeF(100, 200));
1517     leftItem->setAcceptHoverEvents(true);
1518
1519     HoverItem *rightItem = new HoverItem(parentItem);
1520     rightItem->setSize(QSizeF(100, 200));
1521     rightItem->setPos(QPointF(100, 0));
1522     rightItem->setAcceptHoverEvents(true);
1523
1524     const QPoint insideLeft(50, 100);
1525     const QPoint insideRight(150, 100);
1526
1527     sendMouseMove(canvas, insideLeft);
1528     parentItem->resetCounters();
1529     leftItem->resetCounters();
1530     rightItem->resetCounters();
1531
1532     sendMouseMove(canvas, insideRight);
1533     QCOMPARE(parentItem->hoverEnterCount, 0);
1534     QCOMPARE(parentItem->hoverLeaveCount, 0);
1535     QCOMPARE(leftItem->hoverEnterCount, 0);
1536     QCOMPARE(leftItem->hoverLeaveCount, 1);
1537     QCOMPARE(rightItem->hoverEnterCount, 1);
1538     QCOMPARE(rightItem->hoverLeaveCount, 0);
1539
1540     sendMouseMove(canvas, insideLeft);
1541     QCOMPARE(parentItem->hoverEnterCount, 0);
1542     QCOMPARE(parentItem->hoverLeaveCount, 0);
1543     QCOMPARE(leftItem->hoverEnterCount, 1);
1544     QCOMPARE(leftItem->hoverLeaveCount, 1);
1545     QCOMPARE(rightItem->hoverEnterCount, 1);
1546     QCOMPARE(rightItem->hoverLeaveCount, 1);
1547
1548     delete canvas;
1549 }
1550
1551 void tst_qquickitem::paintOrder_data()
1552 {
1553     const QUrl order1Url = testFileUrl("order.1.qml");
1554     const QUrl order2Url = testFileUrl("order.2.qml");
1555
1556     QTest::addColumn<QUrl>("source");
1557     QTest::addColumn<int>("op");
1558     QTest::addColumn<QVariant>("param1");
1559     QTest::addColumn<QVariant>("param2");
1560     QTest::addColumn<QStringList>("expected");
1561
1562     QTest::newRow("test 1 noop") << order1Url
1563         << int(NoOp) << QVariant() << QVariant()
1564         << (QStringList() << "1" << "2" << "3");
1565     QTest::newRow("test 1 add") << order1Url
1566         << int(Append) << QVariant("new") << QVariant()
1567         << (QStringList() << "1" << "2" << "3" << "new");
1568     QTest::newRow("test 1 remove") << order1Url
1569         << int(Remove) << QVariant(1) << QVariant()
1570         << (QStringList() << "1" << "3");
1571     QTest::newRow("test 1 stack before") << order1Url
1572         << int(StackBefore) << QVariant(2) << QVariant(1)
1573         << (QStringList() << "1" << "3" << "2");
1574     QTest::newRow("test 1 stack after") << order1Url
1575         << int(StackAfter) << QVariant(0) << QVariant(1)
1576         << (QStringList() << "2" << "1" << "3");
1577     QTest::newRow("test 1 set z") << order1Url
1578         << int(SetZ) << QVariant(1) << QVariant(qreal(1.))
1579         << (QStringList() << "1" << "3" << "2");
1580
1581     QTest::newRow("test 2 noop") << order2Url
1582         << int(NoOp) << QVariant() << QVariant()
1583         << (QStringList() << "1" << "3" << "2");
1584     QTest::newRow("test 2 add") << order2Url
1585         << int(Append) << QVariant("new") << QVariant()
1586         << (QStringList() << "1" << "3" << "new" << "2");
1587     QTest::newRow("test 2 remove 1") << order2Url
1588         << int(Remove) << QVariant(1) << QVariant()
1589         << (QStringList() << "1" << "3");
1590     QTest::newRow("test 2 remove 2") << order2Url
1591         << int(Remove) << QVariant(2) << QVariant()
1592         << (QStringList() << "1" << "2");
1593     QTest::newRow("test 2 stack before 1") << order2Url
1594         << int(StackBefore) << QVariant(1) << QVariant(0)
1595         << (QStringList() << "1" << "3" << "2");
1596     QTest::newRow("test 2 stack before 2") << order2Url
1597         << int(StackBefore) << QVariant(2) << QVariant(0)
1598         << (QStringList() << "3" << "1" << "2");
1599     QTest::newRow("test 2 stack after 1") << order2Url
1600         << int(StackAfter) << QVariant(0) << QVariant(1)
1601         << (QStringList() << "1" << "3" << "2");
1602     QTest::newRow("test 2 stack after 2") << order2Url
1603         << int(StackAfter) << QVariant(0) << QVariant(2)
1604         << (QStringList() << "3" << "1" << "2");
1605     QTest::newRow("test 1 set z") << order1Url
1606         << int(SetZ) << QVariant(2) << QVariant(qreal(2.))
1607         << (QStringList() << "1" << "2" << "3");
1608 }
1609
1610 void tst_qquickitem::paintOrder()
1611 {
1612     QFETCH(QUrl, source);
1613     QFETCH(int, op);
1614     QFETCH(QVariant, param1);
1615     QFETCH(QVariant, param2);
1616     QFETCH(QStringList, expected);
1617
1618     QQuickView view;
1619     view.setSource(source);
1620
1621     QQuickItem *root = qobject_cast<QQuickItem*>(view.rootObject());
1622     QVERIFY(root);
1623
1624     switch (op) {
1625         case Append: {
1626                 QQuickItem *item = new QQuickItem(root);
1627                 item->setObjectName(param1.toString());
1628             }
1629             break;
1630         case Remove: {
1631                 QQuickItem *item = root->childItems().at(param1.toInt());
1632                 delete item;
1633             }
1634             break;
1635         case StackBefore: {
1636                 QQuickItem *item1 = root->childItems().at(param1.toInt());
1637                 QQuickItem *item2 = root->childItems().at(param2.toInt());
1638                 item1->stackBefore(item2);
1639             }
1640             break;
1641         case StackAfter: {
1642                 QQuickItem *item1 = root->childItems().at(param1.toInt());
1643                 QQuickItem *item2 = root->childItems().at(param2.toInt());
1644                 item1->stackAfter(item2);
1645             }
1646             break;
1647         case SetZ: {
1648                 QQuickItem *item = root->childItems().at(param1.toInt());
1649                 item->setZ(param2.toReal());
1650             }
1651             break;
1652         default:
1653             break;
1654     }
1655
1656     QList<QQuickItem*> list = QQuickItemPrivate::get(root)->paintOrderChildItems();
1657
1658     QStringList items;
1659     for (int i = 0; i < list.count(); ++i)
1660         items << list.at(i)->objectName();
1661
1662     QCOMPARE(items, expected);
1663 }
1664
1665 void tst_qquickitem::acceptedMouseButtons()
1666 {
1667     TestItem item;
1668     QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::NoButton));
1669
1670     QQuickCanvas canvas;
1671     item.setSize(QSizeF(200,100));
1672     item.setParentItem(canvas.rootItem());
1673
1674     QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(50, 50));
1675     QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(50, 50));
1676     QCOMPARE(item.pressCount, 0);
1677     QCOMPARE(item.releaseCount, 0);
1678
1679     QTest::mousePress(&canvas, Qt::RightButton, 0, QPoint(50, 50));
1680     QTest::mouseRelease(&canvas, Qt::RightButton, 0, QPoint(50, 50));
1681     QCOMPARE(item.pressCount, 0);
1682     QCOMPARE(item.releaseCount, 0);
1683
1684     QTest::mousePress(&canvas, Qt::MiddleButton, 0, QPoint(50, 50));
1685     QTest::mouseRelease(&canvas, Qt::MiddleButton, 0, QPoint(50, 50));
1686     QCOMPARE(item.pressCount, 0);
1687     QCOMPARE(item.releaseCount, 0);
1688
1689     item.setAcceptedMouseButtons(Qt::LeftButton);
1690     QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::LeftButton));
1691
1692     QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(50, 50));
1693     QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(50, 50));
1694     QCOMPARE(item.pressCount, 1);
1695     QCOMPARE(item.releaseCount, 1);
1696
1697     QTest::mousePress(&canvas, Qt::RightButton, 0, QPoint(50, 50));
1698     QTest::mouseRelease(&canvas, Qt::RightButton, 0, QPoint(50, 50));
1699     QCOMPARE(item.pressCount, 1);
1700     QCOMPARE(item.releaseCount, 1);
1701
1702     QTest::mousePress(&canvas, Qt::MiddleButton, 0, QPoint(50, 50));
1703     QTest::mouseRelease(&canvas, Qt::MiddleButton, 0, QPoint(50, 50));
1704     QCOMPARE(item.pressCount, 1);
1705     QCOMPARE(item.releaseCount, 1);
1706
1707     item.setAcceptedMouseButtons(Qt::RightButton | Qt::MiddleButton);
1708     QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::RightButton | Qt::MiddleButton));
1709
1710     QTest::mousePress(&canvas, Qt::LeftButton, 0, QPoint(50, 50));
1711     QTest::mouseRelease(&canvas, Qt::LeftButton, 0, QPoint(50, 50));
1712     QCOMPARE(item.pressCount, 1);
1713     QCOMPARE(item.releaseCount, 1);
1714
1715     QTest::mousePress(&canvas, Qt::RightButton, 0, QPoint(50, 50));
1716     QTest::mouseRelease(&canvas, Qt::RightButton, 0, QPoint(50, 50));
1717     QCOMPARE(item.pressCount, 2);
1718     QCOMPARE(item.releaseCount, 2);
1719
1720     QTest::mousePress(&canvas, Qt::MiddleButton, 0, QPoint(50, 50));
1721     QTest::mouseRelease(&canvas, Qt::MiddleButton, 0, QPoint(50, 50));
1722     QCOMPARE(item.pressCount, 3);
1723     QCOMPARE(item.releaseCount, 3);
1724 }
1725
1726
1727 QTEST_MAIN(tst_qquickitem)
1728
1729 #include "tst_qquickitem.moc"