From 8359e44324a9554d1a340d91a0df962e83302228 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Sat, 22 Jan 2022 00:43:56 +0100 Subject: [PATCH] Offscreen: Fix implementation of QScreen::grabWindow If id == 0, then we should grab the specified rect from the screen. To do that, find all windows intersecting with the screen geometry, and compose their backing store images into a screen-size pixmap. Otherwise, find the respective backing store and grab only that. Remove the old code respecting the desktop widget, which is no longer a thing in Qt 6. The code was also wrongly grabbing only the first containing - not intersecting - window's backing store into the screen pixmap. Enable the QScreen::grabImage test for the offscreen platform, where it now passes. Task-number: QTBUG-99962 Change-Id: I16eca7b082d65095a62c73624f86a4423e997a7a Reviewed-by: Qt CI Bot Reviewed-by: Laszlo Agocs --- .../platforms/offscreen/qoffscreencommon.cpp | 28 +++++++++++-------- tests/auto/gui/kernel/qscreen/tst_qscreen.cpp | 3 -- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/src/plugins/platforms/offscreen/qoffscreencommon.cpp b/src/plugins/platforms/offscreen/qoffscreencommon.cpp index f485b4eed8..76ebe79590 100644 --- a/src/plugins/platforms/offscreen/qoffscreencommon.cpp +++ b/src/plugins/platforms/offscreen/qoffscreencommon.cpp @@ -42,6 +42,7 @@ #include "qoffscreenwindow.h" +#include #include #include @@ -116,22 +117,25 @@ QPixmap QOffscreenScreen::grabWindow(WId id, int x, int y, int width, int height { QRect rect(x, y, width, height); - QOffscreenWindow *window = QOffscreenWindow::windowForWinId(id); - if (!window || window->window()->type() == Qt::Desktop) { + // id == 0 -> grab the screen, so all windows intersecting rect + if (!id) { + if (width == -1) + rect.setWidth(m_geometry.width()); + if (height == -1) + rect.setHeight(m_geometry.height()); + QPixmap screenImage(rect.size()); + QPainter painter(&screenImage); + painter.translate(-x, -y); const QWindowList wl = QGuiApplication::topLevelWindows(); - QWindow *containing = nullptr; for (QWindow *w : wl) { - if (w->type() != Qt::Desktop && w->isExposed() && w->geometry().contains(rect)) { - containing = w; - break; + if (w->isExposed() && w->geometry().intersects(rect)) { + QOffscreenBackingStore *store = QOffscreenBackingStore::backingStoreForWinId(w->winId()); + const QImage windowImage = store ? store->toImage() : QImage(); + if (!windowImage.isNull()) + painter.drawImage(w->position(), windowImage); } } - - if (!containing) - return QPixmap(); - - id = containing->winId(); - rect = rect.translated(-containing->geometry().topLeft()); + return screenImage; } QOffscreenBackingStore *store = QOffscreenBackingStore::backingStoreForWinId(id); diff --git a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp index 83d476e812..a6e9535e88 100644 --- a/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp +++ b/tests/auto/gui/kernel/qscreen/tst_qscreen.cpp @@ -205,9 +205,6 @@ void tst_QScreen::orientationChange() void tst_QScreen::grabWindow_data() { - if (QGuiApplication::platformName().startsWith(QLatin1String("offscreen"), Qt::CaseInsensitive)) - QSKIP("Offscreen: Screen grabbing not implemented."); - QTest::addColumn("screenIndex"); QTest::addColumn("screenName"); QTest::addColumn("grabWindow");