From 17b73b0d2b8e0d643bdf13b543cc23d657a4b330 Mon Sep 17 00:00:00 2001 From: Pablo Marcos Oltra Date: Wed, 21 Feb 2018 19:44:34 +0100 Subject: Cocoa: fix grabWindow when mixing highDPI and non-highDPI screens MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CGDisplayCreateImageForRect seems to have a weird behavior when mixing highDPI and non-highDPI screens since it may take part of the non-highDPI screen when the highDPI display is at the left or at the top of the main monitor. To workaround this issue, we capture the whole screen and then crop the image to the desired size. Task-number: QTBUG-47643 Change-Id: Ib2a3850a0a549964c7fe272abb563bd23518c234 Reviewed-by: Morten Johan Sørvig --- src/plugins/platforms/cocoa/qcocoascreen.mm | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm index ed1b19cd53..a17a02b629 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.mm +++ b/src/plugins/platforms/cocoa/qcocoascreen.mm @@ -233,25 +233,28 @@ QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height windowSize.setHeight(windowRect.height()); } - QPixmap windowPixmap(windowSize * devicePixelRatio()); + const qreal dpr = devicePixelRatio(); + QPixmap windowPixmap(windowSize * dpr); 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) * devicePixelRatio(); - int h = (height < 0 ? bounds.size.height : height) * devicePixelRatio(); - QRect displayRect = QRect(x, y, w, h); - displayRect = displayRect.translated(qRound(-bounds.origin.x), qRound(-bounds.origin.y)); - QCFType 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); - QMacCGContext ctx(&pix); - qt_mac_drawCGImage(ctx, &rect, image); + // Calculate the position and size of the requested area + QPoint pos(qAbs(bounds.origin.x - x), qAbs(bounds.origin.y - y)); + QSize size(qMin(pos.x() + width, qRound(bounds.size.width)), + qMin(pos.y() + height, qRound(bounds.size.height))); + pos *= dpr; + size *= dpr; + + // Take the whole screen and crop it afterwards, because CGDisplayCreateImageForRect + // has a strange behavior when mixing highDPI and non-highDPI displays + QCFType cgImage = CGDisplayCreateImage(displays[i]); + const QImage image = qt_mac_toQImage(cgImage); + + // Draw into windowPixmap only the requested size QPainter painter(&windowPixmap); - painter.drawPixmap(0, 0, pix); + painter.drawImage(windowPixmap.rect(), image, QRect(pos, size)); } return windowPixmap; } -- cgit v1.2.3