summaryrefslogtreecommitdiffstats
path: root/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/gui/kernel/qscreen/tst_qscreen.cpp')
-rw-r--r--tests/auto/gui/kernel/qscreen/tst_qscreen.cpp138
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);