diff options
Diffstat (limited to 'tests/auto/quickcontrols/qquickpopup')
45 files changed, 1212 insertions, 140 deletions
diff --git a/tests/auto/quickcontrols/qquickpopup/BLACKLIST b/tests/auto/quickcontrols/qquickpopup/BLACKLIST index aa31440328..3beb1d6cc7 100644 --- a/tests/auto/quickcontrols/qquickpopup/BLACKLIST +++ b/tests/auto/quickcontrols/qquickpopup/BLACKLIST @@ -1,5 +1,16 @@ # See qtbase/src/testlib/qtestblacklist.cpp for format +# QTBUG-114718 (begin) +[overlay] +macos +[invisibleToolTipOpen] +macos +[cursorShape] +macos +[doubleClickInMouseArea] +macos +# QTBUG-114718 (end) + [overlay] macos # QTBUG-89938 @@ -12,3 +23,7 @@ opensuse-leap [cursorShape] opensuse-leap + +[popupWindowFocus] +* # QTBUG-121363 + diff --git a/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt b/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt index 81eb78c906..3110e4d26b 100644 --- a/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt +++ b/tests/auto/quickcontrols/qquickpopup/CMakeLists.txt @@ -6,7 +6,7 @@ if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) cmake_minimum_required(VERSION 3.16) project(tst_qquickpopup LANGUAGES C CXX ASM) - find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) endif() ##################################################################### diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterExit.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterExit.qml index 359dc772f2..d918159f65 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterExit.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterExit.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml new file mode 100644 index 0000000000..1d4dc87e41 --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusAfterWindowInactive.qml @@ -0,0 +1,27 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +ApplicationWindow { + width: 400 + height: 400 + + property alias popup: popup + property alias button: button + + Button { + id: button + text: "button" + focus: true + } + + Popup { + id: popup + focus: true + width: 100 + height: 100 + anchors.centerIn: Overlay.overlay + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose1.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose1.qml index 81893bbcbd..7cbc5f479a 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose1.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose1.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose2.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose2.qml index 6cb1c5ad07..c1b60b7282 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose2.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose2.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose3.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose3.qml index 89165e355e..0e1e2aa703 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose3.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClose3.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml index 3a85f7d580..5ed1c5988d 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnClosingSeveralPopups.qml @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnDelayedEnter.qml b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnDelayedEnter.qml index 37a595ec25..e4b7438d2a 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnDelayedEnter.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/activeFocusOnDelayedEnter.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick 2.12 import QtQuick.Controls 2.12 diff --git a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml index d4c8b78355..f1acf42d2a 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-hover.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls @@ -15,22 +15,24 @@ ApplicationWindow { Button { id: parentButton text: "Parent" + palette.buttonText: hovered ? "tomato" : "black" anchors.fill: parent + anchors.margins: 10 Popup { id: popup - x: 1 - y: 1 - leftPadding: 1 - rightPadding: 1 - topPadding: 1 - bottomPadding: 1 - + x: 10 + y: 10 + leftPadding: 10 + rightPadding: 10 + topPadding: 10 + bottomPadding: 10 Button { anchors.centerIn: parent id: childButton text: "Child" + palette.buttonText: hovered ? "tomato" : "black" } } } diff --git a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-wheel.qml b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-wheel.qml index 1668b042e0..eb09d7eba3 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-wheel.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow-wheel.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Window diff --git a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow.qml b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow.qml index 46c4dda18b..7ab22ff8bd 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/applicationwindow.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/applicationwindow.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/centerInOverlayWithinStackViewItem.qml b/tests/auto/quickcontrols/qquickpopup/data/centerInOverlayWithinStackViewItem.qml index 1c96bb687c..a0a76206da 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/centerInOverlayWithinStackViewItem.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/centerInOverlayWithinStackViewItem.qml @@ -1,5 +1,5 @@ // Copyright (C) 2020 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/closeOnEscapeWithNestedPopups.qml b/tests/auto/quickcontrols/qquickpopup/data/closeOnEscapeWithNestedPopups.qml index 6aeede9aff..5533591ac4 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/closeOnEscapeWithNestedPopups.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/closeOnEscapeWithNestedPopups.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/countChanged.qml b/tests/auto/quickcontrols/qquickpopup/data/countChanged.qml index e95be76e56..41f306781d 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/countChanged.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/countChanged.qml @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Window diff --git a/tests/auto/quickcontrols/qquickpopup/data/cursor.qml b/tests/auto/quickcontrols/qquickpopup/data/cursor.qml index 3eefa7570e..6ea4e03dac 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/cursor.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/cursor.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/destroyDuringExitTransition.qml b/tests/auto/quickcontrols/qquickpopup/data/destroyDuringExitTransition.qml index dacffd3199..5c34f22f60 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/destroyDuringExitTransition.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/destroyDuringExitTransition.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/dialog.qml b/tests/auto/quickcontrols/qquickpopup/data/dialog.qml index 112bfaefcd..d28e540701 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/dialog.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/dialog.qml @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Window diff --git a/tests/auto/quickcontrols/qquickpopup/data/dimmerContainmentMask.qml b/tests/auto/quickcontrols/qquickpopup/data/dimmerContainmentMask.qml index 30a412a1cc..5f7e9afc08 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/dimmerContainmentMask.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/dimmerContainmentMask.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/disabledPalette.qml b/tests/auto/quickcontrols/qquickpopup/data/disabledPalette.qml index 4b54b5b1fd..2af92158dc 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/disabledPalette.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/disabledPalette.qml @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/doubleClickInMouseArea.qml b/tests/auto/quickcontrols/qquickpopup/data/doubleClickInMouseArea.qml new file mode 100644 index 0000000000..e43a2f3160 --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/doubleClickInMouseArea.qml @@ -0,0 +1,23 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Window + +Rectangle { + width: 200; height: 200 + color: mouseArea.pressed ? "red" : "orange" + + Popup { + visible: true + closePolicy: Popup.NoAutoClose + width: 100 + height: 100 + contentItem: MouseArea { + id: mouseArea + + anchors.fill: parent + } + background: Rectangle { + color: "green" + } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml b/tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml new file mode 100644 index 0000000000..d5edc11466 --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/fadeDimmer.qml @@ -0,0 +1,39 @@ +import QtQuick +import QtQuick.Controls + +Window { + id: window + + Text {text: "Hello"} + Popup { + id: popup + anchors.centerIn: parent + dim: true + property double dimmerOpacity: 0.5 + + Overlay.modeless: Rectangle { + color: "blue" + opacity: popup.dimmerOpacity + + Behavior on opacity { + NumberAnimation { from: 0; to: popup.dimmerOpacity; duration: 250 } + } + } + + Overlay.modal: Rectangle { + color: "blue" + opacity: popup.dimmerOpacity + + Behavior on opacity { + NumberAnimation { from: 0; to: popup.dimmerOpacity; duration: 250 } + } + } + + enter: Transition { + NumberAnimation { property: "opacity"; from: 0; to: 1; duration: 250 } + } + exit: Transition { + NumberAnimation { property: "opacity"; from: 1; to: 0; duration: 250 } + } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/grabber.qml b/tests/auto/quickcontrols/qquickpopup/data/grabber.qml index ec76829f4f..952212dc0b 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/grabber.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/grabber.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/mirroredCombobox.qml b/tests/auto/quickcontrols/qquickpopup/data/mirroredCombobox.qml index ed48179bce..7449072e89 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/mirroredCombobox.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/mirroredCombobox.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/modelessOnModalOnModeless.qml b/tests/auto/quickcontrols/qquickpopup/data/modelessOnModalOnModeless.qml index 5da5a5524b..f1fe64e49a 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/modelessOnModalOnModeless.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/modelessOnModalOnModeless.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/multiplepopup.qml b/tests/auto/quickcontrols/qquickpopup/data/multiplepopup.qml new file mode 100644 index 0000000000..395514546d --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/multiplepopup.qml @@ -0,0 +1,82 @@ +import QtQuick +import QtQuick.Controls +import QtQuick.Layouts + +Window { + id: window + width: 200 + height: 200 + visible: false + + Item { + id: rootItem + objectName: "rootItem" + + width: parent.width + height: parent.height + visible: true + focus: true + + Popup { + id: popup1 + objectName: "popup1" + + width: parent.width / 2 + height: parent.height + focus: true + modal: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + + Button { + id: buttonPopup1 + objectName: "button" + + text: "ButtonPopup" + width: 20 + visible: true + } + } + + Popup { + id: popup2 + objectName: "popup2" + + width: parent.width / 2 + height: parent.height + focus: true + modal: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + + TextEdit { + id: texteditPopup2 + objectName: "textedit" + + focus: true + text: "Text Edit Content" + visible: true + } + } + + Popup { + id: popup3 + objectName: "popup3" + + width: parent.width / 2 + height: parent.height + focus: true + modal: true + closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent + + Drawer { + id: drawerPopup3 + objectName: "drawer" + + width: parent.width / 2 + height: parent.height + focus: true + visible: true + } + } + } +} + diff --git a/tests/auto/quickcontrols/qquickpopup/data/nested-wheel-overlay-parent.qml b/tests/auto/quickcontrols/qquickpopup/data/nested-wheel-overlay-parent.qml new file mode 100644 index 0000000000..06dafa112a --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/nested-wheel-overlay-parent.qml @@ -0,0 +1,39 @@ +import QtQuick +import QtQuick.Controls + +ApplicationWindow { + width: 100 + height: 100 + + property alias _drawer: drawer + property alias _listView: drawer.contentItem + property alias _dropArea: dropArea + + Drawer { + id: drawer + width: 50 + height: parent.height + contentItem: ListView { + width: parent.width + height: contentHeight + model: 500 + delegate: Rectangle { + height: 15 + Label { + text: modelData + } + } + } + } + + DropArea { + id: dropArea + anchors.fill: parent + Connections { + target: drawer + function onOpened() { + dropArea.parent = drawer.parent + } + } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/nested.qml b/tests/auto/quickcontrols/qquickpopup/data/nested.qml index d88142f661..d0257bf700 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/nested.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/nested.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml b/tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml new file mode 100644 index 0000000000..6d42dc10e8 --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/noDimmer.qml @@ -0,0 +1,22 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Templates as T + +Window { + T.Drawer { + id: root + onModalChanged: { + if (!modal) { + open() + } + } + } + Timer { + interval: 100 + running: true + repeat: false + onTriggered: root.modal = false + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/orientation.qml b/tests/auto/quickcontrols/qquickpopup/data/orientation.qml index 198f716fc0..f83cfda74e 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/orientation.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/orientation.qml @@ -1,29 +1,35 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Window import QtQuick.Controls Window { - width: 600 - height: 300 + width: 200 + height: 100 property alias popup: popup Rectangle { - width: 60 - height: 30 + width: 100 + height: 80 anchors.centerIn: parent border.width: 1 Popup { id: popup - x: parent.width - y: parent.height - width: 30 - height: 60 + width: 50 + height: 40 + anchors.centerIn: parent visible: true + modal: false + dim: true + + Overlay.modeless: Rectangle { + opacity: 0.5 + color: "blue" + } } } } diff --git a/tests/auto/quickcontrols/qquickpopup/data/popupCenterIn.qml b/tests/auto/quickcontrols/qquickpopup/data/popupCenterIn.qml new file mode 100644 index 0000000000..6a67af30fc --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/popupCenterIn.qml @@ -0,0 +1,22 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +Window { + width: 1080 + height: 720 + + property alias popup: simplepopup + + Popup { + id: simplepopup + anchors.centerIn: parent + popupType: Popup.Window + + Text { + text: "I am a centered popup" + } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml b/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml new file mode 100644 index 0000000000..1477db047e --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/popupWindowFocusHandling.qml @@ -0,0 +1,28 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +Window { + width: 400 + height: 400 + + property alias popup: simplepopup + property alias textField1: outerTextField + property alias textField2: innerTextField + + TextField { + id: outerTextField + focus: true + } + + Popup { + id: simplepopup + popupType: Popup.Window + TextField { + id: innerTextField + focus: true + } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/popupWithButtonInBackground.qml b/tests/auto/quickcontrols/qquickpopup/data/popupWithButtonInBackground.qml new file mode 100644 index 0000000000..b265a80df7 --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/popupWithButtonInBackground.qml @@ -0,0 +1,28 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +Window { + width: 1080 + height: 720 + + property alias popup: simplepopup + + Button { + text: "Button" + } + + Popup { + id: simplepopup + popupType: Popup.Window + + x: 50 + y: 50 + + Text { + text: "I am a very interesting popup" + } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/releaseAfterExitTransition.qml b/tests/auto/quickcontrols/qquickpopup/data/releaseAfterExitTransition.qml index f3a1f218c1..9ddf4577ee 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/releaseAfterExitTransition.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/releaseAfterExitTransition.qml @@ -1,5 +1,5 @@ // Copyright (C) 2021 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/reparentingPopup.qml b/tests/auto/quickcontrols/qquickpopup/data/reparentingPopup.qml new file mode 100644 index 0000000000..bf622b7713 --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/reparentingPopup.qml @@ -0,0 +1,48 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +Window { + width: 400 + height: 400 + + property alias popup: simplepopup + property alias rectangle1: item1 + property alias rectangle2: item2 + property alias rectangle3: item3 + + Popup { + id: simplepopup + popupType: Popup.Window + x: 10 + y: 10 + width: 200 + height: 200 + } + + Rectangle { + id: item1 + color: "red" + width: 200 + height: 200 + } + + Rectangle { + id: item2 + color: "green" + x: 0 + y: 200 + width: parent.width + height: 200 + Rectangle { + id: item3 + color: "blue" + x: 200 + y: 0 + width: 200 + height: item2.height + } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/rotatedCombobox.qml b/tests/auto/quickcontrols/qquickpopup/data/rotatedCombobox.qml index df217be4b7..16cce45263 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/rotatedCombobox.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/rotatedCombobox.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowHeight.qml b/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowHeight.qml index b9b8874622..0de6122431 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowHeight.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowHeight.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowWidth.qml b/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowWidth.qml index aa78353eb0..2cb655f129 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowWidth.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/shrinkPopupThatWasLargerThanWindowWidth.qml @@ -1,5 +1,5 @@ // Copyright (C) 2022 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Controls diff --git a/tests/auto/quickcontrols/qquickpopup/data/simplepopup.qml b/tests/auto/quickcontrols/qquickpopup/data/simplepopup.qml new file mode 100644 index 0000000000..eeafa10c9e --- /dev/null +++ b/tests/auto/quickcontrols/qquickpopup/data/simplepopup.qml @@ -0,0 +1,22 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +import QtQuick +import QtQuick.Controls + +Window { + width: 1080 + height: 720 + + property alias popup: simplepopup + + Popup { + id: simplepopup + x: 50 + y: 50 + + Text { + text: "I am a very interesting popup" + } + } +} diff --git a/tests/auto/quickcontrols/qquickpopup/data/tabFence.qml b/tests/auto/quickcontrols/qquickpopup/data/tabFence.qml index a96cf1687c..376ca66e6e 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/tabFence.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/tabFence.qml @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Layouts diff --git a/tests/auto/quickcontrols/qquickpopup/data/toolTipCrashOnClose.qml b/tests/auto/quickcontrols/qquickpopup/data/toolTipCrashOnClose.qml index f40fa0939c..8e4eb877dc 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/toolTipCrashOnClose.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/toolTipCrashOnClose.qml @@ -1,5 +1,5 @@ // Copyright (C) 2019 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Window diff --git a/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml b/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml index fa61e8b706..5beca69317 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/window-hover.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Window @@ -16,21 +16,24 @@ Window { Button { id: parentButton text: "Parent" + palette.buttonText: hovered ? "tomato" : "black" anchors.fill: parent + anchors.margins: 10 Popup { id: popup - x: 1 - y: 1 - topPadding: 1 - bottomPadding: 1 - leftPadding: 1 - rightPadding: 1 + x: 10 + y: 10 + leftPadding: 10 + rightPadding: 10 + topPadding: 10 + bottomPadding: 10 Button { anchors.centerIn: parent id: childButton text: "Child" + palette.buttonText: hovered ? "tomato" : "black" } } } diff --git a/tests/auto/quickcontrols/qquickpopup/data/window-wheel.qml b/tests/auto/quickcontrols/qquickpopup/data/window-wheel.qml index ae9c2ecdfd..57cce40982 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/window-wheel.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/window-wheel.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Window diff --git a/tests/auto/quickcontrols/qquickpopup/data/window.qml b/tests/auto/quickcontrols/qquickpopup/data/window.qml index 6ffe5165fe..0db6896f59 100644 --- a/tests/auto/quickcontrols/qquickpopup/data/window.qml +++ b/tests/auto/quickcontrols/qquickpopup/data/window.qml @@ -1,5 +1,5 @@ // Copyright (C) 2017 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only import QtQuick import QtQuick.Window diff --git a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp index 8343cc4f3a..650d168c65 100644 --- a/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp +++ b/tests/auto/quickcontrols/qquickpopup/tst_qquickpopup.cpp @@ -1,30 +1,39 @@ // Copyright (C) 2017 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 <QtTest/qtest.h> #include <QtTest/qsignalspy.h> +#include <QtQuickTest/quicktest.h> #include <QtCore/qoperatingsystemversion.h> #include <QtGui/qpa/qwindowsysteminterface.h> #include <QtGui/qpa/qplatformintegration.h> #include <QtGui/private/qguiapplication_p.h> #include <QtQuick/qquickview.h> +#include <QtQuick/private/qquickmousearea_p.h> #include <QtQuick/private/qquickpalette_p.h> #include <QtQuickTestUtils/private/qmlutils_p.h> #include <QtQuickTestUtils/private/viewtestutils_p.h> #include <QtQuickTestUtils/private/visualtestutils_p.h> #include <QtQuickTemplates2/private/qquickapplicationwindow_p.h> +#include <QtQuickTemplates2/private/qquickbutton_p.h> #include <QtQuickTemplates2/private/qquickcombobox_p.h> #include <QtQuickTemplates2/private/qquickdialog_p.h> +#include <QtQuickTemplates2/private/qquickdrawer_p.h> #include <QtQuickTemplates2/private/qquickoverlay_p.h> #include <QtQuickTemplates2/private/qquickoverlay_p_p.h> #include <QtQuickTemplates2/private/qquickpopup_p.h> +#include <QtQuickTemplates2/private/qquickpopup_p_p.h> +#include <QtQuickTemplates2/private/qquickpopupanchors_p.h> #include <QtQuickTemplates2/private/qquickpopupitem_p_p.h> -#include <QtQuickTemplates2/private/qquickbutton_p.h> +#include <QtQuickTemplates2/private/qquickpopupwindow_p_p.h> #include <QtQuickTemplates2/private/qquickslider_p.h> #include <QtQuickTemplates2/private/qquickstackview_p.h> -#include <QtQuickTemplates2/private/qquickpopup_p_p.h> #include <QtQuickTemplates2/private/qquicktooltip_p.h> +#include <QtQuick/private/qquicktextinput_p.h> +#include <QtQuick/private/qquicklistview_p.h> +#include <QtQuick/private/qquicktextedit_p.h> +#include <QtQuick/private/qquickdroparea_p.h> #include <QtQuickControlsTestUtils/private/controlstestutils_p.h> #include <QtQuickControlsTestUtils/private/qtest_quickcontrols_p.h> @@ -59,13 +68,19 @@ private slots: void activeFocusAfterExit(); void activeFocusOnDelayedEnter(); void activeFocusDespiteLowerStackingOrder(); + void activeFocusItemAfterWindowInactive(); void hover_data(); void hover(); +#if QT_CONFIG(wheelevent) void wheel_data(); void wheel(); +#endif void parentDestroyed(); void nested(); +#if QT_CONFIG(wheelevent) void nestedWheel(); + void nestedWheelWithOverlayParent(); +#endif void modelessOnModalOnModeless(); void grabber(); void cursorShape(); @@ -92,10 +107,28 @@ private slots: void relativeZOrder(); void mirroredCombobox(); void rotatedCombobox(); + void focusMultiplePopup(); + void contentChildrenChange(); + void doubleClickInMouseArea(); + void fadeDimmer_data(); + void fadeDimmer(); + void noDimmer(); + + void popupWindowPositioning(); + void popupWindowAnchorsCenterIn_data(); + void popupWindowAnchorsCenterIn(); + void popupWindowModality(); + void popupWindowClosesOnParentWindowClosing(); + void initialPopupSize_data(); + void initialPopupSize(); + void popupWindowChangingParent(); + void popupWindowFocus(); + void popupTypeChangeFromWindowToItem(); + void popupTypeChangeFromItemToWindow(); private: - static bool hasWindowActivation(); QScopedPointer<QPointingDevice> touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice()); + bool popupWindowsSupported = false; }; using namespace Qt::StringLiterals; @@ -103,11 +136,14 @@ using namespace Qt::StringLiterals; tst_QQuickPopup::tst_QQuickPopup() : QQmlDataTest(QT_QMLTEST_DATADIR) { + popupWindowsSupported = QGuiApplicationPrivate::platformIntegration() + ->hasCapability(QPlatformIntegration::Capability::MultipleWindows); } void tst_QQuickPopup::initTestCase() { QQmlDataTest::initTestCase(); + QCoreApplication::setAttribute(Qt::AA_DontUseNativeMenuWindows); qputenv("QML_NO_TOUCH_COMPRESSION", "1"); } @@ -118,11 +154,6 @@ void tst_QQuickPopup::visible_data() QTest::newRow("ApplicationWindow") << "applicationwindow.qml"; } -bool tst_QQuickPopup::hasWindowActivation() -{ - return (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)); -} - void tst_QQuickPopup::visible() { QFETCH(QString, source); @@ -217,6 +248,10 @@ void tst_QQuickPopup::overlay_data() void tst_QQuickPopup::overlay() { +#ifdef Q_OS_ANDROID + QSKIP("Test crashes. See QTBUG-118532"); +#endif + QFETCH(QString, source); QFETCH(bool, modal); QFETCH(bool, dim); @@ -497,8 +532,7 @@ void tst_QQuickPopup::closePolicy_data() void tst_QQuickPopup::closePolicy() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QFETCH(QString, source); QFETCH(const QPointingDevice *, device); @@ -640,8 +674,7 @@ void tst_QQuickPopup::closePolicy_grabberInside() void tst_QQuickPopup::activeFocusOnClose1() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that a popup that never sets focus: true (e.g. ToolTip) doesn't affect // the active focus item when it closes. @@ -686,8 +719,7 @@ void tst_QQuickPopup::activeFocusOnClose1() void tst_QQuickPopup::activeFocusOnClose2() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that a popup that sets focus: true but relinquishes focus (e.g. by // calling forceActiveFocus() on another item) before it closes doesn't @@ -728,8 +760,7 @@ void tst_QQuickPopup::activeFocusOnClose2() void tst_QQuickPopup::activeFocusOnClose3() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that a closing popup that had focus doesn't steal focus from // another popup that the focus was transferred to. @@ -764,8 +795,7 @@ void tst_QQuickPopup::activeFocusOnClose3() void tst_QQuickPopup::activeFocusOnClosingSeveralPopups() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that active focus isn't lost when multiple popup closing simultaneously QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusOnClosingSeveralPopups.qml")); @@ -816,8 +846,7 @@ void tst_QQuickPopup::activeFocusOnClosingSeveralPopups() void tst_QQuickPopup::activeFocusAfterExit() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that after closing a popup the highest one in z-order receives it instead. QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusAfterExit.qml")); @@ -868,8 +897,7 @@ void tst_QQuickPopup::activeFocusAfterExit() void tst_QQuickPopup::activeFocusOnDelayedEnter() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Test that after opening two popups, first of which has an animation, does not cause // the first one to receive focus after the animation stops. @@ -897,8 +925,7 @@ void tst_QQuickPopup::activeFocusOnDelayedEnter() // key events due to having active focus. void tst_QQuickPopup::activeFocusDespiteLowerStackingOrder() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusOnClose3.qml")); QVERIFY2(helper.ready, helper.failureMessage()); @@ -937,6 +964,52 @@ void tst_QQuickPopup::activeFocusDespiteLowerStackingOrder() QVERIFY(!popup1->hasActiveFocus()); } +void tst_QQuickPopup::activeFocusItemAfterWindowInactive() +{ + SKIP_IF_NO_WINDOW_ACTIVATION + + QQuickControlsApplicationHelper helper(this, QStringLiteral("activeFocusAfterWindowInactive.qml")); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickApplicationWindow *window = helper.appWindow; + window->show(); + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowFocused(window)); + + QQuickPopup *popup = helper.appWindow->property("popup").value<QQuickPopup*>(); + QQuickButton *button = helper.appWindow->property("button").value<QQuickButton*>(); + QVERIFY(popup); + QVERIFY(button); + + popup->open(); + QVERIFY(popup->isVisible()); + QTRY_VERIFY(popup->isOpened()); + QVERIFY(popup->hasActiveFocus()); + QVERIFY(!button->hasActiveFocus()); + + popup->close(); + QVERIFY(!popup->isVisible()); + QTRY_VERIFY(!popup->isOpened()); + QVERIFY(button->hasActiveFocus()); + QCOMPARE(window->activeFocusItem(), button); + + popup->open(); + QVERIFY(popup->isVisible()); + QTRY_VERIFY(popup->isOpened()); + + QQuickWindow newWindow; + newWindow.setTitle("newFocusWindow"); + newWindow.show(); + newWindow.requestActivate(); + QVERIFY(QTest::qWaitForWindowFocused(&newWindow)); + + popup->close(); + QCOMPARE(QGuiApplication::focusWindow(), &newWindow); + + window->requestActivate(); + QVERIFY(QTest::qWaitForWindowFocused(window)); + QCOMPARE(window->activeFocusItem(), button); +} + void tst_QQuickPopup::hover_data() { QTest::addColumn<QString>("source"); @@ -977,18 +1050,19 @@ void tst_QQuickPopup::hover() QVERIFY(openedSpy.size() == 1 || openedSpy.wait()); QTRY_VERIFY(popup->width() > 10); // somehow this can take a short time with macOS style - // hover the parent button outside the popup - QTest::mouseMove(window, QPoint(window->width() - 1, window->height() - 1)); + // Hover the parent button outside the popup. It has 10 pixel anchor margins around the window. + PointLerper pointLerper(window); + pointLerper.move(15, 15); QCOMPARE(parentButton->isHovered(), !modal); QVERIFY(!childButton->isHovered()); - // hover the popup background - QTest::mouseMove(window, QPoint(1, 1)); + // Hover the popup background. Its top-left is 10 pixels in from its parent. + pointLerper.move(25, 25); QVERIFY(!parentButton->isHovered()); QVERIFY(!childButton->isHovered()); - // hover the child button in a popup - QTest::mouseMove(window, QPoint(popup->x() + popup->width() / 2, popup->y() + popup->height() / 2)); + // Hover the child button in a popup. + pointLerper.move(mapCenterToWindow(childButton)); QVERIFY(!parentButton->isHovered()); QVERIFY(childButton->isHovered()); @@ -1002,6 +1076,7 @@ void tst_QQuickPopup::hover() QVERIFY(parentButton->isHovered()); } +#if QT_CONFIG(wheelevent) void tst_QQuickPopup::wheel_data() { QTest::addColumn<QString>("source"); @@ -1115,6 +1190,7 @@ void tst_QQuickPopup::wheel() QVERIFY(qFuzzyCompare(popupSlider->value(), oldPopupValue)); // must not have moved } } +#endif void tst_QQuickPopup::parentDestroyed() { @@ -1153,6 +1229,7 @@ void tst_QQuickPopup::nested() QCOMPARE(modalPopup->isVisible(), true); } +#if QT_CONFIG(wheelevent) void tst_QQuickPopup::nestedWheel() { QQuickControlsApplicationHelper helper(this, QStringLiteral("nested-wheel.qml")); @@ -1183,6 +1260,42 @@ void tst_QQuickPopup::nestedWheel() QTRY_COMPARE_GT(vbar->property("position").toDouble(), startPosition); } +void tst_QQuickPopup::nestedWheelWithOverlayParent() +{ + QQuickControlsApplicationHelper helper(this, QStringLiteral("nested-wheel-overlay-parent.qml")); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *drawer= window->property("_drawer").value<QQuickDrawer *>(); + QVERIFY(drawer); + + auto *dropArea = window->property("_dropArea").value<QQuickDropArea *>(); + QVERIFY(dropArea); + + drawer->open(); + QCOMPARE(drawer->isVisible(), true); + QTRY_COMPARE(drawer->isOpened(), true); + + QQuickListView *listView = window->property("_listView").value<QQuickListView *>(); + QTRY_VERIFY(listView != nullptr); + QQuickItem *contentItem = listView->contentItem(); + QTRY_VERIFY(contentItem != nullptr); + + // Check parent is set as overlay + QTRY_COMPARE(dropArea->parentItem(), QQuickOverlay::overlay(window)); + // Consider the center point of the control as event position to trigger wheel event + QVERIFY(sendWheelEvent(listView, -15)); + + if (QQuickTest::qIsPolishScheduled(listView)) + QVERIFY(QQuickTest::qWaitForPolish(listView)); + + // Wheel over the list view, verify that it scrolls + QTRY_COMPARE(listView->contentY(), 72.); +} +#endif + void tst_QQuickPopup::modelessOnModalOnModeless() { QQuickControlsApplicationHelper helper(this, QStringLiteral("modelessOnModalOnModeless.qml")); @@ -1339,8 +1452,7 @@ void tst_QQuickPopup::componentComplete() void tst_QQuickPopup::closeOnEscapeWithNestedPopups() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION // Tests the scenario in the Gallery example, where there are nested popups that should // close in the correct order when the Escape key is pressed. @@ -1409,8 +1521,7 @@ void tst_QQuickPopup::closeOnEscapeWithNestedPopups() void tst_QQuickPopup::closeOnEscapeWithVisiblePopup() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, QStringLiteral("closeOnEscapeWithVisiblePopup.qml")); QVERIFY2(helper.ready, helper.failureMessage()); @@ -1450,66 +1561,49 @@ void tst_QQuickPopup::enabled() void tst_QQuickPopup::orientation_data() { QTest::addColumn<Qt::ScreenOrientation>("orientation"); - QTest::addColumn<QPointF>("position"); - // On Android the screen size will usually be smaller than the 600x300 - // size of a Window in orientation.qml - // Because of that we need to calculate proper positions at runtime. -#ifndef Q_OS_ANDROID - QQuickControlsApplicationHelper helper(this, "orientation.qml"); - const QSize availableSize = helper.window->size(); -#else - const QSize availableSize = QGuiApplication::primaryScreen()->availableSize(); -#endif - const int width = availableSize.width(); - const int height = availableSize.height(); - - // The width & height might be odd numbers, so we calculate center in a way - // similar to anchors.centerIn. - // Also note that when we emulate the screen orientation change (by calling - // window->reportContentOrientationChange() in the test), these values need - // to be adjusted, because the "logical" (0, 0) of the screen changes. - const int widthCenter = (width % 2) ? (width + 1) / 2 : width / 2; - const int heightCenter = (height % 2) ? (height + 1) / 2 : height / 2; - - // Rectangle is (60x30); popup is (30x60). - // Rectangle is using "anchors.centerIn: parent", and popup is positioned at - // (rectangle.width, rectangle.height) - QTest::newRow("Portrait") << Qt::PortraitOrientation - << QPointF(widthCenter - 30 + 60, heightCenter - 15 + 30); - // in landscape orientation the top left corner of physical screen - // (not rotated) becomes (0, 0), so we need to adjust our widthCenter - QTest::newRow("Landscape") << Qt::LandscapeOrientation - << QPointF(heightCenter - 15 + 30, (width - widthCenter) + 30 - 60); - // In inverted portrait orientation the bottom right corner of physical - // screen (not rotated) becomes (0, 0), so we need to adjust both - // widthCenter and heightCenter - QTest::newRow("InvertedPortrait") << Qt::InvertedPortraitOrientation - << QPointF((width - widthCenter) + 30 - 60, (height - heightCenter) + 15 - 30); - // In inverted landscape orientation the bottom right corner of physical - // screen (not rotated) becomes (0, 0), so we need to adjust heightCenter - QTest::newRow("InvertedLandscape") << Qt::InvertedLandscapeOrientation - << QPointF((height - heightCenter) + 15 - 30, widthCenter - 30 + 60); + QTest::newRow("Portrait") << Qt::PortraitOrientation; + QTest::newRow("Landscape") << Qt::LandscapeOrientation; + QTest::newRow("InvertedPortrait") << Qt::InvertedPortraitOrientation; + QTest::newRow("InvertedLandscape") << Qt::InvertedLandscapeOrientation; } +/* + Verify that the popup is centered, and that the dimmer and overlay cover + the content item for any content orientation and content rotation. +*/ void tst_QQuickPopup::orientation() { QFETCH(Qt::ScreenOrientation, orientation); - QFETCH(QPointF, position); QQuickControlsApplicationHelper helper(this, "orientation.qml"); QVERIFY2(helper.ready, helper.failureMessage()); QQuickWindow *window = helper.window; - window->reportContentOrientationChange(orientation); window->show(); QVERIFY(QTest::qWaitForWindowExposed(window)); - QQuickPopup *popup = window->property("popup").value<QQuickPopup*>(); + QQuickPopup *popup = window->property("popup").value<QQuickPopup *>(); QVERIFY(popup); - popup->open(); QTRY_VERIFY(popup->isOpened()); - QCOMPARE(popup->popupItem()->position(), position); + + QQuickItem *dimmer = QQuickPopupPrivate::get(popup)->dimmer; + QVERIFY(dimmer); + QQuickItem *popupItem = popup->popupItem(); + QVERIFY(popupItem); + QQuickOverlay *overlay = QQuickOverlay::overlay(window); + QVERIFY(overlay); + QQuickItem *contentItem = window->contentItem(); + QVERIFY(contentItem); + + const auto rotation = window->screen()->angleBetween(Qt::PrimaryOrientation, orientation); + QCOMPARE(popupItem->mapToScene(popupItem->boundingRect().center()), contentItem->boundingRect().center()); + QCOMPARE(dimmer->boundingRect(), contentItem->boundingRect()); + QCOMPARE(overlay->boundingRect(), contentItem->boundingRect()); + window->contentItem()->setRotation(rotation); + QCOMPARE(popupItem->mapToScene(popupItem->boundingRect().center()), contentItem->boundingRect().center()); + QCOMPARE(dimmer->boundingRect(), contentItem->boundingRect()); + QCOMPARE(overlay->boundingRect(), contentItem->boundingRect()); } void tst_QQuickPopup::qquickview() @@ -1537,8 +1631,7 @@ void tst_QQuickPopup::qquickview() // QTBUG-73447 void tst_QQuickPopup::disabledPalette() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, "disabledPalette.qml"); QVERIFY2(helper.ready, helper.failureMessage()); @@ -1577,8 +1670,7 @@ void tst_QQuickPopup::disabledPalette() void tst_QQuickPopup::disabledParentPalette() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, "disabledPalette.qml"); QVERIFY2(helper.ready, helper.failureMessage()); @@ -1686,8 +1778,7 @@ void tst_QQuickPopup::setOverlayParentToNull() void tst_QQuickPopup::tabFence() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION if (QGuiApplication::styleHints()->tabFocusBehavior() != Qt::TabFocusAllControls) QSKIP("This platform only allows tab focus for text controls"); @@ -1799,8 +1890,7 @@ void tst_QQuickPopup::centerInOverlayWithinStackViewItem() void tst_QQuickPopup::destroyDuringExitTransition() { - if (!hasWindowActivation()) - QSKIP("Window activation is not supported"); + SKIP_IF_NO_WINDOW_ACTIVATION QQuickControlsApplicationHelper helper(this, "destroyDuringExitTransition.qml"); QVERIFY2(helper.ready, helper.failureMessage()); @@ -2149,6 +2239,582 @@ void tst_QQuickPopup::rotatedCombobox() } } +void tst_QQuickPopup::focusMultiplePopup() +{ + QQuickApplicationHelper helper(this, "multiplepopup.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *rootItem = window->findChild<QQuickItem *>("rootItem"); + QTRY_VERIFY(rootItem->hasFocus()); + + auto *buttonPopup = window->findChild<QQuickPopup *>("popup1"); + buttonPopup->open(); + QTRY_VERIFY(buttonPopup->isOpened()); + QVERIFY(!rootItem->hasFocus()); + QVERIFY(buttonPopup->hasFocus()); + + auto *textEditPopup = window->findChild<QQuickPopup *>("popup2"); + textEditPopup->open(); + QTRY_VERIFY(textEditPopup->isOpened()); + QVERIFY(textEditPopup->hasFocus()); + + auto *drawerPopup = window->findChild<QQuickPopup *>("popup3"); + drawerPopup->open(); + QTRY_VERIFY(drawerPopup->isVisible()); + QVERIFY(drawerPopup->hasFocus()); + + auto *drawer = window->findChild<QQuickDrawer *>("drawer"); + drawer->close(); + QTRY_VERIFY(!drawer->isVisible()); + drawerPopup->close(); + QTRY_VERIFY(!drawerPopup->isVisible()); + QVERIFY(textEditPopup->hasFocus()); + + textEditPopup->close(); + QTRY_VERIFY(!textEditPopup->isVisible()); + QVERIFY(buttonPopup->hasFocus()); + + buttonPopup->close(); + QTRY_VERIFY(!buttonPopup->isVisible()); + + QVERIFY(rootItem->hasFocus()); +} + +void tst_QQuickPopup::contentChildrenChange() +{ + QQmlEngine engine; + QQmlComponent comp(&engine); + comp.loadFromModule("QtQuick.Controls", "Popup"); + std::unique_ptr<QObject> root {comp.create()}; + QVERIFY(root); + QQuickPopup *popup = qobject_cast<QQuickPopup *>(root.get()); + QVERIFY(popup); + QSignalSpy spy(popup, &QQuickPopup::contentChildrenChanged); + auto contentItem = std::make_unique<QQuickItem>(); + popup->setContentItem(contentItem.get()); + QCOMPARE(spy.count(), 1); + auto newChild = std::make_unique<QQuickItem>(); + QQmlProperty contentItemChildren(contentItem.get()); + contentItemChildren.write(QVariant::fromValue(newChild.get())); + QCOMPARE(spy.count(), 2); +} + +void tst_QQuickPopup::doubleClickInMouseArea() +{ +#ifdef Q_OS_ANDROID + QSKIP("Test crashes. See QTBUG-118532"); +#endif + + QQuickView window; + QVERIFY(QQuickTest::showView(window, testFileUrl("doubleClickInMouseArea.qml"))); + + auto *ma = window.rootObject()->findChild<QQuickMouseArea *>(); + QVERIFY(ma); + QSignalSpy doubleClickSpy(ma, &QQuickMouseArea::doubleClicked); + QSignalSpy longPressSpy(ma, &QQuickMouseArea::pressAndHold); + QPoint p = ma->mapToScene(ma->boundingRect().center()).toPoint(); + + // check with normal double click + QTest::mouseDClick(&window, Qt::LeftButton, Qt::NoModifier, p); + QCOMPARE(doubleClickSpy.count(), 1); + + // wait enough time for a wrong long press to happen + QTest::qWait(QGuiApplication::styleHints()->mousePressAndHoldInterval() + 10); + QCOMPARE(longPressSpy.count(), 0); +} + +void tst_QQuickPopup::fadeDimmer_data() +{ + QTest::addColumn<bool>("modality"); + + QTest::addRow("modal") << true; + QTest::addRow("modeless") << true; +} + +void tst_QQuickPopup::fadeDimmer() +{ + QFETCH(const bool, modality); + QQuickApplicationHelper helper(this, "fadeDimmer.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + + popup->setModal(modality); + popup->open(); + auto dimmer = QQuickPopupPrivate::get(popup)->dimmer; + QVERIFY(dimmer); + int opacityChangeCount = 0; + connect(dimmer, &QQuickItem::opacityChanged, this, [&opacityChangeCount]{ + ++opacityChangeCount; + }); + QTRY_VERIFY(popup->isOpened()); + QTRY_COMPARE(dimmer->opacity(), popup->property("dimmerOpacity").toDouble()); + QCOMPARE_GT(opacityChangeCount, 2); + + opacityChangeCount = 0; + popup->setVisible(false); + QTRY_VERIFY(!popup->isVisible()); + QCOMPARE_GT(opacityChangeCount, 2); +} + +void tst_QQuickPopup::noDimmer() +{ + QQuickApplicationHelper helper(this, "noDimmer.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *drawer = window->contentItem()->findChild<QQuickDrawer *>(); + QVERIFY(drawer); + + drawer->open(); + auto dimmer = QQuickPopupPrivate::get(drawer)->dimmer; + QVERIFY(dimmer); + // this must not crash + QTRY_VERIFY(!drawer->isModal()); +} + +#define VERIFY_LOCAL_POS(POPUP, EXPECTED) \ + QTRY_VERIFY2(qAbs(POPUP->x() - qreal(EXPECTED.x())) <= 1, \ + qPrintable(QStringLiteral("QQuickPopup::x() = %1, expected = %2").arg(POPUP->x()).arg(EXPECTED.x())));\ + QVERIFY2(qAbs(POPUP->y() - qreal(EXPECTED.y())) <= 1, \ + qPrintable(QStringLiteral("QQuickPopup::y() = %1, expected = %2").arg(POPUP->y()).arg(EXPECTED.y()))) + +#define VERIFY_GLOBAL_POS(FROM, POPUPWINDOW, EXPECTED) \ + QTRY_VERIFY2((POPUPWINDOW->position() - FROM->mapToGlobal(EXPECTED.x(), EXPECTED.y())).manhattanLength() <= 2, \ + qPrintable(QStringLiteral("PopupWindow pos = (%1, %2), expected (%3, %4)") \ + .arg(POPUPWINDOW->x()).arg(POPUPWINDOW->y()).arg(EXPECTED.x()).arg(EXPECTED.y()))) + +void tst_QQuickPopup::popupWindowPositioning() +{ + if (!popupWindowsSupported) + QSKIP("The platform doesn't support popup windows. Skipping test."); + + QQuickApplicationHelper helper(this, "simplepopup.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + auto *popupPrivate = QQuickPopupPrivate::get(popup); + QVERIFY(popupPrivate); + + popup->setPopupType(QQuickPopup::Window); + + popup->open(); + QTRY_VERIFY(popup->isVisible()); + + QSignalSpy xSpy(popup, SIGNAL(xChanged())); + QSignalSpy ySpy(popup, SIGNAL(yChanged())); + + auto *popupWindow = popupPrivate->popupWindow; + QVERIFY(popupWindow); + + // x and y properties should be 50 initially + const QPoint initialPos(50, 50); + + VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, initialPos); + VERIFY_LOCAL_POS(popup, initialPos); + + // Move popup via QQuickPopup API + const QPoint secondPosition(100, 100); + popup->setPosition(secondPosition.toPointF()); + + QTRY_COMPARE(xSpy.count(), 1); + QCOMPARE(ySpy.count(), 1); + + VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, secondPosition); + VERIFY_LOCAL_POS(popup, secondPosition); + + // Move popup via QWindow API (which uses global coordinates) + const QPoint thirdPosition(150, 150); + popupWindow->setPosition(popup->parentItem()->mapToGlobal(thirdPosition.x(), thirdPosition.y()).toPoint()); + + QTRY_COMPARE(xSpy.count(), 2); + QCOMPARE(ySpy.count(), 2); + + VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, thirdPosition); + VERIFY_LOCAL_POS(popup, thirdPosition); + + // Moving parent window should change the popups position (because it's stationary, but x and y are relative coordinates) + const QPoint movement(30, 30); + const QPoint oldPos = window->position(); + window->setPosition(oldPos + movement); + + // TODO: Figure out these signals are emitted twice + // QTRY_COMPARE(xSpy.count(), 3); + // QCOMPARE(ySpy.count(), 3); + + VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, (thirdPosition - movement)); +} + +void tst_QQuickPopup::popupWindowAnchorsCenterIn_data() +{ + QTest::addColumn<bool>("centerInParent"); + QTest::newRow("parent") << true; + QTest::newRow("overlay") << false; +} + +void tst_QQuickPopup::popupWindowAnchorsCenterIn() +{ + QFETCH(bool, centerInParent); + + if (!popupWindowsSupported) + QSKIP("The platform doesn't support popup windows. Skipping test."); + + QQuickApplicationHelper helper(this, "popupCenterIn.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + auto *popupPrivate = QQuickPopupPrivate::get(popup); + QVERIFY(popupPrivate); + + popupPrivate->getAnchors()->setCenterIn(centerInParent ? window->contentItem() : QQuickOverlay::overlay(window)); + + popup->open(); + QTRY_VERIFY(popup->isVisible()); + + auto *popupWindow = popupPrivate->popupWindow; + QVERIFY(popupWindow); + + const QPoint centeredPosition(qFloor(window->width() / 2 - popupWindow->width() / 2), qFloor(window->height() / 2 - popupWindow->height() / 2)); + + VERIFY_GLOBAL_POS(popup->parentItem(), popupWindow, centeredPosition); + VERIFY_LOCAL_POS(popup, centeredPosition); +} + +void tst_QQuickPopup::popupWindowModality() +{ + QSKIP("The behavior isn't correctly implemented yet. Waiting for patch in qtbase"); + + if (!popupWindowsSupported) + QSKIP("The platform doesn't support popup windows. Skipping test."); + + QQuickApplicationHelper helper(this, "popupWithButtonInBackground.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + + auto *popupPrivate = QQuickPopupPrivate::get(popup); + QVERIFY(popupPrivate); + + auto *button = window->findChild<QQuickButton *>(); + QVERIFY(button); + + QSignalSpy buttonSpy(button, SIGNAL(clicked())); + + popup->open(); + QTRY_VERIFY(popup->isVisible()); + + auto *popupWindow = popupPrivate->popupWindow; + QVERIFY(popupWindow); + QVERIFY(popupWindow->isVisible()); + // NonModal by default + QCOMPARE(popupWindow->modality(), Qt::NonModal); + + // Non modal popups should close on press outside + QTest::mouseClick(helper.window, Qt::LeftButton, Qt::NoModifier, button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint()); + QTRY_COMPARE(buttonSpy.count(), 1); + QVERIFY(!popupWindow->isVisible()); + + popup->setModal(true); + popup->open(); + QTRY_VERIFY(popup->isVisible()); + QVERIFY(popupWindow->isVisible()); + QCOMPARE(popupWindow->modality(), Qt::ApplicationModal); + + // Pressing outside the popup shouldn't cause the button to get the event, because of modality. + QTest::mouseClick(helper.window, Qt::LeftButton, Qt::NoModifier, button->mapToScene(QPointF(button->width() / 2, button->height() / 2)).toPoint()); + QCoreApplication::processEvents(); + QCOMPARE(buttonSpy.count(), 1); + QVERIFY(popupWindow->isVisible()); + + popup->close(); + QTRY_VERIFY(!popup->isVisible()); +} + +void tst_QQuickPopup::popupWindowClosesOnParentWindowClosing() +{ + QSKIP("The behavior isn't correctly implemented yet. Waiting for patch in qtbase"); + if (!popupWindowsSupported) + QSKIP("The platform doesn't support popup windows. Skipping test."); + + QQuickApplicationHelper helper(this, "simplepopup.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + auto *popupPrivate = QQuickPopupPrivate::get(popup); + QVERIFY(popupPrivate); + + popup->setPopupType(QQuickPopup::Window); + + popup->open(); + QTRY_VERIFY(popup->isVisible()); + + auto *popupWindow = popupPrivate->popupWindow; + QVERIFY(popupWindow); + QVERIFY(popupWindow->isVisible()); + + // Closing parent window, should close child window; + window->close(); + + QTRY_VERIFY(!window->isVisible()); + QTRY_VERIFY(!popupWindow->isVisible()); +} + +void tst_QQuickPopup::initialPopupSize_data() +{ + QTest::addColumn<QQuickPopup::PopupType>("popupType"); + + QTest::newRow("Item") << QQuickPopup::Item; + if (popupWindowsSupported) + QTest::newRow("Window") << QQuickPopup::Window; +} + +void tst_QQuickPopup::initialPopupSize() +{ + QFETCH(QQuickPopup::PopupType, popupType); + QQuickApplicationHelper helper(this, "reparentingPopup.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + auto *popupPrivate = QQuickPopupPrivate::get(popup); + QVERIFY(popupPrivate); + + popup->setPopupType(popupType); + popup->open(); + QTRY_VERIFY(popup->isOpened()); + + QCOMPARE(popup->width(), 200); + QCOMPARE(popup->height(), 200); + + auto popupItem = popupPrivate->popupItem; + QCOMPARE(popupItem->width(), 200); + QCOMPARE(popupItem->height(), 200); + + if (popupType == QQuickPopup::Window) { + auto *popupWindow = popupPrivate->popupWindow; + QVERIFY(popupWindow); + QVERIFY(popupWindow->isVisible()); + QCOMPARE(popupWindow->width(), 200); + QCOMPARE(popupWindow->height(), 200); + } +} + +void tst_QQuickPopup::popupWindowChangingParent() +{ + if (!popupWindowsSupported) + QSKIP("The platform doesn't support popup windows. Skipping test."); + + QQuickApplicationHelper helper(this, "reparentingPopup.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickWindow *window = helper.window; + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + auto *popupPrivate = QQuickPopupPrivate::get(popup); + QVERIFY(popupPrivate); + + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + QVERIFY(!popup->isVisible()); + + QQuickItem *item1 = window->property("rectangle1").value<QQuickItem *>(); + QVERIFY(item1); + + QQuickItem *item2 = window->property("rectangle2").value<QQuickItem *>(); + QVERIFY(item2); + + QQuickItem *item3 = window->property("rectangle3").value<QQuickItem *>(); + QVERIFY(item3); + + popup->open(); + QTRY_VERIFY(popup->isOpened()); + + QTRY_VERIFY(popupPrivate->popupWindow); + QWindow *popupWindow = popupPrivate->popupWindow; + + QTRY_VERIFY(popupWindow->isVisible()); + QVERIFY(QTest::qWaitForWindowExposed(popupWindow)); + + const QPoint initialPos(10, 10); + + VERIFY_GLOBAL_POS(item1, popupWindow, initialPos); + VERIFY_LOCAL_POS(popup, initialPos); + + popup->setParentItem(item1); + + VERIFY_GLOBAL_POS(item1, popupWindow, initialPos); + VERIFY_LOCAL_POS(popup, initialPos); + + popup->setParentItem(item2); + + VERIFY_GLOBAL_POS(item2, popupWindow, initialPos); + VERIFY_LOCAL_POS(popup, initialPos); + + popup->setParentItem(item3); + + VERIFY_GLOBAL_POS(item3, popupWindow, initialPos); + VERIFY_LOCAL_POS(popup, initialPos); +} + +void tst_QQuickPopup::popupWindowFocus() +{ + if (!popupWindowsSupported) + QSKIP("The platform doesn't support popup windows. Skipping test."); + + QQuickApplicationHelper helper(this, "popupWindowFocusHandling.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickWindow *window = helper.window; + QVERIFY(window); + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + auto *popupPrivate = QQuickPopupPrivate::get(popup); + QVERIFY(popupPrivate); + QQuickTextInput *textField1 = window->property("textField1").value<QQuickTextInput *>(); + QVERIFY(textField1); + QQuickTextInput *textField2 = window->property("textField2").value<QQuickTextInput *>(); + QVERIFY(textField2); + + window->show(); + QVERIFY(QTest::qWaitForWindowFocused(window)); + QVERIFY(QGuiApplication::focusObject() == textField1); + QTest::keyClick(helper.window, Qt::Key_Q); + QTRY_COMPARE(textField1->text(), "q"); + popup->open(); + QTRY_VERIFY(popup->isVisible()); + auto *popupWindow = popupPrivate->popupWindow; + QVERIFY(popupWindow); + QVERIFY(popupWindow->isVisible()); + // The focusWindow should still be the main window, + // the popup window should get its event forwarded via the delivery agent + QVERIFY(QGuiApplication::focusWindow() == helper.window); + QVERIFY(popupWindow->focusObject() == textField2); + QTest::keyClick(popupWindow, Qt::Key_T); + QTRY_COMPARE(textField2->text(), "t"); + popup->close(); + QTRY_VERIFY(!popup->isVisible()); + QVERIFY(QGuiApplication::focusObject() == textField1); +} + +void tst_QQuickPopup::popupTypeChangeFromWindowToItem() +{ + if (!popupWindowsSupported) + QSKIP("The platform doesn't support native popup windows. Skipping test."); + + QQuickApplicationHelper helper(this, "simplepopup.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + auto *popupPrivate = QQuickPopupPrivate::get(popup); + QVERIFY(popupPrivate); + + QQuickOverlay *overlay = QQuickOverlay::overlay(window); + QVERIFY(overlay); + + popup->setPopupType(QQuickPopup::Window); + + popup->open(); + QTRY_VERIFY(popup->isOpened()); + const QWindow *popupWindow = popupPrivate->popupWindow; + QVERIFY(popupWindow); + QTRY_VERIFY(popupWindow->isVisible()); + QCOMPARE(popupPrivate->popupItem->position(), QPointF(0, 0)); + QVERIFY(!overlay->childItems().contains(popup->popupItem())); + + popup->close(); + QTRY_VERIFY(!popup->isVisible()); + QVERIFY(!popupWindow->isVisible()); + + popup->setPopupType(QQuickPopup::Item); + + popup->open(); + QTRY_VERIFY(popup->isOpened()); + QVERIFY(!popupWindow || !popupWindow->isVisible()); + QCOMPARE(popupPrivate->popupItem->position(), QPointF(50, 50)); + QVERIFY(overlay->childItems().contains(popup->popupItem())); + + popup->close(); +} + +void tst_QQuickPopup::popupTypeChangeFromItemToWindow() +{ + if (!popupWindowsSupported) + QSKIP("The platform doesn't support popup windows. Skipping test."); + + QQuickApplicationHelper helper(this, "simplepopup.qml"); + QVERIFY2(helper.ready, helper.failureMessage()); + QQuickWindow *window = helper.window; + window->show(); + QVERIFY(QTest::qWaitForWindowExposed(window)); + auto *popup = window->contentItem()->findChild<QQuickPopup *>(); + QVERIFY(popup); + auto *popupPrivate = QQuickPopupPrivate::get(popup); + QVERIFY(popupPrivate); + + QQuickOverlay *overlay = QQuickOverlay::overlay(window); + QVERIFY(overlay); + + popup->setPopupType(QQuickPopup::Item); + + popup->open(); + QTRY_VERIFY(popup->isOpened()); + QVERIFY(!popupPrivate->popupWindow); + QCOMPARE(popupPrivate->popupItem->position(), QPointF(50, 50)); + QVERIFY(overlay->childItems().contains(popup->popupItem())); + + popup->close(); + QTRY_VERIFY(!popup->isVisible()); + + popup->setPopupType(QQuickPopup::Window); + + popup->open(); + QTRY_VERIFY(popup->isOpened()); + const QWindow *popupWindow = popupPrivate->popupWindow; + QVERIFY(popupWindow); + QTRY_VERIFY(popupWindow->isVisible()); + QCOMPARE(popupPrivate->popupItem->position(), QPointF(0, 0)); + QVERIFY(!overlay->childItems().contains(popup->popupItem())); + + popup->close(); +} + QTEST_QUICKCONTROLS_MAIN(tst_QQuickPopup) #include "tst_qquickpopup.moc" |