summaryrefslogtreecommitdiffstats
path: root/tests/auto/widgets
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/widgets')
-rw-r--r--tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp19
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp5
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp1
-rw-r--r--tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp91
-rw-r--r--tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp118
-rw-r--r--tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp111
-rw-r--r--tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp3
-rw-r--r--tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp217
-rw-r--r--tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp51
-rw-r--r--tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp68
-rw-r--r--tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp2
11 files changed, 669 insertions, 17 deletions
diff --git a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
index 94afff6e40..26a6245164 100644
--- a/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
+++ b/tests/auto/widgets/dialogs/qmessagebox/tst_qmessagebox.cpp
@@ -63,6 +63,7 @@ private slots:
void hideNativeByDestruction();
void explicitDoneAfterButtonClicked();
+ void legacyApiReturnValue();
void cleanup();
};
@@ -511,7 +512,7 @@ QT_WARNING_DISABLE_DEPRECATED
// the button text versions
closeHelper.start(Qt::Key_Enter);
ret = QMessageBox::information(nullptr, "title", "text", "Yes", "No", QString(), 1);
- COMPARE(ret, 3); // Custom button opaque result
+ COMPARE(ret, 1);
QVERIFY(closeHelper.done());
#endif // QT_DEPRECATED_SINCE(6, 2)
#undef COMPARE
@@ -863,5 +864,21 @@ void tst_QMessageBox::explicitDoneAfterButtonClicked()
QCOMPARE(rejectedSpy.size(), 3);
}
+void tst_QMessageBox::legacyApiReturnValue()
+{
+ ExecCloseHelper closeHelper;
+ for (int i = 0; i < 3; ++i) {
+ closeHelper.start(Qt::Key_Enter);
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+ QCOMPARE(QMessageBox::warning(nullptr, "Title", "Text",
+ "Button 0", "Button 1", "Button 2", i), i);
+ closeHelper.start(Qt::Key_Escape);
+ QCOMPARE(QMessageBox::warning(nullptr, "Title", "Text",
+ "Button 0", "Button 1", "Button 2", 0, i), i);
+QT_WARNING_POP
+ }
+}
+
QTEST_MAIN(tst_QMessageBox)
#include "tst_qmessagebox.moc"
diff --git a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
index c91a0803ee..fad75ec045 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsgridlayout/tst_qgraphicsgridlayout.cpp
@@ -2976,11 +2976,6 @@ static QSizeF wfh(Qt::SizeHint /*which*/, const QSizeF &constraint)
return result;
}
-bool qFuzzyCompare(const QSizeF &a, const QSizeF &b)
-{
- return qFuzzyCompare(a.width(), b.width()) && qFuzzyCompare(a.height(), b.height());
-}
-
void tst_QGraphicsGridLayout::heightForWidth()
{
QGraphicsWidget *widget = new QGraphicsWidget;
diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
index ee1a8c530a..c3f77957f8 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp
@@ -3872,6 +3872,7 @@ void tst_QGraphicsProxyWidget::touchEventPropagation()
break;
}
case QEvent::MouseButtonPress:
+ case QEvent::MouseButtonDblClick:
mousePressReceiver = qobject_cast<QWidget*>(receiver);
break;
default:
diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
index 7ed1f28b0a..ed99cd93a8 100644
--- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
+++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp
@@ -26,6 +26,7 @@
#include <QtWidgets/QStyle>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QScroller>
+#include <QtWidgets/QStackedWidget>
#if QT_CONFIG(opengl)
#include <QtOpenGLWidgets/QOpenGLWidget>
#endif
@@ -114,6 +115,7 @@ protected:
#if defined QT_BUILD_INTERNAL
class FriendlyGraphicsScene : public QGraphicsScene
{
+ using QGraphicsScene::QGraphicsScene;
friend class tst_QGraphicsView;
Q_DECLARE_PRIVATE(QGraphicsScene);
};
@@ -254,6 +256,9 @@ private slots:
#ifndef QT_NO_CURSOR
void QTBUG_7438_cursor();
#endif
+#ifdef QT_BUILD_INTERNAL
+ void QTBUG_53974_mismatched_hide_show_events();
+#endif
void resizeContentsOnItemDrag_data();
void resizeContentsOnItemDrag();
@@ -4975,6 +4980,92 @@ void tst_QGraphicsView::QTBUG_70255_scrollTo()
QCOMPARE(point, QPoint(0, -500));
}
+#ifdef QT_BUILD_INTERNAL
+void tst_QGraphicsView::QTBUG_53974_mismatched_hide_show_events()
+{
+ QGraphicsView *view = new QGraphicsView;
+ FriendlyGraphicsScene *scene = new FriendlyGraphicsScene(view);
+ view->setScene(scene);
+
+ QStackedWidget *lowLevel = new QStackedWidget;
+ lowLevel->addWidget(new QLabel);
+ lowLevel->addWidget(view);
+
+ QStackedWidget topLevel;
+ topLevel.addWidget(new QLabel);
+ topLevel.addWidget(lowLevel);
+
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ topLevel.show();
+ topLevel.activateWindow();
+ QVERIFY(QTest::qWaitForWindowActive(&topLevel));
+
+ // Starting point
+ QCOMPARE_EQ(topLevel.currentIndex(), 0);
+ QCOMPARE_EQ(lowLevel->currentIndex(), 0);
+
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ // lowLevel is not visible. Changing the current index there
+ // should not affect the refcount.
+ lowLevel->setCurrentIndex(1);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ lowLevel->setCurrentIndex(0);
+ QEXPECT_FAIL("", "The view was already hidden, so the refcount should still be 0", Continue);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+ scene->d_func()->activationRefCount = 0;
+
+ // Make lowLevel visible.
+ topLevel.setCurrentIndex(1);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ // Show and hide the QGV a couple of times.
+ lowLevel->setCurrentIndex(1);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 1);
+
+ lowLevel->setCurrentIndex(0);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ lowLevel->setCurrentIndex(1);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 1);
+
+ lowLevel->setCurrentIndex(0);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ // Make lowLevel hidden again.
+ topLevel.setCurrentIndex(0);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ // Change the current index in the hidden lowLevel
+ lowLevel->setCurrentIndex(1);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ lowLevel->setCurrentIndex(0);
+ QEXPECT_FAIL("", "The view was already hidden, so the refcount should still be 0", Continue);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+ scene->d_func()->activationRefCount = 0;
+
+ // Make lowLevel and the QGV visible.
+ lowLevel->setCurrentIndex(1);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ topLevel.setCurrentIndex(1);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 1);
+
+ // Make lowLevel hidden (keeping the QGV as current index).
+ topLevel.setCurrentIndex(0);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+
+ // Hide the QGV:
+ lowLevel->setCurrentIndex(0);
+ QEXPECT_FAIL("", "The view was already hidden, so the refcount should still be 0", Continue);
+ QCOMPARE_EQ(scene->d_func()->activationRefCount, 0);
+ scene->d_func()->activationRefCount = 0;
+}
+#endif
+
void tst_QGraphicsView::resizeContentsOnItemDrag_data()
{
QTest::addColumn<Qt::Alignment>("alignment");
diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
index dfc138d8fc..2eb2d84504 100644
--- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
+++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp
@@ -23,6 +23,7 @@
#include <QtGui/QFontDatabase>
#include <QtGui/QClipboard>
+#include <QtGui/QStyleHints>
#include <QtWidgets/QApplication>
#include <QtWidgets/QMessageBox>
@@ -119,6 +120,7 @@ private slots:
void style();
void applicationPalettePolish();
+ void setColorScheme();
void allWidgets();
void topLevelWidgets();
@@ -2051,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;
diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
index 3447c9af28..cac968c5dd 100644
--- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
+++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp
@@ -432,6 +432,7 @@ private slots:
void touchUpdateOnNewTouch();
void touchCancel();
void touchEventsForGesturePendingWidgets();
+ void synthMouseDoubleClick();
void styleSheetPropagation();
@@ -477,6 +478,10 @@ private slots:
void reparentWindowHandles_data();
void reparentWindowHandles();
+#ifndef QT_NO_CONTEXTMENU
+ void contextMenuTrigger();
+#endif
+
private:
const QString m_platform;
QSize m_testWidgetSize;
@@ -1898,6 +1903,7 @@ void tst_QWidget::focusChainOnReparent()
}
QWidget window2;
+ child22->setParent(child21);
child2->setParent(&window2);
QWidget *expectedNewChain[5] = {&window2, child2, child21, child22, &window2};
@@ -11149,6 +11155,10 @@ void tst_QWidget::hoverPosition()
QVERIFY(QTest::qWaitForWindowExposed(&root));
const QPoint middle(50, 50);
+ // wait until we got the correct global pos
+ QPoint expectedGlobalPos = root.geometry().topLeft() + QPoint(100, 100) + middle;
+ if (!QTest::qWaitFor([&]{ return expectedGlobalPos == h.mapToGlobal(middle); }))
+ QSKIP("Can't move cursor");
QPoint curpos = h.mapToGlobal(middle);
QCursor::setPos(curpos);
if (!QTest::qWaitFor([curpos]{ return QCursor::pos() == curpos; }))
@@ -12248,7 +12258,24 @@ protected:
case QEvent::MouseMove:
case QEvent::MouseButtonRelease:
++m_mouseEventCount;
- m_lastMouseEventPos = static_cast<QMouseEvent *>(e)->position();
+ {
+ QMouseEvent *me = static_cast<QMouseEvent *>(e);
+ m_lastMouseEventPos = me->position();
+ m_lastMouseTimestamp = me->timestamp();
+ }
+ if (m_acceptMouse)
+ e->accept();
+ else
+ e->ignore();
+ return true;
+
+ case QEvent::MouseButtonDblClick:
+ ++m_mouseEventCount;
+ {
+ QMouseEvent *me = static_cast<QMouseEvent *>(e);
+ m_lastMouseEventPos = me->position();
+ m_doubleClickTimestamp = me->timestamp();
+ }
if (m_acceptMouse)
e->accept();
else
@@ -12274,6 +12301,8 @@ public:
int m_mouseEventCount = 0;
bool m_acceptMouse = true;
QPointF m_lastMouseEventPos;
+ quint64 m_lastMouseTimestamp = 0;
+ quint64 m_doubleClickTimestamp = 0;
};
void tst_QWidget::touchEventSynthesizedMouseEvent()
@@ -12515,6 +12544,50 @@ void tst_QWidget::touchEventsForGesturePendingWidgets()
QVERIFY(parent.m_gestureEventCount > 0);
}
+void tst_QWidget::synthMouseDoubleClick()
+{
+ TouchMouseWidget widget;
+ widget.setWindowTitle(QLatin1String(QTest::currentTestFunction()));
+ widget.show();
+ QWindow* window = widget.windowHandle();
+ QVERIFY(QTest::qWaitForWindowExposed(window));
+
+ // tap once; move slightly from press to release
+ QPoint p(20, 20);
+ int expectedMouseEventCount = 0;
+ QTest::touchEvent(window, m_touchScreen).press(1, p, window);
+ QCOMPARE(widget.m_touchBeginCount, 0);
+ QCOMPARE(widget.m_mouseEventCount, ++expectedMouseEventCount);
+ QCOMPARE(widget.m_lastMouseEventPos.toPoint(), p);
+ quint64 mouseTimestamp = widget.m_lastMouseTimestamp;
+ p += {1, 0};
+ QTest::touchEvent(window, m_touchScreen).move(1, p, window);
+ QCOMPARE(widget.m_mouseEventCount, ++expectedMouseEventCount);
+ QCOMPARE(widget.m_lastMouseEventPos.toPoint(), p);
+ QCOMPARE_GT(widget.m_lastMouseTimestamp, mouseTimestamp);
+ mouseTimestamp = widget.m_lastMouseTimestamp;
+ QTest::touchEvent(window, m_touchScreen).release(1, p, window);
+ QCOMPARE(widget.m_mouseEventCount, ++expectedMouseEventCount);
+ QCOMPARE(widget.m_lastMouseEventPos.toPoint(), p);
+ QCOMPARE_GT(widget.m_lastMouseTimestamp, mouseTimestamp);
+ mouseTimestamp = widget.m_lastMouseTimestamp;
+
+ // tap again nearby: a double-click event should be synthesized
+ p += {0, 1};
+ QTest::touchEvent(window, m_touchScreen).press(2, p, window);
+ QCOMPARE(widget.m_touchBeginCount, 0);
+ QCOMPARE(widget.m_mouseEventCount, ++expectedMouseEventCount);
+ QCOMPARE(widget.m_lastMouseEventPos.toPoint(), p);
+ QCOMPARE_GT(widget.m_doubleClickTimestamp, mouseTimestamp);
+ mouseTimestamp = widget.m_doubleClickTimestamp;
+
+ QTest::touchEvent(window, m_touchScreen).release(2, p, window);
+ QCOMPARE(widget.m_mouseEventCount, ++expectedMouseEventCount);
+ QCOMPARE(widget.m_lastMouseEventPos.toPoint(), p);
+ QCOMPARE_GT(widget.m_lastMouseTimestamp, mouseTimestamp);
+ mouseTimestamp = widget.m_lastMouseTimestamp;
+}
+
void tst_QWidget::styleSheetPropagation()
{
QTableView tw;
@@ -14040,5 +14113,41 @@ void tst_QWidget::reparentWindowHandles()
}
}
+#ifndef QT_NO_CONTEXTMENU
+void tst_QWidget::contextMenuTrigger()
+{
+ class ContextMenuWidget : public QWidget
+ {
+ public:
+ int events = 0;
+
+ protected:
+ void contextMenuEvent(QContextMenuEvent *) override { ++events; }
+ };
+
+ const Qt::ContextMenuTrigger wasTrigger = QGuiApplication::styleHints()->contextMenuTrigger();
+ auto restoreTriggerGuard = qScopeGuard([wasTrigger]{
+ QGuiApplication::styleHints()->setContextMenuTrigger(wasTrigger);
+ });
+
+ ContextMenuWidget widget;
+ widget.show();
+ QVERIFY(!qApp->topLevelWindows().empty());
+ auto *window = qApp->topLevelWindows()[0];
+ QVERIFY(window);
+ QCOMPARE(widget.events, 0);
+ QGuiApplication::styleHints()->setContextMenuTrigger(Qt::ContextMenuTrigger::Press);
+ QTest::mousePress(window, Qt::RightButton);
+ QCOMPARE(widget.events, 1);
+ QTest::mouseRelease(window, Qt::RightButton);
+ QCOMPARE(widget.events, 1);
+ QGuiApplication::styleHints()->setContextMenuTrigger(Qt::ContextMenuTrigger::Release);
+ QTest::mousePress(window, Qt::RightButton);
+ QCOMPARE(widget.events, 1);
+ QTest::mouseRelease(window, Qt::RightButton);
+ QCOMPARE(widget.events, 2);
+}
+#endif
+
QTEST_MAIN(tst_QWidget)
#include "tst_qwidget.moc"
diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
index e771737ae0..1fab69fdcc 100644
--- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
+++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp
@@ -1634,8 +1634,7 @@ void tst_QWidget_window::mouseMoveWithPopup()
// but the release event will still be delivered to the first popup - dialogs might not get it
QCOMPARE(mouseAction(Qt::LeftButton), QEvent::MouseButtonRelease);
- if (topLevel.popup->mouseReleaseCount != 1
- && !QGuiApplication::platformName().startsWith(QLatin1String("windows"), Qt::CaseInsensitive))
+ if (topLevel.popup->mouseReleaseCount != 1)
QEXPECT_FAIL("Dialog", "Platform specific behavior", Continue);
QCOMPARE(topLevel.popup->mouseReleaseCount, 1);
}
diff --git a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp
index 9059a9262e..64ebeb08b0 100644
--- a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp
+++ b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp
@@ -260,6 +260,7 @@ private slots:
void staticContents();
void scroll();
void paintOnScreenUpdates();
+ void evaluateRhi();
#if defined(QT_BUILD_INTERNAL)
void scrollWithOverlap();
@@ -581,6 +582,222 @@ void tst_QWidgetRepaintManager::paintOnScreenUpdates()
}
}
+class RhiWidgetPrivate : public QWidgetPrivate
+{
+public:
+ RhiWidgetPrivate(const QPlatformBackingStoreRhiConfig &config)
+ : config(config)
+ {
+ }
+
+ QPlatformBackingStoreRhiConfig rhiConfig() const override
+ {
+ return config;
+ }
+
+ QPlatformBackingStoreRhiConfig config = QPlatformBackingStoreRhiConfig::Null;
+};
+
+class RhiWidget : public QWidget
+{
+public:
+ RhiWidget(const QPlatformBackingStoreRhiConfig &config = QPlatformBackingStoreRhiConfig::Null, QWidget *parent = nullptr)
+ : QWidget(*new RhiWidgetPrivate(config), parent, {})
+ {
+ }
+};
+
+void tst_QWidgetRepaintManager::evaluateRhi()
+{
+ const auto *integration = QGuiApplicationPrivate::platformIntegration();
+ if (!integration->hasCapability(QPlatformIntegration::RhiBasedRendering))
+ QSKIP("Platform does not support RHI based rendering");
+
+ // We need full control over whether widgets are native or not
+ const bool nativeSiblingsOriginal = qApp->testAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, true);
+ auto nativeSiblingGuard = qScopeGuard([&]{
+ qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings, nativeSiblingsOriginal);
+ });
+
+ auto defaultSurfaceType = QSurface::RasterSurface;
+ bool usesRhiBackingStore = false;
+
+ {
+ // Plain QWidget doesn't enable RHI
+ QWidget regularWidget;
+ regularWidget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&regularWidget));
+ QVERIFY(!QWidgetPrivate::get(&regularWidget)->usesRhiFlush);
+
+ // The platform might use a non-raster surface type if it uses
+ // an RHI backingstore by default (e.g. Android, iOS, QNX).
+ defaultSurfaceType = regularWidget.windowHandle()->surfaceType();
+
+ // Record whether the platform uses an RHI backingstore,
+ // so we can opt out of some tests further down.
+ if (defaultSurfaceType != QSurface::RasterSurface)
+ usesRhiBackingStore = QWidgetPrivate::get(&regularWidget)->rhi();
+ else
+ QVERIFY(!QWidgetPrivate::get(&regularWidget)->rhi());
+ }
+
+ {
+ // But a top level RHI widget does
+ RhiWidget rhiWidget;
+ rhiWidget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&rhiWidget));
+ QVERIFY(QWidgetPrivate::get(&rhiWidget)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi());
+ }
+
+#if QT_CONFIG(opengl)
+ {
+ // Non-native child RHI widget enables RHI for top level regular widget
+ QWidget topLevel;
+ RhiWidget rhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel);
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+ QCOMPARE(topLevel.windowHandle()->surfaceType(), QSurface::OpenGLSurface);
+ QVERIFY(QWidgetPrivate::get(&topLevel)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&topLevel)->rhi());
+ // Only the native widget that actually flushes will report usesRhiFlush
+ QVERIFY(!QWidgetPrivate::get(&rhiWidget)->usesRhiFlush);
+ // But it should have an RHI it can use
+ QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi());
+ }
+
+ {
+ // Native child RHI widget does not enable RHI for top level
+ QWidget topLevel;
+ RhiWidget nativeRhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel);
+ nativeRhiWidget.setAttribute(Qt::WA_NativeWindow);
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+ QCOMPARE(nativeRhiWidget.windowHandle()->surfaceType(), QSurface::OpenGLSurface);
+ QVERIFY(QWidgetPrivate::get(&nativeRhiWidget)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&nativeRhiWidget)->rhi());
+ QCOMPARE(topLevel.windowHandle()->surfaceType(), defaultSurfaceType);
+ QVERIFY(!QWidgetPrivate::get(&topLevel)->usesRhiFlush);
+
+ if (!usesRhiBackingStore)
+ QVERIFY(!QWidgetPrivate::get(&topLevel)->rhi());
+ }
+
+ {
+ // Non-native RHI child of native child enables RHI for native child,
+ // but not top level.
+ QWidget topLevel;
+ QWidget nativeChild(&topLevel);
+ nativeChild.setAttribute(Qt::WA_NativeWindow);
+ RhiWidget rhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &nativeChild);
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+
+ QCOMPARE(nativeChild.windowHandle()->surfaceType(), QSurface::OpenGLSurface);
+ QVERIFY(QWidgetPrivate::get(&nativeChild)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&nativeChild)->rhi());
+ QVERIFY(!QWidgetPrivate::get(&rhiWidget)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi());
+ QCOMPARE(topLevel.windowHandle()->surfaceType(), defaultSurfaceType);
+ QVERIFY(!QWidgetPrivate::get(&topLevel)->usesRhiFlush);
+ if (!usesRhiBackingStore)
+ QVERIFY(!QWidgetPrivate::get(&topLevel)->rhi());
+ }
+
+ {
+ // Native child RHI widget does not prevent RHI for top level
+ // if non-native RHI child widget is also present.
+ QWidget topLevel;
+ RhiWidget rhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel);
+ RhiWidget nativeRhiWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel);
+ nativeRhiWidget.setAttribute(Qt::WA_NativeWindow);
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+
+ QCOMPARE(nativeRhiWidget.windowHandle()->surfaceType(), QSurface::OpenGLSurface);
+ QVERIFY(QWidgetPrivate::get(&nativeRhiWidget)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&nativeRhiWidget)->rhi());
+ QVERIFY(!QWidgetPrivate::get(&rhiWidget)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi());
+ QCOMPARE(topLevel.windowHandle()->surfaceType(), QSurface::OpenGLSurface);
+ QVERIFY(QWidgetPrivate::get(&topLevel)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&topLevel)->rhi());
+ }
+
+ {
+ // Reparenting into a window that already matches the required
+ // surface type should still mark the parent as flushing with RHI.
+ QWidget topLevel;
+
+ RhiWidget rhiWidget(QPlatformBackingStoreRhiConfig::Null);
+ rhiWidget.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&rhiWidget));
+ QVERIFY(QWidgetPrivate::get(&rhiWidget)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&rhiWidget)->rhi());
+
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+ rhiWidget.setParent(&topLevel);
+ QVERIFY(QWidgetPrivate::get(&topLevel)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&topLevel)->rhi());
+ }
+
+ {
+ // Non-native RHI child of native child enables RHI for native child,
+ // but does not prevent top level from flushing with RHI.
+ QWidget topLevel;
+ QWidget nativeChild(&topLevel);
+ nativeChild.setAttribute(Qt::WA_NativeWindow);
+ RhiWidget rhiGranchild(QPlatformBackingStoreRhiConfig::OpenGL, &nativeChild);
+ RhiWidget rhiChild(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel);
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+
+ QCOMPARE(nativeChild.windowHandle()->surfaceType(), QSurface::OpenGLSurface);
+ QVERIFY(QWidgetPrivate::get(&nativeChild)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&nativeChild)->rhi());
+ QVERIFY(!QWidgetPrivate::get(&rhiGranchild)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&rhiGranchild)->rhi());
+ QCOMPARE(topLevel.windowHandle()->surfaceType(), QSurface::OpenGLSurface);
+ QVERIFY(QWidgetPrivate::get(&topLevel)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&topLevel)->rhi());
+ QVERIFY(!QWidgetPrivate::get(&rhiChild)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&rhiChild)->rhi());
+ }
+
+#if QT_CONFIG(metal)
+ QRhiMetalInitParams metalParams;
+ if (QRhi::probe(QRhi::Metal, &metalParams)) {
+ // Native RHI childen allows mixing RHI backends
+ QWidget topLevel;
+ RhiWidget openglWidget(QPlatformBackingStoreRhiConfig::OpenGL, &topLevel);
+ openglWidget.setAttribute(Qt::WA_NativeWindow);
+ RhiWidget metalWidget(QPlatformBackingStoreRhiConfig::Metal, &topLevel);
+ metalWidget.setAttribute(Qt::WA_NativeWindow);
+ topLevel.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&topLevel));
+
+ QCOMPARE(topLevel.windowHandle()->surfaceType(), defaultSurfaceType);
+ QVERIFY(!QWidgetPrivate::get(&topLevel)->usesRhiFlush);
+ if (!usesRhiBackingStore)
+ QVERIFY(!QWidgetPrivate::get(&topLevel)->rhi());
+
+ QCOMPARE(openglWidget.windowHandle()->surfaceType(), QSurface::OpenGLSurface);
+ QVERIFY(QWidgetPrivate::get(&openglWidget)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&openglWidget)->rhi());
+
+ QCOMPARE(metalWidget.windowHandle()->surfaceType(), QSurface::MetalSurface);
+ QVERIFY(QWidgetPrivate::get(&metalWidget)->usesRhiFlush);
+ QVERIFY(QWidgetPrivate::get(&metalWidget)->rhi());
+
+ QVERIFY(QWidgetPrivate::get(&openglWidget)->rhi() != QWidgetPrivate::get(&metalWidget)->rhi());
+ }
+#endif // QT_CONFIG(metal)
+
+#endif // QT_CONFIG(opengl)
+}
+
#if defined(QT_BUILD_INTERNAL)
/*!
diff --git a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
index af62d0d089..88a7057d2e 100644
--- a/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
+++ b/tests/auto/widgets/widgets/qdockwidget/tst_qdockwidget.cpp
@@ -96,6 +96,20 @@ private:
QPointer<QDockWidget> &d1, QPointer<QDockWidget> &d2,
QList<int> &path1, QList<int> &path2) const;
+#if defined(Q_OS_DARWIN) || defined(Q_OS_ANDROID) || defined(Q_OS_QNX)
+#define qCreateFloatingTabs(mainWindow, centralWidget, d1, d2, path1, path2)\
+ mainWindow = nullptr;\
+ Q_UNUSED(path1);\
+ Q_UNUSED(path2);\
+ QSKIP("Platform not supported");
+#else
+#define qCreateFloatingTabs(mainWindow, centralWidget, d1, d2, path1, path2)\
+ createFloatingTabs(mainWindow, centralWidget, d1, d2, path1, path2);\
+ std::unique_ptr<QMainWindow> up_mainWindow(mainWindow);\
+ if (!platformSupportingRaise)\
+ QSKIP("Platform not supporting raise(). Floating tab based tests will fail.")
+#endif
+
static inline QPoint dragPoint(QDockWidget* dockWidget);
static inline QPoint home1(QMainWindow* MainWindow)
{ return MainWindow->mapToGlobal(MainWindow->rect().topLeft() + QPoint(0.1 * MainWindow->width(), 0.1 * MainWindow->height())); }
@@ -447,6 +461,23 @@ void tst_QDockWidget::setFloating()
dw.setFloating(dw.isFloating());
QCOMPARE(spy.size(), 0);
spy.clear();
+
+#if defined(QT_BUILD_INTERNAL) && !defined(Q_OS_WIN)
+ // Check that setFloating() reparents the dock widget to the main window,
+ // in case it has a QDockWidgetGroupWindow parent
+ QPointer<QDockWidget> d1;
+ QPointer<QDockWidget> d2;
+ QPointer<QWidget> cent;
+ QMainWindow* mainWindow;
+ QList<int> path1;
+ QList<int> path2;
+ qCreateFloatingTabs(mainWindow, cent, d1, d2, path1, path2);
+ QVERIFY(qobject_cast<QDockWidgetGroupWindow *>(d1->parentWidget()));
+ QVERIFY(qobject_cast<QDockWidgetGroupWindow *>(d2->parentWidget()));
+ d1->setFloating(true);
+ QTRY_COMPARE(mainWindow, d1->parentWidget());
+ QTRY_COMPARE(mainWindow, d2->parentWidget());
+#endif // defined(QT_BUILD_INTERNAL) && !defined(Q_OS_WIN)
}
void tst_QDockWidget::allowedAreas()
@@ -1399,7 +1430,7 @@ void tst_QDockWidget::createFloatingTabs(QMainWindow* &mainWindow, QPointer<QWid
// Test will fail if platform doesn't support raise.
mainWindow->windowHandle()->handle()->raise();
if (!platformSupportingRaise)
- QSKIP("Platform not supporting raise(). Floating tab based tests will fail.");
+ return;
// remember paths to d1 and d2
QMainWindowLayout* layout = qobject_cast<QMainWindowLayout *>(mainWindow->layout());
@@ -1443,8 +1474,7 @@ void tst_QDockWidget::floatingTabs()
QMainWindow* mainWindow;
QList<int> path1;
QList<int> path2;
- createFloatingTabs(mainWindow, cent, d1, d2, path1, path2);
- std::unique_ptr<QMainWindow> up_mainWindow(mainWindow);
+ qCreateFloatingTabs(mainWindow, cent, d1, d2, path1, path2);
QCOMPARE(mainWindow->tabifiedDockWidgets(d1), {d2});
QCOMPARE(mainWindow->tabifiedDockWidgets(d2), {d1});
@@ -1497,9 +1527,13 @@ void tst_QDockWidget::floatingTabs()
QTest::mouseClick(floatButton, Qt::LeftButton, Qt::KeyboardModifiers(), pos1);
QTest::qWait(waitingTime);
- // d1 must be floating again, while d2 is still in its GroupWindow
+ // d1 and d2 must be floating again
QTRY_VERIFY(d1->isFloating());
- QTRY_VERIFY(!d2->isFloating());
+ QTRY_VERIFY(d2->isFloating());
+
+ // d2 was the active tab, so d1 was not visible
+ QTRY_VERIFY(d1->isVisible());
+ QTRY_VERIFY(d2->isVisible());
// Plug back into dock areas
qCDebug(lcTestDockWidget) << "*** test plugging back to dock areas ***";
@@ -1562,8 +1596,7 @@ void tst_QDockWidget::deleteFloatingTabWithSingleDockWidget()
QMainWindow* mainWindow;
QList<int> path1;
QList<int> path2;
- createFloatingTabs(mainWindow, cent, d1, d2, path1, path2);
- std::unique_ptr<QMainWindow> up_mainWindow(mainWindow);
+ qCreateFloatingTabs(mainWindow, cent, d1, d2, path1, path2);
switch (removalReason) {
case ChildRemovalReason::Destroyed:
@@ -1698,6 +1731,9 @@ void tst_QDockWidget::closeAndDelete()
if (QGuiApplication::platformName().startsWith(QLatin1String("wayland"), Qt::CaseInsensitive))
QSKIP("Test skipped on Wayland.");
#ifdef QT_BUILD_INTERNAL
+ if (QSysInfo::productType() == "rhel")
+ QSKIP("Memory leak on RHEL 9.2 QTBUG-124559", TestFailMode::Abort);
+
// Create a mainwindow with a central widget and two dock widgets
QPointer<QDockWidget> d1;
QPointer<QDockWidget> d2;
@@ -1992,6 +2028,7 @@ void tst_QDockWidget::saveAndRestore()
QCOMPARE(d1->isFloating(), isFloating1);
QCOMPARE(d2->isFloating(), isFloating2);
+#undef qCreateFloatingTabs
#endif // QT_BUILD_INTERNAL
}
diff --git a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
index 7c1fb97b97..06750b099b 100644
--- a/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
+++ b/tests/auto/widgets/widgets/qmenubar/tst_qmenubar.cpp
@@ -124,6 +124,9 @@ private slots:
void platformMenu();
void addActionQt5connect();
void QTBUG_65488_hiddenActionTriggered();
+ void pressDragRelease_data();
+ void pressDragRelease();
+
protected slots:
void onSimpleActivated( QAction*);
void onComplexActionTriggered();
@@ -141,6 +144,7 @@ private:
int m_simpleActivatedCount;
int m_complexTriggerCount[int('k')];
QMenuBar* taskQTBUG53205MenuBar;
+ QScopedPointer<QPointingDevice> m_touchScreen = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
};
// Testing get/set functions
@@ -1420,6 +1424,70 @@ void tst_QMenuBar::QTBUG_65488_hiddenActionTriggered()
QCOMPARE(spy.size(), 0);
}
+void tst_QMenuBar::pressDragRelease_data()
+{
+ QTest::addColumn<QPointingDevice *>("device");
+
+ QTest::newRow("mouse") << const_cast<QPointingDevice *>(QPointingDevice::primaryPointingDevice());
+ QTest::newRow("touchscreen") << m_touchScreen.get();
+}
+
+void tst_QMenuBar::pressDragRelease()
+{
+ QFETCH(QPointingDevice *, device);
+
+ QMainWindow w;
+ const TestMenu menu = initWindowWithComplexMenuBar(w);
+ const QMenu *firstMenu = menu.menus.first();
+ QAction *hoveredAction = nullptr;
+ connect(firstMenu, &QMenu::hovered, firstMenu, [&hoveredAction](QAction *hov) { hoveredAction = hov; });
+ w.show();
+ QVERIFY(QTest::qWaitForWindowActive(&w));
+ QWindow *win = w.windowHandle();
+ const QPoint p1(50, w.menuBar()->geometry().height() / 2);
+ switch (device->type()) {
+ case QInputDevice::DeviceType::Mouse:
+ case QInputDevice::DeviceType::TouchPad:
+ QTest::mousePress(win, Qt::LeftButton, {}, p1);
+ break;
+ case QInputDevice::DeviceType::TouchScreen:
+ QTest::touchEvent(win, device).press(0, p1);
+ break;
+ default:
+ break;
+ }
+
+ QTRY_VERIFY(firstMenu->isVisible());
+ const QPoint firstMenuItemPos = firstMenu->geometry().center() - QPoint(0, 2);
+ const QPoint firstMenuItemPosInWin = w.mapFromGlobal(firstMenuItemPos);
+ switch (device->type()) {
+ case QInputDevice::DeviceType::Mouse:
+ case QInputDevice::DeviceType::TouchPad:
+ QTest::mouseMove(win, firstMenuItemPosInWin);
+ break;
+ case QInputDevice::DeviceType::TouchScreen:
+ QTest::touchEvent(win, device).move(0, firstMenuItemPosInWin);
+ break;
+ default:
+ break;
+ }
+ QVERIFY(hoveredAction);
+ QCOMPARE(hoveredAction, firstMenu->actionAt(firstMenu->mapFromGlobal(firstMenuItemPos)));
+ QSignalSpy triggeredSpy(hoveredAction, &QAction::triggered);
+ switch (device->type()) {
+ case QInputDevice::DeviceType::Mouse:
+ case QInputDevice::DeviceType::TouchPad:
+ QTest::mouseRelease(win, Qt::LeftButton, {}, firstMenuItemPosInWin);
+ break;
+ case QInputDevice::DeviceType::TouchScreen:
+ QTest::touchEvent(win, device).release(0, firstMenuItemPosInWin);
+ break;
+ default:
+ break;
+ }
+ QTRY_COMPARE(triggeredSpy.size(), 1);
+}
+
// QTBUG-56526
void tst_QMenuBar::platformMenu()
{
diff --git a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
index 773ccd894c..51f898c953 100644
--- a/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
+++ b/tests/auto/widgets/widgets/qopenglwidget/tst_qopenglwidget.cpp
@@ -203,7 +203,7 @@ void tst_QOpenGLWidget::deviceLoss()
w->resize(640, 480);
w->show();
- auto rhi = w->backingStore()->handle()->rhi();
+ auto rhi = w->backingStore()->handle()->rhi(w->windowHandle());
QNativeInterface::QEGLContext *rhiContext = nullptr;
if (rhi->backend() == QRhi::OpenGLES2) {
auto rhiHandles = static_cast<const QRhiGles2NativeHandles *>(rhi->nativeHandles());