| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2016 The Qt Company Ltd. | 
| 4 | ** Contact: https://www.qt.io/licensing/ | 
| 5 | ** | 
| 6 | ** This file is part of the test suite of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see https://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at https://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU | 
| 19 | ** General Public License version 3 as published by the Free Software | 
| 20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT | 
| 21 | ** included in the packaging of this file. Please review the following | 
| 22 | ** information to ensure the GNU General Public License requirements will | 
| 23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. | 
| 24 | ** | 
| 25 | ** $QT_END_LICENSE$ | 
| 26 | ** | 
| 27 | ****************************************************************************/ | 
| 28 |  | 
| 29 | #include <qtest.h> | 
| 30 |  | 
| 31 | #include <QtQuick/qquickitem.h> | 
| 32 | #include <QtQuick/qquickwindow.h> | 
| 33 | #include <QtQuick/qquickview.h> | 
| 34 | #include "private/qquickfocusscope_p.h" | 
| 35 | #include "private/qquickitem_p.h" | 
| 36 | #include <qpa/qwindowsysteminterface.h> | 
| 37 | #include <QDebug> | 
| 38 | #include <QTimer> | 
| 39 | #include <QQmlEngine> | 
| 40 | #include "../../shared/util.h" | 
| 41 | #include "../shared/viewtestutil.h" | 
| 42 | #include <QSignalSpy> | 
| 43 | #include <QTranslator> | 
| 44 | #include <QtCore/qregularexpression.h> | 
| 45 |  | 
| 46 | #ifdef TEST_QTBUG_60123 | 
| 47 | #include <QWidget> | 
| 48 | #include <QMainWindow> | 
| 49 | #endif | 
| 50 |  | 
| 51 | class TestItem : public QQuickItem | 
| 52 | { | 
| 53 | Q_OBJECT | 
| 54 | public: | 
| 55 |     TestItem(QQuickItem *parent = nullptr) | 
| 56 |         : QQuickItem(parent), focused(false), pressCount(0), releaseCount(0) | 
| 57 |         , wheelCount(0), acceptIncomingTouchEvents(true) | 
| 58 |         , touchEventReached(false), timestamp(0) | 
| 59 |         , lastWheelEventPos(0, 0), lastWheelEventGlobalPos(0, 0) | 
| 60 |     { | 
| 61 | #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) | 
| 62 |         setAcceptTouchEvents(true); | 
| 63 | #endif | 
| 64 |     } | 
| 65 |  | 
| 66 |     bool focused; | 
| 67 |     int pressCount; | 
| 68 |     int releaseCount; | 
| 69 |     int wheelCount; | 
| 70 |     bool acceptIncomingTouchEvents; | 
| 71 |     bool touchEventReached; | 
| 72 |     ulong timestamp; | 
| 73 |     QPoint lastWheelEventPos; | 
| 74 |     QPoint lastWheelEventGlobalPos; | 
| 75 |     int languageChangeEventCount = 0; | 
| 76 | protected: | 
| 77 |     void focusInEvent(QFocusEvent *) override { Q_ASSERT(!focused); focused = true; } | 
| 78 |     void focusOutEvent(QFocusEvent *) override { Q_ASSERT(focused); focused = false; } | 
| 79 |     void mousePressEvent(QMouseEvent *event) override { event->accept(); ++pressCount; } | 
| 80 |     void mouseReleaseEvent(QMouseEvent *event) override { event->accept(); ++releaseCount; } | 
| 81 |     void touchEvent(QTouchEvent *event) override { | 
| 82 |         touchEventReached = true; | 
| 83 |         event->setAccepted(acceptIncomingTouchEvents); | 
| 84 |     } | 
| 85 |     void wheelEvent(QWheelEvent *event) override { | 
| 86 |         event->accept(); | 
| 87 |         ++wheelCount; | 
| 88 |         timestamp = event->timestamp(); | 
| 89 |         lastWheelEventPos = event->position().toPoint(); | 
| 90 |         lastWheelEventGlobalPos = event->globalPosition().toPoint(); | 
| 91 |     } | 
| 92 |     bool event(QEvent *e) override | 
| 93 |     { | 
| 94 |         if (e->type() == QEvent::LanguageChange) | 
| 95 |             languageChangeEventCount++; | 
| 96 |         return QQuickItem::event(e); | 
| 97 |     } | 
| 98 | }; | 
| 99 |  | 
| 100 | class TestWindow: public QQuickWindow | 
| 101 | { | 
| 102 | public: | 
| 103 |     TestWindow() | 
| 104 |         : QQuickWindow() | 
| 105 |     {} | 
| 106 |  | 
| 107 |     virtual bool event(QEvent *event) | 
| 108 |     { | 
| 109 |         return QQuickWindow::event(event); | 
| 110 |     } | 
| 111 | }; | 
| 112 |  | 
| 113 | class TestPolishItem : public QQuickItem | 
| 114 | { | 
| 115 | Q_OBJECT | 
| 116 | public: | 
| 117 |     TestPolishItem(QQuickItem *parent = nullptr) | 
| 118 |     : QQuickItem(parent), wasPolished(false) { | 
| 119 |  | 
| 120 |     } | 
| 121 |  | 
| 122 |     bool wasPolished; | 
| 123 |     int repolishLoopCount = 0; | 
| 124 |  | 
| 125 | protected: | 
| 126 |     virtual void updatePolish() { | 
| 127 |         wasPolished = true; | 
| 128 |         if (repolishLoopCount > 0) { | 
| 129 |             --repolishLoopCount; | 
| 130 |             polish(); | 
| 131 |         } | 
| 132 |     } | 
| 133 |  | 
| 134 | public slots: | 
| 135 |     void doPolish() { | 
| 136 |         polish(); | 
| 137 |     } | 
| 138 | }; | 
| 139 |  | 
| 140 | class TestFocusScope : public QQuickFocusScope | 
| 141 | { | 
| 142 | Q_OBJECT | 
| 143 | public: | 
| 144 |     TestFocusScope(QQuickItem *parent = nullptr) : QQuickFocusScope(parent), focused(false) {} | 
| 145 |  | 
| 146 |     bool focused; | 
| 147 | protected: | 
| 148 |     virtual void focusInEvent(QFocusEvent *) { Q_ASSERT(!focused); focused = true; } | 
| 149 |     virtual void focusOutEvent(QFocusEvent *) { Q_ASSERT(focused); focused = false; } | 
| 150 | }; | 
| 151 |  | 
| 152 | class tst_qquickitem : public QQmlDataTest | 
| 153 | { | 
| 154 |     Q_OBJECT | 
| 155 | public: | 
| 156 |  | 
| 157 | private slots: | 
| 158 |     void initTestCase(); | 
| 159 |  | 
| 160 |     void noWindow(); | 
| 161 |     void simpleFocus(); | 
| 162 |     void scopedFocus(); | 
| 163 |     void addedToWindow(); | 
| 164 |     void changeParent(); | 
| 165 |     void multipleFocusClears(); | 
| 166 |     void focusSubItemInNonFocusScope(); | 
| 167 |     void parentItemWithFocus(); | 
| 168 |     void reparentFocusedItem(); | 
| 169 |  | 
| 170 |     void constructor(); | 
| 171 |     void setParentItem(); | 
| 172 |  | 
| 173 |     void visible(); | 
| 174 |     void enabled(); | 
| 175 |     void enabledFocus(); | 
| 176 |  | 
| 177 |     void mouseGrab(); | 
| 178 |     void touchEventAcceptIgnore_data(); | 
| 179 |     void touchEventAcceptIgnore(); | 
| 180 |     void polishOutsideAnimation(); | 
| 181 |     void polishOnCompleted(); | 
| 182 |  | 
| 183 |     void wheelEvent_data(); | 
| 184 |     void wheelEvent(); | 
| 185 |     void hoverEvent_data(); | 
| 186 |     void hoverEvent(); | 
| 187 |     void hoverEventInParent(); | 
| 188 |  | 
| 189 |     void paintOrder_data(); | 
| 190 |     void paintOrder(); | 
| 191 |  | 
| 192 |     void acceptedMouseButtons(); | 
| 193 |  | 
| 194 |     void visualParentOwnership(); | 
| 195 |     void visualParentOwnershipWindow(); | 
| 196 |  | 
| 197 |     void testSGInvalidate(); | 
| 198 |  | 
| 199 |     void objectChildTransform(); | 
| 200 |  | 
| 201 |     void contains_data(); | 
| 202 |     void contains(); | 
| 203 |  | 
| 204 |     void childAt(); | 
| 205 |  | 
| 206 |     void ignoreButtonPressNotInAcceptedMouseButtons(); | 
| 207 |  | 
| 208 |     void shortcutOverride(); | 
| 209 |  | 
| 210 | #ifdef TEST_QTBUG_60123 | 
| 211 |     void qtBug60123(); | 
| 212 | #endif | 
| 213 |  | 
| 214 |     void setParentCalledInOnWindowChanged(); | 
| 215 |     void receivesLanguageChangeEvent(); | 
| 216 |     void polishLoopDetection_data(); | 
| 217 |     void polishLoopDetection(); | 
| 218 |  | 
| 219 | private: | 
| 220 |  | 
| 221 |     enum PaintOrderOp { | 
| 222 |         NoOp, Append, Remove, StackBefore, StackAfter, SetZ | 
| 223 |     }; | 
| 224 |  | 
| 225 |     bool ensureFocus(QWindow *w) { | 
| 226 |         if (w->width() <=0 || w->height() <= 0) | 
| 227 |             w->setGeometry(posx: 100, posy: 100, w: 400, h: 300); | 
| 228 |         w->show(); | 
| 229 |         w->requestActivate(); | 
| 230 |         return QTest::qWaitForWindowActive(window: w); | 
| 231 |     } | 
| 232 | }; | 
| 233 |  | 
| 234 | void tst_qquickitem::initTestCase() | 
| 235 | { | 
| 236 |     QQmlDataTest::initTestCase(); | 
| 237 |     qmlRegisterType<TestPolishItem>(uri: "Qt.test" , versionMajor: 1, versionMinor: 0, qmlName: "TestPolishItem" ); | 
| 238 | } | 
| 239 |  | 
| 240 | // Focus still updates when outside a window | 
| 241 | void tst_qquickitem::noWindow() | 
| 242 | { | 
| 243 |     QQuickItem *root = new TestItem; | 
| 244 |     QQuickItem *child = new TestItem(root); | 
| 245 |     QQuickItem *scope = new TestItem(root); | 
| 246 |     QQuickFocusScope *scopedChild = new TestFocusScope(scope); | 
| 247 |     QQuickFocusScope *scopedChild2 = new TestFocusScope(scope); | 
| 248 |  | 
| 249 |     QCOMPARE(root->hasFocus(), false); | 
| 250 |     QCOMPARE(child->hasFocus(), false); | 
| 251 |     QCOMPARE(scope->hasFocus(), false); | 
| 252 |     QCOMPARE(scopedChild->hasFocus(), false); | 
| 253 |     QCOMPARE(scopedChild2->hasFocus(), false); | 
| 254 |  | 
| 255 |     root->setFocus(true); | 
| 256 |     scope->setFocus(true); | 
| 257 |     scopedChild2->setFocus(true); | 
| 258 |     QCOMPARE(root->hasFocus(), false); | 
| 259 |     QCOMPARE(child->hasFocus(), false); | 
| 260 |     QCOMPARE(scope->hasFocus(), false); | 
| 261 |     QCOMPARE(scopedChild->hasFocus(), false); | 
| 262 |     QCOMPARE(scopedChild2->hasFocus(), true); | 
| 263 |  | 
| 264 |     root->setFocus(false); | 
| 265 |     child->setFocus(true); | 
| 266 |     scopedChild->setFocus(true); | 
| 267 |     scope->setFocus(false); | 
| 268 |     QCOMPARE(root->hasFocus(), false); | 
| 269 |     QCOMPARE(child->hasFocus(), false); | 
| 270 |     QCOMPARE(scope->hasFocus(), false); | 
| 271 |     QCOMPARE(scopedChild->hasFocus(), true); | 
| 272 |     QCOMPARE(scopedChild2->hasFocus(), false); | 
| 273 |  | 
| 274 |     delete root; | 
| 275 | } | 
| 276 |  | 
| 277 | struct FocusData { | 
| 278 |     FocusData() : focus(false), activeFocus(false) {} | 
| 279 |  | 
| 280 |     void set(bool f, bool af) { focus = f; activeFocus = af; } | 
| 281 |     bool focus; | 
| 282 |     bool activeFocus; | 
| 283 | }; | 
| 284 | struct FocusState : public QHash<QQuickItem *, FocusData> | 
| 285 | { | 
| 286 |     FocusState() : activeFocusItem(nullptr) {} | 
| 287 |     FocusState &operator<<(QQuickItem *item) { | 
| 288 |         insert(key: item, value: FocusData()); | 
| 289 |         return *this; | 
| 290 |     } | 
| 291 |  | 
| 292 |     void active(QQuickItem *i) { | 
| 293 |         activeFocusItem = i; | 
| 294 |     } | 
| 295 |     QQuickItem *activeFocusItem; | 
| 296 | }; | 
| 297 |  | 
| 298 | #define FVERIFY() \ | 
| 299 |     do { \ | 
| 300 |         if (focusState.activeFocusItem) { \ | 
| 301 |             QCOMPARE(window.activeFocusItem(), focusState.activeFocusItem); \ | 
| 302 |             if (qobject_cast<TestItem *>(window.activeFocusItem())) \ | 
| 303 |                 QCOMPARE(qobject_cast<TestItem *>(window.activeFocusItem())->focused, true); \ | 
| 304 |             else if (qobject_cast<TestFocusScope *>(window.activeFocusItem())) \ | 
| 305 |                 QCOMPARE(qobject_cast<TestFocusScope *>(window.activeFocusItem())->focused, true); \ | 
| 306 |         } else { \ | 
| 307 |             QCOMPARE(window.activeFocusItem(), window.contentItem()); \ | 
| 308 |         } \ | 
| 309 |         for (QHash<QQuickItem *, FocusData>::Iterator iter = focusState.begin(); \ | 
| 310 |             iter != focusState.end(); \ | 
| 311 |             iter++) { \ | 
| 312 |             QCOMPARE(iter.key()->hasFocus(), iter.value().focus); \ | 
| 313 |             QCOMPARE(iter.key()->hasActiveFocus(), iter.value().activeFocus); \ | 
| 314 |         } \ | 
| 315 |     } while (false) | 
| 316 |  | 
| 317 | // Tests a simple set of top-level scoped items | 
| 318 | void tst_qquickitem::simpleFocus() | 
| 319 | { | 
| 320 |     QQuickWindow window; | 
| 321 |     QVERIFY(ensureFocus(&window)); | 
| 322 |  | 
| 323 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 324 |  | 
| 325 |     QQuickItem *l1c1 = new TestItem(window.contentItem()); | 
| 326 |     QQuickItem *l1c2 = new TestItem(window.contentItem()); | 
| 327 |     QQuickItem *l1c3 = new TestItem(window.contentItem()); | 
| 328 |  | 
| 329 |     QQuickItem *l2c1 = new TestItem(l1c1); | 
| 330 |     QQuickItem *l2c2 = new TestItem(l1c1); | 
| 331 |     QQuickItem *l2c3 = new TestItem(l1c3); | 
| 332 |  | 
| 333 |     FocusState focusState; | 
| 334 |     focusState << l1c1 << l1c2 << l1c3 | 
| 335 |                << l2c1 << l2c2 << l2c3; | 
| 336 |     FVERIFY(); | 
| 337 |  | 
| 338 |     l1c1->setFocus(true); | 
| 339 |     focusState[l1c1].set(f: true, af: true); | 
| 340 |     focusState.active(i: l1c1); | 
| 341 |     FVERIFY(); | 
| 342 |  | 
| 343 |     l2c3->setFocus(true); | 
| 344 |     focusState[l1c1].set(f: false, af: false); | 
| 345 |     focusState[l2c3].set(f: true, af: true); | 
| 346 |     focusState.active(i: l2c3); | 
| 347 |     FVERIFY(); | 
| 348 |  | 
| 349 |     l1c3->setFocus(true); | 
| 350 |     focusState[l2c3].set(f: false, af: false); | 
| 351 |     focusState[l1c3].set(f: true, af: true); | 
| 352 |     focusState.active(i: l1c3); | 
| 353 |     FVERIFY(); | 
| 354 |  | 
| 355 |     l1c2->setFocus(false); | 
| 356 |     FVERIFY(); | 
| 357 |  | 
| 358 |     l1c3->setFocus(false); | 
| 359 |     focusState[l1c3].set(f: false, af: false); | 
| 360 |     focusState.active(i: nullptr); | 
| 361 |     FVERIFY(); | 
| 362 |  | 
| 363 |     l2c1->setFocus(true); | 
| 364 |     focusState[l2c1].set(f: true, af: true); | 
| 365 |     focusState.active(i: l2c1); | 
| 366 |     FVERIFY(); | 
| 367 | } | 
| 368 |  | 
| 369 | // Items with a focus scope | 
| 370 | void tst_qquickitem::scopedFocus() | 
| 371 | { | 
| 372 |     QQuickWindow window; | 
| 373 |     QVERIFY(ensureFocus(&window)); | 
| 374 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 375 |  | 
| 376 |     QQuickItem *l1c1 = new TestItem(window.contentItem()); | 
| 377 |     QQuickItem *l1c2 = new TestItem(window.contentItem()); | 
| 378 |     QQuickItem *l1c3 = new TestItem(window.contentItem()); | 
| 379 |  | 
| 380 |     QQuickItem *l2c1 = new TestItem(l1c1); | 
| 381 |     QQuickItem *l2c2 = new TestItem(l1c1); | 
| 382 |     QQuickItem *l2c3 = new TestFocusScope(l1c3); | 
| 383 |  | 
| 384 |     QQuickItem *l3c1 = new TestItem(l2c3); | 
| 385 |     QQuickItem *l3c2 = new TestFocusScope(l2c3); | 
| 386 |  | 
| 387 |     QQuickItem *l4c1 = new TestItem(l3c2); | 
| 388 |     QQuickItem *l4c2 = new TestItem(l3c2); | 
| 389 |  | 
| 390 |     FocusState focusState; | 
| 391 |     focusState << l1c1 << l1c2 << l1c3 | 
| 392 |                << l2c1 << l2c2 << l2c3 | 
| 393 |                << l3c1 << l3c2 | 
| 394 |                << l4c1 << l4c2; | 
| 395 |     FVERIFY(); | 
| 396 |  | 
| 397 |     l4c2->setFocus(true); | 
| 398 |     focusState[l4c2].set(f: true, af: false); | 
| 399 |     FVERIFY(); | 
| 400 |  | 
| 401 |     l4c1->setFocus(true); | 
| 402 |     focusState[l4c2].set(f: false, af: false); | 
| 403 |     focusState[l4c1].set(f: true, af: false); | 
| 404 |     FVERIFY(); | 
| 405 |  | 
| 406 |     l1c1->setFocus(true); | 
| 407 |     focusState[l1c1].set(f: true, af: true); | 
| 408 |     focusState.active(i: l1c1); | 
| 409 |     FVERIFY(); | 
| 410 |  | 
| 411 |     l3c2->setFocus(true); | 
| 412 |     focusState[l3c2].set(f: true, af: false); | 
| 413 |     FVERIFY(); | 
| 414 |  | 
| 415 |     l2c3->setFocus(true); | 
| 416 |     focusState[l1c1].set(f: false, af: false); | 
| 417 |     focusState[l2c3].set(f: true, af: true); | 
| 418 |     focusState[l3c2].set(f: true, af: true); | 
| 419 |     focusState[l4c1].set(f: true, af: true); | 
| 420 |     focusState.active(i: l4c1); | 
| 421 |     FVERIFY(); | 
| 422 |  | 
| 423 |     l3c2->setFocus(false); | 
| 424 |     focusState[l3c2].set(f: false, af: false); | 
| 425 |     focusState[l4c1].set(f: true, af: false); | 
| 426 |     focusState.active(i: l2c3); | 
| 427 |     FVERIFY(); | 
| 428 |  | 
| 429 |     l3c2->setFocus(true); | 
| 430 |     focusState[l3c2].set(f: true, af: true); | 
| 431 |     focusState[l4c1].set(f: true, af: true); | 
| 432 |     focusState.active(i: l4c1); | 
| 433 |     FVERIFY(); | 
| 434 |  | 
| 435 |     l4c1->setFocus(false); | 
| 436 |     focusState[l4c1].set(f: false, af: false); | 
| 437 |     focusState.active(i: l3c2); | 
| 438 |     FVERIFY(); | 
| 439 |  | 
| 440 |     l1c3->setFocus(true); | 
| 441 |     focusState[l1c3].set(f: true, af: true); | 
| 442 |     focusState[l2c3].set(f: false, af: false); | 
| 443 |     focusState[l3c2].set(f: true, af: false); | 
| 444 |     focusState.active(i: l1c3); | 
| 445 |     FVERIFY(); | 
| 446 | } | 
| 447 |  | 
| 448 | // Tests focus corrects itself when a tree is added to a window for the first time | 
| 449 | void tst_qquickitem::addedToWindow() | 
| 450 | { | 
| 451 |     { | 
| 452 |     QQuickWindow window; | 
| 453 |     QVERIFY(ensureFocus(&window)); | 
| 454 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 455 |  | 
| 456 |     QQuickItem *item = new TestItem; | 
| 457 |  | 
| 458 |     FocusState focusState; | 
| 459 |     focusState << item; | 
| 460 |  | 
| 461 |     item->setFocus(true); | 
| 462 |     focusState[item].set(f: true, af: false); | 
| 463 |     FVERIFY(); | 
| 464 |  | 
| 465 |     item->setParentItem(window.contentItem()); | 
| 466 |     focusState[item].set(f: true, af: true); | 
| 467 |     focusState.active(i: item); | 
| 468 |     FVERIFY(); | 
| 469 |     } | 
| 470 |  | 
| 471 |     { | 
| 472 |     QQuickWindow window; | 
| 473 |     QVERIFY(ensureFocus(&window)); | 
| 474 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 475 |  | 
| 476 |     QQuickItem *item = new TestItem(window.contentItem()); | 
| 477 |  | 
| 478 |     QQuickItem *tree = new TestItem; | 
| 479 |     QQuickItem *c1 = new TestItem(tree); | 
| 480 |     QQuickItem *c2 = new TestItem(tree); | 
| 481 |  | 
| 482 |     FocusState focusState; | 
| 483 |     focusState << item << tree << c1 << c2; | 
| 484 |  | 
| 485 |     item->setFocus(true); | 
| 486 |     c1->setFocus(true); | 
| 487 |     c2->setFocus(true); | 
| 488 |     focusState[item].set(f: true, af: true); | 
| 489 |     focusState[c1].set(f: false, af: false); | 
| 490 |     focusState[c2].set(f: true, af: false); | 
| 491 |     focusState.active(i: item); | 
| 492 |     FVERIFY(); | 
| 493 |  | 
| 494 |     tree->setParentItem(item); | 
| 495 |     focusState[c1].set(f: false, af: false); | 
| 496 |     focusState[c2].set(f: false, af: false); | 
| 497 |     FVERIFY(); | 
| 498 |     } | 
| 499 |  | 
| 500 |     { | 
| 501 |     QQuickWindow window; | 
| 502 |     QVERIFY(ensureFocus(&window)); | 
| 503 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 504 |  | 
| 505 |     QQuickItem *tree = new TestItem; | 
| 506 |     QQuickItem *c1 = new TestItem(tree); | 
| 507 |     QQuickItem *c2 = new TestItem(tree); | 
| 508 |  | 
| 509 |     FocusState focusState; | 
| 510 |     focusState << tree << c1 << c2; | 
| 511 |     c1->setFocus(true); | 
| 512 |     c2->setFocus(true); | 
| 513 |     focusState[c1].set(f: false, af: false); | 
| 514 |     focusState[c2].set(f: true, af: false); | 
| 515 |     FVERIFY(); | 
| 516 |  | 
| 517 |     tree->setParentItem(window.contentItem()); | 
| 518 |     focusState[c1].set(f: false, af: false); | 
| 519 |     focusState[c2].set(f: true, af: true); | 
| 520 |     focusState.active(i: c2); | 
| 521 |     FVERIFY(); | 
| 522 |     } | 
| 523 |  | 
| 524 |     { | 
| 525 |     QQuickWindow window; | 
| 526 |     QVERIFY(ensureFocus(&window)); | 
| 527 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 528 |     QQuickItem *tree = new TestFocusScope; | 
| 529 |     QQuickItem *c1 = new TestItem(tree); | 
| 530 |     QQuickItem *c2 = new TestItem(tree); | 
| 531 |  | 
| 532 |     FocusState focusState; | 
| 533 |     focusState << tree << c1 << c2; | 
| 534 |     c1->setFocus(true); | 
| 535 |     c2->setFocus(true); | 
| 536 |     focusState[c1].set(f: false, af: false); | 
| 537 |     focusState[c2].set(f: true, af: false); | 
| 538 |     FVERIFY(); | 
| 539 |  | 
| 540 |     tree->setParentItem(window.contentItem()); | 
| 541 |     focusState[c1].set(f: false, af: false); | 
| 542 |     focusState[c2].set(f: true, af: false); | 
| 543 |     FVERIFY(); | 
| 544 |  | 
| 545 |     tree->setFocus(true); | 
| 546 |     focusState[tree].set(f: true, af: true); | 
| 547 |     focusState[c2].set(f: true, af: true); | 
| 548 |     focusState.active(i: c2); | 
| 549 |     FVERIFY(); | 
| 550 |     } | 
| 551 |  | 
| 552 |     { | 
| 553 |     QQuickWindow window; | 
| 554 |     QVERIFY(ensureFocus(&window)); | 
| 555 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 556 |     QQuickItem *tree = new TestFocusScope; | 
| 557 |     QQuickItem *c1 = new TestItem(tree); | 
| 558 |     QQuickItem *c2 = new TestItem(tree); | 
| 559 |  | 
| 560 |     FocusState focusState; | 
| 561 |     focusState << tree << c1 << c2; | 
| 562 |     tree->setFocus(true); | 
| 563 |     c1->setFocus(true); | 
| 564 |     c2->setFocus(true); | 
| 565 |     focusState[tree].set(f: true, af: false); | 
| 566 |     focusState[c1].set(f: false, af: false); | 
| 567 |     focusState[c2].set(f: true, af: false); | 
| 568 |     FVERIFY(); | 
| 569 |  | 
| 570 |     tree->setParentItem(window.contentItem()); | 
| 571 |     focusState[tree].set(f: true, af: true); | 
| 572 |     focusState[c1].set(f: false, af: false); | 
| 573 |     focusState[c2].set(f: true, af: true); | 
| 574 |     focusState.active(i: c2); | 
| 575 |     FVERIFY(); | 
| 576 |     } | 
| 577 |  | 
| 578 |     { | 
| 579 |     QQuickWindow window; | 
| 580 |     QVERIFY(ensureFocus(&window)); | 
| 581 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 582 |     QQuickItem *child = new TestItem(window.contentItem()); | 
| 583 |     QQuickItem *tree = new TestFocusScope; | 
| 584 |     QQuickItem *c1 = new TestItem(tree); | 
| 585 |     QQuickItem *c2 = new TestItem(tree); | 
| 586 |  | 
| 587 |     FocusState focusState; | 
| 588 |     focusState << child << tree << c1 << c2; | 
| 589 |     child->setFocus(true); | 
| 590 |     tree->setFocus(true); | 
| 591 |     c1->setFocus(true); | 
| 592 |     c2->setFocus(true); | 
| 593 |     focusState[child].set(f: true, af: true); | 
| 594 |     focusState[tree].set(f: true, af: false); | 
| 595 |     focusState[c1].set(f: false, af: false); | 
| 596 |     focusState[c2].set(f: true, af: false); | 
| 597 |     focusState.active(i: child); | 
| 598 |     FVERIFY(); | 
| 599 |  | 
| 600 |     tree->setParentItem(window.contentItem()); | 
| 601 |     focusState[tree].set(f: false, af: false); | 
| 602 |     focusState[c1].set(f: false, af: false); | 
| 603 |     focusState[c2].set(f: true, af: false); | 
| 604 |     FVERIFY(); | 
| 605 |  | 
| 606 |     tree->setFocus(true); | 
| 607 |     focusState[child].set(f: false, af: false); | 
| 608 |     focusState[tree].set(f: true, af: true); | 
| 609 |     focusState[c2].set(f: true, af: true); | 
| 610 |     focusState.active(i: c2); | 
| 611 |     FVERIFY(); | 
| 612 |     } | 
| 613 | } | 
| 614 |  | 
| 615 | void tst_qquickitem::changeParent() | 
| 616 | { | 
| 617 |     // Parent to no parent | 
| 618 |     { | 
| 619 |     QQuickWindow window; | 
| 620 |     QVERIFY(ensureFocus(&window)); | 
| 621 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 622 |     QQuickItem *child = new TestItem(window.contentItem()); | 
| 623 |  | 
| 624 |     FocusState focusState; | 
| 625 |     focusState << child; | 
| 626 |     FVERIFY(); | 
| 627 |  | 
| 628 |     child->setFocus(true); | 
| 629 |     focusState[child].set(f: true, af: true); | 
| 630 |     focusState.active(i: child); | 
| 631 |     FVERIFY(); | 
| 632 |  | 
| 633 |     child->setParentItem(nullptr); | 
| 634 |     focusState[child].set(f: true, af: false); | 
| 635 |     focusState.active(i: nullptr); | 
| 636 |     FVERIFY(); | 
| 637 |     } | 
| 638 |  | 
| 639 |     // Different parent, same focus scope | 
| 640 |     { | 
| 641 |     QQuickWindow window; | 
| 642 |     QVERIFY(ensureFocus(&window)); | 
| 643 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 644 |     QQuickItem *child = new TestItem(window.contentItem()); | 
| 645 |     QQuickItem *child2 = new TestItem(window.contentItem()); | 
| 646 |  | 
| 647 |     FocusState focusState; | 
| 648 |     focusState << child << child2; | 
| 649 |     FVERIFY(); | 
| 650 |  | 
| 651 |     child->setFocus(true); | 
| 652 |     focusState[child].set(f: true, af: true); | 
| 653 |     focusState.active(i: child); | 
| 654 |     FVERIFY(); | 
| 655 |  | 
| 656 |     child->setParentItem(child2); | 
| 657 |     FVERIFY(); | 
| 658 |     } | 
| 659 |  | 
| 660 |     // Different parent, different focus scope | 
| 661 |     { | 
| 662 |     QQuickWindow window; | 
| 663 |     QVERIFY(ensureFocus(&window)); | 
| 664 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 665 |     QQuickItem *child = new TestItem(window.contentItem()); | 
| 666 |     QQuickItem *child2 = new TestFocusScope(window.contentItem()); | 
| 667 |     QQuickItem *item = new TestItem(child); | 
| 668 |  | 
| 669 |     FocusState focusState; | 
| 670 |     focusState << child << child2 << item; | 
| 671 |     FVERIFY(); | 
| 672 |  | 
| 673 |     item->setFocus(true); | 
| 674 |     focusState[item].set(f: true, af: true); | 
| 675 |     focusState.active(i: item); | 
| 676 |     FVERIFY(); | 
| 677 |  | 
| 678 |     item->setParentItem(child2); | 
| 679 |     focusState[item].set(f: true, af: false); | 
| 680 |     focusState.active(i: nullptr); | 
| 681 |     FVERIFY(); | 
| 682 |     } | 
| 683 |     { | 
| 684 |     QQuickWindow window; | 
| 685 |     QVERIFY(ensureFocus(&window)); | 
| 686 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 687 |     QQuickItem *child = new TestItem(window.contentItem()); | 
| 688 |     QQuickItem *child2 = new TestFocusScope(window.contentItem()); | 
| 689 |     QQuickItem *item = new TestItem(child2); | 
| 690 |  | 
| 691 |     FocusState focusState; | 
| 692 |     focusState << child << child2 << item; | 
| 693 |     FVERIFY(); | 
| 694 |  | 
| 695 |     item->setFocus(true); | 
| 696 |     focusState[item].set(f: true, af: false); | 
| 697 |     focusState.active(i: nullptr); | 
| 698 |     FVERIFY(); | 
| 699 |  | 
| 700 |     item->setParentItem(child); | 
| 701 |     focusState[item].set(f: true, af: true); | 
| 702 |     focusState.active(i: item); | 
| 703 |     FVERIFY(); | 
| 704 |     } | 
| 705 |     { | 
| 706 |     QQuickWindow window; | 
| 707 |     QVERIFY(ensureFocus(&window)); | 
| 708 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 709 |     QQuickItem *child = new TestItem(window.contentItem()); | 
| 710 |     QQuickItem *child2 = new TestFocusScope(window.contentItem()); | 
| 711 |     QQuickItem *item = new TestItem(child2); | 
| 712 |  | 
| 713 |     FocusState focusState; | 
| 714 |     focusState << child << child2 << item; | 
| 715 |     FVERIFY(); | 
| 716 |  | 
| 717 |     child->setFocus(true); | 
| 718 |     item->setFocus(true); | 
| 719 |     focusState[child].set(f: true, af: true); | 
| 720 |     focusState[item].set(f: true, af: false); | 
| 721 |     focusState.active(i: child); | 
| 722 |     FVERIFY(); | 
| 723 |  | 
| 724 |     item->setParentItem(child); | 
| 725 |     focusState[item].set(f: false, af: false); | 
| 726 |     FVERIFY(); | 
| 727 |     } | 
| 728 |  | 
| 729 |     // child has active focus, then its fs parent changes parent to 0, then | 
| 730 |     // child is deleted, then its parent changes again to a valid parent | 
| 731 |     { | 
| 732 |     QQuickWindow window; | 
| 733 |     QVERIFY(ensureFocus(&window)); | 
| 734 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 735 |     QQuickItem *item = new TestFocusScope(window.contentItem()); | 
| 736 |     QQuickItem *child = new TestItem(item); | 
| 737 |     QQuickItem *child2 = new TestItem; | 
| 738 |  | 
| 739 |     FocusState focusState; | 
| 740 |     focusState << item << child; | 
| 741 |     FVERIFY(); | 
| 742 |  | 
| 743 |     item->setFocus(true); | 
| 744 |     child->setFocus(true); | 
| 745 |     focusState[child].set(f: true, af: true); | 
| 746 |     focusState[item].set(f: true, af: true); | 
| 747 |     focusState.active(i: child); | 
| 748 |     FVERIFY(); | 
| 749 |  | 
| 750 |     item->setParentItem(nullptr); | 
| 751 |     focusState[child].set(f: true, af: false); | 
| 752 |     focusState[item].set(f: true, af: false); | 
| 753 |     focusState.active(i: nullptr); | 
| 754 |     FVERIFY(); | 
| 755 |  | 
| 756 |     focusState.remove(key: child); | 
| 757 |     delete child; | 
| 758 |     item->setParentItem(window.contentItem()); | 
| 759 |     focusState[item].set(f: true, af: true); | 
| 760 |     focusState.active(i: item); | 
| 761 |     FVERIFY(); | 
| 762 |     delete child2; | 
| 763 |     } | 
| 764 | } | 
| 765 |  | 
| 766 | void tst_qquickitem::multipleFocusClears() | 
| 767 | { | 
| 768 |     //Multiple clears of focus inside a focus scope shouldn't crash. QTBUG-24714 | 
| 769 |     QQuickView view; | 
| 770 |     view.setSource(testFileUrl(fileName: "multipleFocusClears.qml" )); | 
| 771 |     view.show(); | 
| 772 |     QVERIFY(ensureFocus(&view)); | 
| 773 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &view); | 
| 774 | } | 
| 775 |  | 
| 776 | void tst_qquickitem::focusSubItemInNonFocusScope() | 
| 777 | { | 
| 778 |     QQuickView view; | 
| 779 |     view.setSource(testFileUrl(fileName: "focusSubItemInNonFocusScope.qml" )); | 
| 780 |     view.show(); | 
| 781 |     QVERIFY(QTest::qWaitForWindowActive(&view)); | 
| 782 |  | 
| 783 |     QQuickItem *dummyItem = view.rootObject()->findChild<QQuickItem *>(aName: "dummyItem" ); | 
| 784 |     QVERIFY(dummyItem); | 
| 785 |  | 
| 786 |     QQuickItem *textInput = view.rootObject()->findChild<QQuickItem *>(aName: "textInput" ); | 
| 787 |     QVERIFY(textInput); | 
| 788 |  | 
| 789 |     QVERIFY(dummyItem->hasFocus()); | 
| 790 |     QVERIFY(!textInput->hasFocus()); | 
| 791 |     QVERIFY(dummyItem->hasActiveFocus()); | 
| 792 |  | 
| 793 |     QVERIFY(QMetaObject::invokeMethod(textInput, "forceActiveFocus" )); | 
| 794 |  | 
| 795 |     QVERIFY(!dummyItem->hasFocus()); | 
| 796 |     QVERIFY(textInput->hasFocus()); | 
| 797 |     QVERIFY(textInput->hasActiveFocus()); | 
| 798 | } | 
| 799 |  | 
| 800 | void tst_qquickitem::parentItemWithFocus() | 
| 801 | { | 
| 802 |     QQuickWindow window; | 
| 803 |     QVERIFY(ensureFocus(&window)); | 
| 804 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 805 |     { | 
| 806 |     QQuickItem parent; | 
| 807 |     QQuickItem child; | 
| 808 |  | 
| 809 |     FocusState focusState; | 
| 810 |     focusState << &parent << &child; | 
| 811 |     FVERIFY(); | 
| 812 |  | 
| 813 |     parent.setFocus(true); | 
| 814 |     child.setFocus(true); | 
| 815 |     focusState[&parent].set(f: true, af: false); | 
| 816 |     focusState[&child].set(f: true, af: false); | 
| 817 |     FVERIFY(); | 
| 818 |  | 
| 819 |     child.setParentItem(&parent); | 
| 820 |     focusState[&parent].set(f: true, af: false); | 
| 821 |     focusState[&child].set(f: false, af: false); | 
| 822 |     FVERIFY(); | 
| 823 |  | 
| 824 |     parent.setParentItem(window.contentItem()); | 
| 825 |     focusState[&parent].set(f: true, af: true); | 
| 826 |     focusState[&child].set(f: false, af: false); | 
| 827 |     focusState.active(i: &parent); | 
| 828 |     FVERIFY(); | 
| 829 |  | 
| 830 |     child.forceActiveFocus(); | 
| 831 |     focusState[&parent].set(f: false, af: false); | 
| 832 |     focusState[&child].set(f: true, af: true); | 
| 833 |     focusState.active(i: &child); | 
| 834 |     FVERIFY(); | 
| 835 |     } { | 
| 836 |     QQuickItem parent; | 
| 837 |     QQuickItem child; | 
| 838 |     QQuickItem grandchild(&child); | 
| 839 |  | 
| 840 |     FocusState focusState; | 
| 841 |     focusState << &parent << &child << &grandchild; | 
| 842 |     FVERIFY(); | 
| 843 |  | 
| 844 |     parent.setFocus(true); | 
| 845 |     grandchild.setFocus(true); | 
| 846 |     focusState[&parent].set(f: true, af: false); | 
| 847 |     focusState[&child].set(f: false, af: false); | 
| 848 |     focusState[&grandchild].set(f: true, af: false); | 
| 849 |     FVERIFY(); | 
| 850 |  | 
| 851 |     child.setParentItem(&parent); | 
| 852 |     focusState[&parent].set(f: true, af: false); | 
| 853 |     focusState[&child].set(f: false, af: false); | 
| 854 |     focusState[&grandchild].set(f: false, af: false); | 
| 855 |     FVERIFY(); | 
| 856 |  | 
| 857 |     parent.setParentItem(window.contentItem()); | 
| 858 |     focusState[&parent].set(f: true, af: true); | 
| 859 |     focusState[&child].set(f: false, af: false); | 
| 860 |     focusState[&grandchild].set(f: false, af: false); | 
| 861 |     focusState.active(i: &parent); | 
| 862 |     FVERIFY(); | 
| 863 |  | 
| 864 |     grandchild.forceActiveFocus(); | 
| 865 |     focusState[&parent].set(f: false, af: false); | 
| 866 |     focusState[&child].set(f: false, af: false); | 
| 867 |     focusState[&grandchild].set(f: true, af: true); | 
| 868 |     focusState.active(i: &grandchild); | 
| 869 |     FVERIFY(); | 
| 870 |     } | 
| 871 |  | 
| 872 |     { | 
| 873 |     QQuickItem parent; | 
| 874 |     QQuickItem child1; | 
| 875 |     QQuickItem child2; | 
| 876 |  | 
| 877 |     FocusState focusState; | 
| 878 |     focusState << &parent << &child1 << &child2; | 
| 879 |     parent.setFocus(true); | 
| 880 |     child1.setParentItem(&parent); | 
| 881 |     child2.setParentItem(&parent); | 
| 882 |     focusState[&parent].set(f: true, af: false); | 
| 883 |     focusState[&child1].set(f: false, af: false); | 
| 884 |     focusState[&child2].set(f: false, af: false); | 
| 885 |     FVERIFY(); | 
| 886 |  | 
| 887 |     child1.setFocus(true); | 
| 888 |     focusState[&parent].set(f: false, af: false); | 
| 889 |     focusState[&child1].set(f: true, af: false); | 
| 890 |     FVERIFY(); | 
| 891 |  | 
| 892 |     parent.setFocus(true); | 
| 893 |     focusState[&parent].set(f: true, af: false); | 
| 894 |     focusState[&child1].set(f: false, af: false); | 
| 895 |     FVERIFY(); | 
| 896 |     } | 
| 897 | } | 
| 898 |  | 
| 899 | void tst_qquickitem::reparentFocusedItem() | 
| 900 | { | 
| 901 |     QQuickWindow window; | 
| 902 |     QVERIFY(ensureFocus(&window)); | 
| 903 |     QTRY_COMPARE(QGuiApplication::focusWindow(), &window); | 
| 904 |  | 
| 905 |     QQuickItem parent(window.contentItem()); | 
| 906 |     QQuickItem child(&parent); | 
| 907 |     QQuickItem sibling(&parent); | 
| 908 |     QQuickItem grandchild(&child); | 
| 909 |  | 
| 910 |     FocusState focusState; | 
| 911 |     focusState << &parent << &child << &sibling << &grandchild; | 
| 912 |     FVERIFY(); | 
| 913 |  | 
| 914 |     grandchild.setFocus(true); | 
| 915 |     focusState[&parent].set(f: false, af: false); | 
| 916 |     focusState[&child].set(f: false, af: false); | 
| 917 |     focusState[&sibling].set(f: false, af: false); | 
| 918 |     focusState[&grandchild].set(f: true, af: true); | 
| 919 |     focusState.active(i: &grandchild); | 
| 920 |     FVERIFY(); | 
| 921 |  | 
| 922 |     // Parenting the item to another item within the same focus scope shouldn't change it's focus. | 
| 923 |     child.setParentItem(&sibling); | 
| 924 |     FVERIFY(); | 
| 925 | } | 
| 926 |  | 
| 927 | void tst_qquickitem::constructor() | 
| 928 | { | 
| 929 |     QScopedPointer<QQuickItem> root(new QQuickItem); | 
| 930 |     QVERIFY(!root->parent()); | 
| 931 |     QVERIFY(!root->parentItem()); | 
| 932 |  | 
| 933 |     QQuickItem *child1 = new QQuickItem(root.data()); | 
| 934 |     QCOMPARE(child1->parent(), root.data()); | 
| 935 |     QCOMPARE(child1->parentItem(), root.data()); | 
| 936 |     QCOMPARE(root->childItems().count(), 1); | 
| 937 |     QCOMPARE(root->childItems().at(0), child1); | 
| 938 |  | 
| 939 |     QQuickItem *child2 = new QQuickItem(root.data()); | 
| 940 |     QCOMPARE(child2->parent(), root.data()); | 
| 941 |     QCOMPARE(child2->parentItem(), root.data()); | 
| 942 |     QCOMPARE(root->childItems().count(), 2); | 
| 943 |     QCOMPARE(root->childItems().at(0), child1); | 
| 944 |     QCOMPARE(root->childItems().at(1), child2); | 
| 945 | } | 
| 946 |  | 
| 947 | void tst_qquickitem::setParentItem() | 
| 948 | { | 
| 949 |     QQuickItem *root = new QQuickItem; | 
| 950 |     QVERIFY(!root->parent()); | 
| 951 |     QVERIFY(!root->parentItem()); | 
| 952 |  | 
| 953 |     QQuickItem *child1 = new QQuickItem; | 
| 954 |     QVERIFY(!child1->parent()); | 
| 955 |     QVERIFY(!child1->parentItem()); | 
| 956 |  | 
| 957 |     child1->setParentItem(root); | 
| 958 |     QVERIFY(!child1->parent()); | 
| 959 |     QCOMPARE(child1->parentItem(), root); | 
| 960 |     QCOMPARE(root->childItems().count(), 1); | 
| 961 |     QCOMPARE(root->childItems().at(0), child1); | 
| 962 |  | 
| 963 |     QQuickItem *child2 = new QQuickItem; | 
| 964 |     QVERIFY(!child2->parent()); | 
| 965 |     QVERIFY(!child2->parentItem()); | 
| 966 |     child2->setParentItem(root); | 
| 967 |     QVERIFY(!child2->parent()); | 
| 968 |     QCOMPARE(child2->parentItem(), root); | 
| 969 |     QCOMPARE(root->childItems().count(), 2); | 
| 970 |     QCOMPARE(root->childItems().at(0), child1); | 
| 971 |     QCOMPARE(root->childItems().at(1), child2); | 
| 972 |  | 
| 973 |     child1->setParentItem(nullptr); | 
| 974 |     QVERIFY(!child1->parent()); | 
| 975 |     QVERIFY(!child1->parentItem()); | 
| 976 |     QCOMPARE(root->childItems().count(), 1); | 
| 977 |     QCOMPARE(root->childItems().at(0), child2); | 
| 978 |  | 
| 979 |     delete root; | 
| 980 |  | 
| 981 |     QVERIFY(!child1->parent()); | 
| 982 |     QVERIFY(!child1->parentItem()); | 
| 983 |     QVERIFY(!child2->parent()); | 
| 984 |     QVERIFY(!child2->parentItem()); | 
| 985 |  | 
| 986 |     delete child1; | 
| 987 |     delete child2; | 
| 988 | } | 
| 989 |  | 
| 990 | void tst_qquickitem::visible() | 
| 991 | { | 
| 992 |     QQuickItem *root = new QQuickItem; | 
| 993 |  | 
| 994 |     QQuickItem *child1 = new QQuickItem; | 
| 995 |     child1->setParentItem(root); | 
| 996 |  | 
| 997 |     QQuickItem *child2 = new QQuickItem; | 
| 998 |     child2->setParentItem(root); | 
| 999 |  | 
| 1000 |     QVERIFY(child1->isVisible()); | 
| 1001 |     QVERIFY(child2->isVisible()); | 
| 1002 |  | 
| 1003 |     root->setVisible(false); | 
| 1004 |     QVERIFY(!child1->isVisible()); | 
| 1005 |     QVERIFY(!child2->isVisible()); | 
| 1006 |  | 
| 1007 |     root->setVisible(true); | 
| 1008 |     QVERIFY(child1->isVisible()); | 
| 1009 |     QVERIFY(child2->isVisible()); | 
| 1010 |  | 
| 1011 |     child1->setVisible(false); | 
| 1012 |     QVERIFY(!child1->isVisible()); | 
| 1013 |     QVERIFY(child2->isVisible()); | 
| 1014 |  | 
| 1015 |     child2->setParentItem(child1); | 
| 1016 |     QVERIFY(!child1->isVisible()); | 
| 1017 |     QVERIFY(!child2->isVisible()); | 
| 1018 |  | 
| 1019 |     child2->setParentItem(root); | 
| 1020 |     QVERIFY(!child1->isVisible()); | 
| 1021 |     QVERIFY(child2->isVisible()); | 
| 1022 |  | 
| 1023 |     delete root; | 
| 1024 |     delete child1; | 
| 1025 |     delete child2; | 
| 1026 | } | 
| 1027 |  | 
| 1028 | void tst_qquickitem::enabled() | 
| 1029 | { | 
| 1030 |     QQuickItem *root = new QQuickItem; | 
| 1031 |  | 
| 1032 |     QQuickItem *child1 = new QQuickItem; | 
| 1033 |     child1->setParentItem(root); | 
| 1034 |  | 
| 1035 |     QQuickItem *child2 = new QQuickItem; | 
| 1036 |     child2->setParentItem(root); | 
| 1037 |  | 
| 1038 |     QVERIFY(child1->isEnabled()); | 
| 1039 |     QVERIFY(child2->isEnabled()); | 
| 1040 |  | 
| 1041 |     root->setEnabled(false); | 
| 1042 |     QVERIFY(!child1->isEnabled()); | 
| 1043 |     QVERIFY(!child2->isEnabled()); | 
| 1044 |  | 
| 1045 |     root->setEnabled(true); | 
| 1046 |     QVERIFY(child1->isEnabled()); | 
| 1047 |     QVERIFY(child2->isEnabled()); | 
| 1048 |  | 
| 1049 |     child1->setEnabled(false); | 
| 1050 |     QVERIFY(!child1->isEnabled()); | 
| 1051 |     QVERIFY(child2->isEnabled()); | 
| 1052 |  | 
| 1053 |     child2->setParentItem(child1); | 
| 1054 |     QVERIFY(!child1->isEnabled()); | 
| 1055 |     QVERIFY(!child2->isEnabled()); | 
| 1056 |  | 
| 1057 |     child2->setParentItem(root); | 
| 1058 |     QVERIFY(!child1->isEnabled()); | 
| 1059 |     QVERIFY(child2->isEnabled()); | 
| 1060 |  | 
| 1061 |     delete root; | 
| 1062 |     delete child1; | 
| 1063 |     delete child2; | 
| 1064 | } | 
| 1065 |  | 
| 1066 | void tst_qquickitem::enabledFocus() | 
| 1067 | { | 
| 1068 |     QQuickWindow window; | 
| 1069 |     QVERIFY(ensureFocus(&window)); | 
| 1070 |  | 
| 1071 |     QQuickFocusScope root; | 
| 1072 |  | 
| 1073 |     root.setFocus(true); | 
| 1074 |     root.setEnabled(false); | 
| 1075 |  | 
| 1076 |     QCOMPARE(root.isEnabled(), false); | 
| 1077 |     QCOMPARE(root.hasFocus(), true); | 
| 1078 |     QCOMPARE(root.hasActiveFocus(), false); | 
| 1079 |  | 
| 1080 |     root.setParentItem(window.contentItem()); | 
| 1081 |  | 
| 1082 |     QCOMPARE(root.isEnabled(), false); | 
| 1083 |     QCOMPARE(root.hasFocus(), true); | 
| 1084 |     QCOMPARE(root.hasActiveFocus(), false); | 
| 1085 |     QCOMPARE(window.activeFocusItem(), window.contentItem()); | 
| 1086 |  | 
| 1087 |     root.setEnabled(true); | 
| 1088 |     QCOMPARE(root.isEnabled(), true); | 
| 1089 |     QCOMPARE(root.hasFocus(), true); | 
| 1090 |     QCOMPARE(root.hasActiveFocus(), true); | 
| 1091 |     QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&root)); | 
| 1092 |  | 
| 1093 |     QQuickItem child1; | 
| 1094 |     child1.setParentItem(&root); | 
| 1095 |  | 
| 1096 |     QCOMPARE(child1.isEnabled(), true); | 
| 1097 |     QCOMPARE(child1.hasFocus(), false); | 
| 1098 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1099 |     QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&root)); | 
| 1100 |  | 
| 1101 |     QQuickItem child2; | 
| 1102 |     child2.setFocus(true); | 
| 1103 |     child2.setParentItem(&root); | 
| 1104 |  | 
| 1105 |     QCOMPARE(root.isEnabled(), true); | 
| 1106 |     QCOMPARE(root.hasFocus(), true); | 
| 1107 |     QCOMPARE(root.hasActiveFocus(), true); | 
| 1108 |     QCOMPARE(child2.isEnabled(), true); | 
| 1109 |     QCOMPARE(child2.hasFocus(), true); | 
| 1110 |     QCOMPARE(child2.hasActiveFocus(), true); | 
| 1111 |     QCOMPARE(window.activeFocusItem(), &child2); | 
| 1112 |  | 
| 1113 |     child2.setEnabled(false); | 
| 1114 |  | 
| 1115 |     QCOMPARE(root.isEnabled(), true); | 
| 1116 |     QCOMPARE(root.hasFocus(), true); | 
| 1117 |     QCOMPARE(root.hasActiveFocus(), true); | 
| 1118 |     QCOMPARE(child1.isEnabled(), true); | 
| 1119 |     QCOMPARE(child1.hasFocus(), false); | 
| 1120 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1121 |     QCOMPARE(child2.isEnabled(), false); | 
| 1122 |     QCOMPARE(child2.hasFocus(), true); | 
| 1123 |     QCOMPARE(child2.hasActiveFocus(), false); | 
| 1124 |     QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&root)); | 
| 1125 |  | 
| 1126 |     child1.setEnabled(false); | 
| 1127 |     QCOMPARE(child1.isEnabled(), false); | 
| 1128 |     QCOMPARE(child1.hasFocus(), false); | 
| 1129 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1130 |  | 
| 1131 |     child1.setFocus(true); | 
| 1132 |     QCOMPARE(child1.isEnabled(), false); | 
| 1133 |     QCOMPARE(child1.hasFocus(), true); | 
| 1134 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1135 |     QCOMPARE(child2.isEnabled(), false); | 
| 1136 |     QCOMPARE(child2.hasFocus(), false); | 
| 1137 |     QCOMPARE(child2.hasActiveFocus(), false); | 
| 1138 |     QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&root)); | 
| 1139 |  | 
| 1140 |     child1.setEnabled(true); | 
| 1141 |     QCOMPARE(child1.isEnabled(), true); | 
| 1142 |     QCOMPARE(child1.hasFocus(), true); | 
| 1143 |     QCOMPARE(child1.hasActiveFocus(), true); | 
| 1144 |     QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&child1)); | 
| 1145 |  | 
| 1146 |     root.setFocus(false); | 
| 1147 |     QCOMPARE(root.isEnabled(), true); | 
| 1148 |     QCOMPARE(root.hasFocus(), false); | 
| 1149 |     QCOMPARE(root.hasActiveFocus(), false); | 
| 1150 |     QCOMPARE(child1.isEnabled(), true); | 
| 1151 |     QCOMPARE(child1.hasFocus(), true); | 
| 1152 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1153 |     QCOMPARE(window.activeFocusItem(), window.contentItem()); | 
| 1154 |  | 
| 1155 |     child2.forceActiveFocus(); | 
| 1156 |     QCOMPARE(root.isEnabled(), true); | 
| 1157 |     QCOMPARE(root.hasFocus(), true); | 
| 1158 |     QCOMPARE(root.hasActiveFocus(), true); | 
| 1159 |     QCOMPARE(child1.isEnabled(), true); | 
| 1160 |     QCOMPARE(child1.hasFocus(), false); | 
| 1161 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1162 |     QCOMPARE(child2.isEnabled(), false); | 
| 1163 |     QCOMPARE(child2.hasFocus(), true); | 
| 1164 |     QCOMPARE(child2.hasActiveFocus(), false); | 
| 1165 |     QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&root)); | 
| 1166 |  | 
| 1167 |     root.setEnabled(false); | 
| 1168 |     QCOMPARE(root.isEnabled(), false); | 
| 1169 |     QCOMPARE(root.hasFocus(), true); | 
| 1170 |     QCOMPARE(root.hasActiveFocus(), false); | 
| 1171 |     QCOMPARE(child1.isEnabled(), false); | 
| 1172 |     QCOMPARE(child1.hasFocus(), false); | 
| 1173 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1174 |     QCOMPARE(child2.isEnabled(), false); | 
| 1175 |     QCOMPARE(child2.hasFocus(), true); | 
| 1176 |     QCOMPARE(child2.hasActiveFocus(), false); | 
| 1177 |     QCOMPARE(window.activeFocusItem(), window.contentItem()); | 
| 1178 |  | 
| 1179 |     child1.forceActiveFocus(); | 
| 1180 |     QCOMPARE(root.isEnabled(), false); | 
| 1181 |     QCOMPARE(root.hasFocus(), true); | 
| 1182 |     QCOMPARE(root.hasActiveFocus(), false); | 
| 1183 |     QCOMPARE(child1.isEnabled(), false); | 
| 1184 |     QCOMPARE(child1.hasFocus(), true); | 
| 1185 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1186 |     QCOMPARE(child2.isEnabled(), false); | 
| 1187 |     QCOMPARE(child2.hasFocus(), false); | 
| 1188 |     QCOMPARE(child2.hasActiveFocus(), false); | 
| 1189 |     QCOMPARE(window.activeFocusItem(), window.contentItem()); | 
| 1190 |  | 
| 1191 |     root.setEnabled(true); | 
| 1192 |     QCOMPARE(root.isEnabled(), true); | 
| 1193 |     QCOMPARE(root.hasFocus(), true); | 
| 1194 |     QCOMPARE(root.hasActiveFocus(), true); | 
| 1195 |     QCOMPARE(child1.isEnabled(), true); | 
| 1196 |     QCOMPARE(child1.hasFocus(), true); | 
| 1197 |     QCOMPARE(child1.hasActiveFocus(), true); | 
| 1198 |     QCOMPARE(child2.isEnabled(), false); | 
| 1199 |     QCOMPARE(child2.hasFocus(), false); | 
| 1200 |     QCOMPARE(child2.hasActiveFocus(), false); | 
| 1201 |     QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&child1)); | 
| 1202 |  | 
| 1203 |     child2.setFocus(true); | 
| 1204 |     QCOMPARE(root.isEnabled(), true); | 
| 1205 |     QCOMPARE(root.hasFocus(), true); | 
| 1206 |     QCOMPARE(root.hasActiveFocus(), true); | 
| 1207 |     QCOMPARE(child1.isEnabled(), true); | 
| 1208 |     QCOMPARE(child1.hasFocus(), false); | 
| 1209 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1210 |     QCOMPARE(child2.isEnabled(), false); | 
| 1211 |     QCOMPARE(child2.hasFocus(), true); | 
| 1212 |     QCOMPARE(child2.hasActiveFocus(), false); | 
| 1213 |     QCOMPARE(window.activeFocusItem(), static_cast<QQuickItem *>(&root)); | 
| 1214 |  | 
| 1215 |     root.setEnabled(false); | 
| 1216 |     QCOMPARE(root.isEnabled(), false); | 
| 1217 |     QCOMPARE(root.hasFocus(), true); | 
| 1218 |     QCOMPARE(root.hasActiveFocus(), false); | 
| 1219 |     QCOMPARE(child1.isEnabled(), false); | 
| 1220 |     QCOMPARE(child1.hasFocus(), false); | 
| 1221 |     QCOMPARE(child1.hasActiveFocus(), false); | 
| 1222 |     QCOMPARE(child2.isEnabled(), false); | 
| 1223 |     QCOMPARE(child2.hasFocus(), true); | 
| 1224 |     QCOMPARE(child2.hasActiveFocus(), false); | 
| 1225 |     QCOMPARE(window.activeFocusItem(), window.contentItem()); | 
| 1226 | } | 
| 1227 |  | 
| 1228 | static inline QByteArray msgItem(const QQuickItem *item) | 
| 1229 | { | 
| 1230 |     QString result; | 
| 1231 |     QDebug(&result) << item; | 
| 1232 |     return result.toLocal8Bit(); | 
| 1233 | } | 
| 1234 |  | 
| 1235 | void tst_qquickitem::mouseGrab() | 
| 1236 | { | 
| 1237 | #ifdef Q_OS_WIN | 
| 1238 |     if (QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES) | 
| 1239 |         QSKIP("Fails in the CI for ANGLE builds on Windows, QTBUG-32664" ); | 
| 1240 | #endif | 
| 1241 |     QQuickWindow window; | 
| 1242 |     window.setFramePosition(QPoint(100, 100)); | 
| 1243 |     window.resize(w: 200, h: 200); | 
| 1244 |     window.show(); | 
| 1245 |     QVERIFY(QTest::qWaitForWindowExposed(&window)); | 
| 1246 |  | 
| 1247 |     QScopedPointer<TestItem> child1(new TestItem); | 
| 1248 |     child1->setObjectName(QStringLiteral("child1" )); | 
| 1249 |     child1->setAcceptedMouseButtons(Qt::LeftButton); | 
| 1250 |     child1->setSize(QSizeF(200, 100)); | 
| 1251 |     child1->setParentItem(window.contentItem()); | 
| 1252 |  | 
| 1253 |     QScopedPointer<TestItem> child2(new TestItem); | 
| 1254 |     child2->setObjectName(QStringLiteral("child2" )); | 
| 1255 |     child2->setAcceptedMouseButtons(Qt::LeftButton); | 
| 1256 |     child2->setY(51); | 
| 1257 |     child2->setSize(QSizeF(200, 100)); | 
| 1258 |     child2->setParentItem(window.contentItem()); | 
| 1259 |  | 
| 1260 |     QTest::mousePress(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1261 |     QTest::qWait(ms: 100); | 
| 1262 |     QVERIFY2(window.mouseGrabberItem() == child1.data(), msgItem(window.mouseGrabberItem()).constData()); | 
| 1263 |     QTest::qWait(ms: 100); | 
| 1264 |  | 
| 1265 |     QCOMPARE(child1->pressCount, 1); | 
| 1266 |     QTest::mouseRelease(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1267 |     QTest::qWait(ms: 50); | 
| 1268 |     QVERIFY2(window.mouseGrabberItem() == nullptr, msgItem(window.mouseGrabberItem()).constData()); | 
| 1269 |     QCOMPARE(child1->releaseCount, 1); | 
| 1270 |  | 
| 1271 |     QTest::mousePress(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1272 |     QTest::qWait(ms: 50); | 
| 1273 |     QVERIFY2(window.mouseGrabberItem() == child1.data(), msgItem(window.mouseGrabberItem()).constData()); | 
| 1274 |     QCOMPARE(child1->pressCount, 2); | 
| 1275 |     child1->setEnabled(false); | 
| 1276 |     QVERIFY2(window.mouseGrabberItem() == nullptr, msgItem(window.mouseGrabberItem()).constData()); | 
| 1277 |     QTest::mouseRelease(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1278 |     QTest::qWait(ms: 50); | 
| 1279 |     QCOMPARE(child1->releaseCount, 1); | 
| 1280 |     child1->setEnabled(true); | 
| 1281 |  | 
| 1282 |     QTest::mousePress(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1283 |     QTest::qWait(ms: 50); | 
| 1284 |     QVERIFY2(window.mouseGrabberItem() == child1.data(), msgItem(window.mouseGrabberItem()).constData()); | 
| 1285 |     QCOMPARE(child1->pressCount, 3); | 
| 1286 |     child1->setVisible(false); | 
| 1287 |     QVERIFY2(window.mouseGrabberItem() == nullptr, msgItem(window.mouseGrabberItem())); | 
| 1288 |     QTest::mouseRelease(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1289 |     QCOMPARE(child1->releaseCount, 1); | 
| 1290 |     child1->setVisible(true); | 
| 1291 |  | 
| 1292 |     QTest::mousePress(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1293 |     QTest::qWait(ms: 50); | 
| 1294 |     QVERIFY2(window.mouseGrabberItem() == child1.data(), msgItem(window.mouseGrabberItem()).constData()); | 
| 1295 |     QCOMPARE(child1->pressCount, 4); | 
| 1296 |     child2->grabMouse(); | 
| 1297 |     QVERIFY2(window.mouseGrabberItem() == child2.data(), msgItem(window.mouseGrabberItem()).constData()); | 
| 1298 |     QTest::mouseRelease(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1299 |     QTest::qWait(ms: 50); | 
| 1300 |     QCOMPARE(child1->releaseCount, 1); | 
| 1301 |     QCOMPARE(child2->releaseCount, 1); | 
| 1302 |  | 
| 1303 |     child2->grabMouse(); | 
| 1304 |     QVERIFY2(window.mouseGrabberItem() == child2.data(), msgItem(window.mouseGrabberItem()).constData()); | 
| 1305 |     QTest::mousePress(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1306 |     QTest::qWait(ms: 50); | 
| 1307 |     QCOMPARE(child1->pressCount, 4); | 
| 1308 |     QCOMPARE(child2->pressCount, 1); | 
| 1309 |     QTest::mouseRelease(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50,50)); | 
| 1310 |     QTest::qWait(ms: 50); | 
| 1311 |     QCOMPARE(child1->releaseCount, 1); | 
| 1312 |     QCOMPARE(child2->releaseCount, 2); | 
| 1313 | } | 
| 1314 |  | 
| 1315 | void tst_qquickitem::touchEventAcceptIgnore_data() | 
| 1316 | { | 
| 1317 |     QTest::addColumn<bool>(name: "itemSupportsTouch" ); | 
| 1318 |  | 
| 1319 |     QTest::newRow(dataTag: "with touch" ) << true; | 
| 1320 |     QTest::newRow(dataTag: "without touch" ) << false; | 
| 1321 | } | 
| 1322 |  | 
| 1323 | void tst_qquickitem::touchEventAcceptIgnore() | 
| 1324 | { | 
| 1325 |     QFETCH(bool, itemSupportsTouch); | 
| 1326 |  | 
| 1327 |     TestWindow window; | 
| 1328 |     window.resize(w: 100, h: 100); | 
| 1329 |     window.show(); | 
| 1330 |     QVERIFY(QTest::qWaitForWindowExposed(&window)); | 
| 1331 |  | 
| 1332 |     QScopedPointer<TestItem> item(new TestItem); | 
| 1333 |     item->setSize(QSizeF(100, 100)); | 
| 1334 |     item->setParentItem(window.contentItem()); | 
| 1335 |     item->acceptIncomingTouchEvents = itemSupportsTouch; | 
| 1336 |  | 
| 1337 |     static QTouchDevice* device = nullptr; | 
| 1338 |     if (!device) { | 
| 1339 |         device =new QTouchDevice; | 
| 1340 |         device->setType(QTouchDevice::TouchScreen); | 
| 1341 |         QWindowSystemInterface::registerTouchDevice(device); | 
| 1342 |     } | 
| 1343 |  | 
| 1344 |     // Send Begin, Update & End touch sequence | 
| 1345 |     { | 
| 1346 |         QTouchEvent::TouchPoint point; | 
| 1347 |         point.setId(1); | 
| 1348 |         point.setPos(QPointF(50, 50)); | 
| 1349 |         point.setScreenPos(point.pos()); | 
| 1350 |         point.setState(Qt::TouchPointPressed); | 
| 1351 |  | 
| 1352 |         QTouchEvent event(QEvent::TouchBegin, device, | 
| 1353 |                           Qt::NoModifier, | 
| 1354 |                           Qt::TouchPointPressed, | 
| 1355 |                           QList<QTouchEvent::TouchPoint>() << point); | 
| 1356 |         event.setAccepted(true); | 
| 1357 |  | 
| 1358 |         item->touchEventReached = false; | 
| 1359 |  | 
| 1360 |         bool accepted = window.event(event: &event); | 
| 1361 |         QQuickTouchUtils::flush(window: &window); | 
| 1362 |  | 
| 1363 |         QVERIFY(item->touchEventReached); | 
| 1364 |  | 
| 1365 |         // always true because QtQuick always eats touch events so as to not | 
| 1366 |         // allow QtGui to synthesise them for us. | 
| 1367 |         QCOMPARE(accepted && event.isAccepted(), true); | 
| 1368 |     } | 
| 1369 |     { | 
| 1370 |         QTouchEvent::TouchPoint point; | 
| 1371 |         point.setId(1); | 
| 1372 |         point.setPos(QPointF(60, 60)); | 
| 1373 |         point.setScreenPos(point.pos()); | 
| 1374 |         point.setState(Qt::TouchPointMoved); | 
| 1375 |  | 
| 1376 |         QTouchEvent event(QEvent::TouchUpdate, device, | 
| 1377 |                           Qt::NoModifier, | 
| 1378 |                           Qt::TouchPointMoved, | 
| 1379 |                           QList<QTouchEvent::TouchPoint>() << point); | 
| 1380 |         event.setAccepted(true); | 
| 1381 |  | 
| 1382 |         item->touchEventReached = false; | 
| 1383 |  | 
| 1384 |         bool accepted = window.event(event: &event); | 
| 1385 |         QQuickTouchUtils::flush(window: &window); | 
| 1386 |  | 
| 1387 |         QCOMPARE(item->touchEventReached, itemSupportsTouch); | 
| 1388 |  | 
| 1389 |         // always true because QtQuick always eats touch events so as to not | 
| 1390 |         // allow QtGui to synthesise them for us. | 
| 1391 |         QCOMPARE(accepted && event.isAccepted(), true); | 
| 1392 |     } | 
| 1393 |     { | 
| 1394 |         QTouchEvent::TouchPoint point; | 
| 1395 |         point.setId(1); | 
| 1396 |         point.setPos(QPointF(60, 60)); | 
| 1397 |         point.setScreenPos(point.pos()); | 
| 1398 |         point.setState(Qt::TouchPointReleased); | 
| 1399 |  | 
| 1400 |         QTouchEvent event(QEvent::TouchEnd, device, | 
| 1401 |                           Qt::NoModifier, | 
| 1402 |                           Qt::TouchPointReleased, | 
| 1403 |                           QList<QTouchEvent::TouchPoint>() << point); | 
| 1404 |         event.setAccepted(true); | 
| 1405 |  | 
| 1406 |         item->touchEventReached = false; | 
| 1407 |  | 
| 1408 |         bool accepted = window.event(event: &event); | 
| 1409 |         QQuickTouchUtils::flush(window: &window); | 
| 1410 |  | 
| 1411 |         QCOMPARE(item->touchEventReached, itemSupportsTouch); | 
| 1412 |  | 
| 1413 |         // always true because QtQuick always eats touch events so as to not | 
| 1414 |         // allow QtGui to synthesise them for us. | 
| 1415 |         QCOMPARE(accepted && event.isAccepted(), true); | 
| 1416 |     } | 
| 1417 | } | 
| 1418 |  | 
| 1419 | void tst_qquickitem::polishOutsideAnimation() | 
| 1420 | { | 
| 1421 |     QQuickWindow *window = new QQuickWindow; | 
| 1422 |     window->resize(w: 200, h: 200); | 
| 1423 |     window->show(); | 
| 1424 |  | 
| 1425 |     TestPolishItem *item = new TestPolishItem(window->contentItem()); | 
| 1426 |     item->setSize(QSizeF(200, 100)); | 
| 1427 |     QTest::qWait(ms: 50); | 
| 1428 |  | 
| 1429 |     QTimer::singleShot(msec: 10, receiver: item, SLOT(doPolish())); | 
| 1430 |     QTRY_VERIFY(item->wasPolished); | 
| 1431 |  | 
| 1432 |     delete item; | 
| 1433 |     delete window; | 
| 1434 | } | 
| 1435 |  | 
| 1436 | void tst_qquickitem::polishOnCompleted() | 
| 1437 | { | 
| 1438 |     QQuickView view; | 
| 1439 |     view.setSource(testFileUrl(fileName: "polishOnCompleted.qml" )); | 
| 1440 |     view.show(); | 
| 1441 |     QVERIFY(QTest::qWaitForWindowExposed(&view)); | 
| 1442 |  | 
| 1443 |     TestPolishItem *item = qobject_cast<TestPolishItem*>(object: view.rootObject()); | 
| 1444 |     QVERIFY(item); | 
| 1445 |  | 
| 1446 |     QTRY_VERIFY(item->wasPolished); | 
| 1447 | } | 
| 1448 |  | 
| 1449 | struct PolishItemSpan { | 
| 1450 |     int itemCount;      // Number of items... | 
| 1451 |     int repolishCount;  // ...repolishing 'repolishCount' times | 
| 1452 | }; | 
| 1453 |  | 
| 1454 | /* | 
| 1455 |  * For instance, two consecutive spans {99,0} and {1,2000} } instructs to | 
| 1456 |  * construct 99 items with no repolish, and 1 item with 2000 repolishes (in that sibling order) | 
| 1457 |  */ | 
| 1458 | typedef QVector<PolishItemSpan> PolishItemSpans; | 
| 1459 |  | 
| 1460 | Q_DECLARE_METATYPE(PolishItemSpan) | 
| 1461 | Q_DECLARE_METATYPE(PolishItemSpans) | 
| 1462 |  | 
| 1463 | void tst_qquickitem::polishLoopDetection_data() | 
| 1464 | { | 
| 1465 |     QTest::addColumn<PolishItemSpans>(name: "listOfItemsToPolish" ); | 
| 1466 |     QTest::addColumn<int>(name: "expectedNumberOfWarnings" ); | 
| 1467 |  | 
| 1468 |     QTest::newRow(dataTag: "test1.100" ) <<   PolishItemSpans({ {.itemCount: 1, .repolishCount: 100} }) << 0; | 
| 1469 |     QTest::newRow(dataTag: "test1.1002" ) <<  PolishItemSpans({ {.itemCount: 1, .repolishCount: 1002} }) << 3; | 
| 1470 |     QTest::newRow(dataTag: "test1.2020" ) <<  PolishItemSpans({ {.itemCount: 1, .repolishCount: 2020} }) << 10; | 
| 1471 |  | 
| 1472 |     QTest::newRow(dataTag: "test5.1" ) <<    PolishItemSpans({ {.itemCount: 5, .repolishCount: 1} }) << 0; | 
| 1473 |     QTest::newRow(dataTag: "test5.10" ) <<   PolishItemSpans({ {.itemCount: 5, .repolishCount: 10} }) << 0; | 
| 1474 |     QTest::newRow(dataTag: "test5.100" ) <<  PolishItemSpans({ {.itemCount: 5, .repolishCount: 100} }) << 0; | 
| 1475 |     QTest::newRow(dataTag: "test5.1000" ) << PolishItemSpans({ {.itemCount: 5, .repolishCount: 1000} }) << 5; | 
| 1476 |  | 
| 1477 |     QTest::newRow(dataTag: "test1000.1" ) <<  PolishItemSpans({ {.itemCount: 1000,.repolishCount: 1} }) << 0; | 
| 1478 |     QTest::newRow(dataTag: "test2000.1" ) <<  PolishItemSpans({ {.itemCount: 2000,.repolishCount: 1} }) << 0; | 
| 1479 |  | 
| 1480 |     QTest::newRow(dataTag: "test99.0-1.1100" ) << PolishItemSpans({ {.itemCount: 99,.repolishCount: 0},{.itemCount: 1,.repolishCount: 1100} }) << 5; | 
| 1481 |     QTest::newRow(dataTag: "test98.0-2.1100" ) << PolishItemSpans({ {.itemCount: 98,.repolishCount: 0},{.itemCount: 2,.repolishCount: 1100} }) << 5+5; | 
| 1482 |  | 
| 1483 |     // reverse the two above | 
| 1484 |     QTest::newRow(dataTag: "test1.1100-99.0" ) << PolishItemSpans({ {.itemCount: 1,.repolishCount: 1100},{.itemCount: 99,.repolishCount: 0} }) << 5; | 
| 1485 |     QTest::newRow(dataTag: "test2.1100-98.0" ) << PolishItemSpans({ {.itemCount: 2,.repolishCount: 1100},{.itemCount: 98,.repolishCount: 0} }) << 5+5; | 
| 1486 | } | 
| 1487 |  | 
| 1488 | void tst_qquickitem::polishLoopDetection() | 
| 1489 | { | 
| 1490 |     QFETCH(PolishItemSpans, listOfItemsToPolish); | 
| 1491 |     QFETCH(int, expectedNumberOfWarnings); | 
| 1492 |  | 
| 1493 |     QQuickWindow window; | 
| 1494 |     window.resize(w: 200, h: 200); | 
| 1495 |     window.show(); | 
| 1496 |  | 
| 1497 |     TestPolishItem *item = nullptr; | 
| 1498 |     int count = 0; | 
| 1499 |     for (PolishItemSpan s : listOfItemsToPolish) { | 
| 1500 |         for (int i = 0; i < s.itemCount; ++i) { | 
| 1501 |             item = new TestPolishItem(window.contentItem()); | 
| 1502 |             item->setSize(QSizeF(200, 100)); | 
| 1503 |             item->repolishLoopCount = s.repolishCount; | 
| 1504 |             item->setObjectName(QString::fromLatin1(str: "obj%1" ).arg(a: count++)); | 
| 1505 |         } | 
| 1506 |     } | 
| 1507 |  | 
| 1508 |     for (int i = 0; i < expectedNumberOfWarnings; ++i) { | 
| 1509 |         QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*possible QQuickItem..polish.. loop.*" )); | 
| 1510 |         QTest::ignoreMessage(type: QtWarningMsg, messagePattern: QRegularExpression(".*TestPolishItem.* called polish.. inside updatePolish.. of TestPolishItem.*" )); | 
| 1511 |     } | 
| 1512 |  | 
| 1513 |     QList<QQuickItem*> items = window.contentItem()->childItems(); | 
| 1514 |     for (int i = 0; i < items.count(); ++i) { | 
| 1515 |         static_cast<TestPolishItem*>(items.at(i))->doPolish(); | 
| 1516 |     } | 
| 1517 |     item = static_cast<TestPolishItem*>(items.first()); | 
| 1518 |     // item is the last item, so we wait until the last item reached 0 | 
| 1519 |     QVERIFY(QTest::qWaitFor([=](){return item->repolishLoopCount == 0 && item->wasPolished;})); | 
| 1520 | } | 
| 1521 |  | 
| 1522 | void tst_qquickitem::wheelEvent_data() | 
| 1523 | { | 
| 1524 |     QTest::addColumn<bool>(name: "visible" ); | 
| 1525 |     QTest::addColumn<bool>(name: "enabled" ); | 
| 1526 |  | 
| 1527 |     QTest::newRow(dataTag: "visible and enabled" ) << true << true; | 
| 1528 |     QTest::newRow(dataTag: "visible and disabled" ) << true << false; | 
| 1529 |     QTest::newRow(dataTag: "invisible and enabled" ) << false << true; | 
| 1530 |     QTest::newRow(dataTag: "invisible and disabled" ) << false << false; | 
| 1531 | } | 
| 1532 |  | 
| 1533 | void tst_qquickitem::wheelEvent() | 
| 1534 | { | 
| 1535 |     QFETCH(bool, visible); | 
| 1536 |     QFETCH(bool, enabled); | 
| 1537 |  | 
| 1538 |     const bool shouldReceiveWheelEvents = visible && enabled; | 
| 1539 |  | 
| 1540 |     const int width = 200; | 
| 1541 |     const int height = 200; | 
| 1542 |  | 
| 1543 |     QQuickWindow window; | 
| 1544 |     window.resize(w: width, h: height); | 
| 1545 |     window.show(); | 
| 1546 |     QVERIFY(QTest::qWaitForWindowExposed(&window)); | 
| 1547 |  | 
| 1548 |     TestItem *item = new TestItem; | 
| 1549 |     item->setSize(QSizeF(width, height)); | 
| 1550 |     item->setParentItem(window.contentItem()); | 
| 1551 |  | 
| 1552 |     item->setEnabled(enabled); | 
| 1553 |     item->setVisible(visible); | 
| 1554 |  | 
| 1555 |     QPoint localPoint(width / 2, height / 2); | 
| 1556 |     QPoint globalPoint = window.mapToGlobal(pos: localPoint); | 
| 1557 |     QWheelEvent event(localPoint, globalPoint, QPoint(0, 0), QPoint(0, -120), | 
| 1558 |                       Qt::NoButton, Qt::NoModifier, Qt::NoScrollPhase, false); | 
| 1559 |     event.setTimestamp(123456UL); | 
| 1560 |     event.setAccepted(false); | 
| 1561 |     QGuiApplication::sendEvent(receiver: &window, event: &event); | 
| 1562 |  | 
| 1563 |     if (shouldReceiveWheelEvents) { | 
| 1564 |         QVERIFY(event.isAccepted()); | 
| 1565 |         QCOMPARE(item->wheelCount, 1); | 
| 1566 |         QCOMPARE(item->timestamp, 123456UL); | 
| 1567 |         QCOMPARE(item->lastWheelEventPos, localPoint); | 
| 1568 |         QCOMPARE(item->lastWheelEventGlobalPos, globalPoint); | 
| 1569 |     } else { | 
| 1570 |         QVERIFY(!event.isAccepted()); | 
| 1571 |         QCOMPARE(item->wheelCount, 0); | 
| 1572 |     } | 
| 1573 | } | 
| 1574 |  | 
| 1575 | class HoverItem : public QQuickItem | 
| 1576 | { | 
| 1577 | Q_OBJECT | 
| 1578 | public: | 
| 1579 |     HoverItem(QQuickItem *parent = nullptr) | 
| 1580 |         : QQuickItem(parent), hoverEnterCount(0), hoverMoveCount(0), hoverLeaveCount(0) | 
| 1581 |     { } | 
| 1582 |     void resetCounters() { | 
| 1583 |         hoverEnterCount = 0; | 
| 1584 |         hoverMoveCount = 0; | 
| 1585 |         hoverLeaveCount = 0; | 
| 1586 |     } | 
| 1587 |     int hoverEnterCount; | 
| 1588 |     int hoverMoveCount; | 
| 1589 |     int hoverLeaveCount; | 
| 1590 | protected: | 
| 1591 |     virtual void hoverEnterEvent(QHoverEvent *event) { | 
| 1592 |         event->accept(); | 
| 1593 |         ++hoverEnterCount; | 
| 1594 |     } | 
| 1595 |     virtual void hoverMoveEvent(QHoverEvent *event) { | 
| 1596 |         event->accept(); | 
| 1597 |         ++hoverMoveCount; | 
| 1598 |     } | 
| 1599 |     virtual void hoverLeaveEvent(QHoverEvent *event) { | 
| 1600 |         event->accept(); | 
| 1601 |         ++hoverLeaveCount; | 
| 1602 |     } | 
| 1603 | }; | 
| 1604 |  | 
| 1605 | void tst_qquickitem::hoverEvent_data() | 
| 1606 | { | 
| 1607 |     QTest::addColumn<bool>(name: "visible" ); | 
| 1608 |     QTest::addColumn<bool>(name: "enabled" ); | 
| 1609 |     QTest::addColumn<bool>(name: "acceptHoverEvents" ); | 
| 1610 |  | 
| 1611 |     QTest::newRow(dataTag: "visible, enabled, accept hover" ) << true << true << true; | 
| 1612 |     QTest::newRow(dataTag: "visible, disabled, accept hover" ) << true << false << true; | 
| 1613 |     QTest::newRow(dataTag: "invisible, enabled, accept hover" ) << false << true << true; | 
| 1614 |     QTest::newRow(dataTag: "invisible, disabled, accept hover" ) << false << false << true; | 
| 1615 |  | 
| 1616 |     QTest::newRow(dataTag: "visible, enabled, not accept hover" ) << true << true << false; | 
| 1617 |     QTest::newRow(dataTag: "visible, disabled, not accept hover" ) << true << false << false; | 
| 1618 |     QTest::newRow(dataTag: "invisible, enabled, not accept hover" ) << false << true << false; | 
| 1619 |     QTest::newRow(dataTag: "invisible, disabled, not accept hover" ) << false << false << false; | 
| 1620 | } | 
| 1621 |  | 
| 1622 | // ### For some unknown reason QTest::mouseMove() isn't working correctly. | 
| 1623 | static void sendMouseMove(QObject *object, const QPoint &position) | 
| 1624 | { | 
| 1625 |     QMouseEvent moveEvent(QEvent::MouseMove, position, Qt::NoButton, Qt::NoButton, nullptr); | 
| 1626 |     QGuiApplication::sendEvent(receiver: object, event: &moveEvent); | 
| 1627 | } | 
| 1628 |  | 
| 1629 | void tst_qquickitem::hoverEvent() | 
| 1630 | { | 
| 1631 |     QFETCH(bool, visible); | 
| 1632 |     QFETCH(bool, enabled); | 
| 1633 |     QFETCH(bool, acceptHoverEvents); | 
| 1634 |  | 
| 1635 |     QQuickWindow *window = new QQuickWindow(); | 
| 1636 |     window->resize(w: 200, h: 200); | 
| 1637 |     window->show(); | 
| 1638 |  | 
| 1639 |     HoverItem *item = new HoverItem; | 
| 1640 |     item->setSize(QSizeF(100, 100)); | 
| 1641 |     item->setParentItem(window->contentItem()); | 
| 1642 |  | 
| 1643 |     item->setEnabled(enabled); | 
| 1644 |     item->setVisible(visible); | 
| 1645 |     item->setAcceptHoverEvents(acceptHoverEvents); | 
| 1646 |  | 
| 1647 |     const QPoint outside(150, 150); | 
| 1648 |     const QPoint inside(50, 50); | 
| 1649 |     const QPoint anotherInside(51, 51); | 
| 1650 |  | 
| 1651 |     sendMouseMove(object: window, position: outside); | 
| 1652 |     item->resetCounters(); | 
| 1653 |  | 
| 1654 |     // Enter, then move twice inside, then leave. | 
| 1655 |     sendMouseMove(object: window, position: inside); | 
| 1656 |     sendMouseMove(object: window, position: anotherInside); | 
| 1657 |     sendMouseMove(object: window, position: inside); | 
| 1658 |     sendMouseMove(object: window, position: outside); | 
| 1659 |  | 
| 1660 |     const bool shouldReceiveHoverEvents = visible && enabled && acceptHoverEvents; | 
| 1661 |     if (shouldReceiveHoverEvents) { | 
| 1662 |         QCOMPARE(item->hoverEnterCount, 1); | 
| 1663 |         QCOMPARE(item->hoverMoveCount, 2); | 
| 1664 |         QCOMPARE(item->hoverLeaveCount, 1); | 
| 1665 |     } else { | 
| 1666 |         QCOMPARE(item->hoverEnterCount, 0); | 
| 1667 |         QCOMPARE(item->hoverMoveCount, 0); | 
| 1668 |         QCOMPARE(item->hoverLeaveCount, 0); | 
| 1669 |     } | 
| 1670 |  | 
| 1671 |     delete window; | 
| 1672 | } | 
| 1673 |  | 
| 1674 | void tst_qquickitem::hoverEventInParent() | 
| 1675 | { | 
| 1676 |     QQuickWindow window; | 
| 1677 |     window.resize(w: 200, h: 200); | 
| 1678 |     window.show(); | 
| 1679 |  | 
| 1680 |     HoverItem *parentItem = new HoverItem(window.contentItem()); | 
| 1681 |     parentItem->setSize(QSizeF(200, 200)); | 
| 1682 |     parentItem->setAcceptHoverEvents(true); | 
| 1683 |  | 
| 1684 |     HoverItem *leftItem = new HoverItem(parentItem); | 
| 1685 |     leftItem->setSize(QSizeF(100, 200)); | 
| 1686 |     leftItem->setAcceptHoverEvents(true); | 
| 1687 |  | 
| 1688 |     HoverItem *rightItem = new HoverItem(parentItem); | 
| 1689 |     rightItem->setSize(QSizeF(100, 200)); | 
| 1690 |     rightItem->setPosition(QPointF(100, 0)); | 
| 1691 |     rightItem->setAcceptHoverEvents(true); | 
| 1692 |  | 
| 1693 |     const QPoint insideLeft(50, 100); | 
| 1694 |     const QPoint insideRight(150, 100); | 
| 1695 |  | 
| 1696 |     sendMouseMove(object: &window, position: insideLeft); | 
| 1697 |     parentItem->resetCounters(); | 
| 1698 |     leftItem->resetCounters(); | 
| 1699 |     rightItem->resetCounters(); | 
| 1700 |  | 
| 1701 |     sendMouseMove(object: &window, position: insideRight); | 
| 1702 |     QCOMPARE(parentItem->hoverEnterCount, 0); | 
| 1703 |     QCOMPARE(parentItem->hoverLeaveCount, 0); | 
| 1704 |     QCOMPARE(leftItem->hoverEnterCount, 0); | 
| 1705 |     QCOMPARE(leftItem->hoverLeaveCount, 1); | 
| 1706 |     QCOMPARE(rightItem->hoverEnterCount, 1); | 
| 1707 |     QCOMPARE(rightItem->hoverLeaveCount, 0); | 
| 1708 |  | 
| 1709 |     sendMouseMove(object: &window, position: insideLeft); | 
| 1710 |     QCOMPARE(parentItem->hoverEnterCount, 0); | 
| 1711 |     QCOMPARE(parentItem->hoverLeaveCount, 0); | 
| 1712 |     QCOMPARE(leftItem->hoverEnterCount, 1); | 
| 1713 |     QCOMPARE(leftItem->hoverLeaveCount, 1); | 
| 1714 |     QCOMPARE(rightItem->hoverEnterCount, 1); | 
| 1715 |     QCOMPARE(rightItem->hoverLeaveCount, 1); | 
| 1716 | } | 
| 1717 |  | 
| 1718 | void tst_qquickitem::paintOrder_data() | 
| 1719 | { | 
| 1720 |     const QUrl order1Url = testFileUrl(fileName: "order.1.qml" ); | 
| 1721 |     const QUrl order2Url = testFileUrl(fileName: "order.2.qml" ); | 
| 1722 |  | 
| 1723 |     QTest::addColumn<QUrl>(name: "source" ); | 
| 1724 |     QTest::addColumn<int>(name: "op" ); | 
| 1725 |     QTest::addColumn<QVariant>(name: "param1" ); | 
| 1726 |     QTest::addColumn<QVariant>(name: "param2" ); | 
| 1727 |     QTest::addColumn<QStringList>(name: "expected" ); | 
| 1728 |  | 
| 1729 |     QTest::newRow(dataTag: "test 1 noop" ) << order1Url | 
| 1730 |         << int(NoOp) << QVariant() << QVariant() | 
| 1731 |         << (QStringList() << "1"  << "2"  << "3" ); | 
| 1732 |     QTest::newRow(dataTag: "test 1 add" ) << order1Url | 
| 1733 |         << int(Append) << QVariant("new" ) << QVariant() | 
| 1734 |         << (QStringList() << "1"  << "2"  << "3"  << "new" ); | 
| 1735 |     QTest::newRow(dataTag: "test 1 remove" ) << order1Url | 
| 1736 |         << int(Remove) << QVariant(1) << QVariant() | 
| 1737 |         << (QStringList() << "1"  << "3" ); | 
| 1738 |     QTest::newRow(dataTag: "test 1 stack before" ) << order1Url | 
| 1739 |         << int(StackBefore) << QVariant(2) << QVariant(1) | 
| 1740 |         << (QStringList() << "1"  << "3"  << "2" ); | 
| 1741 |     QTest::newRow(dataTag: "test 1 stack after" ) << order1Url | 
| 1742 |         << int(StackAfter) << QVariant(0) << QVariant(1) | 
| 1743 |         << (QStringList() << "2"  << "1"  << "3" ); | 
| 1744 |     QTest::newRow(dataTag: "test 1 set z" ) << order1Url | 
| 1745 |         << int(SetZ) << QVariant(1) << QVariant(qreal(1.)) | 
| 1746 |         << (QStringList() << "1"  << "3"  << "2" ); | 
| 1747 |  | 
| 1748 |     QTest::newRow(dataTag: "test 2 noop" ) << order2Url | 
| 1749 |         << int(NoOp) << QVariant() << QVariant() | 
| 1750 |         << (QStringList() << "1"  << "3"  << "2" ); | 
| 1751 |     QTest::newRow(dataTag: "test 2 add" ) << order2Url | 
| 1752 |         << int(Append) << QVariant("new" ) << QVariant() | 
| 1753 |         << (QStringList() << "1"  << "3"  << "new"  << "2" ); | 
| 1754 |     QTest::newRow(dataTag: "test 2 remove 1" ) << order2Url | 
| 1755 |         << int(Remove) << QVariant(1) << QVariant() | 
| 1756 |         << (QStringList() << "1"  << "3" ); | 
| 1757 |     QTest::newRow(dataTag: "test 2 remove 2" ) << order2Url | 
| 1758 |         << int(Remove) << QVariant(2) << QVariant() | 
| 1759 |         << (QStringList() << "1"  << "2" ); | 
| 1760 |     QTest::newRow(dataTag: "test 2 stack before 1" ) << order2Url | 
| 1761 |         << int(StackBefore) << QVariant(1) << QVariant(0) | 
| 1762 |         << (QStringList() << "1"  << "3"  << "2" ); | 
| 1763 |     QTest::newRow(dataTag: "test 2 stack before 2" ) << order2Url | 
| 1764 |         << int(StackBefore) << QVariant(2) << QVariant(0) | 
| 1765 |         << (QStringList() << "3"  << "1"  << "2" ); | 
| 1766 |     QTest::newRow(dataTag: "test 2 stack after 1" ) << order2Url | 
| 1767 |         << int(StackAfter) << QVariant(0) << QVariant(1) | 
| 1768 |         << (QStringList() << "1"  << "3"  << "2" ); | 
| 1769 |     QTest::newRow(dataTag: "test 2 stack after 2" ) << order2Url | 
| 1770 |         << int(StackAfter) << QVariant(0) << QVariant(2) | 
| 1771 |         << (QStringList() << "3"  << "1"  << "2" ); | 
| 1772 |     QTest::newRow(dataTag: "test 1 set z" ) << order1Url | 
| 1773 |         << int(SetZ) << QVariant(2) << QVariant(qreal(2.)) | 
| 1774 |         << (QStringList() << "1"  << "2"  << "3" ); | 
| 1775 | } | 
| 1776 |  | 
| 1777 | void tst_qquickitem::paintOrder() | 
| 1778 | { | 
| 1779 |     QFETCH(QUrl, source); | 
| 1780 |     QFETCH(int, op); | 
| 1781 |     QFETCH(QVariant, param1); | 
| 1782 |     QFETCH(QVariant, param2); | 
| 1783 |     QFETCH(QStringList, expected); | 
| 1784 |  | 
| 1785 |     QQuickView view; | 
| 1786 |     view.setSource(source); | 
| 1787 |  | 
| 1788 |     QQuickItem *root = qobject_cast<QQuickItem*>(object: view.rootObject()); | 
| 1789 |     QVERIFY(root); | 
| 1790 |  | 
| 1791 |     switch (op) { | 
| 1792 |         case Append: { | 
| 1793 |                 QQuickItem *item = new QQuickItem(root); | 
| 1794 |                 item->setObjectName(param1.toString()); | 
| 1795 |             } | 
| 1796 |             break; | 
| 1797 |         case Remove: { | 
| 1798 |                 QQuickItem *item = root->childItems().at(i: param1.toInt()); | 
| 1799 |                 delete item; | 
| 1800 |             } | 
| 1801 |             break; | 
| 1802 |         case StackBefore: { | 
| 1803 |                 QQuickItem *item1 = root->childItems().at(i: param1.toInt()); | 
| 1804 |                 QQuickItem *item2 = root->childItems().at(i: param2.toInt()); | 
| 1805 |                 item1->stackBefore(item2); | 
| 1806 |             } | 
| 1807 |             break; | 
| 1808 |         case StackAfter: { | 
| 1809 |                 QQuickItem *item1 = root->childItems().at(i: param1.toInt()); | 
| 1810 |                 QQuickItem *item2 = root->childItems().at(i: param2.toInt()); | 
| 1811 |                 item1->stackAfter(item2); | 
| 1812 |             } | 
| 1813 |             break; | 
| 1814 |         case SetZ: { | 
| 1815 |                 QQuickItem *item = root->childItems().at(i: param1.toInt()); | 
| 1816 |                 item->setZ(param2.toReal()); | 
| 1817 |             } | 
| 1818 |             break; | 
| 1819 |         default: | 
| 1820 |             break; | 
| 1821 |     } | 
| 1822 |  | 
| 1823 |     QList<QQuickItem*> list = QQuickItemPrivate::get(item: root)->paintOrderChildItems(); | 
| 1824 |  | 
| 1825 |     QStringList items; | 
| 1826 |     for (int i = 0; i < list.count(); ++i) | 
| 1827 |         items << list.at(i)->objectName(); | 
| 1828 |  | 
| 1829 |     QCOMPARE(items, expected); | 
| 1830 | } | 
| 1831 |  | 
| 1832 | void tst_qquickitem::acceptedMouseButtons() | 
| 1833 | { | 
| 1834 |     TestItem item; | 
| 1835 |     QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::NoButton)); | 
| 1836 |  | 
| 1837 |     QQuickWindow window; | 
| 1838 |     item.setSize(QSizeF(200,100)); | 
| 1839 |     item.setParentItem(window.contentItem()); | 
| 1840 |  | 
| 1841 |     QTest::mousePress(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1842 |     QTest::mouseRelease(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1843 |     QCOMPARE(item.pressCount, 0); | 
| 1844 |     QCOMPARE(item.releaseCount, 0); | 
| 1845 |  | 
| 1846 |     QTest::mousePress(window: &window, button: Qt::RightButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1847 |     QTest::mouseRelease(window: &window, button: Qt::RightButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1848 |     QCOMPARE(item.pressCount, 0); | 
| 1849 |     QCOMPARE(item.releaseCount, 0); | 
| 1850 |  | 
| 1851 |     QTest::mousePress(window: &window, button: Qt::MiddleButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1852 |     QTest::mouseRelease(window: &window, button: Qt::MiddleButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1853 |     QCOMPARE(item.pressCount, 0); | 
| 1854 |     QCOMPARE(item.releaseCount, 0); | 
| 1855 |  | 
| 1856 |     item.setAcceptedMouseButtons(Qt::LeftButton); | 
| 1857 |     QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::LeftButton)); | 
| 1858 |  | 
| 1859 |     QTest::mousePress(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1860 |     QTest::mouseRelease(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1861 |     QCOMPARE(item.pressCount, 1); | 
| 1862 |     QCOMPARE(item.releaseCount, 1); | 
| 1863 |  | 
| 1864 |     QTest::mousePress(window: &window, button: Qt::RightButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1865 |     QTest::mouseRelease(window: &window, button: Qt::RightButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1866 |     QCOMPARE(item.pressCount, 1); | 
| 1867 |     QCOMPARE(item.releaseCount, 1); | 
| 1868 |  | 
| 1869 |     QTest::mousePress(window: &window, button: Qt::MiddleButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1870 |     QTest::mouseRelease(window: &window, button: Qt::MiddleButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1871 |     QCOMPARE(item.pressCount, 1); | 
| 1872 |     QCOMPARE(item.releaseCount, 1); | 
| 1873 |  | 
| 1874 |     item.setAcceptedMouseButtons(Qt::RightButton | Qt::MiddleButton); | 
| 1875 |     QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::RightButton | Qt::MiddleButton)); | 
| 1876 |  | 
| 1877 |     QTest::mousePress(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1878 |     QTest::mouseRelease(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1879 |     QCOMPARE(item.pressCount, 1); | 
| 1880 |     QCOMPARE(item.releaseCount, 1); | 
| 1881 |  | 
| 1882 |     QTest::mousePress(window: &window, button: Qt::RightButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1883 |     QTest::mouseRelease(window: &window, button: Qt::RightButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1884 |     QCOMPARE(item.pressCount, 2); | 
| 1885 |     QCOMPARE(item.releaseCount, 2); | 
| 1886 |  | 
| 1887 |     QTest::mousePress(window: &window, button: Qt::MiddleButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1888 |     QTest::mouseRelease(window: &window, button: Qt::MiddleButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 1889 |     QCOMPARE(item.pressCount, 3); | 
| 1890 |     QCOMPARE(item.releaseCount, 3); | 
| 1891 | } | 
| 1892 |  | 
| 1893 | static void gc(QQmlEngine &engine) | 
| 1894 | { | 
| 1895 |     engine.collectGarbage(); | 
| 1896 |     QCoreApplication::sendPostedEvents(receiver: nullptr, event_type: QEvent::DeferredDelete); | 
| 1897 |     QCoreApplication::processEvents(); | 
| 1898 | } | 
| 1899 |  | 
| 1900 | void tst_qquickitem::visualParentOwnership() | 
| 1901 | { | 
| 1902 |     QQmlEngine engine; | 
| 1903 |     QQmlComponent component(&engine, testFileUrl(fileName: "visualParentOwnership.qml" )); | 
| 1904 |  | 
| 1905 |     QScopedPointer<QQuickItem> root(qobject_cast<QQuickItem*>(object: component.create())); | 
| 1906 |     QVERIFY(root); | 
| 1907 |  | 
| 1908 |     QVariant newObject; | 
| 1909 |     { | 
| 1910 |         QVERIFY(QMetaObject::invokeMethod(root.data(), "createItemWithoutParent" , Q_RETURN_ARG(QVariant, newObject))); | 
| 1911 |         QPointer<QQuickItem> newItem = qvariant_cast<QQuickItem*>(v: newObject); | 
| 1912 |         QVERIFY(!newItem.isNull()); | 
| 1913 |  | 
| 1914 |         QVERIFY(!newItem->parent()); | 
| 1915 |         QVERIFY(!newItem->parentItem()); | 
| 1916 |  | 
| 1917 |         newItem->setParentItem(root.data()); | 
| 1918 |  | 
| 1919 |         gc(engine); | 
| 1920 |  | 
| 1921 |         QVERIFY(!newItem.isNull()); | 
| 1922 |         newItem->setParentItem(nullptr); | 
| 1923 |  | 
| 1924 |         gc(engine); | 
| 1925 |         QVERIFY(newItem.isNull()); | 
| 1926 |     } | 
| 1927 |     { | 
| 1928 |         QVERIFY(QMetaObject::invokeMethod(root.data(), "createItemWithoutParent" , Q_RETURN_ARG(QVariant, newObject))); | 
| 1929 |         QPointer<QQuickItem> firstItem = qvariant_cast<QQuickItem*>(v: newObject); | 
| 1930 |         QVERIFY(!firstItem.isNull()); | 
| 1931 |  | 
| 1932 |         firstItem->setParentItem(root.data()); | 
| 1933 |  | 
| 1934 |         QVERIFY(QMetaObject::invokeMethod(root.data(), "createItemWithoutParent" , Q_RETURN_ARG(QVariant, newObject))); | 
| 1935 |         QPointer<QQuickItem> secondItem = qvariant_cast<QQuickItem*>(v: newObject); | 
| 1936 |         QVERIFY(!firstItem.isNull()); | 
| 1937 |  | 
| 1938 |         secondItem->setParentItem(firstItem); | 
| 1939 |  | 
| 1940 |         gc(engine); | 
| 1941 |  | 
| 1942 |         delete firstItem; | 
| 1943 |  | 
| 1944 |         root->setProperty(name: "keepAliveProperty" , value: newObject); | 
| 1945 |  | 
| 1946 |         gc(engine); | 
| 1947 |         QVERIFY(!secondItem.isNull()); | 
| 1948 |  | 
| 1949 |         root->setProperty(name: "keepAliveProperty" , value: QVariant()); | 
| 1950 |  | 
| 1951 |         gc(engine); | 
| 1952 |         QVERIFY(secondItem.isNull()); | 
| 1953 |     } | 
| 1954 | } | 
| 1955 |  | 
| 1956 | void tst_qquickitem::visualParentOwnershipWindow() | 
| 1957 | { | 
| 1958 |     QQmlEngine engine; | 
| 1959 |     QQmlComponent component(&engine, testFileUrl(fileName: "visualParentOwnershipWindow.qml" )); | 
| 1960 |  | 
| 1961 |     QQuickWindow *window = qobject_cast<QQuickWindow*>(object: component.create()); | 
| 1962 |     QVERIFY(window); | 
| 1963 |     QQuickItem *root = window->contentItem(); | 
| 1964 |  | 
| 1965 |     QVariant newObject; | 
| 1966 |     { | 
| 1967 |         QVERIFY(QMetaObject::invokeMethod(window, "createItemWithoutParent" , Q_RETURN_ARG(QVariant, newObject))); | 
| 1968 |         QPointer<QQuickItem> newItem = qvariant_cast<QQuickItem*>(v: newObject); | 
| 1969 |         QVERIFY(!newItem.isNull()); | 
| 1970 |  | 
| 1971 |         QVERIFY(!newItem->parent()); | 
| 1972 |         QVERIFY(!newItem->parentItem()); | 
| 1973 |  | 
| 1974 |         newItem->setParentItem(root); | 
| 1975 |  | 
| 1976 |         gc(engine); | 
| 1977 |  | 
| 1978 |         QVERIFY(!newItem.isNull()); | 
| 1979 |         newItem->setParentItem(nullptr); | 
| 1980 |  | 
| 1981 |         gc(engine); | 
| 1982 |         QVERIFY(newItem.isNull()); | 
| 1983 |     } | 
| 1984 |     { | 
| 1985 |         QVERIFY(QMetaObject::invokeMethod(window, "createItemWithoutParent" , Q_RETURN_ARG(QVariant, newObject))); | 
| 1986 |         QPointer<QQuickItem> firstItem = qvariant_cast<QQuickItem*>(v: newObject); | 
| 1987 |         QVERIFY(!firstItem.isNull()); | 
| 1988 |  | 
| 1989 |         firstItem->setParentItem(root); | 
| 1990 |  | 
| 1991 |         QVERIFY(QMetaObject::invokeMethod(window, "createItemWithoutParent" , Q_RETURN_ARG(QVariant, newObject))); | 
| 1992 |         QPointer<QQuickItem> secondItem = qvariant_cast<QQuickItem*>(v: newObject); | 
| 1993 |         QVERIFY(!firstItem.isNull()); | 
| 1994 |  | 
| 1995 |         secondItem->setParentItem(firstItem); | 
| 1996 |  | 
| 1997 |         gc(engine); | 
| 1998 |  | 
| 1999 |         delete firstItem; | 
| 2000 |  | 
| 2001 |         window->setProperty(name: "keepAliveProperty" , value: newObject); | 
| 2002 |  | 
| 2003 |         gc(engine); | 
| 2004 |         QVERIFY(!secondItem.isNull()); | 
| 2005 |  | 
| 2006 |         window->setProperty(name: "keepAliveProperty" , value: QVariant()); | 
| 2007 |  | 
| 2008 |         gc(engine); | 
| 2009 |         QVERIFY(secondItem.isNull()); | 
| 2010 |     } | 
| 2011 | } | 
| 2012 |  | 
| 2013 | class InvalidatedItem : public QQuickItem { | 
| 2014 |     Q_OBJECT | 
| 2015 | signals: | 
| 2016 |     void invalidated(); | 
| 2017 | public slots: | 
| 2018 |     void invalidateSceneGraph() { emit invalidated(); } | 
| 2019 | }; | 
| 2020 |  | 
| 2021 | void tst_qquickitem::testSGInvalidate() | 
| 2022 | { | 
| 2023 |     for (int i=0; i<2; ++i) { | 
| 2024 |         QScopedPointer<QQuickView> view(new QQuickView()); | 
| 2025 |  | 
| 2026 |         InvalidatedItem *item = new InvalidatedItem(); | 
| 2027 |  | 
| 2028 |         int expected = 0; | 
| 2029 |         if (i == 0) { | 
| 2030 |             // First iteration, item has contents and should get signals | 
| 2031 |             expected = 1; | 
| 2032 |             item->setFlag(flag: QQuickItem::ItemHasContents, enabled: true); | 
| 2033 |         } else { | 
| 2034 |             // Second iteration, item does not have content and will not get signals | 
| 2035 |         } | 
| 2036 |  | 
| 2037 |         QSignalSpy invalidateSpy(item, SIGNAL(invalidated())); | 
| 2038 |         item->setParentItem(view->contentItem()); | 
| 2039 |         view->show(); | 
| 2040 |  | 
| 2041 |         QVERIFY(QTest::qWaitForWindowExposed(view.data())); | 
| 2042 |  | 
| 2043 |         delete view.take(); | 
| 2044 |         QCOMPARE(invalidateSpy.size(), expected); | 
| 2045 |     } | 
| 2046 | } | 
| 2047 |  | 
| 2048 | void tst_qquickitem::objectChildTransform() | 
| 2049 | { | 
| 2050 |     QQuickView view; | 
| 2051 |     view.setSource(testFileUrl(fileName: "objectChildTransform.qml" )); | 
| 2052 |  | 
| 2053 |     QQuickItem *root = qobject_cast<QQuickItem*>(object: view.rootObject()); | 
| 2054 |     QVERIFY(root); | 
| 2055 |  | 
| 2056 |     root->setProperty(name: "source" , value: QString()); | 
| 2057 |     // Shouldn't crash. | 
| 2058 | } | 
| 2059 |  | 
| 2060 | void tst_qquickitem::contains_data() | 
| 2061 | { | 
| 2062 |     QTest::addColumn<int>(name: "x" ); | 
| 2063 |     QTest::addColumn<int>(name: "y" ); | 
| 2064 |     QTest::addColumn<bool>(name: "contains" ); | 
| 2065 |  | 
| 2066 |     QTest::newRow(dataTag: "(0, 0) = false" ) << 0 << 0 << false; | 
| 2067 |     QTest::newRow(dataTag: "(50, 0) = false" ) << 50 << 0 << false; | 
| 2068 |     QTest::newRow(dataTag: "(0, 50) = false" ) << 0 << 50 << false; | 
| 2069 |     QTest::newRow(dataTag: "(50, 50) = true" ) << 50 << 50 << true; | 
| 2070 |     QTest::newRow(dataTag: "(100, 100) = true" ) << 100 << 100 << true; | 
| 2071 |     QTest::newRow(dataTag: "(150, 150) = false" ) << 150 << 150 << false; | 
| 2072 | } | 
| 2073 |  | 
| 2074 | void tst_qquickitem::contains() | 
| 2075 | { | 
| 2076 |     // Tests that contains works, but also checks that mapToItem/mapFromItem | 
| 2077 |     // return the correct type (point or rect, not a JS object with those properties), | 
| 2078 |     // as this is a common combination of calls. | 
| 2079 |  | 
| 2080 |     QFETCH(int, x); | 
| 2081 |     QFETCH(int, y); | 
| 2082 |     QFETCH(bool, contains); | 
| 2083 |  | 
| 2084 |     QQuickView view; | 
| 2085 |     view.setSource(testFileUrl(fileName: "contains.qml" )); | 
| 2086 |  | 
| 2087 |     QQuickItem *root = qobject_cast<QQuickItem*>(object: view.rootObject()); | 
| 2088 |     QVERIFY(root); | 
| 2089 |  | 
| 2090 |     QVariant result = false; | 
| 2091 |     QVERIFY(QMetaObject::invokeMethod(root, "childContainsViaMapToItem" , | 
| 2092 |         Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, qreal(x)), Q_ARG(QVariant, qreal(y)))); | 
| 2093 |     QCOMPARE(result.toBool(), contains); | 
| 2094 |  | 
| 2095 |     result = false; | 
| 2096 |     QVERIFY(QMetaObject::invokeMethod(root, "childContainsViaMapFromItem" , | 
| 2097 |         Q_RETURN_ARG(QVariant, result), Q_ARG(QVariant, qreal(x)), Q_ARG(QVariant, qreal(y)))); | 
| 2098 |     QCOMPARE(result.toBool(), contains); | 
| 2099 | } | 
| 2100 |  | 
| 2101 | void tst_qquickitem::childAt() | 
| 2102 | { | 
| 2103 |     QQuickView view; | 
| 2104 |     view.setSource(testFileUrl(fileName: "childAtRectangle.qml" )); | 
| 2105 |     QQuickItem *root = qobject_cast<QQuickItem*>(object: view.rootObject()); | 
| 2106 |  | 
| 2107 |     int found = 0; | 
| 2108 |     for (int i = 0; i < 16; i++) | 
| 2109 |     { | 
| 2110 |         if (root->childAt(x: i, y: 0)) | 
| 2111 |             found++; | 
| 2112 |     } | 
| 2113 |     QCOMPARE(found, 16); | 
| 2114 |  | 
| 2115 |     found = 0; | 
| 2116 |     for (int i = 0; i < 16; i++) | 
| 2117 |     { | 
| 2118 |         if (root->childAt(x: 0, y: i)) | 
| 2119 |             found++; | 
| 2120 |     } | 
| 2121 |     QCOMPARE(found, 16); | 
| 2122 |  | 
| 2123 |     found = 0; | 
| 2124 |     for (int i = 0; i < 2; i++) | 
| 2125 |     { | 
| 2126 |         if (root->childAt(x: 18 + i, y: 0)) | 
| 2127 |             found++; | 
| 2128 |     } | 
| 2129 |     QCOMPARE(found, 1); | 
| 2130 |  | 
| 2131 |     found = 0; | 
| 2132 |     for (int i = 0; i < 16; i++) | 
| 2133 |     { | 
| 2134 |         if (root->childAt(x: 18, y: i)) | 
| 2135 |             found++; | 
| 2136 |     } | 
| 2137 |     QCOMPARE(found, 1); | 
| 2138 |  | 
| 2139 |     QVERIFY(!root->childAt(19,19)); | 
| 2140 | } | 
| 2141 |  | 
| 2142 | void tst_qquickitem::ignoreButtonPressNotInAcceptedMouseButtons() | 
| 2143 | { | 
| 2144 |     // Verify the fix for QTBUG-31861 | 
| 2145 |     TestItem item; | 
| 2146 |     QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::NoButton)); | 
| 2147 |  | 
| 2148 |     QQuickWindow window; | 
| 2149 |     item.setSize(QSizeF(200,100)); | 
| 2150 |     item.setParentItem(window.contentItem()); | 
| 2151 |  | 
| 2152 |     item.setAcceptedMouseButtons(Qt::LeftButton); | 
| 2153 |     QCOMPARE(item.acceptedMouseButtons(), Qt::MouseButtons(Qt::LeftButton)); | 
| 2154 |  | 
| 2155 |     QTest::mousePress(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 2156 |     QTest::mousePress(window: &window, button: Qt::RightButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); // ignored because it's not LeftButton | 
| 2157 |     QTest::mouseRelease(window: &window, button: Qt::RightButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); // ignored because it didn't grab the RightButton press | 
| 2158 |     QTest::mouseRelease(window: &window, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(50, 50)); | 
| 2159 |  | 
| 2160 |     QCOMPARE(item.pressCount, 1); | 
| 2161 |     QCOMPARE(item.releaseCount, 1); | 
| 2162 | } | 
| 2163 |  | 
| 2164 | void tst_qquickitem::shortcutOverride() | 
| 2165 | { | 
| 2166 |     QQuickView view; | 
| 2167 |     view.setSource(testFileUrl(fileName: "shortcutOverride.qml" )); | 
| 2168 |     QVERIFY(ensureFocus(&view)); | 
| 2169 |  | 
| 2170 |     QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount" ).toInt(), 0); | 
| 2171 |     QCOMPARE(view.rootObject()->property("shortcutActivationCount" ).toInt(), 0); | 
| 2172 |  | 
| 2173 |     QQuickItem *escapeItem = view.rootObject()->property(name: "escapeItem" ).value<QQuickItem*>(); | 
| 2174 |     QVERIFY(escapeItem); | 
| 2175 |     QVERIFY(escapeItem->hasActiveFocus()); | 
| 2176 |  | 
| 2177 |     // escapeItem's onEscapePressed handler should accept the first escape press event. | 
| 2178 |     QTest::keyPress(window: &view, key: Qt::Key_Escape); | 
| 2179 |     QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount" ).toInt(), 1); | 
| 2180 |     QCOMPARE(view.rootObject()->property("shortcutActivationCount" ).toInt(), 0); | 
| 2181 |     // Now it shouldn't have focus, so it can't handle the next escape press event. | 
| 2182 |     QVERIFY(!escapeItem->hasActiveFocus()); | 
| 2183 |  | 
| 2184 |     QTest::keyRelease(window: &view, key: Qt::Key_Escape); | 
| 2185 |     QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount" ).toInt(), 1); | 
| 2186 |     QCOMPARE(view.rootObject()->property("shortcutActivationCount" ).toInt(), 0); | 
| 2187 |  | 
| 2188 |     QTest::keyPress(window: &view, key: Qt::Key_Escape); | 
| 2189 |     QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount" ).toInt(), 1); | 
| 2190 |     QCOMPARE(view.rootObject()->property("shortcutActivationCount" ).toInt(), 1); | 
| 2191 |  | 
| 2192 |     QTest::keyRelease(window: &view, key: Qt::Key_Escape); | 
| 2193 |     QCOMPARE(view.rootObject()->property("escapeHandlerActivationCount" ).toInt(), 1); | 
| 2194 |     QCOMPARE(view.rootObject()->property("shortcutActivationCount" ).toInt(), 1); | 
| 2195 | } | 
| 2196 |  | 
| 2197 | #ifdef TEST_QTBUG_60123 | 
| 2198 | void tst_qquickitem::qtBug60123() | 
| 2199 | { | 
| 2200 |     QMainWindow main; | 
| 2201 |     main.resize(w: 400, h: 200); | 
| 2202 |  | 
| 2203 |     QQuickView window; | 
| 2204 |     QQuickView window2; | 
| 2205 |     window.setSource(testFileUrl(fileName: "mainWindowQtBug60123.qml" )); | 
| 2206 |     window2.setSource(testFileUrl(fileName: "mainWindowQtBug60123.qml" )); | 
| 2207 |  | 
| 2208 |     // Create central widget for the main window | 
| 2209 |     QWidget *baseWidget = new QWidget(&main); | 
| 2210 |     baseWidget->resize(w: 400, h: 200); | 
| 2211 |     baseWidget->setMaximumHeight(200); | 
| 2212 |     baseWidget->setMaximumWidth(400); | 
| 2213 |     main.setCentralWidget(baseWidget); | 
| 2214 |  | 
| 2215 |     // Create container widgets for both windows | 
| 2216 |     QWidget *containers = QWidget::createWindowContainer(window: &window, parent: baseWidget); | 
| 2217 |     QWidget *containers2 = QWidget::createWindowContainer(window: &window2, parent: baseWidget); | 
| 2218 |     containers->setGeometry(ax: 0, ay: 0, aw: 100, ah: 100); | 
| 2219 |     containers2->setGeometry(ax: 100, ay: 100, aw: 100, ah: 100); | 
| 2220 |  | 
| 2221 |     // Show and activate the main window | 
| 2222 |     main.show(); | 
| 2223 |     QVERIFY(QTest::qWaitForWindowExposed(&main)); | 
| 2224 |  | 
| 2225 |     // Activate window, test press and release events | 
| 2226 |     auto activateWindowAndTestPress = [] (QQuickView* testWindow) { | 
| 2227 |         testWindow->requestActivate(); | 
| 2228 |         QVERIFY(QTest::qWaitForWindowActive(testWindow)); | 
| 2229 |         QTest::mousePress(window: testWindow, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(10, 10)); | 
| 2230 |         QCOMPARE(testWindow->rootObject()->property("lastEvent" ).toString(), QString("pressed" )); | 
| 2231 |         QTest::mouseRelease(window: testWindow, button: Qt::LeftButton, stateKey: Qt::NoModifier, pos: QPoint(10, 10)); | 
| 2232 |         QCOMPARE(testWindow->rootObject()->property("lastEvent" ).toString(), QString("released" )); | 
| 2233 |     }; | 
| 2234 |  | 
| 2235 |     // First press after switching focus window resulted in cancelled event | 
| 2236 |     activateWindowAndTestPress(&window); | 
| 2237 |     activateWindowAndTestPress(&window2); | 
| 2238 |     activateWindowAndTestPress(&window); | 
| 2239 | } | 
| 2240 | #endif | 
| 2241 | void tst_qquickitem::setParentCalledInOnWindowChanged() | 
| 2242 | { | 
| 2243 |     QQuickView view; | 
| 2244 |     view.setSource(testFileUrl(fileName: "setParentInWindowChange.qml" )); | 
| 2245 |     QVERIFY(ensureFocus(&view)); // should not crash | 
| 2246 | } | 
| 2247 |  | 
| 2248 | void tst_qquickitem::receivesLanguageChangeEvent() | 
| 2249 | { | 
| 2250 |     QQuickWindow window; | 
| 2251 |     window.setFramePosition(QPoint(100, 100)); | 
| 2252 |     window.resize(w: 200, h: 200); | 
| 2253 |     window.show(); | 
| 2254 |     QVERIFY(QTest::qWaitForWindowExposed(&window)); | 
| 2255 |  | 
| 2256 |     QScopedPointer<TestItem> child1(new TestItem); | 
| 2257 |     child1->setObjectName(QStringLiteral("child1" )); | 
| 2258 |     child1->setSize(QSizeF(200, 100)); | 
| 2259 |     child1->setParentItem(window.contentItem()); | 
| 2260 |  | 
| 2261 |     QScopedPointer<TestItem> child2(new TestItem); | 
| 2262 |     child2->setObjectName(QStringLiteral("child2" )); | 
| 2263 |     child2->setSize(QSizeF(50, 50)); | 
| 2264 |     child2->setParentItem(child1.data()); | 
| 2265 |  | 
| 2266 |     QTranslator t; | 
| 2267 |     QVERIFY(t.load("hellotr_la.qm" , dataDirectory())); | 
| 2268 |     QVERIFY(QCoreApplication::installTranslator(&t)); | 
| 2269 |  | 
| 2270 |     QTRY_COMPARE(child1->languageChangeEventCount, 1); | 
| 2271 |     QCOMPARE(child2->languageChangeEventCount, 1); | 
| 2272 | } | 
| 2273 |  | 
| 2274 | QTEST_MAIN(tst_qquickitem) | 
| 2275 |  | 
| 2276 | #include "tst_qquickitem.moc" | 
| 2277 |  |