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 <qt_ci_bot@qt-project.org>
Reviewed-by: Laszlo Agocs <laszlo.agocs@qt.io>
bb10
Volker Hilsheimer 2022-01-22 00:43:56 +01:00
parent 5d1bb2ed57
commit 8359e44324
2 changed files with 16 additions and 15 deletions

View File

@ -42,6 +42,7 @@
#include "qoffscreenwindow.h"
#include <QtGui/QPainter>
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
@ -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);

View File

@ -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<int>("screenIndex");
QTest::addColumn<QByteArray>("screenName");
QTest::addColumn<bool>("grabWindow");