diff options
Diffstat (limited to 'tests/auto/gui/kernel/qscreen/tst_qscreen.cpp')
-rw-r--r-- | tests/auto/gui/kernel/qscreen/tst_qscreen.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp index 9f2a767d60..baa36f2c4e 100644 --- a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp +++ b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp @@ -26,6 +26,8 @@ ** ****************************************************************************/ +#include <qpainter.h> +#include <qrasterwindow.h> #include <qscreen.h> #include <qpa/qwindowsysteminterface.h> @@ -41,6 +43,9 @@ private slots: void transformBetween_data(); void transformBetween(); void orientationChange(); + + void grabWindow_data(); + void grabWindow(); }; void tst_QScreen::angleBetween_data() @@ -197,5 +202,138 @@ void tst_QScreen::orientationChange() QCOMPARE(spy.count(), ++expectedSignalCount); } +void tst_QScreen::grabWindow_data() +{ + if (QGuiApplication::platformName().startsWith(QLatin1String("offscreen"), Qt::CaseInsensitive)) + QSKIP("Offscreen: Screen grabbing not implemented."); + + QTest::addColumn<int>("screenIndex"); + QTest::addColumn<QByteArray>("screenName"); + QTest::addColumn<bool>("grabWindow"); + QTest::addColumn<QRect>("windowRect"); + QTest::addColumn<QRect>("grabRect"); + + int screenIndex = 0; + for (const auto screen : QGuiApplication::screens()) { + const QByteArray screenName = screen->name().toUtf8(); + const QRect availableGeometry = screen->availableGeometry(); + const QPoint topLeft = availableGeometry.topLeft() + QPoint(20, 20); + QTest::addRow("%s - Window", screenName.data()) + << screenIndex << screenName << true << QRect(topLeft, QSize(200, 200)) << QRect(0, 0, -1, -1); + QTest::addRow("%s - Window Section", screenName.data()) + << screenIndex << screenName << true << QRect(topLeft, QSize(200, 200)) << QRect(50, 50, 100, 100); + QTest::addRow("%s - Screen", screenName.data()) + << screenIndex << screenName << false << QRect(topLeft, QSize(200, 200)) << QRect(0, 0, -1, -1); + QTest::addRow("%s - Screen Section", screenName.data()) + << screenIndex << screenName << false << QRect(topLeft, QSize(200, 200)) << QRect(topLeft, QSize(200, 200)); + + ++screenIndex; + } +} + +void tst_QScreen::grabWindow() +{ + QFETCH(int, screenIndex); + QFETCH(QByteArray, screenName); + QFETCH(bool, grabWindow); + QFETCH(QRect, windowRect); + QFETCH(QRect, grabRect); + + class Window : public QRasterWindow + { + public: + Window(QScreen *scr) + : image(scr->size(), QImage::Format_ARGB32_Premultiplied) + { + setFlags(Qt::CustomizeWindowHint|Qt::FramelessWindowHint|Qt::WindowStaysOnTopHint); + setScreen(scr); + image.setDevicePixelRatio(scr->devicePixelRatio()); + } + QImage image; + + protected: + void resizeEvent(QResizeEvent *e) override + { + const QSize sz = e->size(); + image = image.scaled(sz * image.devicePixelRatioF()); + QPainter painter(&image); + painter.fillRect(0, 0, sz.width(), sz.height(), Qt::black); + painter.setPen(QPen(Qt::red, 2)); + painter.drawLine(0, 0, sz.width(), sz.height()); + painter.drawLine(0, sz.height(), sz.width(), 0); + painter.drawRect(0, 0, sz.width(), sz.height()); + } + void paintEvent(QPaintEvent *) override + { + QPainter painter(this); + painter.drawImage(0, 0, image); + } + }; + const auto screens = QGuiApplication::screens(); + double highestDpr = 0; + for (auto screen : screens) + highestDpr = qMax(highestDpr, screen->devicePixelRatio()); + + QScreen *screen = screens.at(screenIndex); + QCOMPARE(screen->name().toUtf8(), screenName); + const double screenDpr = screen->devicePixelRatio(); + + Window window(screen); + window.setGeometry(windowRect); + window.show(); + + if (!QTest::qWaitForWindowExposed(&window)) + QSKIP("Failed to expose window - aborting"); + + if (QGuiApplication::platformName().startsWith(QLatin1String("xcb"), Qt::CaseInsensitive)) + QTest::qWait(1500); // this is ridiculously necessary because of effects combined with slowness of VMs +#ifdef Q_OS_MACOS // wait for desktop on screen to scroll into place + QTest::qWait(1000); +#endif + + QSize expectedGrabSize = grabRect.isValid() ? grabRect.size() : (grabWindow ? windowRect.size() : screen->size()); + // we ask for pixel coordinates, but will get a pixmap with device-specific DPR + expectedGrabSize *= screen->devicePixelRatio(); + + // the painted image will always be in the screen's DPR + QImage paintedImage = window.image; + QCOMPARE(paintedImage.devicePixelRatio(), screenDpr); + + const QPixmap pixmap = screen->grabWindow(grabWindow ? window.winId() : 0, grabRect.x(), grabRect.y(), grabRect.width(), grabRect.height()); + + QImage grabbedImage = pixmap.toImage(); + const QSize grabbedSize = grabbedImage.size(); + QCOMPARE(grabbedSize, expectedGrabSize); + + QPoint pixelOffset = QPoint(0, 0); + if (!grabRect.isValid()) { + if (grabWindow) { + // if we grab the entire window, then the grabbed image should be as large as the window + QCOMPARE(grabbedImage.size(), paintedImage.size()); + } else { + // if we grab the entire screen, then the grabbed image should be as large as the screen + QCOMPARE(grabbedImage.size(), screen->size() * screenDpr); + pixelOffset = window.geometry().topLeft() - screen->geometry().topLeft(); + grabbedImage = grabbedImage.copy(QRect(pixelOffset * screenDpr, window.geometry().size() * screenDpr)); + } + } else if (grabWindow) { + // if we grab the section, compare with the corresponding section from the painted image + const QRect sectionRect = QRect(grabRect.topLeft() * screenDpr, + grabRect.size() * screenDpr); + paintedImage = paintedImage.copy(sectionRect); + } + QCOMPARE(grabbedImage.size(), paintedImage.size()); + + // the two images might differ in format, or DPR, so instead of comparing them, sample a few pixels + for (auto point : { + QPoint(0, 0), + QPoint(5, 15), + QPoint(paintedImage.width() - 1, paintedImage.height() - 1), + QPoint(paintedImage.width() - 5, paintedImage.height() - 10) + }) { + QCOMPARE(grabbedImage.pixelColor(point), paintedImage.pixelColor(point)); + } +} + #include <tst_qscreen.moc> QTEST_MAIN(tst_QScreen); |