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 <volker.hilsheimer@qt.io>
(cherry picked from commit 4096667d6601dcbc5e713e6b0fd5b5218453c4cb)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Axel Spoerl 2023-01-09 14:33:23 +01:00 committed by Qt Cherry-pick Bot
parent 7b0fc393a0
commit f20f1c6b7c
2 changed files with 37 additions and 12 deletions

View File

@ -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

View File

@ -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()