diff options
author | Liang Qi <liang.qi@qt.io> | 2018-12-04 09:58:43 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2018-12-04 09:58:43 +0100 |
commit | 5d5c00c67682bce105197b659687fd1fee8f60cf (patch) | |
tree | 686e41dc3ea121235fb73afb9157ed603f1bfeff /src/plugins/platforms/cocoa | |
parent | f213e818f03d35cb82e3daf187415197fd156f8e (diff) | |
parent | b82559244e2dc03f1ceff66bb67630df4300dc7c (diff) |
Merge remote-tracking branch 'origin/5.12' into dev
Conflicts:
src/gui/painting/qdrawhelper.cpp
Change-Id: I4916e07b635e1d3830e9b46ef7914f99bec3098e
Diffstat (limited to 'src/plugins/platforms/cocoa')
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoahelpers.mm | 25 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoaintegration.mm | 4 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qcocoascreen.mm | 95 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qmacclipboard.mm | 28 | ||||
-rw-r--r-- | src/plugins/platforms/cocoa/qpaintengine_mac.mm | 1 |
5 files changed, 92 insertions, 61 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 36841c77ab..d86e935788 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -402,23 +402,30 @@ QOperatingSystemVersion QMacVersion::currentRuntime() QMacVersion::VersionTuple QMacVersion::versionsForImage(const mach_header *machHeader) { + static auto makeVersionTuple = [](uint32_t dt, uint32_t sdk) { + return qMakePair( + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, + dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff), + QOperatingSystemVersion(QOperatingSystemVersion::MacOS, + sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff) + ); + }; + auto commandCursor = uintptr_t(machHeader) + sizeof(mach_header_64); for (uint32_t i = 0; i < machHeader->ncmds; ++i) { load_command *loadCommand = reinterpret_cast<load_command *>(commandCursor); if (loadCommand->cmd == LC_VERSION_MIN_MACOSX) { auto versionCommand = reinterpret_cast<version_min_command *>(loadCommand); - uint32_t dt = versionCommand->version; // Deployment target - uint32_t sdk = versionCommand->sdk; // Build SDK - return qMakePair( - QOperatingSystemVersion(QOperatingSystemVersion::MacOS, - dt >> 16 & 0xffff, dt >> 8 & 0xff, dt & 0xff), - QOperatingSystemVersion(QOperatingSystemVersion::MacOS, - sdk >> 16 & 0xffff, sdk >> 8 & 0xff, sdk & 0xff) - ); + return makeVersionTuple(versionCommand->version, versionCommand->sdk); +#if QT_MACOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_13) + } else if (loadCommand->cmd == LC_BUILD_VERSION) { + auto versionCommand = reinterpret_cast<build_version_command *>(loadCommand); + return makeVersionTuple(versionCommand->minos, versionCommand->sdk); +#endif } commandCursor += loadCommand->cmdsize; } - Q_ASSERT_X(false, "QCocoaIntegration", "Could not find version-min load command"); + Q_ASSERT_X(false, "QCocoaIntegration", "Could not find any version load command"); Q_UNREACHABLE(); } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 1bd1029863..f6a49dd74f 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -63,6 +63,8 @@ #include <QtGui/private/qcoregraphics_p.h> +#include <QtFontDatabaseSupport/private/qfontengine_coretext_p.h> + #ifdef QT_WIDGETS_LIB #include <QtWidgets/qtwidgetsglobal.h> #if QT_CONFIG(filedialog) @@ -477,7 +479,7 @@ QCocoaServices *QCocoaIntegration::services() const QVariant QCocoaIntegration::styleHint(StyleHint hint) const { if (hint == QPlatformIntegration::FontSmoothingGamma) - return 2.0; + return QCoreTextFontEngine::fontSmoothingGamma(); return QPlatformIntegration::styleHint(hint); } diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm index 0d6567070e..afe14e623c 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.mm +++ b/src/plugins/platforms/cocoa/qcocoascreen.mm @@ -428,66 +428,71 @@ QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const return window; } -QPixmap QCocoaScreen::grabWindow(WId window, int x, int y, int width, int height) const +QPixmap QCocoaScreen::grabWindow(WId view, 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. + // Determine the grab rect. FIXME: The rect should be bounded by the view's + // geometry, but note that for the pixeltool use case that window will be the + // desktop widgets's view, which currently gets resized to fit one screen + // only, since its NSWindow has the NSWindowStyleMaskTitled flag set. + Q_UNUSED(view); + QRect grabRect = QRect(x, y, width, height); + qCDebug(lcQpaScreen) << "input grab rect" << grabRect; + + // Find which displays to grab from, or all of them if the grab size is unspecified + const int maxDisplays = 128; CGDirectDisplayID displays[maxDisplays]; CGDisplayCount displayCount; - CGRect cgRect; - - if (width < 0 || height < 0) { - // get all displays - cgRect = CGRectInfinite; - } else { - cgRect = CGRectMake(x, y, width, height); - } + CGRect cgRect = (width < 0 || height < 0) ? CGRectInfinite : grabRect.toCGRect(); const CGDisplayErr err = CGGetDisplaysWithRect(cgRect, maxDisplays, displays, &displayCount); - - if (err && displayCount == 0) + if (err || displayCount == 0) return QPixmap(); - // calculate pixmap size - QSize windowSize(width, height); + // If the grab size is not specified, set it to be the bounding box of all screens, 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); + QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(displays[i])).toRect(); + windowRect = windowRect.united(displayBounds); } - if (width < 0) - windowSize.setWidth(windowRect.width()); - if (height < 0) - windowSize.setHeight(windowRect.height()); + if (grabRect.width() < 0) + grabRect.setWidth(windowRect.width()); + if (grabRect.height() < 0) + grabRect.setHeight(windowRect.height()); } - const qreal dpr = devicePixelRatio(); - QPixmap windowPixmap(windowSize * dpr); - windowPixmap.setDevicePixelRatio(dpr); - windowPixmap.fill(Qt::transparent); + qCDebug(lcQpaScreen) << "final grab rect" << grabRect << "from" << displayCount << "displays"; + // Grab images from each display + QVector<QImage> images; + QVector<QRect> destinations; for (uint i = 0; i < displayCount; ++i) { - const CGRect bounds = CGDisplayBounds(displays[i]); - - // Calculate the position and size of the requested area - QPoint pos(qAbs(bounds.origin.x - x), qAbs(bounds.origin.y - y)); - QSize size(qMin(width, qRound(bounds.size.width)), - qMin(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.drawImage(windowPixmap.rect(), image, QRect(pos, size)); + auto display = displays[i]; + QRect displayBounds = QRectF::fromCGRect(CGDisplayBounds(display)).toRect(); + QRect grabBounds = displayBounds.intersected(grabRect); + QRect displayLocalGrabBounds = QRect(QPoint(grabBounds.topLeft() - displayBounds.topLeft()), grabBounds.size()); + QImage displayImage = qt_mac_toQImage(QCFType<CGImageRef>(CGDisplayCreateImageForRect(display, displayLocalGrabBounds.toCGRect()))); + displayImage.setDevicePixelRatio(displayImage.size().width() / displayLocalGrabBounds.size().width()); + images.append(displayImage); + QRect destBounds = QRect(QPoint(grabBounds.topLeft() - grabRect.topLeft()), grabBounds.size()); + destinations.append(destBounds); + qCDebug(lcQpaScreen) << "grab display" << i << "global" << grabBounds << "local" << displayLocalGrabBounds + << "grab image size" << displayImage.size() << "devicePixelRatio" << displayImage.devicePixelRatio(); } + + // Determine the highest dpr, which becomes the dpr for the returned pixmap. + qreal dpr = 1.0; + for (uint i = 0; i < displayCount; ++i) + dpr = qMax(dpr, images.at(i).devicePixelRatio()); + + // Alocate target pixmap and draw each screen's content + qCDebug(lcQpaScreen) << "Create grap pixmap" << grabRect.size() << "at devicePixelRatio" << dpr; + QPixmap windowPixmap(grabRect.size() * dpr); + windowPixmap.setDevicePixelRatio(dpr); + windowPixmap.fill(Qt::transparent); + QPainter painter(&windowPixmap); + for (uint i = 0; i < displayCount; ++i) + painter.drawImage(destinations.at(i), images.at(i)); + return windowPixmap; } diff --git a/src/plugins/platforms/cocoa/qmacclipboard.mm b/src/plugins/platforms/cocoa/qmacclipboard.mm index 5939003c64..ba6cfca219 100644 --- a/src/plugins/platforms/cocoa/qmacclipboard.mm +++ b/src/plugins/platforms/cocoa/qmacclipboard.mm @@ -49,6 +49,7 @@ #include <stdlib.h> #include <string.h> #include "qcocoahelpers.h" +#include <type_traits> QT_BEGIN_NAMESPACE @@ -61,6 +62,23 @@ QT_BEGIN_NAMESPACE QMacPasteboard code *****************************************************************************/ +namespace +{ +OSStatus PasteboardGetItemCountSafe(PasteboardRef paste, ItemCount *cnt) +{ + Q_ASSERT(paste); + Q_ASSERT(cnt); + const OSStatus result = PasteboardGetItemCount(paste, cnt); + // Despite being declared unsigned, this API can return -1 + if (std::make_signed<ItemCount>::type(*cnt) < 0) + *cnt = 0; + return result; +} +} // namespace + +// Ensure we don't call the broken one later on +#define PasteboardGetItemCount + class QMacMimeData : public QMimeData { public: @@ -210,7 +228,7 @@ QMacPasteboard::hasOSType(int c_flavor) const sync(); ItemCount cnt = 0; - if (PasteboardGetItemCount(paste, &cnt) || !cnt) + if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt) return false; #ifdef DEBUG_PASTEBOARD @@ -257,7 +275,7 @@ QMacPasteboard::hasFlavor(QString c_flavor) const sync(); ItemCount cnt = 0; - if (PasteboardGetItemCount(paste, &cnt) || !cnt) + if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt) return false; #ifdef DEBUG_PASTEBOARD @@ -374,7 +392,7 @@ QMacPasteboard::formats() const QStringList ret; ItemCount cnt = 0; - if (PasteboardGetItemCount(paste, &cnt) || !cnt) + if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt) return ret; #ifdef DEBUG_PASTEBOARD @@ -417,7 +435,7 @@ QMacPasteboard::hasFormat(const QString &format) const sync(); ItemCount cnt = 0; - if (PasteboardGetItemCount(paste, &cnt) || !cnt) + if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt) return false; #ifdef DEBUG_PASTEBOARD @@ -460,7 +478,7 @@ QMacPasteboard::retrieveData(const QString &format, QVariant::Type) const sync(); ItemCount cnt = 0; - if (PasteboardGetItemCount(paste, &cnt) || !cnt) + if (PasteboardGetItemCountSafe(paste, &cnt) || !cnt) return QByteArray(); #ifdef DEBUG_PASTEBOARD diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 5c880b1cad..3677877538 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -914,7 +914,6 @@ void QCoreGraphicsPaintEngine::drawTextItem(const QPointF &pos, const QTextItem QFontEngine *fe = ti.fontEngine; const bool textAA = ((state->renderHints() & QPainter::TextAntialiasing) - && (fe->fontDef.pointSize > QCoreTextFontEngine::antialiasingThreshold) && !(fe->fontDef.styleStrategy & QFont::NoAntialias)); const bool lineAA = state->renderHints() & QPainter::Antialiasing; if (textAA != lineAA) |