From f20f1c6b7c65285a78ae7381bd7d2d1a4bdc3d30 Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Mon, 9 Jan 2023 14:33:23 +0100 Subject: [PATCH] Fix tst_QWidgetRepaintManager on XCB Due to an XCB library change, QXcbBackingStore::toImage() cannot be safely assumed to return an image identical to QWidget::grab(). The test functions fastMove(), moveAccross() and moveInOutOverlapped() relied on QXcbBackingStore::toImage() and failed. They were backlisted on Linux/XCB. This patch obtains a screen shot instead of an image from the backing store on XCB platforms. It processes events until the screen shot matches QWidget::grab(). It makes the test fail only if the comparison times out. The patch also removes the BLACKLIST file, containing only the test functions mentioned above. Fixes: QTBUG-109036 Change-Id: I26dd5b89dc62b313db066a285f6ad7d4d92baaf2 Reviewed-by: Volker Hilsheimer (cherry picked from commit 4096667d6601dcbc5e713e6b0fd5b5218453c4cb) Reviewed-by: Qt Cherry-pick Bot --- .../kernel/qwidgetrepaintmanager/BLACKLIST | 11 ------ .../tst_qwidgetrepaintmanager.cpp | 38 ++++++++++++++++++- 2 files changed, 37 insertions(+), 12 deletions(-) delete mode 100644 tests/auto/widgets/kernel/qwidgetrepaintmanager/BLACKLIST diff --git a/tests/auto/widgets/kernel/qwidgetrepaintmanager/BLACKLIST b/tests/auto/widgets/kernel/qwidgetrepaintmanager/BLACKLIST deleted file mode 100644 index 94692ee20a3..00000000000 --- a/tests/auto/widgets/kernel/qwidgetrepaintmanager/BLACKLIST +++ /dev/null @@ -1,11 +0,0 @@ -# Temporary for QTBUG-109036 -[fastMove] -opensuse-leap - -# Temporary for QTBUG-109036 -[moveAccross] -opensuse-leap - -# Temporary for QTBUG-109036 -[moveInOutOverlapped] -opensuse-leap diff --git a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp index f53d5aeb050..feb8a991316 100644 --- a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp +++ b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp @@ -262,6 +262,8 @@ private slots: void moveInOutOverlapped(); protected: + bool m_xcb = false; + /* This helper compares the widget as rendered into the backingstore with the widget as rendered via QWidget::grab. The latter always produces a fully rendered image, @@ -279,14 +281,44 @@ protected: } QImage backingstoreContent = platformBackingStore->toImage(); + + // QXcbBackingStore::toImage() is not reliable. Take a screenshot instead. + // X11 draws the screen in a thread, which is not a QThread. + // The first screenshot is therefore unlikely to contain the correct image. + // It is taken just to obtain size and format. + QWidget *window = nullptr; + if (m_xcb) { + + // Widget must be shown to be caught on a screen shot + if (!w->isWindow()) { + qWarning() << "Hidden widget" << w << "cannot be compared on XCB"; + return false; + } + + window = w->window(); + Q_ASSERT(window); + + backingstoreContent = window->screen()->grabWindow(window->winId()).toImage(); + } + if (!w->isWindow()) { const qreal dpr = w->devicePixelRatioF(); const QPointF offset = w->mapTo(w->window(), QPointF(0, 0)) * dpr; backingstoreContent = backingstoreContent.copy(offset.x(), offset.y(), w->width() * dpr, w->height() * dpr); } + const QImage widgetRender = w->grab().toImage().convertToFormat(backingstoreContent.format()); - const bool result = backingstoreContent == widgetRender; + // XCB: Process events, until screenshot equals widgetRender or timeout kicks in. + if (m_xcb) { + // Unuse result to hit MANUAL_DEBUG code path + Q_UNUSED(QTest::qWaitFor([&](){ + backingstoreContent = window->screen()->grabWindow(window->winId()).toImage(); + return widgetRender == backingstoreContent; + })); + } + + const bool result = widgetRender == backingstoreContent; #ifdef MANUAL_DEBUG if (!result) { @@ -334,6 +366,10 @@ void tst_QWidgetRepaintManager::initTestCase() m_implementsScroll = widget.backingStore()->handle()->scroll(QRegion(widget.rect()), 1, 1); qInfo() << QGuiApplication::platformName() << "QPA backend implements scroll:" << m_implementsScroll; + +#if defined(QT_BUILD_INTERNAL) + m_xcb = QGuiApplication::platformName().contains("xcb", Qt::CaseInsensitive); +#endif } void tst_QWidgetRepaintManager::cleanup()