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