QPlatformScreen::grabWindow() support on Mac
authorTasuku Suzuki <tasuku.suzuki@nokia.com>
Sun, 1 Jul 2012 08:27:30 +0000 (17:27 +0900)
committerQt by Nokia <qt-info@nokia.com>
Fri, 6 Jul 2012 11:57:55 +0000 (13:57 +0200)
Added QCocoaScreen::grabWindow() and copied Qt 4 implimentation.
examples/desktop/screenshot works but WId window is not handled yet.

Change-Id: If228bb59d98a5166788ab38293d7e6a6300d1f85
Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
src/plugins/platforms/cocoa/qcocoaintegration.h
src/plugins/platforms/cocoa/qcocoaintegration.mm
src/plugins/platforms/cocoa/qpaintengine_mac.mm

index fa0c25a..dc29e52 100644 (file)
@@ -61,6 +61,8 @@ public:
     QCocoaScreen(int screenIndex);
     ~QCocoaScreen();
 
+    QPixmap grabWindow(WId window, int x, int y, int width, int height) const;
+
     QRect geometry() const { return m_geometry; }
     QRect availableGeometry() const { return m_availableGeometry; }
     int depth() const { return m_depth; }
index 29c5ec7..ccb1121 100644 (file)
@@ -88,6 +88,67 @@ QCocoaScreen::~QCocoaScreen()
     delete m_cursor;
 }
 
+extern CGContextRef qt_mac_cg_context(const QPaintDevice *pdev);
+
+QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const
+{
+    // TODO window should be handled
+    Q_UNUSED(window)
+
+    const int maxDisplays = 128; // 128 displays should be enough for everyone.
+    CGDirectDisplayID displays[maxDisplays];
+    CGDisplayCount displayCount;
+    CGRect cgRect;
+
+    if (width < 0 || height < 0) {
+        // get all displays
+        cgRect = CGRectInfinite;
+    } else {
+        cgRect = CGRectMake(x, y, width, height);
+    }
+    const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount);
+
+    if (err && displayCount == 0)
+        return QPixmap();
+
+    // calculate pixmap size
+    QSize windowSize(width, height);
+    if (width < 0 || height < 0) {
+        QRect windowRect;
+        for (uint i = 0; i < displayCount; ++i) {
+            const CGRect cgRect = CGDisplayBounds(displays[i]);
+            QRect qRect(cgRect.origin.x, cgRect.origin.y, cgRect.size.width, cgRect.size.height);
+            windowRect = windowRect.united(qRect);
+        }
+        if (width < 0)
+            windowSize.setWidth(windowRect.width());
+        if (height < 0)
+            windowSize.setHeight(windowRect.height());
+    }
+
+    QPixmap windowPixmap(windowSize);
+    windowPixmap.fill(Qt::transparent);
+
+    for (uint i = 0; i < displayCount; ++i) {
+        const CGRect bounds = CGDisplayBounds(displays[i]);
+        int w = (width < 0 ? bounds.size.width : width);
+        int h = (height < 0 ? bounds.size.height : height);
+        QRect displayRect = QRect(x, y, w, h);
+        QCFType<CGImageRef> image = CGDisplayCreateImageForRect(displays[i],
+            CGRectMake(displayRect.x(), displayRect.y(), displayRect.width(), displayRect.height()));
+        QPixmap pix(w, h);
+        pix.fill(Qt::transparent);
+        CGRect rect = CGRectMake(0, 0, w, h);
+        CGContextRef ctx = qt_mac_cg_context(&pix);
+        qt_mac_drawCGImage(ctx, &rect, image);
+        CGContextRelease(ctx);
+
+        QPainter painter(&windowPixmap);
+        painter.drawPixmap(bounds.origin.x, bounds.origin.y, pix);
+    }
+    return windowPixmap;
+}
+
 QCocoaIntegration::QCocoaIntegration()
     : mFontDb(new QCoreTextFontDatabase())
     , mEventDispatcher(new QCocoaEventDispatcher())
index 38c8162..3eaf327 100644 (file)
@@ -226,7 +226,7 @@ CGContextRef qt_mac_cg_context(const QPaintDevice *pdev)
         CGContextRef ret = 0;
 
         QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data();
-        if (data->classId() == QPlatformPixmap::RasterClass) {
+        if (data && data->classId() == QPlatformPixmap::RasterClass) {
             QImage *image = data->buffer();
             ret = CGBitmapContextCreate(image->bits(), image->width(), image->height(),
                                         8, image->bytesPerLine(), colorspace, flags);