summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2018-12-04 09:58:43 +0100
committerLiang Qi <liang.qi@qt.io>2018-12-04 09:58:43 +0100
commit5d5c00c67682bce105197b659687fd1fee8f60cf (patch)
tree686e41dc3ea121235fb73afb9157ed603f1bfeff /src/plugins/platforms/cocoa
parentf213e818f03d35cb82e3daf187415197fd156f8e (diff)
parentb82559244e2dc03f1ceff66bb67630df4300dc7c (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.mm25
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm4
-rw-r--r--src/plugins/platforms/cocoa/qcocoascreen.mm95
-rw-r--r--src/plugins/platforms/cocoa/qmacclipboard.mm28
-rw-r--r--src/plugins/platforms/cocoa/qpaintengine_mac.mm1
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)