Fix QPixmap::grabWindow() on Mac OS X Lion
authorAndy Shaw <andy.shaw@digia.com>
Fri, 19 Aug 2011 11:46:51 +0000 (13:46 +0200)
committerQt by Nokia <qt-info@nokia.com>
Mon, 12 Sep 2011 14:03:47 +0000 (16:03 +0200)
The old approach was not the recommended one and although it worked on
Mac OS X 10.6 it did not work on 10.7.  The new approach works correctly
on 10.6 and 10.7, so the fix is applied for both versions.

Task-number: QTBUG-19824
Merge-request: 1332
Reviewed-by: sroedal
(cherry picked from commit aaf94776ce1034ec2b2402b9ca0e5cf7c7848b12)

Change-Id: I567d7e2ed2e4b3256f3110f4110ab1342087bc43
Reviewed-on: http://codereview.qt-project.org/4583
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@nokia.com>
src/gui/image/qpixmap_mac.cpp

index bdf1f90..63b568e 100644 (file)
@@ -852,6 +852,31 @@ static void qt_mac_grabDisplayRect(CGDirectDisplayID display, const QRect &displ
 }
 
 // Returns a pixmap containing the screen contents at rect.
+static QPixmap qt_mac_grabScreenRect_10_6(const QRect &rect)
+{
+    const int maxDisplays = 128; // 128 displays should be enough for everyone.
+    CGDirectDisplayID displays[maxDisplays];
+    CGDisplayCount displayCount;
+    const CGRect cgRect = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height());
+    const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount);
+
+    if (err && displayCount == 0)
+        return QPixmap();
+    QPixmap windowPixmap(rect.size());
+    for (uint i = 0; i < displayCount; ++i) {
+        const CGRect bounds = CGDisplayBounds(displays[i]);
+        // Translate to display-local coordinates
+        QRect displayRect = rect.translated(qRound(-bounds.origin.x), qRound(-bounds.origin.y));
+        // Adjust for inverted y axis.
+        displayRect.moveTop(qRound(bounds.size.height) - displayRect.y() - rect.height());
+        QCFType<CGImageRef> image = CGDisplayCreateImageForRect(displays[i], bounds);
+        QPixmap pix = QPixmap::fromMacCGImageRef(image);
+        QPainter painter(&windowPixmap);
+        painter.drawPixmap(-bounds.origin.x, -bounds.origin.y, pix);
+    }
+    return windowPixmap;
+}
+
 static QPixmap qt_mac_grabScreenRect(const QRect &rect)
 {
     if (!resolveOpenGLSymbols())
@@ -927,7 +952,8 @@ QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h)
     QRect rect(globalCoord.x() + x, globalCoord.y() + y, w, h);
 
 #ifdef QT_MAC_USE_COCOA
-    return qt_mac_grabScreenRect(rect);
+    return (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) ?
+        qt_mac_grabScreenRect_10_6(rect) : qt_mac_grabScreenRect(rect);
 #else
 #if (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4)
     if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) {