diff options
Diffstat (limited to 'tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp')
-rw-r--r-- | tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp | 174 |
1 files changed, 164 insertions, 10 deletions
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index 57bd4515ad..2eb2d84504 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -1,5 +1,5 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #define QT_STATICPLUGIN #include <QtWidgets/qstyleplugin.h> @@ -23,6 +23,7 @@ #include <QtGui/QFontDatabase> #include <QtGui/QClipboard> +#include <QtGui/QStyleHints> #include <QtWidgets/QApplication> #include <QtWidgets/QMessageBox> @@ -94,7 +95,9 @@ private slots: void libraryPaths_qt_plugin_path_2(); #endif +#ifdef QT_BUILD_INTERNAL void sendPostedEvents(); +#endif // ifdef QT_BUILD_INTERNAL void thread(); void desktopSettingsAware(); @@ -117,6 +120,7 @@ private slots: void style(); void applicationPalettePolish(); + void setColorScheme(); void allWidgets(); void topLevelWidgets(); @@ -164,6 +168,21 @@ void tst_QApplication::sendEventsOnProcessEvents() QCoreApplication::postEvent(&app, new QEvent(QEvent::Type(QEvent::User + 1))); QCoreApplication::processEvents(); + +#ifdef Q_OS_LINUX + if ((QSysInfo::productType() == "rhel" && QSysInfo::productVersion().startsWith(u'9')) + || (QSysInfo::productType() == "ubuntu" && QSysInfo::productVersion().startsWith(u'2'))) + { + QFile f("/proc/self/maps"); + QVERIFY(f.open(QIODevice::ReadOnly)); + + QByteArray libs = f.readAll(); + if (libs.contains("libqgtk3.") || libs.contains("libqgtk3TestInfix.")) { + QEXPECT_FAIL("", "Fails if qgtk3 (Glib) is loaded, see QTBUG-87137", Abort); + } + } +#endif + QVERIFY(spy.recordedEvents.contains(QEvent::User + 1)); } @@ -294,10 +313,8 @@ void tst_QApplication::alert() QApplication::alert(&widget, -1); QApplication::alert(&widget, 250); widget2.activateWindow(); - QApplicationPrivate::setActiveWindow(&widget2); QApplication::alert(&widget, 0); widget.activateWindow(); - QApplicationPrivate::setActiveWindow(&widget); QApplication::alert(&widget, 200); } @@ -886,6 +903,7 @@ void tst_QApplication::closeAllWindows() { int argc = 0; QApplication app(argc, nullptr); + app.setAttribute(Qt::AA_DontUseNativeDialogs, true); // create some windows new QWidget; @@ -1125,6 +1143,7 @@ void tst_QApplication::libraryPaths_qt_plugin_path_2() } #endif +#ifdef QT_BUILD_INTERNAL class SendPostedEventsTester : public QObject { Q_OBJECT @@ -1146,7 +1165,7 @@ void SendPostedEventsTester::doTest() QPointer<SendPostedEventsTester> p = this; QApplication::postEvent(this, new QEvent(QEvent::User)); // DeferredDelete should not be delivered until returning from this function - QApplication::postEvent(this, new QDeferredDeleteEvent()); + deleteLater(); QEventLoop eventLoop; QMetaObject::invokeMethod(&eventLoop, "quit", Qt::QueuedConnection); @@ -1170,6 +1189,7 @@ void tst_QApplication::sendPostedEvents() (void) QCoreApplication::exec(); QVERIFY(p.isNull()); } +#endif void tst_QApplication::thread() { @@ -1314,9 +1334,6 @@ void DeleteLaterWidget::checkDeleteLater() void tst_QApplication::testDeleteLater() { -#ifdef Q_OS_MAC - QSKIP("This test fails and then hangs on OS X, see QTBUG-24318"); -#endif int argc = 0; QApplication app(argc, nullptr); connect(&app, &QGuiApplication::lastWindowClosed, &app, &QCoreApplication::quit); @@ -1607,7 +1624,6 @@ void tst_QApplication::focusWidget() QTextEdit te; te.show(); - QApplicationPrivate::setActiveWindow(&te); QVERIFY(QTest::qWaitForWindowActive(&te)); const auto focusWidget = QApplication::focusWidget(); @@ -1623,7 +1639,6 @@ void tst_QApplication::focusWidget() QTextEdit te(&w); w.show(); - QApplicationPrivate::setActiveWindow(&w); QVERIFY(QTest::qWaitForWindowActive(&w)); const auto focusWidget = QApplication::focusWidget(); @@ -2038,6 +2053,122 @@ void tst_QApplication::applicationPalettePolish() } } +void tst_QApplication::setColorScheme() +{ + int argc = 1; + QApplication app(argc, &argv0); + + if (QStringList{"minimal", "offscreen", "wayland", "xcb", "wasm", "webassembly"} + .contains(QGuiApplication::platformName(), Qt::CaseInsensitive)) { + QSKIP("Setting the colorScheme is not implemented on this platform."); + } + qDebug() << "Testing setColorScheme on platform" << QGuiApplication::platformName(); + + if (QByteArrayView(app.style()->metaObject()->className()) == "QWindowsVistaStyle") + QSKIP("Setting the colorScheme is not supported with the Windows Vista style."); + + const Qt::ColorScheme defaultColorScheme = QApplication::styleHints()->colorScheme(); + // if we implement setColorScheme, then we must be able to read it + QVERIFY(defaultColorScheme != Qt::ColorScheme::Unknown); + const Qt::ColorScheme newColorScheme = defaultColorScheme == Qt::ColorScheme::Light + ? Qt::ColorScheme::Dark : Qt::ColorScheme::Light; + + class TopLevelWidget : public QWidget + { + QList<QEvent::Type> events; + public: + TopLevelWidget() + { + setObjectName("colorScheme TopLevelWidget"); + } + + void clearEvents() + { + events.clear(); + } + qsizetype eventCount(QEvent::Type type) const + { + return events.count(type); + } + protected: + bool event(QEvent *event) override + { + switch (event->type()) { + case QEvent::ApplicationPaletteChange: + case QEvent::PaletteChange: + case QEvent::ThemeChange: + events << event->type(); + break; + default: + break; + } + + return QWidget::event(event); + } + } topLevelWidget; + topLevelWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&topLevelWidget)); + + QSignalSpy colorSchemeChangedSpy(app.styleHints(), &QStyleHints::colorSchemeChanged); + + // always start with a clean list + topLevelWidget.clearEvents(); + const QPalette defaultPalette = topLevelWidget.palette(); + + bool oldPaletteWhenSchemeChanged = false; + connect(app.styleHints(), &QStyleHints::colorSchemeChanged, this, + [defaultPalette, &topLevelWidget, &oldPaletteWhenSchemeChanged]{ + oldPaletteWhenSchemeChanged = defaultPalette == topLevelWidget.palette(); + }); + + app.styleHints()->setColorScheme(newColorScheme); + QTRY_COMPARE(colorSchemeChangedSpy.count(), 1); + // We have not yet updated the palette when we emit the colorSchemeChanged + // signal, so the toplevel widget should still use the previous palette + QVERIFY(oldPaletteWhenSchemeChanged); + QCOMPARE(topLevelWidget.eventCount(QEvent::ThemeChange), 1); + // We can't guarantee that there is only one ApplicationPaletteChange, + // and they might arrive asynchronously in response to ThemeChange + QTRY_COMPARE_GE(topLevelWidget.eventCount(QEvent::ApplicationPaletteChange), 1); + // But we can guarantee a single PaletteChange event for the widget + QCOMPARE(topLevelWidget.eventCount(QEvent::PaletteChange), 1); + // The palette should have changed + QCOMPARE_NE(topLevelWidget.palette(), defaultPalette); + + topLevelWidget.clearEvents(); + colorSchemeChangedSpy.clear(); + + // verify that a widget shown with a color scheme override in place respect that + QWidget newWidget; + newWidget.show(); + QVERIFY(QTest::qWaitForWindowExposed(&newWidget)); + QCOMPARE(newWidget.palette(), topLevelWidget.palette()); + + // Setting to Unknown should follow the system preference again + app.styleHints()->setColorScheme(Qt::ColorScheme::Unknown); + QTRY_COMPARE(colorSchemeChangedSpy.count(), 1); + QCOMPARE(app.styleHints()->colorScheme(), defaultColorScheme); + QTRY_COMPARE(topLevelWidget.eventCount(QEvent::PaletteChange), 1); + + auto debugPalette = qScopeGuard([defaultPalette, &topLevelWidget]{ + qDebug() << "Inspecting palettes for differences"; + const QPalette palette = topLevelWidget.palette(); + for (int g = 0; g < QPalette::NColorGroups; ++g) { + for (int r = 0; r < QPalette::NColorRoles; ++r) { + const auto group = static_cast<QPalette::ColorGroup>(g); + const auto role = static_cast<QPalette::ColorRole>(r); + qDebug() << "...Checking" << group << role; + const auto actualBrush = palette.brush(group, role); + const auto expectedBrush = defaultPalette.brush(group, role); + if (palette.brush(group, role) != defaultPalette.brush(group, role)) + qWarning() << "...Difference in" << group << role << actualBrush << expectedBrush; + } + } + }); + QCOMPARE(topLevelWidget.palette(), defaultPalette); + debugPalette.dismiss(); +} + void tst_QApplication::allWidgets() { int argc = 1; @@ -2557,8 +2688,26 @@ public: explicit ShowCloseShowWidget(bool showAgain, QWidget *parent = nullptr) : QWidget(parent), showAgain(showAgain) { + int timeout = 500; +#ifdef Q_OS_ANDROID + // On Android, CI Android emulator is not running HW accelerated graphics and can be slow, + // use a longer timeout to avoid flaky failures + timeout = 1000; +#endif + QTimer::singleShot(timeout, this, [] () { QCoreApplication::exit(1); }); + } + + bool shown = false; + +protected: + void showEvent(QShowEvent *) override + { QTimer::singleShot(0, this, &ShowCloseShowWidget::doClose); - QTimer::singleShot(500, this, [] () { QCoreApplication::exit(1); }); + shown = true; + } + void hideEvent(QHideEvent *) override + { + shown = false; } private slots: @@ -2574,16 +2723,21 @@ private: void tst_QApplication::abortQuitOnShow() { + if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive)) + QSKIP("Wayland: This crash, see QTBUG-123172."); + int argc = 0; QApplication app(argc, nullptr); ShowCloseShowWidget window1(false); window1.setWindowTitle(QLatin1String(QTest::currentTestFunction())); window1.show(); + QVERIFY(QTest::qWaitFor([&window1](){ return window1.shown; })); QCOMPARE(QCoreApplication::exec(), 0); ShowCloseShowWidget window2(true); window2.setWindowTitle(QLatin1String(QTest::currentTestFunction())); window2.show(); + QVERIFY(QTest::qWaitFor([&window2](){ return window2.shown; })); QCOMPARE(QCoreApplication::exec(), 1); } |