1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the test suite of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
45 #include "qsgcanvas.h"
46 #include "private/qsgfocusscope_p.h"
49 class TestItem : public QSGItem
53 TestItem(QSGItem *parent = 0) : QSGItem(parent), focused(false), pressCount(0), releaseCount(0) {}
59 virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
60 virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
61 virtual void mousePressEvent(QGraphicsSceneMouseEvent *event) { event->accept(); ++pressCount; }
62 virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { event->accept(); ++releaseCount; }
65 class TestFocusScope : public QSGFocusScope
69 TestFocusScope(QSGItem *parent = 0) : QSGFocusScope(parent), focused(false) {}
73 virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; }
74 virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; }
77 class tst_qsgitem : public QObject
85 void cleanupTestCase();
102 void ensureFocus(QWidget *w) {
104 qApp->setActiveWindow(w);
105 qApp->processEvents();
108 // to be safe and avoid failing setFocus with window managers
109 qt_x11_wait_for_window_manager(w);
114 tst_qsgitem::tst_qsgitem()
118 void tst_qsgitem::initTestCase()
122 void tst_qsgitem::cleanupTestCase()
126 // Focus has no effect when outside a canvas
127 void tst_qsgitem::noCanvas()
129 QSGItem *root = new TestItem;
130 QSGItem *child = new TestItem(root);
131 QSGItem *scope = new TestItem(root);
132 QSGFocusScope *scopedChild = new TestFocusScope(scope);
133 QSGFocusScope *scopedChild2 = new TestFocusScope(scope);
135 QCOMPARE(root->hasFocus(), false);
136 QCOMPARE(child->hasFocus(), false);
137 QCOMPARE(scope->hasFocus(), false);
138 QCOMPARE(scopedChild->hasFocus(), false);
139 QCOMPARE(scopedChild2->hasFocus(), false);
141 root->setFocus(true);
142 scope->setFocus(true);
143 scopedChild2->setFocus(true);
144 QCOMPARE(root->hasFocus(), true);
145 QCOMPARE(child->hasFocus(), false);
146 QCOMPARE(scope->hasFocus(), true);
147 QCOMPARE(scopedChild->hasFocus(), false);
148 QCOMPARE(scopedChild2->hasFocus(), true);
150 root->setFocus(false);
151 child->setFocus(true);
152 scopedChild->setFocus(true);
153 scope->setFocus(false);
154 QCOMPARE(root->hasFocus(), false);
155 QCOMPARE(child->hasFocus(), true);
156 QCOMPARE(scope->hasFocus(), false);
157 QCOMPARE(scopedChild->hasFocus(), true);
158 QCOMPARE(scopedChild2->hasFocus(), true);
164 FocusData() : focus(false), activeFocus(false) {}
166 void set(bool f, bool af) { focus = f; activeFocus = af; }
170 struct FocusState : public QHash<QSGItem *, FocusData>
172 FocusState() : activeFocusItem(0) {}
173 FocusState &operator<<(QSGItem *item) {
174 insert(item, FocusData());
178 void active(QSGItem *i) {
181 QSGItem *activeFocusItem;
186 if (focusState.activeFocusItem) { \
187 QCOMPARE(canvas.activeFocusItem(), focusState.activeFocusItem); \
188 if (qobject_cast<TestItem *>(canvas.activeFocusItem())) \
189 QCOMPARE(qobject_cast<TestItem *>(canvas.activeFocusItem())->focused, true); \
190 else if (qobject_cast<TestFocusScope *>(canvas.activeFocusItem())) \
191 QCOMPARE(qobject_cast<TestFocusScope *>(canvas.activeFocusItem())->focused, true); \
193 QCOMPARE(canvas.activeFocusItem(), canvas.rootItem()); \
195 for(QHash<QSGItem *, FocusData>::Iterator iter = focusState.begin(); \
196 iter != focusState.end(); \
198 QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \
199 QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \
203 // Tests a simple set of top-level scoped items
204 void tst_qsgitem::simpleFocus()
207 ensureFocus(&canvas);
209 QSGItem *l1c1 = new TestItem(canvas.rootItem());
210 QSGItem *l1c2 = new TestItem(canvas.rootItem());
211 QSGItem *l1c3 = new TestItem(canvas.rootItem());
213 QSGItem *l2c1 = new TestItem(l1c1);
214 QSGItem *l2c2 = new TestItem(l1c1);
215 QSGItem *l2c3 = new TestItem(l1c3);
217 FocusState focusState;
218 focusState << l1c1 << l1c2 << l1c3
219 << l2c1 << l2c2 << l2c3;
222 l1c1->setFocus(true);
223 focusState[l1c1].set(true, true);
224 focusState.active(l1c1);
227 l2c3->setFocus(true);
228 focusState[l1c1].set(false, false);
229 focusState[l2c3].set(true, true);
230 focusState.active(l2c3);
233 l1c3->setFocus(true);
234 focusState[l2c3].set(false, false);
235 focusState[l1c3].set(true, true);
236 focusState.active(l1c3);
239 l1c2->setFocus(false);
242 l1c3->setFocus(false);
243 focusState[l1c3].set(false, false);
244 focusState.active(0);
247 l2c1->setFocus(true);
248 focusState[l2c1].set(true, true);
249 focusState.active(l2c1);
253 // Items with a focus scope
254 void tst_qsgitem::scopedFocus()
257 ensureFocus(&canvas);
259 QSGItem *l1c1 = new TestItem(canvas.rootItem());
260 QSGItem *l1c2 = new TestItem(canvas.rootItem());
261 QSGItem *l1c3 = new TestItem(canvas.rootItem());
263 QSGItem *l2c1 = new TestItem(l1c1);
264 QSGItem *l2c2 = new TestItem(l1c1);
265 QSGItem *l2c3 = new TestFocusScope(l1c3);
267 QSGItem *l3c1 = new TestItem(l2c3);
268 QSGItem *l3c2 = new TestFocusScope(l2c3);
270 QSGItem *l4c1 = new TestItem(l3c2);
271 QSGItem *l4c2 = new TestItem(l3c2);
273 FocusState focusState;
274 focusState << l1c1 << l1c2 << l1c3
275 << l2c1 << l2c2 << l2c3
280 l4c2->setFocus(true);
281 focusState[l4c2].set(true, false);
284 l4c1->setFocus(true);
285 focusState[l4c2].set(false, false);
286 focusState[l4c1].set(true, false);
289 l1c1->setFocus(true);
290 focusState[l1c1].set(true, true);
291 focusState.active(l1c1);
294 l3c2->setFocus(true);
295 focusState[l3c2].set(true, false);
298 l2c3->setFocus(true);
299 focusState[l1c1].set(false, false);
300 focusState[l2c3].set(true, true);
301 focusState[l3c2].set(true, true);
302 focusState[l4c1].set(true, true);
303 focusState.active(l4c1);
306 l3c2->setFocus(false);
307 focusState[l3c2].set(false, false);
308 focusState[l4c1].set(true, false);
309 focusState.active(l2c3);
312 l3c2->setFocus(true);
313 focusState[l3c2].set(true, true);
314 focusState[l4c1].set(true, true);
315 focusState.active(l4c1);
318 l4c1->setFocus(false);
319 focusState[l4c1].set(false, false);
320 focusState.active(l3c2);
323 l1c3->setFocus(true);
324 focusState[l1c3].set(true, true);
325 focusState[l2c3].set(false, false);
326 focusState[l3c2].set(true, false);
327 focusState.active(l1c3);
331 // Tests focus corrects itself when a tree is added to a canvas for the first time
332 void tst_qsgitem::addedToCanvas()
336 ensureFocus(&canvas);
338 QSGItem *item = new TestItem;
340 FocusState focusState;
343 item->setFocus(true);
344 focusState[item].set(true, false);
347 item->setParentItem(canvas.rootItem());
348 focusState[item].set(true, true);
349 focusState.active(item);
355 ensureFocus(&canvas);
357 QSGItem *item = new TestItem(canvas.rootItem());
359 QSGItem *tree = new TestItem;
360 QSGItem *c1 = new TestItem(tree);
361 QSGItem *c2 = new TestItem(tree);
363 FocusState focusState;
364 focusState << item << tree << c1 << c2;
366 item->setFocus(true);
369 focusState[item].set(true, true);
370 focusState[c1].set(true, false);
371 focusState[c2].set(true, false);
372 focusState.active(item);
375 tree->setParentItem(item);
376 focusState[c1].set(false, false);
377 focusState[c2].set(false, false);
383 ensureFocus(&canvas);
385 QSGItem *tree = new TestItem;
386 QSGItem *c1 = new TestItem(tree);
387 QSGItem *c2 = new TestItem(tree);
389 FocusState focusState;
390 focusState << tree << c1 << c2;
393 focusState[c1].set(true, false);
394 focusState[c2].set(true, false);
397 tree->setParentItem(canvas.rootItem());
398 focusState[c1].set(true, true);
399 focusState[c2].set(false, false);
400 focusState.active(c1);
406 ensureFocus(&canvas);
407 QSGItem *tree = new TestFocusScope;
408 QSGItem *c1 = new TestItem(tree);
409 QSGItem *c2 = new TestItem(tree);
411 FocusState focusState;
412 focusState << tree << c1 << c2;
415 focusState[c1].set(true, false);
416 focusState[c2].set(true, false);
419 tree->setParentItem(canvas.rootItem());
420 focusState[c1].set(true, false);
421 focusState[c2].set(false, false);
424 tree->setFocus(true);
425 focusState[tree].set(true, true);
426 focusState[c1].set(true, true);
427 focusState.active(c1);
433 ensureFocus(&canvas);
434 QSGItem *tree = new TestFocusScope;
435 QSGItem *c1 = new TestItem(tree);
436 QSGItem *c2 = new TestItem(tree);
438 FocusState focusState;
439 focusState << tree << c1 << c2;
440 tree->setFocus(true);
443 focusState[tree].set(true, false);
444 focusState[c1].set(true, false);
445 focusState[c2].set(true, false);
448 tree->setParentItem(canvas.rootItem());
449 focusState[tree].set(true, true);
450 focusState[c1].set(true, true);
451 focusState[c2].set(false, false);
452 focusState.active(c1);
458 ensureFocus(&canvas);
459 QSGItem *child = new TestItem(canvas.rootItem());
460 QSGItem *tree = new TestFocusScope;
461 QSGItem *c1 = new TestItem(tree);
462 QSGItem *c2 = new TestItem(tree);
464 FocusState focusState;
465 focusState << child << tree << c1 << c2;
466 child->setFocus(true);
467 tree->setFocus(true);
470 focusState[child].set(true, true);
471 focusState[tree].set(true, false);
472 focusState[c1].set(true, false);
473 focusState[c2].set(true, false);
474 focusState.active(child);
477 tree->setParentItem(canvas.rootItem());
478 focusState[tree].set(false, false);
479 focusState[c1].set(true, false);
480 focusState[c2].set(false, false);
483 tree->setFocus(true);
484 focusState[child].set(false, false);
485 focusState[tree].set(true, true);
486 focusState[c1].set(true, true);
487 focusState.active(c1);
492 void tst_qsgitem::changeParent()
494 // Parent to no parent
497 ensureFocus(&canvas);
498 QSGItem *child = new TestItem(canvas.rootItem());
500 FocusState focusState;
504 child->setFocus(true);
505 focusState[child].set(true, true);
506 focusState.active(child);
509 child->setParentItem(0);
510 focusState[child].set(true, false);
511 focusState.active(0);
515 // Different parent, same focus scope
518 ensureFocus(&canvas);
519 QSGItem *child = new TestItem(canvas.rootItem());
520 QSGItem *child2 = new TestItem(canvas.rootItem());
522 FocusState focusState;
523 focusState << child << child2;
526 child->setFocus(true);
527 focusState[child].set(true, true);
528 focusState.active(child);
531 child->setParentItem(child2);
535 // Different parent, different focus scope
538 ensureFocus(&canvas);
539 QSGItem *child = new TestItem(canvas.rootItem());
540 QSGItem *child2 = new TestFocusScope(canvas.rootItem());
541 QSGItem *item = new TestItem(child);
543 FocusState focusState;
544 focusState << child << child2 << item;
547 item->setFocus(true);
548 focusState[item].set(true, true);
549 focusState.active(item);
552 item->setParentItem(child2);
553 focusState[item].set(true, false);
554 focusState.active(0);
559 ensureFocus(&canvas);
560 QSGItem *child = new TestItem(canvas.rootItem());
561 QSGItem *child2 = new TestFocusScope(canvas.rootItem());
562 QSGItem *item = new TestItem(child2);
564 FocusState focusState;
565 focusState << child << child2 << item;
568 item->setFocus(true);
569 focusState[item].set(true, false);
570 focusState.active(0);
573 item->setParentItem(child);
574 focusState[item].set(true, true);
575 focusState.active(item);
580 ensureFocus(&canvas);
581 QSGItem *child = new TestItem(canvas.rootItem());
582 QSGItem *child2 = new TestFocusScope(canvas.rootItem());
583 QSGItem *item = new TestItem(child2);
585 FocusState focusState;
586 focusState << child << child2 << item;
589 child->setFocus(true);
590 item->setFocus(true);
591 focusState[child].set(true, true);
592 focusState[item].set(true, false);
593 focusState.active(child);
596 item->setParentItem(child);
597 focusState[item].set(false, false);
603 void tst_qsgitem::constructor()
605 QSGItem *root = new QSGItem;
606 QVERIFY(root->parent() == 0);
607 QVERIFY(root->parentItem() == 0);
609 QSGItem *child1 = new QSGItem(root);
610 QVERIFY(child1->parent() == root);
611 QVERIFY(child1->parentItem() == root);
612 QCOMPARE(root->childItems().count(), 1);
613 QCOMPARE(root->childItems().at(0), child1);
615 QSGItem *child2 = new QSGItem(root);
616 QVERIFY(child2->parent() == root);
617 QVERIFY(child2->parentItem() == root);
618 QCOMPARE(root->childItems().count(), 2);
619 QCOMPARE(root->childItems().at(0), child1);
620 QCOMPARE(root->childItems().at(1), child2);
625 void tst_qsgitem::setParentItem()
627 QSGItem *root = new QSGItem;
628 QVERIFY(root->parent() == 0);
629 QVERIFY(root->parentItem() == 0);
631 QSGItem *child1 = new QSGItem;
632 QVERIFY(child1->parent() == 0);
633 QVERIFY(child1->parentItem() == 0);
635 child1->setParentItem(root);
636 QVERIFY(child1->parent() == 0);
637 QVERIFY(child1->parentItem() == root);
638 QCOMPARE(root->childItems().count(), 1);
639 QCOMPARE(root->childItems().at(0), child1);
641 QSGItem *child2 = new QSGItem;
642 QVERIFY(child2->parent() == 0);
643 QVERIFY(child2->parentItem() == 0);
644 child2->setParentItem(root);
645 QVERIFY(child2->parent() == 0);
646 QVERIFY(child2->parentItem() == root);
647 QCOMPARE(root->childItems().count(), 2);
648 QCOMPARE(root->childItems().at(0), child1);
649 QCOMPARE(root->childItems().at(1), child2);
651 child1->setParentItem(0);
652 QVERIFY(child1->parent() == 0);
653 QVERIFY(child1->parentItem() == 0);
654 QCOMPARE(root->childItems().count(), 1);
655 QCOMPARE(root->childItems().at(0), child2);
659 QVERIFY(child1->parent() == 0);
660 QVERIFY(child1->parentItem() == 0);
661 QVERIFY(child2->parent() == 0);
662 QVERIFY(child2->parentItem() == 0);
668 void tst_qsgitem::visible()
670 QSGItem *root = new QSGItem;
672 QSGItem *child1 = new QSGItem;
673 child1->setParentItem(root);
675 QSGItem *child2 = new QSGItem;
676 child2->setParentItem(root);
678 QVERIFY(child1->isVisible());
679 QVERIFY(child2->isVisible());
681 root->setVisible(false);
682 QVERIFY(!child1->isVisible());
683 QVERIFY(!child2->isVisible());
685 root->setVisible(true);
686 QVERIFY(child1->isVisible());
687 QVERIFY(child2->isVisible());
689 child1->setVisible(false);
690 QVERIFY(!child1->isVisible());
691 QVERIFY(child2->isVisible());
693 child2->setParentItem(child1);
694 QVERIFY(!child1->isVisible());
695 QVERIFY(!child2->isVisible());
697 child2->setParentItem(root);
698 QVERIFY(!child1->isVisible());
699 QVERIFY(child2->isVisible());
706 void tst_qsgitem::enabled()
708 QSGItem *root = new QSGItem;
710 QSGItem *child1 = new QSGItem;
711 child1->setParentItem(root);
713 QSGItem *child2 = new QSGItem;
714 child2->setParentItem(root);
716 QVERIFY(child1->isEnabled());
717 QVERIFY(child2->isEnabled());
719 root->setEnabled(false);
720 QVERIFY(!child1->isEnabled());
721 QVERIFY(!child2->isEnabled());
723 root->setEnabled(true);
724 QVERIFY(child1->isEnabled());
725 QVERIFY(child2->isEnabled());
727 child1->setEnabled(false);
728 QVERIFY(!child1->isEnabled());
729 QVERIFY(child2->isEnabled());
731 child2->setParentItem(child1);
732 QVERIFY(!child1->isEnabled());
733 QVERIFY(!child2->isEnabled());
735 child2->setParentItem(root);
736 QVERIFY(!child1->isEnabled());
737 QVERIFY(child2->isEnabled());
744 void tst_qsgitem::mouseGrab()
746 QSGCanvas *canvas = new QSGCanvas;
747 canvas->resize(200, 200);
750 TestItem *child1 = new TestItem;
751 child1->setAcceptedMouseButtons(Qt::LeftButton);
752 child1->setSize(QSizeF(200, 100));
753 child1->setParentItem(canvas->rootItem());
755 TestItem *child2 = new TestItem;
756 child2->setAcceptedMouseButtons(Qt::LeftButton);
758 child2->setSize(QSizeF(200, 100));
759 child2->setParentItem(canvas->rootItem());
761 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
762 QVERIFY(canvas->mouseGrabberItem() == child1);
763 QCOMPARE(child1->pressCount, 1);
764 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
765 QVERIFY(canvas->mouseGrabberItem() == 0);
766 QCOMPARE(child1->releaseCount, 1);
768 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
769 QVERIFY(canvas->mouseGrabberItem() == child1);
770 QCOMPARE(child1->pressCount, 2);
771 child1->setEnabled(false);
772 QVERIFY(canvas->mouseGrabberItem() == 0);
773 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
774 QCOMPARE(child1->releaseCount, 1);
775 child1->setEnabled(true);
777 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
778 QVERIFY(canvas->mouseGrabberItem() == child1);
779 QCOMPARE(child1->pressCount, 3);
780 child1->setVisible(false);
781 QVERIFY(canvas->mouseGrabberItem() == 0);
782 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
783 QCOMPARE(child1->releaseCount, 1);
784 child1->setVisible(true);
786 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
787 QVERIFY(canvas->mouseGrabberItem() == child1);
788 QCOMPARE(child1->pressCount, 4);
790 QVERIFY(canvas->mouseGrabberItem() == child2);
791 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
792 QCOMPARE(child1->releaseCount, 1);
793 QCOMPARE(child2->releaseCount, 1);
796 QVERIFY(canvas->mouseGrabberItem() == child2);
797 QTest::mousePress(canvas, Qt::LeftButton, 0, QPoint(50,50));
798 QCOMPARE(child1->pressCount, 4);
799 QCOMPARE(child2->pressCount, 1);
800 QTest::mouseRelease(canvas, Qt::LeftButton, 0, QPoint(50,50));
801 QCOMPARE(child1->releaseCount, 1);
802 QCOMPARE(child2->releaseCount, 2);
810 QTEST_MAIN(tst_qsgitem)
812 #include "tst_qsgitem.moc"