Implement QQuickWindow::grabWindow() for isVisible=false
authorGunnar Sletta <gunnar.sletta@digia.com>
Thu, 18 Apr 2013 15:02:24 +0000 (17:02 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Fri, 26 Apr 2013 17:05:45 +0000 (19:05 +0200)
Webkit uses this for testing.

Change-Id: I4539e169a02592fb6c0062903917d4dd23a4303c
Reviewed-by: Jocelyn Turcotte <jocelyn.turcotte@digia.com>
src/quick/items/qquickwindow.cpp
tests/auto/quick/qquickwindow/tst_qquickwindow.cpp

index 6b82f3f..a4dff96 100644 (file)
@@ -72,6 +72,8 @@
 
 QT_BEGIN_NAMESPACE
 
+extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
+
 void QQuickWindowPrivate::updateFocusItemTransform()
 {
     Q_Q(QQuickWindow);
@@ -2653,7 +2655,10 @@ QOpenGLFramebufferObject *QQuickWindow::renderTarget() const
 /*!
     Grabs the contents of the window and returns it as an image.
 
-    This function might not work if the window is not visible.
+    It is possible to call the grabWindow() function when the window is not
+    visible. This requires that the window is \l{QWindow::create} {created}
+    and has a valid size and that no other QQuickWindow instances are rendering
+    in the same process.
 
     \warning Calling this function will cause performance problems.
 
@@ -2662,6 +2667,36 @@ QOpenGLFramebufferObject *QQuickWindow::renderTarget() const
 QImage QQuickWindow::grabWindow()
 {
     Q_D(QQuickWindow);
+    if (!isVisible()) {
+
+        if (d->context->isReady()) {
+            qWarning("QQuickWindow::grabWindow: scene graph already in use");
+            return QImage();
+        }
+
+        if (!handle() || !size().isValid()) {
+            qWarning("QQuickWindow::grabWindow: window must be created and have a valid size");
+            return QImage();
+        }
+
+        QOpenGLContext context;
+        context.setFormat(requestedFormat());
+        context.create();
+        context.makeCurrent(this);
+        d->context->initialize(&context);
+
+        d->polishItems();
+        d->syncSceneGraph();
+        d->renderSceneGraph(size());
+
+        QImage image = qt_gl_read_framebuffer(size(), false, false);
+        d->cleanupNodesOnShutdown();
+        d->context->invalidate();
+        context.doneCurrent();
+
+        return image;
+    }
+
     return d->windowManager->grab(this);
 }
 
index 2d3c8f7..dbf0086 100644 (file)
@@ -304,6 +304,7 @@ private slots:
     void qmlCreation();
     void clearColor();
 
+    void grab_data();
     void grab();
     void multipleWindows();
 
@@ -929,15 +930,28 @@ void tst_qquickwindow::clearColor()
     QCOMPARE(window->color(), QColor(Qt::blue));
 }
 
+void tst_qquickwindow::grab_data()
+{
+    QTest::addColumn<bool>("visible");
+    QTest::newRow("visible") << true;
+    QTest::newRow("invisible") << false;
+}
+
 void tst_qquickwindow::grab()
 {
+    QFETCH(bool, visible);
+
     QQuickWindow window;
     window.setColor(Qt::red);
 
     window.resize(250, 250);
-    window.show();
 
-    QVERIFY(QTest::qWaitForWindowExposed(&window));
+    if (visible) {
+        window.show();
+        QVERIFY(QTest::qWaitForWindowExposed(&window));
+    } else {
+        window.create();
+    }
 
     QImage content = window.grabWindow();
     QCOMPARE(content.width(), window.width());