Skip to content

Commit

Permalink
Cocoa: fix grabWindow when mixing highDPI and non-highDPI screens
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
pamarcos committed Feb 22, 2018
1 parent 8ef9a0a commit 17b73b0
Showing 1 changed file with 16 additions and 13 deletions.
29 changes: 16 additions & 13 deletions src/plugins/platforms/cocoa/qcocoascreen.mm
Original file line number Diff line number Diff line change
Expand Up @@ -233,25 +233,28 @@ static QString displayName(CGDirectDisplayID displayID)
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<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);
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<CGImageRef> 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;
}
Expand Down

0 comments on commit 17b73b0

Please sign in to comment.