summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/widgets/kernel')
-rw-r--r--tests/auto/widgets/kernel/CMakeLists.txt2
-rw-r--r--tests/auto/widgets/kernel/qaction/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qaction/tst_qaction.cpp2
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp2
-rw-r--r--tests/auto/widgets/kernel/qapplication/BLACKLIST4
-rw-r--r--tests/auto/widgets/kernel/qapplication/CMakeLists.txt6
-rw-r--r--tests/auto/widgets/kernel/qapplication/desktopsettingsaware/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp2
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/base.cpp2
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/base.h2
-rw-r--r--tests/auto/widgets/kernel/qapplication/modal/main.cpp2
-rw-r--r--tests/auto/widgets/kernel/qapplication/test/CMakeLists.txt20
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp51
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp4
-rw-r--r--tests/auto/widgets/kernel/qformlayout/BLACKLIST0
-rw-r--r--tests/auto/widgets/kernel/qformlayout/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp2
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp4
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp5
-rw-r--r--tests/auto/widgets/kernel/qlayout/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp14
-rw-r--r--tests/auto/widgets/kernel/qshortcut/CMakeLists.txt22
-rw-r--r--tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp4
-rw-r--r--tests/auto/widgets/kernel/qsizepolicy/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp4
-rw-r--r--tests/auto/widgets/kernel/qstackedlayout/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp2
-rw-r--r--tests/auto/widgets/kernel/qtooltip/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp33
-rw-r--r--tests/auto/widgets/kernel/qwidget/BLACKLIST10
-rw-r--r--tests/auto/widgets/kernel/qwidget/CMakeLists.txt11
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp1048
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/BLACKLIST4
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp187
-rw-r--r--tests/auto/widgets/kernel/qwidgetaction/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp2
-rw-r--r--tests/auto/widgets/kernel/qwidgetmetatype/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp2
-rw-r--r--tests/auto/widgets/kernel/qwidgetrepaintmanager/CMakeLists.txt6
-rw-r--r--tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp111
-rw-r--r--tests/auto/widgets/kernel/qwidgetsvariant/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qwidgetsvariant/tst_qwidgetsvariant.cpp2
-rw-r--r--tests/auto/widgets/kernel/qwindowcontainer/CMakeLists.txt8
-rw-r--r--tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp122
50 files changed, 1609 insertions, 221 deletions
diff --git a/tests/auto/widgets/kernel/CMakeLists.txt b/tests/auto/widgets/kernel/CMakeLists.txt
index 0ec1fa4626..2d4880ea3c 100644
--- a/tests/auto/widgets/kernel/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from kernel.pro.
-
add_subdirectory(qapplication)
add_subdirectory(qboxlayout)
add_subdirectory(qformlayout)
diff --git a/tests/auto/widgets/kernel/qaction/CMakeLists.txt b/tests/auto/widgets/kernel/qaction/CMakeLists.txt
index 1c0c49c11d..9d1985da0b 100644
--- a/tests/auto/widgets/kernel/qaction/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qaction/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qaction.pro.
-
#####################################################################
## tst_qaction Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qaction LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qaction
SOURCES
tst_qaction.cpp
diff --git a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
index d9c6c02d6b..36985c0de3 100644
--- a/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
+++ b/tests/auto/widgets/kernel/qaction/tst_qaction.cpp
@@ -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
#include <QDialog>
#include <QMainWindow>
diff --git a/tests/auto/widgets/kernel/qactiongroup/CMakeLists.txt b/tests/auto/widgets/kernel/qactiongroup/CMakeLists.txt
index 3c323d3187..e26ee75bc1 100644
--- a/tests/auto/widgets/kernel/qactiongroup/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qactiongroup/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qactiongroup.pro.
-
#####################################################################
## tst_qactiongroup Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qactiongroup LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qactiongroup
SOURCES
tst_qactiongroup.cpp
diff --git a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
index 56d2feee47..0d42340bfb 100644
--- a/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
+++ b/tests/auto/widgets/kernel/qactiongroup/tst_qactiongroup.cpp
@@ -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
#include <QTest>
diff --git a/tests/auto/widgets/kernel/qapplication/BLACKLIST b/tests/auto/widgets/kernel/qapplication/BLACKLIST
index 7f4dd88261..c68c7d6b14 100644
--- a/tests/auto/widgets/kernel/qapplication/BLACKLIST
+++ b/tests/auto/widgets/kernel/qapplication/BLACKLIST
@@ -1,7 +1,3 @@
-[sendEventsOnProcessEvents]
-ubuntu-20.04
-ubuntu-22.04
-rhel-9.0
[touchEventPropagation]
# QTBUG-66745
opensuse-leap
diff --git a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt
index 85c3ba5686..524db06560 100644
--- a/tests/auto/widgets/kernel/qapplication/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qapplication/CMakeLists.txt
@@ -1,7 +1,11 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qapplication.pro.
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qapplication LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
add_subdirectory(desktopsettingsaware)
add_subdirectory(modal)
diff --git a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/CMakeLists.txt
index aa378d59e6..f094a451d2 100644
--- a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/CMakeLists.txt
@@ -1,17 +1,15 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from desktopsettingsaware.pro.
-
#####################################################################
## desktopsettingsaware Binary:
#####################################################################
-qt_internal_add_executable(desktopsettingsaware_helper # special case
+qt_internal_add_executable(desktopsettingsaware_helper
SOURCES
main.cpp
- OUTPUT_DIRECTORY # special case
- ${CMAKE_CURRENT_BINARY_DIR}/.. # special case
+ OUTPUT_DIRECTORY
+ ${CMAKE_CURRENT_BINARY_DIR}/..
LIBRARIES
Qt::Gui
Qt::Widgets
diff --git a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp
index 0584dbeab8..1bf3eef55c 100644
--- a/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp
+++ b/tests/auto/widgets/kernel/qapplication/desktopsettingsaware/main.cpp
@@ -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
#include <QApplication>
diff --git a/tests/auto/widgets/kernel/qapplication/modal/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/modal/CMakeLists.txt
index 0d9414e3b6..79c5660650 100644
--- a/tests/auto/widgets/kernel/qapplication/modal/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qapplication/modal/CMakeLists.txt
@@ -1,18 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from modal.pro.
-
#####################################################################
## modal Binary:
#####################################################################
-qt_internal_add_executable(modal_helper # special case
+qt_internal_add_executable(modal_helper
SOURCES
base.cpp base.h
main.cpp
- OUTPUT_DIRECTORY # special case
- ${CMAKE_CURRENT_BINARY_DIR}/.. # special case
+ OUTPUT_DIRECTORY
+ ${CMAKE_CURRENT_BINARY_DIR}/..
LIBRARIES
Qt::Gui
Qt::Widgets
diff --git a/tests/auto/widgets/kernel/qapplication/modal/base.cpp b/tests/auto/widgets/kernel/qapplication/modal/base.cpp
index 0108c9c789..49a90723dd 100644
--- a/tests/auto/widgets/kernel/qapplication/modal/base.cpp
+++ b/tests/auto/widgets/kernel/qapplication/modal/base.cpp
@@ -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
#include "base.h"
diff --git a/tests/auto/widgets/kernel/qapplication/modal/base.h b/tests/auto/widgets/kernel/qapplication/modal/base.h
index a78b2306ba..168da92f97 100644
--- a/tests/auto/widgets/kernel/qapplication/modal/base.h
+++ b/tests/auto/widgets/kernel/qapplication/modal/base.h
@@ -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
#ifndef BASE_H
#define BASE_H
diff --git a/tests/auto/widgets/kernel/qapplication/modal/main.cpp b/tests/auto/widgets/kernel/qapplication/modal/main.cpp
index be38c41786..3f3496834d 100644
--- a/tests/auto/widgets/kernel/qapplication/modal/main.cpp
+++ b/tests/auto/widgets/kernel/qapplication/modal/main.cpp
@@ -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
#include <QApplication>
#include "base.h"
diff --git a/tests/auto/widgets/kernel/qapplication/test/CMakeLists.txt b/tests/auto/widgets/kernel/qapplication/test/CMakeLists.txt
index 93d59c91ce..fc80b8af7e 100644
--- a/tests/auto/widgets/kernel/qapplication/test/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qapplication/test/CMakeLists.txt
@@ -1,8 +1,6 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from test.pro.
-
#####################################################################
## test Test:
#####################################################################
@@ -11,7 +9,7 @@
list(APPEND test_data "../tmp/README")
list(APPEND test_data "../modal")
-qt_internal_add_test(tst_qapplication # special case
+qt_internal_add_test(tst_qapplication
SOURCES
../tst_qapplication.cpp
LIBRARIES
@@ -21,25 +19,13 @@ qt_internal_add_test(tst_qapplication # special case
Qt::Widgets
Qt::WidgetsPrivate
TESTDATA ${test_data}
- OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.." # special case
+ OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/.."
)
## Scopes:
#####################################################################
-qt_internal_extend_target(tst_qapplication CONDITION builtin_testdata # special case
+qt_internal_extend_target(tst_qapplication CONDITION builtin_testdata
DEFINES
BUILTIN_TESTDATA
)
-
-#### Keys ignored in scope 3:.:.:test.pro:NOT ANDROID:
-# SUBPROGRAMS = "desktopsettingsaware" "modal"
-
-#### Keys ignored in scope 6:.:.:test.pro:NOT ANDROID:
-# TEST_HELPER_INSTALLS = "../debug/helper"
-
-#### Keys ignored in scope 8:.:.:test.pro:NOT ANDROID:
-# TEST_HELPER_INSTALLS = "../release/helper"
-
-#### Keys ignored in scope 10:.:.:test.pro:NOT ANDROID:
-# TEST_HELPER_INSTALLS = "../helper"
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index 3ed9743838..b71a7a0a31 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -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
#define QT_STATICPLUGIN
#include <QtWidgets/qstyleplugin.h>
@@ -94,7 +94,9 @@ private slots:
void libraryPaths_qt_plugin_path_2();
#endif
+#ifdef QT_BUILD_INTERNAL
void sendPostedEvents();
+#endif // ifdef QT_BUILD_INTERNAL
void thread();
void desktopSettingsAware();
@@ -164,6 +166,21 @@ void tst_QApplication::sendEventsOnProcessEvents()
QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1)));
QCoreApplication::processEvents();
+
+#ifdef Q_OS_LINUX
+ if ((QSysInfo::productType() == "rhel" && QSysInfo::productVersion().startsWith(u'9'))
+ || (QSysInfo::productType() == "ubuntu" && QSysInfo::productVersion().startsWith(u'2')))
+ {
+ QFile f("/proc/self/maps");
+ QVERIFY(f.open(QIODevice::ReadOnly));
+
+ QByteArray libs = f.readAll();
+ if (libs.contains("libqgtk3.") || libs.contains("libqgtk3TestInfix.")) {
+ QEXPECT_FAIL("", "Fails if qgtk3 (Glib) is loaded, see QTBUG-87137", Abort);
+ }
+ }
+#endif
+
QVERIFY(spy.recordedEvents.contains(QEvent::User + 1));
}
@@ -1126,6 +1143,7 @@ void tst_QApplication::libraryPaths_qt_plugin_path_2()
}
#endif
+#ifdef QT_BUILD_INTERNAL
class SendPostedEventsTester : public QObject
{
Q_OBJECT
@@ -1147,7 +1165,7 @@ void SendPostedEventsTester::doTest()
QPointer<SendPostedEventsTester> p = this;
QApplication::postEvent(this, new QEvent(QEvent::User));
// DeferredDelete should not be delivered until returning from this function
- QApplication::postEvent(this, new QDeferredDeleteEvent());
+ deleteLater();
QEventLoop eventLoop;
QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection);
@@ -1171,6 +1189,7 @@ void tst_QApplication::sendPostedEvents()
(void) QCoreApplication::exec();
QVERIFY(p.isNull());
}
+#endif
void tst_QApplication::thread()
{
@@ -1315,9 +1334,6 @@ void DeleteLaterWidget::checkDeleteLater()
void tst_QApplication::testDeleteLater()
{
-#ifdef Q_OS_MAC
- QSKIP("This test fails and then hangs on OS X, see QTBUG-24318");
-#endif
int argc = 0;
QApplication app(argc, nullptr);
connect(&app, &QGuiApplication::lastWindowClosed, &app, &QCoreApplication::quit);
@@ -2558,8 +2574,26 @@ public:
explicit ShowCloseShowWidget(bool showAgain, QWidget *parent = nullptr)
: QWidget(parent), showAgain(showAgain)
{
+ int timeout = 500;
+#ifdef Q_OS_ANDROID
+ // On Android, CI Android emulator is not running HW accelerated graphics and can be slow,
+ // use a longer timeout to avoid flaky failures
+ timeout = 1000;
+#endif
+ QTimer::singleShot(timeout, this, [] () { QCoreApplication::exit(1); });
+ }
+
+ bool shown = false;
+
+protected:
+ void showEvent(QShowEvent *) override
+ {
QTimer::singleShot(0, this, &ShowCloseShowWidget::doClose);
- QTimer::singleShot(500, this, [] () { QCoreApplication::exit(1); });
+ shown = true;
+ }
+ void hideEvent(QHideEvent *) override
+ {
+ shown = false;
}
private slots:
@@ -2575,16 +2609,21 @@ private:
void tst_QApplication::abortQuitOnShow()
{
+ if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
+ QSKIP("Wayland: This crash, see QTBUG-123172.");
+
int argc = 0;
QApplication app(argc, nullptr);
ShowCloseShowWidget window1(false);
window1.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
window1.show();
+ QVERIFY(QTest::qWaitFor([&window1](){ return window1.shown; }));
QCOMPARE(QCoreApplication::exec(), 0);
ShowCloseShowWidget window2(true);
window2.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
window2.show();
+ QVERIFY(QTest::qWaitFor([&window2](){ return window2.shown; }));
QCOMPARE(QCoreApplication::exec(), 1);
}
diff --git a/tests/auto/widgets/kernel/qboxlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qboxlayout/CMakeLists.txt
index 0563a130cc..5b60382fba 100644
--- a/tests/auto/widgets/kernel/qboxlayout/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qboxlayout/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qboxlayout.pro.
-
#####################################################################
## tst_qboxlayout Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qboxlayout LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qboxlayout
SOURCES
tst_qboxlayout.cpp
diff --git a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
index febb517638..4313d9891c 100644
--- a/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
+++ b/tests/auto/widgets/kernel/qboxlayout/tst_qboxlayout.cpp
@@ -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
#include <QTest>
@@ -192,7 +192,7 @@ void tst_QBoxLayout::setStyleShouldChangeSpacing()
window.setWindowTitle(QTest::currentTestFunction());
QHBoxLayout *hbox = new QHBoxLayout(&window);
QPushButton *pb1 = new QPushButton(tr("The spacing between this"));
- QPushButton *pb2 = new QPushButton(tr("and this button should depend on the style of the parent widget"));;
+ QPushButton *pb2 = new QPushButton(tr("and this button should depend on the style of the parent widget"));
pb1->setAttribute(Qt::WA_LayoutUsesWidgetRect);
pb2->setAttribute(Qt::WA_LayoutUsesWidgetRect);
hbox->addWidget(pb1);
diff --git a/tests/auto/widgets/kernel/qformlayout/BLACKLIST b/tests/auto/widgets/kernel/qformlayout/BLACKLIST
deleted file mode 100644
index e69de29bb2..0000000000
--- a/tests/auto/widgets/kernel/qformlayout/BLACKLIST
+++ /dev/null
diff --git a/tests/auto/widgets/kernel/qformlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qformlayout/CMakeLists.txt
index 38a6580cb0..9e1da4c6a3 100644
--- a/tests/auto/widgets/kernel/qformlayout/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qformlayout/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qformlayout.pro.
-
#####################################################################
## tst_qformlayout Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qformlayout LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qformlayout
SOURCES
tst_qformlayout.cpp
diff --git a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
index 44b716bb34..9638823538 100644
--- a/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
+++ b/tests/auto/widgets/kernel/qformlayout/tst_qformlayout.cpp
@@ -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
#include <QTest>
diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/CMakeLists.txt b/tests/auto/widgets/kernel/qgesturerecognizer/CMakeLists.txt
index 2427e4a2ab..ffa54992d3 100644
--- a/tests/auto/widgets/kernel/qgesturerecognizer/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qgesturerecognizer.pro.
-
#####################################################################
## tst_qgesturerecognizer Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qgesturerecognizer LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qgesturerecognizer
SOURCES
tst_qgesturerecognizer.cpp
diff --git a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
index 87e0290473..cdab480d84 100644
--- a/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
+++ b/tests/auto/widgets/kernel/qgesturerecognizer/tst_qgesturerecognizer.cpp
@@ -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
#include <QtTest/QTest>
@@ -71,7 +71,7 @@ TestWidget::TestWidget(const GestureTypeVector &gestureTypes)
{
setAttribute(Qt::WA_AcceptTouchEvents);
- foreach (Qt::GestureType gestureType, gestureTypes) {
+ for (Qt::GestureType gestureType : gestureTypes) {
grabGesture(gestureType);
m_receivedGestures.insert(gestureType, false);
}
diff --git a/tests/auto/widgets/kernel/qgridlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qgridlayout/CMakeLists.txt
index 016c4f4490..bf72bc0ae6 100644
--- a/tests/auto/widgets/kernel/qgridlayout/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qgridlayout/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qgridlayout.pro.
-
#####################################################################
## tst_qgridlayout Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qgridlayout LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qgridlayout
SOURCES
sortdialog.ui
diff --git a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
index 3871079da7..3c325699a7 100644
--- a/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
+++ b/tests/auto/widgets/kernel/qgridlayout/tst_qgridlayout.cpp
@@ -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
#include <QTest>
@@ -58,7 +58,8 @@ private slots:
static inline int visibleTopLevelWidgetCount()
{
int result= 0;
- foreach (const QWidget *topLevel, QApplication::topLevelWidgets()) {
+ const auto topLevels = QApplication::topLevelWidgets();
+ for (const QWidget *topLevel : topLevels) {
if (topLevel->isVisible())
++result;
}
diff --git a/tests/auto/widgets/kernel/qlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qlayout/CMakeLists.txt
index 459af03f3a..6bda750c0f 100644
--- a/tests/auto/widgets/kernel/qlayout/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qlayout/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qlayout.pro.
-
#####################################################################
## tst_qlayout Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qlayout LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Collect test data
file(GLOB_RECURSE test_data_glob
RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
diff --git a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
index 9d5f7940cc..bd170ca8ab 100644
--- a/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
+++ b/tests/auto/widgets/kernel/qlayout/tst_qlayout.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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>
@@ -378,10 +378,10 @@ void tst_QLayout::removeWidget()
{
QHBoxLayout layout;
QCOMPARE(layout.count(), 0);
- QWidget w;
- layout.addWidget(&w);
+ std::unique_ptr<QWidget> w(new QWidget);
+ layout.addWidget(w.get());
QCOMPARE(layout.count(), 1);
- layout.removeWidget(&w);
+ layout.removeWidget(w.get());
QCOMPARE(layout.count(), 0);
QPointer<QLayout> childLayout(new QHBoxLayout);
@@ -395,6 +395,12 @@ void tst_QLayout::removeWidget()
QCOMPARE(layout.count(), 0);
QVERIFY(!childLayout.isNull());
+
+ // Test inactive layout consumes ChildRemoved event (QTBUG-124151)
+ layout.addWidget(w.get());
+ layout.setEnabled(false);
+ w.reset();
+ layout.setEnabled(true);
}
QTEST_MAIN(tst_QLayout)
diff --git a/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt b/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt
index 78c0bb26de..517286f324 100644
--- a/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qshortcut/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qshortcut.pro.
-
#####################################################################
## tst_qshortcut Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qshortcut LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qshortcut
SOURCES
tst_qshortcut.cpp
@@ -18,3 +22,17 @@ qt_internal_add_test(tst_qshortcut
Qt::Widgets
Qt::WidgetsPrivate
)
+
+qt_internal_add_test(tst_qguishortcut_with_qapplication
+ SOURCES
+ ../../../gui/kernel/qshortcut/tst_qshortcut.cpp
+ DEFINES
+ tst_QShortcut=tst_QGuiShortcutWithQApplication
+ INCLUDE_DIRECTORIES
+ ..
+ LIBRARIES
+ Qt::Gui
+ Qt::GuiPrivate
+ Qt::Widgets
+ Qt::WidgetsPrivate
+)
diff --git a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp
index df4dfde0d2..d34df43b01 100644
--- a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp
+++ b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp
@@ -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
#include <QTest>
@@ -1064,7 +1064,6 @@ void tst_QShortcut::context()
// Focus on 'other1' edit, so Active Window context should trigger
other1->activateWindow(); // <---
- QApplicationPrivate::setActiveWindow(other1);
QCOMPARE(QApplication::activeWindow(), other1->window());
QCOMPARE(QApplication::focusWidget(), static_cast<QWidget *>(other1));
@@ -1156,7 +1155,6 @@ void tst_QShortcut::duplicatedShortcutOverride()
w.resize(200, 200);
w.move(QGuiApplication::primaryScreen()->availableGeometry().center() - QPoint(100, 100));
w.show();
- QApplicationPrivate::setActiveWindow(&w);
QVERIFY(QTest::qWaitForWindowActive(&w));
QTest::keyPress(w.windowHandle(), Qt::Key_A);
QCoreApplication::processEvents();
diff --git a/tests/auto/widgets/kernel/qsizepolicy/CMakeLists.txt b/tests/auto/widgets/kernel/qsizepolicy/CMakeLists.txt
index 7acb14bbe4..efdd72db73 100644
--- a/tests/auto/widgets/kernel/qsizepolicy/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qsizepolicy/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qsizepolicy.pro.
-
#####################################################################
## tst_qsizepolicy Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qsizepolicy LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qsizepolicy
SOURCES
tst_qsizepolicy.cpp
diff --git a/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp b/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp
index 5b64f122e2..19d267f7e5 100644
--- a/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp
+++ b/tests/auto/widgets/kernel/qsizepolicy/tst_qsizepolicy.cpp
@@ -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
#include <qsizepolicy.h>
@@ -95,7 +95,7 @@ void tst_QSizePolicy::constExpr()
{
// QTBUG-69983: For ControlType != QSizePolicy::DefaultType, qCountTrailingZeroBits()
// is used, which MSVC 15.8.1 does not consider constexpr due to built-ins
-# if defined(QT_HAS_CONSTEXPR_BUILTINS) && (!defined(Q_CC_MSVC) || _MSC_VER < 1915)
+# if defined(QT_HAS_CONSTEXPR_BITOPS)
constexpr auto sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed, QSizePolicy::CheckBox);
# else
constexpr auto sp = QSizePolicy(QSizePolicy::Minimum, QSizePolicy::Expanding, QSizePolicy::DefaultType);
diff --git a/tests/auto/widgets/kernel/qstackedlayout/CMakeLists.txt b/tests/auto/widgets/kernel/qstackedlayout/CMakeLists.txt
index c5304b8eb7..5701f455b5 100644
--- a/tests/auto/widgets/kernel/qstackedlayout/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qstackedlayout/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qstackedlayout.pro.
-
#####################################################################
## tst_qstackedlayout Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qstackedlayout LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qstackedlayout
SOURCES
tst_qstackedlayout.cpp
diff --git a/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp b/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp
index 967535dbc7..ca002a1375 100644
--- a/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp
+++ b/tests/auto/widgets/kernel/qstackedlayout/tst_qstackedlayout.cpp
@@ -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
#include <QTest>
diff --git a/tests/auto/widgets/kernel/qtooltip/CMakeLists.txt b/tests/auto/widgets/kernel/qtooltip/CMakeLists.txt
index 04ef24b99a..af2de80e24 100644
--- a/tests/auto/widgets/kernel/qtooltip/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qtooltip/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qtooltip.pro.
-
#####################################################################
## tst_qtooltip Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qtooltip LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qtooltip
SOURCES
tst_qtooltip.cpp
diff --git a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
index b959d8982f..bc0624c9ab 100644
--- a/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
+++ b/tests/auto/widgets/kernel/qtooltip/tst_qtooltip.cpp
@@ -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
#include <QTest>
@@ -26,6 +26,7 @@ private slots:
void setPalette();
void qtbug64550_stylesheet();
void dontCrashOutsideScreenGeometry();
+ void marginSetWithStyleSheet();
};
void tst_QToolTip::init()
@@ -97,7 +98,6 @@ void tst_QToolTip::keyEvent()
widget.setWindowTitle(QLatin1String(QTest::currentTestFunction())
+ QLatin1Char(' ') + QLatin1String(QTest::currentDataTag()));
widget.show();
- QApplicationPrivate::setActiveWindow(&widget);
QVERIFY(QTest::qWaitForWindowActive(&widget));
widget.showDelayedToolTip(100);
@@ -117,7 +117,8 @@ void tst_QToolTip::keyEvent()
static QWidget *findWhatsThat()
{
- foreach (QWidget *widget, QApplication::topLevelWidgets()) {
+ const auto widgets = QApplication::topLevelWidgets();
+ for (QWidget *widget : widgets) {
if (widget->inherits("QWhatsThat"))
return widget;
}
@@ -191,7 +192,6 @@ void tst_QToolTip::qtbug64550_stylesheet()
Widget widget;
widget.setStyleSheet(QStringLiteral("* { font-size: 48pt; }\n"));
widget.show();
- QApplicationPrivate::setActiveWindow(&widget);
QVERIFY(QTest::qWaitForWindowActive(&widget));
widget.showDelayedToolTip(100);
@@ -213,5 +213,30 @@ void tst_QToolTip::dontCrashOutsideScreenGeometry() {
QToolTip::hideText();
}
+void tst_QToolTip::marginSetWithStyleSheet()
+{
+ const char *toolTipText = "Test Tool Tip";
+
+ qApp->setStyleSheet("QToolTip {font-size: 8px; margin: 5px;}");
+ QToolTip::showText(QGuiApplication::primaryScreen()->availableGeometry().topLeft(), toolTipText);
+ QTRY_VERIFY(QToolTip::isVisible());
+ QWidget *toolTip = findToolTip();
+ QVERIFY(toolTip);
+ QTRY_VERIFY(toolTip->isVisible());
+ int toolTipHeight = toolTip->size().height();
+ qApp->setStyleSheet(QString());
+ QToolTip::hideText();
+
+ qApp->setStyleSheet("QToolTip {font-size: 8px; margin: 10px;}");
+ QToolTip::showText(QGuiApplication::primaryScreen()->availableGeometry().topLeft(), toolTipText);
+ QTRY_VERIFY(QToolTip::isVisible());
+ toolTip = findToolTip();
+ QVERIFY(toolTip);
+ QTRY_VERIFY(toolTip->isVisible());
+ QCOMPARE_LE(toolTip->size().height(), toolTipHeight + 10);
+ qApp->setStyleSheet(QString());
+ QToolTip::hideText();
+}
+
QTEST_MAIN(tst_QToolTip)
#include "tst_qtooltip.moc"
diff --git a/tests/auto/widgets/kernel/qwidget/BLACKLIST b/tests/auto/widgets/kernel/qwidget/BLACKLIST
index 257a837311..4c17af245b 100644
--- a/tests/auto/widgets/kernel/qwidget/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget/BLACKLIST
@@ -1,9 +1,5 @@
[raise]
opensuse-leap
-[renderInvisible]
-macos
-[optimizedResizeMove]
-osx
[optimizedResize_topLevel]
osx
[render_windowOpacity]
@@ -19,6 +15,7 @@ sles-15
[showMinimizedKeepsFocus]
android
macos-13 ci
+macos-14 ci
[normalGeometry]
android
[saveRestoreGeometry]
@@ -45,3 +42,8 @@ android
android
[optimizedResize_topLevel]
android
+[hoverPosition]
+macos-14 x86
+# QTBUG-124291
+[setParentChangesFocus:make dialog parentless, after]
+android
diff --git a/tests/auto/widgets/kernel/qwidget/CMakeLists.txt b/tests/auto/widgets/kernel/qwidget/CMakeLists.txt
index a18c64a780..f18bc98bb3 100644
--- a/tests/auto/widgets/kernel/qwidget/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qwidget/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qwidget.pro.
-
#####################################################################
## tst_qwidget Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qwidget LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
# Resources:
set(qwidget_resource_files
"geometry-fullscreen.dat"
@@ -29,9 +33,6 @@ qt_internal_add_test(tst_qwidget
BUILTIN_TESTDATA
)
-#### Keys ignored in scope 1:.:.:qwidget.pro:<TRUE>:
-# testcase.timeout = "600"
-
## Scopes:
#####################################################################
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 23d915155e..9b66002a2f 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -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
#include "../../../shared/highdpi.h"
@@ -13,6 +13,7 @@
#include <qlineedit.h>
#include <qlistview.h>
#include <qmessagebox.h>
+#include <qmimedata.h>
#include <qpainter.h>
#include <qpoint.h>
#include <qpushbutton.h>
@@ -37,6 +38,7 @@
#include <QtGui/qbackingstore.h>
#include <QtGui/qguiapplication.h>
#include <QtGui/qpa/qplatformwindow.h>
+#include <QtGui/qpa/qplatformdrag.h>
#include <QtGui/qscreen.h>
#include <qmenubar.h>
#include <qcompleter.h>
@@ -49,6 +51,7 @@
#include <QtGui/qwindow.h>
#include <qtimer.h>
#include <QtWidgets/QDoubleSpinBox>
+#include <QtWidgets/QComboBox>
#include <QtTest/QTest>
#include <QtTest/private/qtesthelpers_p.h>
@@ -119,6 +122,34 @@ static QByteArray msgComparisonFailed(T v1, const char *op, T v2)
return s.toLocal8Bit();
}
+template<class T> class EventSpy : public QObject
+{
+public:
+ EventSpy(T *widget, QEvent::Type event)
+ : m_widget(widget), eventToSpy(event)
+ {
+ if (m_widget)
+ m_widget->installEventFilter(this);
+ }
+
+ T *widget() const { return m_widget; }
+ int count() const { return m_count; }
+ void clear() { m_count = 0; }
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event) override
+ {
+ if (event->type() == eventToSpy)
+ ++m_count;
+ return QObject::eventFilter(object, event);
+ }
+
+private:
+ T *m_widget;
+ const QEvent::Type eventToSpy;
+ int m_count = 0;
+};
+
Q_LOGGING_CATEGORY(lcTests, "qt.widgets.tests")
class tst_QWidget : public QObject
@@ -132,7 +163,9 @@ public:
public slots:
void initTestCase();
void cleanup();
+
private slots:
+ void nativeWindowAttribute();
void addActionOverloads();
void getSetCheck();
void fontPropagation();
@@ -158,12 +191,15 @@ private slots:
void mapFromAndTo();
void focusChainOnHide();
void focusChainOnReparent();
+ void focusAbstraction();
void defaultTabOrder();
void reverseTabOrder();
void tabOrderWithProxy();
void tabOrderWithProxyDisabled();
void tabOrderWithProxyOutOfOrder();
void tabOrderWithCompoundWidgets();
+ void tabOrderWithCompoundWidgetsInflection_data();
+ void tabOrderWithCompoundWidgetsInflection();
void tabOrderWithCompoundWidgetsNoFocusPolicy();
void tabOrderNoChange();
void tabOrderNoChange2();
@@ -171,6 +207,9 @@ private slots:
void appFocusWidgetWhenLosingFocusProxy();
void explicitTabOrderWithComplexWidget();
void explicitTabOrderWithSpinBox_QTBUG81097();
+ void tabOrderList();
+ void tabOrderComboBox_data();
+ void tabOrderComboBox();
#if defined(Q_OS_WIN)
void activation();
#endif
@@ -217,6 +256,7 @@ private slots:
void ensureCreated();
void createAndDestroy();
+ void eventsAndAttributesOnDestroy();
void winIdChangeEvent();
void persistentWinId();
void showNativeChild();
@@ -427,6 +467,15 @@ private slots:
void showFullscreenAndroid();
#endif
+ void setVisibleDuringDestruction();
+
+ void explicitShowHide();
+
+ void dragEnterLeaveSymmetry();
+
+ void reparentWindowHandles_data();
+ void reparentWindowHandles();
+
private:
const QString m_platform;
QSize m_testWidgetSize;
@@ -640,6 +689,10 @@ tst_QWidget::~tst_QWidget()
void tst_QWidget::initTestCase()
{
+#ifdef Q_OS_ANDROID
+ if (QNativeInterface::QAndroidApplication::sdkVersion() == 33)
+ QSKIP("Is flaky on Android 13 / RHEL 8.6 and 8.8 (QTQAINFRA-5606)");
+#endif
// Size of reference widget, 200 for < 2000, scale up for larger screens
// to avoid Windows warnings about minimum size for decorated windows.
int width = 200;
@@ -672,6 +725,24 @@ struct ImplicitlyConvertibleTo {
void testFunction0() {}
void testFunction1(bool) {}
+void tst_QWidget::nativeWindowAttribute()
+{
+ QWidget parent;
+ QWidget child(&parent);
+
+ QCOMPARE(parent.windowHandle(), nullptr);
+ QCOMPARE(child.windowHandle(), nullptr);
+
+ // Setting WA_NativeWindow should create window handle
+ parent.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(parent.windowHandle() != nullptr);
+ // But not its child's window handle
+ QCOMPARE(child.windowHandle(), nullptr);
+ // Until the child also gains WA_NativeWindow
+ child.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(child.windowHandle() != nullptr);
+}
+
void tst_QWidget::addActionOverloads()
{
// almost exhaustive check of addAction() overloads:
@@ -1866,8 +1937,6 @@ void tst_QWidget::focusChainOnHide()
QWidget::setTabOrder(child, parent.data());
parent->show();
- QApplicationPrivate::setActiveWindow(parent->window());
- child->activateWindow();
child->setFocus();
QTRY_VERIFY(child->hasFocus());
@@ -1927,6 +1996,112 @@ public:
QLineEdit *lineEdit3;
};
+static QList<QWidget *> getFocusChain(QWidget *start, bool bForward)
+{
+ QList<QWidget *> ret;
+ QWidget *cur = start;
+ // detect infinite loop
+ int count = 100;
+ auto loopGuard = qScopeGuard([]{
+ QFAIL("Inifinite loop detected in focus chain");
+ });
+ do {
+ ret += cur;
+ cur = bForward ? cur->nextInFocusChain() : cur->previousInFocusChain();
+ if (!--count)
+ return ret;
+ } while (cur != start);
+ loopGuard.dismiss();
+ return ret;
+}
+
+void tst_QWidget::focusAbstraction()
+{
+ QLoggingCategory::setFilterRules("qt.widgets.focus=true");
+ QWidget *widget1 = new QWidget;
+ widget1->setObjectName("Widget 1");
+ QWidget *widget2 = new QWidget;
+ widget2->setObjectName("Widget 2");
+ QWidget *widget3 = new QWidget;
+ widget3->setObjectName("Widget 3");
+ QWidgetPrivate *priv1 = QWidgetPrivate::get(widget1);
+ QWidgetPrivate *priv2 = QWidgetPrivate::get(widget2);
+ QWidgetPrivate *priv3 = QWidgetPrivate::get(widget3);
+
+ // Verify initialization
+ QVERIFY(!priv1->isInFocusChain());
+ QVERIFY(!priv2->isInFocusChain());
+ QVERIFY(!priv3->isInFocusChain());
+
+ // Verify, that parenting builds a focus chain.
+ QWidget parent;
+ parent.setObjectName("Parent");
+ widget1->setParent(&parent);
+ widget2->setParent(&parent);
+ widget3->setParent(&parent);
+ QVERIFY(priv1->isInFocusChain());
+ QVERIFY(priv2->isInFocusChain());
+ QVERIFY(priv3->isInFocusChain());
+ QWidgetList expected{widget1, widget2, widget3, &parent};
+ QCOMPARE(getFocusChain(widget1, true), expected);
+
+ // Verify, that reparented focus children end up behind parent.
+ widget1->setParent(widget2);
+ priv2->insertIntoFocusChainAfter(widget3);
+ priv2->reparentFocusChildren(QWidgetPrivate::FocusDirection::Next);
+ expected = {widget1, &parent, widget3, widget2};
+ QCOMPARE(getFocusChain(widget1, true), expected);
+ QVERIFY(priv1->isInFocusChain());
+ QVERIFY(priv2->isInFocusChain());
+ QVERIFY(priv3->isInFocusChain());
+
+ // Check removal
+ priv3->removeFromFocusChain(QWidgetPrivate::FocusChainRemovalRule::AssertConsistency);
+ expected.removeOne(widget3);
+ QCOMPARE(getFocusChain(widget1, true), expected);
+ QVERIFY(priv1->isInFocusChain());
+ QVERIFY(priv2->isInFocusChain());
+ QVERIFY(!priv3->isInFocusChain());
+
+ // Check insert
+ priv3->insertIntoFocusChain(QWidgetPrivate::FocusDirection::Previous, widget1);
+ expected = {widget3, widget1, &parent, widget2};
+ QCOMPARE(getFocusChain(widget3, true), expected);
+
+ // Verify, that take doesn't break
+ const QWidgetList taken = QWidgetPrivate::takeFromFocusChain(widget1, widget2);
+ QVERIFY(priv1->isFocusChainConsistent());
+ expected = {widget1, &parent, widget2};
+ QCOMPARE(taken, expected);
+ QVERIFY(priv1->isInFocusChain());
+ QVERIFY(priv2->isInFocusChain());
+ QVERIFY(!priv3->isInFocusChain());
+
+ // Verify insertion of multiple widgets
+ QWidgetPrivate::insertIntoFocusChain(taken, QWidgetPrivate::FocusDirection::Next, widget3);
+ expected = {widget3, widget1, &parent, widget2};
+ QCOMPARE(getFocusChain(widget3, true), expected);
+ QVERIFY(priv1->isInFocusChain());
+ QVERIFY(priv2->isInFocusChain());
+ QVERIFY(priv2->isInFocusChain());
+
+ // Verify broken chain identification
+ // d'tor asserts chain consistency => repair before going out of scope
+ auto guard = qScopeGuard([priv2, widget3]{ priv2->focus_next = widget3; });
+
+ // Nullptr is not allowed
+ priv2->focus_next = nullptr;
+ QVERIFY(!priv1->isFocusChainConsistent());
+
+ // Chain looping back in the middle
+ priv2->focus_next = widget1;
+ QVERIFY(!priv1->isFocusChainConsistent());
+
+ // "last" element pointing to itself
+ priv2->focus_next = widget2;
+ QVERIFY(!priv1->isFocusChainConsistent());
+}
+
void tst_QWidget::defaultTabOrder()
{
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
@@ -1950,7 +2125,6 @@ void tst_QWidget::defaultTabOrder()
container.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
container.show();
container.activateWindow();
- QApplicationPrivate::setActiveWindow(&container);
QVERIFY(QTest::qWaitForWindowActive(&container));
QTRY_VERIFY(firstEdit->hasFocus());
@@ -1986,23 +2160,29 @@ void tst_QWidget::defaultTabOrder()
void tst_QWidget::reverseTabOrder()
{
- if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
+ if (QGuiApplication::platformName().startsWith(QLatin1StringView("wayland"), Qt::CaseInsensitive))
QSKIP("Wayland: This fails. Figure out why.");
const int compositeCount = 2;
Container container;
- container.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
+ container.setObjectName(QLatin1StringView("Container"));
+ container.setWindowTitle(QLatin1StringView(QTest::currentTestFunction()));
Composite* composite[compositeCount];
QLineEdit *firstEdit = new QLineEdit();
+ firstEdit->setObjectName(QLatin1StringView("FirstEdit"));
container.box->addWidget(firstEdit);
+ static constexpr QLatin1StringView comp("Composite-%1");
for (int i = 0; i < compositeCount; i++) {
- composite[i] = new Composite();
+ const QString name = QString(comp).arg(i);
+ composite[i] = new Composite(nullptr, name);
+ composite[i]->setObjectName(name);
container.box->addWidget(composite[i]);
}
QLineEdit *lastEdit = new QLineEdit();
+ lastEdit->setObjectName(QLatin1StringView("LastEdit"));
container.box->addWidget(lastEdit);
// Reverse tab order inside each composite
@@ -2011,7 +2191,6 @@ void tst_QWidget::reverseTabOrder()
container.show();
container.activateWindow();
- QApplicationPrivate::setActiveWindow(&container);
QVERIFY(QTest::qWaitForWindowActive(&container));
QTRY_VERIFY(firstEdit->hasFocus());
@@ -2046,6 +2225,139 @@ void tst_QWidget::reverseTabOrder()
QVERIFY(firstEdit->hasFocus());
}
+void tst_QWidget::tabOrderList()
+{
+ Composite c;
+ QCOMPARE(getFocusChain(&c, true),
+ QList<QWidget *>({&c, c.lineEdit1, c.lineEdit2, c.lineEdit3}));
+ QWidget::setTabOrder({c.lineEdit3, c.lineEdit2, c.lineEdit1});
+ // not starting with 3 like one would maybe expect, but still 3, 2, 1
+ QCOMPARE(getFocusChain(&c, true),
+ QList<QWidget *>({&c, c.lineEdit1, c.lineEdit3, c.lineEdit2}));
+}
+
+void tst_QWidget::tabOrderComboBox_data()
+{
+ QTest::addColumn<const bool>("editableAtBeginning");
+ QTest::addColumn<const QList<int>>("firstTabOrder");
+ QTest::addColumn<const QList<int>>("secondTabOrder");
+
+ QTest::addRow("3 not editable") << false << QList<int>{2, 1, 0} << QList<int>{0, 1, 2};
+ QTest::addRow("4 editable") << true << QList<int>{2, 1, 0, 3} << QList<int>{3, 0, 2, 1};
+}
+
+QWidgetList expectedFocusChain(const QList<QComboBox *> &boxes, const QList<int> &sequence)
+{
+ Q_ASSERT(boxes.count() == sequence.count());
+ QWidgetList widgets;
+ for (int i : sequence) {
+ Q_ASSERT(i >= 0);
+ Q_ASSERT(i < boxes.count());
+ QComboBox *box = boxes.at(i);
+ widgets.append(box);
+ if (box->lineEdit())
+ widgets.append(box->lineEdit());
+ }
+
+ return widgets;
+}
+
+QWidgetList realFocusChain(const QList<QComboBox *> &boxes, const QList<int> &sequence)
+{
+ const QWidgetList all = getFocusChain(boxes.at(sequence.at(0)), true);
+ QWidgetList chain;
+ // Filter everything with NoFocus
+ for (auto *widget : all) {
+ if (widget->focusPolicy() != Qt::NoFocus)
+ chain << widget;
+ }
+ return chain;
+}
+
+void setTabOrder(const QList<QComboBox *> &boxes, const QList<int> &sequence)
+{
+ Q_ASSERT(boxes.count() == sequence.count());
+ QWidget *previous = nullptr;
+ for (int i : sequence) {
+ Q_ASSERT(i >= 0);
+ Q_ASSERT(i < boxes.count());
+ QWidget *box = boxes.at(i);
+ if (!previous) {
+ previous = box;
+ } else {
+ QWidget::setTabOrder(previous, box);
+ previous = box;
+ }
+ }
+}
+
+void tst_QWidget::tabOrderComboBox()
+{
+ QFETCH(const bool, editableAtBeginning);
+ QFETCH(const QList<int>, firstTabOrder);
+ QFETCH(const QList<int>, secondTabOrder);
+ const int count = firstTabOrder.count();
+ Q_ASSERT(count == secondTabOrder.count());
+ Q_ASSERT(count > 1);
+
+ QWidget w;
+ w.setObjectName("MainWidget");
+ QVBoxLayout* layout = new QVBoxLayout();
+ w.setLayout(layout);
+
+ QList<QComboBox *> boxes;
+ for (int i = 0; i < count; ++i) {
+ auto box = new QComboBox;
+ box->setObjectName("ComboBox " + QString::number(i));
+ if (editableAtBeginning) {
+ box->setEditable(true);
+ box->lineEdit()->setObjectName("LineEdit " + QString::number(i));
+ }
+ boxes.append(box);
+ layout->addWidget(box);
+ }
+ layout->addStretch();
+
+#define COMPARE(seq)\
+ setTabOrder(boxes, seq);\
+ QCOMPARE(realFocusChain(boxes, seq), expectedFocusChain(boxes, seq))
+
+ COMPARE(firstTabOrder);
+
+ if (!editableAtBeginning) {
+ for (auto *box : boxes)
+ box->setEditable(box);
+ }
+
+ COMPARE(secondTabOrder);
+
+ // Remove the focus proxy of the first combobox's line edit.
+ QComboBox *box = boxes.at(0);
+ QLineEdit *lineEdit = box->lineEdit();
+ const QWidget *prev = lineEdit->previousInFocusChain();
+ const QWidget *next = lineEdit->nextInFocusChain();
+ const QWidget *proxy = lineEdit->focusProxy();
+ QCOMPARE(proxy, box);
+ lineEdit->setFocusProxy(nullptr);
+ QCOMPARE(lineEdit->focusProxy(), nullptr);
+ QCOMPARE(lineEdit->previousInFocusChain(), prev);
+ QCOMPARE(lineEdit->nextInFocusChain(), next);
+
+ // Remove first item and check chain consistency
+ boxes.removeFirst();
+ delete box;
+
+ // Create new list with 0 removed and other indexes updated
+ QList<int> thirdTabOrder(secondTabOrder);
+ thirdTabOrder.removeIf([](int i){ return i == 0; });
+ for (int &i : thirdTabOrder)
+ --i;
+
+ COMPARE(thirdTabOrder);
+
+#undef COMPARE
+}
+
void tst_QWidget::tabOrderWithProxy()
{
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
@@ -2073,7 +2385,6 @@ void tst_QWidget::tabOrderWithProxy()
container.show();
container.activateWindow();
- QApplicationPrivate::setActiveWindow(&container);
QVERIFY(QTest::qWaitForWindowActive(&container));
QTRY_VERIFY(firstEdit->hasFocus());
@@ -2134,7 +2445,6 @@ void tst_QWidget::tabOrderWithProxyDisabled()
container.show();
container.activateWindow();
- QApplicationPrivate::setActiveWindow(&container);
if (!QTest::qWaitForWindowActive(&container))
QSKIP("Window failed to activate, skipping test");
@@ -2216,7 +2526,6 @@ void tst_QWidget::tabOrderWithCompoundWidgets()
container.show();
container.activateWindow();
- QApplicationPrivate::setActiveWindow(&container);
QVERIFY(QTest::qWaitForWindowActive(&container));
lastEdit->setFocus();
@@ -2267,30 +2576,19 @@ void tst_QWidget::tabOrderWithCompoundWidgets()
QVERIFY(lastEdit->hasFocus());
}
-static QList<QWidget *> getFocusChain(QWidget *start, bool bForward)
-{
- QList<QWidget *> ret;
- QWidget *cur = start;
- do {
- ret += cur;
- auto widgetPrivate = static_cast<QWidgetPrivate *>(qt_widget_private(cur));
- cur = bForward ? widgetPrivate->focus_next : widgetPrivate->focus_prev;
- } while (cur != start);
- return ret;
-}
-
void tst_QWidget::tabOrderWithProxyOutOfOrder()
{
Container container;
container.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
+ container.setObjectName(QLatin1StringView("Container"));
// important to create the widgets with parent so that they are
// added to the focus chain already now, and with the buttonBox
// before the outsideButton.
QWidget buttonBox(&container);
- buttonBox.setObjectName("buttonBox");
+ buttonBox.setObjectName(QLatin1StringView("buttonBox"));
QPushButton outsideButton(&container);
- outsideButton.setObjectName("outsideButton");
+ outsideButton.setObjectName(QLatin1StringView("outsideButton"));
container.box->addWidget(&outsideButton);
container.box->addWidget(&buttonBox);
@@ -2318,7 +2616,6 @@ void tst_QWidget::tabOrderWithProxyOutOfOrder()
container.show();
container.activateWindow();
- QApplicationPrivate::setActiveWindow(&container);
if (!QTest::qWaitForWindowActive(&container))
QSKIP("Window failed to activate, skipping test");
@@ -2340,6 +2637,121 @@ void tst_QWidget::tabOrderWithProxyOutOfOrder()
QCOMPARE(QApplication::focusWidget(), &cancelButton);
}
+static bool isFocusChainConsistent(QWidget *widget)
+{
+ auto forward = getFocusChain(widget, true);
+ auto backward = getFocusChain(widget, false);
+ auto logger = qScopeGuard([=]{
+ qCritical("Focus chain is not consistent!");
+ qWarning() << forward.size() << "forwards: " << forward;
+ qWarning() << backward.size() << "backwards:" << backward;
+ });
+ // both lists start with the same, the widget
+ if (forward.takeFirst() != backward.takeFirst())
+ return false;
+ const qsizetype chainLength = forward.size();
+ if (backward.size() != chainLength)
+ return false;
+ for (qsizetype i = 0; i < chainLength; ++i) {
+ if (forward.at(i) != backward.at(chainLength - i - 1))
+ return false;
+ }
+ logger.dismiss();
+ return true;
+}
+
+/*
+ This tests that we end up with consistent and complete chains when we set
+ the tab order from a widget (the lineEdit) inside a compound (the tabWidget)
+ to the compound, or visa versa. In that case, QWidget::setTabOrder will walk
+ the focus chain to the focus child inside the compound to replace the compound
+ itself when manipulating the tab order. If that last focus child is then
+ however also the lineEdit, then we must not create an inconsistent or
+ incomplete loop.
+
+ The tabWidget is seen as a compound because QTabWidget sets the tab bar as
+ the focus proxy, and it has more widgets inside, like pages, toolbuttons etc.
+*/
+void tst_QWidget::tabOrderWithCompoundWidgetsInflection_data()
+{
+ QTest::addColumn<QByteArrayList>("tabOrder");
+
+ QTest::addRow("forward")
+ << QByteArrayList{"dialog", "tabWidget", "lineEdit", "compound", "okButton", "cancelButton"};
+ QTest::addRow("backward")
+ << QByteArrayList{"dialog", "cancelButton", "okButton", "compound", "lineEdit", "tabWidget"};
+}
+
+void tst_QWidget::tabOrderWithCompoundWidgetsInflection()
+{
+ QFETCH(const QByteArrayList, tabOrder);
+
+ QDialog dialog;
+ dialog.setObjectName("dialog");
+ QTabWidget *tabWidget = new QTabWidget;
+ tabWidget->setObjectName("tabWidget");
+ tabWidget->setFocusPolicy(Qt::TabFocus);
+ QWidget *page = new QWidget;
+ page->setObjectName("page");
+ QLineEdit *lineEdit = new QLineEdit;
+ lineEdit->setObjectName("lineEdit");
+ QWidget *compound = new QWidget;
+ compound->setObjectName("compound");
+ compound->setFocusPolicy(Qt::TabFocus);
+ QPushButton *okButton = new QPushButton("Ok");
+ okButton->setObjectName("okButton");
+ okButton->setFocusPolicy(Qt::TabFocus);
+ QPushButton *cancelButton = new QPushButton("Cancel");
+ cancelButton->setObjectName("cancelButton");
+ cancelButton->setFocusPolicy(Qt::TabFocus);
+
+ QVBoxLayout *pageLayout = new QVBoxLayout;
+ pageLayout->addWidget(lineEdit);
+ page->setLayout(pageLayout);
+ tabWidget->addTab(page, "Tab");
+
+ QHBoxLayout *compoundLayout = new QHBoxLayout;
+ compoundLayout->addStretch();
+ compoundLayout->addWidget(cancelButton);
+ compoundLayout->addWidget(okButton);
+ compound->setFocusProxy(okButton);
+ compound->setLayout(compoundLayout);
+
+ QVBoxLayout *dialogLayout = new QVBoxLayout;
+ dialogLayout->addWidget(tabWidget);
+ dialogLayout->addWidget(compound);
+ dialog.setLayout(dialogLayout);
+
+ QVERIFY(isFocusChainConsistent(&dialog));
+
+ QList<QWidget *> expectedFocusChain;
+ for (qsizetype i = 0; i < tabOrder.size() - 1; ++i) {
+ QWidget *first = dialog.findChild<QWidget *>(tabOrder.at(i));
+ if (!first && tabOrder.at(i) == dialog.objectName())
+ first = &dialog;
+ QVERIFY(first);
+ if (i == 0)
+ expectedFocusChain.append(first);
+ QWidget *second = dialog.findChild<QWidget *>(tabOrder.at(i + 1));
+ QVERIFY(second);
+ expectedFocusChain.append(second);
+ QWidget::setTabOrder(first, second);
+ QVERIFY(isFocusChainConsistent(&dialog));
+ }
+
+ const auto forwardChain = getFocusChain(&dialog, true);
+ auto logger = qScopeGuard([=]{
+ qCritical("Order of widgets in focus chain not matching:");
+ qCritical() << " Actual :" << forwardChain;
+ qCritical() << " Expected:" << expectedFocusChain;
+ });
+ for (qsizetype i = 0; i < expectedFocusChain.size() - 2; ++i) {
+ QCOMPARE_LT(forwardChain.indexOf(expectedFocusChain.at(i)),
+ forwardChain.indexOf(expectedFocusChain.at(i + 1)));
+ }
+ logger.dismiss();
+}
+
void tst_QWidget::tabOrderWithCompoundWidgetsNoFocusPolicy()
{
Container container;
@@ -2361,7 +2773,6 @@ void tst_QWidget::tabOrderWithCompoundWidgetsNoFocusPolicy()
container.show();
container.activateWindow();
- QApplicationPrivate::setActiveWindow(&container);
if (!QTest::qWaitForWindowActive(&container))
QSKIP("Window failed to activate, skipping test");
@@ -2467,7 +2878,6 @@ void tst_QWidget::appFocusWidgetWithFocusProxyLater()
QLineEdit *lineEdit = new QLineEdit(&window);
lineEdit->setFocus();
window.show();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(QApplication::focusWidget(), lineEdit);
@@ -2495,7 +2905,6 @@ void tst_QWidget::appFocusWidgetWhenLosingFocusProxy()
lineEdit->setFocusProxy(lineEditFocusProxy);
lineEdit->setFocus();
window.show();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
QCOMPARE(QApplication::focusWidget(), lineEditFocusProxy);
QVERIFY(lineEdit->hasFocus());
@@ -2522,7 +2931,6 @@ void tst_QWidget::explicitTabOrderWithComplexWidget()
QWidget::setTabOrder(lineEditOne, lineEditTwo);
lineEditOne->setFocus();
window.show();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
QTRY_COMPARE(QApplication::focusWidget(), lineEditOne);
@@ -2551,7 +2959,6 @@ void tst_QWidget::explicitTabOrderWithSpinBox_QTBUG81097()
QWidget::setTabOrder(spinBoxTwo, lineEdit);
spinBoxOne->setFocus();
window.show();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
QTRY_COMPARE(QApplication::focusWidget(), spinBoxOne);
@@ -3179,7 +3586,6 @@ void tst_QWidget::showMinimizedKeepsFocus()
QWidget *child = new QWidget(&window);
child->setFocusPolicy(Qt::StrongFocus);
window.show();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
child->setFocus();
QTRY_COMPARE(window.focusWidget(), child);
@@ -3198,7 +3604,6 @@ void tst_QWidget::showMinimizedKeepsFocus()
QWidget *child = new QWidget(&window);
child->setFocusPolicy(Qt::StrongFocus);
window.show();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
child->setFocus();
QTRY_COMPARE(window.focusWidget(), child);
@@ -3218,7 +3623,6 @@ void tst_QWidget::showMinimizedKeepsFocus()
QWidget *child = new QWidget(&window);
child->setFocusPolicy(Qt::StrongFocus);
window.show();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
child->setFocus();
QTRY_COMPARE(window.focusWidget(), child);
@@ -3239,7 +3643,6 @@ void tst_QWidget::showMinimizedKeepsFocus()
QWidget *child = new QWidget(&window);
child->setFocusPolicy(Qt::StrongFocus);
window.show();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
child->setFocus();
QTRY_COMPARE(window.focusWidget(), child);
@@ -3256,7 +3659,6 @@ void tst_QWidget::showMinimizedKeepsFocus()
QTRY_COMPARE(QApplication::focusWidget(), nullptr);
window.showNormal();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
#ifdef Q_OS_MACOS
if (!macHasAccessToWindowsServer())
@@ -4199,8 +4601,7 @@ void tst_QWidget::restoreVersion1Geometry()
const Qt::WindowStates WindowStateMask = Qt::WindowFullScreen | Qt::WindowMaximized | Qt::WindowMinimized;
QFile f(fileName);
- QVERIFY(f.exists());
- f.open(QIODevice::ReadOnly);
+ QVERIFY(f.open(QIODevice::ReadOnly));
const QByteArray savedGeometry = f.readAll();
QCOMPARE(savedGeometry.size(), 46);
f.close();
@@ -4630,7 +5031,7 @@ private:
/*
Test that widget resizes and moves can be done with minimal repaints when WA_StaticContents
- and WA_OpaquePaintEvent is set. Test is mac-only for now.
+ and WA_OpaquePaintEvent is set.
*/
void tst_QWidget::optimizedResizeMove()
{
@@ -4969,6 +5370,84 @@ void tst_QWidget::createAndDestroy()
QVERIFY(widget.internalWinId());
}
+void tst_QWidget::eventsAndAttributesOnDestroy()
+{
+ // The events and attributes when destroying a widget should
+ // include those of hiding the widget.
+
+ CreateDestroyWidget widget;
+ EventSpy<QWidget> showEventSpy(&widget, QEvent::Show);
+ EventSpy<QWidget> hideEventSpy(&widget, QEvent::Hide);
+
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), false);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(widget.testAttribute(Qt::WA_Mapped), false);
+
+ widget.show();
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), true);
+ QTRY_COMPARE(widget.testAttribute(Qt::WA_Mapped), true);
+ QCOMPARE(showEventSpy.count(), 1);
+ QCOMPARE(hideEventSpy.count(), 0);
+
+ widget.hide();
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(widget.testAttribute(Qt::WA_Mapped), false);
+ QCOMPARE(showEventSpy.count(), 1);
+ QCOMPARE(hideEventSpy.count(), 1);
+
+ widget.show();
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), true);
+ QTRY_COMPARE(widget.testAttribute(Qt::WA_Mapped), true);
+ QCOMPARE(showEventSpy.count(), 2);
+ QCOMPARE(hideEventSpy.count(), 1);
+
+ widget.destroy();
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), false);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(widget.testAttribute(Qt::WA_Mapped), false);
+ QCOMPARE(showEventSpy.count(), 2);
+ QCOMPARE(hideEventSpy.count(), 2);
+
+ const int hideEventsAfterDestroy = hideEventSpy.count();
+
+ widget.create();
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(widget.testAttribute(Qt::WA_Mapped), false);
+ QCOMPARE(showEventSpy.count(), 2);
+ QCOMPARE(hideEventSpy.count(), hideEventsAfterDestroy);
+
+ QWidgetPrivate::get(&widget)->setVisible(true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Created), true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), true);
+ QTRY_COMPARE(widget.testAttribute(Qt::WA_Mapped), true);
+ QCOMPARE(showEventSpy.count(), 3);
+ QCOMPARE(hideEventSpy.count(), hideEventsAfterDestroy);
+
+ // Make sure the destroy that happens when a top level
+ // is moved to being a child does not prevent the child
+ // being shown again.
+
+ QWidget parent;
+ QWidget child;
+ parent.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&parent));
+ child.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&child));
+
+ child.setParent(&parent);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Created), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false);
+
+ child.show();
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Created), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), true);
+ QVERIFY(QTest::qWaitForWindowExposed(&child));
+}
+
void tst_QWidget::winIdChangeEvent()
{
{
@@ -5136,24 +5615,29 @@ void tst_QWidget::closeAndShowWithNativeChild()
QApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
QWidget topLevel;
+ topLevel.setObjectName("TopLevel");
QWidget *nativeChild = new QWidget;
+ nativeChild->setObjectName("NativeChild");
nativeChild->setFixedSize(200, 200);
- QWidget *nativeHiddenChild = new QWidget;
- nativeHiddenChild->setFixedSize(200, 200);
QWidget *normalChild = new QWidget;
+ normalChild->setObjectName("NormalChild");
normalChild->setFixedSize(200, 200);
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(nativeChild);
- layout->addWidget(nativeHiddenChild);
layout->addWidget(normalChild);
topLevel.setLayout(layout);
- nativeHiddenChild->hide();
+ nativeChild->setAttribute(Qt::WA_NativeWindow);
+
+ QCOMPARE(normalChild->testAttribute(Qt::WA_WState_Hidden), false);
+ QCOMPARE(normalChild->testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+
+ QCOMPARE(nativeChild->testAttribute(Qt::WA_WState_Hidden), false);
+ QCOMPARE(nativeChild->testAttribute(Qt::WA_WState_ExplicitShowHide), false);
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
- nativeChild->winId();
const QSize originalSize = topLevel.size();
topLevel.close();
@@ -5578,7 +6062,6 @@ void tst_QWidget::scroll()
updateWidget.reset();
updateWidget.move(m_availableTopLeft);
updateWidget.showNormal();
- QApplicationPrivate::setActiveWindow(&updateWidget);
QVERIFY(QTest::qWaitForWindowActive(&updateWidget));
QVERIFY(updateWidget.numPaintEvents > 0);
@@ -6311,6 +6794,9 @@ void tst_QWidget::moveChild()
void tst_QWidget::showAndMoveChild()
{
+#ifdef ANDROID
+ QSKIP("Fails on Android due to removed grabWindow(): QTBUG-118849");
+#endif
if (m_platform == QStringLiteral("wayland"))
QSKIP("Wayland: This fails. Figure out why.");
QWidget parent(nullptr, Qt::Window | Qt::WindowStaysOnTopHint);
@@ -6328,7 +6814,6 @@ void tst_QWidget::showAndMoveChild()
parent.setGeometry(desktopDimensions);
parent.setPalette(Qt::red);
parent.show();
- QApplicationPrivate::setActiveWindow(&parent);
QVERIFY(QTest::qWaitForWindowActive(&parent));
QWidget child(&parent);
@@ -6759,34 +7244,6 @@ void tst_QWidget::setFocus()
}
}
-template<class T> class EventSpy : public QObject
-{
-public:
- EventSpy(T *widget, QEvent::Type event)
- : m_widget(widget), eventToSpy(event)
- {
- if (m_widget)
- m_widget->installEventFilter(this);
- }
-
- T *widget() const { return m_widget; }
- int count() const { return m_count; }
- void clear() { m_count = 0; }
-
-protected:
- bool eventFilter(QObject *object, QEvent *event) override
- {
- if (event->type() == eventToSpy)
- ++m_count;
- return QObject::eventFilter(object, event);
- }
-
-private:
- T *m_widget;
- const QEvent::Type eventToSpy;
- int m_count = 0;
-};
-
#ifndef QT_NO_CURSOR
void tst_QWidget::setCursor()
{
@@ -7211,7 +7668,6 @@ void tst_QWidget::clean_qt_x11_enforce_cursor()
child->setAttribute(Qt::WA_SetCursor, true);
window.show();
- QApplicationPrivate::setActiveWindow(&window);
QVERIFY(QTest::qWaitForWindowActive(&window));
QTest::qWait(100);
QCursor::setPos(window.geometry().center());
@@ -7588,6 +8044,9 @@ private:
void tst_QWidget::render()
{
+#ifdef Q_OS_ANDROID
+ QSKIP("QTBUG-118984: crashes on Android.");
+#endif
QCalendarWidget source;
source.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
// disable anti-aliasing to eliminate potential differences when subpixel antialiasing
@@ -7680,15 +8139,12 @@ void tst_QWidget::renderTargetOffset()
QCOMPARE(image.pixel(120, 120), QColor(Qt::blue).rgb());
}
-// On Windows the active palette is used instead of the inactive palette even
-// though the widget is invisible. This is probably related to task 178507/168682,
-// but for the renderInvisible test it doesn't matter, we're mostly interested
-// in testing the geometry so just workaround the palette issue for now.
+// On some platforms the active palette is used instead of the inactive palette even
+// though the widget is invisible, but for the renderInvisible test it doesn't matter,
+// as we're mostly interested in testing the geometry, so just workaround the palette
+// issue for now.
static void workaroundPaletteIssue(QWidget *widget)
{
-#ifndef Q_OS_WIN
- return;
-#endif
if (!widget)
return;
@@ -7732,7 +8188,7 @@ void tst_QWidget::renderInvisible()
// Create normal reference image.
const QSize calendarSize = calendar->size();
- QImage referenceImage(calendarSize, QImage::Format_ARGB32);
+ QImage referenceImage(calendarSize, QImage::Format_ARGB32_Premultiplied);
calendar->render(&referenceImage);
#ifdef RENDER_DEBUG
referenceImage.save("referenceImage.png");
@@ -7743,7 +8199,7 @@ void tst_QWidget::renderInvisible()
const QSize calendarSizeResized = calendar->size() + QSize(50, 50);
calendar->resize(calendarSizeResized);
QTest::qWait(30);
- QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32);
+ QImage referenceImageResized(calendarSizeResized, QImage::Format_ARGB32_Premultiplied);
calendar->render(&referenceImageResized);
#ifdef RENDER_DEBUG
referenceImageResized.save("referenceImageResized.png");
@@ -7756,7 +8212,7 @@ void tst_QWidget::renderInvisible()
workaroundPaletteIssue(calendar.data());
{ // Make sure we get the same image when the calendar is explicitly hidden.
- QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
+ QImage testImage(calendarSizeResized, QImage::Format_ARGB32_Premultiplied);
calendar->render(&testImage);
#ifdef RENDER_DEBUG
testImage.save("explicitlyHiddenCalendarResized.png");
@@ -7772,7 +8228,7 @@ void tst_QWidget::renderInvisible()
workaroundPaletteIssue(calendar.data());
{ // Never been visible, created or laid out.
- QImage testImage(calendarSize, QImage::Format_ARGB32);
+ QImage testImage(calendarSize, QImage::Format_ARGB32_Premultiplied);
calendar->render(&testImage);
#ifdef RENDER_DEBUG
testImage.save("neverBeenVisibleCreatedOrLaidOut.png");
@@ -7784,7 +8240,7 @@ void tst_QWidget::renderInvisible()
QTest::qWait(30);
{ // Calendar explicitly hidden.
- QImage testImage(calendarSize, QImage::Format_ARGB32);
+ QImage testImage(calendarSize, QImage::Format_ARGB32_Premultiplied);
calendar->render(&testImage);
#ifdef RENDER_DEBUG
testImage.save("explicitlyHiddenCalendar.png");
@@ -7798,7 +8254,7 @@ void tst_QWidget::renderInvisible()
navigationBar->hide();
{ // Check that the navigation bar isn't drawn when rendering the entire calendar.
- QImage testImage(calendarSize, QImage::Format_ARGB32);
+ QImage testImage(calendarSize, QImage::Format_ARGB32_Premultiplied);
calendar->render(&testImage);
#ifdef RENDER_DEBUG
testImage.save("calendarWithoutNavigationBar.png");
@@ -7807,7 +8263,7 @@ void tst_QWidget::renderInvisible()
}
{ // Make sure the navigation bar renders correctly even though it's hidden.
- QImage testImage(navigationBar->size(), QImage::Format_ARGB32);
+ QImage testImage(navigationBar->size(), QImage::Format_ARGB32_Premultiplied);
navigationBar->render(&testImage);
#ifdef RENDER_DEBUG
testImage.save("explicitlyHiddenNavigationBar.png");
@@ -7821,7 +8277,7 @@ void tst_QWidget::renderInvisible()
{ // Render next month button.
// Fill test image with correct background color.
- QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32);
+ QImage testImage(nextMonthButton->size(), QImage::Format_ARGB32_Premultiplied);
navigationBar->render(&testImage, QPoint(), QRegion(), QWidget::RenderFlags());
#ifdef RENDER_DEBUG
testImage.save("nextMonthButtonBackground.png");
@@ -7859,7 +8315,7 @@ void tst_QWidget::renderInvisible()
QCoreApplication::processEvents();
{ // Make sure we get an image equal to the resized reference image.
- QImage testImage(calendarSizeResized, QImage::Format_ARGB32);
+ QImage testImage(calendarSizeResized, QImage::Format_ARGB32_Premultiplied);
calendar->render(&testImage);
#ifdef RENDER_DEBUG
testImage.save("calendarResized.png");
@@ -7871,7 +8327,7 @@ void tst_QWidget::renderInvisible()
QCalendarWidget calendar;
const QSize calendarSize = calendar.sizeHint();
- QImage image(2 * calendarSize, QImage::Format_ARGB32);
+ QImage image(2 * calendarSize, QImage::Format_ARGB32_Premultiplied);
image.fill(QColor(Qt::red).rgb());
calendar.render(&image);
@@ -9365,7 +9821,6 @@ void tst_QWidget::dumpObjectTree()
}
QTestPrivate::androidCompatibleShow(&w);
- QApplicationPrivate::setActiveWindow(&w);
QVERIFY(QTest::qWaitForWindowActive(&w));
{
@@ -10446,7 +10901,6 @@ void tst_QWidget::enterLeaveOnWindowShowHide()
if (!QTest::qWaitFor([&]{ return widget.geometry().contains(QCursor::pos()); }))
QSKIP("We can't move the cursor");
widget.show();
- QApplicationPrivate::setActiveWindow(&widget);
QVERIFY(QTest::qWaitForWindowActive(&widget));
++expectedEnter;
@@ -11266,7 +11720,6 @@ void tst_QWidget::imEnabledNotImplemented()
topLevel.show();
QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
- QApplicationPrivate::setActiveWindow(&topLevel);
QVERIFY(QTest::qWaitForWindowActive(&topLevel));
// A plain widget should return false for ImEnabled
@@ -11283,11 +11736,12 @@ void tst_QWidget::imEnabledNotImplemented()
QVERIFY(imEnabled.isValid());
QVERIFY(imEnabled.toBool());
- // ...even if it's read-only
+ // ImEnabled should be false when a lineedit is read-only since
+ // ImEnabled indicates the widget accepts input method _input_.
edit.setReadOnly(true);
imEnabled = QApplication::inputMethod()->queryFocusObject(Qt::ImEnabled, QVariant());
QVERIFY(imEnabled.isValid());
- QVERIFY(imEnabled.toBool());
+ QVERIFY(!imEnabled.toBool());
}
#ifdef QT_BUILD_INTERNAL
@@ -11646,7 +12100,6 @@ void tst_QWidget::grabMouse()
layout->addWidget(grabber);
centerOnScreen(&w);
w.show();
- QApplicationPrivate::setActiveWindow(&w);
QVERIFY(QTest::qWaitForWindowActive(&w));
QStringList expectedLog;
@@ -11683,7 +12136,6 @@ void tst_QWidget::grabKeyboard()
layout->addWidget(nonGrabber);
centerOnScreen(&w);
w.show();
- QApplicationPrivate::setActiveWindow(&w);
QVERIFY(QTest::qWaitForWindowActive(&w));
nonGrabber->setFocus();
grabber->grabKeyboard();
@@ -13054,6 +13506,7 @@ void tst_QWidget::setParentChangesFocus()
QApplicationPrivate::setActiveWindow(secondary.get());
QVERIFY(QTest::qWaitForWindowActive(secondary.get()));
}
+ QVERIFY(QTest::qWaitFor([]{ return QApplication::focusWidget(); }));
QCOMPARE(QApplication::focusWidget()->objectName(), focusWidget);
}
@@ -13141,5 +13594,402 @@ void tst_QWidget::showFullscreenAndroid()
}
#endif // Q_OS_ANDROID
+void tst_QWidget::setVisibleDuringDestruction()
+{
+ CreateDestroyWidget widget;
+ widget.create();
+ QVERIFY(widget.windowHandle());
+
+ QSignalSpy signalSpy(widget.windowHandle(), &QWindow::visibleChanged);
+ EventSpy<QWindow> showEventSpy(widget.windowHandle(), QEvent::Show);
+ widget.show();
+ QTRY_COMPARE(showEventSpy.count(), 1);
+ QTRY_COMPARE(signalSpy.count(), 1);
+
+ EventSpy<QWindow> hideEventSpy(widget.windowHandle(), QEvent::Hide);
+ widget.hide();
+ QTRY_COMPARE(hideEventSpy.count(), 1);
+ QTRY_COMPARE(signalSpy.count(), 2);
+
+ widget.show();
+ QTRY_COMPARE(showEventSpy.count(), 2);
+ QTRY_COMPARE(signalSpy.count(), 3);
+
+ widget.destroy();
+ QTRY_COMPARE(hideEventSpy.count(), 2);
+ QTRY_COMPARE(signalSpy.count(), 4);
+}
+
+void tst_QWidget::explicitShowHide()
+{
+ {
+ QWidget parent;
+ parent.setObjectName("Parent");
+ QWidget child(&parent);
+ child.setObjectName("Child");
+
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+
+ parent.show();
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), true);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+
+ // Fix up earlier expected failure
+ child.setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+
+ parent.hide();
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), true);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+ }
+
+ {
+ // Test what happens when a child is reparented after showing it
+
+ QWidget parent;
+ parent.setObjectName("Parent");
+ QWidget child;
+ child.setObjectName("Child");
+
+ child.show();
+ QCOMPARE(child.isVisible(), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+
+ child.setParent(&parent);
+ // As documented, a widget becomes invisible as part of changing
+ // its parent, even if it was previously visible. The user must call
+ // show() to make the widget visible again.
+ QCOMPARE(child.isVisible(), false);
+
+ // However, the widget does not end up with Qt::WA_WState_Hidden,
+ // as QWidget::setParent treats it as a child, which normally will
+ // not get Qt::WA_WState_Hidden out of the box.
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+
+ // For some reason we reset WA_WState_ExplicitShowHide, and it's
+ // not clear whether this is correct or not See QWidget::setParent()
+ // for a comment with more details.
+ QEXPECT_FAIL("", "We reset WA_WState_ExplicitShowHide on widget re-parent", Continue);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), true);
+
+ // The fact that the child doesn't have Qt::WA_WState_Hidden means
+ // it's sufficient to show the parent widget. We don't need to
+ // explicitly show the child.
+ parent.show();
+ QCOMPARE(child.isVisible(), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+ }
+
+ {
+ QWidget parent;
+ parent.setObjectName("Parent");
+ QWidget child(&parent);
+ child.setObjectName("Child");
+
+ parent.show();
+
+ // If a non-native child ends up being closed, we will hide the
+ // widget, but do so via QWidget::hide(), which marks the widget
+ // as explicitly hidden.
+
+ child.setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ QCOMPARE(child.close(), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), true);
+
+ child.show();
+ child.setAttribute(Qt::WA_NativeWindow);
+ child.setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ QCOMPARE(child.close(), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), true);
+
+ child.show();
+ child.setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ QCOMPARE(child.windowHandle()->close(), false); // Can't close non-top level QWindows
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+
+ // If we end up in QWidgetPrivate::handleClose via QWidgetWindow::closeEvent,
+ // either through QWindow::close(), or via QWSI::handleCloseEvent, we'll still
+ // do the explicit hide.
+
+ child.show();
+ child.setAttribute(Qt::WA_WState_ExplicitShowHide, false);
+ QCOMPARE(QWindowSystemInterface::handleCloseEvent<QWindowSystemInterface::SynchronousDelivery>(
+ child.windowHandle()), true);
+ QEXPECT_FAIL("", "Closing a native child via QWSI is treated as an explicit hide", Continue);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), true);
+ }
+
+ {
+ QWidget widget;
+ widget.show();
+ widget.hide();
+
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_ExplicitShowHide), true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Hidden), true);
+
+ // The widget is now explicitly hidden. Showing it again, via QWindow,
+ // should make the widget visible, and it should not stay hidden, as
+ // that's an invalid state for a widget.
+
+ widget.windowHandle()->setVisible(true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Visible), true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_ExplicitShowHide), true);
+ QCOMPARE(widget.testAttribute(Qt::WA_WState_Hidden), false);
+ }
+}
+
+/*!
+ Verify that we deliver DragEnter/Leave events symmetrically, even if the
+ widget entered didn't accept the DragEnter event.
+*/
+void tst_QWidget::dragEnterLeaveSymmetry()
+{
+ QWidget widget;
+ widget.setAcceptDrops(true);
+ QLineEdit lineEdit;
+ QLabel label("Hello world");
+ label.setAcceptDrops(true);
+
+ struct EventFilter : QObject
+ {
+ bool eventFilter(QObject *receiver, QEvent *event) override
+ {
+ switch (event->type()) {
+ case QEvent::DragEnter:
+ case QEvent::DragLeave:
+ receivers[event->type()] << receiver;
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+ QMap<QEvent::Type, QList<QObject *>> receivers;
+
+ void clear() { receivers.clear(); }
+ bool hasEntered(QWidget *widget) const
+ {
+ return receivers.value(QEvent::DragEnter).contains(widget);
+ }
+ bool hasLeft(QWidget *widget) const
+ {
+ return receivers.value(QEvent::DragLeave).contains(widget);
+ }
+ } filter;
+
+ widget.installEventFilter(&filter);
+ lineEdit.installEventFilter(&filter);
+ label.installEventFilter(&filter);
+
+ QVBoxLayout vbox;
+ vbox.setContentsMargins(10, 10, 10, 10);
+ vbox.addWidget(&lineEdit);
+ vbox.addWidget(&label);
+ widget.setLayout(&vbox);
+
+ widget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&widget));
+
+ QMimeData data;
+ data.setColorData(QVariant::fromValue(Qt::red));
+ QWindowSystemInterface::handleDrag(widget.windowHandle(), &data, QPoint(1, 1),
+ Qt::ActionMask, Qt::LeftButton, {});
+ QVERIFY(filter.hasEntered(&widget));
+ QVERIFY(!filter.hasEntered(&lineEdit));
+ QVERIFY(!filter.hasEntered(&label));
+ QVERIFY(widget.underMouse());
+ QVERIFY(!lineEdit.underMouse());
+ filter.clear();
+
+ QWindowSystemInterface::handleDrag(widget.windowHandle(), &data, lineEdit.geometry().center(),
+ Qt::ActionMask, Qt::LeftButton, {});
+ // DragEnter propagates as the lineEdit doesn't want it, so the widget
+ // sees both a Leave and an Enter event
+ QVERIFY(filter.hasLeft(&widget));
+ QVERIFY(filter.hasEntered(&widget));
+ QVERIFY(filter.hasEntered(&widget));
+ // both have the UnderMouse attribute set
+ QVERIFY(lineEdit.underMouse());
+ QVERIFY(widget.underMouse());
+
+ // The lineEdit didn't accept the DragEnter, but it should still has to
+ // get the DragLeave so that UnderMouse is cleared; the widget gets both
+ // Leave and Enter through propagation.
+ QWindowSystemInterface::handleDrag(widget.windowHandle(), &data, label.geometry().center(),
+ Qt::ActionMask, Qt::LeftButton, {});
+ QVERIFY(filter.hasLeft(&lineEdit));
+ QVERIFY(filter.hasLeft(&widget));
+ QVERIFY(filter.hasEntered(&label));
+ QVERIFY(filter.hasEntered(&widget));
+
+ QVERIFY(!lineEdit.underMouse());
+ QVERIFY(label.underMouse());
+ QVERIFY(widget.underMouse());
+}
+
+void tst_QWidget::reparentWindowHandles_data()
+{
+ QTest::addColumn<int>("stage");
+ QTest::addRow("reparent child") << 1;
+ QTest::addRow("top level to child") << 2;
+ QTest::addRow("transient parent") << 3;
+ QTest::addRow("window container") << 4;
+}
+
+void tst_QWidget::reparentWindowHandles()
+{
+ const bool nativeSiblingsOriginal = qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
+ auto nativeSiblingGuard = qScopeGuard([&]{
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, nativeSiblingsOriginal);
+ });
+
+ QFETCH(int, stage);
+
+ switch (stage) {
+ case 1: {
+ // Reparent child widget
+
+ QWidget topLevel;
+ topLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(topLevel.windowHandle());
+ QPointer<QWidget> child = new QWidget(&topLevel);
+ child->setAttribute(Qt::WA_DontCreateNativeAncestors);
+ child->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(child->windowHandle());
+
+ QWidget anotherTopLevel;
+ anotherTopLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(anotherTopLevel.windowHandle());
+ QPointer<QWidget> intermediate = new QWidget(&anotherTopLevel);
+ QPointer<QWidget> leaf = new QWidget(intermediate);
+ leaf->setAttribute(Qt::WA_DontCreateNativeAncestors);
+ leaf->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(leaf->windowHandle());
+ QVERIFY(!intermediate->windowHandle());
+
+ // Reparenting a native widget should reparent the QWindow
+ child->setParent(leaf);
+ QCOMPARE(child->windowHandle()->parent(), leaf->windowHandle());
+ QCOMPARE(child->windowHandle()->transientParent(), nullptr);
+ QVERIFY(!intermediate->windowHandle());
+
+ // So should reparenting a non-native widget with native children
+ intermediate->setParent(&topLevel);
+ QVERIFY(!intermediate->windowHandle());
+ QCOMPARE(leaf->windowHandle()->parent(), topLevel.windowHandle());
+ QCOMPARE(leaf->windowHandle()->transientParent(), nullptr);
+ QCOMPARE(child->windowHandle()->parent(), leaf->windowHandle());
+ QCOMPARE(child->windowHandle()->transientParent(), nullptr);
+ }
+ break;
+ case 2: {
+ // Top level to child
+
+ QWidget topLevel;
+ topLevel.setAttribute(Qt::WA_NativeWindow);
+
+ // A regular top level loses its nativeness
+ QPointer<QWidget> regularToplevel = new QWidget;
+ regularToplevel->show();
+ QVERIFY(QTest::qWaitForWindowExposed(regularToplevel));
+ QVERIFY(regularToplevel->windowHandle());
+ regularToplevel->setParent(&topLevel);
+ QVERIFY(!regularToplevel->windowHandle());
+
+ // A regular top level loses its nativeness
+ QPointer<QWidget> regularToplevelWithNativeChildren = new QWidget;
+ QPointer<QWidget> nativeChild = new QWidget(regularToplevelWithNativeChildren);
+ nativeChild->setAttribute(Qt::WA_DontCreateNativeAncestors);
+ nativeChild->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(nativeChild->windowHandle());
+ regularToplevelWithNativeChildren->show();
+ QVERIFY(QTest::qWaitForWindowExposed(regularToplevelWithNativeChildren));
+ QVERIFY(regularToplevelWithNativeChildren->windowHandle());
+ regularToplevelWithNativeChildren->setParent(&topLevel);
+ QVERIFY(!regularToplevelWithNativeChildren->windowHandle());
+ // But the native child does not
+ QVERIFY(nativeChild->windowHandle());
+ QCOMPARE(nativeChild->windowHandle()->parent(), topLevel.windowHandle());
+
+ // An explicitly native top level keeps its nativeness, and the window handle moves
+ QPointer<QWidget> nativeTopLevel = new QWidget;
+ nativeTopLevel->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(nativeTopLevel->windowHandle());
+ nativeTopLevel->setParent(&topLevel);
+ QVERIFY(nativeTopLevel->windowHandle());
+ QCOMPARE(nativeTopLevel->windowHandle()->parent(), topLevel.windowHandle());
+ }
+ break;
+ case 3: {
+ // Transient parent
+
+ QWidget topLevel;
+ topLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(topLevel.windowHandle());
+ QPointer<QWidget> child = new QWidget(&topLevel);
+ child->setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(child->windowHandle());
+
+ QWidget anotherTopLevel;
+ anotherTopLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(anotherTopLevel.windowHandle());
+
+ // Make transient child of top level
+ anotherTopLevel.setParent(&topLevel, Qt::Window);
+ QCOMPARE(anotherTopLevel.windowHandle()->parent(), nullptr);
+ QCOMPARE(anotherTopLevel.windowHandle()->transientParent(), topLevel.windowHandle());
+
+ // Make transient child of child
+ anotherTopLevel.setParent(child, Qt::Window);
+ QCOMPARE(anotherTopLevel.windowHandle()->parent(), nullptr);
+ QCOMPARE(anotherTopLevel.windowHandle()->transientParent(), topLevel.windowHandle());
+ }
+ break;
+ case 4: {
+ // Window container
+
+ QWidget topLevel;
+ topLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(topLevel.windowHandle());
+
+ QPointer<QWidget> child = new QWidget(&topLevel);
+ QVERIFY(!child->windowHandle());
+
+ QWindow *window = new QWindow;
+ QWidget *container = QWidget::createWindowContainer(window);
+ container->setParent(child);
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+ QCOMPARE(window->parent(), topLevel.windowHandle());
+
+ QWidget anotherTopLevel;
+ anotherTopLevel.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(anotherTopLevel.windowHandle());
+
+ child->setParent(&anotherTopLevel);
+ QCOMPARE(window->parent(), anotherTopLevel.windowHandle());
+ }
+ break;
+ default:
+ Q_UNREACHABLE();
+ }
+}
+
QTEST_MAIN(tst_QWidget)
#include "tst_qwidget.moc"
diff --git a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
index 0e1a2d58dc..77853a3e8c 100644
--- a/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
+++ b/tests/auto/widgets/kernel/qwidget_window/BLACKLIST
@@ -1,7 +1,3 @@
-[tst_resize_count]
-# QTBUG-66345
-opensuse-42.3
-ubuntu-16.04
# QTBUG-87412
[tst_move_show]
android
diff --git a/tests/auto/widgets/kernel/qwidget_window/CMakeLists.txt b/tests/auto/widgets/kernel/qwidget_window/CMakeLists.txt
index 49525918f1..af60c92cbf 100644
--- a/tests/auto/widgets/kernel/qwidget_window/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qwidget_window/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qwidget_window.pro.
-
#####################################################################
## tst_qwidget_window Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qwidget_window LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qwidget_window
SOURCES
tst_qwidget_window.cpp
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
index 3211edbb33..e771737ae0 100644
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -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
#include <QTest>
@@ -53,6 +53,7 @@ public:
tst_QWidget_window();
public slots:
+ void init();
void initTestCase();
void cleanupTestCase();
void cleanup();
@@ -110,8 +111,13 @@ private slots:
void mouseMoveWithPopup_data();
void mouseMoveWithPopup();
+ void showHideWindowHandle_data();
+ void showHideWindowHandle();
+
void resetFocusObjectOnDestruction();
+ void cleanupOnDestruction();
+
private:
QSize m_testWidgetSize;
const int m_fuzz;
@@ -129,6 +135,11 @@ void tst_QWidget_window::initTestCase()
{
}
+void tst_QWidget_window::init()
+{
+ QTest::failOnWarning(QRegularExpression(".*No such slot.*"));
+}
+
void tst_QWidget_window::cleanupTestCase()
{
}
@@ -680,7 +691,6 @@ void tst_QWidget_window::tst_dnd()
dndTestWidget.show();
QVERIFY(QTest::qWaitForWindowExposed(&dndTestWidget));
- QApplicationPrivate::setActiveWindow(&dndTestWidget);
QVERIFY(QTest::qWaitForWindowActive(&dndTestWidget));
QMimeData mimeData;
@@ -1630,6 +1640,154 @@ void tst_QWidget_window::mouseMoveWithPopup()
QCOMPARE(topLevel.popup->mouseReleaseCount, 1);
}
+struct ShowHideEntry {
+ QEvent::Type action;
+ Qt::WindowType target;
+ using List = QList<ShowHideEntry>;
+};
+
+void tst_QWidget_window::showHideWindowHandle_data()
+{
+ QTest::addColumn<ShowHideEntry::List>("entries");
+
+ QTest::addRow("show/hide widget") << ShowHideEntry::List{
+ { QEvent::Show, Qt::Widget }, { QEvent::Hide, Qt::Widget }
+ };
+ QTest::addRow("show/hide window") << ShowHideEntry::List{
+ { QEvent::Show, Qt::Window }, { QEvent::Hide, Qt::Window }
+ };
+ QTest::addRow("show widget, hide window") << ShowHideEntry::List{
+ { QEvent::Show, Qt::Widget }, { QEvent::Hide, Qt::Window }
+ };
+ QTest::addRow("show window, hide widget") << ShowHideEntry::List{
+ { QEvent::Show, Qt::Window }, { QEvent::Hide, Qt::Widget }
+ };
+ QTest::addRow("show/hide widget, then show window, hide widget") << ShowHideEntry::List{
+ { QEvent::Show, Qt::Widget }, { QEvent::Hide, Qt::Widget },
+ { QEvent::Show, Qt::Window }, { QEvent::Hide, Qt::Widget }
+ };
+ QTest::addRow("show widget, close widget, show widget") << ShowHideEntry::List{
+ { QEvent::Show, Qt::Widget }, { QEvent::Close, Qt::Widget }, { QEvent::Show, Qt::Widget }
+ };
+ QTest::addRow("show widget, close widget, show window") << ShowHideEntry::List{
+ { QEvent::Show, Qt::Widget }, { QEvent::Close, Qt::Widget }, { QEvent::Show, Qt::Window }
+ };
+ QTest::addRow("show widget, close window, show widget") << ShowHideEntry::List{
+ { QEvent::Show, Qt::Widget }, { QEvent::Close, Qt::Window }, { QEvent::Show, Qt::Widget }
+ };
+ QTest::addRow("show widget, close window, show window") << ShowHideEntry::List{
+ { QEvent::Show, Qt::Widget }, { QEvent::Close, Qt::Window }, { QEvent::Show, Qt::Window }
+ };
+}
+
+void tst_QWidget_window::showHideWindowHandle()
+{
+ QWidget parent;
+ parent.setObjectName("Parent");
+ QCOMPARE(parent.isVisible(), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true);
+
+ QWidget child;
+ child.setObjectName("Child");
+ QCOMPARE(child.isVisible(), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), true);
+
+ child.setParent(&parent);
+ QCOMPARE(child.isVisible(), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+
+ QFETCH(QList<ShowHideEntry>, entries);
+ for (const auto entry : entries) {
+
+ if (entry.action == QEvent::Show) {
+ if (entry.target == Qt::Window && !parent.windowHandle()) {
+ parent.setAttribute(Qt::WA_NativeWindow);
+ QVERIFY(parent.windowHandle());
+
+ QCOMPARE(parent.isVisible(), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true);
+ }
+
+ bool wasExplicitShowHide = parent.testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ if (entry.target == Qt::Widget)
+ parent.show();
+ else
+ parent.windowHandle()->show();
+
+ QVERIFY(QTest::qWaitForWindowActive(&parent));
+
+ QCOMPARE(parent.isVisible(), true);
+ QVERIFY(parent.windowHandle());
+ QCOMPARE(parent.windowHandle()->isVisible(), true);
+
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), true);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide),
+ entry.target == Qt::Widget || wasExplicitShowHide);
+
+ QCOMPARE(child.isVisible(), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), true);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+
+ } else if (entry.action == QEvent::Hide) {
+
+ bool wasExplicitShowHide = parent.testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ if (entry.target == Qt::Widget)
+ parent.hide();
+ else
+ parent.windowHandle()->hide();
+
+ QCOMPARE(parent.isVisible(), false);
+ QVERIFY(parent.windowHandle());
+ QCOMPARE(parent.windowHandle()->isVisible(), false);
+
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide),
+ entry.target == Qt::Widget || wasExplicitShowHide);
+
+ QCOMPARE(child.isVisible(), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+
+ } else if (entry.action == QEvent::Close) {
+
+ bool wasExplicitShowHide = parent.testAttribute(Qt::WA_WState_ExplicitShowHide);
+
+ if (entry.target == Qt::Widget)
+ parent.close();
+ else
+ parent.windowHandle()->close();
+
+ QCOMPARE(parent.isVisible(), false);
+ QVERIFY(parent.windowHandle());
+ QCOMPARE(parent.windowHandle()->isVisible(), false);
+
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_Hidden), true);
+ QCOMPARE(parent.testAttribute(Qt::WA_WState_ExplicitShowHide),
+ entry.target == Qt::Widget || wasExplicitShowHide);
+
+ QCOMPARE(child.isVisible(), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_ExplicitShowHide), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Visible), false);
+ QCOMPARE(child.testAttribute(Qt::WA_WState_Hidden), false);
+ }
+ }
+}
+
void tst_QWidget_window::resetFocusObjectOnDestruction()
{
if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation))
@@ -1666,5 +1824,30 @@ void tst_QWidget_window::resetFocusObjectOnDestruction()
QCOMPARE(focusObjectChangedSpy.last().last().value<QObject*>(), nullptr);
}
+class CreateDestroyWidget : public QWidget
+{
+public:
+ using QWidget::create;
+ using QWidget::destroy;
+};
+
+void tst_QWidget_window::cleanupOnDestruction()
+{
+ CreateDestroyWidget widget;
+ QWidget child(&widget);
+
+ QWidget grandChild(&child);
+ // Ensure there's not a 1:1 native window hierarhcy that we could
+ // recurse during QWidget::destroy(), triggering the issue that
+ // we were failing to clean up when not destroyed via QWidget.
+ grandChild.setAttribute(Qt::WA_DontCreateNativeAncestors);
+ grandChild.winId();
+
+ widget.destroy();
+ widget.create();
+
+ widget.show();
+}
+
QTEST_MAIN(tst_QWidget_window)
#include "tst_qwidget_window.moc"
diff --git a/tests/auto/widgets/kernel/qwidgetaction/CMakeLists.txt b/tests/auto/widgets/kernel/qwidgetaction/CMakeLists.txt
index b784433833..fb5409464d 100644
--- a/tests/auto/widgets/kernel/qwidgetaction/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qwidgetaction/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qwidgetaction.pro.
-
#####################################################################
## tst_qwidgetaction Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qwidgetaction LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qwidgetaction
SOURCES
tst_qwidgetaction.cpp
diff --git a/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp b/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp
index 0e0f84dbb1..a06e072b71 100644
--- a/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp
+++ b/tests/auto/widgets/kernel/qwidgetaction/tst_qwidgetaction.cpp
@@ -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
#include <QTest>
diff --git a/tests/auto/widgets/kernel/qwidgetmetatype/CMakeLists.txt b/tests/auto/widgets/kernel/qwidgetmetatype/CMakeLists.txt
index 546923e0ac..431a584a60 100644
--- a/tests/auto/widgets/kernel/qwidgetmetatype/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qwidgetmetatype/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qwidgetmetatype.pro.
-
#####################################################################
## tst_qwidgetmetatype Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qwidgetmetatype LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qwidgetmetatype
SOURCES
tst_qwidgetmetatype.cpp
diff --git a/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp b/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp
index da417b377e..885c26a128 100644
--- a/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp
+++ b/tests/auto/widgets/kernel/qwidgetmetatype/tst_qwidgetmetatype.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2012 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.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
#include <QTest>
diff --git a/tests/auto/widgets/kernel/qwidgetrepaintmanager/CMakeLists.txt b/tests/auto/widgets/kernel/qwidgetrepaintmanager/CMakeLists.txt
index 117f805cdb..ae91af064c 100644
--- a/tests/auto/widgets/kernel/qwidgetrepaintmanager/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qwidgetrepaintmanager/CMakeLists.txt
@@ -1,6 +1,12 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qwidgetrepaintmanager LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qwidgetrepaintmanager
SOURCES
tst_qwidgetrepaintmanager.cpp
diff --git a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp
index f53d5aeb05..9059a9262e 100644
--- a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp
+++ b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp
@@ -1,5 +1,5 @@
// Copyright (C) 2021 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>
@@ -11,7 +11,9 @@
#include <private/qhighdpiscaling_p.h>
#include <private/qwidget_p.h>
#include <private/qwidgetrepaintmanager_p.h>
+#include <qpa/qplatformintegration.h>
#include <qpa/qplatformbackingstore.h>
+#include <private/qguiapplication_p.h>
//#define MANUAL_DEBUG
@@ -75,8 +77,11 @@ public:
const auto type = event->type();
if (type == QEvent::WindowActivate || type == QEvent::WindowDeactivate)
return true;
+ if (type == QEvent::UpdateRequest)
+ ++updateRequests;
return QWidget::event(event);
}
+ int updateRequests = 0;
protected:
void paintEvent(QPaintEvent *event) override
@@ -254,6 +259,8 @@ private slots:
void opaqueChildren();
void staticContents();
void scroll();
+ void paintOnScreenUpdates();
+
#if defined(QT_BUILD_INTERNAL)
void scrollWithOverlap();
void overlappedRegion();
@@ -429,16 +436,26 @@ void tst_QWidgetRepaintManager::opaqueChildren()
*/
void tst_QWidgetRepaintManager::staticContents()
{
+ const auto *integration = QGuiApplicationPrivate::platformIntegration();
+ if (!integration->hasCapability(QPlatformIntegration::BackingStoreStaticContents))
+ QSKIP("Platform does not support static backingstore content");
+
TestWidget widget;
widget.setAttribute(Qt::WA_StaticContents);
widget.initialShow();
- const QSize oldSize = widget.size();
+ // Trigger resize via QWindow (similar to QWSI code path)
+ QVERIFY(widget.windowHandle());
+ QSize oldSize = widget.size();
+ widget.windowHandle()->resize(widget.width(), widget.height() + 10);
+ QVERIFY(widget.waitForPainted());
+ QCOMPARE(widget.takePaintedRegions(), QRegion(0, oldSize.width(), widget.width(), 10));
+ // Trigger resize via QWidget
+ oldSize = widget.size();
widget.resize(widget.width() + 10, widget.height());
-
QVERIFY(widget.waitForPainted());
- QEXPECT_FAIL("", "This should just repaint the newly exposed region", Continue);
+ QEXPECT_FAIL("", "QWidgetPrivate::setGeometry_sys wrongly triggers full update", Continue);
QCOMPARE(widget.takePaintedRegions(), QRegion(oldSize.width(), 0, 10, widget.height()));
}
@@ -479,6 +496,90 @@ void tst_QWidgetRepaintManager::scroll()
QCOMPARE(widget.takePaintedRegions(), QRegion());
}
+class PaintOnScreenWidget : public TestWidget
+{
+public:
+ using TestWidget::TestWidget;
+
+ // Explicit override to prevent noPaintOnScreen on Windows
+ QPaintEngine *paintEngine() const override
+ {
+ return nullptr;
+ }
+};
+
+void tst_QWidgetRepaintManager::paintOnScreenUpdates()
+{
+ {
+ TestWidget topLevel;
+ topLevel.setObjectName("TopLevel");
+ topLevel.resize(500, 500);
+ TestWidget renderToTextureWidget(&topLevel);
+ renderToTextureWidget.setObjectName("RenderToTexture");
+ renderToTextureWidget.setGeometry(0, 0, 200, 200);
+ QWidgetPrivate::get(&renderToTextureWidget)->setRenderToTexture();
+
+ PaintOnScreenWidget paintOnScreenWidget(&topLevel);
+ paintOnScreenWidget.setObjectName("PaintOnScreen");
+ paintOnScreenWidget.setGeometry(200, 200, 300, 300);
+
+ topLevel.initialShow();
+
+ // Updating before toggling WA_PaintOnScreen should work fine
+ paintOnScreenWidget.update();
+ paintOnScreenWidget.waitForPainted();
+ QVERIFY(paintOnScreenWidget.waitForPainted());
+
+#ifdef Q_OS_ANDROID
+ QEXPECT_FAIL("", "This test fails on Android", Abort);
+#endif
+ QCOMPARE(paintOnScreenWidget.takePaintedRegions(), paintOnScreenWidget.rect());
+
+ renderToTextureWidget.update();
+ QVERIFY(renderToTextureWidget.waitForPainted());
+ QCOMPARE(renderToTextureWidget.takePaintedRegions(), renderToTextureWidget.rect());
+
+ // Then toggle WA_PaintOnScreen
+ paintOnScreenWidget.setAttribute(Qt::WA_PaintOnScreen);
+
+ // The render-to-texture widget updates fine
+ renderToTextureWidget.update();
+ QVERIFY(renderToTextureWidget.waitForPainted());
+ QCOMPARE(renderToTextureWidget.takePaintedRegions(), renderToTextureWidget.rect());
+
+ // Updating the paint-on-screen texture widget will not result
+ // in a paint event, but should result in an update request.
+ paintOnScreenWidget.updateRequests = 0;
+ paintOnScreenWidget.update();
+ QVERIFY(QTest::qWaitFor([&]{ return paintOnScreenWidget.updateRequests > 0; }));
+
+ // And should not prevent the render-to-texture widget from receiving updates
+ renderToTextureWidget.update();
+ QVERIFY(renderToTextureWidget.waitForPainted());
+ QCOMPARE(renderToTextureWidget.takePaintedRegions(), renderToTextureWidget.rect());
+ }
+
+ {
+ TestWidget paintOnScreenTopLevel;
+ paintOnScreenTopLevel.setObjectName("PaintOnScreenTopLevel");
+ paintOnScreenTopLevel.setAttribute(Qt::WA_PaintOnScreen);
+
+ paintOnScreenTopLevel.initialShow();
+
+ paintOnScreenTopLevel.updateRequests = 0;
+ paintOnScreenTopLevel.update();
+ QVERIFY(QTest::qWaitFor([&]{ return paintOnScreenTopLevel.updateRequests > 0; }));
+
+ // Turn off paint on screen and make it a render-to-texture widget.
+ // This will lead us into a QWidgetRepaintManager::markDirty() code
+ // path that checks updateRequestSent, which is still set from the
+ // update above since paint-on-screen handling doesn't reset it.
+ paintOnScreenTopLevel.setAttribute(Qt::WA_PaintOnScreen, false);
+ QWidgetPrivate::get(&paintOnScreenTopLevel)->setRenderToTexture();
+ paintOnScreenTopLevel.update();
+ QVERIFY(QTest::qWaitFor([&]{ return paintOnScreenTopLevel.updateRequests > 1; }));
+ }
+}
#if defined(QT_BUILD_INTERNAL)
@@ -499,6 +600,8 @@ void tst_QWidgetRepaintManager::scrollWithOverlap()
: QWidget(parent, Qt::WindowStaysOnTopHint)
{
m_scrollArea = new QScrollArea(this);
+ m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+ m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
QWidget *w = new QWidget;
w->setPalette(QPalette(Qt::gray));
w->setAutoFillBackground(true);
diff --git a/tests/auto/widgets/kernel/qwidgetsvariant/CMakeLists.txt b/tests/auto/widgets/kernel/qwidgetsvariant/CMakeLists.txt
index f09c7c66a0..bb3c1e2ad6 100644
--- a/tests/auto/widgets/kernel/qwidgetsvariant/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qwidgetsvariant/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qwidgetsvariant.pro.
-
#####################################################################
## tst_qwidgetsvariant Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qwidgetsvariant LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qwidgetsvariant
SOURCES
tst_qwidgetsvariant.cpp
diff --git a/tests/auto/widgets/kernel/qwidgetsvariant/tst_qwidgetsvariant.cpp b/tests/auto/widgets/kernel/qwidgetsvariant/tst_qwidgetsvariant.cpp
index bb30f3fd43..0a03fb9e1d 100644
--- a/tests/auto/widgets/kernel/qwidgetsvariant/tst_qwidgetsvariant.cpp
+++ b/tests/auto/widgets/kernel/qwidgetsvariant/tst_qwidgetsvariant.cpp
@@ -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
#include <QTest>
diff --git a/tests/auto/widgets/kernel/qwindowcontainer/CMakeLists.txt b/tests/auto/widgets/kernel/qwindowcontainer/CMakeLists.txt
index cc5b74e936..787505972f 100644
--- a/tests/auto/widgets/kernel/qwindowcontainer/CMakeLists.txt
+++ b/tests/auto/widgets/kernel/qwindowcontainer/CMakeLists.txt
@@ -1,12 +1,16 @@
# Copyright (C) 2022 The Qt Company Ltd.
# SPDX-License-Identifier: BSD-3-Clause
-# Generated from qwindowcontainer.pro.
-
#####################################################################
## tst_qwindowcontainer Test:
#####################################################################
+if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+ cmake_minimum_required(VERSION 3.16)
+ project(tst_qwindowcontainer LANGUAGES CXX)
+ find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST)
+endif()
+
qt_internal_add_test(tst_qwindowcontainer
SOURCES
tst_qwindowcontainer.cpp
diff --git a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp
index 19c9606d79..52aaf094b4 100644
--- a/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp
+++ b/tests/auto/widgets/kernel/qwindowcontainer/tst_qwindowcontainer.cpp
@@ -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
#include <QTest>
@@ -7,12 +7,14 @@
#include <qapplication.h>
#include <qwindow.h>
#include <qwidget.h>
+#include <qlineedit.h>
#include <qdockwidget.h>
#include <qmainwindow.h>
#include <qscreen.h>
#include <qscopedpointer.h>
#include <qevent.h>
+#include <qboxlayout.h>
class Window : public QWindow
@@ -46,6 +48,7 @@ public:
private slots:
void testShow();
void testPositionAndSize();
+ void testSizeHints();
void testExposeObscure();
void testOwnership();
void testBehindTheScenesDeletion();
@@ -57,6 +60,8 @@ private slots:
void testDockWidget();
void testNativeContainerParent();
void testPlatformSurfaceEvent();
+ void embedWidgetWindow();
+ void testFocus();
void cleanup();
private:
@@ -108,7 +113,29 @@ void tst_QWindowContainer::testPositionAndSize()
QCOMPARE(window->height(), container->height());
}
+void tst_QWindowContainer::testSizeHints()
+{
+ QScopedPointer<QWidget> tlw(new QWidget);
+ QWindow *window = new QWindow();
+ window->setMinimumSize(QSize(200, 200));
+ window->setGeometry(m_availableGeometry.x() + 300, m_availableGeometry.y() + 400, 500, 600);
+
+ QScopedPointer<QWidget> container(QWidget::createWindowContainer(window));
+ container->setWindowTitle(QTest::currentTestFunction());
+ QVBoxLayout *vbox = new QVBoxLayout(tlw.data());
+ vbox->addWidget(container.data());
+ vbox->setContentsMargins(0, 0, 0, 0);
+
+ // Size hints should work regardless of visibility
+ QCOMPARE(container->minimumSizeHint(), window->minimumSize());
+ QCOMPARE(vbox->minimumSize(), window->minimumSize());
+
+ // Respect dynamic updates
+ window->setMinimumSize(QSize(210, 210));
+ QCOMPARE(container->minimumSizeHint(), window->minimumSize());
+ QCOMPARE(vbox->minimumSize(), window->minimumSize());
+}
void tst_QWindowContainer::testExposeObscure()
{
@@ -410,6 +437,99 @@ void tst_QWindowContainer::testPlatformSurfaceEvent()
QVERIFY(ok);
}
+void tst_QWindowContainer::embedWidgetWindow()
+{
+ {
+ QWidget parent;
+ QWidget *widget = new QWidget;
+ widget->show();
+ QVERIFY(QTest::qWaitForWindowExposed(widget));
+ QVERIFY(widget->windowHandle());
+ QPointer<QWindow> widgetWindow = widget->windowHandle();
+ auto *container = QWidget::createWindowContainer(widgetWindow, &parent);
+ QCOMPARE(container, widget);
+ QCOMPARE(widget->parent(), &parent);
+ delete widget;
+ QTRY_VERIFY(widgetWindow.isNull());
+ }
+
+ QPointer<QWidget> widget = new QWidget;
+ QPointer<QWindow> widgetWindow;
+ {
+ QWidget parent;
+ widget->show();
+ QVERIFY(QTest::qWaitForWindowExposed(widget));
+ QVERIFY(widget->windowHandle());
+ widgetWindow = widget->windowHandle();
+ auto *container = QWidget::createWindowContainer(widgetWindow, &parent);
+ QCOMPARE(container, widget);
+ QCOMPARE(widget->parent(), &parent);
+ }
+ QTRY_VERIFY(widget.isNull());
+ QTRY_VERIFY(widgetWindow.isNull());
+
+}
+
+void tst_QWindowContainer::testFocus()
+{
+ QWidget root;
+ root.setGeometry(m_availableGeometry);
+
+ QLineEdit *lineEdit = new QLineEdit(&root);
+ lineEdit->setGeometry(0, 0, m_availableGeometry.width() * 0.1, 17);
+ lineEdit->setFocusPolicy(Qt::FocusPolicy::StrongFocus);
+
+ QWindow *embedded = new QWindow();
+ QWidget *container = QWidget::createWindowContainer(embedded, &root);
+ container->setGeometry(0, lineEdit->height() + 10, m_availableGeometry.width() * 0.2, m_availableGeometry.height() - (lineEdit->height() + 10));
+ container->setFocusPolicy(Qt::StrongFocus);
+
+ root.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&root));
+ lineEdit->setFocus();
+ QTRY_VERIFY(lineEdit->hasFocus());
+ QCOMPARE(QGuiApplication::focusWindow(), root.windowHandle());
+ QCOMPARE(QApplication::focusWidget(), lineEdit);
+
+ // embedded window gets focused because of mouse click
+ QPoint embeddedCenter = container->rect().center();
+ QTest::mousePress(root.windowHandle(), Qt::LeftButton, {}, embeddedCenter);
+ QVERIFY(QTest::qWaitForWindowFocused(embedded));
+ QVERIFY(container->hasFocus());
+ QCOMPARE(QGuiApplication::focusWindow(), embedded);
+ QCOMPARE(QApplication::focusWidget(), container);
+ QVERIFY(!lineEdit->hasFocus());
+
+ QTest::mouseClick(lineEdit, Qt::LeftButton, {});
+ QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle()));
+ QCOMPARE(QGuiApplication::focusWindow(), root.windowHandle());
+ QCOMPARE(QApplication::focusWidget(), lineEdit);
+ QVERIFY(lineEdit->hasFocus());
+
+ // embedded window gets focused because of Tab key event
+ QTest::keyClick(root.windowHandle(), Qt::Key_Tab);
+ QVERIFY(QTest::qWaitForWindowFocused(embedded));
+ QVERIFY(container->hasFocus());
+ QCOMPARE(QGuiApplication::focusWindow(), embedded);
+ QCOMPARE(QApplication::focusWidget(), container);
+ QVERIFY(!lineEdit->hasFocus());
+ // A key tab event sent to the root window should cause
+ // the nextInFocusChain of the window container to get focused
+ QTest::keyClick(root.windowHandle(), Qt::Key_Tab);
+ QVERIFY(QTest::qWaitForWindowFocused(root.windowHandle()));
+ QCOMPARE(QGuiApplication::focusWindow(), root.windowHandle());
+ QCOMPARE(QApplication::focusWidget(), lineEdit);
+ QVERIFY(lineEdit->hasFocus());
+
+ // embedded window gets focused programmatically
+ embedded->requestActivate();
+ QVERIFY(QTest::qWaitForWindowFocused(embedded));
+ QVERIFY(container->hasFocus());
+ QCOMPARE(QGuiApplication::focusWindow(), embedded);
+ QCOMPARE(QApplication::focusWidget(), container);
+ QVERIFY(!lineEdit->hasFocus());
+}
+
QTEST_MAIN(tst_QWindowContainer)
#include "tst_qwindowcontainer.moc"