diff options
Diffstat (limited to 'tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp')
-rw-r--r-- | tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp | 119 |
1 files changed, 118 insertions, 1 deletions
diff --git a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp index 52b179fedb..490c2a7d8c 100644 --- a/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp +++ b/tests/auto/widgets/kernel/qwidgetrepaintmanager/tst_qwidgetrepaintmanager.cpp @@ -29,7 +29,8 @@ #include <QTest> #include <QPainter> -#include <QWidget> +#include <QScrollArea> +#include <QScrollBar> #include <QApplication> #include <private/qhighdpiscaling_p.h> @@ -94,6 +95,7 @@ private slots: void opaqueChildren(); void staticContents(); void scroll(); + void moveWithOverlap(); private: const int m_fuzz; @@ -246,5 +248,120 @@ void tst_QWidgetRepaintManager::scroll() QCOMPARE(widget.takePaintedRegions(), QRegion()); } + +/*! + Verify that overlapping children are repainted correctly when + a widget is moved (via a scroll area) for such a distance that + none of the old area is still visible. QTBUG-26269 +*/ +void tst_QWidgetRepaintManager::moveWithOverlap() +{ + if (QStringList{"android"}.contains(QGuiApplication::platformName())) + QSKIP("This test fails on Android"); + + class MainWindow : public QWidget + { + public: + MainWindow(QWidget *parent = 0) + : QWidget(parent, Qt::WindowStaysOnTopHint) + { + m_scrollArea = new QScrollArea(this); + QWidget *w = new QWidget; + w->setPalette(QPalette(Qt::gray)); + w->setAutoFillBackground(true); + m_scrollArea->setWidget(w); + m_scrollArea->resize(500, 100); + w->resize(5000, 600); + + m_topWidget = new QWidget(this); + m_topWidget->setPalette(QPalette(Qt::red)); + m_topWidget->setAutoFillBackground(true); + m_topWidget->resize(300, 200); + } + + void resizeEvent(QResizeEvent *e) override + { + QWidget::resizeEvent(e); + // move scroll area and top widget to the center of the main window + scrollArea()->move((width() - scrollArea()->width()) / 2, (height() - scrollArea()->height()) / 2); + topWidget()->move((width() - topWidget()->width()) / 2, (height() - topWidget()->height()) / 2); + } + + + inline QScrollArea *scrollArea() const { return m_scrollArea; } + inline QWidget *topWidget() const { return m_topWidget; } + + bool grabWidgetBackground(QWidget *w) + { + // To check widget's background we should compare two screenshots: + // the first one is taken by system tools through QScreen::grabWindow(), + // the second one is taken by Qt rendering to a pixmap via QWidget::grab(). + + QScreen *screen = w->screen(); + const QRect screenGeometry = screen->geometry(); + QPoint globalPos = w->mapToGlobal(QPoint(0, 0)); + if (globalPos.x() >= screenGeometry.width()) + globalPos.rx() -= screenGeometry.x(); + if (globalPos.y() >= screenGeometry.height()) + globalPos.ry() -= screenGeometry.y(); + + return QTest::qWaitFor([&]{ + QImage systemScreenshot = screen->grabWindow(winId(), + globalPos.x(), globalPos.y(), + w->width(), w->height()).toImage(); + systemScreenshot = systemScreenshot.convertToFormat(QImage::Format_RGB32); + QImage qtScreenshot = w->grab().toImage().convertToFormat(systemScreenshot.format()); + return systemScreenshot == qtScreenshot; + }); + }; + + private: + QScrollArea *m_scrollArea; + QWidget *m_topWidget; + }; + + MainWindow w; + w.showFullScreen(); + + QVERIFY(QTest::qWaitForWindowActive(&w)); + + bool result = w.grabWidgetBackground(w.topWidget()); + // if this fails already, then the system we test on can't compare screenshots from grabbed widgets, + // and we have to skip this test. Possible reasons are that showing the window took too long, differences + // in surface formats, or unrelated bugs in QScreen::grabWindow. + if (!result) + QSKIP("Cannot compare QWidget::grab with QScreen::grabWindow on this machine"); + + // scroll the horizontal slider to the right side + { + w.scrollArea()->horizontalScrollBar()->setValue(w.scrollArea()->horizontalScrollBar()->maximum()); + QVERIFY(w.grabWidgetBackground(w.topWidget())); + } + + // scroll the vertical slider down + { + w.scrollArea()->verticalScrollBar()->setValue(w.scrollArea()->verticalScrollBar()->maximum()); + QVERIFY(w.grabWidgetBackground(w.topWidget())); + } + + // hide the top widget + { + w.topWidget()->hide(); + QVERIFY(w.grabWidgetBackground(w.scrollArea()->viewport())); + } + + // scroll the horizontal slider to the left side + { + w.scrollArea()->horizontalScrollBar()->setValue(w.scrollArea()->horizontalScrollBar()->minimum()); + QVERIFY(w.grabWidgetBackground(w.scrollArea()->viewport())); + } + + // scroll the vertical slider up + { + w.scrollArea()->verticalScrollBar()->setValue(w.scrollArea()->verticalScrollBar()->minimum()); + QVERIFY(w.grabWidgetBackground(w.scrollArea()->viewport())); + } +} + QTEST_MAIN(tst_QWidgetRepaintManager) #include "tst_qwidgetrepaintmanager.moc" |