aboutsummaryrefslogtreecommitdiffstats
path: root/tests/auto/quick/qquickitem2
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/quick/qquickitem2')
-rw-r--r--tests/auto/quick/qquickitem2/CMakeLists.txt11
-rw-r--r--tests/auto/quick/qquickitem2/data/embedded.qml30
-rw-r--r--tests/auto/quick/qquickitem2/data/embedded_FocusScope.qml37
-rw-r--r--tests/auto/quick/qquickitem2/data/focusInScopeChanges.qml31
-rw-r--r--tests/auto/quick/qquickitem2/data/focusReason.qml85
-rw-r--r--tests/auto/quick/qquickitem2/data/grabToImage.qml2
-rw-r--r--tests/auto/quick/qquickitem2/data/keysforward.qml2
-rw-r--r--tests/auto/quick/qquickitem2/data/mapCoordinates.qml2
-rw-r--r--tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml2
-rw-r--r--tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml51
-rw-r--r--tests/auto/quick/qquickitem2/data/standardkeys.qml2
-rw-r--r--tests/auto/quick/qquickitem2/tst_qquickitem.cpp576
12 files changed, 725 insertions, 106 deletions
diff --git a/tests/auto/quick/qquickitem2/CMakeLists.txt b/tests/auto/quick/qquickitem2/CMakeLists.txt
index 44620cacd6..6b115efd2e 100644
--- a/tests/auto/quick/qquickitem2/CMakeLists.txt
+++ b/tests/auto/quick/qquickitem2/CMakeLists.txt
@@ -7,6 +7,12 @@
## tst_qquickitem2 Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qquickitem2 LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
@@ -31,6 +37,11 @@ qt_internal_add_test(tst_qquickitem2
## Scopes:
#####################################################################
+qt_internal_extend_target(tst_qquickitem2 CONDITION TARGET Qt::Widgets
+ LIBRARIES
+ Qt::Widgets
+)
+
qt_internal_extend_target(tst_qquickitem2 CONDITION ANDROID OR IOS
DEFINES
QT_QMLTEST_DATADIR=":/data"
diff --git a/tests/auto/quick/qquickitem2/data/embedded.qml b/tests/auto/quick/qquickitem2/data/embedded.qml
new file mode 100644
index 0000000000..a9cf115699
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/embedded.qml
@@ -0,0 +1,30 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 300
+
+ Column {
+ anchors.fill: parent
+ anchors.rightMargin: 2
+ anchors.leftMargin: 2
+ anchors.topMargin: 10
+ spacing: 20
+ Rectangle {
+ objectName: "rect1"
+ width: parent.width
+ height: 30
+ border.width: 1
+ border.color: activeFocus ? "blue" : "black"
+ focusPolicy: Qt.TabFocus
+ }
+ Rectangle {
+ objectName: "rect2"
+ width: parent.width
+ height: 30
+ border.width: 1
+ border.color: activeFocus ? "blue" : "black"
+ focusPolicy: Qt.TabFocus
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/embedded_FocusScope.qml b/tests/auto/quick/qquickitem2/data/embedded_FocusScope.qml
new file mode 100644
index 0000000000..0d154f76e5
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/embedded_FocusScope.qml
@@ -0,0 +1,37 @@
+import QtQuick
+
+Rectangle {
+ width: 300
+ height: 300
+
+ FocusScope {
+ width: parent.width
+ height: parent.height
+ focus: true
+
+ Column {
+ anchors.fill: parent
+ anchors.rightMargin: 2
+ anchors.leftMargin: 2
+ anchors.topMargin: 10
+ spacing: 20
+ Rectangle {
+ objectName: "rect1"
+ width: parent.width
+ height: 30
+ border.width: 1
+ border.color: activeFocus ? "blue" : "black"
+ focusPolicy: Qt.TabFocus
+ }
+ Rectangle {
+ objectName: "rect2"
+ width: parent.width
+ height: 30
+ border.width: 1
+ border.color: activeFocus ? "blue" : "black"
+ focusPolicy: Qt.TabFocus
+ focus: true
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/focusInScopeChanges.qml b/tests/auto/quick/qquickitem2/data/focusInScopeChanges.qml
new file mode 100644
index 0000000000..3bf765a29d
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/focusInScopeChanges.qml
@@ -0,0 +1,31 @@
+import QtQuick
+
+Item {
+ id: main
+ objectName: "main"
+ width: 800
+ height: 600
+
+ FocusScope {
+ objectName: "focusScope"
+
+ Column {
+ Rectangle {
+ id: rectangle
+ focus: true
+ objectName: "rect"
+ width: textInput.width
+ height: textInput.height
+ border.width: 1
+ onActiveFocusChanged: textInput.forceActiveFocus()
+ }
+
+ TextInput {
+ id: textInput
+ objectName: "textInput"
+ font.pixelSize: 40
+ text: "focus me"
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/focusReason.qml b/tests/auto/quick/qquickitem2/data/focusReason.qml
new file mode 100644
index 0000000000..7f9e303dba
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/focusReason.qml
@@ -0,0 +1,85 @@
+import QtQuick
+
+Item {
+ Component.onCompleted: item.focus = true
+ width: 640
+ height: 480
+
+ Column {
+ anchors.top: parent.top
+ anchors.topMargin: 10
+ spacing: 10
+ objectName: "column"
+ focusPolicy: Qt.ClickFocus
+
+ Item {
+ id: item
+ implicitWidth: 100
+ implicitHeight: 20
+ objectName: "item"
+ focusPolicy: Qt.TabFocus
+
+ Rectangle {
+ id: rect
+ anchors.fill: parent
+ color: "yellow"
+ opacity: 0.5
+ }
+
+ MouseArea {
+ anchors.fill: parent
+ acceptedButtons: Qt.LeftButton | Qt.RightButton
+ onClicked: function onClicked(mouseEvent) {
+ if (mouseEvent.button == Qt.RightButton)
+ rect.color = "pink"
+ }
+ }
+ }
+
+ Item {
+ id: customText
+ objectName: "customText"
+ implicitWidth: 100
+ implicitHeight: 50
+ TextInput {
+ anchors.fill: parent
+ objectName: "textInputChild"
+ text: parent.activeFocus ? "focus" : "no focus"
+ }
+ activeFocusOnTab: true
+ }
+
+ Item {
+ id: customItem
+ objectName: "customItem"
+ implicitWidth: 100
+ implicitHeight: 50
+ Rectangle {
+ anchors.fill: parent
+ color: parent.activeFocus ? "red" : "blue"
+ opacity: 0.3
+ }
+ focusPolicy: Qt.WheelFocus
+ }
+
+ Text {
+ id: hyperlink
+ objectName: "hyperlink"
+ color: "blue"
+ onLinkActivated: { text = "Clicked"; }
+ textFormat: Text.RichText
+ text: "<a href=\"http://qt-project.org\">Qt Project website</a>"
+ focusPolicy: Qt.StrongFocus
+
+ MouseArea {
+ id: mouseArea
+ anchors.fill: parent
+ acceptedButtons: Qt.NoButton // Don't eat the mouse clicks
+ cursorShape: Qt.PointingHandCursor
+ // the acceptedButtons will take precedence
+ // and the click focus policy will be ignored
+ focusPolicy: Qt.ClickFocus
+ }
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/grabToImage.qml b/tests/auto/quick/qquickitem2/data/grabToImage.qml
index 7df6d097a6..1298a3c6a9 100644
--- a/tests/auto/quick/qquickitem2/data/grabToImage.qml
+++ b/tests/auto/quick/qquickitem2/data/grabToImage.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 Jolla Ltd, author: <gunnar.sletta@jollamobile.com>
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem2/data/keysforward.qml b/tests/auto/quick/qquickitem2/data/keysforward.qml
index 8ea2d96022..09a0f926ed 100644
--- a/tests/auto/quick/qquickitem2/data/keysforward.qml
+++ b/tests/auto/quick/qquickitem2/data/keysforward.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
index 1db5a4219d..29cfdd73cb 100644
--- a/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinates.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml b/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml
index 2cd48adc06..06f625624a 100644
--- a/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinatesRect.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.0
diff --git a/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml b/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml
new file mode 100644
index 0000000000..98fc0e77af
--- /dev/null
+++ b/tests/auto/quick/qquickitem2/data/mapCoordinatesWithWindows.qml
@@ -0,0 +1,51 @@
+import QtQuick
+
+QtObject {
+ id: root
+
+ property Window windowA: Window {
+ visible: true
+ flags: Qt.FramelessWindowHint
+ color: "green"
+ x: 100; y: 100
+ width: 300; height: 300
+
+ Rectangle {
+ objectName: "childItem"
+ x: 50; y: 50
+ width: 100; height: 100
+ color: "red"
+ }
+
+ WindowContainer {
+ x: 100; y: 100
+ width: 100; height: 100
+ window: Window {
+ objectName: "childWindow"
+ color: "blue"
+
+ Rectangle {
+ objectName: "childItemInChildWindow"
+ x: 30; y: 30
+ width: 50; height: 50
+ color: "orange"
+ }
+ }
+ }
+ }
+
+ property Window windowB: Window {
+ visible: true
+ flags: Qt.FramelessWindowHint
+ color: "magenta"
+ x: 500; y: 200
+ width: 200; height: 200
+
+ Rectangle {
+ objectName: "childItem"
+ x: 50; y: 50
+ width: 100; height: 100
+ color: "cyan"
+ }
+ }
+}
diff --git a/tests/auto/quick/qquickitem2/data/standardkeys.qml b/tests/auto/quick/qquickitem2/data/standardkeys.qml
index 68ee185e87..e19b0705c1 100644
--- a/tests/auto/quick/qquickitem2/data/standardkeys.qml
+++ b/tests/auto/quick/qquickitem2/data/standardkeys.qml
@@ -1,5 +1,5 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
import QtQuick 2.2
diff --git a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
index f7601cade1..56271ec3f2 100644
--- a/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
+++ b/tests/auto/quick/qquickitem2/tst_qquickitem.cpp
@@ -1,5 +1,6 @@
// Copyright (C) 2016 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
#include <qtest.h>
#include <QtTest/QSignalSpy>
#include <QtQml/qqmlengine.h>
@@ -16,11 +17,17 @@
#include <QtQuick/private/qquickanchors_p.h>
#include <QtGui/qstylehints.h>
#include <private/qquickitem_p.h>
+#include <QtQuickTest/QtQuickTest>
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
#include <QtQuickTestUtils/private/platforminputcontext_p.h>
#include <QtTest/private/qpropertytesthelper_p.h>
+#ifdef QT_WIDGETS_LIB
+#include <QtWidgets/qwidget.h>
+#include <QtWidgets/qboxlayout.h>
+#include <QtWidgets/qlineedit.h>
+#endif
using namespace QQuickVisualTestUtils;
@@ -87,6 +94,7 @@ private slots:
void mapCoordinates_data();
void mapCoordinatesRect();
void mapCoordinatesRect_data();
+ void mapCoordinatesWithWindows();
void propertyChanges();
void nonexistentPropertyConnection();
void transforms();
@@ -128,6 +136,14 @@ private slots:
void signalsOnDestruction();
void visibleChanged();
+ void lastFocusChangeReason();
+ void focusInScopeChanges();
+
+#ifdef QT_WIDGETS_LIB
+ void embeddedInWidgetsFocus_data();
+ void embeddedInWidgetsFocus();
+#endif
+
private:
QQmlEngine engine;
bool qt_tab_all_widgets() {
@@ -1873,90 +1889,90 @@ void tst_QQuickItem::layoutMirroring()
QQuickItemPrivate *rootPrivate = QQuickItemPrivate::get(rootItem);
QVERIFY(rootPrivate);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
-
- QCOMPARE(anchorsMirrored(rootItem, "mirrored1"), true);
- QCOMPARE(anchorsMirrored(rootItem, "mirrored2"), true);
- QCOMPARE(anchorsMirrored(rootItem, "notMirrored1"), false);
- QCOMPARE(anchorsMirrored(rootItem, "notMirrored2"), false);
- QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror1"), true);
- QCOMPARE(anchorsMirrored(rootItem, "inheritedMirror2"), true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit, true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent, true);
-
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem, true);
- QCOMPARE(childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem, false);
+ QVERIFY(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "mirrored2")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored2")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror);
+
+ QVERIFY(anchorsMirrored(rootItem, "mirrored1"));
+ QVERIFY(anchorsMirrored(rootItem, "mirrored2"));
+ QVERIFY(!anchorsMirrored(rootItem, "notMirrored1"));
+ QVERIFY(!anchorsMirrored(rootItem, "notMirrored2"));
+ QVERIFY(anchorsMirrored(rootItem, "inheritedMirror1"));
+ QVERIFY(anchorsMirrored(rootItem, "inheritedMirror2"));
+
+ QVERIFY(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "mirrored2")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored2")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror);
+
+ QVERIFY(!childPrivate(rootItem, "mirrored1")->isMirrorImplicit);
+ QVERIFY(!childPrivate(rootItem, "mirrored2")->isMirrorImplicit);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->isMirrorImplicit);
+ QVERIFY(childPrivate(rootItem, "notMirrored2")->isMirrorImplicit);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->isMirrorImplicit);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->isMirrorImplicit);
+
+ QVERIFY(childPrivate(rootItem, "mirrored1")->inheritMirrorFromParent);
+ QVERIFY(!childPrivate(rootItem, "mirrored2")->inheritMirrorFromParent);
+ QVERIFY(childPrivate(rootItem, "notMirrored1")->inheritMirrorFromParent);
+ QVERIFY(!childPrivate(rootItem, "notMirrored2")->inheritMirrorFromParent);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromParent);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromParent);
+
+ QVERIFY(childPrivate(rootItem, "mirrored1")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "mirrored2")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "notMirrored2")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror1")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror2")->inheritMirrorFromItem);
// load dynamic content using Loader that needs to inherit mirroring
rootItem->setProperty("state", "newContent");
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror, true);
+ QVERIFY(!childPrivate(rootItem, "notMirrored3")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror3")->effectiveLayoutMirror);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror, true);
+ QVERIFY(childPrivate(rootItem, "notMirrored3")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror3")->inheritedLayoutMirror);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->isMirrorImplicit, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit, true);
+ QVERIFY(!childPrivate(rootItem, "notMirrored3")->isMirrorImplicit);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror3")->isMirrorImplicit);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent, true);
+ QVERIFY(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromParent);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror3")->inheritMirrorFromParent);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem, false);
+ QVERIFY(!childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem);
+ QVERIFY(!childPrivate(rootItem, "notMirrored3")->inheritMirrorFromItem);
// disable inheritance
rootItem->setProperty("childrenInherit", false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, false);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, false);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror);
// re-enable inheritance
rootItem->setProperty("childrenInherit", true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror, false);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->effectiveLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "mirrored1")->effectiveLayoutMirror);
+ QVERIFY(!childPrivate(rootItem, "notMirrored1")->effectiveLayoutMirror);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror, true);
- QCOMPARE(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror, true);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror1")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "inheritedMirror2")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "mirrored1")->inheritedLayoutMirror);
+ QVERIFY(childPrivate(rootItem, "notMirrored1")->inheritedLayoutMirror);
//
// dynamic parenting
@@ -1969,24 +1985,24 @@ void tst_QQuickItem::layoutMirroring()
// inherit in constructor
QQuickItem *childItem1 = new QQuickItem(parentItem1);
- QCOMPARE(QQuickItemPrivate::get(childItem1)->effectiveLayoutMirror, true);
- QCOMPARE(QQuickItemPrivate::get(childItem1)->inheritMirrorFromParent, true);
+ QVERIFY(QQuickItemPrivate::get(childItem1)->effectiveLayoutMirror);
+ QVERIFY(QQuickItemPrivate::get(childItem1)->inheritMirrorFromParent);
// inherit through a parent change
QQuickItem *childItem2 = new QQuickItem();
- QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
+ QVERIFY(!QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror);
+ QVERIFY(!QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent);
childItem2->setParentItem(parentItem1);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, true);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, true);
+ QVERIFY(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror);
+ QVERIFY(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent);
// stop inherting through a parent change
QQuickItem *parentItem2 = new QQuickItem();
QQuickItemPrivate::get(parentItem2)->effectiveLayoutMirror = true; // LayoutMirroring.enabled: true
QQuickItemPrivate::get(parentItem2)->resolveLayoutMirror();
childItem2->setParentItem(parentItem2);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror, false);
- QCOMPARE(QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent, false);
+ QVERIFY(!QQuickItemPrivate::get(childItem2)->effectiveLayoutMirror);
+ QVERIFY(!QQuickItemPrivate::get(childItem2)->inheritMirrorFromParent);
delete parentItem1;
delete parentItem2;
@@ -2002,11 +2018,11 @@ void tst_QQuickItem::layoutMirroringWindow()
window->show();
QQuickItemPrivate *content = QQuickItemPrivate::get(window->contentItem());
- QCOMPARE(content->effectiveLayoutMirror, true);
- QCOMPARE(content->inheritedLayoutMirror, true);
- QCOMPARE(content->isMirrorImplicit, false);
- QCOMPARE(content->inheritMirrorFromParent, true);
- QCOMPARE(content->inheritMirrorFromItem, true);
+ QVERIFY(content->effectiveLayoutMirror);
+ QVERIFY(content->inheritedLayoutMirror);
+ QVERIFY(!content->isMirrorImplicit);
+ QVERIFY(content->inheritMirrorFromParent);
+ QVERIFY(content->inheritMirrorFromItem);
}
void tst_QQuickItem::layoutMirroringIllegalParent()
@@ -2797,6 +2813,76 @@ void tst_QQuickItem::mapCoordinatesRect_data()
QTest::newRow(QTest::toString(i)) << i << i << i << i;
}
+void tst_QQuickItem::mapCoordinatesWithWindows()
+{
+ QQmlComponent component(&engine, testFileUrl("mapCoordinatesWithWindows.qml"));
+ std::unique_ptr<QObject> root(component.create());
+ QVERIFY(root);
+
+ auto *windowA = root->property("windowA").value<QQuickWindow*>();
+ QVERIFY(windowA);
+
+ // The window container geometry, parenting, etc, is applied
+ // during polish, so to test these we need to wait for one.
+ QVERIFY(QQuickTest::qWaitForPolish(windowA));
+
+ auto *childItem = windowA->findChild<QQuickItem*>("childItem");
+ QVERIFY(childItem);
+
+ QPoint itemPos = childItem->position().toPoint();
+ QCOMPARE(childItem->mapToScene({0, 0}), itemPos);
+ QCOMPARE(childItem->mapToGlobal({0, 0}), windowA->position() + itemPos);
+
+ auto *childItemInChildWindow = windowA->findChild<QQuickItem*>("childItemInChildWindow");
+ QVERIFY(childItemInChildWindow);
+
+ QPoint windowItemPos = childItemInChildWindow->position().toPoint();
+ QCOMPARE(childItemInChildWindow->mapToScene({0, 0}), windowItemPos);
+ QCOMPARE(childItemInChildWindow->mapToGlobal({0, 0}), windowA->position()
+ + childItemInChildWindow->window()->position() + windowItemPos);
+
+ QCOMPARE(childItemInChildWindow->mapToItem(nullptr, {0, 0}), windowItemPos);
+
+ auto globalItemOffset = [](QQuickItem *a, QQuickItem *b) {
+ return a->mapToGlobal({0, 0}) - b->mapToGlobal({0, 0});
+ };
+
+ QCOMPARE(childItemInChildWindow->mapToItem(childItem, {0, 0}),
+ globalItemOffset(childItemInChildWindow, childItem));
+ QCOMPARE(childItemInChildWindow->mapFromItem(childItem, {0, 0}),
+ globalItemOffset(childItem, childItemInChildWindow));
+
+ QCOMPARE(childItem->mapToItem(childItemInChildWindow, {0, 0}),
+ globalItemOffset(childItem, childItemInChildWindow));
+ QCOMPARE(childItem->mapFromItem(childItemInChildWindow, {0, 0}),
+ globalItemOffset(childItemInChildWindow, childItem));
+
+ auto *windowB = root->property("windowB").value<QQuickWindow*>();
+ QVERIFY(windowA);
+ auto *childItemInOtherWindow = windowB->findChild<QQuickItem*>("childItem");
+ QVERIFY(childItemInOtherWindow);
+
+ QCOMPARE(childItemInOtherWindow->mapToItem(childItem, {0, 0}),
+ globalItemOffset(childItemInOtherWindow, childItem));
+ QCOMPARE(childItemInOtherWindow->mapFromItem(childItem, {0, 0}),
+ globalItemOffset(childItem, childItemInOtherWindow));
+
+ QCOMPARE(childItem->mapToItem(childItemInOtherWindow, {0, 0}),
+ globalItemOffset(childItem, childItemInOtherWindow));
+ QCOMPARE(childItem->mapFromItem(childItemInOtherWindow, {0, 0}),
+ globalItemOffset(childItemInOtherWindow, childItem));
+
+ QCOMPARE(childItemInOtherWindow->mapToItem(childItemInChildWindow, {0, 0}),
+ globalItemOffset(childItemInOtherWindow, childItemInChildWindow));
+ QCOMPARE(childItemInOtherWindow->mapFromItem(childItemInChildWindow, {0, 0}),
+ globalItemOffset(childItemInChildWindow, childItemInOtherWindow));
+
+ QCOMPARE(childItemInChildWindow->mapToItem(childItemInOtherWindow, {0, 0}),
+ globalItemOffset(childItemInChildWindow, childItemInOtherWindow));
+ QCOMPARE(childItemInChildWindow->mapFromItem(childItemInOtherWindow, {0, 0}),
+ globalItemOffset(childItemInOtherWindow, childItemInChildWindow));
+}
+
void tst_QQuickItem::transforms_data()
{
QTest::addColumn<QByteArray>("qml");
@@ -3268,93 +3354,93 @@ void tst_QQuickItem::changeListener()
listeners << new TestListener(true);
// itemVisibilityChanged x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Visibility);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setVisible(false);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Visibility), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemRotationChanged x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Rotation);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setRotation(90);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Rotation), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemOpacityChanged x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Opacity);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setOpacity(0.5);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Opacity), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemChildAdded() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Children);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
child1 = new QQuickItem(parent);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Children), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemParentChanged() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(child1)->addItemChangeListener(listener, QQuickItemPrivate::Parent);
QCOMPARE(QQuickItemPrivate::get(child1)->changeListeners.size(), listeners.size());
child1->setParentItem(nullptr);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Parent), 1);
QCOMPARE(QQuickItemPrivate::get(child1)->changeListeners.size(), 0);
// itemImplicitWidthChanged() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::ImplicitWidth);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setImplicitWidth(parent->implicitWidth() + 1);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::ImplicitWidth), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemImplicitHeightChanged() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::ImplicitHeight);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setImplicitHeight(parent->implicitHeight() + 1);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::ImplicitHeight), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemGeometryChanged() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Geometry);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
parent->setWidth(parent->width() + 1);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Geometry), 1);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemChildRemoved() x 5
child1->setParentItem(parent);
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Children);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
delete child1;
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Children), 2);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), 0);
// itemDestroyed() x 5
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QQuickItemPrivate::get(parent)->addItemChangeListener(listener, QQuickItemPrivate::Destroyed);
QCOMPARE(QQuickItemPrivate::get(parent)->changeListeners.size(), listeners.size());
delete parent;
- foreach (TestListener *listener, listeners)
+ for (TestListener *listener : std::as_const(listeners))
QCOMPARE(listener->count(QQuickItemPrivate::Destroyed), 1);
}
@@ -4139,6 +4225,294 @@ void tst_QQuickItem::visibleChanged()
QCOMPARE(childItemSpy.count(), 1);
}
+void tst_QQuickItem::lastFocusChangeReason()
+{
+ std::unique_ptr<QQuickView> window = std::make_unique<QQuickView>();
+ window->setSource(testFileUrl("focusReason.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowActive(window.get()));
+
+ QQuickItem *item = window->findChild<QQuickItem *>("item");
+ QQuickItem *customText = window->findChild<QQuickItem *>("customText");
+ QQuickItem *customItem = window->findChild<QQuickItem *>("customItem");
+ QQuickItem *hyperlink = window->findChild<QQuickItem *>("hyperlink");
+ QQuickItem *textInputChild = window->findChild<QQuickItem *>("textInputChild");
+
+ QQuickItemPrivate *itemPrivate = QQuickItemPrivate::get(item);
+ QQuickItemPrivate *customTextPrivate = QQuickItemPrivate::get(customText);
+ QQuickItemPrivate *customItemPrivate = QQuickItemPrivate::get(customItem);
+ QQuickItemPrivate *hyperlinkPrivate = QQuickItemPrivate::get(hyperlink);
+ QQuickItemPrivate *textInputChildPrivate = QQuickItemPrivate::get(textInputChild);
+
+ QVERIFY(item);
+ QVERIFY(customText);
+ QVERIFY(customItem);
+ QVERIFY(hyperlink);
+ QVERIFY(textInputChild);
+
+ QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusAllControls);
+ auto resetTabFocusBehavior = qScopeGuard([]{
+ QGuiApplication::styleHints()->setTabFocusBehavior(Qt::TabFocusBehavior(-1));
+ });
+
+ // helper for clicking into an item
+ const auto itemCenter = [](const QQuickItem *item) -> QPoint {
+ return item->mapToScene(item->clipRect().center()).toPoint();
+ };
+
+ // setting focusPolicy to Strong/WheelFocus doesn't implicitly turn on event delivery
+ customText->setAcceptedMouseButtons(Qt::LeftButton);
+ customItem->setAcceptedMouseButtons(Qt::LeftButton);
+ customItem->setAcceptTouchEvents(true);
+ customText->setAcceptTouchEvents(true);
+ hyperlink->setAcceptTouchEvents(true);
+
+ // window activation -> ActiveWindowFocusReason
+ QVERIFY(item->hasFocus());
+ QVERIFY(item->hasActiveFocus());
+ if (itemPrivate->lastFocusChangeReason() != Qt::ActiveWindowFocusReason
+ && QStringList{"windows", "offscreen"}.contains(QGuiApplication::platformName())) {
+ QEXPECT_FAIL("", "On Windows and offscreen platforms, window activation does not set focus reason", Continue);
+ }
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::ActiveWindowFocusReason);
+
+ // test setter/getter
+ item->setFocus(false, Qt::MouseFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ item->setFocus(true, Qt::TabFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ item->setFocus(false, Qt::BacktabFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+ item->forceActiveFocus(Qt::ShortcutFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::ShortcutFocusReason);
+ item->setFocus(false, Qt::NoFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::NoFocusReason);
+ QVERIFY(!item->hasFocus());
+
+ // programmatic focus changes
+ item->setFocus(true, Qt::OtherFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::OtherFocusReason);
+
+ QVERIFY(item->hasFocus());
+ QVERIFY(item->hasActiveFocus());
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::OtherFocusReason);
+
+ // tab focus -> TabFocusReason
+ QTest::keyClick(window.get(), Qt::Key_Tab);
+ QVERIFY(customText->hasFocus());
+ QVERIFY(customText->hasActiveFocus());
+ QCOMPARE(qApp->focusObject(), customText);
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab);
+ QVERIFY(customItem->hasFocus());
+ QVERIFY(customItem->hasActiveFocus());
+ QCOMPARE(qApp->focusObject(), customItem);
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab);
+ QVERIFY(hyperlink->hasFocus());
+ QVERIFY(hyperlink->hasActiveFocus());
+ QCOMPARE(qApp->focusObject(), hyperlink);
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab);
+ QVERIFY(item->hasFocus());
+ QVERIFY(item->hasActiveFocus());
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::TabFocusReason);
+
+ // backtab -> BacktabFocusReason
+ QTest::keyClick(window.get(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(hyperlink->hasFocus());
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+ QCOMPARE(itemPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(customItem->hasFocus());
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+
+ QTest::keyClick(window.get(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(customText->hasFocus());
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::BacktabFocusReason);
+
+ // click focus -> MouseFocusReason
+ QTest::mouseClick(window.get(), Qt::LeftButton, {}, itemCenter(customItem));
+ QVERIFY(customItem->hasFocus());
+ QVERIFY(customItem->hasActiveFocus());
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(customTextPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ QTest::mouseClick(window.get(), Qt::LeftButton, {}, itemCenter(hyperlink));
+ QVERIFY(hyperlink->hasFocus());
+ QVERIFY(hyperlink->hasActiveFocus());
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ QTest::mouseClick(window.get(), Qt::LeftButton, {}, itemCenter(customText));
+ QCOMPARE(textInputChild, textInputChild);
+ QVERIFY(textInputChild->hasFocus());
+ QVERIFY(textInputChild->hasActiveFocus());
+ QCOMPARE(textInputChildPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ // touch focus -> MouseFocusReason
+ std::unique_ptr<QPointingDevice> touchDevice(QTest::createTouchDevice());
+
+ QTest::touchEvent(window.get(), touchDevice.get()).press(0, itemCenter(customItem));
+ QTest::touchEvent(window.get(), touchDevice.get()).press(0, itemCenter(customItem));
+ QTest::touchEvent(window.get(), touchDevice.get()).release(0, itemCenter(customItem));
+ QVERIFY(customItem->hasFocus());
+ QVERIFY(customItem->hasActiveFocus());
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(textInputChildPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ QTest::touchEvent(window.get(), touchDevice.get()).press(0, itemCenter(hyperlink));
+ QTest::touchEvent(window.get(), touchDevice.get()).release(0, itemCenter(hyperlink));
+ QVERIFY(hyperlink->hasFocus());
+ QVERIFY(hyperlink->hasActiveFocus());
+ QCOMPARE(hyperlinkPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+
+ // Wheel focus -> MouseFocusReason
+ QWheelEvent wheelEvent(QPointF(customItem->width() / 2, customItem->height() / 2), QPointF(),
+ QPoint(), QPoint(0, 10), Qt::NoButton, Qt::NoModifier,
+ Qt::NoScrollPhase, false);
+ QGuiApplication::sendEvent(customItem, &wheelEvent);
+ QVERIFY(customItem->hasActiveFocus());
+ QCOMPARE(customItemPrivate->lastFocusChangeReason(), Qt::MouseFocusReason);
+}
+
+void tst_QQuickItem::focusInScopeChanges()
+{
+ std::unique_ptr<QQuickView> window = std::make_unique<QQuickView>();
+ window->setSource(testFileUrl("focusInScopeChanges.qml"));
+ window->show();
+ window->requestActivate();
+ QVERIFY(QTest::qWaitForWindowFocused(window.get()));
+
+ QQuickItem *main = window->rootObject();
+ QVERIFY(main);
+ QQuickItem *focusScope = main->findChild<QQuickItem *>("focusScope");
+ QQuickItem *rect = main->findChild<QQuickItem *>("rect");
+ QQuickItem *textInput = main->findChild<QQuickItem *>("textInput");
+
+ QVERIFY(focusScope);
+ QVERIFY(rect);
+ QVERIFY(textInput);
+ QVERIFY(window->contentItem());
+
+ QSignalSpy fsActiveFocusSpy(focusScope, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy rectActiveFocusSpy(rect, SIGNAL(activeFocusChanged(bool)));
+ QSignalSpy textInputActiveFocusSpy(textInput, SIGNAL(activeFocusChanged(bool)));
+
+ // The window's content item will have activeFocus if window is focused
+ QTRY_VERIFY(window->contentItem()->hasActiveFocus());
+
+ QVERIFY(!focusScope->hasActiveFocus());
+ QVERIFY(!rect->hasActiveFocus());
+ QVERIFY(!textInput->hasActiveFocus());
+ QCOMPARE(fsActiveFocusSpy.size(), 0);
+ QCOMPARE(rectActiveFocusSpy.size(), 0);
+ QCOMPARE(textInputActiveFocusSpy.size(), 0);
+
+ // setting focus to rect shouldn't affect activeFocus as long as its
+ // parent focus scope doesn't have the activeFocus
+ rect->setFocus(true);
+ QCOMPARE(fsActiveFocusSpy.size(), 0);
+ QCOMPARE(rectActiveFocusSpy.size(), 0);
+ QCOMPARE(textInputActiveFocusSpy.size(), 0);
+
+ // focusScope is the only child with focus in the parent
+ // scope, so it will gain activeFocus
+ focusScope->setFocus(true);
+ QCOMPARE(fsActiveFocusSpy.size(), 1);
+ QVERIFY(fsActiveFocusSpy.first().at(0).toBool());
+ // rect loses activeFocus because textInput gains it (as a result of code in signal handler)
+ QCOMPARE(rectActiveFocusSpy.size(), 2);
+ QVERIFY(!rect->hasActiveFocus());
+ QCOMPARE(textInputActiveFocusSpy.size(), 1);
+ QVERIFY(textInput->hasActiveFocus());
+}
+
+#ifdef QT_WIDGETS_LIB
+void tst_QQuickItem::embeddedInWidgetsFocus_data()
+{
+ QTest::addColumn<QUrl>("source");
+ QTest::newRow("Embedded") << testFileUrl("embedded.qml");
+ QTest::newRow("Embedded Focus Scope") << testFileUrl("embedded_FocusScope.qml");
+}
+
+void tst_QQuickItem::embeddedInWidgetsFocus()
+{
+ QFETCH(QUrl, source);
+ QWidget root;
+ QVBoxLayout *layout = new QVBoxLayout(&root);
+
+ QLineEdit *lineEdit1 = new QLineEdit(&root);
+ lineEdit1->setFocusPolicy(Qt::FocusPolicy::TabFocus);
+
+ QQuickView *quickView = new QQuickView;
+ quickView->setSource(source);
+ QWidget *container = QWidget::createWindowContainer(quickView, &root);
+ container->setMinimumSize(quickView->size());
+ container->setFocusPolicy(Qt::TabFocus);
+
+ QLineEdit *lineEdit2 = new QLineEdit(&root);
+ lineEdit2->setFocusPolicy(Qt::FocusPolicy::TabFocus);
+
+ layout->addWidget(lineEdit1);
+ layout->addWidget(container);
+ layout->addWidget(lineEdit2);
+
+ QQuickItem *rect1 = findItem<QQuickItem>(quickView->rootObject(), "rect1");
+ QQuickItem *rect2 = findItem<QQuickItem>(quickView->rootObject(), "rect2");
+ QVERIFY(rect1);
+ QVERIFY(rect2);
+
+ root.show();
+ QTRY_VERIFY(root.isVisible());
+ QVERIFY(QTest::qWaitForWindowExposed(&root));
+ QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle()));
+
+ lineEdit1->setFocus();
+ QTRY_VERIFY(lineEdit1->hasFocus());
+
+ // Tab forward
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab);
+ QTRY_VERIFY(container->hasFocus());
+ QVERIFY(QTest::qWaitForWindowFocused(quickView));
+ QVERIFY(rect1->hasActiveFocus());
+
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab);
+ QTRY_VERIFY(rect2->hasActiveFocus());
+
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab);
+ QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle()));
+ QVERIFY(lineEdit2->hasFocus());
+ QVERIFY(!rect2->hasActiveFocus());
+
+ // Tab backwards
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab, Qt::ShiftModifier);
+ QTRY_VERIFY(container->hasFocus());
+ QVERIFY(QTest::qWaitForWindowFocused(quickView));
+ QVERIFY(rect2->hasActiveFocus());
+
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(rect1->hasActiveFocus());
+
+ QTest::keyClick(QGuiApplication::focusWindow(), Qt::Key_Tab, Qt::ShiftModifier);
+ QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle()));
+ QVERIFY(lineEdit1->hasFocus());
+}
+#endif
+
QTEST_MAIN(tst_QQuickItem)
#include "tst_qquickitem.moc"