diff options
Diffstat (limited to 'tests/auto/gui/kernel')
133 files changed, 4124 insertions, 2368 deletions
diff --git a/tests/auto/gui/kernel/.prev_CMakeLists.txt b/tests/auto/gui/kernel/.prev_CMakeLists.txt deleted file mode 100644 index 33c8b35391..0000000000 --- a/tests/auto/gui/kernel/.prev_CMakeLists.txt +++ /dev/null @@ -1,50 +0,0 @@ -# Generated from kernel.pro. - -if(QT_FEATURE_action) - add_subdirectory(qaction) - add_subdirectory(qactiongroup) -endif() -add_subdirectory(qbackingstore) -add_subdirectory(qcursor) -add_subdirectory(qdrag) -add_subdirectory(qevent) -add_subdirectory(qfileopenevent) -add_subdirectory(qguieventdispatcher) -add_subdirectory(qguitimer) -add_subdirectory(qinputdevice) -add_subdirectory(qinputmethod) -add_subdirectory(qkeyevent) -add_subdirectory(qmouseevent) -add_subdirectory(qpalette) -add_subdirectory(qscreen) -add_subdirectory(qsurfaceformat) -add_subdirectory(qwindow) -add_subdirectory(qguiapplication) -add_subdirectory(qpixelformat) -add_subdirectory(qrasterwindow) -add_subdirectory(qaddpostroutine) -if(NOT ANDROID AND NOT UIKIT) - add_subdirectory(qclipboard) -endif() -if(TARGET Qt::Network) - add_subdirectory(qguieventloop) -endif() -if(QT_FEATURE_shortcut) - add_subdirectory(qguimetatype) - add_subdirectory(qguivariant) - add_subdirectory(qkeysequence) - add_subdirectory(qshortcut) -endif() -if(QT_FEATURE_highdpiscaling) - add_subdirectory(qhighdpiscaling) -endif() -if(TARGET Qt::Widgets) - add_subdirectory(qmouseevent_modal) - add_subdirectory(qtouchevent) -endif() -if(QT_FEATURE_opengl) - add_subdirectory(qopenglwindow) -endif() -if(TARGET Qt::Network AND WIN32) - add_subdirectory(noqteventloop) -endif() diff --git a/tests/auto/gui/kernel/CMakeLists.txt b/tests/auto/gui/kernel/CMakeLists.txt index 690a679833..9acd817610 100644 --- a/tests/auto/gui/kernel/CMakeLists.txt +++ b/tests/auto/gui/kernel/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from kernel.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause if(QT_FEATURE_action) add_subdirectory(qaction) @@ -9,8 +10,12 @@ add_subdirectory(qcursor) add_subdirectory(qdrag) add_subdirectory(qevent) add_subdirectory(qfileopenevent) +add_subdirectory(qguichronotimer) add_subdirectory(qguieventdispatcher) add_subdirectory(qguitimer) +if(NOT ANDROID AND NOT WASM) + add_subdirectory(qhighdpi) +endif() add_subdirectory(qinputdevice) add_subdirectory(qinputmethod) add_subdirectory(qkeyevent) @@ -19,11 +24,13 @@ add_subdirectory(qpalette) add_subdirectory(qscreen) add_subdirectory(qsurfaceformat) add_subdirectory(qwindow) -add_subdirectory(qguiapplication) +if(QT_FEATURE_private_tests) + add_subdirectory(qguiapplication) +endif() add_subdirectory(qpixelformat) add_subdirectory(qrasterwindow) add_subdirectory(qaddpostroutine) -if(NOT ANDROID AND NOT UIKIT) +if(NOT UIKIT) add_subdirectory(qclipboard) endif() if(TARGET Qt::Network) @@ -35,20 +42,12 @@ if(QT_FEATURE_shortcut) add_subdirectory(qkeysequence) add_subdirectory(qshortcut) endif() -if(QT_FEATURE_highdpiscaling) - add_subdirectory(qhighdpiscaling) -endif() if(TARGET Qt::Widgets) add_subdirectory(qmouseevent_modal) add_subdirectory(qtouchevent) endif() if(QT_FEATURE_opengl) - # special case begin - # QTBUG-85364 - if(NOT LINUX) - add_subdirectory(qopenglwindow) - endif() - # special case end + add_subdirectory(qopenglwindow) endif() if(TARGET Qt::Network AND WIN32) add_subdirectory(noqteventloop) diff --git a/tests/auto/gui/kernel/kernel.pro b/tests/auto/gui/kernel/kernel.pro deleted file mode 100644 index c11c0ad26b..0000000000 --- a/tests/auto/gui/kernel/kernel.pro +++ /dev/null @@ -1,58 +0,0 @@ -TEMPLATE=subdirs -SUBDIRS=\ - qaction \ - qactiongroup \ - qbackingstore \ - qclipboard \ - qcursor \ - qdrag \ - qevent \ - qfileopenevent \ - qguieventdispatcher \ - qguieventloop \ - qguimetatype \ - qguitimer \ - qguivariant \ - qhighdpiscaling \ - qinputdevice \ - qinputmethod \ - qkeyevent \ - qkeysequence \ - qmouseevent \ - qmouseevent_modal \ - qpalette \ - qscreen \ - qshortcut \ - qsurfaceformat \ - qtouchevent \ - qwindow \ - qguiapplication \ - qpixelformat \ - qopenglwindow \ - qrasterwindow \ - qaddpostroutine - -win32:qtHaveModule(network): SUBDIRS += noqteventloop - -!qtConfig(shortcut): SUBDIRS -= \ - qkeysequence \ - qshortcut \ - qguimetatype \ - qguivariant - -!qtHaveModule(widgets): SUBDIRS -= \ - qmouseevent_modal \ - qtouchevent - -!qtHaveModule(network): SUBDIRS -= \ - qguieventloop - -!qtConfig(action): SUBDIRS -= \ - qaction \ - qactiongroup - -!qtConfig(highdpiscaling): SUBDIRS -= qhighdpiscaling - -!qtConfig(opengl): SUBDIRS -= qopenglwindow - -android|uikit: SUBDIRS -= qclipboard diff --git a/tests/auto/gui/kernel/noqteventloop/CMakeLists.txt b/tests/auto/gui/kernel/noqteventloop/CMakeLists.txt index 262b2ad2f2..e9d3d96af9 100644 --- a/tests/auto/gui/kernel/noqteventloop/CMakeLists.txt +++ b/tests/auto/gui/kernel/noqteventloop/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from noqteventloop.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_noqteventloop Test: ##################################################################### -qt_add_test(tst_noqteventloop +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_noqteventloop LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_noqteventloop SOURCES tst_noqteventloop.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate @@ -17,7 +24,7 @@ qt_add_test(tst_noqteventloop ## Scopes: ##################################################################### -qt_extend_target(tst_noqteventloop CONDITION QT_FEATURE_dynamicgl AND WIN32 - PUBLIC_LIBRARIES +qt_internal_extend_target(tst_noqteventloop CONDITION QT_FEATURE_dynamicgl AND WIN32 + LIBRARIES user32 ) diff --git a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro deleted file mode 100644 index 7394c6b6ac..0000000000 --- a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG += testcase -TARGET = tst_noqteventloop - -QT += core-private network gui-private testlib - -SOURCES += tst_noqteventloop.cpp - -qtConfig(dynamicgl):win32: QMAKE_USE += user32 diff --git a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp index 3e19764618..65fe4a83ed 100644 --- a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp +++ b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp @@ -1,40 +1,18 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> #include <QEvent> +#include <QtTest/QSignalSpy> #include <QtCore/qthread.h> #include <QtGui/qguiapplication.h> #include <QtGui/qpainter.h> #include <QtGui/qrasterwindow.h> #include <QtNetwork/qtcpserver.h> #include <QtNetwork/qtcpsocket.h> +#include <QtNetwork/qlocalserver.h> +#include <QtNetwork/qlocalsocket.h> #include <QtCore/qelapsedtimer.h> #include <QtCore/qtimer.h> #include <QtCore/qwineventnotifier.h> @@ -51,6 +29,7 @@ class tst_NoQtEventLoop : public QObject private slots: void consumeMouseEvents(); void consumeSocketEvents(); + void consumeLocalSocketEvents(); void consumeWinEvents_data(); void consumeWinEvents(); void deliverEventsInLivelock(); @@ -152,7 +131,8 @@ public: } - void run() { + void run() override + { struct ScopedCleanup { /* This is in order to ensure that the window is hidden when returning from run(), @@ -318,6 +298,44 @@ void tst_NoQtEventLoop::consumeSocketEvents() QVERIFY(server.hasPendingConnections()); } +void tst_NoQtEventLoop::consumeLocalSocketEvents() +{ + int argc = 1; + char *argv[] = { const_cast<char *>("test"), 0 }; + QGuiApplication app(argc, argv); + QLocalServer server; + QLocalSocket client; + QSignalSpy readyReadSpy(&client, &QIODevice::readyRead); + + QVERIFY(server.listen("consumeLocalSocketEvents")); + client.connectToServer("consumeLocalSocketEvents"); + QVERIFY(client.waitForConnected(200)); + QVERIFY(server.waitForNewConnection(200)); + QLocalSocket *clientSocket = server.nextPendingConnection(); + QVERIFY(clientSocket); + QSignalSpy bytesWrittenSpy(clientSocket, &QIODevice::bytesWritten); + server.close(); + + bool timeExpired = false; + QTimer::singleShot(3000, Qt::CoarseTimer, [&timeExpired]() { + timeExpired = true; + }); + QVERIFY(clientSocket->putChar(0)); + + // Exec own message loop + MSG msg; + while (::GetMessage(&msg, NULL, 0, 0)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + + if (timeExpired || readyReadSpy.count() != 0) + break; + } + QVERIFY(!timeExpired); + QCOMPARE(bytesWrittenSpy.count(), 1); + QCOMPARE(readyReadSpy.count(), 1); +} + void tst_NoQtEventLoop::consumeWinEvents_data() { QTest::addColumn<bool>("peeking"); diff --git a/tests/auto/gui/kernel/qaction/CMakeLists.txt b/tests/auto/gui/kernel/qaction/CMakeLists.txt index 70065156ca..8f70a36c61 100644 --- a/tests/auto/gui/kernel/qaction/CMakeLists.txt +++ b/tests/auto/gui/kernel/qaction/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qaction.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qaction_kernel Test: ##################################################################### -qt_add_test(tst_qaction_kernel +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qaction_kernel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qaction_kernel SOURCES tst_qaction.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/gui/kernel/qaction/qaction.pro b/tests/auto/gui/kernel/qaction/qaction.pro deleted file mode 100644 index 83e8296e68..0000000000 --- a/tests/auto/gui/kernel/qaction/qaction.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qaction_kernel -QT += gui-private core-private testlib -SOURCES += tst_qaction.cpp diff --git a/tests/auto/gui/kernel/qaction/tst_qaction.cpp b/tests/auto/gui/kernel/qaction/tst_qaction.cpp index 277e86d1be..4a4d1a75c8 100644 --- a/tests/auto/gui/kernel/qaction/tst_qaction.cpp +++ b/tests/auto/gui/kernel/qaction/tst_qaction.cpp @@ -1,32 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtTest/QtTest> +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> +#include <QSignalSpy> +#include <QFont> #include <qguiapplication.h> #include <qevent.h> @@ -232,11 +209,11 @@ void tst_QAction::setToolTip() QFETCH(QStringList, values); QFETCH(QStringList, expectedToolTips); - QCOMPARE(properties.count(), values.count()); - QCOMPARE(properties.count(), expectedToolTips.count()); + QCOMPARE(properties.size(), values.size()); + QCOMPARE(properties.size(), expectedToolTips.size()); QAction action(nullptr); - for (int i = 0; i < properties.count(); ++i) { + for (int i = 0; i < properties.size(); ++i) { const auto property = properties.at(i); const auto value = values.at(i); const auto expectedToolTip = expectedToolTips.at(i); @@ -295,19 +272,19 @@ void tst_QAction::task229128TriggeredSignalWithoutActiongroup() // test without a group const QScopedPointer<QAction> actionWithoutGroup(new QAction("Test", nullptr)); QSignalSpy spyWithoutGroup(actionWithoutGroup.data(), QOverload<bool>::of(&QAction::triggered)); - QCOMPARE(spyWithoutGroup.count(), 0); + QCOMPARE(spyWithoutGroup.size(), 0); actionWithoutGroup->trigger(); // signal should be emitted - QCOMPARE(spyWithoutGroup.count(), 1); + QCOMPARE(spyWithoutGroup.size(), 1); // it is now a checkable checked action actionWithoutGroup->setCheckable(true); actionWithoutGroup->setChecked(true); spyWithoutGroup.clear(); - QCOMPARE(spyWithoutGroup.count(), 0); + QCOMPARE(spyWithoutGroup.size(), 0); actionWithoutGroup->trigger(); // signal should be emitted - QCOMPARE(spyWithoutGroup.count(), 1); + QCOMPARE(spyWithoutGroup.size(), 1); } void tst_QAction::setData() // QTBUG-62006 @@ -315,14 +292,14 @@ void tst_QAction::setData() // QTBUG-62006 QAction act(nullptr); QSignalSpy spy(&act, &QAction::changed); QCOMPARE(act.data(), QVariant()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); act.setData(QVariant()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); act.setData(-1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); act.setData(-1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QAction::setEnabledSetVisible() @@ -331,22 +308,22 @@ void tst_QAction::setEnabledSetVisible() QSignalSpy spy(&action, &QAction::enabledChanged); QVERIFY(action.isEnabled()); QVERIFY(action.isVisible()); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); action.setVisible(false); QVERIFY(!action.isEnabled()); QVERIFY(!action.isVisible()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); action.setEnabled(false); QVERIFY(!action.isEnabled()); QVERIFY(!action.isVisible()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); action.setVisible(true); QVERIFY(!action.isEnabled()); QVERIFY(action.isVisible()); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); action.resetEnabled(); QVERIFY(action.isEnabled()); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); } void tst_QAction::setCheckabledSetChecked() @@ -357,37 +334,37 @@ void tst_QAction::setCheckabledSetChecked() QSignalSpy checkableSpy(&action, &QAction::checkableChanged); QVERIFY(!action.isCheckable()); QVERIFY(!action.isChecked()); - QCOMPARE(changedSpy.count(), 0); - QCOMPARE(checkedSpy.count(), 0); - QCOMPARE(checkableSpy.count(), 0); + QCOMPARE(changedSpy.size(), 0); + QCOMPARE(checkedSpy.size(), 0); + QCOMPARE(checkableSpy.size(), 0); action.setCheckable(true); QVERIFY(action.isCheckable()); QVERIFY(!action.isChecked()); - QCOMPARE(changedSpy.count(), 1); - QCOMPARE(checkedSpy.count(), 0); - QCOMPARE(checkableSpy.count(), 1); + QCOMPARE(changedSpy.size(), 1); + QCOMPARE(checkedSpy.size(), 0); + QCOMPARE(checkableSpy.size(), 1); action.setChecked(true); QVERIFY(action.isCheckable()); QVERIFY(action.isChecked()); - QCOMPARE(changedSpy.count(), 2); - QCOMPARE(checkedSpy.count(), 1); - QCOMPARE(checkableSpy.count(), 1); + QCOMPARE(changedSpy.size(), 2); + QCOMPARE(checkedSpy.size(), 1); + QCOMPARE(checkableSpy.size(), 1); action.setCheckable(false); QVERIFY(!action.isCheckable()); QVERIFY(!action.isChecked()); - QCOMPARE(changedSpy.count(), 3); - QCOMPARE(checkedSpy.count(), 2); - QCOMPARE(checkableSpy.count(), 2); + QCOMPARE(changedSpy.size(), 3); + QCOMPARE(checkedSpy.size(), 2); + QCOMPARE(checkableSpy.size(), 2); action.setCheckable(true); QVERIFY(action.isCheckable()); QVERIFY(action.isChecked()); - QCOMPARE(changedSpy.count(), 4); - QCOMPARE(checkedSpy.count(), 3); - QCOMPARE(checkableSpy.count(), 3); + QCOMPARE(changedSpy.size(), 4); + QCOMPARE(checkedSpy.size(), 3); + QCOMPARE(checkableSpy.size(), 3); } QTEST_MAIN(tst_QAction) diff --git a/tests/auto/gui/kernel/qactiongroup/CMakeLists.txt b/tests/auto/gui/kernel/qactiongroup/CMakeLists.txt index e313aebec5..360a20cc95 100644 --- a/tests/auto/gui/kernel/qactiongroup/CMakeLists.txt +++ b/tests/auto/gui/kernel/qactiongroup/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qactiongroup.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qactiongroup_kernel Test: ##################################################################### -qt_add_test(tst_qactiongroup_kernel +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qactiongroup_kernel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qactiongroup_kernel SOURCES tst_qactiongroup.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qactiongroup/qactiongroup.pro b/tests/auto/gui/kernel/qactiongroup/qactiongroup.pro deleted file mode 100644 index a60109c63e..0000000000 --- a/tests/auto/gui/kernel/qactiongroup/qactiongroup.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qactiongroup_kernel -QT += testlib -SOURCES += tst_qactiongroup.cpp diff --git a/tests/auto/gui/kernel/qactiongroup/tst_qactiongroup.cpp b/tests/auto/gui/kernel/qactiongroup/tst_qactiongroup.cpp index 52720ab7ff..a9e331e111 100644 --- a/tests/auto/gui/kernel/qactiongroup/tst_qactiongroup.cpp +++ b/tests/auto/gui/kernel/qactiongroup/tst_qactiongroup.cpp @@ -1,32 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtTest/QtTest> +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> #include <qaction.h> #include <qactiongroup.h> diff --git a/tests/auto/gui/kernel/qaddpostroutine/CMakeLists.txt b/tests/auto/gui/kernel/qaddpostroutine/CMakeLists.txt index 4af9ebedd5..46a0475521 100644 --- a/tests/auto/gui/kernel/qaddpostroutine/CMakeLists.txt +++ b/tests/auto/gui/kernel/qaddpostroutine/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qaddpostroutine.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qaddpostroutine Test: ##################################################################### -qt_add_test(tst_qaddpostroutine +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qaddpostroutine LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qaddpostroutine SOURCES tst_qaddpostroutine.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qaddpostroutine/qaddpostroutine.pro b/tests/auto/gui/kernel/qaddpostroutine/qaddpostroutine.pro deleted file mode 100644 index e67720b5d5..0000000000 --- a/tests/auto/gui/kernel/qaddpostroutine/qaddpostroutine.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase -TARGET = tst_qaddpostroutine - -QT += testlib - -SOURCES += tst_qaddpostroutine.cpp - diff --git a/tests/auto/gui/kernel/qaddpostroutine/tst_qaddpostroutine.cpp b/tests/auto/gui/kernel/qaddpostroutine/tst_qaddpostroutine.cpp index 500543d2e1..c5cc0a9b20 100644 --- a/tests/auto/gui/kernel/qaddpostroutine/tst_qaddpostroutine.cpp +++ b/tests/auto/gui/kernel/qaddpostroutine/tst_qaddpostroutine.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include <QtTest/QtTest> +#include <QTest> #include <QTimer> static bool done = false; diff --git a/tests/auto/gui/kernel/qbackingstore/CMakeLists.txt b/tests/auto/gui/kernel/qbackingstore/CMakeLists.txt index 55d53545bb..811da8bb53 100644 --- a/tests/auto/gui/kernel/qbackingstore/CMakeLists.txt +++ b/tests/auto/gui/kernel/qbackingstore/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qbackingstore.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qbackingstore Test: ##################################################################### -qt_add_test(tst_qbackingstore +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qbackingstore LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qbackingstore SOURCES tst_qbackingstore.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro b/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro deleted file mode 100644 index 211be4c1c0..0000000000 --- a/tests/auto/gui/kernel/qbackingstore/qbackingstore.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase -TARGET = tst_qbackingstore - -QT += core-private gui-private testlib - -SOURCES += tst_qbackingstore.cpp diff --git a/tests/auto/gui/kernel/qbackingstore/tst_qbackingstore.cpp b/tests/auto/gui/kernel/qbackingstore/tst_qbackingstore.cpp index b2dc8ee035..a830d14be8 100644 --- a/tests/auto/gui/kernel/qbackingstore/tst_qbackingstore.cpp +++ b/tests/auto/gui/kernel/qbackingstore/tst_qbackingstore.cpp @@ -1,36 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qwindow.h> #include <qbackingstore.h> +#include <qpa/qplatformbackingstore.h> +#include <qpa/qplatformintegration.h> +#include <private/qguiapplication_p.h> #include <qpainter.h> -#include <QtTest/QtTest> +#include <QTest> #include <QEvent> @@ -42,9 +20,221 @@ class tst_QBackingStore : public QObject Q_OBJECT private slots: + + void initTestCase_data(); + void init(); + + void resize(); + void paint(); + + void scrollRectInImage_data(); + void scrollRectInImage(); + + void scroll(); void flush(); + + void staticContents(); }; +void tst_QBackingStore::initTestCase_data() +{ + QTest::addColumn<QSurfaceFormat::SwapBehavior>("swapBehavior"); + + QTest::newRow("single-buffer") << QSurfaceFormat::SingleBuffer; + QTest::newRow("double-buffer") << QSurfaceFormat::DoubleBuffer; +} + +void tst_QBackingStore::init() +{ + QFETCH_GLOBAL(QSurfaceFormat::SwapBehavior, swapBehavior); + + QSurfaceFormat defaultFormat = QSurfaceFormat::defaultFormat(); + defaultFormat.setSwapBehavior(swapBehavior); + QSurfaceFormat::setDefaultFormat(defaultFormat); +} + +void tst_QBackingStore::resize() +{ + QWindow window; + window.create(); + + QBackingStore backingStore(&window); + + QRect rect(0, 0, 100, 100); + backingStore.resize(rect.size()); + QCOMPARE(backingStore.size(), rect.size()); + + // The paint device should reflect the requested + // size, taking the window's DPR into account. + backingStore.beginPaint(rect); + auto paintDevice = backingStore.paintDevice(); + QCOMPARE(paintDevice->devicePixelRatio(), window.devicePixelRatio()); + QCOMPARE(QSize(paintDevice->width(), paintDevice->height()), + rect.size() * window.devicePixelRatio()); + backingStore.endPaint(); + + // So should the platform backingstore when accessed as an QImage + QImage image = backingStore.handle()->toImage(); + if (!image.isNull()) // toImage might not be implemented + QCOMPARE(image.size(), rect.size() * window.devicePixelRatio()); +} + +void tst_QBackingStore::paint() +{ + QWindow window; + window.create(); + + // The resize() test verifies that the backingstore image + // has a size that takes the window's DPR into account. + auto dpr = window.devicePixelRatio(); + + QBackingStore backingStore(&window); + + QRect rect(0, 0, 100, 100); + backingStore.resize(rect.size()); + + // Partial fill of a fresh backingstore should not crash + backingStore.beginPaint(QRect(0, 0, 50, 50)); + backingStore.endPaint(); + backingStore.flush(rect); + + // Two rounds, with flush in between + for (int i = 0; i < 2; ++i) { + backingStore.beginPaint(rect); + QPainter p(backingStore.paintDevice()); + QColor bgColor = i ? Qt::red : Qt::blue; + QColor fgColor = i ? Qt::green : Qt::yellow; + p.fillRect(rect, bgColor); + p.fillRect(QRect(50, 50, 10, 10), fgColor); + p.end(); + backingStore.endPaint(); + + QImage image = backingStore.handle()->toImage(); + if (image.isNull()) + QSKIP("Platform backingstore does not implement toImage"); + + QCOMPARE(image.pixelColor(50 * dpr, 50 * dpr), fgColor); + QCOMPARE(image.pixelColor(49 * dpr, 50 * dpr), bgColor); + QCOMPARE(image.pixelColor(50 * dpr, 49 * dpr), bgColor); + QCOMPARE(image.pixelColor(59 * dpr, 59 * dpr), fgColor); + QCOMPARE(image.pixelColor(60 * dpr, 59 * dpr), bgColor); + QCOMPARE(image.pixelColor(59 * dpr, 60 * dpr), bgColor); + + backingStore.flush(rect); + } +} + +void tst_QBackingStore::scrollRectInImage_data() +{ + QTest::addColumn<QRect>("rect"); + QTest::addColumn<QPoint>("offset"); + + QTest::newRow("empty rect") << QRect() << QPoint(); + QTest::newRow("rect outside image") << QRect(-100, -100, 1000, 1000) << QPoint(10, 10); + QTest::newRow("scroll outside positive") << QRect(10, 10, 10, 10) << QPoint(1000, 1000); + QTest::newRow("scroll outside negative") << QRect(10, 10, 10, 10) << QPoint(-1000, -1000); + + QTest::newRow("sub-rect positive scroll") << QRect(100, 100, 50, 50) << QPoint(10, 10); + QTest::newRow("sub-rect negative scroll") << QRect(100, 100, 50, 50) << QPoint(-10, -10); + + QTest::newRow("positive vertical only") << QRect(100, 100, 50, 50) << QPoint(0, 10); + QTest::newRow("negative vertical only") << QRect(100, 100, 50, 50) << QPoint(0, -10); + QTest::newRow("positive horizontal only") << QRect(100, 100, 50, 50) << QPoint(10, 0); + QTest::newRow("negative horizontal only") << QRect(100, 100, 50, 50) << QPoint(-10, 0); + + QTest::newRow("whole rect positive") << QRect(0, 0, 250, 250) << QPoint(10, 10); + QTest::newRow("whole rect negative") << QRect(0, 0, 250, 250) << QPoint(-10, -10); +} + +QT_BEGIN_NAMESPACE +Q_GUI_EXPORT void qt_scrollRectInImage(QImage &, const QRect &, const QPoint &); +QT_END_NAMESPACE + +void tst_QBackingStore::scrollRectInImage() +{ + QImage test(250, 250, QImage::Format_ARGB32_Premultiplied); + + QFETCH(QRect, rect); + QFETCH(QPoint, offset); + + qt_scrollRectInImage(test, rect, offset); +} + +void tst_QBackingStore::scroll() +{ + QWindow window; + window.create(); + + // The resize() test verifies that the backingstore image + // has a size that takes the window's DPR into account. + auto dpr = window.devicePixelRatio(); + + QBackingStore backingStore(&window); + QRect rect(0, 0, 100, 100); + + // Scrolling a backingstore without a size shouldn't crash + backingStore.scroll(rect, 10, 10); + backingStore.scroll(rect, -10, -10); + + backingStore.resize(rect.size()); + + // Scrolling a backingstore without painting to it shouldn't crash + backingStore.scroll(rect, 10, 10); + backingStore.scroll(rect, -10, -10); + + // Two rounds, with flush in between + for (int i = 0; i < 2; ++i) { + + backingStore.beginPaint(rect); + QPainter p(backingStore.paintDevice()); + QColor bgColor = i ? Qt::red : Qt::blue; + QColor fgColor = i ? Qt::green : Qt::yellow; + p.fillRect(rect, bgColor); + p.fillRect(QRect(50, 50, 10, 10), fgColor); + p.end(); + backingStore.endPaint(); + + QImage image = backingStore.handle()->toImage(); + if (image.isNull()) + QSKIP("Platform backingstore does not implement toImage"); + + QCOMPARE(image.pixelColor(50 * dpr, 50 * dpr), fgColor); + QCOMPARE(image.pixelColor(49 * dpr, 50 * dpr), bgColor); + QCOMPARE(image.pixelColor(50 * dpr, 49 * dpr), bgColor); + QCOMPARE(image.pixelColor(59 * dpr, 59 * dpr), fgColor); + QCOMPARE(image.pixelColor(60 * dpr, 59 * dpr), bgColor); + QCOMPARE(image.pixelColor(59 * dpr, 60 * dpr), bgColor); + image = {}; + + bool supportsScroll = backingStore.scroll(QRect(52, 52, 6, 6), -12, -12); + if (!supportsScroll) + QSKIP("Platform backingstore does not support scrolling"); + + image = backingStore.handle()->toImage(); + QCOMPARE(image.pixelColor(40 * dpr, 40 * dpr), fgColor); + QCOMPARE(image.pixelColor(39 * dpr, 40 * dpr), bgColor); + QCOMPARE(image.pixelColor(40 * dpr, 39 * dpr), bgColor); + QCOMPARE(image.pixelColor(45 * dpr, 45 * dpr), fgColor); + QCOMPARE(image.pixelColor(46 * dpr, 45 * dpr), bgColor); + QCOMPARE(image.pixelColor(45 * dpr, 46 * dpr), bgColor); + image = {}; + + backingStore.flush(rect); + + // Scroll again after flush, but before new round of painting + backingStore.scroll(QRect(52, 52, 6, 6), 12, 12); + + image = backingStore.handle()->toImage(); + QCOMPARE(image.pixelColor(64 * dpr, 64 * dpr), fgColor); + QCOMPARE(image.pixelColor(63 * dpr, 64 * dpr), bgColor); + QCOMPARE(image.pixelColor(64 * dpr, 63 * dpr), bgColor); + QCOMPARE(image.pixelColor(69 * dpr, 69 * dpr), fgColor); + QCOMPARE(image.pixelColor(70 * dpr, 69 * dpr), bgColor); + QCOMPARE(image.pixelColor(69 * dpr, 70 * dpr), bgColor); + image = {}; + } +} + class Window : public QWindow { public: @@ -58,7 +248,7 @@ public: backingStore.resize(size()); } - void exposeEvent(QExposeEvent *event) override + void paintEvent(QPaintEvent *event) override { QRect rect(QPoint(), size()); @@ -70,10 +260,7 @@ public: backingStore.endPaint(); -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED backingStore.flush(event->region().boundingRect()); -QT_WARNING_POP } private: @@ -89,5 +276,79 @@ void tst_QBackingStore::flush() QTRY_VERIFY(window.isExposed()); } +void tst_QBackingStore::staticContents() +{ + const auto *integration = QGuiApplicationPrivate::platformIntegration(); + if (!integration->hasCapability(QPlatformIntegration::BackingStoreStaticContents)) + QSKIP("Platform does not support static backingstore content"); + + QWindow window; + window.create(); + + const auto dpr = window.devicePixelRatio(); + + QBackingStore backingStore(&window); + + QRect initialRect(0, 0, 100, 100); + + // Static contents without paint first should not crash + backingStore.setStaticContents(initialRect); + backingStore.resize(initialRect.size()); + QCOMPARE(backingStore.size(), initialRect.size()); + backingStore.beginPaint(QRect(0, 0, 50, 50)); + backingStore.endPaint(); + backingStore.handle()->toImage(); + + { + backingStore.setStaticContents(QRect()); + backingStore.beginPaint(initialRect); + QPainter p(backingStore.paintDevice()); + p.fillRect(initialRect, Qt::green); + p.end(); + backingStore.endPaint(); + + QImage image = backingStore.handle()->toImage(); + if (image.isNull()) + QSKIP("Platform backingstore does not implement toImage"); + + QCOMPARE(image.pixelColor(initialRect.topLeft() * dpr), Qt::green); + QCOMPARE(image.pixelColor(initialRect.bottomLeft() * dpr), Qt::green); + QCOMPARE(image.pixelColor(initialRect.topRight() * dpr), Qt::green); + QCOMPARE(image.pixelColor(initialRect.bottomRight() * dpr), Qt::green); + } + + { + backingStore.setStaticContents(initialRect); + + QRect resizedRect(0, 0, 200, 200); + backingStore.resize(resizedRect.size()); + + QRegion repaintRegion = QRegion(resizedRect) - QRegion(initialRect); + + backingStore.beginPaint(repaintRegion); + QPainter p(backingStore.paintDevice()); + for (auto repaintRect : repaintRegion) + p.fillRect(repaintRect, Qt::red); + p.end(); + backingStore.endPaint(); + + QImage image = backingStore.handle()->toImage(); + if (image.isNull()) + QSKIP("Platform backingstore does not implement toImage"); + + QCOMPARE(image.pixelColor(initialRect.topLeft() * dpr), Qt::green); + QCOMPARE(image.pixelColor(initialRect.bottomLeft() * dpr), Qt::green); + QCOMPARE(image.pixelColor(initialRect.topRight() * dpr), Qt::green); + QCOMPARE(image.pixelColor(initialRect.bottomRight() * dpr), Qt::green); + + for (auto repaintRect : repaintRegion) { + QCOMPARE(image.pixelColor(repaintRect.topLeft() * dpr), Qt::red); + QCOMPARE(image.pixelColor(repaintRect.bottomLeft() * dpr), Qt::red); + QCOMPARE(image.pixelColor(repaintRect.topRight() * dpr), Qt::red); + QCOMPARE(image.pixelColor(repaintRect.bottomRight() * dpr), Qt::red); + } + } +} + #include <tst_qbackingstore.moc> QTEST_MAIN(tst_QBackingStore); diff --git a/tests/auto/gui/kernel/qclipboard/CMakeLists.txt b/tests/auto/gui/kernel/qclipboard/CMakeLists.txt index 05eba972d6..b7a0467758 100644 --- a/tests/auto/gui/kernel/qclipboard/CMakeLists.txt +++ b/tests/auto/gui/kernel/qclipboard/CMakeLists.txt @@ -1,4 +1,11 @@ -# Generated from qclipboard.pro. +# 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_qclipboard LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() add_subdirectory(copier) add_subdirectory(paster) diff --git a/tests/auto/gui/kernel/qclipboard/copier/.prev_CMakeLists.txt b/tests/auto/gui/kernel/qclipboard/copier/.prev_CMakeLists.txt deleted file mode 100644 index 744bd3d654..0000000000 --- a/tests/auto/gui/kernel/qclipboard/copier/.prev_CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Generated from copier.pro. - -##################################################################### -## copier Binary: -##################################################################### - -qt_add_executable(copier - SOURCES - main.cpp - PUBLIC_LIBRARIES - Qt::Gui -) - -## Scopes: -##################################################################### - -#### Keys ignored in scope 2:.:.:copier.pro:WIN32: -# DESTDIR = "../copier" diff --git a/tests/auto/gui/kernel/qclipboard/copier/CMakeLists.txt b/tests/auto/gui/kernel/qclipboard/copier/CMakeLists.txt index ee3c7b1ab9..ea7def8c0d 100644 --- a/tests/auto/gui/kernel/qclipboard/copier/CMakeLists.txt +++ b/tests/auto/gui/kernel/qclipboard/copier/CMakeLists.txt @@ -1,23 +1,16 @@ -# Generated from copier.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## copier Binary: ##################################################################### -# special case begin set(args OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -# special case end -qt_add_executable(copier - ${args} # special case +qt_internal_add_executable(copier + ${args} SOURCES main.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) - -## Scopes: -##################################################################### - -#### Keys ignored in scope 2:.:.:copier.pro:WIN32: -# DESTDIR = "../copier" diff --git a/tests/auto/gui/kernel/qclipboard/copier/copier.pro b/tests/auto/gui/kernel/qclipboard/copier/copier.pro deleted file mode 100644 index def50b6476..0000000000 --- a/tests/auto/gui/kernel/qclipboard/copier/copier.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG -= app_bundle -win32: DESTDIR = ../copier - -SOURCES += main.cpp diff --git a/tests/auto/gui/kernel/qclipboard/copier/main.cpp b/tests/auto/gui/kernel/qclipboard/copier/main.cpp index 32e91a9939..362ede38b7 100644 --- a/tests/auto/gui/kernel/qclipboard/copier/main.cpp +++ b/tests/auto/gui/kernel/qclipboard/copier/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtGui/QGuiApplication> #include <QtGui/QClipboard> #include <QtCore/QStringList> diff --git a/tests/auto/gui/kernel/qclipboard/paster/.prev_CMakeLists.txt b/tests/auto/gui/kernel/qclipboard/paster/.prev_CMakeLists.txt deleted file mode 100644 index 0f2fbb1b9b..0000000000 --- a/tests/auto/gui/kernel/qclipboard/paster/.prev_CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -# Generated from paster.pro. - -##################################################################### -## paster Binary: -##################################################################### - -qt_add_executable(paster - SOURCES - main.cpp - PUBLIC_LIBRARIES - Qt::Gui -) - -## Scopes: -##################################################################### - -#### Keys ignored in scope 2:.:.:paster.pro:WIN32: -# DESTDIR = "../paster" diff --git a/tests/auto/gui/kernel/qclipboard/paster/CMakeLists.txt b/tests/auto/gui/kernel/qclipboard/paster/CMakeLists.txt index 6ce4070af2..9bc1985ee4 100644 --- a/tests/auto/gui/kernel/qclipboard/paster/CMakeLists.txt +++ b/tests/auto/gui/kernel/qclipboard/paster/CMakeLists.txt @@ -1,23 +1,16 @@ -# Generated from paster.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## paster Binary: ##################################################################### -# special case begin set(args OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}") -# special case end -qt_add_executable(paster - ${args} # special case +qt_internal_add_executable(paster + ${args} SOURCES main.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) - -## Scopes: -##################################################################### - -#### Keys ignored in scope 2:.:.:paster.pro:WIN32: -# DESTDIR = "../paster" diff --git a/tests/auto/gui/kernel/qclipboard/paster/main.cpp b/tests/auto/gui/kernel/qclipboard/paster/main.cpp index 7fca8af1cb..bf47b10ba6 100644 --- a/tests/auto/gui/kernel/qclipboard/paster/main.cpp +++ b/tests/auto/gui/kernel/qclipboard/paster/main.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtGui/QGuiApplication> #include <QtGui/QClipboard> #include <QtGui/QImage> diff --git a/tests/auto/gui/kernel/qclipboard/paster/paster.pro b/tests/auto/gui/kernel/qclipboard/paster/paster.pro deleted file mode 100644 index ef91e77b6e..0000000000 --- a/tests/auto/gui/kernel/qclipboard/paster/paster.pro +++ /dev/null @@ -1,4 +0,0 @@ -win32: DESTDIR = ../paster -CONFIG -= app_bundle - -SOURCES += main.cpp diff --git a/tests/auto/gui/kernel/qclipboard/qclipboard.pro b/tests/auto/gui/kernel/qclipboard/qclipboard.pro deleted file mode 100644 index d97c58dea0..0000000000 --- a/tests/auto/gui/kernel/qclipboard/qclipboard.pro +++ /dev/null @@ -1,4 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = copier paster -test.depends += $$SUBDIRS -SUBDIRS += test diff --git a/tests/auto/gui/kernel/qclipboard/test/.prev_CMakeLists.txt b/tests/auto/gui/kernel/qclipboard/test/.prev_CMakeLists.txt deleted file mode 100644 index e7c1313c7b..0000000000 --- a/tests/auto/gui/kernel/qclipboard/test/.prev_CMakeLists.txt +++ /dev/null @@ -1,24 +0,0 @@ -# Generated from test.pro. - -##################################################################### -## tst_qclipboard Test: -##################################################################### - -add_qt_test(tst_qclipboard - OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" - SOURCES - ../tst_qclipboard.cpp - PUBLIC_LIBRARIES - Qt::Gui -) - -## Scopes: -##################################################################### - -extend_target(tst_qclipboard CONDITION MACOS - PUBLIC_LIBRARIES - ${FWAppKit} -) - -#### Keys ignored in scope 6:.:.:test.pro:NOT ANDROID: -# TEST_HELPER_INSTALLS = "../copier/copier" "../paster/paster" diff --git a/tests/auto/gui/kernel/qclipboard/test/BLACKLIST b/tests/auto/gui/kernel/qclipboard/test/BLACKLIST new file mode 100644 index 0000000000..3ca7791b37 --- /dev/null +++ b/tests/auto/gui/kernel/qclipboard/test/BLACKLIST @@ -0,0 +1,5 @@ +# QTBUG-87429 +[testSignals] +android +[setMimeData] +android diff --git a/tests/auto/gui/kernel/qclipboard/test/CMakeLists.txt b/tests/auto/gui/kernel/qclipboard/test/CMakeLists.txt index 1e2c89e538..fad30c16fd 100644 --- a/tests/auto/gui/kernel/qclipboard/test/CMakeLists.txt +++ b/tests/auto/gui/kernel/qclipboard/test/CMakeLists.txt @@ -1,14 +1,15 @@ -# Generated from test.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qclipboard Test: ##################################################################### -qt_add_test(tst_qclipboard +qt_internal_add_test(tst_qclipboard OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/../" SOURCES ../tst_qclipboard.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::GuiPrivate ) @@ -16,10 +17,9 @@ qt_add_test(tst_qclipboard ## Scopes: ##################################################################### -qt_extend_target(tst_qclipboard CONDITION MACOS - PUBLIC_LIBRARIES +qt_internal_extend_target(tst_qclipboard CONDITION MACOS + LIBRARIES ${FWAppKit} ) -#### Keys ignored in scope 6:.:.:test.pro:NOT ANDROID: # TEST_HELPER_INSTALLS = "../copier/copier" "../paster/paster" diff --git a/tests/auto/gui/kernel/qclipboard/test/test.pro b/tests/auto/gui/kernel/qclipboard/test/test.pro deleted file mode 100644 index 8ccdecd405..0000000000 --- a/tests/auto/gui/kernel/qclipboard/test/test.pro +++ /dev/null @@ -1,18 +0,0 @@ -CONFIG += testcase -SOURCES += ../tst_qclipboard.cpp -TARGET = ../tst_qclipboard -QT += testlib gui-private - -osx: LIBS += -framework AppKit - -win32 { - CONFIG(debug, debug|release) { - TARGET = ../../debug/tst_qclipboard -} else { - TARGET = ../../release/tst_qclipboard - } -} - -!android: TEST_HELPER_INSTALLS = \ - ../copier/copier \ - ../paster/paster diff --git a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp index 0df949acba..30366c6aa1 100644 --- a/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp +++ b/tests/auto/gui/kernel/qclipboard/tst_qclipboard.cpp @@ -1,33 +1,13 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> +#include <QMimeData> +#include <QSignalSpy> +#if QT_CONFIG(process) +#include <QProcess> +#endif #include <QtCore/QDebug> #include <QtCore/QFileInfo> #include <QtCore/QDir> @@ -41,8 +21,9 @@ #ifdef Q_OS_WIN # include <QtGui/private/qguiapplication_p.h> -# include <QtGui/private/qwindowsmime_p.h> +# include <QtGui/qwindowsmimeconverter.h> # include <QtGui/qpa/qplatformintegration.h> +# include <QtCore/qt_windows.h> #endif class tst_QClipboard : public QObject @@ -61,6 +42,7 @@ private slots: void testSignals(); void setMimeData(); void clearBeforeSetText(); + void getTextFromHTMLMimeType(); # ifdef Q_OS_WIN void testWindowsMimeRegisterType(); void testWindowsMime_data(); @@ -81,7 +63,7 @@ void tst_QClipboard::initTestCase() #if QT_CONFIG(clipboard) void tst_QClipboard::init() { -#if QT_CONFIG(process) +#if QT_CONFIG(process) && !defined(Q_OS_ANDROID) const QString testdataDir = QFileInfo(QFINDTESTDATA("copier")).absolutePath(); QVERIFY2(QDir::setCurrent(testdataDir), qPrintable("Could not chdir to " + testdataDir)); #endif @@ -144,7 +126,7 @@ public: operator bool() const { - if (m_timer.elapsed() && !m_spy.count()) + if (m_timer.elapsed() && !m_spy.size()) return true; m_spy.clear(); return false; @@ -186,11 +168,11 @@ void tst_QClipboard::testSignals() // Test the default mode signal. clipboard->setText(text); - QTRY_COMPARE(dataChangedSpy.count(), 1); - QCOMPARE(searchChangedSpy.count(), 0); - QCOMPARE(selectionChangedSpy.count(), 0); - QCOMPARE(changedSpy.count(), 1); - QCOMPARE(changedSpy.at(0).count(), 1); + QTRY_COMPARE(dataChangedSpy.size(), 1); + QCOMPARE(searchChangedSpy.size(), 0); + QCOMPARE(selectionChangedSpy.size(), 0); + QCOMPARE(changedSpy.size(), 1); + QCOMPARE(changedSpy.at(0).size(), 1); QCOMPARE(qvariant_cast<QClipboard::Mode>(changedSpy.at(0).at(0)), QClipboard::Clipboard); changedSpy.clear(); @@ -198,29 +180,29 @@ void tst_QClipboard::testSignals() // Test the selection mode signal. if (clipboard->supportsSelection()) { clipboard->setText(text, QClipboard::Selection); - QCOMPARE(selectionChangedSpy.count(), 1); - QCOMPARE(changedSpy.count(), 1); - QCOMPARE(changedSpy.at(0).count(), 1); + QCOMPARE(selectionChangedSpy.size(), 1); + QCOMPARE(changedSpy.size(), 1); + QCOMPARE(changedSpy.at(0).size(), 1); QCOMPARE(qvariant_cast<QClipboard::Mode>(changedSpy.at(0).at(0)), QClipboard::Selection); } else { - QCOMPARE(selectionChangedSpy.count(), 0); + QCOMPARE(selectionChangedSpy.size(), 0); } - QCOMPARE(dataChangedSpy.count(), 1); - QCOMPARE(searchChangedSpy.count(), 0); + QCOMPARE(dataChangedSpy.size(), 1); + QCOMPARE(searchChangedSpy.size(), 0); changedSpy.clear(); // Test the search mode signal. if (clipboard->supportsFindBuffer()) { clipboard->setText(text, QClipboard::FindBuffer); - QCOMPARE(searchChangedSpy.count(), 1); - QCOMPARE(changedSpy.count(), 1); - QCOMPARE(changedSpy.at(0).count(), 1); + QCOMPARE(searchChangedSpy.size(), 1); + QCOMPARE(changedSpy.size(), 1); + QCOMPARE(changedSpy.at(0).size(), 1); QCOMPARE(qvariant_cast<QClipboard::Mode>(changedSpy.at(0).at(0)), QClipboard::FindBuffer); } else { - QCOMPARE(searchChangedSpy.count(), 0); + QCOMPARE(searchChangedSpy.size(), 0); } - QCOMPARE(dataChangedSpy.count(), 1); + QCOMPARE(dataChangedSpy.size(), 1); } #if defined(Q_OS_WIN) || defined(Q_OS_MAC) || defined(Q_OS_QNX) @@ -360,16 +342,16 @@ void tst_QClipboard::setMimeData() QGuiApplication::clipboard()->clear(QClipboard::FindBuffer); if (QGuiApplication::clipboard()->supportsSelection()) - QCOMPARE(spySelection.count(), 1); + QCOMPARE(spySelection.size(), 1); else - QCOMPARE(spySelection.count(), 0); + QCOMPARE(spySelection.size(), 0); if (QGuiApplication::clipboard()->supportsFindBuffer()) - QCOMPARE(spyFindBuffer.count(), 1); + QCOMPARE(spyFindBuffer.size(), 1); else - QCOMPARE(spyFindBuffer.count(), 0); + QCOMPARE(spyFindBuffer.size(), 0); - QTRY_COMPARE(spyData.count(), 1); + QTRY_COMPARE(spyData.size(), 1); // an other crash test data = new QMimeData; @@ -396,16 +378,16 @@ void tst_QClipboard::setMimeData() QGuiApplication::clipboard()->setMimeData(newData, QClipboard::FindBuffer); if (QGuiApplication::clipboard()->supportsSelection()) - QCOMPARE(spySelection.count(), 1); + QCOMPARE(spySelection.size(), 1); else - QCOMPARE(spySelection.count(), 0); + QCOMPARE(spySelection.size(), 0); if (QGuiApplication::clipboard()->supportsFindBuffer()) - QCOMPARE(spyFindBuffer.count(), 1); + QCOMPARE(spyFindBuffer.size(), 1); else - QCOMPARE(spyFindBuffer.count(), 0); + QCOMPARE(spyFindBuffer.size(), 0); - QTRY_COMPARE(spyData.count(), 1); + QTRY_COMPARE(spyData.size(), 1); } void tst_QClipboard::clearBeforeSetText() @@ -444,12 +426,30 @@ void tst_QClipboard::clearBeforeSetText() QCOMPARE(QGuiApplication::clipboard()->text(), text); } +void tst_QClipboard::getTextFromHTMLMimeType() +{ + QClipboard * clipboard = QGuiApplication::clipboard(); + QMimeData * mimeData = new QMimeData(); + const QString testString("TEST"); + const QString htmlString(QLatin1String("<html><body>") + testString + QLatin1String("</body></html>")); + + mimeData->setText(testString); + mimeData->setHtml(htmlString); + clipboard->setMimeData(mimeData); + + QCOMPARE(clipboard->text(), testString); + QVERIFY(clipboard->mimeData()->hasText()); + QVERIFY(clipboard->mimeData()->hasHtml()); + QCOMPARE(clipboard->mimeData()->text(), testString); + QCOMPARE(clipboard->mimeData()->html(), htmlString); +} + # ifdef Q_OS_WIN -using QWindowsMime = QPlatformInterface::Private::QWindowsMime; -using QWindowsApplication = QPlatformInterface::Private::QWindowsApplication; +using QWindowsMimeConverter = QWindowsMimeConverter; +using QWindowsApplication = QNativeInterface::Private::QWindowsApplication; -class TestMime : public QWindowsMime +class TestMime : public QWindowsMimeConverter { public: bool canConvertFromMime(const FORMATETC &, const QMimeData *) const override @@ -514,11 +514,11 @@ void tst_QClipboard::testWindowsMime() nativeWindowsApp->registerMime(&testMime); auto clipboard = QGuiApplication::clipboard(); - switch (data.type()) { - case QVariant::String: + switch (data.metaType().id()) { + case QMetaType::QString: clipboard->setText(data.toString()); break; - case QVariant::Pixmap: + case QMetaType::QPixmap: clipboard->setPixmap(data.value<QPixmap>()); break; default: diff --git a/tests/auto/gui/kernel/qcursor/CMakeLists.txt b/tests/auto/gui/kernel/qcursor/CMakeLists.txt index 2c3cf28c1a..52c88fc231 100644 --- a/tests/auto/gui/kernel/qcursor/CMakeLists.txt +++ b/tests/auto/gui/kernel/qcursor/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qcursor.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qcursor Test: ##################################################################### -qt_add_test(tst_qcursor +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qcursor LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qcursor SOURCES tst_qcursor.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qcursor/qcursor.pro b/tests/auto/gui/kernel/qcursor/qcursor.pro deleted file mode 100644 index 16e7d7c41c..0000000000 --- a/tests/auto/gui/kernel/qcursor/qcursor.pro +++ /dev/null @@ -1,6 +0,0 @@ -QT += testlib -TARGET = tst_qcursor -CONFIG += testcase -CONFIG -= app_bundle - -SOURCES += tst_qcursor.cpp diff --git a/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp b/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp index eb33cce95b..edc44b9ea6 100644 --- a/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp +++ b/tests/auto/gui/kernel/qcursor/tst_qcursor.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtTest/QTest> #include <qcursor.h> diff --git a/tests/auto/gui/kernel/qdrag/CMakeLists.txt b/tests/auto/gui/kernel/qdrag/CMakeLists.txt index 1b13df54d3..015cfe70d0 100644 --- a/tests/auto/gui/kernel/qdrag/CMakeLists.txt +++ b/tests/auto/gui/kernel/qdrag/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qdrag.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qdrag Test: ##################################################################### -qt_add_test(tst_qdrag +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qdrag LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qdrag SOURCES tst_qdrag.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qdrag/qdrag.pro b/tests/auto/gui/kernel/qdrag/qdrag.pro deleted file mode 100644 index ac3fde8028..0000000000 --- a/tests/auto/gui/kernel/qdrag/qdrag.pro +++ /dev/null @@ -1,10 +0,0 @@ -############################################################ -# Project file for autotest for file qdrag.h -############################################################ - -CONFIG += testcase -TARGET = tst_qdrag -QT += testlib -SOURCES += tst_qdrag.cpp - - diff --git a/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp b/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp index 91ff24ffd1..9e0d5ad0f4 100644 --- a/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp +++ b/tests/auto/gui/kernel/qdrag/tst_qdrag.cpp @@ -1,33 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include <QtTest/QtTest> +#include <QTest> +#include <QMimeData> #include <qcoreapplication.h> #include <qdebug.h> diff --git a/tests/auto/gui/kernel/qevent/CMakeLists.txt b/tests/auto/gui/kernel/qevent/CMakeLists.txt index 21a2ddad66..c6ad861f25 100644 --- a/tests/auto/gui/kernel/qevent/CMakeLists.txt +++ b/tests/auto/gui/kernel/qevent/CMakeLists.txt @@ -1,10 +1,20 @@ -# Generated from qevent.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qevent Test: ##################################################################### -qt_add_test(tst_qevent +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qevent LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qevent SOURCES tst_qevent.cpp + LIBRARIES + Qt::Gui + Qt::CorePrivate ) diff --git a/tests/auto/gui/kernel/qevent/qevent.pro b/tests/auto/gui/kernel/qevent/qevent.pro deleted file mode 100644 index 2959089ce3..0000000000 --- a/tests/auto/gui/kernel/qevent/qevent.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qevent -SOURCES += tst_qevent.cpp -QT = core testlib diff --git a/tests/auto/gui/kernel/qevent/tst_qevent.cpp b/tests/auto/gui/kernel/qevent/tst_qevent.cpp index 50710a0475..8e8169b16c 100644 --- a/tests/auto/gui/kernel/qevent/tst_qevent.cpp +++ b/tests/auto/gui/kernel/qevent/tst_qevent.cpp @@ -1,36 +1,117 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> - -#include <QtCore/qcoreapplication.h> -#include <QtCore/qcoreevent.h> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> + +#include <QtGui/qguiapplication.h> +#include <QtGui/qevent.h> +#if QT_CONFIG(future) +#include <QtCore/private/qfutureinterface_p.h> +#endif + + +#if QT_CONFIG(future) +#define X_QFutureCallOutEvent(X) X(QFutureCallOutEvent, ()) +#else +#define X_QFutureCallOutEvent(X) +#endif + +#if QT_CONFIG(wheelevent) +#define X_QWheelEvent(X) X(QWheelEvent, ({}, {}, {}, {}, {}, {}, {}, {})) +#else +#define X_QWheelEvent(X) +#endif + +#if QT_CONFIG(tabletevent) +#define X_QTabletEvent(X) X(QTabletEvent, (QEvent::None, QPointingDevice::primaryPointingDevice(), {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {})) +#else +#define X_QTabletEvent(X) +#endif + +#if QT_CONFIG(gestures) +#define X_QNativeGestureEvent(X) X(QNativeGestureEvent, ({}, QPointingDevice::primaryPointingDevice(), 0, {}, {}, {}, {}, {})) +#else +#define X_QNativeGestureEvent(X) +#endif + +#if QT_CONFIG(whatsthis) +#define X_QWhatsThisClickedEvent(X) X(QWhatsThisClickedEvent, ({})) +#else +#define X_QWhatsThisClickedEvent(X) +#endif + +#if QT_CONFIG(action) +#define X_QActionEvent(X) X(QActionEvent, (0, nullptr)) +#else +#define X_QActionEvent(X) +#endif + +#if QT_CONFIG(shortcut) +#define X_QShortcutEvent(X) X(QShortcutEvent, ({}, 0)) +#else +#define X_QShortcutEvent(X) +#endif + +#define FOR_EACH_CORE_EVENT(X) \ + /* qcoreevent.h */ \ + X(QEvent, (QEvent::None)) \ + X(QTimerEvent, (42)) \ + X(QChildEvent, (QEvent::ChildAdded, nullptr)) \ + X(QDynamicPropertyChangeEvent, ("size")) \ + /* qfutureinterface_p.h */ \ + X_QFutureCallOutEvent(X) \ + /* end */ + +#define FOR_EACH_GUI_EVENT(X) \ + /* qevent.h */ \ + X(QInputEvent, (QEvent::None, nullptr)) \ + X(QPointerEvent, (QEvent::None, nullptr)) \ + /* doesn't work with nullptr: */ \ + X(QSinglePointEvent, (QEvent::None, QPointingDevice::primaryPointingDevice(), {}, {}, {}, {}, {}, {})) \ + X(QEnterEvent, ({}, {}, {})) \ + X(QMouseEvent, (QEvent::None, {}, {}, {}, {}, {}, {}, {}, QPointingDevice::primaryPointingDevice())) \ + X(QHoverEvent, (QEvent::None, {}, {}, QPointF{})) \ + X_QWheelEvent(X) \ + X_QTabletEvent(X) \ + X_QNativeGestureEvent(X) \ + X(QKeyEvent, (QEvent::None, 0, {})) \ + X(QFocusEvent, (QEvent::None)) \ + X(QPaintEvent, (QRect{0, 0, 100, 100})) \ + X(QMoveEvent, ({}, {})) \ + X(QExposeEvent, ({})) \ + X(QPlatformSurfaceEvent, ({})) \ + X(QResizeEvent, ({}, {})) \ + X(QCloseEvent, ()) \ + X(QIconDragEvent, ()) \ + X(QShowEvent, ()) \ + X(QHideEvent, ()) \ + X(QContextMenuEvent, (QContextMenuEvent::Reason::Keyboard, {}, {})) \ + X(QInputMethodEvent, ()) \ + X(QInputMethodQueryEvent, ({})) \ + X(QDropEvent, ({}, {}, {}, {}, {})) \ + X(QDragMoveEvent, ({}, {}, {}, {}, {})) \ + X(QDragEnterEvent, ({}, {}, {}, {}, {})) \ + X(QDragLeaveEvent, ()) \ + X(QHelpEvent, ({}, {}, {})) \ + X(QStatusTipEvent, ({})) \ + X_QWhatsThisClickedEvent(X) \ + X_QActionEvent(X) \ + X(QFileOpenEvent, (QString{})) \ + X(QToolBarChangeEvent, (false)) \ + X_QShortcutEvent(X) \ + X(QWindowStateChangeEvent, ({})) \ + X(QTouchEvent, (QEvent::None)) \ + X(QScrollPrepareEvent, ({})) \ + X(QScrollEvent, ({}, {}, {})) \ + X(QScreenOrientationChangeEvent, (nullptr, {})) \ + X(QApplicationStateChangeEvent, ({})) \ + /* end */ + +#define FOR_EACH_EVENT(X) \ + FOR_EACH_CORE_EVENT(X) \ + FOR_EACH_GUI_EVENT(X) \ + /* end */ class tst_QEvent : public QObject { @@ -40,6 +121,7 @@ public: ~tst_QEvent(); private slots: + void clone() const; void registerEventType_data(); void registerEventType(); void exhaustEventTypeRegistration(); // keep behind registerEventType() test @@ -55,6 +137,18 @@ tst_QEvent::tst_QEvent() tst_QEvent::~tst_QEvent() { } +void tst_QEvent::clone() const +{ +#define ACTION(Type, Init) do { \ + const std::unique_ptr<const Type> e(new Type Init); \ + auto c = e->clone(); \ + static_assert(std::is_same_v<decltype(c), Type *>); \ + delete c; \ + } while (0); + + FOR_EACH_EVENT(ACTION) +} + void tst_QEvent::registerEventType_data() { QTest::addColumn<int>("hint"); diff --git a/tests/auto/gui/kernel/qfileopenevent/CMakeLists.txt b/tests/auto/gui/kernel/qfileopenevent/CMakeLists.txt index 2404833737..9906400a66 100644 --- a/tests/auto/gui/kernel/qfileopenevent/CMakeLists.txt +++ b/tests/auto/gui/kernel/qfileopenevent/CMakeLists.txt @@ -1,4 +1,11 @@ -# Generated from qfileopenevent.pro. +# 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_qfileopenevent LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() add_subdirectory(test) add_subdirectory(qfileopeneventexternal) diff --git a/tests/auto/gui/kernel/qfileopenevent/qfileopenevent.pro b/tests/auto/gui/kernel/qfileopenevent/qfileopenevent.pro deleted file mode 100644 index 45978d7b7e..0000000000 --- a/tests/auto/gui/kernel/qfileopenevent/qfileopenevent.pro +++ /dev/null @@ -1,2 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = test qfileopeneventexternal diff --git a/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/CMakeLists.txt b/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/CMakeLists.txt index 0b9cd6d481..7a39bc111c 100644 --- a/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/CMakeLists.txt +++ b/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/CMakeLists.txt @@ -1,16 +1,14 @@ -# Generated from qfileopeneventexternal.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## qfileopeneventexternal Binary: ##################################################################### -qt_add_executable(qfileopeneventexternal +qt_internal_add_executable(qfileopeneventexternal GUI SOURCES qfileopeneventexternal.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) - -#### Keys ignored in scope 1:.:.:qfileopeneventexternal.pro:<TRUE>: -# TEMPLATE = "app" diff --git a/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp b/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp index f21b0680bc..bd74e7497f 100644 --- a/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp +++ b/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtGui> #include <QEvent> @@ -39,8 +14,8 @@ struct MyApplication : public QGuiApplication { if (event->type() == QEvent::FileOpen) { QFileOpenEvent* ev = static_cast<QFileOpenEvent *>(event); - QFile file; - bool ok = ev->openFile(file, QFile::Append | QFile::Unbuffered); + QFile file(ev->file()); + bool ok = file.open(QFile::Append | QFile::Unbuffered); if (ok) file.write(QByteArray("+external")); return true; diff --git a/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro b/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro deleted file mode 100644 index a4abaeedc6..0000000000 --- a/tests/auto/gui/kernel/qfileopenevent/qfileopeneventexternal/qfileopeneventexternal.pro +++ /dev/null @@ -1,3 +0,0 @@ -TEMPLATE = app -TARGET = qfileopeneventexternal -SOURCES += qfileopeneventexternal.cpp diff --git a/tests/auto/gui/kernel/qfileopenevent/test/CMakeLists.txt b/tests/auto/gui/kernel/qfileopenevent/test/CMakeLists.txt index a306a3eae6..d7f4e32f70 100644 --- a/tests/auto/gui/kernel/qfileopenevent/test/CMakeLists.txt +++ b/tests/auto/gui/kernel/qfileopenevent/test/CMakeLists.txt @@ -1,12 +1,13 @@ -# Generated from test.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qfileopenevent Test: ##################################################################### -qt_add_test(tst_qfileopenevent +qt_internal_add_test(tst_qfileopenevent SOURCES tst_qfileopenevent.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qfileopenevent/test/test.pro b/tests/auto/gui/kernel/qfileopenevent/test/test.pro deleted file mode 100644 index a6d3f322ef..0000000000 --- a/tests/auto/gui/kernel/qfileopenevent/test/test.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qfileopenevent -QT += testlib -SOURCES += tst_qfileopenevent.cpp diff --git a/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp b/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp index 9da15b3e36..4b9a23ffcf 100644 --- a/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp +++ b/tests/auto/gui/kernel/qfileopenevent/test/tst_qfileopenevent.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/QTemporaryDir> -#include <QtTest/QtTest> +#include <QTest> #include <QtGui/qevent.h> class tst_qfileopenevent : public QObject @@ -79,7 +54,7 @@ void tst_qfileopenevent::cleanupTestCase() void tst_qfileopenevent::createFile(const QString &filename, const QByteArray &content) { QFile file(filename); - file.open(QFile::WriteOnly); + QVERIFY(file.open(QFile::WriteOnly)); file.write(content); file.close(); } @@ -103,8 +78,9 @@ void tst_qfileopenevent::constructor() QByteArray tst_qfileopenevent::readFileContent(QFileOpenEvent& event) { - QFile file; - event.openFile(file, QFile::ReadOnly); + QFile file(event.file()); + if (!file.open(QFile::ReadOnly)) + qFatal("Cannot open file %s", qPrintable(event.file())); file.seek(0); QByteArray data = file.readAll(); return data; @@ -112,8 +88,8 @@ QByteArray tst_qfileopenevent::readFileContent(QFileOpenEvent& event) bool tst_qfileopenevent::appendFileContent(QFileOpenEvent& event, const QByteArray& writeContent) { - QFile file; - bool ok = event.openFile(file, QFile::Append | QFile::Unbuffered); + QFile file(event.file()); + bool ok = file.open(QFile::Append | QFile::Unbuffered); if (ok) ok = file.write(writeContent) == writeContent.size(); return ok; @@ -152,8 +128,8 @@ void tst_qfileopenevent::handleLifetime() QScopedPointer<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testHandleLifetime"), QByteArray("test content"))); // open a QFile after the original RFile is closed - QFile qFile; - QCOMPARE(event->openFile(qFile, QFile::Append | QFile::Unbuffered), true); + QFile qFile(event->file()); + QVERIFY(qFile.open(QFile::Append | QFile::Unbuffered)); event.reset(0); // write to the QFile after the event is closed @@ -163,7 +139,7 @@ void tst_qfileopenevent::handleLifetime() // check the content QFile checkContent("testHandleLifetime"); - checkContent.open(QFile::ReadOnly); + QVERIFY(checkContent.open(QFile::ReadOnly)); QString content(checkContent.readAll()); QCOMPARE(content, QLatin1String("test content+closed original handles")); checkContent.close(); @@ -177,7 +153,8 @@ void tst_qfileopenevent::multiOpen() QFile files[5]; for (int i=0; i<5; i++) { - QCOMPARE(event->openFile(files[i], QFile::ReadOnly), true); + files[i].setFileName(event->file()); + QVERIFY(files[i].open(QFile::ReadOnly)); } for (int i=0; i<5; i++) files[i].seek(i); @@ -204,9 +181,9 @@ bool tst_qfileopenevent::event(QEvent *event) void tst_qfileopenevent::sendAndReceive() { - QScopedPointer<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testSendAndReceive"), QByteArray("sending"))); + std::unique_ptr<QFileOpenEvent> event(createFileAndEvent(QLatin1String("testSendAndReceive"), QByteArray("sending"))); - QCoreApplication::instance()->postEvent(this, event.take()); + QCoreApplication::instance()->postEvent(this, event.release()); QCoreApplication::instance()->processEvents(); // QTBUG-17468: On Mac, processEvents doesn't always process posted events diff --git a/tests/auto/gui/kernel/qguiapplication/.prev_CMakeLists.txt b/tests/auto/gui/kernel/qguiapplication/.prev_CMakeLists.txt deleted file mode 100644 index 0da40c5aa3..0000000000 --- a/tests/auto/gui/kernel/qguiapplication/.prev_CMakeLists.txt +++ /dev/null @@ -1,45 +0,0 @@ -# Generated from qguiapplication.pro. - -if(NOT QT_FEATURE_private_tests) - return() -endif() - -##################################################################### -## tst_qguiapplication Test: -##################################################################### - -qt_add_test(tst_qguiapplication - SOURCES - tst_qcoreapplication.cpp tst_qcoreapplication.h - tst_qguiapplication.cpp - DEFINES - QT_DISABLE_DEPRECATED_BEFORE=0x050E00 - INCLUDE_DIRECTORIES - ../../../corelib/kernel/qcoreapplication - PUBLIC_LIBRARIES - Qt::CorePrivate - Qt::GuiPrivate -) - -# Resources: -set(tst_qguiapplication_resource_files - "icons/appicon.png" - "icons/usericon.png" -) - -qt_add_resource(tst_qguiapplication "tst_qguiapplication" - PREFIX - "/" - FILES - ${tst_qguiapplication_resource_files} -) - - -## Scopes: -##################################################################### - -#### Keys ignored in scope 3:.:../../../corelib/kernel/qcoreapplication:../../../corelib/kernel/qcoreapplication/qcoreapplication.pro:WIN32: -# VERSION = "1.2.3.4" - -#### Keys ignored in scope 4:.:../../../corelib/kernel/qcoreapplication:../../../corelib/kernel/qcoreapplication/qcoreapplication.pro:else: -# VERSION = "1.2.3" diff --git a/tests/auto/gui/kernel/qguiapplication/BLACKLIST b/tests/auto/gui/kernel/qguiapplication/BLACKLIST index 58ca7bf782..3fa6c4880b 100644 --- a/tests/auto/gui/kernel/qguiapplication/BLACKLIST +++ b/tests/auto/gui/kernel/qguiapplication/BLACKLIST @@ -1,6 +1,2 @@ -[focusObject] -ubuntu-16.04 -opensuse-42.3 - -[quitOnLastWindowClosedMulti] -macos ci +[quitOnLastWindowClosedWithEventLoopLocker] +b2qt diff --git a/tests/auto/gui/kernel/qguiapplication/CMakeLists.txt b/tests/auto/gui/kernel/qguiapplication/CMakeLists.txt index 0347b3cc4a..6f1f845edd 100644 --- a/tests/auto/gui/kernel/qguiapplication/CMakeLists.txt +++ b/tests/auto/gui/kernel/qguiapplication/CMakeLists.txt @@ -1,60 +1,48 @@ -# Generated from qguiapplication.pro. - -if(NOT QT_FEATURE_private_tests) - return() -endif() +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qguiapplication Test: ##################################################################### -# special case begin +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qguiapplication LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + if (WIN32) set(target_version "1.2.3.4") else() set(target_version "1.2.3") endif() -# special case end -qt_add_test(tst_qguiapplication - VERSION ${target_version} # special case +# Resources: +set(tst_qguiapplication_resource_files + "icons/appicon.png" + "icons/usericon.png" +) + +qt_internal_add_test(tst_qguiapplication + VERSION ${target_version} SOURCES - ../../../corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp ../../../corelib/kernel/qcoreapplication/tst_qcoreapplication.h # special case + ../../../corelib/kernel/qcoreapplication/tst_qcoreapplication.cpp ../../../corelib/kernel/qcoreapplication/tst_qcoreapplication.h tst_qguiapplication.cpp DEFINES - QT_DISABLE_DEPRECATED_BEFORE=0x050E00 + QT_QGUIAPPLICATIONTEST=1 INCLUDE_DIRECTORIES ../../../corelib/kernel/qcoreapplication - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::GuiPrivate + TESTDATA ${tst_qguiapplication_resource_files} + BUILTIN_TESTDATA ) -# Resources: -set(tst_qguiapplication_resource_files - "icons/appicon.png" - "icons/usericon.png" -) - -qt_add_resource(tst_qguiapplication "tst_qguiapplication" - PREFIX - "/" - FILES - ${tst_qguiapplication_resource_files} -) - -# special case begin +if (ANDROID) + set_property(TARGET tst_qguiapplication PROPERTY QT_ANDROID_VERSION_NAME ${target_version}) +endif() if (APPLE) set_property(TARGET tst_qguiapplication PROPERTY MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist") set_property(TARGET tst_qguiapplication PROPERTY PROPERTY MACOSX_BUNDLE TRUE) endif() -# special case end - -## Scopes: -##################################################################### - -#### Keys ignored in scope 3:.:../../../corelib/kernel/qcoreapplication:../../../corelib/kernel/qcoreapplication/qcoreapplication.pro:WIN32: -# VERSION = "1.2.3.4" - -#### Keys ignored in scope 4:.:../../../corelib/kernel/qcoreapplication:../../../corelib/kernel/qcoreapplication/qcoreapplication.pro:else: -# VERSION = "1.2.3" diff --git a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro b/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro deleted file mode 100644 index 34b75a8397..0000000000 --- a/tests/auto/gui/kernel/qguiapplication/qguiapplication.pro +++ /dev/null @@ -1,12 +0,0 @@ -CORE_TEST_PATH = ../../../corelib/kernel/qcoreapplication - -VPATH += $$CORE_TEST_PATH -include($${CORE_TEST_PATH}/qcoreapplication.pro) -INCLUDEPATH += $$CORE_TEST_PATH - -TARGET = tst_qguiapplication -QT += gui-private -DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050E00 -SOURCES += tst_qguiapplication.cpp - -RESOURCES = tst_qguiapplication.qrc diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp index b68f00ea46..d1a50e3d69 100644 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp +++ b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.cpp @@ -1,33 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> +#include <QSignalSpy> #include <QtGui/QGuiApplication> #include <QtGui/QWindow> #include <QtGui/QScreen> @@ -71,11 +47,13 @@ private slots: void changeFocusWindow(); void keyboardModifiers(); void palette(); + void paletteNoCrash(); void font(); void modalWindow(); void quitOnLastWindowClosed(); void quitOnLastWindowClosedMulti(); void dontQuitOnLastWindowClosed(); + void quitOnLastWindowClosedWithEventLoopLocker(); void genericPluginsAndWindowSystemEvents(); void layoutDirection(); void globalShareContext(); @@ -83,6 +61,8 @@ private slots: void staticFunctions(); + void topLevelAt(); + void settableStyleHints_data(); void settableStyleHints(); // Needs to run last as it changes style hints. }; @@ -121,20 +101,20 @@ void tst_QGuiApplication::displayName() QGuiApplication::setApplicationName("The Core Application"); QCOMPARE(QGuiApplication::applicationName(), QString::fromLatin1("The Core Application")); QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The Core Application")); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QGuiApplication::setApplicationDisplayName("The GUI Application"); QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The GUI Application")); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QGuiApplication::setApplicationName("The Core Application 2"); QCOMPARE(QGuiApplication::applicationName(), QString::fromLatin1("The Core Application 2")); QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The GUI Application")); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); QGuiApplication::setApplicationDisplayName("The GUI Application 2"); QCOMPARE(QGuiApplication::applicationDisplayName(), QString::fromLatin1("The GUI Application 2")); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); } void tst_QGuiApplication::desktopFileName() @@ -145,8 +125,8 @@ void tst_QGuiApplication::desktopFileName() QCOMPARE(QGuiApplication::desktopFileName(), QString()); - QGuiApplication::setDesktopFileName("io.qt.QGuiApplication.desktop"); - QCOMPARE(QGuiApplication::desktopFileName(), QString::fromLatin1("io.qt.QGuiApplication.desktop")); + QGuiApplication::setDesktopFileName("io.qt.QGuiApplication"); + QCOMPARE(QGuiApplication::desktopFileName(), QString::fromLatin1("io.qt.QGuiApplication")); QGuiApplication::setDesktopFileName(QString()); QCOMPARE(QGuiApplication::desktopFileName(), QString()); @@ -245,12 +225,12 @@ void tst_QGuiApplication::focusObject() window1.setFocusObject(&obj1); QCOMPARE(app.focusObject(), &obj1); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); window1.setFocusObject(&obj2); QCOMPARE(app.focusObject(), &obj2); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); window2.setFocusObject(&obj3); @@ -259,12 +239,12 @@ void tst_QGuiApplication::focusObject() QVERIFY(QTest::qWaitForWindowExposed(&window2)); QTRY_COMPARE(app.focusWindow(), &window2); QCOMPARE(app.focusObject(), &obj3); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); // focus change on unfocused window does not show spy.clear(); window1.setFocusObject(&obj1); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); QCOMPARE(app.focusObject(), &obj3); } @@ -276,13 +256,13 @@ void tst_QGuiApplication::allWindows() QWindow *window2 = new QWindow(window1); QVERIFY(app.allWindows().contains(window1)); QVERIFY(app.allWindows().contains(window2)); - QCOMPARE(app.allWindows().count(), 2); + QCOMPARE(app.allWindows().size(), 2); delete window1; window1 = nullptr; window2 = nullptr; QVERIFY(!app.allWindows().contains(window2)); QVERIFY(!app.allWindows().contains(window1)); - QCOMPARE(app.allWindows().count(), 0); + QCOMPARE(app.allWindows().size(), 0); } void tst_QGuiApplication::topLevelWindows() @@ -293,13 +273,13 @@ void tst_QGuiApplication::topLevelWindows() QWindow *window2 = new QWindow(window1); QVERIFY(app.topLevelWindows().contains(window1)); QVERIFY(!app.topLevelWindows().contains(window2)); - QCOMPARE(app.topLevelWindows().count(), 1); + QCOMPARE(app.topLevelWindows().size(), 1); delete window1; window1 = nullptr; window2 = nullptr; QVERIFY(!app.topLevelWindows().contains(window2)); QVERIFY(!app.topLevelWindows().contains(window1)); - QCOMPARE(app.topLevelWindows().count(), 0); + QCOMPARE(app.topLevelWindows().size(), 0); } class ShowCloseShowWindow : public QWindow @@ -480,16 +460,12 @@ void tst_QGuiApplication::keyboardModifiers() QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier); // wheel events - QPoint global = window->mapToGlobal(center); QPoint delta(0, 1); - QWindowSystemInterface::handleWheelEvent(window.data(), center, global, delta, delta, Qt::NoModifier); - QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents); + QTest::wheelEvent(window.data(), center, delta, delta, Qt::NoModifier); QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::NoModifier); - QWindowSystemInterface::handleWheelEvent(window.data(), center, global, delta, delta, Qt::AltModifier); - QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents); + QTest::wheelEvent(window.data(), center, delta, delta, Qt::AltModifier); QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::AltModifier); - QWindowSystemInterface::handleWheelEvent(window.data(), center, global, delta, delta, Qt::ControlModifier); - QWindowSystemInterface::sendWindowSystemEvents(QEventLoop::AllEvents); + QTest::wheelEvent(window.data(), center, delta, delta, Qt::ControlModifier); QCOMPARE(QGuiApplication::keyboardModifiers(), Qt::ControlModifier); // touch events @@ -543,52 +519,78 @@ void tst_QGuiApplication::palette() // The default application palette is not resolved QVERIFY(!QGuiApplication::palette().resolveMask()); + // TODO: add event processing instead of the signal +#if QT_DEPRECATED_SINCE(6, 0) QSignalSpy signalSpy(&app, SIGNAL(paletteChanged(QPalette))); +#endif QPalette oldPalette = QGuiApplication::palette(); QPalette newPalette = QPalette(Qt::red); QGuiApplication::setPalette(newPalette); QVERIFY(palettesMatch(QGuiApplication::palette(), newPalette)); - QCOMPARE(signalSpy.count(), 1); +#if QT_DEPRECATED_SINCE(6, 0) + QCOMPARE(signalSpy.size(), 1); QVERIFY(palettesMatch(signalSpy.at(0).at(0).value<QPalette>(), newPalette)); +#endif QCOMPARE(QGuiApplication::palette(), QPalette()); QGuiApplication::setPalette(oldPalette); QVERIFY(palettesMatch(QGuiApplication::palette(), oldPalette)); - QCOMPARE(signalSpy.count(), 2); +#if QT_DEPRECATED_SINCE(6, 0) + QCOMPARE(signalSpy.size(), 2); QVERIFY(palettesMatch(signalSpy.at(1).at(0).value<QPalette>(), oldPalette)); +#endif QCOMPARE(QGuiApplication::palette(), QPalette()); QGuiApplication::setPalette(oldPalette); QVERIFY(palettesMatch(QGuiApplication::palette(), oldPalette)); - QCOMPARE(signalSpy.count(), 2); +#if QT_DEPRECATED_SINCE(6, 0) + QCOMPARE(signalSpy.size(), 2); +#endif QCOMPARE(QGuiApplication::palette(), QPalette()); } +void tst_QGuiApplication::paletteNoCrash() +{ + QGuiApplication::setDesktopSettingsAware(false); + int argc = 1; + char *argv[] = { const_cast<char*>("tst_qguiapplication") }; + // this would crash on windows (QTBUG-111527) + QGuiApplication a(argc, argv); +} + void tst_QGuiApplication::font() { int argc = 1; char *argv[] = { const_cast<char*>("tst_qguiapplication") }; QGuiApplication app(argc, argv); +#if QT_DEPRECATED_SINCE(6, 0) QSignalSpy signalSpy(&app, SIGNAL(fontChanged(QFont))); +#endif QFont oldFont = QGuiApplication::font(); QFont newFont = QFont("BogusFont", 33); QGuiApplication::setFont(newFont); QCOMPARE(QGuiApplication::font(), newFont); - QCOMPARE(signalSpy.count(), 1); +#if QT_DEPRECATED_SINCE(6, 0) + QCOMPARE(signalSpy.size(), 1); QCOMPARE(signalSpy.at(0).at(0), QVariant(newFont)); +#endif QGuiApplication::setFont(oldFont); QCOMPARE(QGuiApplication::font(), oldFont); - QCOMPARE(signalSpy.count(), 2); +#if QT_DEPRECATED_SINCE(6, 0) + QCOMPARE(signalSpy.size(), 2); QCOMPARE(signalSpy.at(1).at(0), QVariant(oldFont)); +#endif QGuiApplication::setFont(oldFont); QCOMPARE(QGuiApplication::font(), oldFont); - QCOMPARE(signalSpy.count(), 2); +#if QT_DEPRECATED_SINCE(6, 0) + QCOMPARE(signalSpy.size(), 2); +#endif } class BlockableWindow : public QWindow @@ -893,9 +895,9 @@ void tst_QGuiApplication::quitOnLastWindowClosed() app.exec(); - QCOMPARE(spyAboutToQuit.count(), 1); + QCOMPARE(spyAboutToQuit.size(), 1); // Should be around 10 if closing caused the quit - QVERIFY2(spyTimeout.count() < 15, QByteArray::number(spyTimeout.count()).constData()); + QVERIFY2(spyTimeout.size() < 15, QByteArray::number(spyTimeout.size()).constData()); } void tst_QGuiApplication::quitOnLastWindowClosedMulti() @@ -904,11 +906,7 @@ void tst_QGuiApplication::quitOnLastWindowClosedMulti() QGuiApplication app(argc, nullptr); const QRect screenGeometry = QGuiApplication::primaryScreen()->availableVirtualGeometry(); - QTimer timer; - timer.setInterval(100); - QSignalSpy spyAboutToQuit(&app, &QCoreApplication::aboutToQuit); - QSignalSpy spyTimeout(&timer, &QTimer::timeout); QWindow mainWindow; mainWindow.setTitle(QStringLiteral("quitOnLastWindowClosedMultiMainWindow")); @@ -927,15 +925,20 @@ void tst_QGuiApplication::quitOnLastWindowClosedMulti() dialog.show(); QVERIFY(QTest::qWaitForWindowExposed(&dialog)); - timer.start(); - QTimer::singleShot(1000, &mainWindow, &QWindow::close); // This should not quit the application - QTimer::singleShot(2000, &app, &QCoreApplication::quit); + bool prematureQuit = true; + QTimer::singleShot(100, &mainWindow, [&]{ + prematureQuit = true; // this should be reset by the other timer + mainWindow.close(); + }); + QTimer::singleShot(500, &mainWindow, [&]{ + prematureQuit = false; // if we don't get here, then the app quit prematurely + dialog.close(); + }); app.exec(); - QCOMPARE(spyAboutToQuit.count(), 1); - // Should be around 20 if closing did not cause the quit - QVERIFY2(spyTimeout.count() > 15, QByteArray::number(spyTimeout.count()).constData()); + QVERIFY(!prematureQuit); + QCOMPARE(spyAboutToQuit.size(), 1); // fired only once } void tst_QGuiApplication::dontQuitOnLastWindowClosed() @@ -963,8 +966,155 @@ void tst_QGuiApplication::dontQuitOnLastWindowClosed() app.setQuitOnLastWindowClosed(true); // restore underlying static to default value - QCOMPARE(spyTimeout.count(), 1); // quit timer fired - QCOMPARE(spyLastWindowClosed.count(), 1); // lastWindowClosed emitted + QCOMPARE(spyTimeout.size(), 1); // quit timer fired + QCOMPARE(spyLastWindowClosed.size(), 1); // lastWindowClosed emitted +} + +class QuitSpy : public QObject +{ + Q_OBJECT +public: + QuitSpy() + { + qGuiApp->installEventFilter(this); + } + bool eventFilter(QObject *o, QEvent *e) override + { + Q_UNUSED(o); + if (e->type() == QEvent::Quit) + ++quits; + + return false; + } + + int quits = 0; +}; + +void tst_QGuiApplication::quitOnLastWindowClosedWithEventLoopLocker() +{ + int argc = 0; + QGuiApplication app(argc, nullptr); + + QVERIFY(app.quitOnLastWindowClosed()); + QVERIFY(app.isQuitLockEnabled()); + + auto defaultRestorer = qScopeGuard([&]{ + app.setQuitLockEnabled(true); + app.setQuitOnLastWindowClosed(true); + }); + + { + // Disabling QEventLoopLocker automatic quit should not affect + // quitting when last window is closed if there are no lockers. + app.setQuitLockEnabled(false); + + QuitSpy quitSpy; + QWindow window; + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTimer::singleShot(0, &window, &QWindow::close); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 1); + } + + { + // Disabling QEventLoopLocker automatic quit should still block + // quitting when last window is closed if there is a locker alive. + app.setQuitLockEnabled(false); + + QScopedPointer<QEventLoopLocker> locker(new QEventLoopLocker); + + QuitSpy quitSpy; + QWindow window; + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTimer::singleShot(0, &window, &QWindow::close); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 0); + } + + { + // Disabling quitOnLastWindowClosed automatic quit should not affect + // quitting when last QEventLoopLocker goes out of scope if + // there are no windows. + app.setQuitLockEnabled(true); + app.setQuitOnLastWindowClosed(false); + + QuitSpy quitSpy; + QScopedPointer<QEventLoopLocker> locker(new QEventLoopLocker); + QTimer::singleShot(0, [&]{ locker.reset(nullptr); }); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 1); + } + + { + // Disabling quitOnLastWindowClosed automatic quit should still block + // quitting via QEventLoopLocker if there's a window alive. + app.setQuitLockEnabled(true); + app.setQuitOnLastWindowClosed(false); + + QuitSpy quitSpy; + QScopedPointer<QEventLoopLocker> locker(new QEventLoopLocker); + QWindow window; + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTimer::singleShot(0, [&]{ locker.reset(nullptr); }); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 0); + } + + { + // With both properties enabled we need to get rid of both + // the window and locker to trigger a quit. + app.setQuitLockEnabled(true); + app.setQuitOnLastWindowClosed(true); + + QuitSpy quitSpy; + QScopedPointer<QEventLoopLocker> locker(new QEventLoopLocker); + QWindow window; + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTimer::singleShot(0, &window, &QWindow::close); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 0); + + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTimer::singleShot(0, [&]{ locker.reset(nullptr); }); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 0); + + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTimer::singleShot(0, [&]{ locker.reset(nullptr); }); + QTimer::singleShot(0, &window, &QWindow::close); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 1); + } + + { + // With neither properties enabled we don't get automatic quit. + app.setQuitLockEnabled(false); + app.setQuitOnLastWindowClosed(false); + + QuitSpy quitSpy; + QScopedPointer<QEventLoopLocker> locker(new QEventLoopLocker); + QWindow window; + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTimer::singleShot(0, [&]{ locker.reset(nullptr); }); + QTimer::singleShot(0, &window, &QWindow::close); + QTimer::singleShot(200, &app, []{ QCoreApplication::exit(0); }); + app.exec(); + QCOMPARE(quitSpy.quits, 0); + } } static Qt::ScreenOrientation testOrientationToSend = Qt::PrimaryOrientation; @@ -1019,13 +1169,7 @@ void tst_QGuiApplication::genericPluginsAndWindowSystemEvents() QCoreApplication::postEvent(&testReceiver, new QEvent(QEvent::User)); QCOMPARE(testReceiver.customEvents, 0); -#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) - QStaticPlugin testPluginInfo(qt_plugin_instance, qt_plugin_query_metadata); -#else - QStaticPlugin testPluginInfo; - testPluginInfo.instance = qt_plugin_instance; - testPluginInfo.rawMetaData = qt_plugin_query_metadata; -#endif + QStaticPlugin testPluginInfo(qt_plugin_instance, qt_plugin_query_metadata_v2); qRegisterStaticPluginFunction(testPluginInfo); int argc = 3; char *argv[] = { const_cast<char*>(QTest::currentAppName()), const_cast<char*>("-plugin"), const_cast<char*>("testplugin") }; @@ -1044,8 +1188,8 @@ void tst_QGuiApplication::layoutDirection() { qRegisterMetaType<Qt::LayoutDirection>(); - Qt::LayoutDirection oldDirection = QGuiApplication::layoutDirection(); - Qt::LayoutDirection newDirection = oldDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight; + const Qt::LayoutDirection oldDirection = QGuiApplication::layoutDirection(); + const Qt::LayoutDirection newDirection = oldDirection == Qt::LeftToRight ? Qt::RightToLeft : Qt::LeftToRight; QGuiApplication::setLayoutDirection(newDirection); QCOMPARE(QGuiApplication::layoutDirection(), newDirection); @@ -1057,14 +1201,70 @@ void tst_QGuiApplication::layoutDirection() QGuiApplication::setLayoutDirection(oldDirection); QCOMPARE(QGuiApplication::layoutDirection(), oldDirection); - QCOMPARE(signalSpy.count(), 1); + QCOMPARE(signalSpy.size(), 1); QCOMPARE(signalSpy.at(0).at(0).toInt(), static_cast<int>(oldDirection)); QGuiApplication::setLayoutDirection(oldDirection); QCOMPARE(QGuiApplication::layoutDirection(), oldDirection); - QCOMPARE(signalSpy.count(), 1); + QCOMPARE(signalSpy.size(), 1); + + // with QGuiApplication instantiated, install a translator that gives us control + class LayoutDirectionTranslator : public QTranslator + { + public: + LayoutDirectionTranslator(Qt::LayoutDirection direction) + : direction(direction) + {} + + bool isEmpty() const override { return false; } + QString translate(const char *context, const char *sourceText, const char *disambiguation, int n) const override + { + if (QByteArrayView(sourceText) == "QT_LAYOUT_DIRECTION") + return direction == Qt::LeftToRight ? QLatin1String("LTR") : QLatin1String("RTL"); + return QTranslator::translate(context, sourceText, disambiguation, n); + } + + const Qt::LayoutDirection direction; + }; + + int layoutDirectionChangedCount = 0; + // reset to auto-detection, should be back to oldDirection now + QGuiApplication::setLayoutDirection(Qt::LayoutDirectionAuto); + QCOMPARE(QGuiApplication::layoutDirection(), oldDirection); + signalSpy.clear(); + { + // this translator doesn't change the direction + LayoutDirectionTranslator translator(oldDirection); + QGuiApplication::installTranslator(&translator); + QCOMPARE(QGuiApplication::layoutDirection(), translator.direction); + QCOMPARE(signalSpy.size(), layoutDirectionChangedCount); + } + QCOMPARE(signalSpy.size(), layoutDirectionChangedCount); // ltrTranslator removed, no change + + // install a new translator that changes the direction + { + LayoutDirectionTranslator translator(newDirection); + QGuiApplication::installTranslator(&translator); + QCOMPARE(QGuiApplication::layoutDirection(), translator.direction); + QCOMPARE(signalSpy.size(), ++layoutDirectionChangedCount); + } + // rtlTranslator removed + QCOMPARE(signalSpy.size(), ++layoutDirectionChangedCount); + + // override translation + QGuiApplication::setLayoutDirection(newDirection); + QCOMPARE(signalSpy.size(), ++layoutDirectionChangedCount); + { + // this translator will be ignored + LayoutDirectionTranslator translator(oldDirection); + QGuiApplication::installTranslator(&translator); + QCOMPARE(QGuiApplication::layoutDirection(), newDirection); + QCOMPARE(signalSpy.size(), layoutDirectionChangedCount); + } + QCOMPARE(signalSpy.size(), layoutDirectionChangedCount); } + void tst_QGuiApplication::globalShareContext() { #ifndef QT_NO_OPENGL @@ -1119,16 +1319,23 @@ void tst_QGuiApplication::staticFunctions() QGuiApplication::setWindowIcon(QIcon()); QGuiApplication::windowIcon(); QGuiApplication::platformName(); + QTest::ignoreMessage(QtWarningMsg, "Must construct a QGuiApplication first."); QGuiApplication::modalWindow(); QGuiApplication::focusWindow(); QGuiApplication::focusObject(); QGuiApplication::primaryScreen(); QGuiApplication::screens(); + QTest::ignoreMessage(QtWarningMsg, "Must construct a QGuiApplication first."); QGuiApplication::overrideCursor(); + QTest::ignoreMessage(QtWarningMsg, "Must construct a QGuiApplication first."); QGuiApplication::setOverrideCursor(QCursor()); + QTest::ignoreMessage(QtWarningMsg, "Must construct a QGuiApplication first."); QGuiApplication::changeOverrideCursor(QCursor()); + QTest::ignoreMessage(QtWarningMsg, "Must construct a QGuiApplication first."); QGuiApplication::restoreOverrideCursor(); + QTest::ignoreMessage(QtWarningMsg, "Must construct a QGuiApplication first."); QGuiApplication::keyboardModifiers(); + QTest::ignoreMessage(QtWarningMsg, "Must construct a QGuiApplication first."); QGuiApplication::queryKeyboardModifiers(); QGuiApplication::mouseButtons(); QGuiApplication::setLayoutDirection(Qt::LeftToRight); @@ -1138,14 +1345,50 @@ void tst_QGuiApplication::staticFunctions() QGuiApplication::desktopSettingsAware(); QGuiApplication::inputMethod(); QGuiApplication::platformNativeInterface(); + QTest::ignoreMessage(QtWarningMsg, "QGuiApplication::platformFunction(): Must construct a QGuiApplication before accessing a platform function"); QGuiApplication::platformFunction(QByteArrayLiteral("bla")); QGuiApplication::setQuitOnLastWindowClosed(true); QGuiApplication::quitOnLastWindowClosed(); QGuiApplication::applicationState(); + QTest::ignoreMessage(QtWarningMsg, "QPixmap: QGuiApplication must be created before calling defaultDepth()."); QPixmap::defaultDepth(); } +void tst_QGuiApplication::topLevelAt() +{ + int argc = 1; + char *argv[] = { const_cast<char*>("tst_qguiapplication") }; + QGuiApplication app(argc, argv); + + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("QGuiApplication::topLevelAt() is not Wayland compliant, see also QTBUG-121015"); + + QWindow bottom; + bottom.setObjectName("Bottom"); + bottom.setFlag(Qt::FramelessWindowHint); + bottom.setGeometry(200, 200, 200, 200); + bottom.showNormal(); + QVERIFY(QTest::qWaitForWindowExposed(&bottom)); + QTRY_COMPARE(app.topLevelAt(QPoint(300, 300)), &bottom); + + QWindow top; + top.setObjectName("Top"); + top.setFlag(Qt::FramelessWindowHint); + top.setGeometry(200, 200, 200, 200); + top.showNormal(); + QVERIFY(QTest::qWaitForWindowExposed(&top)); + top.raise(); + QTRY_COMPARE(app.topLevelAt(QPoint(300, 300)), &top); + + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowMasks)) + QSKIP("QWindow::setMask() is not supported."); + + top.setMask(QRect(0, 0, 50, 50)); + QTRY_COMPARE(app.topLevelAt(QPoint(300, 300)), &bottom); + QTRY_COMPARE(app.topLevelAt(QPoint(225, 225)), &top); +} + void tst_QGuiApplication::settableStyleHints_data() { QTest::addColumn<bool>("appInstance"); diff --git a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.qrc b/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.qrc deleted file mode 100644 index b26fba37b9..0000000000 --- a/tests/auto/gui/kernel/qguiapplication/tst_qguiapplication.qrc +++ /dev/null @@ -1,6 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource prefix="/"> - <file>icons/usericon.png</file> - <file>icons/appicon.png</file> -</qresource> -</RCC> diff --git a/tests/auto/gui/kernel/qguichronotimer/CMakeLists.txt b/tests/auto/gui/kernel/qguichronotimer/CMakeLists.txt new file mode 100644 index 0000000000..37848d8cec --- /dev/null +++ b/tests/auto/gui/kernel/qguichronotimer/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qguichronotimer Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qguichronotimer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +function(addGuiChronoTimerTest test) + qt_internal_add_test(${test} + SOURCES + ../../../corelib/kernel/qchronotimer/tst_qchronotimer.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::TestPrivate + ) +endfunction() + +addGuiChronoTimerTest(tst_qguichronotimer) +qt_internal_extend_target(tst_qguichronotimer + DEFINES + tst_Qtimer=tst_QGuiChronoTimer +) + +if(QT_FEATURE_glib AND UNIX) + addGuiChronoTimerTest(tst_qguichronotimer_no_glib) + qt_internal_extend_target(tst_qguichronotimer_no_glib + DEFINES + DISABLE_GLIB + tst_QTimer=tst_QGuiChronoTimer_no_glib # Class name in the unittest + ) +endif() diff --git a/tests/auto/gui/kernel/qguieventdispatcher/CMakeLists.txt b/tests/auto/gui/kernel/qguieventdispatcher/CMakeLists.txt index 14babc165c..62299f77df 100644 --- a/tests/auto/gui/kernel/qguieventdispatcher/CMakeLists.txt +++ b/tests/auto/gui/kernel/qguieventdispatcher/CMakeLists.txt @@ -1,12 +1,40 @@ -# Generated from qguieventdispatcher.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qguieventdispatcher Test: ##################################################################### -qt_add_test(tst_qguieventdispatcher - SOURCES - ../../../corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp - PUBLIC_LIBRARIES - Qt::Gui +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qguieventdispatcher LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +set(test_names "tst_qguieventdispatcher") +if(QT_FEATURE_glib AND UNIX) + list(APPEND test_names "tst_qguieventdispatcher_no_glib") +endif() + +foreach(test ${test_names}) + qt_internal_add_test(${test} + NO_BATCH + SOURCES + ../../../corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp + LIBRARIES + Qt::Gui + ) +endforeach() + +qt_internal_extend_target(tst_qguieventdispatcher + DEFINES + tst_QEventDispatcher=tst_qguieventdispatcher ) + +if (TARGET tst_qeventdispatcher_no_glib) + qt_internal_extend_target(tst_qguieventdispatcher_no_glib + DEFINES + DISABLE_GLIB + tst_QEventDispatcher=tst_qguieventdispatcher_no_glib + ) +endif() diff --git a/tests/auto/gui/kernel/qguieventdispatcher/qguieventdispatcher.pro b/tests/auto/gui/kernel/qguieventdispatcher/qguieventdispatcher.pro deleted file mode 100644 index 3057037e74..0000000000 --- a/tests/auto/gui/kernel/qguieventdispatcher/qguieventdispatcher.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qguieventdispatcher -QT = core gui testlib -SOURCES += ../../../corelib/kernel/qeventdispatcher/tst_qeventdispatcher.cpp diff --git a/tests/auto/gui/kernel/qguieventloop/.prev_CMakeLists.txt b/tests/auto/gui/kernel/qguieventloop/.prev_CMakeLists.txt deleted file mode 100644 index 7fb82219a9..0000000000 --- a/tests/auto/gui/kernel/qguieventloop/.prev_CMakeLists.txt +++ /dev/null @@ -1,28 +0,0 @@ -# Generated from qguieventloop.pro. - -##################################################################### -## tst_qguieventloop Test: -##################################################################### - -add_qt_test(tst_qguieventloop - SOURCES - ../../../corelib/kernel/qeventloop/tst_qeventloop.cpp - LIBRARIES - Qt::CorePrivate - PUBLIC_LIBRARIES - Qt::Gui - Qt::Network -) - -## Scopes: -##################################################################### - -extend_target(tst_qguieventloop CONDITION WIN32 - PUBLIC_LIBRARIES - user32 -) - -extend_target(tst_qguieventloop CONDITION QT_FEATURE_glib - DEFINES - HAVE_GLIB -) diff --git a/tests/auto/gui/kernel/qguieventloop/CMakeLists.txt b/tests/auto/gui/kernel/qguieventloop/CMakeLists.txt index 8d62d716a5..89c518be10 100644 --- a/tests/auto/gui/kernel/qguieventloop/CMakeLists.txt +++ b/tests/auto/gui/kernel/qguieventloop/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qguieventloop.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qguieventloop Test: ##################################################################### -qt_add_test(tst_qguieventloop +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qguieventloop LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qguieventloop SOURCES ../../../corelib/kernel/qeventloop/tst_qeventloop.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::Network @@ -16,12 +23,12 @@ qt_add_test(tst_qguieventloop ## Scopes: ##################################################################### -qt_extend_target(tst_qguieventloop CONDITION WIN32 - PUBLIC_LIBRARIES +qt_internal_extend_target(tst_qguieventloop CONDITION WIN32 + LIBRARIES user32 ) -qt_extend_target(tst_qguieventloop CONDITION QT_FEATURE_glib +qt_internal_extend_target(tst_qguieventloop CONDITION QT_FEATURE_glib DEFINES HAVE_GLIB ) diff --git a/tests/auto/gui/kernel/qguieventloop/qguieventloop.pro b/tests/auto/gui/kernel/qguieventloop/qguieventloop.pro deleted file mode 100644 index 633386fa75..0000000000 --- a/tests/auto/gui/kernel/qguieventloop/qguieventloop.pro +++ /dev/null @@ -1,3 +0,0 @@ -include(../../../corelib/kernel/qeventloop/qeventloop.pro) -TARGET = tst_qguieventloop -QT += gui diff --git a/tests/auto/gui/kernel/qguimetatype/CMakeLists.txt b/tests/auto/gui/kernel/qguimetatype/CMakeLists.txt index d124b08828..7c93e4b8a2 100644 --- a/tests/auto/gui/kernel/qguimetatype/CMakeLists.txt +++ b/tests/auto/gui/kernel/qguimetatype/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qguimetatype.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qguimetatype Test: ##################################################################### -qt_add_test(tst_qguimetatype +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qguimetatype LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qguimetatype SOURCES tst_qguimetatype.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qguimetatype/qguimetatype.pro b/tests/auto/gui/kernel/qguimetatype/qguimetatype.pro deleted file mode 100644 index 331295bab9..0000000000 --- a/tests/auto/gui/kernel/qguimetatype/qguimetatype.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qguimetatype -SOURCES += tst_qguimetatype.cpp -QT = core gui testlib diff --git a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp index be34fa7639..54e95a2b38 100644 --- a/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp +++ b/tests/auto/gui/kernel/qguimetatype/tst_qguimetatype.cpp @@ -1,35 +1,10 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore> #include <QtGui> -#include <QtTest/QtTest> +#include <QTest> Q_DECLARE_METATYPE(QMetaType::Type) @@ -45,6 +20,8 @@ private slots: void sizeOf(); void flags_data(); void flags(); + void flags2_data(); + void flags2(); void construct_data(); void construct(); void constructCopy_data(); @@ -318,14 +295,27 @@ struct TypeAlignment enum { Value = alignof(T) }; }; +template <typename T> void addFlagsRow(const char *name, int id = qMetaTypeId<T>()) +{ + QTest::newRow(name) + << id + << bool(QTypeInfo<T>::isRelocatable) + << bool(!std::is_trivially_default_constructible_v<T>) + << bool(!std::is_trivially_copy_constructible_v<T>) + << bool(!std::is_trivially_destructible_v<T>); +} + +// tst_QGuiMetaType::flags is nearly identical to tst_QMetaType::flags void tst_QGuiMetaType::flags_data() { QTest::addColumn<int>("type"); QTest::addColumn<bool>("isRelocatable"); - QTest::addColumn<bool>("isComplex"); + QTest::addColumn<bool>("needsConstruction"); + QTest::addColumn<bool>("needsCopyConstruction"); + QTest::addColumn<bool>("needsDestruction"); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ - QTest::newRow(#RealType) << MetaTypeId << bool(QTypeInfo<RealType>::isRelocatable) << bool(QTypeInfo<RealType>::isComplex); + addFlagsRow<RealType>(#RealType, MetaTypeId); QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } @@ -334,13 +324,62 @@ void tst_QGuiMetaType::flags() { QFETCH(int, type); QFETCH(bool, isRelocatable); - QFETCH(bool, isComplex); + QFETCH(bool, needsConstruction); + QFETCH(bool, needsCopyConstruction); + QFETCH(bool, needsDestruction); + + QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsConstruction), needsConstruction); + QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsCopyConstruction), needsCopyConstruction); + QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsDestruction), needsDestruction); + QCOMPARE(bool(QMetaType(type).flags() & QMetaType::RelocatableType), isRelocatable); +} + +template <typename T> static void addFlags2Row(QMetaType metaType = QMetaType::fromType<T>()) +{ + QTest::newRow(metaType.name() ? metaType.name() : "UnknownType") + << metaType + << std::is_default_constructible_v<T> + << std::is_copy_constructible_v<T> + << std::is_move_constructible_v<T> + << std::is_destructible_v<T> + << (QTypeTraits::has_operator_equal<T>::value || QTypeTraits::has_operator_less_than<T>::value) + << QTypeTraits::has_operator_less_than<T>::value; +}; - QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsConstruction), isComplex); - QCOMPARE(bool(QMetaType(type).flags() & QMetaType::NeedsDestruction), isComplex); - QCOMPARE(bool(QMetaType(type).flags() & QMetaType::MovableType), isRelocatable); +// tst_QGuiMetaType::flags2 is nearly identical to tst_QMetaType::flags2 +void tst_QGuiMetaType::flags2_data() +{ + QTest::addColumn<QMetaType>("type"); + QTest::addColumn<bool>("isDefaultConstructible"); + QTest::addColumn<bool>("isCopyConstructible"); + QTest::addColumn<bool>("isMoveConstructible"); + QTest::addColumn<bool>("isDestructible"); + QTest::addColumn<bool>("isEqualityComparable"); + QTest::addColumn<bool>("isOrdered"); + +#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ + addFlags2Row<RealType>(); +QT_FOR_EACH_STATIC_GUI_CLASS(ADD_METATYPE_TEST_ROW) +#undef ADD_METATYPE_TEST_ROW } +void tst_QGuiMetaType::flags2() +{ + QFETCH(QMetaType, type); + QFETCH(bool, isDefaultConstructible); + QFETCH(bool, isCopyConstructible); + QFETCH(bool, isMoveConstructible); + QFETCH(bool, isDestructible); + QFETCH(bool, isEqualityComparable); + QFETCH(bool, isOrdered); + + QCOMPARE(type.isDefaultConstructible(), isDefaultConstructible); + QCOMPARE(type.isCopyConstructible(), isCopyConstructible); + QCOMPARE(type.isMoveConstructible(), isMoveConstructible); + QCOMPARE(type.isDestructible(), isDestructible); + QCOMPARE(type.isEqualityComparable(), isEqualityComparable); + QCOMPARE(type.isOrdered(), isOrdered); +} void tst_QGuiMetaType::construct_data() { diff --git a/tests/auto/gui/kernel/qguitimer/.prev_CMakeLists.txt b/tests/auto/gui/kernel/qguitimer/.prev_CMakeLists.txt deleted file mode 100644 index 8c2ec60bdf..0000000000 --- a/tests/auto/gui/kernel/qguitimer/.prev_CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -# Generated from qguitimer.pro. - -##################################################################### -## tst_qguitimer Test: -##################################################################### - -qt_add_test(tst_qguitimer - SOURCES - ../../../corelib/kernel/qtimer/tst_qtimer.cpp - PUBLIC_LIBRARIES - Qt::CorePrivate - Qt::Gui -) diff --git a/tests/auto/gui/kernel/qguitimer/CMakeLists.txt b/tests/auto/gui/kernel/qguitimer/CMakeLists.txt index 8c2ec60bdf..bc292e133b 100644 --- a/tests/auto/gui/kernel/qguitimer/CMakeLists.txt +++ b/tests/auto/gui/kernel/qguitimer/CMakeLists.txt @@ -1,13 +1,38 @@ -# Generated from qguitimer.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qguitimer Test: ##################################################################### -qt_add_test(tst_qguitimer - SOURCES - ../../../corelib/kernel/qtimer/tst_qtimer.cpp - PUBLIC_LIBRARIES - Qt::CorePrivate - Qt::Gui +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qguitimer LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +function(addGuiTimerTest test) + qt_internal_add_test(${test} + SOURCES + ../../../corelib/kernel/qtimer/tst_qtimer.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::TestPrivate + ) +endfunction() + +addGuiTimerTest(tst_qguitimer) +qt_internal_extend_target(tst_qguitimer + DEFINES + tst_Qtimer=tst_QGuiTimer ) + +if(QT_FEATURE_glib AND UNIX) + addGuiTimerTest(tst_qguitimer_no_glib) + qt_internal_extend_target(tst_qguitimer_no_glib + DEFINES + DISABLE_GLIB + tst_QTimer=tst_QGuiTimer_no_glib # Class name in the unittest + ) +endif() diff --git a/tests/auto/gui/kernel/qguitimer/qguitimer.pro b/tests/auto/gui/kernel/qguitimer/qguitimer.pro deleted file mode 100644 index 9c58f0e22c..0000000000 --- a/tests/auto/gui/kernel/qguitimer/qguitimer.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qguitimer -QT = core core-private gui testlib -SOURCES += ../../../corelib/kernel/qtimer/tst_qtimer.cpp diff --git a/tests/auto/gui/kernel/qguivariant/CMakeLists.txt b/tests/auto/gui/kernel/qguivariant/CMakeLists.txt index 3a0adab6e3..eda22152ec 100644 --- a/tests/auto/gui/kernel/qguivariant/CMakeLists.txt +++ b/tests/auto/gui/kernel/qguivariant/CMakeLists.txt @@ -1,4 +1,5 @@ -# Generated from qguivariant.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause add_subdirectory(test) add_subdirectory(no_application) diff --git a/tests/auto/gui/kernel/qguivariant/no_application/CMakeLists.txt b/tests/auto/gui/kernel/qguivariant/no_application/CMakeLists.txt index 344b81bf6d..4470411a3b 100644 --- a/tests/auto/gui/kernel/qguivariant/no_application/CMakeLists.txt +++ b/tests/auto/gui/kernel/qguivariant/no_application/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from no_application.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## no_application Test: ##################################################################### -qt_add_test(no_application +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_gui_variant_no_application LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_gui_variant_no_application SOURCES main.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qguivariant/no_application/main.cpp b/tests/auto/gui/kernel/qguivariant/no_application/main.cpp index 4a50c1f7da..2b6ec7b870 100644 --- a/tests/auto/gui/kernel/qguivariant/no_application/main.cpp +++ b/tests/auto/gui/kernel/qguivariant/no_application/main.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> #include <qvariant.h> diff --git a/tests/auto/gui/kernel/qguivariant/no_application/no_application.pro b/tests/auto/gui/kernel/qguivariant/no_application/no_application.pro deleted file mode 100644 index ada3817e55..0000000000 --- a/tests/auto/gui/kernel/qguivariant/no_application/no_application.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = no_application -SOURCES += main.cpp -QT += testlib diff --git a/tests/auto/gui/kernel/qguivariant/qguivariant.pro b/tests/auto/gui/kernel/qguivariant/qguivariant.pro deleted file mode 100644 index 115da945a5..0000000000 --- a/tests/auto/gui/kernel/qguivariant/qguivariant.pro +++ /dev/null @@ -1,2 +0,0 @@ -TEMPLATE = subdirs -SUBDIRS = test no_application diff --git a/tests/auto/gui/kernel/qguivariant/test/CMakeLists.txt b/tests/auto/gui/kernel/qguivariant/test/CMakeLists.txt index 40671c920c..36b732e4ae 100644 --- a/tests/auto/gui/kernel/qguivariant/test/CMakeLists.txt +++ b/tests/auto/gui/kernel/qguivariant/test/CMakeLists.txt @@ -1,27 +1,29 @@ -# Generated from test.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qguivariant Test: ##################################################################### -qt_add_test(tst_qguivariant +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qguivariant LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +# Resources: +file(GLOB_RECURSE qguivariant_resource_files + RELATIVE "${CMAKE_CURRENT_SOURCE_DIR}" + "data/*" +) + +qt_internal_add_test(tst_qguivariant SOURCES tst_qguivariant.cpp INCLUDE_DIRECTORIES ../../../../other/qvariant_common - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui + TESTDATA ${qguivariant_resource_files} + BUILTIN_TESTDATA ) - -# Resources: -set(qguivariant_resource_files - "data" -) - -qt_add_resource(tst_qguivariant "qguivariant" - PREFIX - "/" - FILES - ${qguivariant_resource_files} -) - diff --git a/tests/auto/gui/kernel/qguivariant/test/qguivariant.qrc b/tests/auto/gui/kernel/qguivariant/test/qguivariant.qrc deleted file mode 100644 index 576d9cda1c..0000000000 --- a/tests/auto/gui/kernel/qguivariant/test/qguivariant.qrc +++ /dev/null @@ -1,5 +0,0 @@ -<!DOCTYPE RCC><RCC version="1.0"> -<qresource> - <file>data</file> -</qresource> -</RCC> diff --git a/tests/auto/gui/kernel/qguivariant/test/test.pro b/tests/auto/gui/kernel/qguivariant/test/test.pro deleted file mode 100644 index e285001b07..0000000000 --- a/tests/auto/gui/kernel/qguivariant/test/test.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase -TARGET = tst_qguivariant -SOURCES += tst_qguivariant.cpp -INCLUDEPATH += $$PWD/../../../../other/qvariant_common -QT += testlib -RESOURCES += qguivariant.qrc diff --git a/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp b/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp index 382f17d519..cb22024f76 100644 --- a/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp +++ b/tests/auto/gui/kernel/qguivariant/test/tst_qguivariant.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> #include <qvariant.h> @@ -128,7 +103,7 @@ void tst_QGuiVariant::constructor_invalid() QFETCH(uint, typeId); { QTest::ignoreMessage(QtWarningMsg, QRegularExpression("^Trying to construct an instance of an invalid type, type id:")); - QVariant variant(static_cast<QVariant::Type>(typeId)); + QVariant variant{QMetaType(typeId)}; QVERIFY(!variant.isValid()); QCOMPARE(variant.userType(), int(QMetaType::UnknownType)); } @@ -245,7 +220,7 @@ void tst_QGuiVariant::toColor_data() QTest::newRow("qstring(#ff0000)") << QVariant(QString::fromUtf8("#ff0000")) << c; QTest::newRow("qbytearray(#ff0000)") << QVariant(QByteArray("#ff0000")) << c; - c.setNamedColor("#88112233"); + c = QColor::fromString("#88112233"); QTest::newRow("qstring(#88112233)") << QVariant(QString::fromUtf8("#88112233")) << c; QTest::newRow("qbytearray(#88112233)") << QVariant(QByteArray("#88112233")) << c; } @@ -334,7 +309,7 @@ void tst_QGuiVariant::toFont_data() QTest::addColumn<QFont>("result"); QFont f("times",12,-1,false); - QTest::newRow( "string" ) << QVariant( QString( "times,12,-1,5,400,0,0,0,0,0" ) ) << f; + QTest::newRow( "string" ) << QVariant( QString( "times,12,-1,5,50,0,0,0,0,0" ) ) << f; } void tst_QGuiVariant::toFont() @@ -353,12 +328,12 @@ void tst_QGuiVariant::toKeySequence_data() QTest::addColumn<QKeySequence>("result"); - QTest::newRow( "int" ) << QVariant( 67108929 ) << QKeySequence( Qt::CTRL + Qt::Key_A ); + QTest::newRow( "int" ) << QVariant( 67108929 ) << QKeySequence( Qt::CTRL | Qt::Key_A ); QTest::newRow( "qstring" ) << QVariant( QString( "Ctrl+A" ) ) - << QKeySequence( Qt::CTRL + Qt::Key_A ); + << QKeySequence( Qt::CTRL | Qt::Key_A ); } void tst_QGuiVariant::toKeySequence() @@ -376,7 +351,7 @@ void tst_QGuiVariant::toString_data() QTest::addColumn<QVariant>("value"); QTest::addColumn<QString>("result"); - QTest::newRow( "qkeysequence" ) << QVariant::fromValue( QKeySequence( Qt::CTRL + Qt::Key_A ) ) + QTest::newRow( "qkeysequence" ) << QVariant::fromValue( QKeySequence( Qt::CTRL | Qt::Key_A ) ) #ifndef Q_OS_MAC << QString( "Ctrl+A" ); #else @@ -499,7 +474,7 @@ void tst_QGuiVariant::writeToReadFromDataStream_data() pixmap.fill( Qt::red ); QTest::newRow( "pixmap_valid" ) << QVariant::fromValue( pixmap ) << false; QTest::newRow( "image_invalid" ) << QVariant::fromValue( QImage() ) << false; - QTest::newRow( "keysequence_valid" ) << QVariant::fromValue( QKeySequence( Qt::CTRL + Qt::Key_A ) ) << false; + QTest::newRow( "keysequence_valid" ) << QVariant::fromValue( QKeySequence( Qt::CTRL | Qt::Key_A ) ) << false; QTest::newRow( "palette_valid" ) << QVariant::fromValue(QPalette(QColor("turquoise"))) << false; QTest::newRow( "pen_valid" ) << QVariant::fromValue( QPen( Qt::red ) ) << false; QTest::newRow( "pointarray_invalid" ) << QVariant::fromValue( QPolygon() ) << false; @@ -567,8 +542,8 @@ void tst_QGuiVariant::writeToReadFromDataStream() // Since only a few won't match since the serial numbers are different // I won't bother adding another bool in the data test. const int writeType = writeVariant.userType(); - if ( writeType != QVariant::Invalid && writeType != QVariant::Bitmap && writeType != QVariant::Pixmap - && writeType != QVariant::Image) { + if ( writeType != QMetaType::UnknownType && writeType != QMetaType::QBitmap && writeType != QMetaType::QPixmap + && writeType != QMetaType::QImage) { switch (writeType) { default: QCOMPARE( readVariant, writeVariant ); @@ -655,7 +630,7 @@ void tst_QGuiVariant::debugStream_data() const char *tagName = QMetaType(id).name(); if (!tagName) continue; - QTest::newRow(tagName) << QVariant(static_cast<QVariant::Type>(id)) << id; + QTest::newRow(tagName) << QVariant(QMetaType(id)) << id; } } diff --git a/tests/auto/gui/kernel/qhighdpi/CMakeLists.txt b/tests/auto/gui/kernel/qhighdpi/CMakeLists.txt new file mode 100644 index 0000000000..aa61bfbb0b --- /dev/null +++ b/tests/auto/gui/kernel/qhighdpi/CMakeLists.txt @@ -0,0 +1,21 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +##################################################################### +## tst_qhighdpi Test: +##################################################################### + +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qhighdpi LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qhighdpi + SOURCES + tst_qhighdpi.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate +) diff --git a/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp b/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp new file mode 100644 index 0000000000..6fe4faec03 --- /dev/null +++ b/tests/auto/gui/kernel/qhighdpi/tst_qhighdpi.cpp @@ -0,0 +1,887 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <private/qhighdpiscaling_p.h> +#include <qpa/qplatformscreen.h> +#include <qpa/qplatformnativeinterface.h> + +#include <QTest> +#include <QJsonArray> +#include <QJsonObject> +#include <QJsonDocument> +#include <QStringView> +#include <QSignalSpy> + +Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests") + +class tst_QHighDpi: public QObject +{ + Q_OBJECT +private: // helpers + QJsonArray createStandardScreens(const QList<qreal> &dpiValues); + QGuiApplication *createOffscreenApplication(const QByteArray &jsonConfig); + QGuiApplication *createStandardOffscreenApp(const QList<qreal> &dpiValues); + QGuiApplication *createStandardOffscreenApp(const QJsonArray &screens); + static void standardScreenDpiTestData(); + + static void setOffscreenConfiguration(const QJsonObject &configuration); + static QJsonObject offscreenConfiguration(); + +private slots: + void cleanup(); + void qhighdpiscaling_data(); + void qhighdpiscaling(); + void minimumDpr(); + void noscreens(); + void screenDpiAndDpr_data(); + void screenDpiAndDpr(); + void screenDpiChange(); + void screenDpiChangeWithWindow(); + void environment_QT_SCALE_FACTOR(); + void environment_QT_SCREEN_SCALE_FACTORS_data(); + void environment_QT_SCREEN_SCALE_FACTORS(); + void environment_QT_USE_PHYSICAL_DPI(); + void environment_QT_SCALE_FACTOR_ROUNDING_POLICY(); + void application_setScaleFactorRoundingPolicy(); + void screenAt_data(); + void screenAt(); + void screenGeometry_data(); + void screenGeometry(); + void windowGeometry_data(); + void windowGeometry(); + void spanningWindows_data(); + void spanningWindows(); + void mouseEvents_data(); + void mouseEvents(); + void mouseVelocity(); + void mouseVelocity_data(); + void setCursor(); + void setCursor_data(); + void setGlobalFactorEmits(); + void setScreenFactorEmits(); +}; + +/// Offscreen platform plugin test setup +const int standardScreenWidth = 640; +const int standardScreenHeight = 480; +const int standardBaseDpi = 96; +const int standardScreenCount = 3; + +QJsonArray tst_QHighDpi::createStandardScreens(const QList<qreal> &dpiValues) +{ + Q_ASSERT(dpiValues.size() == standardScreenCount); + + // Create row of three screens: screen#0 screen#1 screen#2 + return QJsonArray { + QJsonObject { + {"name", "screen#0"}, + {"x", -standardScreenWidth}, + {"y", -10}, + {"width", standardScreenWidth}, + {"height", standardScreenHeight}, + {"logicalDpi", dpiValues[0]}, + {"logicalBaseDpi", standardBaseDpi}, + {"dpr", 1} + }, + QJsonObject { + {"name", "screen#1"}, + {"x", 0}, + {"y", 0}, + {"width", standardScreenWidth}, + {"height", standardScreenHeight}, + {"logicalDpi", dpiValues[1]}, + {"logicalBaseDpi", standardBaseDpi}, + {"dpr", 1} + }, + QJsonObject { + {"name", "screen#2"}, + {"x", standardScreenWidth}, + {"y", 10}, + {"width", standardScreenWidth}, + {"height", standardScreenHeight}, + {"logicalDpi", dpiValues[2]}, + {"logicalBaseDpi", standardBaseDpi}, + {"dpr", 1} + } + }; +} + +QGuiApplication *tst_QHighDpi::createOffscreenApplication(const QByteArray &jsonConfig) +{ + // Write offscreen platform config file + QFile configFile(QLatin1String("qt-offscreen-test-config.json")); + if (!configFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) + qFatal("Failed to open test config file: %s", qPrintable(configFile.errorString())); + configFile.resize(0); // truncate + if (configFile.write(jsonConfig) == -1) + qFatal("Could not write config file: %s", qPrintable(configFile.errorString())); + configFile.close(); + + // Create QGuiApplication which loads the offscreen platform plugin + // Note that argc and argv need to stay valid for the duration of the app lifetime, + // and may be used at any point. The config file used at app startup only. + static int argc; + argc = 3; + static char *argv[3]; + static QByteArray binaryNameArg = QByteArray("tst_qguiapplication"); + argv[0] = binaryNameArg.data(); + static QByteArray platformArg = QByteArray("-platform"); + argv[1] = platformArg.data(); + static QByteArray offscreenAndFileArg; + offscreenAndFileArg = QByteArray("offscreen:configfile=") + configFile.fileName().toUtf8(); + argv[2] = offscreenAndFileArg.data(); + + QGuiApplication *app = new QGuiApplication(argc, argv); + configFile.remove(); // config file is needed during QGuiApplication construction only. + return app; +} + +QGuiApplication *tst_QHighDpi::createStandardOffscreenApp(const QList<qreal> &dpiValues) +{ + QJsonArray screens = createStandardScreens(dpiValues); + return createStandardOffscreenApp(screens); +} + +QGuiApplication *tst_QHighDpi::createStandardOffscreenApp(const QJsonArray &screens) +{ + QJsonObject config { + {"synchronousWindowSystemEvents", true}, + {"windowFrameMargins", false}, + {"screens" , screens}, + }; + return createOffscreenApplication(QJsonDocument(config).toJson()); +} + +/// Auto test begins + +void tst_QHighDpi::standardScreenDpiTestData() +{ + // We run each test under different DPI configurations, each with three screens: + QTest::addColumn<QList<qreal>>("dpiValues"); + // Standard-DPI sanity check + QTest::newRow("96") << QList<qreal> { 96, 96, 96 }; + // 2x high DPI + QTest::newRow("192") << QList<qreal> { 192, 192, 192 }; + // Mixed desktop DPI (1.5x, 1.75x, 2x) + QTest::newRow("144-168-192") << QList<qreal> { 144, 168, 192 }; + // Densities from Android's DisplayMetrics docs, normalized to base 96 DPI + QTest::newRow("240-252-360") << QList<qreal> { 400./160 * 96, 420./160 * 96, 600./160 * 96 }; +} + +void tst_QHighDpi::setOffscreenConfiguration(const QJsonObject &configuration) +{ + Q_ASSERT(qApp->platformName() == QLatin1String("offscreen")); + QPlatformNativeInterface *platformNativeInterface = qApp->platformNativeInterface(); + auto setConfiguration = reinterpret_cast<void (*)(QJsonObject, QPlatformNativeInterface *)>( + platformNativeInterface->nativeResourceForIntegration("setConfiguration")); + setConfiguration(configuration, platformNativeInterface); +} + +QJsonObject tst_QHighDpi::offscreenConfiguration() +{ + Q_ASSERT(qApp->platformName() == QLatin1String("offscreen")); + QPlatformNativeInterface *platformNativeInterface = qApp->platformNativeInterface(); + auto getConfiguration = reinterpret_cast<QJsonObject (*)(QPlatformNativeInterface *)>( + platformNativeInterface->nativeResourceForIntegration("configuration")); + return getConfiguration(platformNativeInterface); +} + +void tst_QHighDpi::cleanup() +{ + // Some test functions set environment variables. Unset them here, + // in order to avoid getting confusing follow-on errors on test failures. + qunsetenv("QT_SCALE_FACTOR"); + qunsetenv("QT_SCREEN_SCALE_FACTORS"); + qunsetenv("QT_USE_PHYSICAL_DPI"); + qunsetenv("QT_SCALE_FACTOR_ROUNDING_POLICY"); +} + +void tst_QHighDpi::qhighdpiscaling_data() +{ + standardScreenDpiTestData(); +} + +// Tests the QHighDpiScaling API directly +void tst_QHighDpi::qhighdpiscaling() +{ + QFETCH(QList<qreal>, dpiValues); + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + QHighDpiScaling::setGlobalFactor(2); + + // Verfy that QHighDpiScaling::factor() does not crash on nullptr contexts. + QScreen *screenContext = nullptr; + QVERIFY(QHighDpiScaling::factor(screenContext) >= 0); + QPlatformScreen *platformScreenContext = nullptr; + QVERIFY(QHighDpiScaling::factor(platformScreenContext) >= 0); + QWindow *windowContext = nullptr; + QVERIFY(QHighDpiScaling::factor(windowContext) >= 0); + QHighDpiScaling::setGlobalFactor(1); +} + +void tst_QHighDpi::screenDpiAndDpr_data() +{ + standardScreenDpiTestData(); +} + +void tst_QHighDpi::screenDpiAndDpr() +{ + QFETCH(QList<qreal>, dpiValues); + + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + int i = 0; + for (QScreen *screen : app->screens()) { + qreal dpi = dpiValues[i++]; + + // verify that the devicePixelRatio equation holds: DPR = DPI / BaseDPI + QCOMPARE(screen->devicePixelRatio(), dpi / standardBaseDpi); + QCOMPARE(screen->logicalDotsPerInch(), dpi / screen->devicePixelRatio()); + + QWindow window(screen); + QCOMPARE(window.devicePixelRatio(), screen->devicePixelRatio()); + window.setGeometry(QRect(screen->geometry().center(), QSize(10, 10))); + window.create(); + QCOMPARE(window.devicePixelRatio(), screen->devicePixelRatio()); + } +} + +void tst_QHighDpi::screenDpiChange() +{ + QList<qreal> dpiValues = { 96, 96, 96}; + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + QCOMPARE(app->devicePixelRatio(), 1); + + // Set new DPI + int newDpi = 192; + QJsonValue config = offscreenConfiguration(); + // API defect until Qt 7, so go indirectly via CBOR + QCborMap map = QCborMap::fromJsonObject(config.toObject()); + map[QLatin1String("screens")][0][QLatin1String("logicalDpi")] = newDpi; + map[QLatin1String("screens")][1][QLatin1String("logicalDpi")] = newDpi; + map[QLatin1String("screens")][2][QLatin1String("logicalDpi")] = newDpi; + setOffscreenConfiguration(map.toJsonObject()); + + // TODO check events + + // Verify that the new DPI is in use + for (QScreen *screen : app->screens()) { + QCOMPARE(screen->devicePixelRatio(), newDpi / standardBaseDpi); + QCOMPARE(screen->logicalDotsPerInch(), newDpi / screen->devicePixelRatio()); + + QWindow window(screen); + QCOMPARE(window.devicePixelRatio(), screen->devicePixelRatio()); + window.create(); + QCOMPARE(window.devicePixelRatio(), screen->devicePixelRatio()); + } + QCOMPARE(app->devicePixelRatio(), newDpi / standardBaseDpi); +} + +void tst_QHighDpi::screenDpiChangeWithWindow() +{ + QList<qreal> dpiValues = { 96, 192, 288 }; + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + // Create windows for screens + QList<QScreen *> screens = app->screens(); + QList<QWindow *> windows; + for (int i = 0; i < screens.count(); ++i) { + QScreen *screen = screens[i]; + QWindow *window = new QWindow(); + windows.append(window); + window->setGeometry(QRect(screen->geometry().center(), QSize(10, 10))); + window->create(); + QCOMPARE(window->devicePixelRatio(), dpiValues[i] / standardBaseDpi); + } + + // Change screen DPI + QList<qreal> newDpiValues = { 288, 192, 96 }; + QJsonValue config = offscreenConfiguration(); + QCborMap map = QCborMap::fromJsonObject(config.toObject()); + for (int i = 0; i < screens.count(); ++i) { + map[QLatin1String("screens")][i][QLatin1String("logicalDpi")] = newDpiValues[i]; + } + setOffscreenConfiguration(map.toJsonObject()); + + // Verify that window DPR changes on Screen DPI change. + for (int i = 0; i < screens.count(); ++i) { + QWindow *window = windows[i]; + QCOMPARE(window->devicePixelRatio(), newDpiValues[i] / standardBaseDpi); + } +} + +void tst_QHighDpi::environment_QT_SCALE_FACTOR() +{ + qreal factor = 3.1415; + qputenv("QT_SCALE_FACTOR", std::to_string(factor)); + + QList<qreal> dpiValues { 96, 144, 192 }; + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + int i = 0; + for (QScreen *screen : app->screens()) { + // Verify that QT_SCALE_FACTOR applies as a multiplicative factor. + qreal expextedDpr = (dpiValues[i] / standardBaseDpi) * factor; + ++i; + QCOMPARE(screen->devicePixelRatio(), expextedDpr); + QCOMPARE(screen->logicalDotsPerInch(), 96); + QWindow window(screen); + QCOMPARE(window.devicePixelRatio(), expextedDpr); + } +} + +void tst_QHighDpi::environment_QT_SCREEN_SCALE_FACTORS_data() +{ + QTest::addColumn<QList<qreal>>("platformScreenDpi"); // The to-be-overridden values + QTest::addColumn<QByteArray>("environment"); + QTest::addColumn<QList<qreal>>("expectedDprValues"); + + QList<qreal> platformScreenDpi { 192, 216, 240 }; + QList<qreal> fromPlatformScreenDpr { 2, 2.25, 2.5 }; + QList<qreal> fromEnvironmentDpr { 1, 1.5, 2 }; + + // Correct env. variable values. + QTest::newRow("list") << platformScreenDpi << QByteArray("1;1.5;2") << fromEnvironmentDpr; + QTest::newRow("names") << platformScreenDpi << QByteArray("screen#1=1.5;screen#0=1;screen#2=2") << fromEnvironmentDpr; + + // Various broken env. variable values. Should not crash, + // and should not change the DPR. + QTest::newRow("empty") << platformScreenDpi << QByteArray("") << fromPlatformScreenDpr; + QTest::newRow("bogus-1") << platformScreenDpi << QByteArray("foo=bar") << fromPlatformScreenDpr; + QTest::newRow("bogus-2") << platformScreenDpi << QByteArray("fo0==2;;=;==;=3") << fromPlatformScreenDpr; +} + +void tst_QHighDpi::environment_QT_SCREEN_SCALE_FACTORS() +{ + QFETCH(QList<qreal>, platformScreenDpi); + QFETCH(QByteArray, environment); + QFETCH(QList<qreal>, expectedDprValues); + + qputenv("QT_SCREEN_SCALE_FACTORS", environment); + + // Verify that setting QT_SCREEN_SCALE_FACTORS overrides the from-platform-screen-DPI DPR. + { + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(platformScreenDpi)); + int i = 0; + for (QScreen *screen : app->screens()) { + qreal expextedDpr = expectedDprValues[i]; + ++i; + QCOMPARE(screen->devicePixelRatio(), expextedDpr); + QCOMPARE(screen->logicalDotsPerInch(), 96); + QWindow window(screen); + QCOMPARE(window.devicePixelRatio(), expextedDpr); + } + } + + // Verify that setHighDpiScaleFactorRoundingPolicy applies to QT_SCREEN_SCALE_FACTORS as well + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); + { + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(platformScreenDpi)); + int i = 0; + for (QScreen *screen : app->screens()) { + qreal expectedRounderDpr = qRound(expectedDprValues[i++]); + qreal windowDpr = QWindow(screen).devicePixelRatio(); + QCOMPARE(windowDpr, expectedRounderDpr); + } + } +} + +void tst_QHighDpi::environment_QT_USE_PHYSICAL_DPI() +{ + qputenv("QT_USE_PHYSICAL_DPI", "1"); + + QList<qreal> dpiValues { 96, 144, 192 }; + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + // Verify that the device pixel ratio is computed as physicalDpi / baseDpi. + // (which in practice uses physicalSize since this is what QPlatformScreen provides) + + // The default QPlatformScreen::physicalSize() implementation (which QOffscreenScreen + // currerently uses) assumes a default DPI of 100 and calculates a fake physical size + // based on that value. Use DPI 100 here as well: if you have changed the default value + // in QPlatformScreen and get a test failure then update the value below. + const qreal platformScreenDefualtDpi = 100; + qreal expextedDpr = (platformScreenDefualtDpi / qreal(standardBaseDpi)); + + for (QScreen *screen : app->screens()) { + QCOMPARE(screen->devicePixelRatio(), expextedDpr); + QCOMPARE(screen->logicalDotsPerInch(), 96); + QWindow window(screen); + QCOMPARE(window.devicePixelRatio(), expextedDpr); + } +} + +void tst_QHighDpi::environment_QT_SCALE_FACTOR_ROUNDING_POLICY() +{ + QList<qreal> dpiValues { 96, 144, 192 }; + + qputenv("QT_SCALE_FACTOR_ROUNDING_POLICY", "PassThrough"); + { + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + for (int i = 0; i < dpiValues.size(); ++i) + QCOMPARE(app->screens()[i]->devicePixelRatio(), dpiValues[i] / qreal(96)); + } + + qputenv("QT_SCALE_FACTOR_ROUNDING_POLICY", "Round"); + { + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + for (int i = 0; i < dpiValues.size(); ++i) + QCOMPARE(app->screens()[i]->devicePixelRatio(), qRound(dpiValues[i] / qreal(96))); + } + + qunsetenv("QT_SCALE_FACTOR_ROUNDING_POLICY"); + { + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + for (int i = 0; i < dpiValues.size(); ++i) + QCOMPARE(app->screens()[i]->devicePixelRatio(), dpiValues[i] / qreal(96)); + } +} + +void tst_QHighDpi::application_setScaleFactorRoundingPolicy() +{ + QList<qreal> dpiValues { 96, 144, 192 }; + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); + { + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + for (int i = 0; i < dpiValues.size(); ++i) + QCOMPARE(app->screens()[i]->devicePixelRatio(), qRound(dpiValues[i] / qreal(96))); + } + + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough); + { + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + for (int i = 0; i < dpiValues.size(); ++i) + QCOMPARE(app->screens()[i]->devicePixelRatio(), dpiValues[i] / qreal(96)); + } + + // Verify that environment overrides app setting + QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::Round); + qputenv("QT_SCALE_FACTOR_ROUNDING_POLICY", "PassThrough"); + { + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + for (int i = 0; i < dpiValues.size(); ++i) + QCOMPARE(app->screens()[i]->devicePixelRatio(), dpiValues[i] / qreal(96)); + } +} + +void tst_QHighDpi::minimumDpr() +{ + QList<qreal> dpiValues { 40, 60, 95 }; + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + for (QScreen *screen : app->screens()) { + // Qt does not currently support DPR values < 1. Make sure + // the minimum DPR value is 1, also when the screen reports + // a low DPI. + QCOMPARE(screen->devicePixelRatio(), 1); + QWindow window(screen); + QCOMPARE(window.devicePixelRatio(), 1); + } +} + +QT_BEGIN_NAMESPACE +extern int qt_defaultDpiX(); +extern int qt_defaultDpiY(); +QT_END_NAMESPACE + +void tst_QHighDpi::noscreens() +{ + // Create application object with a no-screens configuration (should not crash) + QJsonArray noScreens; + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(noScreens)); + + QCOMPARE(qApp->devicePixelRatio(), 1); + + // Test calling qt_defaultDpiX/Y: These may be called early during QGuiApplication + // initialization, before the platform plugin has created screen objects. They + // should then 1) not crash and 2) return some default value. + QCOMPARE(qt_defaultDpiX(), qt_defaultDpiY()); +} + +void tst_QHighDpi::screenAt_data() +{ + standardScreenDpiTestData(); +} + +void tst_QHighDpi::screenAt() +{ + QFETCH(QList<qreal>, dpiValues); + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + QCOMPARE(app->screens().size(), standardScreenCount); // standard setup + + // Verify that screenAt() returns the correct or no screen for various points, + // for all screens. + int i = 0; + for (QScreen *screen : app->screens()) { + qreal dpi = dpiValues[i++]; + + // veryfy virtualSiblings and that AA_EnableHighDpiScaling is active + QCOMPARE(screen->virtualSiblings().size(), standardScreenCount); + QCOMPARE(screen->geometry().size(), QSize(standardScreenWidth, standardScreenHeight) * (96.0 / dpi)); + + // test points on screen + QCOMPARE(app->screenAt(screen->geometry().center()), screen); + QCOMPARE(app->screenAt(screen->geometry().topLeft()), screen); + QCOMPARE(app->screenAt(screen->geometry().bottomRight()), screen); + + // test points off screen + QCOMPARE(app->screenAt(screen->geometry().center() + QPoint(0, -1000)), nullptr); + QCOMPARE(app->screenAt(screen->geometry().topLeft() + QPoint(0, -1)), nullptr); + QCOMPARE(app->screenAt(screen->geometry().bottomRight() + QPoint(0, +1)), nullptr); + + // check the "gaps" created by Qt::AA_EnableHighDpiScaling: no screen there + if (dpi > 96) { + QCOMPARE(app->screenAt(screen->geometry().topLeft() + QPoint(-1, 0)), nullptr); + QCOMPARE(app->screenAt(screen->geometry().bottomRight() + QPoint(1, 0)), nullptr); + } + } +} + +void tst_QHighDpi::screenGeometry_data() +{ + standardScreenDpiTestData(); +} + +void tst_QHighDpi::screenGeometry() +{ + QFETCH(QList<qreal>, dpiValues); + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + for (QScreen *screen : app->screens()) { + QRect geometry = screen->geometry(); + QPoint onScreen = geometry.topLeft() + QPoint(10, 10); + QPoint onScreenNative = QHighDpi::toNativePixels(onScreen, screen); + QPoint onScreenBack = QHighDpi::fromNativePixels(onScreenNative, screen); + + QCOMPARE(onScreen, onScreenBack); + + QPoint offScreen = geometry.topLeft() - QPoint(10, 10); + QPoint offScreenNative = QHighDpi::toNativePixels(offScreen, screen); + QPoint offScreenBack = QHighDpi::fromNativePixels(offScreenNative, screen); + QCOMPARE(offScreenBack, offScreenBack); + } +} + +void tst_QHighDpi::windowGeometry_data() +{ + standardScreenDpiTestData(); +} + +void tst_QHighDpi::windowGeometry() +{ + QFETCH(QList<qreal>, dpiValues); + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + auto testWindow = [&app](QWindow *window, QScreen *expectedScreen, QPoint expectedPosition, QSize expectedSize) { + + // Is the window correctly sized and on the correct screen? + QCOMPARE(window->size(), expectedSize); + QCOMPARE(window->position(), expectedPosition); + QCOMPARE(window->screen(), expectedScreen); + QCOMPARE(app->screenAt(window->mapToGlobal(QPoint(0, 0))), expectedScreen); + + // Round-trip coordinates local->global->local, which should return the starting + // coordinates, also for coordinates outside the window (and screen) + auto globalRoundtrip = [](QWindow *window, QPoint pos) { + QCOMPARE(window->mapFromGlobal(window->mapToGlobal(pos)), pos); + }; + globalRoundtrip(window, QPoint(10, 10)); // window-interior + globalRoundtrip(window, QPoint(-5, -5)); // outside window, on same screen + globalRoundtrip(window, QPoint(standardScreenWidth *2, standardScreenHeight * 2)); // Outside window, outside all screens + globalRoundtrip(window, QPoint(0, -standardScreenWidth)); // Outside window, on neighbor screen + + // Round-trip float coordinates + auto globalRoundtripF = [](QWindow *window, QPointF pos) { + QCOMPARE(window->mapFromGlobal(window->mapToGlobal(pos)), pos); + }; + + globalRoundtripF(window, QPointF(10, 10)); // window-interior + globalRoundtripF(window, QPointF(10.1, 10.1)); + globalRoundtripF(window, QPointF(10.5, 10.5)); + globalRoundtripF(window, QPointF(10.9, 10.9)); + globalRoundtripF(window, QPointF(-5.5, -5.5)); // outside window, on same screen + globalRoundtripF(window, QPointF(standardScreenWidth * 2.1, standardScreenHeight * 2.1)); // Outside window, outside all screens + globalRoundtripF(window, QPointF(0.5, -standardScreenWidth)); // Outside window, on neighbor screen + }; + + // verify window geometry for top-level and child windows on all screens + for (QScreen *screen : app->screens()) { + QWindow topLevelWindow; + QSize topLevelSize(40, 40); + QPoint topLevelPosition(screen->geometry().center()); + topLevelWindow.resize(topLevelSize); + topLevelWindow.setPosition(topLevelPosition); + topLevelWindow.show(); + testWindow(&topLevelWindow, screen, topLevelPosition, topLevelSize); + + QWindow childWindow(&topLevelWindow); + QSize childSize(20, 20); + QPoint childPosition(10, 10); + childWindow.resize(childSize); + childWindow.setPosition(childPosition); + childWindow.show(); + testWindow(&childWindow, screen, childPosition, childSize); + } +} + +void tst_QHighDpi::spanningWindows_data() +{ + standardScreenDpiTestData(); +} + +void tst_QHighDpi::spanningWindows() +{ + QFETCH(QList<qreal>, dpiValues); + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + QPoint screen0Center = app->screens()[0]->geometry().center(); + int screenWidth = app->screens()[0]->geometry().width(); + + // Create window spanning screen 0 and screen 1 + QWindow window; + QRect windowGeometry = QRect(screen0Center, QSize(screenWidth - 10, 20)); + windowGeometry.adjust(0, 0, -10, 0); // Make sure the center point is on screen 0 + window.setGeometry(windowGeometry); + window.show(); + QCOMPARE(window.geometry(), windowGeometry); + + // Device independent screen space may be non-contiguous, in which case global + // window geometry behaves non-intuitivly when a window spans multiple screens: + // - The main screen for the window is defined by the windowing system + // (usually the screen with most window coverage), and is reflected + // by QWindow::screen() + // - screen coordinate linear math does not work for points on the window + // extending beyond the main screen - these may be on a different screen + // with a non-linear coordinate offset. + // + // Local window geometry works (mostly) as before: + // - QWindow::mapToGlobal() can map any window-local coordinate to the correct + // global coordinate and screen, as long as the coordinate is on the window. + // - QWindow::mapFromGlobal() can map any global coordinate to the correct + // local coordinate, as long as the coordinate is on screen and on the window. + // + // Open issue: + // - Mapping coordinates which are outside of the window is iffy; we might + // fall back to using/assuming the coordinate system for the main screen + // in this case. + QPoint globalTopLeft = window.mapToGlobal(QPoint(0, 0)); + QSize foo = window.geometry().size() - QSize(1, 1); + QPoint globalBottomRight = window.mapToGlobal(QPoint(foo.width(), foo.height())); + + QCOMPARE(app->screenAt(globalTopLeft), app->screens()[0]); + QCOMPARE(app->screenAt(globalBottomRight), app->screens()[1]); +} + +void tst_QHighDpi::mouseEvents_data() +{ + standardScreenDpiTestData(); +} + +void tst_QHighDpi::mouseEvents() +{ + QFETCH(QList<qreal>, dpiValues); + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + class MousePressTestWindow : public QWindow { + public: + QPoint m_mouseTestPoint; + + MousePressTestWindow(QWindow *parent = nullptr) + :QWindow(parent) + { + + } + + void mousePressEvent(QMouseEvent *ev) override + { + QCOMPARE(ev->position(), m_mouseTestPoint); + if (devicePixelRatio() == 1 || devicePixelRatio() == 2) // ### off-by-one error on non-integer dpr + QCOMPARE(mapFromGlobal(ev->globalPosition()), m_mouseTestPoint); + } + + }; + + // Verify mouse event coordinates for top-level and chlid windows on each screen + for (QScreen *screen : app->screens()) { + QPoint mouseTestPoint(10, 10); + MousePressTestWindow topLevelWindow; + topLevelWindow.m_mouseTestPoint = mouseTestPoint; + topLevelWindow.resize(QSize(40, 40)); + topLevelWindow.setPosition(screen->geometry().center()); + topLevelWindow.show(); + + QTest::mouseClick(&topLevelWindow, Qt::LeftButton, Qt::KeyboardModifiers(), mouseTestPoint); + MousePressTestWindow childWindow(&topLevelWindow); + childWindow.m_mouseTestPoint = mouseTestPoint; + childWindow.resize(QSize(20, 20)); + childWindow.setPosition(QPoint(15, 15)); + childWindow.show(); + QTest::mouseClick(&childWindow, Qt::LeftButton, Qt::KeyboardModifiers(), mouseTestPoint); + } + + // Verify mouse event coordinates for a window spanning screen 0 and screen 1 + QPoint screen0Center = app->screens()[0]->geometry().center(); + int screenWidth = app->screens()[0]->geometry().width(); + QSize windowSize = QSize(screenWidth - 10, 20); + QRect windowGeometry = QRect(screen0Center, windowSize); + windowGeometry.adjust(0, 0, -10, 0); // Make sure the center point is on screen 0 + MousePressTestWindow window; + window.setGeometry(windowGeometry); + window.show(); + + QPoint screen0Point(QPoint(10,10)); + QPoint screen1Point(QPoint(windowSize.width() - 20,10)); + QCOMPARE(app->screenAt(window.mapToGlobal(screen0Point)), app->screens()[0]); + QCOMPARE(app->screenAt(window.mapToGlobal(screen1Point)), app->screens()[1]); + + window.m_mouseTestPoint = screen0Point; + QTest::mouseClick(&window, Qt::LeftButton, Qt::KeyboardModifiers(), screen0Point); + window.m_mouseTestPoint = screen1Point; + QTest::mouseClick(&window, Qt::LeftButton, Qt::KeyboardModifiers(), screen1Point); +} + +void tst_QHighDpi::mouseVelocity_data() +{ + standardScreenDpiTestData(); +} + +void tst_QHighDpi::mouseVelocity() +{ + QFETCH(QList<qreal>, dpiValues); + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + class MouseVelocityTestWindow : public QWindow { + public: + QVector2D velocity; + bool decel = false; + + bool event(QEvent *ev) override + { + if (!ev->isPointerEvent()) + qCDebug(lcTests) << ev; + return QWindow::event(ev); + } + + void mousePressEvent(QMouseEvent *ev) override + { + velocity = ev->points().first().velocity(); + qCDebug(lcTests) << "velocity" << velocity << ev; + } + + void mouseMoveEvent(QMouseEvent *ev) override + { + velocity = ev->points().first().velocity(); + if (ev->buttons()) + qDebug(lcTests) << "velocity" << velocity << ev; + } + }; + + // Verify velocity direction and sign on each screen + // FYI: Turn on the qt.pointer.velocity logging category to see how it's calculated + for (QScreen *screen : app->screens()) { + MouseVelocityTestWindow topLevelWindow; + topLevelWindow.resize(QSize(120, 120)); + topLevelWindow.setPosition(screen->geometry().center()); + topLevelWindow.show(); + + QPoint endP; + qreal maxVx = 0; + qreal maxVy = 0; + qreal minVx = INT_MAX; + qreal minVy = INT_MAX; + for (int xDelta = 10; xDelta >= -10; xDelta -= 10) { + for (int yDelta = 10; yDelta >= -10; yDelta -= 10) { + QPoint p(60, 60); + // move closer to p, decelerating, to get the velocity down to a small value + for (int i = 0; i < 12; ++i) { + endP += (p - endP) / 4; + QTest::mouseMove(&topLevelWindow, endP, 3 * i); + } + qCDebug(lcTests) << "beginning drag with dx" << xDelta << "dy" << yDelta; + QTest::mouseMove(&topLevelWindow, p, 10); + QTest::mousePress(&topLevelWindow, Qt::LeftButton, {}, p); + QVERIFY(qAbs(topLevelWindow.velocity.x()) < 50); + QVERIFY(qAbs(topLevelWindow.velocity.y()) < 50); + for (int i = 0; i < 4; ++i) { + p += QPoint(xDelta, yDelta); + QTest::mouseMove(&topLevelWindow, p, 10); + if (xDelta) { + // same sign and decent magnitude: + // 10 px in 10 ms =~ 1000 px / second; should be in logical coordinates on any screen + // but it's not exactly 1000 because of the Kalman filter + QVERIFY(topLevelWindow.velocity.x() * xDelta > 0); + QVERIFY(qAbs(topLevelWindow.velocity.x()) > 500); + } else { + QVERIFY(qAbs(topLevelWindow.velocity.x()) < 10); + } + if (yDelta) { + QVERIFY(topLevelWindow.velocity.y() * yDelta > 0); + QVERIFY(qAbs(topLevelWindow.velocity.y()) > 500); + } else { + QVERIFY(qAbs(topLevelWindow.velocity.y()) < 10); + } + maxVx = qMax(topLevelWindow.velocity.x(), maxVx); + maxVy = qMax(topLevelWindow.velocity.y(), maxVy); + minVx = qMin(topLevelWindow.velocity.x(), minVx); + minVy = qMin(topLevelWindow.velocity.y(), minVy); + } + QTest::mouseRelease(&topLevelWindow, Qt::LeftButton, {}, p); + endP = p; // QED + } + } + qCDebug(lcTests) << "mouse land speed record: forward" << maxVx << maxVy << "reverse" << minVx << minVy; + // all drags were at the same speed, so max speed should be equal in each direction + QVERIFY(qAbs(maxVx - maxVy) < 10); + QVERIFY(qAbs(minVx - minVy) < 10); + QVERIFY(maxVx + minVx < 10); + QVERIFY(maxVy + minVy < 10); + } +} + +void tst_QHighDpi::setCursor_data() +{ + standardScreenDpiTestData(); +} + +void tst_QHighDpi::setCursor() +{ + QFETCH(QList<qreal>, dpiValues); + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + for (QScreen *screen : app->screens()) { + QPoint center = screen->geometry().center(); + QCursor::setPos(center.x(), center.y()); + QCOMPARE(QCursor::pos(), center); + } +} + +void tst_QHighDpi::setGlobalFactorEmits() +{ + QList<qreal> dpiValues { 96, 96, 96 }; + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + std::vector<std::unique_ptr<QSignalSpy>> spies; + for (QScreen *screen : app->screens()) + spies.push_back(std::make_unique<QSignalSpy>(screen, &QScreen::geometryChanged)); + + QHighDpiScaling::setGlobalFactor(2); + + for (const auto &spy : spies) + QCOMPARE(spy->count(), 1); + + QHighDpiScaling::setGlobalFactor(1); +} + +void tst_QHighDpi::setScreenFactorEmits() +{ + QList<qreal> dpiValues { 96, 96, 96 }; + std::unique_ptr<QGuiApplication> app(createStandardOffscreenApp(dpiValues)); + + for (QScreen *screen : app->screens()) { + QSignalSpy spy(screen, &QScreen::geometryChanged); + QHighDpiScaling::setScreenFactor(screen, 2); + QCOMPARE(spy.count(), 1); + } +} + +#include "tst_qhighdpi.moc" +QTEST_APPLESS_MAIN(tst_QHighDpi); diff --git a/tests/auto/gui/kernel/qhighdpiscaling/CMakeLists.txt b/tests/auto/gui/kernel/qhighdpiscaling/CMakeLists.txt deleted file mode 100644 index 69cff9229f..0000000000 --- a/tests/auto/gui/kernel/qhighdpiscaling/CMakeLists.txt +++ /dev/null @@ -1,14 +0,0 @@ -# Generated from qhighdpiscaling.pro. - -##################################################################### -## tst_qhighdpiscaling Test: -##################################################################### - -qt_add_test(tst_qhighdpiscaling - SOURCES - tst_qhighdpiscaling.cpp - PUBLIC_LIBRARIES - Qt::CorePrivate - Qt::Gui - Qt::GuiPrivate -) diff --git a/tests/auto/gui/kernel/qhighdpiscaling/qhighdpiscaling.pro b/tests/auto/gui/kernel/qhighdpiscaling/qhighdpiscaling.pro deleted file mode 100644 index 6cd7bb01f5..0000000000 --- a/tests/auto/gui/kernel/qhighdpiscaling/qhighdpiscaling.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase -TARGET = tst_qhighdpiscaling - -QT += core-private gui-private testlib - -SOURCES += tst_qhighdpiscaling.cpp diff --git a/tests/auto/gui/kernel/qhighdpiscaling/tst_qhighdpiscaling.cpp b/tests/auto/gui/kernel/qhighdpiscaling/tst_qhighdpiscaling.cpp deleted file mode 100644 index 3fbaa0715a..0000000000 --- a/tests/auto/gui/kernel/qhighdpiscaling/tst_qhighdpiscaling.cpp +++ /dev/null @@ -1,97 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <private/qhighdpiscaling_p.h> -#include <qpa/qplatformscreen.h> - -#include <QtTest/QtTest> - -class tst_QHighDpiScaling: public QObject -{ - Q_OBJECT - -private slots: - void factor(); - void scale(); -}; - -// Emulate the case of a High DPI secondary screen -class MyPlatformScreen : public QPlatformScreen -{ -public: - QRect geometry() const override { return QRect(3840, 0, 3840, 1920); } - QRect availableGeometry() const override { return geometry(); } - - QDpi logicalDpi() const override { return logicalBaseDpi(); } - - int depth() const override { return 32; } - QImage::Format format() const override { return QImage::Format_ARGB32_Premultiplied; } -}; - -void tst_QHighDpiScaling::factor() -{ - QHighDpiScaling::setGlobalFactor(2); - - // Verfy that QHighDpiScaling::factor() does not crash on nullptr contexts. - QPoint fakeNativePosition = QPoint(5, 5); - QPlatformScreen *screenContext = nullptr; - QVERIFY(QHighDpiScaling::factor(screenContext) >= 0); - QVERIFY(QHighDpiScaling::factor(screenContext, &fakeNativePosition) >= 0); - QPlatformScreen *platformScreenContext = nullptr; - QVERIFY(QHighDpiScaling::factor(platformScreenContext) >= 0); - QVERIFY(QHighDpiScaling::factor(platformScreenContext, &fakeNativePosition) >= 0); - QWindow *windowContext = nullptr; - QVERIFY(QHighDpiScaling::factor(windowContext) >= 0); - QVERIFY(QHighDpiScaling::factor(windowContext, &fakeNativePosition) >= 0); -} - -// QTBUG-77255: Test some scaling overloads -void tst_QHighDpiScaling::scale() -{ - QHighDpiScaling::setGlobalFactor(2); - QScopedPointer<QPlatformScreen> screen(new MyPlatformScreen); - - qreal nativeValue = 10; - const qreal value = QHighDpi::fromNativePixels(nativeValue, screen.data()); - QCOMPARE(value, qreal(5)); - QCOMPARE(QHighDpi::toNativePixels(value, screen.data()), nativeValue); - - // 10, 10 within screen should translate to 5,5 with origin preserved - const QPoint nativePoint = screen->geometry().topLeft() + QPoint(10, 10); - const QPoint point = QHighDpi::fromNativePixels(nativePoint, screen.data()); - QCOMPARE(point, QPoint(3845, 5)); - QCOMPARE(QHighDpi::toNativePixels(point, screen.data()), nativePoint); - - const QPointF nativePointF(nativePoint); - const QPointF pointF = QHighDpi::fromNativePixels(nativePointF, screen.data()); - QCOMPARE(pointF, QPointF(3845, 5)); - QCOMPARE(QHighDpi::toNativePixels(pointF, screen.data()), nativePointF); -} - -#include "tst_qhighdpiscaling.moc" -QTEST_MAIN(tst_QHighDpiScaling); diff --git a/tests/auto/gui/kernel/qinputdevice/CMakeLists.txt b/tests/auto/gui/kernel/qinputdevice/CMakeLists.txt index 5c368838ab..afbfd9bb37 100644 --- a/tests/auto/gui/kernel/qinputdevice/CMakeLists.txt +++ b/tests/auto/gui/kernel/qinputdevice/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qinputdevice.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qinputdevice Test: ##################################################################### -qt_add_test(tst_qinputdevice +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qinputdevice LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qinputdevice SOURCES tst_qinputdevice.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::GuiPrivate ) diff --git a/tests/auto/gui/kernel/qinputdevice/qinputdevice.pro b/tests/auto/gui/kernel/qinputdevice/qinputdevice.pro deleted file mode 100644 index a563776556..0000000000 --- a/tests/auto/gui/kernel/qinputdevice/qinputdevice.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qinputdevice -SOURCES += tst_qinputdevice.cpp -QT += gui gui-private testlib diff --git a/tests/auto/gui/kernel/qinputdevice/tst_qinputdevice.cpp b/tests/auto/gui/kernel/qinputdevice/tst_qinputdevice.cpp index 115bea996b..8587aebf2a 100644 --- a/tests/auto/gui/kernel/qinputdevice/tst_qinputdevice.cpp +++ b/tests/auto/gui/kernel/qinputdevice/tst_qinputdevice.cpp @@ -1,32 +1,7 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include <QtTest/QtTest> +#include <QTest> #include <qpa/qwindowsysteminterface.h> #include <QtGui/qinputdevice.h> #include <QtGui/qpointingdevice.h> @@ -43,12 +18,56 @@ private slots: void multiSeatDevices(); private: + const QInputDevice *getPrimaryKeyboard(const QString& seatName = QString()); + const QPointingDevice *getPrimaryPointingDevice(const QString& seatName = QString()); }; void tst_QInputDevice::initTestCase() { } +const QInputDevice *tst_QInputDevice::getPrimaryKeyboard(const QString& seatName) +{ + QList<const QInputDevice *> devices = QInputDevice::devices(); + const QInputDevice *ret = nullptr; + for (const QInputDevice *d : devices) { + if (d->type() != QInputDevice::DeviceType::Keyboard) + continue; + if (seatName.isNull() || d->seatName() == seatName) { + // the master keyboard's parent is not another input device + if (!d->parent() || !qobject_cast<const QInputDevice *>(d->parent())) + return d; + if (!ret) + ret = d; + } + } + return ret; +} + +const QPointingDevice *tst_QInputDevice::getPrimaryPointingDevice(const QString& seatName) +{ + QList<const QInputDevice *> devices = QInputDevice::devices(); + const QPointingDevice *mouse = nullptr; + const QPointingDevice *touchpad = nullptr; + for (const QInputDevice *dev : devices) { + if (!seatName.isNull() && dev->seatName() != seatName) + continue; + if (dev->type() == QInputDevice::DeviceType::Mouse) { + if (!mouse) + mouse = static_cast<const QPointingDevice *>(dev); + // the core pointer is likely a mouse, and its parent is not another input device + if (!mouse->parent() || !qobject_cast<const QInputDevice *>(mouse->parent())) + return mouse; + } else if (dev->type() == QInputDevice::DeviceType::TouchPad) { + if (!touchpad || !dev->parent() || dev->parent()->metaObject() != dev->metaObject()) + touchpad = static_cast<const QPointingDevice *>(dev); + } + } + if (mouse) + return mouse; + return touchpad; +} + void tst_QInputDevice::multiSeatDevices() { QWindowSystemInterface::registerInputDevice(new QInputDevice("seat 1 kbd", 1000, QInputDevice::DeviceType::Keyboard, "seat 1", this)); @@ -59,15 +78,17 @@ void tst_QInputDevice::multiSeatDevices() QWindowSystemInterface::registerInputDevice(new QPointingDevice("seat 2 mouse", 2010, QInputDevice::DeviceType::Mouse, QPointingDevice::PointerType::Generic, QInputDevice::Capability::Position | QInputDevice::Capability::Hover, 1, 2, "seat 2", QPointingDeviceUniqueId(), this)); - QVERIFY(QInputDevice::devices().count() >= 4); + QVERIFY(QInputDevice::devices().size() >= 4); QVERIFY(QInputDevicePrivate::fromId(1010)); QVERIFY(QInputDevicePrivate::fromId(1010)->hasCapability(QInputDevice::Capability::Scroll)); QVERIFY(QInputDevicePrivate::fromId(2010)); QVERIFY(!QInputDevicePrivate::fromId(2010)->hasCapability(QInputDevice::Capability::Scroll)); QVERIFY(QInputDevice::primaryKeyboard()); - QCOMPARE(QInputDevice::primaryKeyboard()->systemId(), qint64(1) << 33); + if (!getPrimaryKeyboard()) + QCOMPARE(QInputDevice::primaryKeyboard()->systemId(), qint64(1) << 33); QVERIFY(QPointingDevice::primaryPointingDevice()); - QCOMPARE(QPointingDevice::primaryPointingDevice()->systemId(), 1); + if (!getPrimaryPointingDevice()) + QCOMPARE(QPointingDevice::primaryPointingDevice()->systemId(), 1); QVERIFY(QInputDevice::primaryKeyboard("seat 1")); QCOMPARE(QInputDevice::primaryKeyboard("seat 1")->systemId(), 1000); QVERIFY(QPointingDevice::primaryPointingDevice("seat 1")); diff --git a/tests/auto/gui/kernel/qinputmethod/CMakeLists.txt b/tests/auto/gui/kernel/qinputmethod/CMakeLists.txt index bdd4940392..e3ce0774bc 100644 --- a/tests/auto/gui/kernel/qinputmethod/CMakeLists.txt +++ b/tests/auto/gui/kernel/qinputmethod/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qinputmethod.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qinputmethod Test: ##################################################################### -qt_add_test(tst_qinputmethod +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qinputmethod LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qinputmethod SOURCES tst_qinputmethod.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/gui/kernel/qinputmethod/qinputmethod.pro b/tests/auto/gui/kernel/qinputmethod/qinputmethod.pro deleted file mode 100644 index 015cc782eb..0000000000 --- a/tests/auto/gui/kernel/qinputmethod/qinputmethod.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qinputmethod -SOURCES += tst_qinputmethod.cpp -QT += core-private gui-private testlib diff --git a/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp b/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp index d28dab3ad0..619de7bed3 100644 --- a/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp +++ b/tests/auto/gui/kernel/qinputmethod/tst_qinputmethod.cpp @@ -1,32 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> +#include <QSignalSpy> #include <private/qguiapplication_p.h> #include <private/qinputmethod_p.h> @@ -149,7 +125,7 @@ void tst_qinputmethod::animating() QSignalSpy spy(qApp->inputMethod(), SIGNAL(animatingChanged())); m_platformInputContext.emitAnimatingChanged(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_qinputmethod::keyboarRectangle() @@ -161,7 +137,7 @@ void tst_qinputmethod::keyboarRectangle() QSignalSpy spy(qApp->inputMethod(), SIGNAL(keyboardRectangleChanged())); m_platformInputContext.emitKeyboardRectChanged(); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_qinputmethod::inputItemTransform() @@ -176,7 +152,7 @@ void tst_qinputmethod::inputItemTransform() qApp->inputMethod()->setInputItemTransform(transform); QCOMPARE(qApp->inputMethod()->inputItemTransform(), transform); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); // reset qApp->inputMethod()->setInputItemTransform(QTransform()); @@ -273,13 +249,13 @@ void tst_qinputmethod::query() void tst_qinputmethod::inputDirection() { - QCOMPARE(m_platformInputContext.m_inputDirectionCallCount, 0); + auto originalCount = m_platformInputContext.m_inputDirectionCallCount; qApp->inputMethod()->inputDirection(); - QCOMPARE(m_platformInputContext.m_inputDirectionCallCount, 1); + QCOMPARE(m_platformInputContext.m_inputDirectionCallCount, originalCount + 1); - QCOMPARE(m_platformInputContext.m_localeCallCount, 0); + originalCount = m_platformInputContext.m_localeCallCount; qApp->inputMethod()->locale(); - QCOMPARE(m_platformInputContext.m_localeCallCount, 1); + QCOMPARE(m_platformInputContext.m_localeCallCount, originalCount + 1); } void tst_qinputmethod::inputMethodAccepted() diff --git a/tests/auto/gui/kernel/qkeyevent/BLACKLIST b/tests/auto/gui/kernel/qkeyevent/BLACKLIST deleted file mode 100644 index e55a200f4d..0000000000 --- a/tests/auto/gui/kernel/qkeyevent/BLACKLIST +++ /dev/null @@ -1,6 +0,0 @@ -# QTBUG-68974 -[basicEventDelivery] -android -# QTBUG-68974 -[modifiers] -android diff --git a/tests/auto/gui/kernel/qkeyevent/CMakeLists.txt b/tests/auto/gui/kernel/qkeyevent/CMakeLists.txt index 3c48a6492b..c3c9892d14 100644 --- a/tests/auto/gui/kernel/qkeyevent/CMakeLists.txt +++ b/tests/auto/gui/kernel/qkeyevent/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qkeyevent.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qkeyevent Test: ##################################################################### -qt_add_test(tst_qkeyevent +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qkeyevent LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qkeyevent SOURCES tst_qkeyevent.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qkeyevent/qkeyevent.pro b/tests/auto/gui/kernel/qkeyevent/qkeyevent.pro deleted file mode 100644 index c0a5786e27..0000000000 --- a/tests/auto/gui/kernel/qkeyevent/qkeyevent.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qkeyevent -SOURCES += tst_qkeyevent.cpp -QT = core gui testlib diff --git a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp index 09becfe860..7d8e0aa5dc 100644 --- a/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp +++ b/tests/auto/gui/kernel/qkeyevent/tst_qkeyevent.cpp @@ -1,32 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include <QtTest/QtTest> +// Copyright (C) 2017 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses + +#include <QTest> #include <QtCore/qcoreapplication.h> #include <QtGui/qevent.h> diff --git a/tests/auto/gui/kernel/qkeysequence/CMakeLists.txt b/tests/auto/gui/kernel/qkeysequence/CMakeLists.txt index f5a0c38fe4..1676302d1b 100644 --- a/tests/auto/gui/kernel/qkeysequence/CMakeLists.txt +++ b/tests/auto/gui/kernel/qkeysequence/CMakeLists.txt @@ -1,17 +1,15 @@ -# Generated from qkeysequence.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qkeysequence Test: ##################################################################### -qt_add_test(tst_qkeysequence - SOURCES - tst_qkeysequence.cpp - PUBLIC_LIBRARIES - Qt::CorePrivate - Qt::Gui - Qt::GuiPrivate -) +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qkeysequence LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() # Resources: set(qkeysequence_resource_files @@ -19,10 +17,13 @@ set(qkeysequence_resource_files "qt_de.qm" ) -qt_add_resource(tst_qkeysequence "qkeysequence" - PREFIX - "/" - FILES - ${qkeysequence_resource_files} +qt_internal_add_test(tst_qkeysequence + SOURCES + tst_qkeysequence.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + TESTDATA ${qkeysequence_resource_files} + BUILTIN_TESTDATA ) - diff --git a/tests/auto/gui/kernel/qkeysequence/qkeysequence.pro b/tests/auto/gui/kernel/qkeysequence/qkeysequence.pro deleted file mode 100644 index 9f79fe9ab7..0000000000 --- a/tests/auto/gui/kernel/qkeysequence/qkeysequence.pro +++ /dev/null @@ -1,9 +0,0 @@ -CONFIG += testcase -TARGET = tst_qkeysequence - -QT += testlib -QT += core-private gui-private - -SOURCES += tst_qkeysequence.cpp - -RESOURCES += qkeysequence.qrc diff --git a/tests/auto/gui/kernel/qkeysequence/qkeysequence.qrc b/tests/auto/gui/kernel/qkeysequence/qkeysequence.qrc deleted file mode 100644 index e224faaddd..0000000000 --- a/tests/auto/gui/kernel/qkeysequence/qkeysequence.qrc +++ /dev/null @@ -1,6 +0,0 @@ -<RCC> - <qresource> - <file>keys_de.qm</file> - <file>qt_de.qm</file> - </qresource> -</RCC> diff --git a/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp b/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp index 107c91507b..67fef3cf44 100644 --- a/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp +++ b/tests/auto/gui/kernel/qkeysequence/tst_qkeysequence.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> #include <qkeysequence.h> #include <qpa/qplatformtheme.h> #include <qpa/qplatformtheme_p.h> @@ -171,19 +146,19 @@ tst_QKeySequence::~tst_QKeySequence() void tst_QKeySequence::initTestCase() { ourTranslator = new QTranslator(this); - ourTranslator->load(":/keys_de"); + (void)ourTranslator->load(":/keys_de"); qtTranslator = new QTranslator(this); - qtTranslator->load(":/qt_de"); + (void)qtTranslator->load(":/qt_de"); } void tst_QKeySequence::swap() { - QKeySequence ks1(Qt::CTRL+Qt::Key_O); - QKeySequence ks2(Qt::CTRL+Qt::Key_L); + QKeySequence ks1(Qt::CTRL | Qt::Key_O); + QKeySequence ks2(Qt::CTRL | Qt::Key_L); ks1.swap(ks2); - QCOMPARE(ks1[0], Qt::CTRL+Qt::Key_L); - QCOMPARE(ks2[0], Qt::CTRL+Qt::Key_O); + QCOMPARE(ks1[0], Qt::CTRL | Qt::Key_L); + QCOMPARE(ks2[0], Qt::CTRL | Qt::Key_O); } void tst_QKeySequence::operatorQString_data() @@ -498,11 +473,15 @@ void tst_QKeySequence::toStringFromKeycode_data() QTest::newRow("A") << QKeySequence(Qt::Key_A) << "A"; QTest::newRow("-1") << QKeySequence(-1) << ""; QTest::newRow("Unknown") << QKeySequence(Qt::Key_unknown) << ""; + QTest::newRow("Ctrl+Unknown") << QKeySequence(Qt::ControlModifier | Qt::Key_unknown) << ""; QTest::newRow("Ctrl+Num+Ins") << QKeySequence(Qt::ControlModifier | Qt::KeypadModifier | Qt::Key_Insert) << "Ctrl+Num+Ins"; QTest::newRow("Ctrl+Num+Del") << QKeySequence(Qt::ControlModifier | Qt::KeypadModifier | Qt::Key_Delete) << "Ctrl+Num+Del"; QTest::newRow("Ctrl+Alt+Num+Del") << QKeySequence(Qt::ControlModifier | Qt::AltModifier | Qt::KeypadModifier | Qt::Key_Delete) << "Ctrl+Alt+Num+Del"; QTest::newRow("Ctrl+Ins") << QKeySequence(Qt::ControlModifier | Qt::Key_Insert) << "Ctrl+Ins"; - QTest::newRow("Ctrl+Num+Ins(1)") << QKeySequence(Qt::Key_Insert | Qt::KeypadModifier | Qt::ControlModifier) << "Ctrl+Num+Ins"; + QTest::newRow("Ctrl") << QKeySequence(Qt::Key_Control) << "Control"; + QTest::newRow("Alt") << QKeySequence(Qt::Key_Alt) << "Alt"; + QTest::newRow("Shift") << QKeySequence(Qt::Key_Shift) << "Shift"; + QTest::newRow("Meta") << QKeySequence(Qt::Key_Meta) << "Meta"; } void tst_QKeySequence::toStringFromKeycode() @@ -549,11 +528,11 @@ void tst_QKeySequence::parseString_data() // Valid QTest::newRow("A") << "A" << QKeySequence(Qt::Key_A); QTest::newRow("a") << "a" << QKeySequence(Qt::Key_A); - QTest::newRow("Ctrl+Left") << "Ctrl+Left" << QKeySequence(Qt::CTRL + Qt::Key_Left); - QTest::newRow("CTRL+LEFT") << "CTRL+LEFT" << QKeySequence(Qt::CTRL + Qt::Key_Left); - QTest::newRow("Meta+A") << "Meta+a" << QKeySequence(Qt::META + Qt::Key_A); - QTest::newRow("mEtA+A") << "mEtA+a" << QKeySequence(Qt::META + Qt::Key_A); - QTest::newRow("Ctrl++") << "Ctrl++" << QKeySequence(Qt::CTRL + Qt::Key_Plus); + QTest::newRow("Ctrl+Left") << "Ctrl+Left" << QKeySequence(Qt::CTRL | Qt::Key_Left); + QTest::newRow("CTRL+LEFT") << "CTRL+LEFT" << QKeySequence(Qt::CTRL | Qt::Key_Left); + QTest::newRow("Meta+A") << "Meta+a" << QKeySequence(Qt::META | Qt::Key_A); + QTest::newRow("mEtA+A") << "mEtA+a" << QKeySequence(Qt::META | Qt::Key_A); + QTest::newRow("Ctrl++") << "Ctrl++" << QKeySequence(Qt::CTRL | Qt::Key_Plus); // Invalid modifiers QTest::newRow("Win+A") << "Win+a" << QKeySequence(Qt::Key_unknown); @@ -580,10 +559,6 @@ void tst_QKeySequence::parseString_data() //QTest::newRow("Ctrl") << "Ctrl" << QKeySequence(Qt::CTRL); //QTest::newRow("Shift") << "Shift" << QKeySequence(Qt::SHIFT); - // Only Keys - QTest::newRow("a") << "a" << QKeySequence(Qt::Key_A); - QTest::newRow("A") << "A" << QKeySequence(Qt::Key_A); - // Incomplete QTest::newRow("Meta+Shift+") << "Meta+Shift+" << QKeySequence(Qt::Key_unknown); } @@ -630,34 +605,34 @@ void tst_QKeySequence::listToString_data() QList<QKeySequence> sequences; - sequences << QKeySequence(Qt::CTRL + Qt::Key_Left) - << QKeySequence(Qt::META + Qt::Key_A); + sequences << QKeySequence(Qt::CTRL | Qt::Key_Left) + << QKeySequence(Qt::META | Qt::Key_A); QTest::newRow("Ctrl+Left; Meta+A") << "Ctrl+Left; Meta+A" << sequences; sequences.clear(); - sequences << QKeySequence(Qt::CTRL + Qt::Key_Semicolon) - << QKeySequence(Qt::META + Qt::Key_A); + sequences << QKeySequence(Qt::CTRL | Qt::Key_Semicolon) + << QKeySequence(Qt::META | Qt::Key_A); QTest::newRow("Ctrl+;; Meta+A") << "Ctrl+;; Meta+A" << sequences; sequences.clear(); sequences << QKeySequence(Qt::Key_Semicolon) - << QKeySequence(Qt::META + Qt::Key_A); + << QKeySequence(Qt::META | Qt::Key_A); QTest::newRow(";; Meta+A") << ";; Meta+A" << sequences; sequences.clear(); - sequences << QKeySequence(Qt::CTRL + Qt::Key_Left) - << QKeySequence(Qt::META + Qt::Key_Semicolon); + sequences << QKeySequence(Qt::CTRL | Qt::Key_Left) + << QKeySequence(Qt::META | Qt::Key_Semicolon); QTest::newRow("Ctrl+Left; Meta+;") << "Ctrl+Left; Meta+;" << sequences; sequences.clear(); - sequences << QKeySequence(Qt::CTRL + Qt::Key_Left) + sequences << QKeySequence(Qt::CTRL | Qt::Key_Left) << QKeySequence(); QTest::newRow("Ctrl+Left; ") << "Ctrl+Left; " << sequences; sequences.clear(); - sequences << QKeySequence(Qt::CTRL + Qt::Key_Left) + sequences << QKeySequence(Qt::CTRL | Qt::Key_Left) << QKeySequence() - << QKeySequence(Qt::META + Qt::Key_A); + << QKeySequence(Qt::META | Qt::Key_A); QTest::newRow("Ctrl+Left; ; Meta+A") << "Ctrl+Left; ; Meta+A" << sequences; } @@ -676,40 +651,40 @@ void tst_QKeySequence::listFromString_data() QList<QKeySequence> sequences; - sequences << QKeySequence(Qt::CTRL + Qt::Key_Left) - << QKeySequence(Qt::META + Qt::Key_A); + sequences << QKeySequence(Qt::CTRL | Qt::Key_Left) + << QKeySequence(Qt::META | Qt::Key_A); QTest::newRow("Ctrl+Left; Meta+A") << "Ctrl+Left; Meta+A" << sequences; sequences.clear(); - sequences << QKeySequence(Qt::CTRL + Qt::Key_Semicolon) - << QKeySequence(Qt::META + Qt::Key_A); + sequences << QKeySequence(Qt::CTRL | Qt::Key_Semicolon) + << QKeySequence(Qt::META | Qt::Key_A); QTest::newRow("Ctrl+;; Meta+A") << "Ctrl+;; Meta+A" << sequences; sequences.clear(); sequences << QKeySequence(Qt::Key_Semicolon) - << QKeySequence(Qt::META + Qt::Key_A); + << QKeySequence(Qt::META | Qt::Key_A); QTest::newRow(";; Meta+A") << ";; Meta+A" << sequences; sequences.clear(); - sequences << QKeySequence(Qt::CTRL + Qt::Key_Left) - << QKeySequence(Qt::META + Qt::Key_Semicolon); + sequences << QKeySequence(Qt::CTRL | Qt::Key_Left) + << QKeySequence(Qt::META | Qt::Key_Semicolon); QTest::newRow("Ctrl+Left; Meta+;") << "Ctrl+Left; Meta+;" << sequences; sequences.clear(); - sequences << QKeySequence(Qt::CTRL + Qt::Key_Left) + sequences << QKeySequence(Qt::CTRL | Qt::Key_Left) << QKeySequence(); QTest::newRow("Ctrl+Left; ") << "Ctrl+Left; " << sequences; sequences.clear(); - sequences << QKeySequence(Qt::CTRL + Qt::Key_Left) + sequences << QKeySequence(Qt::CTRL | Qt::Key_Left) << QKeySequence() - << QKeySequence(Qt::META + Qt::Key_A); + << QKeySequence(Qt::META | Qt::Key_A); QTest::newRow("Ctrl+Left; ; Meta+A") << "Ctrl+Left; ; Meta+A" << sequences; sequences.clear(); - sequences << QKeySequence(Qt::CTRL + Qt::Key_Left) + sequences << QKeySequence(Qt::CTRL | Qt::Key_Left) << QKeySequence(Qt::Key_unknown) - << QKeySequence(Qt::META + Qt::Key_A); + << QKeySequence(Qt::META | Qt::Key_A); QTest::newRow("Ctrl+Left; 4+3=2; Meta+A") << "Ctrl+Left; 4+3=2; Meta+A" << sequences; } diff --git a/tests/auto/gui/kernel/qmouseevent/CMakeLists.txt b/tests/auto/gui/kernel/qmouseevent/CMakeLists.txt index c7cc51a465..ac2200792b 100644 --- a/tests/auto/gui/kernel/qmouseevent/CMakeLists.txt +++ b/tests/auto/gui/kernel/qmouseevent/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qmouseevent.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmouseevent Test: ##################################################################### -qt_add_test(tst_qmouseevent +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmouseevent LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qmouseevent SOURCES tst_qmouseevent.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::GuiPrivate ) diff --git a/tests/auto/gui/kernel/qmouseevent/qmouseevent.pro b/tests/auto/gui/kernel/qmouseevent/qmouseevent.pro deleted file mode 100644 index 6deac78485..0000000000 --- a/tests/auto/gui/kernel/qmouseevent/qmouseevent.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qmouseevent -QT += testlib gui-private -SOURCES += tst_qmouseevent.cpp diff --git a/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp index c5bc7a9460..f703111384 100644 --- a/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp +++ b/tests/auto/gui/kernel/qmouseevent/tst_qmouseevent.cpp @@ -1,37 +1,14 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> #include <qevent.h> #include <qwindow.h> #include <QtGui/private/qpointingdevice_p.h> +#include <QtCore/qpointer.h> + Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests") class MouseEventWidget : public QWindow @@ -122,6 +99,7 @@ private slots: void grabbers_data(); void grabbers(); void velocity(); + void clone(); private: MouseEventWidget* testMouseWidget; @@ -159,6 +137,7 @@ void tst_QMouseEvent::mouseEventBasic() QMouseEvent me(QEvent::MouseButtonPress, local, scene, screen, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); QVERIFY(me.isInputEvent()); QVERIFY(me.isPointerEvent()); + QVERIFY(me.isSinglePointEvent()); QCOMPARE(me.isAccepted(), true); QCOMPARE(me.button(), Qt::LeftButton); QCOMPARE(me.buttons(), Qt::LeftButton); @@ -168,17 +147,17 @@ void tst_QMouseEvent::mouseEventBasic() QCOMPARE(me.scenePosition(), scene); QCOMPARE(me.globalPosition(), screen); // Press right button while left is already pressed - me = QMouseEvent(QEvent::MouseButtonPress, local, scene, screen, Qt::RightButton, Qt::LeftButton | Qt::RightButton, Qt::NoModifier); - QVERIFY(me.isBeginEvent()); - QVERIFY(!me.isEndEvent()); + QMouseEvent me2(QEvent::MouseButtonPress, local, scene, screen, Qt::RightButton, Qt::LeftButton | Qt::RightButton, Qt::NoModifier); + QVERIFY(me2.isBeginEvent()); + QVERIFY(!me2.isEndEvent()); // Release right button while left is still pressed - me = QMouseEvent(QEvent::MouseButtonRelease, local, scene, screen, Qt::RightButton, Qt::LeftButton, Qt::NoModifier); - QVERIFY(!me.isBeginEvent()); - QVERIFY(me.isEndEvent()); + QMouseEvent me3 = QMouseEvent(QEvent::MouseButtonRelease, local, scene, screen, Qt::RightButton, Qt::LeftButton, Qt::NoModifier); + QVERIFY(!me3.isBeginEvent()); + QVERIFY(me3.isEndEvent()); // Release left button in the usual way - me = QMouseEvent(QEvent::MouseButtonRelease, local, scene, screen, Qt::LeftButton, Qt::NoButton, Qt::NoModifier); - QVERIFY(!me.isBeginEvent()); - QVERIFY(me.isEndEvent()); + QMouseEvent me4 = QMouseEvent(QEvent::MouseButtonRelease, local, scene, screen, Qt::LeftButton, Qt::NoButton, Qt::NoModifier); + QVERIFY(!me4.isBeginEvent()); + QVERIFY(me4.isEndEvent()); } void tst_QMouseEvent::checkMousePressEvent_data() @@ -287,14 +266,14 @@ void tst_QMouseEvent::grabbers() auto firstEPD = devPriv->pointById(0); QCOMPARE(firstEPD->eventPoint.pressTimestamp(), testMouseWidget->pressTimestamp); QCOMPARE(firstEPD->exclusiveGrabber, grabExclusive ? testMouseWidget : nullptr); - QCOMPARE(firstEPD->passiveGrabbers.count(), grabPassive ? 1 : 0); + QCOMPARE(firstEPD->passiveGrabbers.size(), grabPassive ? 1 : 0); if (grabPassive) QCOMPARE(firstEPD->passiveGrabbers.first(), testMouseWidget); // Ensure that grabbers are forgotten after release delivery QTest::mouseRelease(testMouseWidget, Qt::LeftButton, Qt::KeyboardModifiers(), {10, 10}); QTRY_COMPARE(firstEPD->exclusiveGrabber, nullptr); - QCOMPARE(firstEPD->passiveGrabbers.count(), 0); + QCOMPARE(firstEPD->passiveGrabbers.size(), 0); } void tst_QMouseEvent::velocity() @@ -333,5 +312,24 @@ void tst_QMouseEvent::velocity() QVERIFY(testMouseWidget->velocity.y() > 0); } +void tst_QMouseEvent::clone() +{ + const QPointF pos(10.0f, 10.0f); + + QMouseEvent originalMe(QEvent::MouseButtonPress, pos, pos, pos, Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + QVERIFY(!originalMe.allPointsAccepted()); + QVERIFY(!originalMe.points().first().isAccepted()); + + // create a clone of the original + std::unique_ptr<QMouseEvent> clonedMe(originalMe.clone()); + QVERIFY(!clonedMe->allPointsAccepted()); + QVERIFY(!clonedMe->points().first().isAccepted()); + + // now we alter originalMe, which should *not* change clonedMe + originalMe.setAccepted(true); + QVERIFY(!clonedMe->allPointsAccepted()); + QVERIFY(!clonedMe->points().first().isAccepted()); +} + QTEST_MAIN(tst_QMouseEvent) #include "tst_qmouseevent.moc" diff --git a/tests/auto/gui/kernel/qmouseevent_modal/CMakeLists.txt b/tests/auto/gui/kernel/qmouseevent_modal/CMakeLists.txt index afe9fe33ed..034b9c794d 100644 --- a/tests/auto/gui/kernel/qmouseevent_modal/CMakeLists.txt +++ b/tests/auto/gui/kernel/qmouseevent_modal/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qmouseevent_modal.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qmouseevent_modal Test: ##################################################################### -qt_add_test(tst_qmouseevent_modal +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qmouseevent_modal LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qmouseevent_modal SOURCES tst_qmouseevent_modal.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::Widgets ) diff --git a/tests/auto/gui/kernel/qmouseevent_modal/qmouseevent_modal.pro b/tests/auto/gui/kernel/qmouseevent_modal/qmouseevent_modal.pro deleted file mode 100644 index 7fd3a59edc..0000000000 --- a/tests/auto/gui/kernel/qmouseevent_modal/qmouseevent_modal.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase -TARGET = tst_qmouseevent_modal -QT += widgets testlib -SOURCES += tst_qmouseevent_modal.cpp - - - diff --git a/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp b/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp index c430148a91..0fe218d503 100644 --- a/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp +++ b/tests/auto/gui/kernel/qmouseevent_modal/tst_qmouseevent_modal.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> #include <qapplication.h> #include <qfontinfo.h> diff --git a/tests/auto/gui/kernel/qopenglwindow/CMakeLists.txt b/tests/auto/gui/kernel/qopenglwindow/CMakeLists.txt index 1a460a567f..0f57b98bc3 100644 --- a/tests/auto/gui/kernel/qopenglwindow/CMakeLists.txt +++ b/tests/auto/gui/kernel/qopenglwindow/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qopenglwindow.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qopenglwindow Test: ##################################################################### -qt_add_test(tst_qopenglwindow +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qopenglwindow LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qopenglwindow SOURCES tst_qopenglwindow.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/gui/kernel/qopenglwindow/qopenglwindow.pro b/tests/auto/gui/kernel/qopenglwindow/qopenglwindow.pro deleted file mode 100644 index 28b12f0677..0000000000 --- a/tests/auto/gui/kernel/qopenglwindow/qopenglwindow.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase -TARGET = tst_qopenglwindow - -QT += opengl core-private gui-private testlib - -SOURCES += tst_qopenglwindow.cpp diff --git a/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp b/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp index 2785d57a42..06a1ffb296 100644 --- a/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp +++ b/tests/auto/gui/kernel/qopenglwindow/tst_qopenglwindow.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtOpenGL/QOpenGLWindow> -#include <QtTest/QtTest> +#include <QTest> #include <QtGui/QOpenGLFunctions> #include <QtGui/QOpenGLContext> #include <QtGui/QPainter> @@ -144,6 +119,9 @@ void tst_QOpenGLWindow::resize() if (isPlatformWayland()) QSKIP("Wayland: Crashes on Intel Mesa due to a driver bug (QTBUG-66848)."); + if (QGuiApplication::platformName().startsWith(QLatin1String("eglfs"), Qt::CaseInsensitive)) + QSKIP("EGLFS does not allow resizing on top level window"); + Window w; w.reset(); w.resize(640, 480); diff --git a/tests/auto/gui/kernel/qpalette/CMakeLists.txt b/tests/auto/gui/kernel/qpalette/CMakeLists.txt index acb413007e..7983b9ac25 100644 --- a/tests/auto/gui/kernel/qpalette/CMakeLists.txt +++ b/tests/auto/gui/kernel/qpalette/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qpalette.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qpalette Test: ##################################################################### -qt_add_test(tst_qpalette +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qpalette LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qpalette SOURCES tst_qpalette.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qpalette/qpalette.pro b/tests/auto/gui/kernel/qpalette/qpalette.pro deleted file mode 100644 index 9dd3f3e715..0000000000 --- a/tests/auto/gui/kernel/qpalette/qpalette.pro +++ /dev/null @@ -1,7 +0,0 @@ -CONFIG += testcase -TARGET = tst_qpalette -QT += testlib -SOURCES += tst_qpalette.cpp - - - diff --git a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp index cd968100e6..c21828bee2 100644 --- a/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp +++ b/tests/auto/gui/kernel/qpalette/tst_qpalette.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + + +#include <QTest> #include "qpalette.h" @@ -47,6 +22,8 @@ private Q_SLOTS: void noBrushesSetForDefaultPalette(); void cannotCheckIfInvalidBrushSet(); void checkIfBrushForCurrentGroupSet(); + void cacheKey(); + void dataStream(); }; void tst_QPalette::roleValues_data() @@ -75,9 +52,10 @@ void tst_QPalette::roleValues_data() QTest::newRow("QPalette::ToolTipBase") << int(QPalette::ToolTipBase) << 18; QTest::newRow("QPalette::ToolTipText") << int(QPalette::ToolTipText) << 19; QTest::newRow("QPalette::PlaceholderText") << int(QPalette::PlaceholderText) << 20; + QTest::newRow("QPalette::Accent") << int(QPalette::Accent) << 21; // Change this value as you add more roles. - QTest::newRow("QPalette::NColorRoles") << int(QPalette::NColorRoles) << 21; + QTest::newRow("QPalette::NColorRoles") << int(QPalette::NColorRoles) << 22; } void tst_QPalette::roleValues() @@ -122,6 +100,21 @@ void tst_QPalette::resolve() QVERIFY(p2ResolvedTo1 != p1); QVERIFY(p2ResolvedTo1 != p2); + + QPalette p3; + // ensure the resolve mask is full + for (int r = 0; r < QPalette::NColorRoles; ++r) + p3.setBrush(QPalette::All, QPalette::ColorRole(r), Qt::red); + const QPalette::ResolveMask fullMask = p3.resolveMask(); + + QPalette p3ResolvedToP1 = p3.resolve(p1); + QVERIFY(p3ResolvedToP1.isCopyOf(p3)); + + QPalette p4; + QCOMPARE(p4.resolveMask(), QPalette::ResolveMask{}); + // resolve must detach even if p4 has no mask + p4 = p4.resolve(p3); + QCOMPARE(p3.resolveMask(), fullMask); } @@ -207,9 +200,6 @@ void tst_QPalette::setBrush() const QPalette pp = p; QVERIFY(pp.isCopyOf(p)); - // Setting the same brush won't detach - p.setBrush(QPalette::Disabled, QPalette::Button, Qt::green); - QVERIFY(pp.isCopyOf(p)); } void tst_QPalette::isBrushSet() @@ -227,6 +217,14 @@ void tst_QPalette::isBrushSet() QVERIFY(p.isBrushSet(QPalette::Active, QPalette::LinkVisited)); QVERIFY(p.isBrushSet(QPalette::Inactive, QPalette::LinkVisited)); QVERIFY(p.isBrushSet(QPalette::Disabled, QPalette::LinkVisited)); + + // Don't set flag when brush doesn't change (and also don't detach - QTBUG-98762) + QPalette p2; + QPalette p3; + QVERIFY(!p2.isBrushSet(QPalette::Active, QPalette::Dark)); + p2.setBrush(QPalette::Active, QPalette::Dark, p2.brush(QPalette::Active, QPalette::Dark)); + QVERIFY(!p3.isBrushSet(QPalette::Active, QPalette::Dark)); + QVERIFY(p2.isBrushSet(QPalette::Active, QPalette::Dark)); } void tst_QPalette::setAllPossibleBrushes() @@ -240,8 +238,14 @@ void tst_QPalette::setAllPossibleBrushes() } for (int r = 0; r < QPalette::NColorRoles; ++r) { + const QPalette::ColorRole role = static_cast<QPalette::ColorRole>(r); for (int g = 0; g < QPalette::NColorGroups; ++g) { - QVERIFY(p.isBrushSet(QPalette::ColorGroup(g), QPalette::ColorRole(r))); + const QPalette::ColorGroup group = static_cast<QPalette::ColorGroup>(g); + // NoRole has no resolve bit => isBrushSet returns false + if (role == QPalette::NoRole) + QVERIFY(!p.isBrushSet(group, role)); + else + QVERIFY(p.isBrushSet(group, role)); } } } @@ -269,5 +273,120 @@ void tst_QPalette::checkIfBrushForCurrentGroupSet() QVERIFY(p.isBrushSet(QPalette::Current, QPalette::Link)); } +void tst_QPalette::cacheKey() +{ + const QPalette defaultPalette; + // precondition: all palettes are expected to have contrasting text on base + QVERIFY(defaultPalette.base() != defaultPalette.text()); + const auto defaultCacheKey = defaultPalette.cacheKey(); + const auto defaultSerNo = defaultCacheKey >> 32; + const auto defaultDetachNo = defaultCacheKey & 0xffffffff; + + QPalette changeTwicePalette(defaultPalette); + changeTwicePalette.setBrush(QPalette::All, QPalette::ButtonText, Qt::red); + const auto firstChangeCacheKey = changeTwicePalette.cacheKey(); + QCOMPARE_NE(firstChangeCacheKey, defaultCacheKey); + changeTwicePalette.setBrush(QPalette::All, QPalette::ButtonText, Qt::green); + const auto secondChangeCacheKey = changeTwicePalette.cacheKey(); + QCOMPARE_NE(firstChangeCacheKey, secondChangeCacheKey); + + QPalette copyDifferentData(defaultPalette); + QPalette copyDifferentMask(defaultPalette); + QPalette copyDifferentMaskAndData(defaultPalette); + + QCOMPARE(defaultPalette.cacheKey(), copyDifferentData.cacheKey()); + + // deep detach of both private and data + copyDifferentData.setBrush(QPalette::Base, defaultPalette.text()); + const auto differentDataKey = copyDifferentData.cacheKey(); + const auto differentDataSerNo = differentDataKey >> 32; + const auto differentDataDetachNo = differentDataKey & 0xffffffff; + auto loggerDeepDetach = qScopeGuard([&](){ + qDebug() << "Deep detach serial" << differentDataSerNo; + qDebug() << "Deep detach detach number" << differentDataDetachNo; + }); + + QCOMPARE_NE(copyDifferentData.cacheKey(), defaultCacheKey); + QCOMPARE(defaultPalette.cacheKey(), defaultCacheKey); + + // shallow detach, both privates reference the same data + copyDifferentMask.setResolveMask(0xffffffffffffffff); + const auto differentMaskKey = copyDifferentMask.cacheKey(); + const auto differentMaskSerNo = differentMaskKey >> 32; + const auto differentMaskDetachNo = differentMaskKey & 0xffffffff; + auto loggerShallowDetach = qScopeGuard([&](){ + qDebug() << "Shallow detach serial" << differentMaskSerNo; + qDebug() << "Shallow detach detach number" << differentMaskDetachNo; + }); + + QCOMPARE(differentMaskSerNo, defaultSerNo); + QCOMPARE_NE(differentMaskSerNo, defaultDetachNo); + QCOMPARE_NE(differentMaskKey, defaultCacheKey); + QCOMPARE_NE(differentMaskKey, differentDataKey); + + // shallow detach, both privates reference the same data + copyDifferentMaskAndData.setResolveMask(0xeeeeeeeeeeeeeeee); + const auto modifiedCacheKey = copyDifferentMaskAndData.cacheKey(); + QCOMPARE_NE(modifiedCacheKey, copyDifferentMask.cacheKey()); + QCOMPARE_NE(modifiedCacheKey, defaultCacheKey); + QCOMPARE_NE(modifiedCacheKey, copyDifferentData.cacheKey()); + QCOMPARE_NE(copyDifferentMask.cacheKey(), defaultCacheKey); + + // full detach - both key elements are different + copyDifferentMaskAndData.setBrush(QPalette::Base, defaultPalette.text()); + const auto modifiedAllKey = copyDifferentMaskAndData.cacheKey(); + const auto modifiedAllSerNo = modifiedAllKey >> 32; + const auto modifiedAllDetachNo = modifiedAllKey & 0xffffffff; + QCOMPARE_NE(modifiedAllSerNo, defaultSerNo); + QCOMPARE_NE(modifiedAllDetachNo, defaultDetachNo); + + QCOMPARE_NE(modifiedAllKey, copyDifferentMask.cacheKey()); + QCOMPARE_NE(modifiedAllKey, defaultCacheKey); + QCOMPARE_NE(modifiedAllKey, differentDataKey); + QCOMPARE_NE(modifiedAllKey, modifiedCacheKey); + + loggerDeepDetach.dismiss(); + loggerShallowDetach.dismiss(); +} + +void tst_QPalette::dataStream() +{ + const QColor highlight(42, 42, 42); + const QColor accent(13, 13, 13); + QPalette palette; + palette.setBrush(QPalette::Highlight, highlight); + palette.setBrush(QPalette::Accent, accent); + + // When saved with Qt_6_5 or earlier, Accent defaults to Highlight + { + QByteArray b; + { + QDataStream stream(&b, QIODevice::WriteOnly); + stream.setVersion(QDataStream::Qt_6_5); + stream << palette; + } + QPalette test; + QDataStream stream (&b, QIODevice::ReadOnly); + stream.setVersion(QDataStream::Qt_6_5); + stream >> test; + QCOMPARE(test.accent().color(), highlight); + } + + // When saved with Qt_6_6 or later, Accent is saved explicitly + { + QByteArray b; + { + QDataStream stream(&b, QIODevice::WriteOnly); + stream.setVersion(QDataStream::Qt_6_6); + stream << palette; + } + QPalette test; + QDataStream stream (&b, QIODevice::ReadOnly); + stream.setVersion(QDataStream::Qt_6_6); + stream >> test; + QCOMPARE(test.accent().color(), accent); + } +} + QTEST_MAIN(tst_QPalette) #include "tst_qpalette.moc" diff --git a/tests/auto/gui/kernel/qpixelformat/CMakeLists.txt b/tests/auto/gui/kernel/qpixelformat/CMakeLists.txt index 907564dc3d..c711ceeafa 100644 --- a/tests/auto/gui/kernel/qpixelformat/CMakeLists.txt +++ b/tests/auto/gui/kernel/qpixelformat/CMakeLists.txt @@ -1,12 +1,19 @@ -# Generated from qpixelformat.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qpixelformat Test: ##################################################################### -qt_add_test(tst_qpixelformat +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qpixelformat LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qpixelformat SOURCES tst_qpixelformat.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui ) diff --git a/tests/auto/gui/kernel/qpixelformat/qpixelformat.pro b/tests/auto/gui/kernel/qpixelformat/qpixelformat.pro deleted file mode 100644 index 970e5c7c2d..0000000000 --- a/tests/auto/gui/kernel/qpixelformat/qpixelformat.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase -TARGET = tst_qpixelformat - -QT += gui testlib - -SOURCES += tst_qpixelformat.cpp diff --git a/tests/auto/gui/kernel/qpixelformat/tst_qpixelformat.cpp b/tests/auto/gui/kernel/qpixelformat/tst_qpixelformat.cpp index 14d2b74491..d6d471bf6b 100644 --- a/tests/auto/gui/kernel/qpixelformat/tst_qpixelformat.cpp +++ b/tests/auto/gui/kernel/qpixelformat/tst_qpixelformat.cpp @@ -1,31 +1,6 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ -#include <QtTest/QtTest> +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include <QTest> #include <QtGui/qpixelformat.h> diff --git a/tests/auto/gui/kernel/qrasterwindow/CMakeLists.txt b/tests/auto/gui/kernel/qrasterwindow/CMakeLists.txt index 6b34b71dac..dc9d6a70c7 100644 --- a/tests/auto/gui/kernel/qrasterwindow/CMakeLists.txt +++ b/tests/auto/gui/kernel/qrasterwindow/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qrasterwindow.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qrasterwindow Test: ##################################################################### -qt_add_test(tst_qrasterwindow +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qrasterwindow LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qrasterwindow SOURCES tst_qrasterwindow.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/gui/kernel/qrasterwindow/qrasterwindow.pro b/tests/auto/gui/kernel/qrasterwindow/qrasterwindow.pro deleted file mode 100644 index 9acd7e510a..0000000000 --- a/tests/auto/gui/kernel/qrasterwindow/qrasterwindow.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase -TARGET = tst_qrasterwindow - -QT += core-private gui-private testlib - -SOURCES += tst_qrasterwindow.cpp diff --git a/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp b/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp index deb4837956..a06e360e35 100644 --- a/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp +++ b/tests/auto/gui/kernel/qrasterwindow/tst_qrasterwindow.cpp @@ -1,33 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtGui/QRasterWindow> -#include <QtTest/QtTest> +#include <QTest> #include <QtGui/QPainter> class tst_QRasterWindow : public QObject @@ -70,7 +45,7 @@ void tst_QRasterWindow::basic() w.reset(); w.resize(400, 400); w.show(); - QVERIFY(QTest::qWaitForWindowExposed(&w));; + QVERIFY(QTest::qWaitForWindowExposed(&w)); QVERIFY(w.paintCount >= 1); diff --git a/tests/auto/gui/kernel/qscreen/BLACKLIST b/tests/auto/gui/kernel/qscreen/BLACKLIST new file mode 100644 index 0000000000..ca3136fdb2 --- /dev/null +++ b/tests/auto/gui/kernel/qscreen/BLACKLIST @@ -0,0 +1,3 @@ +[grabWindow] +# QTBUG-100412 +windows diff --git a/tests/auto/gui/kernel/qscreen/CMakeLists.txt b/tests/auto/gui/kernel/qscreen/CMakeLists.txt index b073070155..8502176ca4 100644 --- a/tests/auto/gui/kernel/qscreen/CMakeLists.txt +++ b/tests/auto/gui/kernel/qscreen/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qscreen.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qscreen Test: ##################################################################### -qt_add_test(tst_qscreen +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qscreen LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qscreen SOURCES tst_qscreen.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/gui/kernel/qscreen/qscreen.pro b/tests/auto/gui/kernel/qscreen/qscreen.pro deleted file mode 100644 index b631f4cf37..0000000000 --- a/tests/auto/gui/kernel/qscreen/qscreen.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase -TARGET = tst_qscreen - -QT += core-private gui-private testlib - -SOURCES += tst_qscreen.cpp diff --git a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp index 57444a3888..74a03ac851 100644 --- a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp +++ b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp @@ -1,37 +1,16 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qpainter.h> #include <qrasterwindow.h> #include <qscreen.h> #include <qpa/qwindowsysteminterface.h> +#include <qpa/qplatformintegration.h> +#include <private/qguiapplication_p.h> +#include <private/qhighdpiscaling_p.h> -#include <QtTest/QtTest> +#include <QTest> +#include <QSignalSpy> class tst_QScreen: public QObject { @@ -179,34 +158,34 @@ void tst_QScreen::orientationChange() QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::LandscapeOrientation); QWindowSystemInterface::flushWindowSystemEvents(); QTRY_COMPARE(screen->orientation(), Qt::LandscapeOrientation); - QCOMPARE(spy.count(), ++expectedSignalCount); + QCOMPARE(spy.size(), ++expectedSignalCount); QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::PortraitOrientation); QWindowSystemInterface::flushWindowSystemEvents(); QTRY_COMPARE(screen->orientation(), Qt::PortraitOrientation); - QCOMPARE(spy.count(), ++expectedSignalCount); + QCOMPARE(spy.size(), ++expectedSignalCount); QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::InvertedLandscapeOrientation); QWindowSystemInterface::flushWindowSystemEvents(); QTRY_COMPARE(screen->orientation(), Qt::InvertedLandscapeOrientation); - QCOMPARE(spy.count(), ++expectedSignalCount); + QCOMPARE(spy.size(), ++expectedSignalCount); QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::InvertedPortraitOrientation); QWindowSystemInterface::flushWindowSystemEvents(); QTRY_COMPARE(screen->orientation(), Qt::InvertedPortraitOrientation); - QCOMPARE(spy.count(), ++expectedSignalCount); + QCOMPARE(spy.size(), ++expectedSignalCount); QWindowSystemInterface::handleScreenOrientationChange(screen, Qt::LandscapeOrientation); QWindowSystemInterface::flushWindowSystemEvents(); QTRY_COMPARE(screen->orientation(), Qt::LandscapeOrientation); - QCOMPARE(spy.count(), ++expectedSignalCount); + QCOMPARE(spy.size(), ++expectedSignalCount); } void tst_QScreen::grabWindow_data() { - if (QGuiApplication::platformName().startsWith(QLatin1String("offscreen"), Qt::CaseInsensitive)) - QSKIP("Offscreen: Screen grabbing not implemented."); - + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::ScreenWindowGrabbing) + || (QGuiApplication::platformName().toLower() == QStringLiteral("xcb") && !qEnvironmentVariableIsEmpty("WAYLAND_DISPLAY"))) + QSKIP("This platform does not support grabbing windows on screen."); QTest::addColumn<int>("screenIndex"); QTest::addColumn<QByteArray>("screenName"); QTest::addColumn<bool>("grabWindow"); @@ -278,20 +257,30 @@ void tst_QScreen::grabWindow() QCOMPARE(screen->name().toUtf8(), screenName); const double screenDpr = screen->devicePixelRatio(); + if (QHighDpiScaling::isActive()) { + const float rawFactor = QHighDpiScaling::factor(screen); + const float roundedFactor = qRound(rawFactor); + if (!qFuzzyCompare(roundedFactor, rawFactor)) + QSKIP("HighDPI enabled with non-integer factor. Skip due to possible rounding errors."); + } + Window window(screen); window.setGeometry(windowRect); +#ifndef Q_OS_ANDROID window.show(); +#else + window.showNormal(); +#endif if (!QTest::qWaitForWindowExposed(&window)) QSKIP("Failed to expose window - aborting"); - if (QGuiApplication::platformName().startsWith(QLatin1String("xcb"), Qt::CaseInsensitive)) - QTest::qWait(1500); // this is ridiculously necessary because of effects combined with slowness of VMs -#ifdef Q_OS_MACOS // wait for desktop on screen to scroll into place - QTest::qWait(1000); -#endif + // this is necessary because of scrolling effects combined with potential slowness of VMs + QTest::qWait(1500); - QSize expectedGrabSize = grabRect.isValid() ? grabRect.size() : (grabWindow ? windowRect.size() : screen->size()); + QSize expectedGrabSize = grabRect.isValid() + ? grabRect.size() + : (grabWindow ? windowRect.size() : screen->size()); // we ask for pixel coordinates, but will get a pixmap with device-specific DPR expectedGrabSize *= screen->devicePixelRatio(); @@ -299,7 +288,9 @@ void tst_QScreen::grabWindow() QImage paintedImage = window.image; QCOMPARE(paintedImage.devicePixelRatio(), screenDpr); - const QPixmap pixmap = screen->grabWindow(grabWindow ? window.winId() : 0, grabRect.x(), grabRect.y(), grabRect.width(), grabRect.height()); + const QPixmap pixmap = screen->grabWindow(grabWindow + ? window.winId() + : 0, grabRect.x(), grabRect.y(), grabRect.width(), grabRect.height()); QImage grabbedImage = pixmap.toImage(); const QSize grabbedSize = grabbedImage.size(); diff --git a/tests/auto/gui/kernel/qshortcut/CMakeLists.txt b/tests/auto/gui/kernel/qshortcut/CMakeLists.txt index 8c3c2556fe..517a4e8a1a 100644 --- a/tests/auto/gui/kernel/qshortcut/CMakeLists.txt +++ b/tests/auto/gui/kernel/qshortcut/CMakeLists.txt @@ -1,12 +1,20 @@ -# Generated from qshortcut.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qshortcut_kernel Test: ##################################################################### -qt_add_test(tst_qshortcut_kernel +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qshortcut_kernel LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qshortcut_kernel SOURCES tst_qshortcut.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui + Qt::GuiPrivate ) diff --git a/tests/auto/gui/kernel/qshortcut/qshortcut.pro b/tests/auto/gui/kernel/qshortcut/qshortcut.pro deleted file mode 100644 index 5dc016b099..0000000000 --- a/tests/auto/gui/kernel/qshortcut/qshortcut.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -TARGET = tst_qshortcut_kernel -QT += testlib -SOURCES += tst_qshortcut.cpp diff --git a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp index cc0492666d..cb6ebab800 100644 --- a/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp +++ b/tests/auto/gui/kernel/qshortcut/tst_qshortcut.cpp @@ -1,80 +1,59 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2019 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#include <QtTest/QtTest> +#include <QTest> #include <QtGui/qguiapplication.h> #include <QtGui/qshortcut.h> -#include <QtGui/qpainter.h> -#include <QtGui/qrasterwindow.h> -#include <QtGui/qscreen.h> #include <QtGui/qwindow.h> +#include <QtTest/qsignalspy.h> + +#include <QtGui/private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> class tst_QShortcut : public QObject { Q_OBJECT -public: private slots: - void trigger(); -}; - -class ColoredWindow : public QRasterWindow { -public: - ColoredWindow(QColor c) : m_color(c) {} - -protected: - void paintEvent(QPaintEvent *event) override; - -private: - const QColor m_color; + void applicationShortcut(); + void windowShortcut(); }; -void ColoredWindow::paintEvent(QPaintEvent *) +void tst_QShortcut::applicationShortcut() { - QPainter p(this); - p.fillRect(QRect(QPoint(), size()), m_color); + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("Window activation is not supported"); + + auto *shortcut = new QShortcut(Qt::CTRL | Qt::Key_A, this); + shortcut->setContext(Qt::ApplicationShortcut); + QSignalSpy activatedSpy(shortcut, &QShortcut::activated); + + // Need a window to send key event to, even if the shortcut is application + // global. The documentation for Qt::ApplicationShortcut also says that + // the shortcut "is active when one of the applications windows are active", + // but this is only honored for Qt Widgets, not for Qt Gui. For now we + // activate the window just in case. + QWindow window; + window.show(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + QTRY_COMPARE(QGuiApplication::applicationState(), Qt::ApplicationActive); + QTest::sendKeyEvent(QTest::Shortcut, &window, Qt::Key_A, 'a', Qt::ControlModifier); + + QVERIFY(activatedSpy.size() > 0); } -static void sendKey(QWindow *target, Qt::Key k, char c, Qt::KeyboardModifiers modifiers) +void tst_QShortcut::windowShortcut() { - QTest::sendKeyEvent(QTest::Press, target, k, c, modifiers); - QTest::sendKeyEvent(QTest::Release, target, k, c, modifiers); -} - -void tst_QShortcut::trigger() -{ - ColoredWindow w(Qt::yellow); - w.setTitle(QTest::currentTestFunction()); - w.resize(QGuiApplication::primaryScreen()->size() / 4); + QWindow w; new QShortcut(Qt::CTRL | Qt::Key_Q, &w, SLOT(close())); w.show(); QVERIFY(QTest::qWaitForWindowExposed(&w)); - sendKey(&w, Qt::Key_Q, 'q', Qt::ControlModifier); + + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QEXPECT_FAIL("", "It failed on Wayland, QTBUG-120334", Abort); + + QTRY_VERIFY(QGuiApplication::applicationState() == Qt::ApplicationActive); + QTest::sendKeyEvent(QTest::Click, &w, Qt::Key_Q, 'q', Qt::ControlModifier); QTRY_VERIFY(!w.isVisible()); } diff --git a/tests/auto/gui/kernel/qsurfaceformat/CMakeLists.txt b/tests/auto/gui/kernel/qsurfaceformat/CMakeLists.txt index 1d319aaddd..1303f48cf3 100644 --- a/tests/auto/gui/kernel/qsurfaceformat/CMakeLists.txt +++ b/tests/auto/gui/kernel/qsurfaceformat/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qsurfaceformat.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qsurfaceformat Test: ##################################################################### -qt_add_test(tst_qsurfaceformat +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qsurfaceformat LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qsurfaceformat SOURCES tst_qsurfaceformat.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate diff --git a/tests/auto/gui/kernel/qsurfaceformat/qsurfaceformat.pro b/tests/auto/gui/kernel/qsurfaceformat/qsurfaceformat.pro deleted file mode 100644 index 97d9d69fb7..0000000000 --- a/tests/auto/gui/kernel/qsurfaceformat/qsurfaceformat.pro +++ /dev/null @@ -1,6 +0,0 @@ -CONFIG += testcase -TARGET = tst_qsurfaceformat - -QT += core-private gui-private testlib - -SOURCES += tst_qsurfaceformat.cpp diff --git a/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp b/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp index 6fd768022c..3f655bd905 100644 --- a/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp +++ b/tests/auto/gui/kernel/qsurfaceformat/tst_qsurfaceformat.cpp @@ -1,34 +1,9 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qsurfaceformat.h> -#include <QtTest/QtTest> +#include <QTest> class tst_QSurfaceFormat: public QObject { diff --git a/tests/auto/gui/kernel/qtouchevent/BLACKLIST b/tests/auto/gui/kernel/qtouchevent/BLACKLIST index dcda77bce7..c4e4b2291d 100644 --- a/tests/auto/gui/kernel/qtouchevent/BLACKLIST +++ b/tests/auto/gui/kernel/qtouchevent/BLACKLIST @@ -1,2 +1,6 @@ -[multiPointRawEventTranslationOnTouchScreen] -ubuntu-16.04 +[multiPointRawEventTranslationOnTouchPad] +# QTBUG-101519 +windows-11 +android +[touchBeginWithGraphicsWidget] +android diff --git a/tests/auto/gui/kernel/qtouchevent/CMakeLists.txt b/tests/auto/gui/kernel/qtouchevent/CMakeLists.txt index a2976c351f..160263ac66 100644 --- a/tests/auto/gui/kernel/qtouchevent/CMakeLists.txt +++ b/tests/auto/gui/kernel/qtouchevent/CMakeLists.txt @@ -1,13 +1,20 @@ -# Generated from qtouchevent.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qtouchevent Test: ##################################################################### -qt_add_test(tst_qtouchevent +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qtouchevent LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qtouchevent SOURCES tst_qtouchevent.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::Gui Qt::GuiPrivate Qt::Widgets diff --git a/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro b/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro deleted file mode 100644 index 8506a005bc..0000000000 --- a/tests/auto/gui/kernel/qtouchevent/qtouchevent.pro +++ /dev/null @@ -1,4 +0,0 @@ -CONFIG += testcase -SOURCES=tst_qtouchevent.cpp -TARGET=tst_qtouchevent -QT += testlib widgets gui-private diff --git a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp index dd36a28854..37ddcb8962 100644 --- a/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp +++ b/tests/auto/gui/kernel/qtouchevent/tst_qtouchevent.cpp @@ -1,43 +1,26 @@ -/**************************************************************************** -** -** Copyright (C) 2020 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the $MODULE$ of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only +#include <QtGui/QCursor> #include <QtGui/QScreen> #include <QtWidgets/QGraphicsItem> #include <QtWidgets/QGraphicsScene> #include <QtWidgets/QGraphicsView> #include <QtWidgets/QGraphicsWidget> #include <QtWidgets/QWidget> -#include <QtTest/QtTest> +#include <QTest> +#include <QSet> +#include <QVarLengthArray> #include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface_p.h> #include <private/qevent_p.h> +#include <QtGui/private/qeventpoint_p.h> #include <private/qhighdpiscaling_p.h> #include <private/qpointingdevice_p.h> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> + +#include <QtCore/qpointer.h> Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests") @@ -67,6 +50,24 @@ public: deleteInTouchBegin = deleteInTouchUpdate = deleteInTouchEnd = false; } + void paintEvent(QPaintEvent *) override + { + QPainter painter(this); + painter.drawRect(rect()); + painter.setPen(Qt::darkGray); + painter.drawText(rect(), Qt::AlignHCenter | Qt::AlignCenter, objectName()); + static const QString pointFormat = QString::fromUtf8("\360\237\226\227 %1, %2"); + painter.setPen(Qt::darkGreen); + for (const auto &pt : std::as_const(touchBeginPoints)) + painter.drawText(pt.position(), pointFormat.arg(pt.position().toPoint().x()).arg(pt.position().toPoint().y())); + painter.setPen(Qt::darkYellow); + for (const auto &pt : std::as_const(touchUpdatePoints)) + painter.drawText(pt.position(), pointFormat.arg(pt.position().toPoint().x()).arg(pt.position().toPoint().y())); + painter.setPen(Qt::darkRed); + for (const auto &pt : std::as_const(touchEndPoints)) + painter.drawText(pt.position(), pointFormat.arg(pt.position().toPoint().x()).arg(pt.position().toPoint().y())); + } + bool event(QEvent *event) override { lastNormalizedPositions.clear(); @@ -78,15 +79,17 @@ public: if (seenTouchEnd) qWarning("TouchBegin: TouchEnd cannot happen before TouchBegin"); seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd; auto touchEvent = static_cast<QTouchEvent *>(event); - touchBeginPoints = touchEvent->touchPoints(); + touchBeginPoints = touchEvent->points(); Q_ASSERT(touchBeginPoints.first().device() == touchEvent->pointingDevice()); - for (const QEventPoint &pt : touchEvent->touchPoints()) - lastNormalizedPositions << pt.normalizedPos(); + for (const QEventPoint &pt : std::as_const(touchBeginPoints)) + lastNormalizedPositions << pt.normalizedPosition(); timestamp = touchEvent->timestamp(); deviceFromEvent = touchEvent->pointingDevice(); event->setAccepted(acceptTouchBegin); if (deleteInTouchBegin) delete this; + else + update(); break; } case QEvent::TouchUpdate: { @@ -95,14 +98,16 @@ public: if (seenTouchEnd) qWarning("TouchUpdate: TouchEnd cannot happen before TouchUpdate"); seenTouchUpdate = seenTouchBegin && !seenTouchEnd; auto touchEvent = static_cast<QTouchEvent *>(event); - touchUpdatePoints = touchEvent->touchPoints(); - for (const QEventPoint &pt : touchEvent->touchPoints()) - lastNormalizedPositions << pt.normalizedPos(); + touchUpdatePoints = touchEvent->points(); + for (const QEventPoint &pt : std::as_const(touchUpdatePoints)) + lastNormalizedPositions << pt.normalizedPosition(); timestamp = touchEvent->timestamp(); deviceFromEvent = touchEvent->pointingDevice(); event->setAccepted(acceptTouchUpdate); if (deleteInTouchUpdate) delete this; + else + update(); break; } case QEvent::TouchEnd: { @@ -111,14 +116,16 @@ public: if (seenTouchEnd) qWarning("TouchEnd: already seen a TouchEnd"); seenTouchEnd = seenTouchBegin && !seenTouchEnd; auto touchEvent = static_cast<QTouchEvent *>(event); - touchEndPoints = touchEvent->touchPoints(); - for (const QEventPoint &pt : touchEvent->touchPoints()) - lastNormalizedPositions << pt.normalizedPos(); + touchEndPoints = touchEvent->points(); + for (const QEventPoint &pt : std::as_const(touchEndPoints)) + lastNormalizedPositions << pt.normalizedPosition(); timestamp = touchEvent->timestamp(); deviceFromEvent = touchEvent->pointingDevice(); event->setAccepted(acceptTouchEnd); if (deleteInTouchEnd) delete this; + else + update(); break; } default: @@ -177,7 +184,7 @@ public: if (seenTouchEnd) qWarning("TouchBegin: TouchEnd cannot happen before TouchBegin"); seenTouchBegin = !seenTouchBegin && !seenTouchUpdate && !seenTouchEnd; ++touchBeginCounter; - touchBeginPoints = static_cast<QTouchEvent *>(event)->touchPoints(); + touchBeginPoints = static_cast<QTouchEvent *>(event)->points(); event->setAccepted(acceptTouchBegin); if (deleteInTouchBegin) delete this; @@ -188,7 +195,7 @@ public: if (seenTouchEnd) qWarning("TouchUpdate: TouchEnd cannot happen before TouchUpdate"); seenTouchUpdate = seenTouchBegin && !seenTouchEnd; ++touchUpdateCounter; - touchUpdatePoints = static_cast<QTouchEvent *>(event)->touchPoints(); + touchUpdatePoints = static_cast<QTouchEvent *>(event)->points(); event->setAccepted(acceptTouchUpdate); if (deleteInTouchUpdate) delete this; @@ -199,7 +206,7 @@ public: if (seenTouchEnd) qWarning("TouchEnd: already seen a TouchEnd"); seenTouchEnd = seenTouchBegin && !seenTouchEnd; ++touchEndCounter; - touchEndPoints = static_cast<QTouchEvent *>(event)->touchPoints(); + touchEndPoints = static_cast<QTouchEvent *>(event)->points(); event->setAccepted(acceptTouchEnd); if (deleteInTouchEnd) delete this; @@ -343,26 +350,32 @@ void tst_QTouchEvent::state() QVERIFY(!touchEvent.isEndEvent()); QVERIFY(touchEvent.isInputEvent()); QVERIFY(touchEvent.isPointerEvent()); - - touchEvent = QTouchEvent(QEvent::TouchBegin, touchScreenDevice, - Qt::NoModifier, QList<QEventPoint>() << - QEventPoint(0, QEventPoint::State::Updated, {}, {}) << - QEventPoint(1, QEventPoint::State::Pressed, {}, {})); - QCOMPARE(touchEvent.touchPointStates(), QEventPoint::State::Updated | QEventPoint::State::Pressed); - QCOMPARE(touchEvent.pointCount(), 2); - QVERIFY(touchEvent.isBeginEvent()); - QVERIFY(!touchEvent.isUpdateEvent()); - QVERIFY(!touchEvent.isEndEvent()); - - touchEvent = QTouchEvent(QEvent::TouchBegin, touchScreenDevice, - Qt::NoModifier, QList<QEventPoint>() << - QEventPoint(0, QEventPoint::State::Updated, {}, {}) << - QEventPoint(1, QEventPoint::State::Released, {}, {})); - QCOMPARE(touchEvent.touchPointStates(), QEventPoint::State::Updated | QEventPoint::State::Released); - QCOMPARE(touchEvent.pointCount(), 2); - QVERIFY(!touchEvent.isBeginEvent()); - QVERIFY(!touchEvent.isUpdateEvent()); - QVERIFY(touchEvent.isEndEvent()); + QVERIFY(!touchEvent.isSinglePointEvent()); + + QTouchEvent touchEvent2 = QTouchEvent(QEvent::TouchBegin, touchScreenDevice, + Qt::NoModifier, QList<QEventPoint>() << + QEventPoint(0, QEventPoint::State::Updated, {}, {}) << + QEventPoint(1, QEventPoint::State::Pressed, {}, {})); + QCOMPARE(touchEvent2.touchPointStates(), QEventPoint::State::Updated | QEventPoint::State::Pressed); + QCOMPARE(touchEvent2.pointCount(), 2); + QVERIFY(touchEvent2.isBeginEvent()); + QVERIFY(!touchEvent2.isUpdateEvent()); + QVERIFY(!touchEvent2.isEndEvent()); + + QTouchEvent touchEvent3 = QTouchEvent(QEvent::TouchBegin, touchScreenDevice, + Qt::NoModifier, QList<QEventPoint>() << + QEventPoint(0, QEventPoint::State::Updated, {}, {}) << + QEventPoint(1, QEventPoint::State::Released, {}, {})); + QCOMPARE(touchEvent3.touchPointStates(), QEventPoint::State::Updated | QEventPoint::State::Released); + QCOMPARE(touchEvent3.pointCount(), 2); + QVERIFY(!touchEvent3.isBeginEvent()); + QVERIFY(!touchEvent3.isUpdateEvent()); + QVERIFY(touchEvent3.isEndEvent()); +#if QT_DEPRECATED_SINCE(6, 0) + QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED // test Qt 5 compatibility wrappers + QCOMPARE(touchEvent3.touchPoints(), touchEvent3.points()); + QT_WARNING_POP +#endif } void tst_QTouchEvent::touchDisabledByDefault() @@ -398,11 +411,11 @@ void tst_QTouchEvent::touchDisabledByDefault() QVERIFY(!item.acceptTouchEvents()); // compose an event to the scene that is over the item - QMutableEventPoint touchPoint(0); - touchPoint.setState(QEventPoint::State::Pressed); - touchPoint.setPosition(view.mapFromScene(item.mapToScene(item.boundingRect().center()))); - touchPoint.setGlobalPosition(view.mapToGlobal(touchPoint.position().toPoint())); - touchPoint.setScenePosition(view.mapToScene(touchPoint.position().toPoint())); + QEventPoint touchPoint(0); + QMutableEventPoint::setState(touchPoint, QEventPoint::State::Pressed); + QMutableEventPoint::setPosition(touchPoint, view.mapFromScene(item.mapToScene(item.boundingRect().center()))); + QMutableEventPoint::setGlobalPosition(touchPoint, view.mapToGlobal(touchPoint.position().toPoint())); + QMutableEventPoint::setScenePosition(touchPoint, view.mapToScene(touchPoint.position().toPoint())); QTouchEvent touchEvent(QEvent::TouchBegin, touchScreenDevice, @@ -439,6 +452,7 @@ void tst_QTouchEvent::touchEventAcceptedByDefault() touchEvent.ignore(); QVERIFY(QApplication::sendEvent(&touchWidget, &touchEvent)); QVERIFY(touchEvent.isAccepted()); + QVERIFY(touchEvent.allPointsAccepted()); } // QGraphicsView @@ -457,16 +471,17 @@ void tst_QTouchEvent::touchEventAcceptedByDefault() // compose an event to the scene that is over the item QPointF pos = view.mapFromScene(item.mapToScene(item.boundingRect().center())); - QMutableEventPoint touchPoint(0, QEventPoint::State::Pressed, - view.mapToScene(pos.toPoint()), - view.mapToGlobal(pos.toPoint())); - touchPoint.setPosition(pos); + QEventPoint touchPoint(0, QEventPoint::State::Pressed, + view.mapToScene(pos.toPoint()), + view.mapToGlobal(pos.toPoint())); + QMutableEventPoint::setPosition(touchPoint, pos); QTouchEvent touchEvent(QEvent::TouchBegin, touchScreenDevice, Qt::NoModifier, (QList<QEventPoint>() << touchPoint)); QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent)); QVERIFY(touchEvent.isAccepted()); + QVERIFY(touchEvent.allPointsAccepted()); QVERIFY(item.seenTouchBegin); } } @@ -493,6 +508,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored() touchPoints); QVERIFY(QApplication::sendEvent(&grandchild, &touchEvent)); QVERIFY(touchEvent.isAccepted()); + QVERIFY(touchEvent.allPointsAccepted()); QVERIFY(grandchild.seenTouchBegin); QVERIFY(child.seenTouchBegin); QVERIFY(!window.seenTouchBegin); @@ -507,6 +523,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored() touchEvent.ignore(); QVERIFY(QApplication::sendEvent(&grandchild, &touchEvent)); QVERIFY(touchEvent.isAccepted()); + QVERIFY(touchEvent.allPointsAccepted()); QVERIFY(!grandchild.seenTouchBegin); QVERIFY(child.seenTouchBegin); QVERIFY(!window.seenTouchBegin); @@ -541,6 +558,7 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored() (QList<QEventPoint>() << touchPoint)); QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent)); QVERIFY(touchEvent.isAccepted()); + QVERIFY(touchEvent.allPointsAccepted()); QVERIFY(grandchild.seenTouchBegin); QVERIFY(child.seenTouchBegin); QVERIFY(!root.seenTouchBegin); @@ -565,16 +583,17 @@ void tst_QTouchEvent::touchBeginPropagatesWhenIgnored() // compose an event to the scene that is over the grandchild QPointF pos = view.mapFromScene(grandchild.mapToScene(grandchild.boundingRect().center())); - QMutableEventPoint touchPoint(0, QEventPoint::State::Pressed, - view.mapToScene(pos.toPoint()), - view.mapToGlobal(pos.toPoint())); - touchPoint.setPosition(pos); + QEventPoint touchPoint(0, QEventPoint::State::Pressed, + view.mapToScene(pos.toPoint()), + view.mapToGlobal(pos.toPoint())); + QMutableEventPoint::setPosition(touchPoint, pos); QTouchEvent touchEvent(QEvent::TouchBegin, touchScreenDevice, Qt::NoModifier, (QList<QEventPoint>() << touchPoint)); QVERIFY(QApplication::sendEvent(view.viewport(), &touchEvent)); QVERIFY(touchEvent.isAccepted()); + QVERIFY(touchEvent.allPointsAccepted()); QVERIFY(!grandchild.seenTouchBegin); QVERIFY(child.seenTouchBegin); QVERIFY(!root.seenTouchBegin); @@ -601,6 +620,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate() touchPoints); QVERIFY(QApplication::sendEvent(&child, &touchBeginEvent)); QVERIFY(touchBeginEvent.isAccepted()); + QVERIFY(touchBeginEvent.allPointsAccepted()); QVERIFY(child.seenTouchBegin); QVERIFY(!window.seenTouchBegin); @@ -611,6 +631,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate() touchPoints); QVERIFY(QApplication::sendEvent(&child, &touchUpdateEvent)); QVERIFY(!touchUpdateEvent.isAccepted()); + QVERIFY(!touchBeginEvent.allPointsAccepted()); QVERIFY(child.seenTouchUpdate); QVERIFY(!window.seenTouchUpdate); @@ -621,6 +642,7 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate() touchPoints); QVERIFY(QApplication::sendEvent(&child, &touchEndEvent)); QVERIFY(!touchEndEvent.isAccepted()); + QVERIFY(!touchBeginEvent.allPointsAccepted()); QVERIFY(child.seenTouchEnd); QVERIFY(!window.seenTouchEnd); } @@ -644,24 +666,25 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate() // compose an event to the scene that is over the child QPointF pos = view.mapFromScene(grandchild.mapToScene(grandchild.boundingRect().center())); - QMutableEventPoint touchPoint(0, QEventPoint::State::Pressed, - view.mapToScene(pos.toPoint()), - view.mapToGlobal(pos.toPoint())); - touchPoint.setPosition(pos); + QEventPoint touchPoint(0, QEventPoint::State::Pressed, + view.mapToScene(pos.toPoint()), + view.mapToGlobal(pos.toPoint())); + QMutableEventPoint::setPosition(touchPoint, pos); QTouchEvent touchBeginEvent(QEvent::TouchBegin, touchScreenDevice, Qt::NoModifier, (QList<QEventPoint>() << touchPoint)); QVERIFY(QApplication::sendEvent(view.viewport(), &touchBeginEvent)); QVERIFY(touchBeginEvent.isAccepted()); + QVERIFY(touchBeginEvent.allPointsAccepted()); QVERIFY(child.seenTouchBegin); QVERIFY(!root.seenTouchBegin); // send the touch update to the child, but ignore it, it doesn't propagate - touchPoint = QMutableEventPoint(0, QEventPoint::State::Updated, - view.mapToScene(pos.toPoint()), - view.mapToGlobal(pos.toPoint())); - touchPoint.setPosition(pos); + touchPoint = QEventPoint(0, QEventPoint::State::Updated, + view.mapToScene(pos.toPoint()), + view.mapToGlobal(pos.toPoint())); + QMutableEventPoint::setPosition(touchPoint, pos); QTouchEvent touchUpdateEvent(QEvent::TouchUpdate, touchScreenDevice, Qt::NoModifier, @@ -673,10 +696,10 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate() QVERIFY(!root.seenTouchUpdate); // send the touch end, same thing should happen as with touch update - touchPoint = QMutableEventPoint(0, QEventPoint::State::Released, - view.mapToScene(pos.toPoint()), - view.mapToGlobal(pos.toPoint())); - touchPoint.setPosition(pos); + touchPoint = QEventPoint(0, QEventPoint::State::Released, + view.mapToScene(pos.toPoint()), + view.mapToGlobal(pos.toPoint())); + QMutableEventPoint::setPosition(touchPoint, pos); QTouchEvent touchEndEvent(QEvent::TouchEnd, touchScreenDevice, Qt::NoModifier, @@ -689,11 +712,6 @@ void tst_QTouchEvent::touchUpdateAndEndNeverPropagate() } } -QPointF normalized(const QPointF &pos, const QRectF &rect) -{ - return QPointF(pos.x() / rect.width(), pos.y() / rect.height()); -} - void tst_QTouchEvent::basicRawEventTranslation() { tst_QTouchEventWidget touchWidget; @@ -718,7 +736,7 @@ void tst_QTouchEvent::basicRawEventTranslation() QVERIFY(touchWidget.seenTouchBegin); QVERIFY(!touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchBeginPoints.count(), 1); + QCOMPARE(touchWidget.touchBeginPoints.size(), 1); QCOMPARE(touchWidget.timestamp, timestamp); QEventPoint touchBeginPoint = touchWidget.touchBeginPoints.first(); QCOMPARE(touchBeginPoint.id(), 0); @@ -748,7 +766,7 @@ void tst_QTouchEvent::basicRawEventTranslation() QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchUpdatePoints.count(), 1); + QCOMPARE(touchWidget.touchUpdatePoints.size(), 1); QEventPoint touchUpdatePoint = touchWidget.touchUpdatePoints.first(); QCOMPARE(touchUpdatePoint.id(), 0); QCOMPARE(touchUpdatePoint.state(), rawTouchPoint.state()); @@ -776,7 +794,7 @@ void tst_QTouchEvent::basicRawEventTranslation() QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QVERIFY(touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchEndPoints.count(), 1); + QCOMPARE(touchWidget.touchEndPoints.size(), 1); QEventPoint touchEndPoint = touchWidget.touchEndPoints.first(); QCOMPARE(touchEndPoint.id(), 0); QCOMPARE(touchEndPoint.state(), rawTouchPoint.state()); @@ -799,9 +817,11 @@ void tst_QTouchEvent::basicRawEventTranslation() void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() { tst_QTouchEventWidget touchWidget; + touchWidget.setObjectName("parent touch widget"); touchWidget.setWindowTitle(QTest::currentTestFunction()); touchWidget.setAttribute(Qt::WA_AcceptTouchEvents); - touchWidget.setGeometry(100, 100, 400, 300); + const QPoint topLeft = QGuiApplication::primaryScreen()->availableGeometry().topLeft() + QPoint(100, 100); + touchWidget.setGeometry({topLeft, QSize(400, 300)}); tst_QTouchEventWidget leftWidget(&touchWidget); leftWidget.setObjectName("leftWidget"); @@ -815,24 +835,25 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() touchWidget.show(); QVERIFY(QTest::qWaitForWindowExposed(&touchWidget)); + if (touchWidget.geometry().topLeft() != topLeft) { + qCDebug(lcTests) << "tried to set position 100, 100 on screen; got geometry" + << touchWidget.geometry() << "frame" << touchWidget.frameGeometry(); + QSKIP("failed to position the widget window on this platform"); + } - QPointF leftPos = leftWidget.rect().center(); - QPointF rightPos = rightWidget.rect().center(); - QPointF centerPos = touchWidget.rect().center(); - QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint()); - QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint()); - QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint()); + QPoint leftPos = leftWidget.rect().center(); + QPoint rightPos = rightWidget.rect().center(); + QPoint centerPos = touchWidget.rect().center(); + QPoint leftScenePos = leftWidget.mapToParent(leftPos); + QPoint rightScenePos = rightWidget.mapToParent(rightPos); + QPoint leftScreenPos = leftWidget.mapToGlobal(leftPos); + QPoint rightScreenPos = rightWidget.mapToGlobal(rightPos); + QPoint centerScreenPos = touchWidget.mapToGlobal(centerPos); // generate TouchBegins on both leftWidget and rightWidget - ulong timestamp = 0; - auto rawTouchPoints = QList<QEventPoint>() - << QEventPoint(0, QEventPoint::State::Pressed, QPointF(), leftScreenPos) - << QEventPoint(1, QEventPoint::State::Pressed, QPointF(), rightScreenPos); - QWindow *window = touchWidget.windowHandle(); - QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints = - QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); - QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints); - QCoreApplication::processEvents(); + auto touchSequence = QTest::touchEvent(touchWidget.windowHandle(), touchScreenDevice); + touchSequence.press(0, leftScenePos).press(1, rightScenePos); + QVERIFY(touchSequence.commit()); // verify acceptance QVERIFY(!touchWidget.seenTouchBegin); QVERIFY(!touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); @@ -842,14 +863,14 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() QVERIFY(rightWidget.seenTouchBegin); QVERIFY(!rightWidget.seenTouchUpdate); QVERIFY(!rightWidget.seenTouchEnd); - QCOMPARE(leftWidget.touchBeginPoints.count(), 1); - QCOMPARE(rightWidget.touchBeginPoints.count(), 1); + QCOMPARE(leftWidget.touchBeginPoints.size(), 1); + QCOMPARE(rightWidget.touchBeginPoints.size(), 1); const int touchPointId0 = 0; const int touchPointId1 = touchPointId0 + 1; { - QEventPoint leftTouchPoint = leftWidget.touchBeginPoints.first(); + const QEventPoint &leftTouchPoint = leftWidget.touchBeginPoints.first(); QCOMPARE(leftTouchPoint.id(), touchPointId0); - QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state()); + QCOMPARE(leftTouchPoint.state(), QEventPoint::Pressed); QCOMPARE(leftTouchPoint.position(), leftPos); QCOMPARE(leftTouchPoint.pressPosition(), leftPos); QCOMPARE(leftTouchPoint.lastPosition(), leftPos); @@ -859,15 +880,12 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() QCOMPARE(leftTouchPoint.globalPosition(), leftScreenPos); QCOMPARE(leftTouchPoint.globalPressPosition(), leftScreenPos); QCOMPARE(leftTouchPoint.globalLastPosition(), leftScreenPos); - QCOMPARE(leftTouchPoint.position(), leftPos); - QCOMPARE(leftTouchPoint.scenePosition(), leftScreenPos); - QCOMPARE(leftTouchPoint.globalPosition(), leftScreenPos); QCOMPARE(leftTouchPoint.ellipseDiameters(), QSizeF(0, 0)); QCOMPARE(leftTouchPoint.pressure(), qreal(1.)); - QEventPoint rightTouchPoint = rightWidget.touchBeginPoints.first(); + const QEventPoint &rightTouchPoint = rightWidget.touchBeginPoints.first(); QCOMPARE(rightTouchPoint.id(), touchPointId1); - QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state()); + QCOMPARE(rightTouchPoint.state(), QEventPoint::Pressed); QCOMPARE(rightTouchPoint.position(), rightPos); QCOMPARE(rightTouchPoint.pressPosition(), rightPos); QCOMPARE(rightTouchPoint.lastPosition(), rightPos); @@ -877,20 +895,13 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() QCOMPARE(rightTouchPoint.globalPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.globalPressPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.globalLastPosition(), rightScreenPos); - QCOMPARE(rightTouchPoint.position(), rightPos); - QCOMPARE(rightTouchPoint.scenePosition(), rightScreenPos); - QCOMPARE(rightTouchPoint.globalPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); QCOMPARE(rightTouchPoint.pressure(), qreal(1.)); } - rawTouchPoints.clear(); - rawTouchPoints << QEventPoint(0, QEventPoint::State::Updated, QPointF(), centerScreenPos) - << QEventPoint(1, QEventPoint::State::Updated, QPointF(), centerScreenPos); - nativeTouchPoints = - QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); - QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints); - QCoreApplication::processEvents(); + // an unlikely event with the two touchpoints moving exactly on top of each other + touchSequence.move(0, centerPos).move(1, centerPos); + QVERIFY(touchSequence.commit()); // verify acceptance QVERIFY(!touchWidget.seenTouchBegin); QVERIFY(!touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); @@ -900,13 +911,13 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() QVERIFY(rightWidget.seenTouchBegin); QVERIFY(rightWidget.seenTouchUpdate); QVERIFY(!rightWidget.seenTouchEnd); - QCOMPARE(leftWidget.touchUpdatePoints.count(), 1); - QCOMPARE(rightWidget.touchUpdatePoints.count(), 1); + QCOMPARE(leftWidget.touchUpdatePoints.size(), 1); + QCOMPARE(rightWidget.touchUpdatePoints.size(), 1); { - QEventPoint leftTouchPoint = leftWidget.touchUpdatePoints.first(); + const QEventPoint &leftTouchPoint = leftWidget.touchUpdatePoints.first(); QCOMPARE(leftTouchPoint.id(), touchPointId0); - QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state()); - QCOMPARE(leftTouchPoint.position(), QPointF(leftWidget.mapFromParent(centerPos.toPoint()))); + QCOMPARE(leftTouchPoint.state(), QEventPoint::Updated); + QCOMPARE(leftTouchPoint.position(), QPointF(leftWidget.mapFromParent(centerPos))); QCOMPARE(leftTouchPoint.pressPosition(), leftPos); QCOMPARE(leftTouchPoint.lastPosition(), leftPos); QCOMPARE(leftTouchPoint.scenePosition(), centerScreenPos); @@ -915,16 +926,13 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() QCOMPARE(leftTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(leftTouchPoint.globalPressPosition(), leftScreenPos); QCOMPARE(leftTouchPoint.globalLastPosition(), leftScreenPos); - QCOMPARE(leftTouchPoint.position(), leftWidget.mapFromParent(centerPos.toPoint())); - QCOMPARE(leftTouchPoint.scenePosition(), centerScreenPos); - QCOMPARE(leftTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(leftTouchPoint.ellipseDiameters(), QSizeF(0, 0)); QCOMPARE(leftTouchPoint.pressure(), qreal(1.)); - QEventPoint rightTouchPoint = rightWidget.touchUpdatePoints.first(); + const QEventPoint &rightTouchPoint = rightWidget.touchUpdatePoints.first(); QCOMPARE(rightTouchPoint.id(), touchPointId1); - QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state()); - QCOMPARE(rightTouchPoint.position(), QPointF(rightWidget.mapFromParent(centerPos.toPoint()))); + QCOMPARE(rightTouchPoint.state(), QEventPoint::Updated); + QCOMPARE(rightTouchPoint.position(), QPointF(rightWidget.mapFromParent(centerPos))); QCOMPARE(rightTouchPoint.pressPosition(), rightPos); QCOMPARE(rightTouchPoint.lastPosition(), rightPos); QCOMPARE(rightTouchPoint.scenePosition(), centerScreenPos); @@ -933,21 +941,13 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() QCOMPARE(rightTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(rightTouchPoint.globalPressPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.globalLastPosition(), rightScreenPos); - QCOMPARE(rightTouchPoint.position(), rightWidget.mapFromParent(centerPos.toPoint())); - QCOMPARE(rightTouchPoint.scenePosition(), centerScreenPos); - QCOMPARE(rightTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); QCOMPARE(rightTouchPoint.pressure(), qreal(1.)); } // generate TouchEnds on both leftWidget and rightWidget - rawTouchPoints.clear(); - rawTouchPoints << QEventPoint(0, QEventPoint::State::Released, QPointF(), centerScreenPos) - << QEventPoint(1, QEventPoint::State::Released, QPointF(), centerScreenPos); - nativeTouchPoints = - QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); - QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints); - QCoreApplication::processEvents(); + touchSequence.release(0, centerPos).release(1, centerPos); + QVERIFY(touchSequence.commit()); // verify acceptance QVERIFY(!touchWidget.seenTouchBegin); QVERIFY(!touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); @@ -957,13 +957,13 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() QVERIFY(rightWidget.seenTouchBegin); QVERIFY(rightWidget.seenTouchUpdate); QVERIFY(rightWidget.seenTouchEnd); - QCOMPARE(leftWidget.touchEndPoints.count(), 1); - QCOMPARE(rightWidget.touchEndPoints.count(), 1); + QCOMPARE(leftWidget.touchEndPoints.size(), 1); + QCOMPARE(rightWidget.touchEndPoints.size(), 1); { - QEventPoint leftTouchPoint = leftWidget.touchEndPoints.first(); + const QEventPoint &leftTouchPoint = leftWidget.touchEndPoints.first(); QCOMPARE(leftTouchPoint.id(), touchPointId0); - QCOMPARE(leftTouchPoint.state(), rawTouchPoints[0].state()); - QCOMPARE(leftTouchPoint.position(), QPointF(leftWidget.mapFromParent(centerPos.toPoint()))); + QCOMPARE(leftTouchPoint.state(), QEventPoint::Released); + QCOMPARE(leftTouchPoint.position(), QPointF(leftWidget.mapFromParent(centerPos))); QCOMPARE(leftTouchPoint.pressPosition(), leftPos); QCOMPARE(leftTouchPoint.lastPosition(), leftPos); QCOMPARE(leftTouchPoint.scenePosition(), centerScreenPos); @@ -972,16 +972,13 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() QCOMPARE(leftTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(leftTouchPoint.globalPressPosition(), leftScreenPos); QCOMPARE(leftTouchPoint.globalLastPosition(), leftScreenPos); - QCOMPARE(leftTouchPoint.position(), leftWidget.mapFromParent(centerPos.toPoint())); - QCOMPARE(leftTouchPoint.scenePosition(), centerScreenPos); - QCOMPARE(leftTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(leftTouchPoint.ellipseDiameters(), QSizeF(0, 0)); QCOMPARE(leftTouchPoint.pressure(), qreal(0.)); - QEventPoint rightTouchPoint = rightWidget.touchEndPoints.first(); + const QEventPoint &rightTouchPoint = rightWidget.touchEndPoints.first(); QCOMPARE(rightTouchPoint.id(), touchPointId1); - QCOMPARE(rightTouchPoint.state(), rawTouchPoints[1].state()); - QCOMPARE(rightTouchPoint.position(), QPointF(rightWidget.mapFromParent(centerPos.toPoint()))); + QCOMPARE(rightTouchPoint.state(), QEventPoint::Released); + QCOMPARE(rightTouchPoint.position(), QPointF(rightWidget.mapFromParent(centerPos))); QCOMPARE(rightTouchPoint.pressPosition(), rightPos); QCOMPARE(rightTouchPoint.lastPosition(), rightPos); QCOMPARE(rightTouchPoint.scenePosition(), centerScreenPos); @@ -990,9 +987,6 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchScreen() QCOMPARE(rightTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(rightTouchPoint.globalPressPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.globalLastPosition(), rightScreenPos); - QCOMPARE(rightTouchPoint.position(), rightWidget.mapFromParent(centerPos.toPoint())); - QCOMPARE(rightTouchPoint.scenePosition(), centerScreenPos); - QCOMPARE(rightTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); QCOMPARE(rightTouchPoint.pressure(), qreal(0.)); } @@ -1016,13 +1010,13 @@ void tst_QTouchEvent::touchOnMultipleTouchscreens() // this should be translated to a TouchBegin QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QEventPoint>() << - QMutableEventPoint(1234, 1, QEventPoint::State::Pressed, screenPos, screenPos, screenPos), window); + QMutableEventPoint::withTimeStamp(1234, 1, QEventPoint::State::Pressed, screenPos, screenPos, screenPos), window); QWindowSystemInterface::handleTouchEvent(window, timestamp, touchScreenDevice, nativeTouchPoints); QCoreApplication::processEvents(); QVERIFY(touchWidget.seenTouchBegin); QVERIFY(!touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchBeginPoints.count(), 1); + QCOMPARE(touchWidget.touchBeginPoints.size(), 1); QCOMPARE(touchWidget.timestamp, timestamp); QEventPoint touchBeginPoint = touchWidget.touchBeginPoints.first(); QCOMPARE(touchBeginPoint.id(), 1); @@ -1033,11 +1027,11 @@ void tst_QTouchEvent::touchOnMultipleTouchscreens() touchWidget.seenTouchBegin = false; nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QEventPoint>() << - QMutableEventPoint(1234, 10, QEventPoint::State::Pressed, screenPos, screenPos, screenPos), window); + QMutableEventPoint::withTimeStamp(1234, 10, QEventPoint::State::Pressed, screenPos, screenPos, screenPos), window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints); QCoreApplication::processEvents(); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchBeginPoints.count(), 1); + QCOMPARE(touchWidget.touchBeginPoints.size(), 1); QCOMPARE(touchWidget.timestamp, timestamp); touchBeginPoint = touchWidget.touchBeginPoints[0]; QCOMPARE(touchBeginPoint.id(), 10); @@ -1048,11 +1042,11 @@ void tst_QTouchEvent::touchOnMultipleTouchscreens() touchWidget.seenTouchBegin = false; nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QEventPoint>() << - QMutableEventPoint(1234, 11, QEventPoint::State::Pressed, screenPos, screenPos, screenPos), window); + QMutableEventPoint::withTimeStamp(1234, 11, QEventPoint::State::Pressed, screenPos, screenPos, screenPos), window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints); QCoreApplication::processEvents(); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchBeginPoints.count(), 1); + QCOMPARE(touchWidget.touchBeginPoints.size(), 1); QCOMPARE(touchWidget.timestamp, timestamp); touchBeginPoint = touchWidget.touchBeginPoints[0]; QCOMPARE(touchBeginPoint.id(), 11); @@ -1062,13 +1056,13 @@ void tst_QTouchEvent::touchOnMultipleTouchscreens() // moving the first point should translate to TouchUpdate nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QEventPoint>() << - QMutableEventPoint(1234, 1, QEventPoint::State::Updated, screenPos + delta, screenPos + delta, screenPos + delta), window); + QMutableEventPoint::withTimeStamp(1234, 1, QEventPoint::State::Updated, screenPos + delta, screenPos + delta, screenPos + delta), window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints); QCoreApplication::processEvents(); QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchUpdatePoints.count(), 1); + QCOMPARE(touchWidget.touchUpdatePoints.size(), 1); QEventPoint touchUpdatePoint = touchWidget.touchUpdatePoints.first(); QCOMPARE(touchUpdatePoint.id(), 1); QCOMPARE(touchUpdatePoint.state(), QEventPoint::State::Updated); @@ -1077,13 +1071,13 @@ void tst_QTouchEvent::touchOnMultipleTouchscreens() // releasing the first point translates to TouchEnd nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QEventPoint>() << - QMutableEventPoint(1234, 1, QEventPoint::State::Released, screenPos + delta + delta, screenPos + delta + delta, screenPos + delta + delta), window); + QMutableEventPoint::withTimeStamp(1234, 1, QEventPoint::State::Released, screenPos + delta + delta, screenPos + delta + delta, screenPos + delta + delta), window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints); QCoreApplication::processEvents(); QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QVERIFY(touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchEndPoints.count(), 1); + QCOMPARE(touchWidget.touchEndPoints.size(), 1); QEventPoint touchEndPoint = touchWidget.touchEndPoints.first(); QCOMPARE(touchEndPoint.id(), 1); QCOMPARE(touchEndPoint.state(), QEventPoint::State::Released); @@ -1101,14 +1095,14 @@ void tst_QTouchEvent::touchOnMultipleTouchscreens() touchWidget.touchEndPoints.clear(); nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QEventPoint>() << - QMutableEventPoint(1234, 10, QEventPoint::State::Released, screenPos, screenPos, screenPos) << - QMutableEventPoint(1234, 11, QEventPoint::State::Stationary, screenPos, screenPos, screenPos), window); + QMutableEventPoint::withTimeStamp(1234, 10, QEventPoint::State::Released, screenPos, screenPos, screenPos) << + QMutableEventPoint::withTimeStamp(1234, 11, QEventPoint::State::Stationary, screenPos, screenPos, screenPos), window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints); QCoreApplication::processEvents(); QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); + QCOMPARE(touchWidget.touchUpdatePoints.size(), 2); QCOMPARE(touchWidget.touchUpdatePoints[0].id(), 10); QCOMPARE(touchWidget.touchUpdatePoints[1].id(), 11); @@ -1116,14 +1110,14 @@ void tst_QTouchEvent::touchOnMultipleTouchscreens() touchWidget.seenTouchEnd = false; nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(QList<QEventPoint>() << - QMutableEventPoint(1234, 11, QEventPoint::State::Released, screenPos + delta + delta, + QMutableEventPoint::withTimeStamp(1234, 11, QEventPoint::State::Released, screenPos + delta + delta, screenPos + delta + delta, screenPos + delta + delta), window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, secondaryTouchScreenDevice, nativeTouchPoints); QCoreApplication::processEvents(); QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QVERIFY(touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchEndPoints.count(), 1); + QCOMPARE(touchWidget.touchEndPoints.size(), 1); touchEndPoint = touchWidget.touchEndPoints.first(); QCOMPARE(touchEndPoint.id(), 11); QCOMPARE(touchEndPoint.state(), QEventPoint::State::Released); @@ -1131,6 +1125,17 @@ void tst_QTouchEvent::touchOnMultipleTouchscreens() void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() { +#ifdef Q_OS_MACOS +#if QT_CONFIG(cursor) + QCursor::setPos(0, 0); // move mouse out of the way + if (!QTest::qWaitFor([]{ return QCursor::pos() == QPoint(0, 0); })) +#endif + QSKIP("The macOS mouse cursor interferes with this test can cannot be moved away"); +#endif + + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + tst_QTouchEventWidget touchWidget; touchWidget.setObjectName("touchWidget"); touchWidget.setWindowTitle(QTest::currentTestFunction()); @@ -1149,28 +1154,29 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() rightWidget.setGeometry(300, 100, 100, 100); touchWidget.show(); - QVERIFY(QTest::qWaitForWindowExposed(&touchWidget)); + QVERIFY(QTest::qWaitForWindowActive(&touchWidget)); - QPointF leftPos = leftWidget.rect().center(); - QPointF rightPos = rightWidget.rect().center(); - QPointF centerPos = touchWidget.rect().center(); - QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint()); - QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint()); - QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint()); + const QPointF leftPos = leftWidget.rect().center(); + const QPointF rightPos = rightWidget.rect().center(); + const QPointF centerPos = touchWidget.rect().center(); + const QPointF leftScreenPos = leftWidget.mapToGlobal(leftPos.toPoint()); + const QPointF rightScreenPos = rightWidget.mapToGlobal(rightPos.toPoint()); + const QPointF centerScreenPos = touchWidget.mapToGlobal(centerPos.toPoint()); ulong timestamp = 0; - QList<QMutableEventPoint> rawTouchPoints; - rawTouchPoints.append(QMutableEventPoint(0)); - rawTouchPoints.append(QMutableEventPoint(1)); + QList<QEventPoint> rawTouchPoints = { + QEventPoint(0), + QEventPoint(1), + }; // generate TouchBegin on leftWidget only { - QMutableEventPoint &tp0 = QMutableEventPoint::from(rawTouchPoints[0]); - tp0.setState(QEventPoint::State::Pressed); - tp0.setGlobalPosition(leftScreenPos); - QMutableEventPoint & tp1 = QMutableEventPoint::from(rawTouchPoints[1]); - tp1.setState(QEventPoint::State::Pressed); - tp1.setGlobalPosition(rightScreenPos); + QEventPoint &tp0 = rawTouchPoints[0]; + QMutableEventPoint::setState(tp0, QEventPoint::State::Pressed); + QMutableEventPoint::setGlobalPosition(tp0, leftScreenPos); + QEventPoint &tp1 = rawTouchPoints[1]; + QMutableEventPoint::setState(tp1, QEventPoint::State::Pressed); + QMutableEventPoint::setGlobalPosition(tp1, rightScreenPos); } QWindow *window = touchWidget.windowHandle(); QList<QWindowSystemInterface::TouchPoint> nativeTouchPoints = @@ -1186,8 +1192,9 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QVERIFY(!rightWidget.seenTouchBegin); QVERIFY(!rightWidget.seenTouchUpdate); QVERIFY(!rightWidget.seenTouchEnd); - QCOMPARE(leftWidget.touchBeginPoints.count(), 2); - QCOMPARE(rightWidget.touchBeginPoints.count(), 0); + QCOMPARE(leftWidget.touchBeginPoints.size(), 2); + QCOMPARE(rightWidget.touchBeginPoints.size(), 0); + QCOMPARE(leftWidget.lastNormalizedPositions.size(), 2); { QEventPoint leftTouchPoint = leftWidget.touchBeginPoints.at(0); qCDebug(lcTests) << "lastNormalizedPositions after press" << leftWidget.lastNormalizedPositions; @@ -1203,7 +1210,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QCOMPARE(leftTouchPoint.globalPosition(), leftScreenPos); QCOMPARE(leftTouchPoint.globalPressPosition(), leftScreenPos); QCOMPARE(leftTouchPoint.globalLastPosition(), leftScreenPos); - QVERIFY(qAbs(leftWidget.lastNormalizedPositions.at(0).x() - 0.2) < 0.05); // 0.198, might depend on window frame size + QCOMPARE_LT(qAbs(leftWidget.lastNormalizedPositions.at(0).x() - 0.2), 0.05); // 0.198, might depend on window frame size QCOMPARE(leftTouchPoint.position(), leftPos); QCOMPARE(leftTouchPoint.scenePosition(), leftScreenPos); QCOMPARE(leftTouchPoint.globalPosition(), leftScreenPos); @@ -1223,7 +1230,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QCOMPARE(rightTouchPoint.globalPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.globalPressPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.globalLastPosition(), rightScreenPos); - QVERIFY(qAbs(leftWidget.lastNormalizedPositions.at(1).x() - 0.8) < 0.05); // 0.798, might depend on window frame size + QCOMPARE_LT(qAbs(leftWidget.lastNormalizedPositions.at(1).x() - 0.8), 0.05); // 0.798, might depend on window frame size QCOMPARE(rightTouchPoint.scenePosition(), rightScreenPos); QCOMPARE(rightTouchPoint.globalPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.ellipseDiameters(), QSizeF(0, 0)); @@ -1231,10 +1238,10 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() } // generate TouchUpdate on leftWidget - rawTouchPoints[0].setState(QEventPoint::State::Updated); - rawTouchPoints[0].setGlobalPosition(centerScreenPos); - rawTouchPoints[1].setState(QEventPoint::State::Updated); - rawTouchPoints[1].setGlobalPosition(centerScreenPos); + QMutableEventPoint::setState(rawTouchPoints[0], QEventPoint::State::Updated); + QMutableEventPoint::setGlobalPosition(rawTouchPoints[0], centerScreenPos); + QMutableEventPoint::setState(rawTouchPoints[1], QEventPoint::State::Updated); + QMutableEventPoint::setGlobalPosition(rawTouchPoints[1], centerScreenPos); nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchPadDevice, nativeTouchPoints); @@ -1248,8 +1255,9 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QVERIFY(!rightWidget.seenTouchBegin); QVERIFY(!rightWidget.seenTouchUpdate); QVERIFY(!rightWidget.seenTouchEnd); - QCOMPARE(leftWidget.touchUpdatePoints.count(), 2); - QCOMPARE(rightWidget.touchUpdatePoints.count(), 0); + QCOMPARE(leftWidget.touchUpdatePoints.size(), 2); + QCOMPARE(rightWidget.touchUpdatePoints.size(), 0); + QCOMPARE(leftWidget.lastNormalizedPositions.size(), 2); { QEventPoint leftTouchPoint = leftWidget.touchUpdatePoints.at(0); qCDebug(lcTests) << "lastNormalizedPositions after update" << leftWidget.lastNormalizedPositions; @@ -1265,7 +1273,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QCOMPARE(leftTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(leftTouchPoint.globalPressPosition(), leftScreenPos); QCOMPARE(leftTouchPoint.globalLastPosition(), leftScreenPos); - QVERIFY(qAbs(leftWidget.lastNormalizedPositions.at(0).x() - 0.5) < 0.05); // 0.498, might depend on window frame size + QCOMPARE_LT(qAbs(leftWidget.lastNormalizedPositions.at(0).x() - 0.5), 0.05); // 0.498, might depend on window frame size QCOMPARE(leftTouchPoint.position(), leftWidget.mapFromParent(centerPos.toPoint())); QCOMPARE(leftTouchPoint.scenePosition(), centerScreenPos); QCOMPARE(leftTouchPoint.globalPosition(), centerScreenPos); @@ -1285,7 +1293,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QCOMPARE(rightTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(rightTouchPoint.globalPressPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.globalLastPosition(), rightScreenPos); - QVERIFY(qAbs(leftWidget.lastNormalizedPositions.at(1).x() - 0.5) < 0.05); // 0.498, might depend on window frame size + QCOMPARE_LT(qAbs(leftWidget.lastNormalizedPositions.at(1).x() - 0.5), 0.05); // 0.498, might depend on window frame size QCOMPARE(rightTouchPoint.position(), leftWidget.mapFromParent(centerPos.toPoint())); QCOMPARE(rightTouchPoint.scenePosition(), centerScreenPos); QCOMPARE(rightTouchPoint.globalPosition(), centerScreenPos); @@ -1295,8 +1303,8 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() // generate TouchEnd on leftWidget // both touchpoints are still at centerScreenPos - rawTouchPoints[0].setState(QEventPoint::State::Released); - rawTouchPoints[1].setState(QEventPoint::State::Released); + QMutableEventPoint::setState(rawTouchPoints[0], QEventPoint::State::Released); + QMutableEventPoint::setState(rawTouchPoints[1], QEventPoint::State::Released); nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchPadDevice, nativeTouchPoints); @@ -1310,8 +1318,9 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QVERIFY(!rightWidget.seenTouchBegin); QVERIFY(!rightWidget.seenTouchUpdate); QVERIFY(!rightWidget.seenTouchEnd); - QCOMPARE(leftWidget.touchEndPoints.count(), 2); - QCOMPARE(rightWidget.touchEndPoints.count(), 0); + QCOMPARE(leftWidget.touchEndPoints.size(), 2); + QCOMPARE(rightWidget.touchEndPoints.size(), 0); + QCOMPARE(leftWidget.lastNormalizedPositions.size(), 2); { QEventPoint leftTouchPoint = leftWidget.touchEndPoints.at(0); qCDebug(lcTests) << "lastNormalizedPositions after release" << leftWidget.lastNormalizedPositions; @@ -1328,7 +1337,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QCOMPARE(leftTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(leftTouchPoint.globalPressPosition(), leftScreenPos); QCOMPARE(leftTouchPoint.globalLastPosition(), leftScreenPos); - QVERIFY(qAbs(leftWidget.lastNormalizedPositions.at(0).x() - 0.5) < 0.05); // 0.498, might depend on window frame size + QCOMPARE_LT(qAbs(leftWidget.lastNormalizedPositions.at(0).x() - 0.5), 0.05); // 0.498, might depend on window frame size QCOMPARE(leftTouchPoint.position(), leftWidget.mapFromParent(centerPos.toPoint())); QCOMPARE(leftTouchPoint.scenePosition(), centerScreenPos); QCOMPARE(leftTouchPoint.globalPosition(), centerScreenPos); @@ -1348,7 +1357,7 @@ void tst_QTouchEvent::multiPointRawEventTranslationOnTouchPad() QCOMPARE(rightTouchPoint.globalPosition(), centerScreenPos); QCOMPARE(rightTouchPoint.globalPressPosition(), rightScreenPos); QCOMPARE(rightTouchPoint.globalLastPosition(), rightScreenPos); - QVERIFY(qAbs(leftWidget.lastNormalizedPositions.at(1).x() - 0.5) < 0.05); // 0.498, might depend on window frame size + QCOMPARE_LT(qAbs(leftWidget.lastNormalizedPositions.at(1).x() - 0.5), 0.05); // 0.498, might depend on window frame size QCOMPARE(rightTouchPoint.position(), leftWidget.mapFromParent(centerPos.toPoint())); QCOMPARE(rightTouchPoint.scenePosition(), centerScreenPos); QCOMPARE(rightTouchPoint.globalPosition(), centerScreenPos); @@ -1373,17 +1382,17 @@ void tst_QTouchEvent::basicRawEventTranslationOfIds() screenPos << touchWidget.mapToGlobal(pos[i].toPoint()); } QPointF delta(10, 10); - QList<QMutableEventPoint> rawTouchPoints; + QList<QEventPoint> rawTouchPoints; // Press both points, this should be translated to a TouchBegin for (int i = 0; i < 2; ++i) { - QMutableEventPoint rawTouchPoint(i); - rawTouchPoint.setState(QEventPoint::State::Pressed); - rawTouchPoint.setGlobalPosition(screenPos[i]); + QEventPoint rawTouchPoint(i); + QMutableEventPoint::setState(rawTouchPoint, QEventPoint::State::Pressed); + QMutableEventPoint::setGlobalPosition(rawTouchPoint, screenPos[i]); rawTouchPoints << rawTouchPoint; } - QMutableEventPoint &p0 = rawTouchPoints[0]; - QMutableEventPoint &p1 = rawTouchPoints[1]; + QEventPoint &p0 = rawTouchPoints[0]; + QEventPoint &p1 = rawTouchPoints[1]; ulong timestamp = 1234; QWindow *window = touchWidget.windowHandle(); @@ -1394,19 +1403,19 @@ void tst_QTouchEvent::basicRawEventTranslationOfIds() QVERIFY(touchWidget.seenTouchBegin); QVERIFY(!touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchBeginPoints.count(), 2); + QCOMPARE(touchWidget.touchBeginPoints.size(), 2); - for (int i = 0; i < touchWidget.touchBeginPoints.count(); ++i) { + for (int i = 0; i < touchWidget.touchBeginPoints.size(); ++i) { QEventPoint touchBeginPoint = touchWidget.touchBeginPoints.at(i); QCOMPARE(touchBeginPoint.id(), i); QCOMPARE(touchBeginPoint.state(), rawTouchPoints[i].state()); } // moving the point should translate to TouchUpdate - for (int i = 0; i < rawTouchPoints.count(); ++i) { + for (int i = 0; i < rawTouchPoints.size(); ++i) { auto &p = rawTouchPoints[i]; - p.setState(QEventPoint::State::Updated); - p.setGlobalPosition(p.globalPosition() + delta); + QMutableEventPoint::setState(p, QEventPoint::State::Updated); + QMutableEventPoint::setGlobalPosition(p, p.globalPosition() + delta); } nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); @@ -1415,13 +1424,13 @@ void tst_QTouchEvent::basicRawEventTranslationOfIds() QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); + QCOMPARE(touchWidget.touchUpdatePoints.size(), 2); QCOMPARE(touchWidget.touchUpdatePoints.at(0).id(), 0); QCOMPARE(touchWidget.touchUpdatePoints.at(1).id(), 1); // release last point - p0.setState(QEventPoint::State::Stationary); - p1.setState(QEventPoint::State::Released); + QMutableEventPoint::setState(p0, QEventPoint::State::Stationary); + QMutableEventPoint::setState(p1, QEventPoint::State::Released); nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); @@ -1430,13 +1439,13 @@ void tst_QTouchEvent::basicRawEventTranslationOfIds() QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QCOMPARE(touchWidget.seenTouchEnd, false); - QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); + QCOMPARE(touchWidget.touchUpdatePoints.size(), 2); QCOMPARE(touchWidget.touchUpdatePoints[0].id(), 0); QCOMPARE(touchWidget.touchUpdatePoints[1].id(), 1); // Press last point again, id should increase - p1.setState(QEventPoint::State::Pressed); - p1.setId(42); // new id + QMutableEventPoint::setState(p1, QEventPoint::State::Pressed); + QMutableEventPoint::setId(p1, 42); // new id nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints); @@ -1444,13 +1453,13 @@ void tst_QTouchEvent::basicRawEventTranslationOfIds() QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QVERIFY(!touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); + QCOMPARE(touchWidget.touchUpdatePoints.size(), 2); QCOMPARE(touchWidget.touchUpdatePoints[0].id(), 0); QCOMPARE(touchWidget.touchUpdatePoints[1].id(), 42); // release everything - p0.setState(QEventPoint::State::Released); - p1.setState(QEventPoint::State::Released); + QMutableEventPoint::setState(p0, QEventPoint::State::Released); + QMutableEventPoint::setState(p1, QEventPoint::State::Released); nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints); @@ -1458,7 +1467,7 @@ void tst_QTouchEvent::basicRawEventTranslationOfIds() QVERIFY(touchWidget.seenTouchBegin); QVERIFY(touchWidget.seenTouchUpdate); QVERIFY(touchWidget.seenTouchEnd); - QCOMPARE(touchWidget.touchUpdatePoints.count(), 2); + QCOMPARE(touchWidget.touchUpdatePoints.size(), 2); QCOMPARE(touchWidget.touchUpdatePoints[0].id(), 0); QCOMPARE(touchWidget.touchUpdatePoints[1].id(), 42); } @@ -1543,23 +1552,23 @@ void tst_QTouchEvent::deleteInEventHandler() view.resize(200, 200); view.fitInView(scene.sceneRect()); - QMutableEventPoint touchPoint(0); - touchPoint.setState(QEventPoint::State::Pressed); - touchPoint.setPosition(view.mapFromScene(child1->mapToScene(child1->boundingRect().center()))); - touchPoint.setGlobalPosition(view.mapToGlobal(touchPoint.position().toPoint())); - touchPoint.setScenePosition(view.mapToScene(touchPoint.position().toPoint())); + QEventPoint touchPoint(0); + QMutableEventPoint::setState(touchPoint, QEventPoint::State::Pressed); + QMutableEventPoint::setPosition(touchPoint, view.mapFromScene(child1->mapToScene(child1->boundingRect().center()))); + QMutableEventPoint::setGlobalPosition(touchPoint, view.mapToGlobal(touchPoint.position().toPoint())); + QMutableEventPoint::setScenePosition(touchPoint, view.mapToScene(touchPoint.position().toPoint())); QTouchEvent touchBeginEvent(QEvent::TouchBegin, touchScreenDevice, Qt::NoModifier, {touchPoint}); - touchPoint.detach(); - touchPoint.setState(QEventPoint::State::Updated); + QMutableEventPoint::detach(touchPoint); + QMutableEventPoint::setState(touchPoint, QEventPoint::State::Updated); QTouchEvent touchUpdateEvent(QEvent::TouchUpdate, touchScreenDevice, Qt::NoModifier, {touchPoint}); - touchPoint.detach(); - touchPoint.setState(QEventPoint::State::Released); + QMutableEventPoint::detach(touchPoint); + QMutableEventPoint::setState(touchPoint, QEventPoint::State::Released); QTouchEvent touchEndEvent(QEvent::TouchEnd, touchScreenDevice, Qt::NoModifier, @@ -1639,16 +1648,17 @@ void tst_QTouchEvent::deleteInRawEventTranslation() QPointF rightScreenPos = rightWidget->mapToGlobal(rightPos.toPoint()); ulong timestamp = 0; - QList<QMutableEventPoint> rawTouchPoints; - rawTouchPoints.append(QMutableEventPoint(0)); - rawTouchPoints.append(QMutableEventPoint(1)); - rawTouchPoints.append(QMutableEventPoint(2)); - rawTouchPoints[0].setState(QEventPoint::State::Pressed); - rawTouchPoints[0].setGlobalPosition(leftScreenPos); - rawTouchPoints[1].setState(QEventPoint::State::Pressed); - rawTouchPoints[1].setGlobalPosition(centerScreenPos); - rawTouchPoints[2].setState(QEventPoint::State::Pressed); - rawTouchPoints[2].setGlobalPosition(rightScreenPos); + QList<QEventPoint> rawTouchPoints = { + QEventPoint(0), + QEventPoint(1), + QEventPoint(2), + }; + QMutableEventPoint::setState(rawTouchPoints[0], QEventPoint::State::Pressed); + QMutableEventPoint::setGlobalPosition(rawTouchPoints[0], leftScreenPos); + QMutableEventPoint::setState(rawTouchPoints[1], QEventPoint::State::Pressed); + QMutableEventPoint::setGlobalPosition(rawTouchPoints[1], centerScreenPos); + QMutableEventPoint::setState(rawTouchPoints[2], QEventPoint::State::Pressed); + QMutableEventPoint::setGlobalPosition(rawTouchPoints[2], rightScreenPos); // generate begin events on all widgets, the left widget should die QWindow *window = touchWidget.windowHandle(); @@ -1661,18 +1671,18 @@ void tst_QTouchEvent::deleteInRawEventTranslation() QVERIFY(!rightWidget.isNull()); // generate update events on all widget, the center widget should die - rawTouchPoints[0].setState(QEventPoint::State::Updated); - rawTouchPoints[1].setState(QEventPoint::State::Updated); - rawTouchPoints[2].setState(QEventPoint::State::Updated); + QMutableEventPoint::setState(rawTouchPoints[0], QEventPoint::State::Updated); + QMutableEventPoint::setState(rawTouchPoints[1], QEventPoint::State::Updated); + QMutableEventPoint::setState(rawTouchPoints[2], QEventPoint::State::Updated); nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints); QCoreApplication::processEvents(); // generate end events on all widget, the right widget should die - rawTouchPoints[0].setState(QEventPoint::State::Released); - rawTouchPoints[1].setState(QEventPoint::State::Released); - rawTouchPoints[2].setState(QEventPoint::State::Released); + QMutableEventPoint::setState(rawTouchPoints[0], QEventPoint::State::Released); + QMutableEventPoint::setState(rawTouchPoints[1], QEventPoint::State::Released); + QMutableEventPoint::setState(rawTouchPoints[2], QEventPoint::State::Released); nativeTouchPoints = QWindowSystemInterfacePrivate::toNativeTouchPoints(rawTouchPoints, window); QWindowSystemInterface::handleTouchEvent(window, ++timestamp, touchScreenDevice, nativeTouchPoints); @@ -1821,25 +1831,25 @@ void tst_QTouchEvent::testQGuiAppDelivery() // Now the real thing. QWindowSystemInterface::handleTouchEvent(&w, touchScreenDevice, points); // TouchBegin QCoreApplication::processEvents(); - QCOMPARE(filter.d.count(), 1); + QCOMPARE(filter.d.size(), 1); QCOMPARE(filter.d.contains(touchScreenDevice), true); - QCOMPARE(filter.d.value(touchScreenDevice).points.count(), 1); + QCOMPARE(filter.d.value(touchScreenDevice).points.size(), 1); QCOMPARE(filter.d.value(touchScreenDevice).lastSeenType, QEvent::TouchBegin); points[0].state = QEventPoint::State::Updated; QWindowSystemInterface::handleTouchEvent(&w, touchScreenDevice, points); // TouchUpdate QCoreApplication::processEvents(); - QCOMPARE(filter.d.count(), 1); + QCOMPARE(filter.d.size(), 1); QCOMPARE(filter.d.contains(touchScreenDevice), true); - QCOMPARE(filter.d.value(touchScreenDevice).points.count(), 2); + QCOMPARE(filter.d.value(touchScreenDevice).points.size(), 2); QCOMPARE(filter.d.value(touchScreenDevice).lastSeenType, QEvent::TouchUpdate); points[0].state = QEventPoint::State::Released; QWindowSystemInterface::handleTouchEvent(&w, touchScreenDevice, points); // TouchEnd QCoreApplication::processEvents(); - QCOMPARE(filter.d.count(), 1); + QCOMPARE(filter.d.size(), 1); QCOMPARE(filter.d.contains(touchScreenDevice), true); - QCOMPARE(filter.d.value(touchScreenDevice).points.count(), 3); + QCOMPARE(filter.d.value(touchScreenDevice).points.size(), 3); QCOMPARE(filter.d.value(touchScreenDevice).lastSeenType, QEvent::TouchEnd); } @@ -1882,8 +1892,8 @@ void tst_QTouchEvent::testMultiDevice() QCOMPARE(filter.d.value(touchScreenDevice).lastSeenType, QEvent::TouchBegin); QCOMPARE(filter.d.value(deviceTwo).lastSeenType, QEvent::TouchBegin); - QCOMPARE(filter.d.value(touchScreenDevice).points.count(), 1); - QCOMPARE(filter.d.value(deviceTwo).points.count(), 2); + QCOMPARE(filter.d.value(touchScreenDevice).points.size(), 1); + QCOMPARE(filter.d.value(deviceTwo).points.size(), 2); QCOMPARE(filter.d.value(touchScreenDevice).points.at(0).globalPosition(), area0.center()); // This fails because QGuiApplicationPrivate::processTouchEvent() sends synth-mouse events @@ -1938,7 +1948,7 @@ void tst_QTouchEvent::grabbers() // Ensure that grabbers are persistent between events, within the stored touchpoints QCOMPARE(devPriv->pointById(0)->exclusiveGrabber, grabExclusive ? &w : nullptr); - QCOMPARE(devPriv->pointById(0)->passiveGrabbers.count(), grabPassive ? 1 : 0); + QCOMPARE(devPriv->pointById(0)->passiveGrabbers.size(), grabPassive ? 1 : 0); if (grabPassive) QCOMPARE(devPriv->pointById(0)->passiveGrabbers.first(), &w); diff --git a/tests/auto/gui/kernel/qwindow/BLACKLIST b/tests/auto/gui/kernel/qwindow/BLACKLIST index 17fe1f62a6..69df8883c8 100644 --- a/tests/auto/gui/kernel/qwindow/BLACKLIST +++ b/tests/auto/gui/kernel/qwindow/BLACKLIST @@ -1,34 +1,28 @@ [positioning] -opensuse-leap -[positioning:default] -linux -macos ci -[positioning:fake] macos ci [modalWithChildWindow] -# QTBUG-66851 # QTBUG-69160 -opensuse-leap -[setVisible] -# QTBUG-69154 android [modalWindowEnterEventOnHide_QTBUG35109] osx +android +windows [spuriousMouseMove] # QTBUG-69162 windows-10 -[testInputEvents] -rhel-7.4 -[exposeEventOnShrink_QTBUG54040] -# QTBUG-69155 -android -opensuse -[initialSize] -# QTBUG-69159 android [modalWindowPosition] # QTBUG-69161 android -[childWindowPositioning:show] -# QTBUG-69156 +# QTBUG-87392 +[paintEvent] +android +[isActive] +android +[modalWindowModallity] +android +[enterLeaveOnWindowShowHide] +windows-10 +windows-11 android +rhel diff --git a/tests/auto/gui/kernel/qwindow/CMakeLists.txt b/tests/auto/gui/kernel/qwindow/CMakeLists.txt index 84b46b76f5..5824989ac3 100644 --- a/tests/auto/gui/kernel/qwindow/CMakeLists.txt +++ b/tests/auto/gui/kernel/qwindow/CMakeLists.txt @@ -1,22 +1,51 @@ -# Generated from qwindow.pro. +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause ##################################################################### ## tst_qwindow Test: ##################################################################### -qt_add_test(tst_qwindow +if(NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT) + cmake_minimum_required(VERSION 3.16) + project(tst_qwindow LANGUAGES CXX) + find_package(Qt6BuildInternals REQUIRED COMPONENTS STANDALONE_TEST) +endif() + +qt_internal_add_test(tst_qwindow SOURCES tst_qwindow.cpp - PUBLIC_LIBRARIES + LIBRARIES Qt::CorePrivate Qt::Gui Qt::GuiPrivate ) +if(APPLE OR WIN32 OR QT_FEATURE_xcb) + qt_internal_add_test(tst_foreignwindow + LOWDPI + SOURCES + tst_foreignwindow.cpp + LIBRARIES + Qt::CorePrivate + Qt::Gui + Qt::GuiPrivate + ) + + if(APPLE) + enable_language(OBJCXX) + set_source_files_properties(tst_foreignwindow.cpp PROPERTIES LANGUAGE OBJCXX) + set_property(TARGET tst_foreignwindow PROPERTY PROPERTY MACOSX_BUNDLE TRUE) + endif() + + if(QT_FEATURE_xcb) + target_link_libraries(tst_foreignwindow PRIVATE XCB::XCB) + endif() +endif() + ## Scopes: ##################################################################### -qt_extend_target(tst_qwindow CONDITION QT_FEATURE_dynamicgl AND WIN32 - PUBLIC_LIBRARIES +qt_internal_extend_target(tst_qwindow CONDITION QT_FEATURE_dynamicgl AND WIN32 + LIBRARIES user32 ) diff --git a/tests/auto/gui/kernel/qwindow/qwindow.pro b/tests/auto/gui/kernel/qwindow/qwindow.pro deleted file mode 100644 index f97d4ef789..0000000000 --- a/tests/auto/gui/kernel/qwindow/qwindow.pro +++ /dev/null @@ -1,8 +0,0 @@ -CONFIG += testcase -TARGET = tst_qwindow - -QT += core-private gui-private testlib - -SOURCES += tst_qwindow.cpp - -qtConfig(dynamicgl):win32: QMAKE_USE += user32 diff --git a/tests/auto/gui/kernel/qwindow/tst_foreignwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_foreignwindow.cpp new file mode 100644 index 0000000000..fdb1b333ef --- /dev/null +++ b/tests/auto/gui/kernel/qwindow/tst_foreignwindow.cpp @@ -0,0 +1,196 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +#include <QTest> + +#include <QtCore/qloggingcategory.h> +#include <private/qguiapplication_p.h> +#include <qpa/qplatformintegration.h> + +#include "../../../../shared/nativewindow.h" + +class tst_ForeignWindow: public QObject +{ + Q_OBJECT + +private slots: + void initTestCase() + { + auto *platformIntegration = QGuiApplicationPrivate::platformIntegration(); + if (!platformIntegration->hasCapability(QPlatformIntegration::ForeignWindows)) + QSKIP("This platform does not support foreign windows"); + } + + void fromWinId(); + void initialState(); + + void embedForeignWindow(); + void embedInForeignWindow(); + + void destroyExplicitly(); + void destroyWhenParentIsDestroyed(); +}; + +void tst_ForeignWindow::fromWinId() +{ + NativeWindow nativeWindow; + QVERIFY(nativeWindow); + + std::unique_ptr<QWindow> foreignWindow(QWindow::fromWinId(nativeWindow)); + QVERIFY(foreignWindow); + QVERIFY(foreignWindow->flags().testFlag(Qt::ForeignWindow)); + QVERIFY(foreignWindow->handle()); + + // fromWinId does not take (exclusive) ownership of the native window, + // so deleting the foreign window should not be a problem/cause crashes. + foreignWindow.reset(); +} + +void tst_ForeignWindow::initialState() +{ + NativeWindow nativeWindow; + QVERIFY(nativeWindow); + + // A foreign window can be used to embed a Qt UI in a foreign window hierarchy, + // in which case the foreign window merely acts as a parent and should not be + // modified, or to embed a foreign window in a Qt UI, in which case the foreign + // window must to be able to re-parent, move, resize, show, etc, so that the + // containing Qt UI can treat it as any other window. + + // At the point of creation though, we don't know what the foreign window + // will be used for, so the platform should not assume it can modify the + // window. Any properties set on the native window should persist past + // creation of the foreign window. + + const QRect initialGeometry(123, 456, 321, 654); + nativeWindow.setGeometry(initialGeometry); + QTRY_COMPARE(nativeWindow.geometry(), initialGeometry); + + std::unique_ptr<QWindow> foreignWindow(QWindow::fromWinId(nativeWindow)); + QCOMPARE(nativeWindow.geometry(), initialGeometry); + + // For extra bonus points, the foreign window should actually + // reflect the state of the native window. + QCOMPARE(foreignWindow->geometry(), initialGeometry); +} + +void tst_ForeignWindow::embedForeignWindow() +{ + // A foreign window embedded into a Qt UI requires that the rest of Qt + // is to be able to treat the foreign child window as any other window + // that it can show, hide, stack, and move around. + + QWindow parentWindow; + + NativeWindow nativeWindow; + QVERIFY(nativeWindow); + + // As a prerequisite to that, we must be able to reparent the foreign window + std::unique_ptr<QWindow> foreignWindow(QWindow::fromWinId(nativeWindow)); + foreignWindow->setParent(&parentWindow); + QTRY_COMPARE(nativeWindow.parentWinId(), parentWindow.winId()); + + // FIXME: This test is flakey on Linux. Figure out why +#if !defined(Q_OS_LINUX) + foreignWindow->setParent(nullptr); + QTRY_VERIFY(nativeWindow.parentWinId() != parentWindow.winId()); +#endif +} + +void tst_ForeignWindow::embedInForeignWindow() +{ + // When a foreign window is used as a container to embed a Qt UI + // in a foreign window hierarchy, the foreign window merely acts + // as a parent, and should not be modified. + + { + // At a minimum, we must be able to reparent into the window + NativeWindow nativeWindow; + QVERIFY(nativeWindow); + + std::unique_ptr<QWindow> foreignWindow(QWindow::fromWinId(nativeWindow)); + + QWindow embeddedWindow; + embeddedWindow.setParent(foreignWindow.get()); + QTRY_VERIFY(nativeWindow.isParentOf(embeddedWindow.winId())); + } + + { + // The foreign window's native window should not be reparent as a + // result of creating the foreign window, adding and removing children, + // or destroying the foreign window. + + NativeWindow topLevelNativeWindow; + NativeWindow childNativeWindow; + childNativeWindow.setParent(topLevelNativeWindow); + QVERIFY(topLevelNativeWindow.isParentOf(childNativeWindow)); + + std::unique_ptr<QWindow> foreignWindow(QWindow::fromWinId(childNativeWindow)); + QVERIFY(topLevelNativeWindow.isParentOf(childNativeWindow)); + + QWindow embeddedWindow; + embeddedWindow.setParent(foreignWindow.get()); + QTRY_VERIFY(childNativeWindow.isParentOf(embeddedWindow.winId())); + QVERIFY(topLevelNativeWindow.isParentOf(childNativeWindow)); + + embeddedWindow.setParent(nullptr); + QVERIFY(topLevelNativeWindow.isParentOf(childNativeWindow)); + + foreignWindow.reset(); + QVERIFY(topLevelNativeWindow.isParentOf(childNativeWindow)); + } +} + +void tst_ForeignWindow::destroyExplicitly() +{ + NativeWindow nativeWindow; + QVERIFY(nativeWindow); + + std::unique_ptr<QWindow> foreignWindow(QWindow::fromWinId(nativeWindow)); + QVERIFY(foreignWindow->handle()); + + // Explicitly destroying a foreign window is a no-op, as + // the documentation claims that it "releases the native + // platform resources associated with this window.", which + // is not technically true for foreign windows. + auto *windowHandleBeforeDestroy = foreignWindow->handle(); + foreignWindow->destroy(); + QCOMPARE(foreignWindow->handle(), windowHandleBeforeDestroy); +} + +void tst_ForeignWindow::destroyWhenParentIsDestroyed() +{ + QWindow parentWindow; + + NativeWindow nativeWindow; + QVERIFY(nativeWindow); + + std::unique_ptr<QWindow> foreignWindow(QWindow::fromWinId(nativeWindow)); + foreignWindow->setParent(&parentWindow); + QTRY_COMPARE(nativeWindow.parentWinId(), parentWindow.winId()); + + // Reparenting into a window will result in creating it + QVERIFY(parentWindow.handle()); + + parentWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&parentWindow)); + + // Destroying the parent window of the foreign window results + // in destroying the foreign window as well, as the foreign + // window no longer has a parent it can be embedded in. + QVERIFY(foreignWindow->handle()); + parentWindow.destroy(); + QVERIFY(!foreignWindow->handle()); + + // But the foreign window can be recreated again, and will + // continue to be a native child of the parent window. + foreignWindow->create(); + QVERIFY(foreignWindow->handle()); + QTRY_COMPARE(nativeWindow.parentWinId(), parentWindow.winId()); + + parentWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&parentWindow)); +} + +#include <tst_foreignwindow.moc> +QTEST_MAIN(tst_ForeignWindow) diff --git a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp index c93783fd9c..227fd77e1a 100644 --- a/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp +++ b/tests/auto/gui/kernel/qwindow/tst_qwindow.cpp @@ -1,30 +1,5 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the test suite of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:GPL-EXCEPT$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2016 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <qrasterwindow.h> #include <qpa/qwindowsysteminterface.h> @@ -32,10 +7,11 @@ #include <qpa/qplatformwindow.h> #include <private/qguiapplication_p.h> #include <private/qhighdpiscaling_p.h> +#include <private/qwindow_p.h> #include <QtGui/QPainter> -#include <QtTest/QtTest> - +#include <QTest> +#include <QSignalSpy> #include <QEvent> #include <QStyleHints> @@ -47,6 +23,12 @@ Q_LOGGING_CATEGORY(lcTests, "qt.gui.tests") +static bool isPlatformEglFS() +{ + static const bool isEglFS = !QGuiApplication::platformName().compare(QLatin1String("eglfs"), Qt::CaseInsensitive); + return isEglFS; +} + class tst_QWindow: public QObject { Q_OBJECT @@ -55,6 +37,7 @@ private slots: void create(); void setParent(); void setVisible(); + void setVisibleThenCreate(); void setVisibleFalseDoesNotCreateWindow(); void eventOrderOnShow(); void paintEvent(); @@ -95,6 +78,7 @@ private slots: void modalWithChildWindow(); void modalWindowModallity(); void modalWindowPosition(); + void modalCloseWhileBlocked(); #ifndef QT_NO_CURSOR void modalWindowEnterEventOnHide_QTBUG35109(); void spuriousMouseMove(); @@ -109,6 +93,17 @@ private slots: void testBlockingWindowShownAfterModalDialog(); void generatedMouseMove(); void keepPendingUpdateRequests(); + void activateDeactivateEvent(); + void qobject_castOnDestruction(); + void touchToMouseTranslationByPopup(); + void stateChangeSignal(); +#ifndef QT_NO_CURSOR + void enterLeaveOnWindowShowHide_data(); + void enterLeaveOnWindowShowHide(); +#endif + void windowExposedAfterReparent(); + void childEvents(); + void parentEvents(); private: QPoint m_availableTopLeft; @@ -119,8 +114,17 @@ private: QInputDevice::Capability::Position | QInputDevice::Capability::MouseEmulation); }; +static bool isPlatformWayland() +{ + return QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive); +} + void tst_QWindow::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 window, 200 for < 2000, scale up for larger screens // to avoid Windows warnings about minimum size for decorated windows. int width = 200; @@ -130,6 +134,10 @@ void tst_QWindow::initTestCase() if (screenWidth > 2000) width = 100 * ((screenWidth + 500) / 1000); m_testWindowSize = QSize(width, width); + + // Make sure test runs consistently on all compositors by force-disabling window decorations + if (isPlatformWayland()) + qputenv("QT_WAYLAND_DISABLE_WINDOWDECORATION", "1"); } void tst_QWindow::cleanup() @@ -242,6 +250,40 @@ void tst_QWindow::setVisible() QVERIFY(QTest::qWaitForWindowExposed(&i)); } +class SurfaceCreatedWindow : public QWindow +{ + Q_OBJECT +public: + using QWindow::QWindow; + + bool eventFilter(QObject *o, QEvent *e) override + { + if (e->type() == QEvent::PlatformSurface) { + auto type = static_cast<QPlatformSurfaceEvent*>(e)->surfaceEventType(); + if (type == QPlatformSurfaceEvent::SurfaceCreated) + ++surfaceCreatedEvents; + } + return QWindow::eventFilter(o, e); + } + + int surfaceCreatedEvents = 0; +}; + +void tst_QWindow::setVisibleThenCreate() +{ + QWindow parent; + parent.setObjectName("Parent"); + SurfaceCreatedWindow child(&parent); + child.installEventFilter(&child); + child.setObjectName("Child"); + child.setVisible(true); + child.create(); + QCOMPARE(child.surfaceCreatedEvents, 1); + parent.setVisible(true); + QCOMPARE(child.surfaceCreatedEvents, 1); + QVERIFY(QTest::qWaitForWindowExposed(&child)); +} + void tst_QWindow::setVisibleFalseDoesNotCreateWindow() { QWindow w; @@ -292,7 +334,7 @@ public: #if !defined(Q_OS_MACOS) // FIXME: All platforms should send window-state change events, regardless // of the sync/async nature of the the underlying platform, but they don't. - connect(this, &QWindow::windowStateChanged, [=]() { + connect(this, &QWindow::windowStateChanged, [this]() { lastReceivedWindowState = windowState(); }); #endif @@ -309,13 +351,6 @@ public: m_received[event->type()]++; m_order << event->type(); switch (event->type()) { - case QEvent::Expose: -QT_WARNING_PUSH -QT_WARNING_DISABLE_DEPRECATED - m_exposeRegion = static_cast<QExposeEvent *>(event)->region(); -QT_WARNING_POP - break; - case QEvent::PlatformSurface: m_surfaceventType = static_cast<QPlatformSurfaceEvent *>(event)->surfaceEventType(); break; @@ -345,11 +380,6 @@ QT_WARNING_POP return m_order.indexOf(type); } - QRegion exposeRegion() const - { - return m_exposeRegion; - } - QPlatformSurfaceEvent::SurfaceEventType surfaceEventType() const { return m_surfaceventType; @@ -361,7 +391,6 @@ QT_WARNING_POP private: QHash<QEvent::Type, int> m_received; QList<QEvent::Type> m_order; - QRegion m_exposeRegion; QPlatformSurfaceEvent::SurfaceEventType m_surfaceventType; }; @@ -453,11 +482,16 @@ void tst_QWindow::resizeEventAfterResize() // Make sure we get a resizeEvent after calling resize window.resize(m_testWindowSize); + if (isPlatformEglFS()) + QEXPECT_FAIL("", "eglfs windows are fullscreen by default.", Continue); + QTRY_COMPARE(window.received(QEvent::Resize), 2); } void tst_QWindow::exposeEventOnShrink_QTBUG54040() { + if (isPlatformEglFS()) + QSKIP("", "eglfs windows are fullscreen by default.", Continue); Window window; window.setGeometry(QRect(m_availableTopLeft + QPoint(80, 80), m_testWindowSize)); window.setTitle(QTest::currentTestFunction()); @@ -521,13 +555,11 @@ static QString msgRectMismatch(const QRect &r1, const QRect &r2) return result; } -static bool isPlatformWayland() -{ - return !QGuiApplication::platformName().compare(QLatin1String("wayland"), Qt::CaseInsensitive); -} - void tst_QWindow::positioning() { +#ifdef Q_OS_ANDROID + QSKIP("Fails on Android. QTBUG-105201"); +#endif if (!QGuiApplicationPrivate::platformIntegration()->hasCapability( QPlatformIntegration::NonFullScreenWindows)) { QSKIP("This platform does not support non-fullscreen windows"); @@ -549,9 +581,8 @@ void tst_QWindow::positioning() QCOMPARE(window.geometry(), geometry); // explicitly use non-fullscreen show. show() can be fullscreen on some platforms window.showNormal(); - QCoreApplication::processEvents(); - QVERIFY(QTest::qWaitForWindowExposed(&window)); + QVERIFY(QTest::qWaitForWindowActive(&window)); QMargins originalMargins = window.frameMargins(); @@ -643,9 +674,8 @@ void tst_QWindow::childWindowPositioning_data() void tst_QWindow::childWindowPositioning() { - if (isPlatformWayland()) - QSKIP("Wayland: This is flaky (protocol errors for xdg-shell v6). See QTBUG-67648."); - + if (isPlatformEglFS()) + QSKIP("eglfs does not support child windows."); const QPoint topLeftOrigin(0, 0); ColoredWindow topLevelWindowFirst(Qt::green); @@ -748,7 +778,7 @@ void tst_QWindow::stateChange() // explicitly use non-fullscreen show. show() can be fullscreen on some platforms window.showNormal(); QVERIFY(QTest::qWaitForWindowExposed(&window)); - for (Qt::WindowState state : qAsConst(stateSequence)) { + for (Qt::WindowState state : std::as_const(stateSequence)) { window.setWindowState(state); QCoreApplication::processEvents(); } @@ -822,16 +852,6 @@ void tst_QWindow::isExposed() QTRY_VERIFY(window.received(QEvent::Expose) > 0); QTRY_VERIFY(window.isExposed()); -#ifndef Q_OS_WIN - // This is a top-level window so assuming it is completely exposed, the - // expose region must be (0, 0), (width, height). If this is not the case, - // the platform plugin is sending expose events with a region in an - // incorrect coordinate system. - QRect r = window.exposeRegion().boundingRect(); - r = QRect(window.mapToGlobal(r.topLeft()), r.size()); - QCOMPARE(r, window.geometry()); -#endif - window.hide(); QCoreApplication::processEvents(); @@ -964,6 +984,10 @@ public: if (ignoreMouse) { event->ignore(); } else { + QCOMPARE(event->isBeginEvent(), true); + QCOMPARE(event->isUpdateEvent(), false); + QCOMPARE(event->isEndEvent(), false); + QCOMPARE(event->points().first().state(), QEventPoint::State::Pressed); ++mousePressedCount; mouseSequenceSignature += 'p'; mousePressButton = event->button(); @@ -972,6 +996,9 @@ public: if (spinLoopWhenPressed) QCoreApplication::processEvents(); } + if (closeOnTap) + this->close(); + } void mouseReleaseEvent(QMouseEvent *event) override { @@ -979,6 +1006,10 @@ public: if (ignoreMouse) { event->ignore(); } else { + QCOMPARE(event->isBeginEvent(), false); + QCOMPARE(event->isUpdateEvent(), false); + QCOMPARE(event->isEndEvent(), true); + QCOMPARE(event->points().first().state(), QEventPoint::State::Released); ++mouseReleasedCount; mouseSequenceSignature += 'r'; mouseReleaseButton = event->button(); @@ -991,6 +1022,10 @@ public: if (ignoreMouse) { event->ignore(); } else { + QCOMPARE(event->isBeginEvent(), false); + QCOMPARE(event->isUpdateEvent(), true); + QCOMPARE(event->isEndEvent(), false); + QCOMPARE(event->points().first().state(), QEventPoint::State::Updated); ++mouseMovedCount; mouseMoveButton = event->button(); mouseMoveScreenPos = event->globalPosition(); @@ -1002,6 +1037,10 @@ public: if (ignoreMouse) { event->ignore(); } else { + QCOMPARE(event->isBeginEvent(), false); + QCOMPARE(event->isUpdateEvent(), true); + QCOMPARE(event->isEndEvent(), false); + QCOMPARE(event->points().first().state(), QEventPoint::State::Stationary); ++mouseDoubleClickedCount; mouseSequenceSignature += 'd'; } @@ -1016,12 +1055,19 @@ public: } touchEventType = event->type(); QList<QTouchEvent::TouchPoint> points = event->points(); - for (int i = 0; i < points.count(); ++i) { - switch (points.at(i).state()) { + for (int i = 0; i < points.size(); ++i) { + const auto &point = points.at(i); + switch (point.state()) { case QEventPoint::State::Pressed: ++touchPressedCount; if (spinLoopWhenPressed) QCoreApplication::processEvents(); + if (i == 0) { + touchPressLocalPos = point.position(); + touchPressGlobalPos = point.globalPosition(); + } + if (closeOnTap) + this->close(); break; case QEventPoint::State::Released: ++touchReleasedCount; @@ -1066,6 +1112,7 @@ public: int mousePressedCount = 0, mouseReleasedCount = 0, mouseMovedCount = 0, mouseDoubleClickedCount = 0; QString mouseSequenceSignature; QPointF mousePressScreenPos, mouseMoveScreenPos, mousePressLocalPos; + QPointF touchPressGlobalPos, touchPressLocalPos; int touchPressedCount = 0, touchReleasedCount = 0, touchMovedCount = 0; QEvent::Type touchEventType = QEvent::None; int enterEventCount = 0, leaveEventCount = 0; @@ -1077,23 +1124,25 @@ public: const QPointingDevice *mouseDevice = nullptr; const QPointingDevice *touchDevice = nullptr; + + bool closeOnTap = false; }; static void simulateMouseClick(QWindow *target, const QPointF &local, const QPointF &global) { QWindowSystemInterface::handleMouseEvent(target, local, global, - {}, Qt::LeftButton, QEvent::MouseButtonPress); + Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress); QWindowSystemInterface::handleMouseEvent(target, local, global, - Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonRelease); + {}, Qt::LeftButton, QEvent::MouseButtonRelease); } static void simulateMouseClick(QWindow *target, ulong &timeStamp, const QPointF &local, const QPointF &global) { QWindowSystemInterface::handleMouseEvent(target, timeStamp++, local, global, - {}, Qt::LeftButton, QEvent::MouseButtonPress); + Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress); QWindowSystemInterface::handleMouseEvent(target, timeStamp++, local, global, - Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonRelease); + {}, Qt::LeftButton, QEvent::MouseButtonRelease); } void tst_QWindow::testInputEvents() @@ -1226,6 +1275,30 @@ void tst_QWindow::touchToMouseTranslation() // mouse event synthesizing disabled QTRY_COMPARE(window.mousePressButton, 0); QTRY_COMPARE(window.mouseReleaseButton, 0); + + points.clear(); + points.append(tp2); + points[0].state = QEventPoint::State::Pressed; + QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); + QCoreApplication::processEvents(); + points.clear(); + points.append(tp1); + points[0].state = QEventPoint::State::Pressed; + QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); + QCoreApplication::processEvents(); + QTRY_COMPARE(window.mousePressButton, 1); + + points.clear(); + points.append(tp2); + points[0].state = QEventPoint::State::Released; + QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); + QCoreApplication::processEvents(); + points.clear(); + points.append(tp1); + points[0].state = QEventPoint::State::Released; + QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); + QCoreApplication::processEvents(); + QTRY_COMPARE(window.mouseReleaseButton, 1); } void tst_QWindow::touchToMouseTranslationForDevices() @@ -1267,7 +1340,8 @@ void tst_QWindow::mouseToTouchTranslation() window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); - QTest::mouseClick(&window, Qt::LeftButton, {}, QPoint(10, 10)); + const QPoint localPos(10, 10); + QTest::mouseClick(&window, Qt::LeftButton, {}, localPos); QCoreApplication::processEvents(); QCoreApplication::setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, false); @@ -1275,13 +1349,17 @@ void tst_QWindow::mouseToTouchTranslation() QTRY_COMPARE(window.touchPressedCount, 1); QTRY_COMPARE(window.touchReleasedCount, 1); QCOMPARE(window.mouseDevice, window.touchDevice); + if (isPlatformWayland()) + QEXPECT_FAIL("", "Wayland: This fails. See QTBUG-100887.", Abort); QCOMPARE(window.touchDevice->type(), QInputDevice::DeviceType::Mouse); + QCOMPARE(window.touchPressLocalPos.toPoint(), localPos); + QCOMPARE(window.touchPressGlobalPos.toPoint(), window.mapToGlobal(localPos)); QCoreApplication::setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, true); window.ignoreMouse = false; - QTest::mouseClick(&window, Qt::LeftButton, {}, QPoint(10, 10)); + QTest::mouseClick(&window, Qt::LeftButton, {}, localPos); QCoreApplication::processEvents(); QCoreApplication::setAttribute(Qt::AA_SynthesizeTouchForUnhandledMouseEvents, false); @@ -1292,14 +1370,12 @@ void tst_QWindow::mouseToTouchTranslation() window.ignoreMouse = true; - QTest::mouseClick(&window, Qt::LeftButton, {}, QPoint(10, 10)); + QTest::mouseClick(&window, Qt::LeftButton, {}, localPos); QCoreApplication::processEvents(); // touch event synthesis disabled QTRY_COMPARE(window.touchPressedCount, 1); QTRY_COMPARE(window.touchReleasedCount, 1); - - } void tst_QWindow::mouseToTouchLoop() @@ -1432,10 +1508,8 @@ void tst_QWindow::touchCancelWithTouchToMouse() void tst_QWindow::touchInterruptedByPopup() { - if (isPlatformWayland()) - QSKIP("Wayland: This test crashes with xdg-shell unstable v6"); - InputTestWindow window; + window.setObjectName("main"); window.setTitle(QLatin1String(QTest::currentTestFunction())); window.setGeometry(QRect(m_availableTopLeft + QPoint(80, 80), m_testWindowSize)); window.show(); @@ -1456,6 +1530,7 @@ void tst_QWindow::touchInterruptedByPopup() // Launch a popup window InputTestWindow popup; + window.setObjectName("popup"); popup.setFlags(Qt::Popup); popup.setModality(Qt::WindowModal); popup.resize(m_testWindowSize / 2); @@ -1478,9 +1553,6 @@ void tst_QWindow::touchInterruptedByPopup() QWindowSystemInterface::handleTouchEvent(&window, touchDevice, points); QCoreApplication::processEvents(); QTRY_COMPARE(window.touchReleasedCount, 0); - - // Due to temporary fix for QTBUG-37371: the original window should receive a TouchCancel - QTRY_COMPARE(window.touchEventType, QEvent::TouchCancel); } void tst_QWindow::orientation() @@ -1499,7 +1571,7 @@ void tst_QWindow::orientation() QSignalSpy spy(&window, SIGNAL(contentOrientationChanged(Qt::ScreenOrientation))); window.reportContentOrientationChange(Qt::LandscapeOrientation); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); } void tst_QWindow::sizes() @@ -1518,56 +1590,168 @@ void tst_QWindow::sizes() QCOMPARE(window.minimumHeight(), 0); QCOMPARE(window.minimumSize(), QSize(10, 0)); QCOMPARE(window.maximumSize(), oldMaximum); - QCOMPARE(minimumWidthSpy.count(), 1); - QCOMPARE(minimumHeightSpy.count(), 0); - QCOMPARE(maximumWidthSpy.count(), 0); - QCOMPARE(maximumHeightSpy.count(), 0); + QCOMPARE(minimumWidthSpy.size(), 1); + QCOMPARE(minimumHeightSpy.size(), 0); + QCOMPARE(maximumWidthSpy.size(), 0); + QCOMPARE(maximumHeightSpy.size(), 0); window.setMinimumHeight(10); QCOMPARE(window.minimumWidth(), 10); QCOMPARE(window.minimumHeight(), 10); QCOMPARE(window.minimumSize(), QSize(10, 10)); QCOMPARE(window.maximumSize(), oldMaximum); - QCOMPARE(minimumWidthSpy.count(), 1); - QCOMPARE(minimumHeightSpy.count(), 1); - QCOMPARE(maximumWidthSpy.count(), 0); - QCOMPARE(maximumHeightSpy.count(), 0); + QCOMPARE(minimumWidthSpy.size(), 1); + QCOMPARE(minimumHeightSpy.size(), 1); + QCOMPARE(maximumWidthSpy.size(), 0); + QCOMPARE(maximumHeightSpy.size(), 0); window.setMaximumWidth(100); QCOMPARE(window.maximumWidth(), 100); QCOMPARE(window.maximumHeight(), oldMaximum.height()); QCOMPARE(window.minimumSize(), QSize(10, 10)); QCOMPARE(window.maximumSize(), QSize(100, oldMaximum.height())); - QCOMPARE(minimumWidthSpy.count(), 1); - QCOMPARE(minimumHeightSpy.count(), 1); - QCOMPARE(maximumWidthSpy.count(), 1); - QCOMPARE(maximumHeightSpy.count(), 0); + QCOMPARE(minimumWidthSpy.size(), 1); + QCOMPARE(minimumHeightSpy.size(), 1); + QCOMPARE(maximumWidthSpy.size(), 1); + QCOMPARE(maximumHeightSpy.size(), 0); window.setMaximumHeight(100); QCOMPARE(window.maximumWidth(), 100); QCOMPARE(window.maximumHeight(), 100); QCOMPARE(window.minimumSize(), QSize(10, 10)); QCOMPARE(window.maximumSize(), QSize(100, 100)); - QCOMPARE(minimumWidthSpy.count(), 1); - QCOMPARE(minimumHeightSpy.count(), 1); - QCOMPARE(maximumWidthSpy.count(), 1); - QCOMPARE(maximumHeightSpy.count(), 1); -} + QCOMPARE(minimumWidthSpy.size(), 1); + QCOMPARE(minimumHeightSpy.size(), 1); + QCOMPARE(maximumWidthSpy.size(), 1); + QCOMPARE(maximumHeightSpy.size(), 1); + + // test if min and max limits will change the size + QVERIFY(window.minimumWidth() < 50 && window.maximumWidth() > 80); + QVERIFY(window.minimumHeight() < 50 && window.maximumHeight() > 80); + window.resize(50, 50); + QCOMPARE(window.size(), QSize(50, 50)); + window.setMinimumSize(QSize(60, 60)); + QCOMPARE(window.size(), QSize(60, 60)); + window.resize(80, 80); + window.setMaximumSize(QSize(70, 70)); + QCOMPARE(window.size(), QSize(70, 70)); + + // QTBUG-113233 + // test for an invalid min/max pair + window.setMinimumSize(QSize(80, 80)); // current maximumSize = QSize(70, 70) + QCOMPARE(window.size(), QSize(70, 70)); + window.setMaximumSize(QSize(90, 90)); + QCOMPARE(window.size(), QSize(80, 80)); +} + +class CloseOnCloseEventWindow : public QWindow +{ +public: + inline static int closeEvents; + CloseOnCloseEventWindow() { closeEvents = 0; } + +protected: + void closeEvent(QCloseEvent *e) override + { + if (++closeEvents > 1) + return; + + close(); + e->accept(); + } +}; void tst_QWindow::close() { - QWindow a; - a.setTitle(QLatin1String(QTest::currentTestFunction())); - QWindow b; - QWindow c(&a); + { + QWindow a; + QWindow b; + QWindow c(&a); + + a.show(); + b.show(); + + // we can not close a non top level window + QVERIFY(!c.close()); + QVERIFY(a.close()); + QVERIFY(b.close()); + } + + // Verify that closing a QWindow deletes its platform window, + // independent of API used to close the window. + { + // Close with QWindow::close + { + QWindow w; + w.create(); + QVERIFY(w.handle()); + w.close(); + QVERIFY(!w.handle()); + } - a.show(); - b.show(); + // Close with QWindowSystemInterface::handleCloseEvent(); + { + QWindow w; + w.create(); + QVERIFY(w.handle()); + QWindowSystemInterface::handleCloseEvent(&w); + QCoreApplication::processEvents(); + QVERIFY(!w.handle()); + } + } - // we can not close a non top level window - QVERIFY(!c.close()); - QVERIFY(a.close()); - QVERIFY(b.close()); + // Verify that closing a QWindow deletes the platform window for + // child windows + { + QWindow w; + QWindow c(&w); + w.create(); + c.create(); + QVERIFY(w.handle()); + QVERIFY(c.handle()); + w.close(); + QVERIFY(!w.handle()); + QVERIFY(!c.handle()); + } + + // Verify that re-creating closed windows is possble. + { + // Re-create top-level window + { + QWindow w; + w.create(); + QVERIFY(w.handle()); + w.close(); + QVERIFY(!w.handle()); + w.create(); + QVERIFY(w.handle()); + } + + // Re-create top-level window with child window + { + QWindow w; + QWindow c(&w); + c.create(); + QVERIFY(w.handle()); + QVERIFY(c.handle()); + w.close(); + QVERIFY(!w.handle()); + QVERIFY(!c.handle()); + c.create(); + QVERIFY(w.handle()); + QVERIFY(c.handle()); + } + } + + { + // A QWidget will call close() from the destructor, and + // we allow widgets deleting itself in the closeEvent, + // so we need to guard against close being called recursively. + CloseOnCloseEventWindow w; + w.create(); + w.close(); + QCOMPARE(CloseOnCloseEventWindow::closeEvents, 1); + } } void tst_QWindow::activateAndClose() @@ -1689,25 +1873,25 @@ void tst_QWindow::windowModality() QCOMPARE(window.modality(), Qt::NonModal); window.setModality(Qt::NonModal); QCOMPARE(window.modality(), Qt::NonModal); - QCOMPARE(spy.count(), 0); + QCOMPARE(spy.size(), 0); window.setModality(Qt::WindowModal); QCOMPARE(window.modality(), Qt::WindowModal); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); window.setModality(Qt::WindowModal); QCOMPARE(window.modality(), Qt::WindowModal); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); window.setModality(Qt::ApplicationModal); QCOMPARE(window.modality(), Qt::ApplicationModal); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); window.setModality(Qt::ApplicationModal); QCOMPARE(window.modality(), Qt::ApplicationModal); - QCOMPARE(spy.count(), 2); + QCOMPARE(spy.size(), 2); window.setModality(Qt::NonModal); QCOMPARE(window.modality(), Qt::NonModal); - QCOMPARE(spy.count(), 3); + QCOMPARE(spy.size(), 3); } void tst_QWindow::inputReentrancy() @@ -1722,12 +1906,12 @@ void tst_QWindow::inputReentrancy() // Queue three events. QPointF local(12, 34); - QWindowSystemInterface::handleMouseEvent(&window, local, local, {}, + QWindowSystemInterface::handleMouseEvent(&window, local, local, Qt::LeftButton, Qt::LeftButton, QEvent::MouseButtonPress); local += QPointF(2, 2); QWindowSystemInterface::handleMouseEvent(&window, local, local, - Qt::LeftButton, Qt::LeftButton, QEvent::MouseMove); - QWindowSystemInterface::handleMouseEvent(&window, local, local, Qt::LeftButton, + Qt::LeftButton, {}, QEvent::MouseMove); + QWindowSystemInterface::handleMouseEvent(&window, local, local, {}, Qt::LeftButton, QEvent::MouseButtonRelease); // Process them. However, the event handler for the press will also call // processEvents() so the move and release will be delivered before returning @@ -1736,7 +1920,8 @@ void tst_QWindow::inputReentrancy() QCOMPARE(window.mousePressButton, int(Qt::LeftButton)); QCOMPARE(window.mouseReleaseButton, int(Qt::LeftButton)); QCOMPARE(window.mousePressedCount, 1); - QCOMPARE(window.mouseMovedCount, 1); + // The mouse press may have generated a synthetic move in QGuiApplicationPrivate::processMouseEvent() + QVERIFY(window.mouseMovedCount == 1 || window.mouseMovedCount == 2); QCOMPARE(window.mouseReleasedCount, 1); // Now the same for touch. @@ -1889,32 +2074,32 @@ void tst_QWindow::visibility() QVERIFY(window.isVisible()); QVERIFY(window.visibility() != QWindow::Hidden); QVERIFY(window.visibility() != QWindow::AutomaticVisibility); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); window.setVisibility(QWindow::Hidden); QVERIFY(!window.isVisible()); QCOMPARE(window.visibility(), QWindow::Hidden); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); window.setVisibility(QWindow::FullScreen); QVERIFY(window.isVisible()); QCOMPARE(window.windowState(), Qt::WindowFullScreen); QCOMPARE(window.visibility(), QWindow::FullScreen); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QTRY_COMPARE(window.lastReceivedWindowState, Qt::WindowFullScreen); spy.clear(); window.setWindowState(Qt::WindowNoState); QCOMPARE(window.visibility(), QWindow::Windowed); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); QTRY_COMPARE(window.lastReceivedWindowState, Qt::WindowNoState); spy.clear(); window.setVisible(false); QCOMPARE(window.visibility(), QWindow::Hidden); - QCOMPARE(spy.count(), 1); + QCOMPARE(spy.size(), 1); spy.clear(); } @@ -1947,9 +2132,6 @@ void tst_QWindow::mask() void tst_QWindow::initialSize() { - if (isPlatformWayland()) - QSKIP("Wayland: This fails. See QTBUG-66818."); - QSize defaultSize(0,0); { Window w; @@ -1964,6 +2146,10 @@ void tst_QWindow::initialSize() w.setTitle(QLatin1String(QTest::currentTestFunction())); w.setWidth(m_testWindowSize.width()); w.showNormal(); + + if (isPlatformEglFS()) + QEXPECT_FAIL("", "eglfs windows are fullscreen by default.", Continue); + QTRY_COMPARE(w.width(), m_testWindowSize.width()); QTRY_VERIFY(w.height() > 0); } @@ -1975,6 +2161,8 @@ void tst_QWindow::initialSize() w.showNormal(); const QSize expectedSize = testSize; + if (isPlatformEglFS()) + QEXPECT_FAIL("", "eglfs windows are fullscreen by default.", Continue); QTRY_COMPARE(w.size(), expectedSize); } } @@ -2014,7 +2202,7 @@ void tst_QWindow::modalDialog() QGuiApplication::processEvents(); if (isPlatformOffscreenOrMinimal()) { - QWARN("Focus stays in normalWindow on offscreen/minimal platforms"); + qWarning("Focus stays in normalWindow on offscreen/minimal platforms"); QTRY_COMPARE(QGuiApplication::focusWindow(), &normalWindow); return; } @@ -2060,7 +2248,7 @@ void tst_QWindow::modalDialogClosingOneOfTwoModal() QGuiApplication::processEvents(); if (isPlatformOffscreenOrMinimal()) { - QWARN("Focus is lost when closing modal dialog on offscreen/minimal platforms"); + qWarning("Focus is lost when closing modal dialog on offscreen/minimal platforms"); QTRY_COMPARE(QGuiApplication::focusWindow(), nullptr); return; } @@ -2139,6 +2327,9 @@ void tst_QWindow::modalWindowModallity() void tst_QWindow::modalWindowPosition() { + if (isPlatformWayland()) + QSKIP("Window position not queryable on Wayland"); + QWindow window; window.setTitle(QLatin1String(QTest::currentTestFunction())); window.setGeometry(QRect(m_availableTopLeft + QPoint(100, 100), m_testWindowSize)); @@ -2147,9 +2338,29 @@ void tst_QWindow::modalWindowPosition() window.setModality(Qt::WindowModal); window.show(); QVERIFY(QTest::qWaitForWindowExposed(&window)); + + if (isPlatformEglFS()) + QEXPECT_FAIL("", "eglfs windows are fullscreen by default.", Continue); + QCOMPARE(window.geometry(), origGeo); } +void tst_QWindow::modalCloseWhileBlocked() +{ + QWindow first; + first.setModality(Qt::ApplicationModal); + first.show(); + QVERIFY(QTest::qWaitForWindowExposed(&first)); + + QWindow second; + second.setModality(Qt::ApplicationModal); + second.show(); + QVERIFY(QTest::qWaitForWindowExposed(&first)); + + first.close(); + QTRY_VERIFY(!first.isVisible()); +} + #ifndef QT_NO_CURSOR void tst_QWindow::modalWindowEnterEventOnHide_QTBUG35109() { @@ -2159,6 +2370,9 @@ void tst_QWindow::modalWindowEnterEventOnHide_QTBUG35109() if (isPlatformOffscreenOrMinimal()) QSKIP("Can't test window focusing on offscreen/minimal"); + if (isPlatformEglFS()) + QSKIP("QCursor::setPos() is not supported on this platform"); + const QPoint center = QGuiApplication::primaryScreen()->availableGeometry().center(); const int childOffset = 16; @@ -2337,6 +2551,10 @@ void tst_QWindow::spuriousMouseMove() const QString &platformName = QGuiApplication::platformName(); if (platformName == QLatin1String("offscreen") || platformName == QLatin1String("cocoa")) QSKIP("No enter events sent"); + if (platformName == QLatin1String("wayland")) + QSKIP("Setting mouse cursor position is not possible on Wayland"); + if (isPlatformEglFS()) + QSKIP("QCursor::setPos() is not supported on this platform"); const QRect screenGeometry = QGuiApplication::primaryScreen()->geometry(); const QPoint center = screenGeometry.center(); QCursor::setPos(center); @@ -2554,6 +2772,453 @@ void tst_QWindow::keepPendingUpdateRequests() QTRY_VERIFY(!platformWindow->hasPendingUpdateRequest()); } +void tst_QWindow::activateDeactivateEvent() +{ + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("QWindow::requestActivate() is not supported."); + + class Window : public QWindow + { + public: + using QWindow::QWindow; + + int activateCount = 0; + int deactivateCount = 0; + protected: + bool event(QEvent *e) override + { + switch (e->type()) { + case QEvent::WindowActivate: + ++activateCount; + break; + case QEvent::WindowDeactivate: + ++deactivateCount; + break; + default: + break; + } + return QWindow::event(e); + } + }; + + Window w1; + Window w2; + + w1.show(); + w1.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&w1)); + QCOMPARE(w1.activateCount, 1); + QCOMPARE(w1.deactivateCount, 0); + + w2.show(); + w2.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&w2)); + QCOMPARE(w1.deactivateCount, 1); + QCOMPARE(w2.activateCount, 1); +} + +// Test that in a slot connected to destroyed() the emitter is +// is no longer a QWindow. +void tst_QWindow::qobject_castOnDestruction() +{ + QWindow window; + QObject::connect(&window, &QObject::destroyed, [](QObject *object) + { + QVERIFY(!qobject_cast<QWindow *>(object)); + QVERIFY(!dynamic_cast<QWindow *>(object)); + QVERIFY(!object->isWindowType()); + }); +} + +void tst_QWindow::touchToMouseTranslationByPopup() +{ + InputTestWindow window; + window.setTitle(QLatin1String(QTest::currentTestFunction())); + window.ignoreTouch = true; + window.setGeometry(QRect(m_availableTopLeft, m_testWindowSize)); + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + + InputTestWindow popupWindow; + popupWindow.setGeometry(QRect(m_availableTopLeft + QPoint(20, 20), + QSize(m_testWindowSize.width(), m_testWindowSize.height() / 2))); + popupWindow.setFlag(Qt::Popup); + popupWindow.setTransientParent(&window); + popupWindow.ignoreTouch = true; + popupWindow.closeOnTap = true; + popupWindow.show(); + QVERIFY(QTest::qWaitForWindowExposed(&popupWindow)); + + QTest::touchEvent(&popupWindow, touchDevice).press(0, {1, 1}, &window); + QVERIFY(!popupWindow.isVisible()); + + // Omit touchpoint 0: because the popup was closed, touchpoint0.release is not sent. + const QPoint tp1(50, 1); + QTest::touchEvent(&window, touchDevice).press(1, tp1, &window); + QTRY_COMPARE(window.mousePressButton, int(Qt::LeftButton)); + QTest::touchEvent(&window, touchDevice).release(1, tp1, &window); + QTRY_COMPARE(window.mouseReleaseButton, int(Qt::LeftButton)); +} + +// Test that windowStateChanged is not emitted on noop change (QTBUG-102478) +void tst_QWindow::stateChangeSignal() +{ + // Test only for Windows, Linux and macOS +#if !defined(Q_OS_LINUX) && !defined(Q_OS_WINDOWS) && !defined(Q_OS_DARWIN) + QSKIP("Singular windowStateChanged signal emission is guaranteed for Linux, Windows and macOS only.\n" + "On other operating systems, the signal may be emitted twice."); +#endif + QWindow w; + Q_ASSERT(connect (&w, &QWindow::windowStateChanged, [](Qt::WindowState s){qCDebug(lcTests) << "State change to" << s;})); + QSignalSpy spy(&w, SIGNAL(windowStateChanged(Qt::WindowState))); + unsigned short signalCount = 0; + QList<Qt::WindowState> effectiveStates; + Q_ASSERT(connect(&w, &QWindow::windowStateChanged, [&effectiveStates](Qt::WindowState state) + { effectiveStates.append(state); })); + // Part 1: + // => test signal emission on programmatic state changes + QCOMPARE(w.windowState(), Qt::WindowNoState); + // - wait for target state to be set + // - wait for signal spy to have reached target count + // - extract state from signal and compare to target +#define CHECK_STATE(State)\ + QTRY_VERIFY(QTest::qWaitFor([&w](){return (w.windowState() == State); }));\ + CHECK_SIGNAL(State) +#define CHECK_SIGNAL(State)\ + QTRY_COMPARE(spy.count(), signalCount);\ + if (signalCount > 0) {\ + QVariantList list = spy.at(signalCount - 1).toList();\ + QCOMPARE(list.count(), 1);\ + bool ok;\ + const int stateInt = list.at(0).toInt(&ok);\ + QVERIFY(ok);\ + const Qt::WindowState newState = static_cast<Qt::WindowState>(stateInt);\ + QCOMPARE(newState, State);\ + } + // Check initialization + CHECK_STATE(Qt::WindowNoState); + // showMaximized after init + // expected behavior: signal emitted once with state == WindowMaximized + ++signalCount; + w.showMaximized(); + CHECK_STATE(Qt::WindowMaximized); + // setWindowState to normal + // expected behavior: signal emitted once with state == WindowNoState + ++signalCount; + w.setWindowState(Qt::WindowNoState); + CHECK_STATE(Qt::WindowNoState); + // redundant setWindowState to normal - except windows, where the no-op is counted + // expected behavior: No emits. + // On Windows, a no-op state change causes a no-op resize and repaint, leading to a + // no-op state change and singal emission. +#ifdef Q_OS_WINDOWS + ++signalCount; + ++signalCount; +#endif + w.setWindowState(Qt::WindowNoState); + CHECK_STATE(Qt::WindowNoState); + // setWindowState to minimized + // expected behavior: signal emitted once with state == WindowMinimized + ++signalCount; + w.showMinimized(); + CHECK_STATE(Qt::WindowMinimized); + // setWindowState to Normal + // expected behavior: signal emitted once with state == WindowNoState + ++signalCount; + w.showNormal(); + CHECK_STATE(Qt::WindowNoState); + /* + - Testcase showFullScreen is omitted: Depending on window manager, + WindowFullScreen can be mapped to WindowMaximized + - Transition from WindowMinimized to WindowMaximized is omitted: + WindowNoState to WindowMaximized + */ + // Part 2: + // => test signal emission on simulated user interaction + // To test the code path, inject state change events into the QPA event queue. + // Test the signal emission only, not the window's actual visible state. + + // Flush pending events and clear + QCoreApplication::processEvents(); + spy.clear(); + effectiveStates.clear(); + signalCount = 0; + // Maximize window + QWindowSystemInterface::handleWindowStateChanged(&w, Qt::WindowMaximized, w.windowState()); + ++signalCount; + CHECK_SIGNAL(Qt::WindowMaximized); + // Normalize window + QWindowSystemInterface::handleWindowStateChanged(&w, Qt::WindowNoState, w.windowState()); + ++signalCount; + CHECK_SIGNAL(Qt::WindowNoState); + // Minimize window + QWindowSystemInterface::handleWindowStateChanged(&w, Qt::WindowMinimized, w.windowState()); + ++signalCount; + CHECK_SIGNAL(Qt::WindowMinimized); +} + +#ifndef QT_NO_CURSOR +void tst_QWindow::enterLeaveOnWindowShowHide_data() +{ + QTest::addColumn<Qt::WindowType>("windowType"); + QTest::addRow("dialog") << Qt::Dialog; + QTest::addRow("popup") << Qt::Popup; +} + +/*! + Verify that we get enter and leave events if the window under the mouse + opens and closes a modal dialog or popup. QWindow might get multiple + events in a row, as the various QPA plugins need to use different techniques + to synthesize events if the native platform doesn't provide them for us. +*/ +void tst_QWindow::enterLeaveOnWindowShowHide() +{ + if (isPlatformWayland()) + QSKIP("Can't set cursor position and qWaitForWindowActive on Wayland"); + + if (isPlatformEglFS()) + QSKIP("QCursor::setPos() is not supported on this platform"); + + QFETCH(Qt::WindowType, windowType); + + class Window : public QWindow + { + public: + int numEnterEvents = 0; + int numLeaveEvents = 0; + QPoint enterPosition; + protected: + bool event(QEvent *e) override + { + switch (e->type()) { + case QEvent::Enter: + ++numEnterEvents; + enterPosition = static_cast<QEnterEvent*>(e)->position().toPoint(); + break; + case QEvent::Leave: + ++numLeaveEvents; + break; + default: + break; + } + return QWindow::event(e); + } + }; + + int expectedEnter = 0; + int expectedLeave = 0; + + Window window; + const QRect screenGeometry = window.screen()->availableGeometry(); + const QPoint cursorPos = screenGeometry.topLeft() + QPoint(50, 50); + window.setGeometry(QRect(cursorPos - QPoint(50, 50), screenGeometry.size() / 4)); + QCursor::setPos(cursorPos); + + if (!QTest::qWaitFor([&]{ return window.geometry().contains(QCursor::pos()); })) + QSKIP("We can't move the cursor"); + + window.show(); + window.requestActivate(); + QVERIFY(QTest::qWaitForWindowActive(&window)); + + ++expectedEnter; + QTRY_COMPARE_WITH_TIMEOUT(window.numEnterEvents, expectedEnter, 250); + QCOMPARE(window.enterPosition, window.mapFromGlobal(QCursor::pos())); + + QWindow secondary; + secondary.setFlag(windowType); + secondary.setModality(Qt::WindowModal); + secondary.setTransientParent(&window); + secondary.setPosition(cursorPos + QPoint(50, 50)); + secondary.show(); + QVERIFY(QTest::qWaitForWindowExposed(&secondary)); + ++expectedLeave; + QTRY_VERIFY(window.numLeaveEvents >= expectedLeave); + secondary.close(); + ++expectedEnter; + QTRY_VERIFY(window.numEnterEvents >= expectedEnter); + QCOMPARE(window.enterPosition, window.mapFromGlobal(QCursor::pos())); +} +#endif + +void tst_QWindow::windowExposedAfterReparent() +{ + QWindow parent; + QWindow child(&parent); + child.show(); + parent.show(); + + QVERIFY(QTest::qWaitForWindowExposed(&parent)); + QVERIFY(QTest::qWaitForWindowExposed(&child)); + + child.setParent(nullptr); + QCoreApplication::processEvents(); + QVERIFY(QTest::qWaitForWindowExposed(&child)); + + child.setParent(&parent); + QCoreApplication::processEvents(); + QVERIFY(QTest::qWaitForWindowExposed(&child)); +} + +struct ParentWindow : public QWindow +{ + bool event(QEvent *event) override + { + [&]() -> void { + if (event->type() == QEvent::ChildWindowAdded + || event->type() == QEvent::ChildWindowRemoved) { + // We should not receive child events after the window has been destructed + QVERIFY(this->isWindowType()); + + auto *parentWindow = this; + auto *childEvent = static_cast<QChildWindowEvent*>(event); + auto *childWindow = childEvent->child(); + + if (event->type() == QEvent::ChildWindowAdded) { + QVERIFY(childWindow->parent()); + QVERIFY(parentWindow->isAncestorOf(childWindow)); + if (childWindow->handle()) + QVERIFY(childWindow->handle()->parent() == parentWindow->handle()); + + } else { + QVERIFY(!childWindow->parent()); + QVERIFY(!parentWindow->isAncestorOf(childWindow)); + if (childWindow->handle()) + QVERIFY(childWindow->handle()->parent() != parentWindow->handle()); + } + } + }(); + + return QWindow::event(event); + } +}; + +void tst_QWindow::childEvents() +{ + ParentWindow parent; + + { + // ChildAdded via constructor + QWindow constructorChild(&parent); + if (QTest::currentTestFailed()) return; + // ChildRemoved via destructor + } + + if (QTest::currentTestFailed()) return; + + // ChildAdded and ChildRemoved via setParent + QWindow child; + child.setParent(&parent); + if (QTest::currentTestFailed()) return; + child.setParent(nullptr); + if (QTest::currentTestFailed()) return; + + parent.create(); + child.create(); + + // ChildAdded and ChildRemoved after creation + child.setParent(&parent); + if (QTest::currentTestFailed()) return; + child.setParent(nullptr); + if (QTest::currentTestFailed()) return; +} + +struct ChildWindowPrivate; +struct ChildWindow : public QWindow +{ + ChildWindow(QWindow *parent = nullptr); +}; + +struct ChildWindowPrivate : public QWindowPrivate +{ + ChildWindowPrivate() : QWindowPrivate() + { + receiveParentEvents = true; + } +}; + +ChildWindow::ChildWindow(QWindow *parent) + : QWindow(*new ChildWindowPrivate, parent) +{} + +struct ParentEventTester : public QObject +{ + bool eventFilter(QObject *object, QEvent *event) override + { + [&]() -> void { + if (event->type() == QEvent::ParentWindowAboutToChange + || event->type() == QEvent::ParentWindowChange) { + // We should not receive parent events after the window has been destructed + QVERIFY(object->isWindowType()); + auto *window = static_cast<QWindow*>(object); + + if (event->type() == QEvent::ParentWindowAboutToChange) { + QVERIFY(window->parent() != nextExpectedParent); + if (window->handle()) { + QVERIFY(window->handle()->parent() != + (nextExpectedParent ? nextExpectedParent->handle() : nullptr)); + } + } else { + QVERIFY(window->parent() == nextExpectedParent); + if (window->handle()) { + QVERIFY(window->handle()->parent() == + (nextExpectedParent ? nextExpectedParent->handle() : nullptr)); + } + } + } + }(); + + return QObject::eventFilter(object, event); + } + + QWindow *nextExpectedParent = nullptr; +}; + + + +void tst_QWindow::parentEvents() +{ + QWindow parent; + + { + ParentEventTester tester; + + { + // We can't hook in early enough to get the parent change during + // QObject construction. + ChildWindow child(&parent); + + // But we can observe the one during destruction + child.installEventFilter(&tester); + tester.nextExpectedParent = nullptr; + } + } + if (QTest::currentTestFailed()) return; + + ParentEventTester tester; + ChildWindow child; + child.installEventFilter(&tester); + + tester.nextExpectedParent = &parent; + child.setParent(&parent); + if (QTest::currentTestFailed()) return; + + tester.nextExpectedParent = nullptr; + child.setParent(nullptr); + if (QTest::currentTestFailed()) return; + + parent.create(); + child.create(); + + tester.nextExpectedParent = &parent; + child.setParent(&parent); + if (QTest::currentTestFailed()) return; + + tester.nextExpectedParent = nullptr; + child.setParent(nullptr); + if (QTest::currentTestFailed()) return; +} + #include <tst_qwindow.moc> QTEST_MAIN(tst_QWindow) |