diff options
Diffstat (limited to 'src/plugins/platforms/cocoa')
48 files changed, 801 insertions, 699 deletions
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 5354bdafbc..2694cb3607 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -14,6 +14,7 @@ SOURCES += main.mm \ qcocoaeventdispatcher.mm \ qcocoaapplicationdelegate.mm \ qcocoaapplication.mm \ + qcocoansmenu.mm \ qcocoamenu.mm \ qcocoamenuitem.mm \ qcocoamenubar.mm \ @@ -47,6 +48,7 @@ HEADERS += qcocoaintegration.h \ qcocoaeventdispatcher.h \ qcocoaapplicationdelegate.h \ qcocoaapplication.h \ + qcocoansmenu.h \ qcocoamenu.h \ qcocoamenuitem.h \ qcocoamenubar.h \ diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.h b/src/plugins/platforms/cocoa/qcocoaaccessibility.h index e7957276c2..e456364555 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibility.h +++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.h @@ -53,10 +53,10 @@ class QCocoaAccessibility : public QPlatformAccessibility public: QCocoaAccessibility(); ~QCocoaAccessibility(); - void notifyAccessibilityUpdate(QAccessibleEvent *event) Q_DECL_OVERRIDE; - void setRootObject(QObject *o) Q_DECL_OVERRIDE; - void initialize() Q_DECL_OVERRIDE; - void cleanup() Q_DECL_OVERRIDE; + void notifyAccessibilityUpdate(QAccessibleEvent *event) override; + void setRootObject(QObject *o) override; + void initialize() override; + void cleanup() override; }; namespace QCocoaAccessible { diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index 7e6bae127c..df2336d08b 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -40,6 +40,7 @@ #include "qcocoaaccessibility.h" #include "qcocoahelpers.h" #include "qcocoawindow.h" +#include "qcocoascreen.h" #include "private/qaccessiblecache_p.h" #include <QtAccessibilitySupport/private/qaccessiblebridgeutils_p.h> #include <QtGui/qaccessible.h> @@ -298,9 +299,9 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of // We're in the same top level element as our parent. return [[self parentElement] accessibilityAttributeValue:NSAccessibilityTopLevelUIElementAttribute]; } else if ([attribute isEqualToString:NSAccessibilityPositionAttribute]) { - QPoint qtPosition = iface->rect().topLeft(); - QSize qtSize = iface->rect().size(); - return [NSValue valueWithPoint: NSMakePoint(qtPosition.x(), qt_mac_flipYCoordinate(qtPosition.y() + qtSize.height()))]; + // The position in points of the element's lower-left corner in screen-relative coordinates + QPointF qtPosition = QRectF(iface->rect()).bottomLeft(); + return [NSValue valueWithPoint:QCocoaScreen::mapToNative(qtPosition)]; } else if ([attribute isEqualToString:NSAccessibilitySizeAttribute]) { QSize qtSize = iface->rect().size(); return [NSValue valueWithSize: NSMakeSize(qtSize.width(), qtSize.height())]; @@ -430,7 +431,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of if ([attribute isEqualToString: NSAccessibilityBoundsForRangeParameterizedAttribute]) { NSRange range = [parameter rangeValue]; QRect firstRect = iface->textInterface()->characterRect(range.location); - QRect rect; + QRectF rect; if (range.length > 0) { NSUInteger position = range.location + range.length - 1; if (position > range.location && iface->textInterface()->text(position, position + 1) == QStringLiteral("\n")) @@ -441,15 +442,14 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of rect = firstRect; rect.setWidth(1); } - return [NSValue valueWithRect: NSMakeRect((CGFloat) rect.x(),(CGFloat) qt_mac_flipYCoordinate(rect.y() + rect.height()), rect.width(), rect.height())]; + return [NSValue valueWithRect:QCocoaScreen::mapToNative(rect)]; } if ([attribute isEqualToString: NSAccessibilityAttributedStringForRangeParameterizedAttribute]) { NSRange range = [parameter rangeValue]; QString text = iface->textInterface()->text(range.location, range.location + range.length); return [[NSAttributedString alloc] initWithString:text.toNSString()]; } else if ([attribute isEqualToString: NSAccessibilityRangeForPositionParameterizedAttribute]) { - NSPoint nsPoint = [parameter pointValue]; - QPoint point(static_cast<int>(nsPoint.x), static_cast<int>(qt_mac_flipYCoordinate(nsPoint.y))); + QPoint point = QCocoaScreen::mapFromNative([parameter pointValue]).toPoint(); int offset = iface->textInterface()->offsetAtPoint(point); return [NSValue valueWithRange:NSMakeRange(static_cast<NSUInteger>(offset), 1)]; } else if ([attribute isEqualToString: NSAccessibilityStyleRangeForIndexParameterizedAttribute]) { @@ -566,8 +566,8 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of return NSAccessibilityUnignoredAncestor(self); } - int y = qt_mac_flipYCoordinate(point.y); - QAccessibleInterface *childInterface = iface->childAt(point.x, y); + QPointF screenPoint = QCocoaScreen::mapFromNative(point); + QAccessibleInterface *childInterface = iface->childAt(screenPoint.x(), screenPoint.y()); // No child found, meaning we hit this element. if (!childInterface || !childInterface->isValid()) return NSAccessibilityUnignoredAncestor(self); @@ -575,7 +575,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of // find the deepest child at the point QAccessibleInterface *childOfChildInterface = 0; do { - childOfChildInterface = childInterface->childAt(point.x, y); + childOfChildInterface = childInterface->childAt(screenPoint.x(), screenPoint.y()); if (childOfChildInterface && childOfChildInterface->isValid()) childInterface = childOfChildInterface; } while (childOfChildInterface && childOfChildInterface->isValid()); diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 5392804d62..32be9ad4ee 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -86,16 +86,21 @@ QT_USE_NAMESPACE -QT_BEGIN_NAMESPACE -static QCocoaApplicationDelegate *sharedCocoaApplicationDelegate = nil; +@implementation QCocoaApplicationDelegate -static void cleanupCocoaApplicationDelegate() ++ (instancetype)sharedDelegate { - [sharedCocoaApplicationDelegate release]; + static QCocoaApplicationDelegate *shared = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shared = [[self alloc] init]; + atexit_b(^{ + [shared release]; + shared = nil; + }); + }); + return shared; } -QT_END_NAMESPACE - -@implementation QCocoaApplicationDelegate - (id)init { @@ -120,7 +125,6 @@ QT_END_NAMESPACE - (void)dealloc { - sharedCocoaApplicationDelegate = nil; [dockMenu release]; if (reflectionDelegate) { [[NSApplication sharedApplication] setDelegate:reflectionDelegate]; @@ -131,27 +135,6 @@ QT_END_NAMESPACE [super dealloc]; } -+ (id)allocWithZone:(NSZone *)zone -{ - @synchronized(self) { - if (sharedCocoaApplicationDelegate == nil) { - sharedCocoaApplicationDelegate = [super allocWithZone:zone]; - qAddPostRoutine(cleanupCocoaApplicationDelegate); - return sharedCocoaApplicationDelegate; - } - } - return nil; -} - -+ (QCocoaApplicationDelegate *)sharedDelegate -{ - @synchronized(self) { - if (sharedCocoaApplicationDelegate == nil) - [[self alloc] init]; - } - return [[sharedCocoaApplicationDelegate retain] autorelease]; -} - - (void)setDockMenu:(NSMenu*)newMenu { [newMenu retain]; diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h index a0bc204013..b4cd506513 100644 --- a/src/plugins/platforms/cocoa/qcocoabackingstore.h +++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h @@ -52,11 +52,11 @@ public: QCocoaBackingStore(QWindow *window); ~QCocoaBackingStore(); - void flush(QWindow *, const QRegion &, const QPoint &) Q_DECL_OVERRIDE; + void flush(QWindow *, const QRegion &, const QPoint &) override; private: bool windowHasUnifiedToolbar() const; - QImage::Format format() const Q_DECL_OVERRIDE; + QImage::Format format() const override; void redrawRoundedBottomCorners(CGRect) const; }; diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.h b/src/plugins/platforms/cocoa/qcocoaclipboard.h index cab2cfaa91..a78d8f4187 100644 --- a/src/plugins/platforms/cocoa/qcocoaclipboard.h +++ b/src/plugins/platforms/cocoa/qcocoaclipboard.h @@ -56,10 +56,10 @@ class QCocoaClipboard : public QObject, public QPlatformClipboard public: QCocoaClipboard(); - QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE; - void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE; - bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE; - bool ownsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE; + QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) override; + void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard) override; + bool supportsMode(QClipboard::Mode mode) const override; + bool ownsMode(QClipboard::Mode mode) const override; private Q_SLOTS: void handleApplicationStateChanged(Qt::ApplicationState state); diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h index 133efd6db8..01ac7e181d 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.h @@ -55,12 +55,12 @@ public: QCocoaColorDialogHelper(); ~QCocoaColorDialogHelper(); - void exec() Q_DECL_OVERRIDE; - bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE; - void hide() Q_DECL_OVERRIDE; + void exec() override; + bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override; + void hide() override; - void setCurrentColor(const QColor&) Q_DECL_OVERRIDE; - QColor currentColor() const Q_DECL_OVERRIDE; + void setCurrentColor(const QColor&) override; + QColor currentColor() const override; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoacursor.h b/src/plugins/platforms/cocoa/qcocoacursor.h index d1586660a4..58b9ef2151 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.h +++ b/src/plugins/platforms/cocoa/qcocoacursor.h @@ -53,9 +53,9 @@ public: QCocoaCursor(); ~QCocoaCursor(); - void changeCursor(QCursor *cursor, QWindow *window) Q_DECL_OVERRIDE; - QPoint pos() const Q_DECL_OVERRIDE; - void setPos(const QPoint &position) Q_DECL_OVERRIDE; + void changeCursor(QCursor *cursor, QWindow *window) override; + QPoint pos() const override; + void setPos(const QPoint &position) override; private: QHash<Qt::CursorShape, NSCursor *> m_cursors; NSCursor *convertCursor(QCursor *cursor); diff --git a/src/plugins/platforms/cocoa/qcocoacursor.mm b/src/plugins/platforms/cocoa/qcocoacursor.mm index 99a136d384..c021128e4c 100644 --- a/src/plugins/platforms/cocoa/qcocoacursor.mm +++ b/src/plugins/platforms/cocoa/qcocoacursor.mm @@ -39,6 +39,7 @@ #include "qcocoacursor.h" #include "qcocoawindow.h" +#include "qcocoascreen.h" #include "qcocoahelpers.h" #include <QtGui/private/qcoregraphics_p.h> @@ -70,7 +71,7 @@ void QCocoaCursor::changeCursor(QCursor *cursor, QWindow *window) QPoint QCocoaCursor::pos() const { - return qt_mac_flipPoint([NSEvent mouseLocation]).toPoint(); + return QCocoaScreen::mapFromNative([NSEvent mouseLocation]).toPoint(); } void QCocoaCursor::setPos(const QPoint &position) @@ -86,7 +87,7 @@ void QCocoaCursor::setPos(const QPoint &position) NSCursor *QCocoaCursor::convertCursor(QCursor *cursor) { - if (cursor == Q_NULLPTR) + if (cursor == nullptr) return 0; const Qt::CursorShape newShape = cursor->shape(); diff --git a/src/plugins/platforms/cocoa/qcocoadrag.h b/src/plugins/platforms/cocoa/qcocoadrag.h index c7277a47bf..dc0cc17dfb 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.h +++ b/src/plugins/platforms/cocoa/qcocoadrag.h @@ -56,10 +56,10 @@ public: ~QCocoaDrag(); QMimeData *dragMimeData(); - Qt::DropAction drag(QDrag *m_drag) Q_DECL_OVERRIDE; + Qt::DropAction drag(QDrag *m_drag) override; Qt::DropAction defaultAction(Qt::DropActions possibleActions, - Qt::KeyboardModifiers modifiers) const Q_DECL_OVERRIDE; + Qt::KeyboardModifiers modifiers) const override; /** * to meet NSView dragImage:at guarantees, we need to record the original diff --git a/src/plugins/platforms/cocoa/qcocoadrag.mm b/src/plugins/platforms/cocoa/qcocoadrag.mm index 3bd0b05725..e1f36b47a1 100644 --- a/src/plugins/platforms/cocoa/qcocoadrag.mm +++ b/src/plugins/platforms/cocoa/qcocoadrag.mm @@ -188,7 +188,7 @@ QPixmap QCocoaDrag::dragPixmap(QDrag *drag, QPoint &hotSpot) const if (s.length() > dragImageMaxChars) s = s.left(dragImageMaxChars -3) + QChar(0x2026); if (!s.isEmpty()) { - const int width = fm.width(s); + const int width = fm.horizontalAdvance(s); const int height = fm.height(); if (width > 0 && height > 0) { qreal dpr = 1.0; diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h index f5ba1dc22e..2ddda14289 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.h @@ -59,19 +59,19 @@ public: QCocoaFileDialogHelper(); virtual ~QCocoaFileDialogHelper(); - void exec() Q_DECL_OVERRIDE; + void exec() override; - bool defaultNameFilterDisables() const Q_DECL_OVERRIDE; + bool defaultNameFilterDisables() const override; - bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE; - void hide() Q_DECL_OVERRIDE; - void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; - QUrl directory() const Q_DECL_OVERRIDE; - void selectFile(const QUrl &filename) Q_DECL_OVERRIDE; - QList<QUrl> selectedFiles() const Q_DECL_OVERRIDE; - void setFilter() Q_DECL_OVERRIDE; - void selectNameFilter(const QString &filter) Q_DECL_OVERRIDE; - QString selectedNameFilter() const Q_DECL_OVERRIDE; + bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override; + void hide() override; + void setDirectory(const QUrl &directory) override; + QUrl directory() const override; + void selectFile(const QUrl &filename) override; + QList<QUrl> selectedFiles() const override; + void setFilter() override; + void selectNameFilter(const QString &filter) override; + QString selectedNameFilter() const override; public: bool showCocoaFilePanel(Qt::WindowModality windowModality, QWindow *parent); diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm index fa123550ef..7ea3d130f7 100644 --- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm @@ -63,7 +63,8 @@ #include <qsysinfo.h> #include <qoperatingsystemversion.h> #include <qglobal.h> -#include <QDir> +#include <qdir.h> +#include <qregularexpression.h> #include <qpa/qplatformnativeinterface.h> @@ -509,9 +510,10 @@ static QString strippedText(QString s) - (QString)removeExtensions:(const QString &)filter { - QRegExp regExp(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp)); - if (regExp.indexIn(filter) != -1) - return regExp.cap(1).trimmed(); + QRegularExpression regExp(QString::fromLatin1(QPlatformFileDialogHelper::filterRegExp)); + QRegularExpressionMatch match = regExp.match(filter); + if (match.hasMatch()) + return match.captured(1).trimmed(); return filter; } diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h index c3fad7cfd6..14f12f2d76 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.h @@ -54,13 +54,13 @@ public: QCocoaFontDialogHelper(); ~QCocoaFontDialogHelper(); - void exec() Q_DECL_OVERRIDE; + void exec() override; - bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) Q_DECL_OVERRIDE; - void hide() Q_DECL_OVERRIDE; + bool show(Qt::WindowFlags windowFlags, Qt::WindowModality windowModality, QWindow *parent) override; + void hide() override; - void setCurrentFont(const QFont &) Q_DECL_OVERRIDE; - QFont currentFont() const Q_DECL_OVERRIDE; + void setCurrentFont(const QFont &) override; + QFont currentFont() const override; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaglcontext.h b/src/plugins/platforms/cocoa/qcocoaglcontext.h index 732b50d29e..0530aa8201 100644 --- a/src/plugins/platforms/cocoa/qcocoaglcontext.h +++ b/src/plugins/platforms/cocoa/qcocoaglcontext.h @@ -55,22 +55,22 @@ public: QCocoaGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, const QVariant &nativeHandle); ~QCocoaGLContext(); - QSurfaceFormat format() const Q_DECL_OVERRIDE; + QSurfaceFormat format() const override; - void swapBuffers(QPlatformSurface *surface) Q_DECL_OVERRIDE; + void swapBuffers(QPlatformSurface *surface) override; - bool makeCurrent(QPlatformSurface *surface) Q_DECL_OVERRIDE; - void doneCurrent() Q_DECL_OVERRIDE; + bool makeCurrent(QPlatformSurface *surface) override; + void doneCurrent() override; - QFunctionPointer getProcAddress(const char *procName) Q_DECL_OVERRIDE; + QFunctionPointer getProcAddress(const char *procName) override; void update(); static NSOpenGLPixelFormat *createNSOpenGLPixelFormat(const QSurfaceFormat &format); NSOpenGLContext *nsOpenGLContext() const; - bool isSharing() const Q_DECL_OVERRIDE; - bool isValid() const Q_DECL_OVERRIDE; + bool isSharing() const override; + bool isValid() const override; void windowWasHidden(); diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.h b/src/plugins/platforms/cocoa/qcocoahelpers.h index 7ce247f861..2c4783b1e3 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.h +++ b/src/plugins/platforms/cocoa/qcocoahelpers.h @@ -85,13 +85,8 @@ QT_MANGLE_NAMESPACE(QNSView) *qnsview_cast(NSView *view); void qt_mac_transformProccessToForegroundApplication(); QString qt_mac_applicationName(); -int qt_mac_flipYCoordinate(int y); -qreal qt_mac_flipYCoordinate(qreal y); -QPointF qt_mac_flipPoint(const NSPoint &p); -NSPoint qt_mac_flipPoint(const QPoint &p); -NSPoint qt_mac_flipPoint(const QPointF &p); - -NSRect qt_mac_flipRect(const QRect &rect); +QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference); +QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference); Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum); @@ -196,6 +191,19 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QNSPanelContentsWrapper); // ------------------------------------------------------------------------- +// QAppleRefCounted expects the retain function to return the object +io_object_t q_IOObjectRetain(io_object_t obj); +// QAppleRefCounted expects the release function to return void +void q_IOObjectRelease(io_object_t obj); + +template <typename T> +class QIOType : public QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease> +{ + using QAppleRefCounted<T, io_object_t, q_IOObjectRetain, q_IOObjectRelease>::QAppleRefCounted; +}; + +// ------------------------------------------------------------------------- + // Depending on the ABI of the platform, we may need to use objc_msgSendSuper_stret: // - http://www.sealiesoftware.com/blog/archive/2008/10/30/objc_explain_objc_msgSend_stret.html // - https://lists.apple.com/archives/cocoa-dev/2008/Feb/msg02338.html diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 0380e0e79d..fdf4733f0e 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -232,50 +232,37 @@ QString qt_mac_applicationName() return appName; } -int qt_mac_primaryScreenHeight() -{ - QMacAutoReleasePool pool; - NSArray *screens = [NSScreen screens]; - if ([screens count] > 0) { - // The first screen in the screens array is documented to - // have the (0,0) origin and is designated the primary screen. - NSRect screenFrame = [[screens objectAtIndex: 0] frame]; - return screenFrame.size.height; - } - return 0; -} +// ------------------------------------------------------------------------- -int qt_mac_flipYCoordinate(int y) -{ - return qt_mac_primaryScreenHeight() - y; -} +/*! + \fn QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference) + \fn QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference) -qreal qt_mac_flipYCoordinate(qreal y) -{ - return qt_mac_primaryScreenHeight() - y; -} + Flips the Y coordinate of the point/rect between quadrant I and IV. -QPointF qt_mac_flipPoint(const NSPoint &p) -{ - return QPointF(p.x, qt_mac_flipYCoordinate(p.y)); -} + The native coordinate system on macOS uses quadrant I, with origin + in bottom left, and Qt uses quadrant IV, with origin in top left. -NSPoint qt_mac_flipPoint(const QPoint &p) -{ - return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y())); -} + By flipping the Y coordinate, we can map the point/rect between + the two coordinate systems. -NSPoint qt_mac_flipPoint(const QPointF &p) + The flip is always in relation to a reference rectangle, e.g. + the frame of the parent view, or the screen geometry. In the + latter case the specialized QCocoaScreen::mapFrom/To functions + should be used instead. +*/ +QPointF qt_mac_flip(const QPointF &pos, const QRectF &reference) { - return NSMakePoint(p.x(), qt_mac_flipYCoordinate(p.y())); + return QPointF(pos.x(), reference.height() - pos.y()); } -NSRect qt_mac_flipRect(const QRect &rect) +QRectF qt_mac_flip(const QRectF &rect, const QRectF &reference) { - int flippedY = qt_mac_flipYCoordinate(rect.y() + rect.height()); - return NSMakeRect(rect.x(), flippedY, rect.width(), rect.height()); + return QRectF(qt_mac_flip(rect.bottomLeft(), reference), rect.size()); } +// ------------------------------------------------------------------------- + Qt::MouseButton cocoaButton2QtButton(NSInteger buttonNum) { if (buttonNum >= 0 && buttonNum <= 31) @@ -408,4 +395,19 @@ QT_END_NAMESPACE [super layout]; } +// ------------------------------------------------------------------------- + +io_object_t q_IOObjectRetain(io_object_t obj) +{ + kern_return_t ret = IOObjectRetain(obj); + Q_ASSERT(!ret); + return obj; +} + +void q_IOObjectRelease(io_object_t obj) +{ + kern_return_t ret = IOObjectRelease(obj); + Q_ASSERT(!ret); +} + @end diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.h b/src/plugins/platforms/cocoa/qcocoainputcontext.h index a248ca0d8d..7190ba0de8 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.h +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.h @@ -53,11 +53,11 @@ public: explicit QCocoaInputContext(); ~QCocoaInputContext(); - bool isValid() const Q_DECL_OVERRIDE { return true; } + bool isValid() const override { return true; } - void reset() Q_DECL_OVERRIDE; + void reset() override; - QLocale locale() const Q_DECL_OVERRIDE { return m_locale; } + QLocale locale() const override { return m_locale; } void updateLocale(); private Q_SLOTS: diff --git a/src/plugins/platforms/cocoa/qcocoainputcontext.mm b/src/plugins/platforms/cocoa/qcocoainputcontext.mm index 9221099a57..d0baea5b36 100644 --- a/src/plugins/platforms/cocoa/qcocoainputcontext.mm +++ b/src/plugins/platforms/cocoa/qcocoainputcontext.mm @@ -129,6 +129,8 @@ void QCocoaInputContext::focusObjectChanged(QObject *focusObject) return; QCocoaWindow *window = static_cast<QCocoaWindow *>(mWindow->handle()); + if (!window) + return; QNSView *view = qnsview_cast(window->view()); if (!view) return; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index 2fc5156d24..301771fd53 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -75,35 +75,35 @@ public: static QCocoaIntegration *instance(); Options options() const; - bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; - QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const Q_DECL_OVERRIDE; + bool hasCapability(QPlatformIntegration::Capability cap) const override; + QPlatformWindow *createPlatformWindow(QWindow *window) const override; + QPlatformWindow *createForeignWindow(QWindow *window, WId nativeHandle) const override; QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const override; #ifndef QT_NO_OPENGL - QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; + QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const override; #endif - QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const Q_DECL_OVERRIDE; + QPlatformBackingStore *createPlatformBackingStore(QWindow *widget) const override; - QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; + QAbstractEventDispatcher *createEventDispatcher() const override; - QCoreTextFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; - QCocoaNativeInterface *nativeInterface() const Q_DECL_OVERRIDE; - QPlatformInputContext *inputContext() const Q_DECL_OVERRIDE; + QCoreTextFontDatabase *fontDatabase() const override; + QCocoaNativeInterface *nativeInterface() const override; + QPlatformInputContext *inputContext() const override; #ifndef QT_NO_ACCESSIBILITY - QCocoaAccessibility *accessibility() const Q_DECL_OVERRIDE; + QCocoaAccessibility *accessibility() const override; #endif #ifndef QT_NO_CLIPBOARD - QCocoaClipboard *clipboard() const Q_DECL_OVERRIDE; + QCocoaClipboard *clipboard() const override; #endif - QCocoaDrag *drag() const Q_DECL_OVERRIDE; + QCocoaDrag *drag() const override; - QStringList themeNames() const Q_DECL_OVERRIDE; - QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE; - QCocoaServices *services() const Q_DECL_OVERRIDE; - QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE; + QStringList themeNames() const override; + QPlatformTheme *createPlatformTheme(const QString &name) const override; + QCocoaServices *services() const override; + QVariant styleHint(StyleHint hint) const override; - Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE; - QList<int> possibleKeys(const QKeyEvent *event) const Q_DECL_OVERRIDE; + Qt::KeyboardModifiers queryKeyboardModifiers() const override; + QList<int> possibleKeys(const QKeyEvent *event) const override; void updateScreens(); QCocoaScreen *screenForNSScreen(NSScreen *nsScreen); @@ -117,9 +117,9 @@ public: QCocoaWindow *activePopupWindow() const; QList<QCocoaWindow *> *popupWindowStack(); - void setApplicationIcon(const QIcon &icon) const Q_DECL_OVERRIDE; + void setApplicationIcon(const QIcon &icon) const override; - void beep() const Q_DECL_OVERRIDE; + void beep() const override; private Q_SLOTS: void focusWindowChanged(QWindow *); diff --git a/src/plugins/platforms/cocoa/qcocoamenu.h b/src/plugins/platforms/cocoa/qcocoamenu.h index 5081fc78c6..2b4cf0ef98 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.h +++ b/src/plugins/platforms/cocoa/qcocoamenu.h @@ -45,6 +45,8 @@ #include <qpa/qplatformmenu.h> #include "qcocoamenuitem.h" +Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaNSMenu)); + QT_BEGIN_NAMESPACE class QCocoaMenuBar; @@ -55,32 +57,31 @@ public: QCocoaMenu(); ~QCocoaMenu(); - void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) Q_DECL_OVERRIDE; - void removeMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE; - void syncMenuItem(QPlatformMenuItem *menuItem) Q_DECL_OVERRIDE; - void setEnabled(bool enabled) Q_DECL_OVERRIDE; - bool isEnabled() const Q_DECL_OVERRIDE; - void setVisible(bool visible) Q_DECL_OVERRIDE; - void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) Q_DECL_OVERRIDE; - void dismiss() Q_DECL_OVERRIDE; + void insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) override; + void removeMenuItem(QPlatformMenuItem *menuItem) override; + void syncMenuItem(QPlatformMenuItem *menuItem) override; + void setEnabled(bool enabled) override; + bool isEnabled() const override; + void setVisible(bool visible) override; + void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item) override; + void dismiss() override; - void syncSeparatorsCollapsible(bool enable) Q_DECL_OVERRIDE; + void syncSeparatorsCollapsible(bool enable) override; void propagateEnabledState(bool enabled); - void setIcon(const QIcon &icon) Q_DECL_OVERRIDE { Q_UNUSED(icon) } + void setIcon(const QIcon &icon) override { Q_UNUSED(icon) } - void setText(const QString &text) Q_DECL_OVERRIDE; - void setMinimumWidth(int width) Q_DECL_OVERRIDE; - void setFont(const QFont &font) Q_DECL_OVERRIDE; + void setText(const QString &text) override; + void setMinimumWidth(int width) override; + void setFont(const QFont &font) override; - inline NSMenu *nsMenu() const - { return m_nativeMenu; } + NSMenu *nsMenu() const; inline bool isVisible() const { return m_visible; } - QPlatformMenuItem *menuItemAt(int position) const Q_DECL_OVERRIDE; - QPlatformMenuItem *menuItemForTag(quintptr tag) const Q_DECL_OVERRIDE; + QPlatformMenuItem *menuItemAt(int position) const override; + QPlatformMenuItem *menuItemForTag(quintptr tag) const override; QList<QCocoaMenuItem *> items() const; QList<QCocoaMenuItem *> merged() const; @@ -91,7 +92,7 @@ public: bool isOpen() const; void setIsOpen(bool isOpen); - void timerEvent(QTimerEvent *e) Q_DECL_OVERRIDE; + void timerEvent(QTimerEvent *e) override; void syncMenuItem_helper(QPlatformMenuItem *menuItem, bool menubarUpdate); @@ -101,7 +102,7 @@ private: void scheduleUpdate(); QList<QCocoaMenuItem *> m_menuItems; - NSMenu *m_nativeMenu; + QT_MANGLE_NAMESPACE(QCocoaNSMenu) *m_nativeMenu; NSMenuItem *m_attachedItem; int m_updateTimer; bool m_enabled:1; diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm index 1345295ef5..7a550b163b 100644 --- a/src/plugins/platforms/cocoa/qcocoamenu.mm +++ b/src/plugins/platforms/cocoa/qcocoamenu.mm @@ -38,234 +38,15 @@ ****************************************************************************/ #include "qcocoamenu.h" +#include "qcocoansmenu.h" #include "qcocoahelpers.h" #include <QtCore/QtDebug> -#include <QtCore/qmetaobject.h> -#include <QtCore/private/qthread_p.h> -#include <QtGui/private/qguiapplication_p.h> #include "qcocoaapplication.h" #include "qcocoamenuloader.h" #include "qcocoamenubar.h" #include "qcocoawindow.h" -#import "qnsview.h" - -QT_BEGIN_NAMESPACE - -NSString *qt_mac_removePrivateUnicode(NSString* string) -{ - int len = [string length]; - if (len) { - QVarLengthArray <unichar, 10> characters(len); - bool changed = false; - for (int i = 0; i<len; i++) { - characters[i] = [string characterAtIndex:i]; - // check if they belong to key codes in private unicode range - // currently we need to handle only the NSDeleteFunctionKey - if (characters[i] == NSDeleteFunctionKey) { - characters[i] = NSDeleteCharacter; - changed = true; - } - } - if (changed) - return [NSString stringWithCharacters:characters.data() length:len]; - } - return string; -} - -QT_END_NAMESPACE - -@interface QT_MANGLE_NAMESPACE(QCocoaMenuDelegate) : NSObject <NSMenuDelegate> { - QCocoaMenu *m_menu; -} - -- (id) initWithMenu:(QCocoaMenu*) m; -- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier; - -@end - -QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaMenuDelegate); - -@implementation QCocoaMenuDelegate - -- (id) initWithMenu:(QCocoaMenu*) m -{ - if ((self = [super init])) - m_menu = m; - - return self; -} - -- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu -{ - Q_ASSERT(m_menu->nsMenu() == menu); - return menu.numberOfItems; -} - -- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel -{ - Q_UNUSED(index); - Q_ASSERT(m_menu->nsMenu() == menu); - if (shouldCancel) { - // TODO detach all submenus - return NO; - } - - QCocoaMenuItem *menuItem = reinterpret_cast<QCocoaMenuItem *>(item.tag); - if (m_menu->items().contains(menuItem)) { - if (QCocoaMenu *itemSubmenu = menuItem->menu()) - itemSubmenu->setAttachedItem(item); - } - return YES; -} - -- (void)menu:(NSMenu*)menu willHighlightItem:(NSMenuItem*)item -{ - Q_UNUSED(menu); - if (item && [item tag]) { - QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([item tag]); - cocoaItem->hovered(); - } -} - -- (void) menuWillOpen:(NSMenu*)m -{ - Q_UNUSED(m); - m_menu->setIsOpen(true); - emit m_menu->aboutToShow(); -} - -- (void) menuDidClose:(NSMenu*)m -{ - Q_UNUSED(m); - m_menu->setIsOpen(false); - // wrong, but it's the best we can do - emit m_menu->aboutToHide(); -} - -- (void) itemFired:(NSMenuItem*) item -{ - QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>([item tag]); - // Menu-holding items also get a target to play nicely - // with NSMenuValidation but should not trigger. - if (cocoaItem->menu()) - return; - QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData); - QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]]; - static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated); - activatedSignal.invoke(cocoaItem, Qt::QueuedConnection); -} - -- (BOOL)validateMenuItem:(NSMenuItem*)menuItem -{ - QCocoaMenuItem *cocoaItem = reinterpret_cast<QCocoaMenuItem *>(menuItem.tag); - // Menu-holding items are always enabled, as it's conventional in Cocoa - if (!cocoaItem || cocoaItem->menu()) - return YES; - - return cocoaItem->isEnabled(); -} - -- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action -{ - /* - Check if the menu actually has a keysequence defined for this key event. - If it does, then we will first send the key sequence to the QWidget that has focus - since (in Qt's eyes) it needs to a chance at the key event first (QEvent::ShortcutOverride). - If the widget accepts the key event, we then return YES, but set the target and action to be nil, - which means that the action should not be triggered, and instead dispatch the event ourselves. - In every other case we return NO, which means that Cocoa can do as it pleases - (i.e., fire the menu action). - */ - - // Change the private unicode keys to the ones used in setting the "Key Equivalents" - NSString *characters = qt_mac_removePrivateUnicode([event characters]); - // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ... - const NSUInteger mask = NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask; - if (NSMenuItem *menuItem = [self findItem:menu forKey:characters forModifiers:([event modifierFlags] & mask)]) { - if (!menuItem.target) { - // This item was modified by QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder - // and it looks like we're running a modal session for NSOpenPanel/NSSavePanel. - // QCocoaFileDialogHelper is actually the only place we use this and we run NSOpenPanel modal - // (modal sheet, window modal, application modal). - // Whatever the current first responder is, let's give it a chance - // and do not touch the Qt's focusObject (which is different from some native view - // having a focus inside NSSave/OpenPanel. - *target = nil; - *action = menuItem.action; - return YES; - } - - QObject *object = qApp->focusObject(); - if (object) { - QChar ch; - int keyCode; - ulong nativeModifiers = [event modifierFlags]; - Qt::KeyboardModifiers modifiers = [QNSView convertKeyModifiers: nativeModifiers]; - NSString *charactersIgnoringModifiers = [event charactersIgnoringModifiers]; - NSString *characters = [event characters]; - - if ([charactersIgnoringModifiers length] > 0) { // convert the first character into a key code - if ((modifiers & Qt::ControlModifier) && ([characters length] != 0)) { - ch = QChar([characters characterAtIndex:0]); - } else { - ch = QChar([charactersIgnoringModifiers characterAtIndex:0]); - } - keyCode = qt_mac_cocoaKey2QtKey(ch); - } else { - // might be a dead key - ch = QChar::ReplacementCharacter; - keyCode = Qt::Key_unknown; - } - - QKeyEvent accel_ev(QEvent::ShortcutOverride, (keyCode & (~Qt::KeyboardModifierMask)), - Qt::KeyboardModifiers(modifiers & Qt::KeyboardModifierMask)); - accel_ev.ignore(); - QCoreApplication::sendEvent(object, &accel_ev); - if (accel_ev.isAccepted()) { - [[NSApp keyWindow] sendEvent: event]; - *target = nil; - *action = nil; - return YES; - } - } - } - return NO; -} - -- (NSMenuItem *)findItem:(NSMenu *)menu forKey:(NSString *)key forModifiers:(NSUInteger)modifier -{ - for (NSMenuItem *item in [menu itemArray]) { - if (![item isEnabled] || [item isHidden] || [item isSeparatorItem]) - continue; - if ([item hasSubmenu]) { - if (NSMenuItem *nested = [self findItem:[item submenu] forKey:key forModifiers:modifier]) - return nested; - } - - NSString *menuKey = [item keyEquivalent]; - if (menuKey - && NSOrderedSame == [menuKey compare:key] - && modifier == [item keyEquivalentModifierMask]) - return item; - } - return nil; -} - -// Cocoa will query the menu item's target for the worksWhenModal selector. -// So we need to implement this to allow the items to be handled correctly -// when a modal dialog is visible. -- (BOOL)worksWhenModal -{ - if (!QGuiApplication::modalWindow()) - return YES; - if (auto *mb = qobject_cast<QCocoaMenuBar *>(m_menu->menuParent())) - return QGuiApplication::modalWindow()->handle() == mb->cocoaWindow() ? YES : NO; - return YES; -} - -@end QT_BEGIN_NAMESPACE @@ -279,9 +60,7 @@ QCocoaMenu::QCocoaMenu() : { QMacAutoReleasePool pool; - m_nativeMenu = [[NSMenu alloc] initWithTitle:@"Untitled"]; - [m_nativeMenu setAutoenablesItems:YES]; - m_nativeMenu.delegate = [[QCocoaMenuDelegate alloc] initWithMenu:this]; + m_nativeMenu = [[QCocoaNSMenu alloc] initWithQPAMenu:this]; } QCocoaMenu::~QCocoaMenu() @@ -291,10 +70,6 @@ QCocoaMenu::~QCocoaMenu() item->setMenuParent(0); } - QMacAutoReleasePool pool; - NSObject *delegate = m_nativeMenu.delegate; - m_nativeMenu.delegate = nil; - [delegate release]; [m_nativeMenu release]; } @@ -319,6 +94,11 @@ void QCocoaMenu::setFont(const QFont &font) } } +NSMenu *QCocoaMenu::nsMenu() const +{ + return static_cast<NSMenu *>(m_nativeMenu); +} + void QCocoaMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatformMenuItem *before) { QMacAutoReleasePool pool; diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.h b/src/plugins/platforms/cocoa/qcocoamenubar.h index a259147247..6f3aca3a51 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.h +++ b/src/plugins/platforms/cocoa/qcocoamenubar.h @@ -56,11 +56,11 @@ public: QCocoaMenuBar(); ~QCocoaMenuBar(); - void insertMenu(QPlatformMenu *menu, QPlatformMenu* before) Q_DECL_OVERRIDE; - void removeMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE; - void syncMenu(QPlatformMenu *menuItem) Q_DECL_OVERRIDE; - void handleReparent(QWindow *newParentWindow) Q_DECL_OVERRIDE; - QPlatformMenu *menuForTag(quintptr tag) const Q_DECL_OVERRIDE; + void insertMenu(QPlatformMenu *menu, QPlatformMenu* before) override; + void removeMenu(QPlatformMenu *menu) override; + void syncMenu(QPlatformMenu *menuItem) override; + void handleReparent(QWindow *newParentWindow) override; + QPlatformMenu *menuForTag(quintptr tag) const override; inline NSMenu *nsMenu() const { return m_nativeMenu; } diff --git a/src/plugins/platforms/cocoa/qcocoamenubar.mm b/src/plugins/platforms/cocoa/qcocoamenubar.mm index cf9553bcf7..8091d00bda 100644 --- a/src/plugins/platforms/cocoa/qcocoamenubar.mm +++ b/src/plugins/platforms/cocoa/qcocoamenubar.mm @@ -449,7 +449,7 @@ NSMenuItem *QCocoaMenuBar::itemForRole(QPlatformMenuItem::MenuRole r) foreach (QCocoaMenuItem *i, m->items()) if (i->effectiveRole() == r) return i->nsItem(); - return Q_NULLPTR; + return nullptr; } QCocoaWindow *QCocoaMenuBar::cocoaWindow() const diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.h b/src/plugins/platforms/cocoa/qcocoamenuitem.h index 53862d0484..2b598ee3a0 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.h +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.h @@ -78,22 +78,22 @@ public: QCocoaMenuItem(); ~QCocoaMenuItem(); - void setText(const QString &text) Q_DECL_OVERRIDE; - void setIcon(const QIcon &icon) Q_DECL_OVERRIDE; - void setMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE; - void setVisible(bool isVisible) Q_DECL_OVERRIDE; - void setIsSeparator(bool isSeparator) Q_DECL_OVERRIDE; - void setFont(const QFont &font) Q_DECL_OVERRIDE; - void setRole(MenuRole role) Q_DECL_OVERRIDE; + void setText(const QString &text) override; + void setIcon(const QIcon &icon) override; + void setMenu(QPlatformMenu *menu) override; + void setVisible(bool isVisible) override; + void setIsSeparator(bool isSeparator) override; + void setFont(const QFont &font) override; + void setRole(MenuRole role) override; #ifndef QT_NO_SHORTCUT - void setShortcut(const QKeySequence& shortcut) Q_DECL_OVERRIDE; + void setShortcut(const QKeySequence& shortcut) override; #endif - void setCheckable(bool checkable) Q_DECL_OVERRIDE { Q_UNUSED(checkable) } - void setChecked(bool isChecked) Q_DECL_OVERRIDE; - void setEnabled(bool isEnabled) Q_DECL_OVERRIDE; - void setIconSize(int size) Q_DECL_OVERRIDE; + void setCheckable(bool checkable) override { Q_UNUSED(checkable) } + void setChecked(bool isChecked) override; + void setEnabled(bool isEnabled) override; + void setIconSize(int size) override; - void setNativeContents(WId item) Q_DECL_OVERRIDE; + void setNativeContents(WId item) override; inline QString text() const { return m_text; } inline NSMenuItem * nsItem() { return m_native; } diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm index eaf310ec51..f8f9648822 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm @@ -49,6 +49,7 @@ #include "qcocoaapplication.h" // for custom application category #include "qcocoamenuloader.h" #include <QtGui/private/qcoregraphics_p.h> +#include <QtCore/qregularexpression.h> #include <QtCore/QDebug> @@ -261,7 +262,8 @@ NSMenuItem *QCocoaMenuItem::sync() m_detectedRole = detectMenuRole(m_text); switch (m_detectedRole) { case QPlatformMenuItem::AboutRole: - if (m_text.indexOf(QRegExp(QString::fromLatin1("qt$"), Qt::CaseInsensitive)) == -1) + if (m_text.indexOf(QRegularExpression(QString::fromLatin1("qt$"), + QRegularExpression::CaseInsensitiveOption)) == -1) mergeItem = [loader aboutMenuItem]; else mergeItem = [loader aboutQtMenuItem]; diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index b986833f6d..cd597da71c 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -57,8 +57,12 @@ static QCocoaMenuLoader *shared = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ - shared = [[self alloc] init]; - }); + shared = [[self alloc] init]; + atexit_b(^{ + [shared release]; + shared = nil; + }); + }); return shared; } diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.h b/src/plugins/platforms/cocoa/qcocoanativeinterface.h index 26fbe3e4bc..c78f1d5a7f 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.h +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.h @@ -60,18 +60,18 @@ public: QCocoaNativeInterface(); #ifndef QT_NO_OPENGL - void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) Q_DECL_OVERRIDE; + void *nativeResourceForContext(const QByteArray &resourceString, QOpenGLContext *context) override; #endif - void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) Q_DECL_OVERRIDE; + void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) override; - NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) Q_DECL_OVERRIDE; + NativeResourceForIntegrationFunction nativeResourceFunctionForIntegration(const QByteArray &resource) override; #ifndef QT_NO_OPENGL static void *cglContextForContext(QOpenGLContext *context); static void *nsOpenGLContextForContext(QOpenGLContext* context); #endif - QFunctionPointer platformFunction(const QByteArray &function) const Q_DECL_OVERRIDE; + QFunctionPointer platformFunction(const QByteArray &function) const override; public Q_SLOTS: void onAppFocusWindowChanged(QWindow *window); diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 58cfcd3c42..955b147bfd 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -233,7 +233,7 @@ QFunctionPointer QCocoaNativeInterface::platformFunction(const QByteArray &funct if (function == QCocoaWindowFunctions::bottomLeftClippedByNSWindowOffsetIdentifier()) return QFunctionPointer(QCocoaWindowFunctions::BottomLeftClippedByNSWindowOffset(QCocoaWindow::bottomLeftClippedByNSWindowOffsetStatic)); - return Q_NULLPTR; + return nullptr; } void QCocoaNativeInterface::addToMimeList(void *macPasteboardMime) diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.h b/src/plugins/platforms/cocoa/qcocoansmenu.h new file mode 100644 index 0000000000..8fb0a26f27 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoansmenu.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOCOANSMENU_H +#define QCOCOANSMENU_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#import <AppKit/AppKit.h> + +#include <QtCore/qpointer.h> +#include <qcocoahelpers.h> + +QT_FORWARD_DECLARE_CLASS(QCocoaMenu); +typedef QPointer<QCocoaMenu> QCocoaMenuPointer; + + +@interface QT_MANGLE_NAMESPACE(QCocoaNSMenuDelegate) : NSObject <NSMenuDelegate> + ++ (instancetype)sharedMenuDelegate; + +- (NSMenuItem *)findItemInMenu:(NSMenu *)menu + forKey:(NSString *)key + modifiers:(NSUInteger)modifiers; + +- (BOOL)validateMenuItem:(NSMenuItem *)item; // NSMenuValidation + +@end + +@interface QT_MANGLE_NAMESPACE(QCocoaNSMenu) : NSMenu + +@property (readonly, nonatomic) QCocoaMenuPointer qpaMenu; + +- (instancetype)initWithQPAMenu:(QCocoaMenu *)menu; + +@end + +QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaNSMenu); +QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaNSMenuDelegate); + +#endif // QCOCOANSMENU_H diff --git a/src/plugins/platforms/cocoa/qcocoansmenu.mm b/src/plugins/platforms/cocoa/qcocoansmenu.mm new file mode 100644 index 0000000000..996a4ff194 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoansmenu.mm @@ -0,0 +1,296 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#import "qcocoansmenu.h" +#include "qcocoamenu.h" +#include "qcocoamenuitem.h" +#import "qnsview.h" + +#include <QtCore/qmetaobject.h> +#include <QtCore/private/qthread_p.h> +#include <QtGui/private/qguiapplication_p.h> + +static NSString *qt_mac_removePrivateUnicode(NSString* string) +{ + int len = [string length]; + if (len) { + QVarLengthArray <unichar, 10> characters(len); + bool changed = false; + for (int i = 0; i<len; i++) { + characters[i] = [string characterAtIndex:i]; + // check if they belong to key codes in private unicode range + // currently we need to handle only the NSDeleteFunctionKey + if (characters[i] == NSDeleteFunctionKey) { + characters[i] = NSDeleteCharacter; + changed = true; + } + } + if (changed) + return [NSString stringWithCharacters:characters.data() length:len]; + } + return string; +} + +@implementation QCocoaNSMenu + +- (instancetype)initWithQPAMenu:(QCocoaMenu *)menu +{ + if ((self = [super initWithTitle:@"Untitled"])) { + _qpaMenu = menu; + self.autoenablesItems = YES; + self.delegate = [QCocoaNSMenuDelegate sharedMenuDelegate]; + } + + return self; +} + +@end + +#define CHECK_MENU_CLASS(menu) Q_ASSERT([menu isMemberOfClass:[QCocoaNSMenu class]]) + +@implementation QCocoaNSMenuDelegate + ++ (instancetype)sharedMenuDelegate +{ + static QCocoaNSMenuDelegate *shared = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shared = [[self alloc] init]; + atexit_b(^{ + [shared release]; + shared = nil; + }); + }); + return shared; +} + +- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu +{ + CHECK_MENU_CLASS(menu); + return menu.numberOfItems; +} + +- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel +{ + Q_UNUSED(index); + CHECK_MENU_CLASS(menu); + + if (shouldCancel) + return NO; + + const auto &qpaMenu = static_cast<QCocoaNSMenu *>(menu).qpaMenu; + if (qpaMenu.isNull()) + return YES; + + auto *menuItem = reinterpret_cast<QCocoaMenuItem *>(item.tag); + if (qpaMenu->items().contains(menuItem)) { + if (QCocoaMenu *itemSubmenu = menuItem->menu()) + itemSubmenu->setAttachedItem(item); + } + + return YES; +} + +- (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item +{ + CHECK_MENU_CLASS(menu); + auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag); + if (qpaItem) + qpaItem->hovered(); +} + +- (void)menuWillOpen:(NSMenu *)menu +{ + CHECK_MENU_CLASS(menu); + const auto &qpaMenu = static_cast<QCocoaNSMenu *>(menu).qpaMenu; + if (qpaMenu.isNull()) + return; + + qpaMenu->setIsOpen(true); + emit qpaMenu->aboutToShow(); +} + +- (void)menuDidClose:(NSMenu *)menu +{ + CHECK_MENU_CLASS(menu); + const auto &qpaMenu = static_cast<QCocoaNSMenu *>(menu).qpaMenu; + if (qpaMenu.isNull()) + return; + + qpaMenu->setIsOpen(false); + // wrong, but it's the best we can do + emit qpaMenu->aboutToHide(); +} + +- (void)itemFired:(NSMenuItem *)item +{ + auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag); + // Menu-holding items also get a target to play nicely + // with NSMenuValidation but should not trigger. + if (!qpaItem || qpaItem->menu()) + return; + + QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData); + QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]]; + + static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated); + activatedSignal.invoke(qpaItem, Qt::QueuedConnection); +} + +- (BOOL)validateMenuItem:(NSMenuItem*)item +{ + auto *qpaItem = reinterpret_cast<QCocoaMenuItem *>(item.tag); + // Menu-holding items are always enabled, as it's conventional in Cocoa + if (!qpaItem || qpaItem->menu()) + return YES; + + return qpaItem->isEnabled(); +} + +- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action +{ + /* + Check if the menu actually has a keysequence defined for this key event. + If it does, then we will first send the key sequence to the QWidget that has focus + since (in Qt's eyes) it needs to a chance at the key event first (QEvent::ShortcutOverride). + If the widget accepts the key event, we then return YES, but set the target and action to be nil, + which means that the action should not be triggered, and instead dispatch the event ourselves. + In every other case we return NO, which means that Cocoa can do as it pleases + (i.e., fire the menu action). + */ + + CHECK_MENU_CLASS(menu); + + // Interested only in Shift, Cmd, Ctrl & Alt Keys, so ignoring masks like, Caps lock, Num Lock ... + static const NSUInteger mask = NSShiftKeyMask | NSControlKeyMask | NSCommandKeyMask | NSAlternateKeyMask; + + // Change the private unicode keys to the ones used in setting the "Key Equivalents" + NSString *characters = qt_mac_removePrivateUnicode(event.charactersIgnoringModifiers); + const auto modifiers = event.modifierFlags & mask; + NSMenuItem *keyEquivalentItem = [self findItemInMenu:menu + forKey:characters + modifiers:modifiers]; + if (!keyEquivalentItem) { + // Maybe the modified character is what we're looking for after all + characters = qt_mac_removePrivateUnicode(event.characters); + keyEquivalentItem = [self findItemInMenu:menu + forKey:characters + modifiers:modifiers]; + } + + if (keyEquivalentItem) { + if (!keyEquivalentItem.target) { + // This item was modified by QCocoaMenuBar::redirectKnownMenuItemsToFirstResponder + // and it looks like we're running a modal session for NSOpenPanel/NSSavePanel. + // QCocoaFileDialogHelper is actually the only place we use this and we run NSOpenPanel modal + // (modal sheet, window modal, application modal). + // Whatever the current first responder is, let's give it a chance + // and do not touch the Qt's focusObject (which is different from some native view + // having a focus inside NSSave/OpenPanel. + *target = nil; + *action = keyEquivalentItem.action; + return YES; + } + + QObject *object = qApp->focusObject(); + if (object) { + QChar ch; + int keyCode; + ulong nativeModifiers = [event modifierFlags]; + Qt::KeyboardModifiers modifiers = [QNSView convertKeyModifiers: nativeModifiers]; + NSString *charactersIgnoringModifiers = [event charactersIgnoringModifiers]; + NSString *characters = [event characters]; + + if ([charactersIgnoringModifiers length] > 0) { // convert the first character into a key code + if ((modifiers & Qt::ControlModifier) && ([characters length] != 0)) { + ch = QChar([characters characterAtIndex:0]); + } else { + ch = QChar([charactersIgnoringModifiers characterAtIndex:0]); + } + keyCode = qt_mac_cocoaKey2QtKey(ch); + } else { + // might be a dead key + ch = QChar::ReplacementCharacter; + keyCode = Qt::Key_unknown; + } + + QKeyEvent accel_ev(QEvent::ShortcutOverride, (keyCode & (~Qt::KeyboardModifierMask)), + Qt::KeyboardModifiers(modifiers & Qt::KeyboardModifierMask)); + accel_ev.ignore(); + QCoreApplication::sendEvent(object, &accel_ev); + if (accel_ev.isAccepted()) { + [[NSApp keyWindow] sendEvent: event]; + *target = nil; + *action = nil; + return YES; + } + } + } + + return NO; +} + +- (NSMenuItem *)findItemInMenu:(NSMenu *)menu + forKey:(NSString *)key + modifiers:(NSUInteger)modifiers +{ + // Find an item in 'menu' that has the same key equivalent as specified by + // 'key' and 'modifiers'. We ignore disabled, hidden and separator items. + // In a similar fashion, we don't need to recurse into submenus because their + // delegate will have [menuHasKeyEquivalent:...] invoked at some point. + + for (NSMenuItem *item in menu.itemArray) { + if (!item.enabled || item.hidden || item.separatorItem) + continue; + + if (item.hasSubmenu) + continue; + + NSString *menuKey = item.keyEquivalent; + if (menuKey && NSOrderedSame == [menuKey compare:key] + && modifiers == item.keyEquivalentModifierMask) + return item; + } + + return nil; +} + +@end + +#undef CHECK_MENU_CLASS diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.h b/src/plugins/platforms/cocoa/qcocoaprintdevice.h index c726cca4e5..20b27f3286 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.h +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.h @@ -68,37 +68,37 @@ public: explicit QCocoaPrintDevice(const QString &id); virtual ~QCocoaPrintDevice(); - bool isValid() const Q_DECL_OVERRIDE; - bool isDefault() const Q_DECL_OVERRIDE; + bool isValid() const override; + bool isDefault() const override; - QPrint::DeviceState state() const Q_DECL_OVERRIDE; + QPrint::DeviceState state() const override; - QPageSize defaultPageSize() const Q_DECL_OVERRIDE; + QPageSize defaultPageSize() const override; QMarginsF printableMargins(const QPageSize &pageSize, QPageLayout::Orientation orientation, - int resolution) const Q_DECL_OVERRIDE; + int resolution) const override; - int defaultResolution() const Q_DECL_OVERRIDE; + int defaultResolution() const override; - QPrint::InputSlot defaultInputSlot() const Q_DECL_OVERRIDE; + QPrint::InputSlot defaultInputSlot() const override; - QPrint::OutputBin defaultOutputBin() const Q_DECL_OVERRIDE; + QPrint::OutputBin defaultOutputBin() const override; - QPrint::DuplexMode defaultDuplexMode() const Q_DECL_OVERRIDE; + QPrint::DuplexMode defaultDuplexMode() const override; - QPrint::ColorMode defaultColorMode() const Q_DECL_OVERRIDE; + QPrint::ColorMode defaultColorMode() const override; PMPrinter macPrinter() const; PMPaper macPaper(const QPageSize &pageSize) const; protected: - void loadPageSizes() const Q_DECL_OVERRIDE; - void loadResolutions() const Q_DECL_OVERRIDE; - void loadInputSlots() const Q_DECL_OVERRIDE; - void loadOutputBins() const Q_DECL_OVERRIDE; - void loadDuplexModes() const Q_DECL_OVERRIDE; - void loadColorModes() const Q_DECL_OVERRIDE; - void loadMimeTypes() const Q_DECL_OVERRIDE; + void loadPageSizes() const override; + void loadResolutions() const override; + void loadInputSlots() const override; + void loadOutputBins() const override; + void loadDuplexModes() const override; + void loadColorModes() const override; + void loadMimeTypes() const override; private: QPageSize createPageSize(const PMPaper &paper) const; diff --git a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm index 39fcf285ed..bfe6cd09b6 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintdevice.mm +++ b/src/plugins/platforms/cocoa/qcocoaprintdevice.mm @@ -46,6 +46,15 @@ QT_BEGIN_NAMESPACE #ifndef QT_NO_PRINTER +// The CUPS PPD APIs were deprecated in CUPS 1.6/macOS 10.8, but +// as long as we're supporting RHEL 6, which still ships CUPS 1.4 +// we're not going to rewrite this, as we want to share the code +// between macOS and Linux for the CUPS-bits. See discussion in +// https://bugreports.qt.io/browse/QTBUG-56545 +#pragma message "Disabling CUPS PPD deprecation warnings. This should be fixed once we drop support for RHEL6 (QTBUG-56545)" +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + static QPrint::DuplexMode macToDuplexMode(const PMDuplexMode &mode) { if (mode == kPMDuplexTumble) @@ -474,6 +483,8 @@ PMPaper QCocoaPrintDevice::macPaper(const QPageSize &pageSize) const return paper; } +#pragma clang diagnostic pop + #endif // QT_NO_PRINTER QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaprintersupport.h b/src/plugins/platforms/cocoa/qcocoaprintersupport.h index a07bf0ec1b..40a638207a 100644 --- a/src/plugins/platforms/cocoa/qcocoaprintersupport.h +++ b/src/plugins/platforms/cocoa/qcocoaprintersupport.h @@ -53,12 +53,12 @@ public: QCocoaPrinterSupport(); ~QCocoaPrinterSupport(); - QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) Q_DECL_OVERRIDE; - QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode) Q_DECL_OVERRIDE; + QPrintEngine *createNativePrintEngine(QPrinter::PrinterMode printerMode, const QString &deviceId = QString()) override; + QPaintEngine *createPaintEngine(QPrintEngine *, QPrinter::PrinterMode printerMode) override; - QPrintDevice createPrintDevice(const QString &id) Q_DECL_OVERRIDE; - QStringList availablePrintDeviceIds() const Q_DECL_OVERRIDE; - QString defaultPrintDeviceId() const Q_DECL_OVERRIDE; + QPrintDevice createPrintDevice(const QString &id) override; + QStringList availablePrintDeviceIds() const override; + QString defaultPrintDeviceId() const override; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoascreen.h b/src/plugins/platforms/cocoa/qcocoascreen.h index 937002f493..3d59c3de79 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.h +++ b/src/plugins/platforms/cocoa/qcocoascreen.h @@ -56,20 +56,20 @@ public: // ---------------------------------------------------- // Virtual methods overridden from QPlatformScreen - QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE; - QRect geometry() const Q_DECL_OVERRIDE { return m_geometry; } - QRect availableGeometry() const Q_DECL_OVERRIDE { return m_availableGeometry; } - int depth() const Q_DECL_OVERRIDE { return m_depth; } - QImage::Format format() const Q_DECL_OVERRIDE { return m_format; } - qreal devicePixelRatio() const Q_DECL_OVERRIDE; - QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_physicalSize; } - QDpi logicalDpi() const Q_DECL_OVERRIDE { return m_logicalDpi; } - qreal refreshRate() const Q_DECL_OVERRIDE { return m_refreshRate; } - QString name() const Q_DECL_OVERRIDE { return m_name; } - QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return m_cursor; } - QWindow *topLevelAt(const QPoint &point) const Q_DECL_OVERRIDE; - QList<QPlatformScreen *> virtualSiblings() const Q_DECL_OVERRIDE { return m_siblings; } - QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const Q_DECL_OVERRIDE; + QPixmap grabWindow(WId window, int x, int y, int width, int height) const override; + QRect geometry() const override { return m_geometry; } + QRect availableGeometry() const override { return m_availableGeometry; } + int depth() const override { return m_depth; } + QImage::Format format() const override { return m_format; } + qreal devicePixelRatio() const override; + QSizeF physicalSize() const override { return m_physicalSize; } + QDpi logicalDpi() const override { return m_logicalDpi; } + qreal refreshRate() const override { return m_refreshRate; } + QString name() const override { return m_name; } + QPlatformCursor *cursor() const override { return m_cursor; } + QWindow *topLevelAt(const QPoint &point) const override; + QList<QPlatformScreen *> virtualSiblings() const override { return m_siblings; } + QPlatformScreen::SubpixelAntialiasingType subpixelAntialiasingTypeHint() const override; // ---------------------------------------------------- // Additional methods @@ -77,16 +77,12 @@ public: NSScreen *nativeScreen() const; void updateGeometry(); - QPointF mapToNative(const QPointF &pos) const { return flipCoordinate(pos); } - QRectF mapToNative(const QRectF &rect) const { return flipCoordinate(rect); } - QPointF mapFromNative(const QPointF &pos) const { return flipCoordinate(pos); } - QRectF mapFromNative(const QRectF &rect) const { return flipCoordinate(rect); } - static QCocoaScreen *primaryScreen(); -private: - QPointF flipCoordinate(const QPointF &pos) const; - QRectF flipCoordinate(const QRectF &rect) const; + static CGPoint mapToNative(const QPointF &pos, QCocoaScreen *screen = QCocoaScreen::primaryScreen()); + static CGRect mapToNative(const QRectF &rect, QCocoaScreen *screen = QCocoaScreen::primaryScreen()); + static QPointF mapFromNative(CGPoint pos, QCocoaScreen *screen = QCocoaScreen::primaryScreen()); + static QRectF mapFromNative(CGRect rect, QCocoaScreen *screen = QCocoaScreen::primaryScreen()); public: int m_screenIndex; diff --git a/src/plugins/platforms/cocoa/qcocoascreen.mm b/src/plugins/platforms/cocoa/qcocoascreen.mm index f523873bde..ed1b19cd53 100644 --- a/src/plugins/platforms/cocoa/qcocoascreen.mm +++ b/src/plugins/platforms/cocoa/qcocoascreen.mm @@ -75,32 +75,36 @@ NSScreen *QCocoaScreen::nativeScreen() const return [screens objectAtIndex:m_screenIndex]; } -/*! - Flips the Y coordinate of the point between quadrant I and IV. +static QString displayName(CGDirectDisplayID displayID) +{ + QIOType<io_iterator_t> iterator; + if (IOServiceGetMatchingServices(kIOMasterPortDefault, + IOServiceMatching("IODisplayConnect"), &iterator)) + return QString(); + + QIOType<io_service_t> display; + while ((display = IOIteratorNext(iterator)) != 0) + { + NSDictionary *info = [(__bridge NSDictionary*)IODisplayCreateInfoDictionary( + display, kIODisplayOnlyPreferredName) autorelease]; + + if ([[info objectForKey:@kDisplayVendorID] longValue] != CGDisplayVendorNumber(displayID)) + continue; - The native coordinate system on macOS uses quadrant I, with origin - in bottom left, and Qt uses quadrant IV, with origin in top left. + if ([[info objectForKey:@kDisplayProductID] longValue] != CGDisplayModelNumber(displayID)) + continue; - By flippig the Y coordinate, we can map the position between the - two coordinate systems. -*/ -QPointF QCocoaScreen::flipCoordinate(const QPointF &pos) const -{ - return QPointF(pos.x(), m_geometry.height() - pos.y()); -} + if ([[info objectForKey:@kDisplaySerialNumber] longValue] != CGDisplaySerialNumber(displayID)) + continue; -/*! - Flips the Y coordinate of the rectangle between quadrant I and IV. + NSDictionary *localizedNames = [info objectForKey:@kDisplayProductName]; + if (![localizedNames count]) + break; // Correct screen, but no name in dictionary - The native coordinate system on macOS uses quadrant I, with origin - in bottom left, and Qt uses quadrant IV, with origin in top left. + return QString::fromNSString([localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]]); + } - By flippig the Y coordinate, we can map the rectangle between the - two coordinate systems. -*/ -QRectF QCocoaScreen::flipCoordinate(const QRectF &rect) const -{ - return QRectF(flipCoordinate(rect.topLeft() + QPoint(0, rect.height())), rect.size()); + return QString(); } void QCocoaScreen::updateGeometry() @@ -109,20 +113,10 @@ void QCocoaScreen::updateGeometry() if (!nsScreen) return; - // At this point the geometry is in native coordinates, but the size - // is correct, which we take advantage of next when we map the native - // coordinates to the Qt coordinate system. - m_geometry = QRectF::fromCGRect(NSRectToCGRect(nsScreen.frame)).toRect(); - m_availableGeometry = QRectF::fromCGRect(NSRectToCGRect(nsScreen.visibleFrame)).toRect(); - - // The reference screen for the geometry is always the primary screen, but since - // we may be in the process of creating and registering the primary screen, we - // must special-case that and assign it direcly. - QCocoaScreen *primaryScreen = (nsScreen == [[NSScreen screens] firstObject]) ? - this : QCocoaScreen::primaryScreen(); - - m_geometry = primaryScreen->mapFromNative(m_geometry).toRect(); - m_availableGeometry = primaryScreen->mapFromNative(m_availableGeometry).toRect(); + // The reference screen for the geometry is always the primary screen + QRectF primaryScreenGeometry = QRectF::fromCGRect([[NSScreen screens] firstObject].frame); + m_geometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.frame), primaryScreenGeometry).toRect(); + m_availableGeometry = qt_mac_flip(QRectF::fromCGRect(nsScreen.visibleFrame), primaryScreenGeometry).toRect(); m_format = QImage::Format_RGB32; m_depth = NSBitsPerPixelFromDepth([nsScreen depth]); @@ -139,12 +133,7 @@ void QCocoaScreen::updateGeometry() if (refresh > 0) m_refreshRate = refresh; - // Get m_name (brand/model of the monitor) - NSDictionary *deviceInfo = (NSDictionary *)IODisplayCreateInfoDictionary(CGDisplayIOServicePort(dpy), kIODisplayOnlyPreferredName); - NSDictionary *localizedNames = [deviceInfo objectForKey:[NSString stringWithUTF8String:kDisplayProductName]]; - if ([localizedNames count] > 0) - m_name = QString::fromUtf8([[localizedNames objectForKey:[[localizedNames allKeys] objectAtIndex:0]] UTF8String]); - [deviceInfo release]; + m_name = displayName(dpy); QWindowSystemInterface::handleScreenGeometryChange(screen(), geometry(), availableGeometry()); QWindowSystemInterface::handleScreenLogicalDotsPerInchChange(screen(), m_logicalDpi.first, m_logicalDpi.second); @@ -170,7 +159,7 @@ QPlatformScreen::SubpixelAntialiasingType QCocoaScreen::subpixelAntialiasingType QWindow *QCocoaScreen::topLevelAt(const QPoint &point) const { - NSPoint screenPoint = qt_mac_flipPoint(point); + NSPoint screenPoint = mapToNative(point); // Search (hit test) for the top-level window. [NSWidow windowNumberAtPoint: // belowWindowWithWindowNumber] may return windows that are not interesting @@ -275,6 +264,30 @@ QCocoaScreen *QCocoaScreen::primaryScreen() return static_cast<QCocoaScreen *>(QGuiApplication::primaryScreen()->handle()); } +CGPoint QCocoaScreen::mapToNative(const QPointF &pos, QCocoaScreen *screen) +{ + Q_ASSERT(screen); + return qt_mac_flip(pos, screen->geometry()).toCGPoint(); +} + +CGRect QCocoaScreen::mapToNative(const QRectF &rect, QCocoaScreen *screen) +{ + Q_ASSERT(screen); + return qt_mac_flip(rect, screen->geometry()).toCGRect(); +} + +QPointF QCocoaScreen::mapFromNative(CGPoint pos, QCocoaScreen *screen) +{ + Q_ASSERT(screen); + return qt_mac_flip(QPointF::fromCGPoint(pos), screen->geometry()); +} + +QRectF QCocoaScreen::mapFromNative(CGRect rect, QCocoaScreen *screen) +{ + Q_ASSERT(screen); + return qt_mac_flip(QRectF::fromCGRect(rect), screen->geometry()); +} + #ifndef QT_NO_DEBUG_STREAM QDebug operator<<(QDebug debug, const QCocoaScreen *screen) { diff --git a/src/plugins/platforms/cocoa/qcocoaservices.h b/src/plugins/platforms/cocoa/qcocoaservices.h index c2ceede0f0..62a8891f96 100644 --- a/src/plugins/platforms/cocoa/qcocoaservices.h +++ b/src/plugins/platforms/cocoa/qcocoaservices.h @@ -47,8 +47,8 @@ QT_BEGIN_NAMESPACE class QCocoaServices : public QPlatformServices { public: - bool openUrl(const QUrl &url) Q_DECL_OVERRIDE; - bool openDocument(const QUrl &url) Q_DECL_OVERRIDE; + bool openUrl(const QUrl &url) override; + bool openDocument(const QUrl &url) override; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h index d542a3cb8f..2f1a1e42a9 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.h @@ -57,17 +57,17 @@ class Q_GUI_EXPORT QCocoaSystemTrayIcon : public QPlatformSystemTrayIcon public: QCocoaSystemTrayIcon() : m_sys(0) {} - void init() Q_DECL_OVERRIDE; - void cleanup() Q_DECL_OVERRIDE; - void updateIcon(const QIcon &icon) Q_DECL_OVERRIDE; - void updateToolTip(const QString &toolTip) Q_DECL_OVERRIDE; - void updateMenu(QPlatformMenu *menu) Q_DECL_OVERRIDE; - QRect geometry() const Q_DECL_OVERRIDE; + void init() override; + void cleanup() override; + void updateIcon(const QIcon &icon) override; + void updateToolTip(const QString &toolTip) override; + void updateMenu(QPlatformMenu *menu) override; + QRect geometry() const override; void showMessage(const QString &title, const QString &msg, - const QIcon& icon, MessageIcon iconType, int secs) Q_DECL_OVERRIDE; + const QIcon& icon, MessageIcon iconType, int secs) override; - bool isSystemTrayAvailable() const Q_DECL_OVERRIDE; - bool supportsMessages() const Q_DECL_OVERRIDE; + bool isSystemTrayAvailable() const override; + bool supportsMessages() const override; private: QSystemTrayIconSys *m_sys; diff --git a/src/plugins/platforms/cocoa/qcocoatheme.h b/src/plugins/platforms/cocoa/qcocoatheme.h index 27c071a8cd..69eaf8db56 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.h +++ b/src/plugins/platforms/cocoa/qcocoatheme.h @@ -56,25 +56,25 @@ public: void reset(); - QPlatformMenuItem* createPlatformMenuItem() const Q_DECL_OVERRIDE; - QPlatformMenu* createPlatformMenu() const Q_DECL_OVERRIDE; - QPlatformMenuBar* createPlatformMenuBar() const Q_DECL_OVERRIDE; + QPlatformMenuItem* createPlatformMenuItem() const override; + QPlatformMenu* createPlatformMenu() const override; + QPlatformMenuBar* createPlatformMenuBar() const override; #ifndef QT_NO_SYSTEMTRAYICON - QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const Q_DECL_OVERRIDE; + QPlatformSystemTrayIcon *createPlatformSystemTrayIcon() const override; #endif - bool usePlatformNativeDialog(DialogType dialogType) const Q_DECL_OVERRIDE; - QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const Q_DECL_OVERRIDE; + bool usePlatformNativeDialog(DialogType dialogType) const override; + QPlatformDialogHelper *createPlatformDialogHelper(DialogType dialogType) const override; - const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE; - const QFont *font(Font type = SystemFont) const Q_DECL_OVERRIDE; - QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE; + const QPalette *palette(Palette type = SystemPalette) const override; + const QFont *font(Font type = SystemFont) const override; + QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const override; QIcon fileIcon(const QFileInfo &fileInfo, QPlatformTheme::IconOptions options = 0) const override; - QVariant themeHint(ThemeHint hint) const Q_DECL_OVERRIDE; - QString standardButtonText(int button) const Q_DECL_OVERRIDE; - QKeySequence standardButtonShortcut(int button) const Q_DECL_OVERRIDE; + QVariant themeHint(ThemeHint hint) const override; + QString standardButtonText(int button) const override; + QKeySequence standardButtonShortcut(int button) const override; static const char *name; diff --git a/src/plugins/platforms/cocoa/qcocoatheme.mm b/src/plugins/platforms/cocoa/qcocoatheme.mm index 5239864ad8..93f0400916 100644 --- a/src/plugins/platforms/cocoa/qcocoatheme.mm +++ b/src/plugins/platforms/cocoa/qcocoatheme.mm @@ -98,7 +98,7 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaThemeNotificationReceiver); { Q_UNUSED(notification); mPrivate->reset(); - QWindowSystemInterface::handleThemeChange(Q_NULLPTR); + QWindowSystemInterface::handleThemeChange(nullptr); } @end @@ -127,7 +127,7 @@ QCocoaTheme::~QCocoaTheme() void QCocoaTheme::reset() { delete m_systemPalette; - m_systemPalette = Q_NULLPTR; + m_systemPalette = nullptr; qDeleteAll(m_palettes); m_palettes.clear(); } @@ -275,7 +275,7 @@ QPixmap QCocoaTheme::standardPixmap(StandardPixmap sp, const QSizeF &size) const } if (iconType != 0) { QPixmap pixmap; - IconRef icon = Q_NULLPTR; + IconRef icon = nullptr; GetIconRef(kOnSystemDisk, kSystemIconsCreator, iconType, &icon); if (icon) { @@ -347,6 +347,8 @@ QVariant QCocoaTheme::themeHint(ThemeHint hint) const return QVariant(int(HoverEffect)); case QPlatformTheme::SpellCheckUnderlineStyle: return QVariant(int(QTextCharFormat::DotLine)); + case QPlatformTheme::UseFullScreenForPopupMenu: + return QVariant(bool([[NSApplication sharedApplication] presentationOptions] & NSApplicationPresentationFullScreen)); default: break; } diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 6fbe29f683..fb91c53a7a 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -97,37 +97,37 @@ public: void initialize() override; - void setGeometry(const QRect &rect) Q_DECL_OVERRIDE; - QRect geometry() const Q_DECL_OVERRIDE; + void setGeometry(const QRect &rect) override; + QRect geometry() const override; void setCocoaGeometry(const QRect &rect); - void setVisible(bool visible) Q_DECL_OVERRIDE; - void setWindowFlags(Qt::WindowFlags flags) Q_DECL_OVERRIDE; - void setWindowState(Qt::WindowStates state) Q_DECL_OVERRIDE; - void setWindowTitle(const QString &title) Q_DECL_OVERRIDE; - void setWindowFilePath(const QString &filePath) Q_DECL_OVERRIDE; - void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE; - void setAlertState(bool enabled) Q_DECL_OVERRIDE; - bool isAlertState() const Q_DECL_OVERRIDE; - void raise() Q_DECL_OVERRIDE; - void lower() Q_DECL_OVERRIDE; - bool isExposed() const Q_DECL_OVERRIDE; + void setVisible(bool visible) override; + void setWindowFlags(Qt::WindowFlags flags) override; + void setWindowState(Qt::WindowStates state) override; + void setWindowTitle(const QString &title) override; + void setWindowFilePath(const QString &filePath) override; + void setWindowIcon(const QIcon &icon) override; + void setAlertState(bool enabled) override; + bool isAlertState() const override; + void raise() override; + void lower() override; + bool isExposed() const override; bool isOpaque() const; - void propagateSizeHints() Q_DECL_OVERRIDE; - void setOpacity(qreal level) Q_DECL_OVERRIDE; - void setMask(const QRegion ®ion) Q_DECL_OVERRIDE; - bool setKeyboardGrabEnabled(bool grab) Q_DECL_OVERRIDE; - bool setMouseGrabEnabled(bool grab) Q_DECL_OVERRIDE; - QMargins frameMargins() const Q_DECL_OVERRIDE; - QSurfaceFormat format() const Q_DECL_OVERRIDE; + void propagateSizeHints() override; + void setOpacity(qreal level) override; + void setMask(const QRegion ®ion) override; + bool setKeyboardGrabEnabled(bool grab) override; + bool setMouseGrabEnabled(bool grab) override; + QMargins frameMargins() const override; + QSurfaceFormat format() const override; - bool isForeignWindow() const Q_DECL_OVERRIDE; + bool isForeignWindow() const override; void requestUpdate() override; - void requestActivateWindow() Q_DECL_OVERRIDE; + void requestActivateWindow() override; - WId winId() const Q_DECL_OVERRIDE; - void setParent(const QPlatformWindow *window) Q_DECL_OVERRIDE; + WId winId() const override; + void setParent(const QPlatformWindow *window) override; NSView *view() const; NSWindow *nativeWindow() const; @@ -167,10 +167,10 @@ public: QCocoaGLContext *currentContext() const; #endif - bool setWindowModified(bool modified) Q_DECL_OVERRIDE; + bool setWindowModified(bool modified) override; - void setFrameStrutEventsEnabled(bool enabled) Q_DECL_OVERRIDE; - bool frameStrutEventsEnabled() const Q_DECL_OVERRIDE + void setFrameStrutEventsEnabled(bool enabled) override; + bool frameStrutEventsEnabled() const override { return m_frameStrutEventsEnabled; } void setMenubar(QCocoaMenuBar *mb); @@ -187,7 +187,7 @@ public: void applyContentBorderThickness(NSWindow *window = nullptr); void updateNSToolbar(); - qreal devicePixelRatio() const Q_DECL_OVERRIDE; + qreal devicePixelRatio() const override; QWindow *childWindowAt(QPoint windowPoint); bool shouldRefuseKeyWindowAndFirstResponder(); @@ -209,8 +209,6 @@ protected: void recreateWindowIfNeeded(); QCocoaNSWindow *createNSWindow(bool shouldBePanel); - QRect nativeWindowGeometry() const; - Qt::WindowState windowState() const; void applyWindowState(Qt::WindowStates newState); void toggleMaximized(); diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index e86cc2d955..c000c90a85 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -287,7 +287,7 @@ QRect QCocoaWindow::geometry() const NSPoint windowPoint = [m_view convertPoint:NSMakePoint(0, 0) toView:nil]; NSRect screenRect = [[m_view window] convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 1, 1)]; NSPoint screenPoint = screenRect.origin; - QPoint position = qt_mac_flipPoint(screenPoint).toPoint(); + QPoint position = QCocoaScreen::mapFromNative(screenPoint).toPoint(); QSize size = QRectF::fromCGRect(NSRectToCGRect([m_view bounds])).toRect().size(); return QRect(position, size); } @@ -310,7 +310,7 @@ void QCocoaWindow::setCocoaGeometry(const QRect &rect) } if (isContentView()) { - NSRect bounds = qt_mac_flipRect(rect); + NSRect bounds = QCocoaScreen::mapToNative(rect); [m_view.window setFrame:[m_view.window frameRectForContentRect:bounds] display:YES animate:NO]; } else { [m_view setFrame:NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height())]; @@ -403,7 +403,7 @@ void QCocoaWindow::setVisible(bool visible) if (!(parentCocoaWindow && window()->transientParent()->isActive()) && window()->type() == Qt::Popup) { removeMonitor(); monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:NSLeftMouseDownMask|NSRightMouseDownMask|NSOtherMouseDownMask|NSMouseMovedMask handler:^(NSEvent *e) { - QPointF localPoint = qt_mac_flipPoint([NSEvent mouseLocation]); + QPointF localPoint = QCocoaScreen::mapFromNative([NSEvent mouseLocation]); QWindowSystemInterface::handleMouseEvent(window(), window()->mapFromGlobal(localPoint.toPoint()), localPoint, cocoaButton2QtButton([e buttonNumber])); }]; @@ -1116,7 +1116,7 @@ void QCocoaWindow::handleGeometryChange() CGRect contentRect = [m_view.window contentRectForFrameRect:m_view.window.frame]; // The result above is in native screen coordinates, so remap to the Qt coordinate system - newGeometry = QCocoaScreen::primaryScreen()->mapFromNative(QRectF::fromCGRect(contentRect)).toRect(); + newGeometry = QCocoaScreen::mapFromNative(contentRect).toRect(); } else { // QNSView has isFlipped set, so no need to remap the geometry newGeometry = QRectF::fromCGRect(m_view.frame).toRect(); @@ -1378,7 +1378,7 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel) rect.translate(-targetScreen->geometry().topLeft()); QCocoaScreen *cocoaScreen = static_cast<QCocoaScreen *>(targetScreen->handle()); - NSRect frame = NSRectFromCGRect(cocoaScreen->mapToNative(rect).toCGRect()); + NSRect frame = QCocoaScreen::mapToNative(rect, cocoaScreen); // Note: The macOS window manager has a bug, where if a screen is rotated, it will not allow // a window to be created within the area of the screen that has a Y coordinate (I quadrant) @@ -1474,19 +1474,6 @@ void QCocoaWindow::removeMonitor() monitor = nil; } -// Returns the current global screen geometry for the nswindow associated with this window. -QRect QCocoaWindow::nativeWindowGeometry() const -{ - if (!isContentView()) - return geometry(); - - NSRect rect = m_view.window.frame; - QPlatformScreen *onScreen = QPlatformScreen::platformScreenForWindow(window()); - int flippedY = onScreen->geometry().height() - rect.origin.y - rect.size.height; // account for nswindow inverted y. - QRect qRect = QRect(rect.origin.x, flippedY, rect.size.width, rect.size.height); - return qRect; -} - /*! Applies the given state to the NSWindow, going in/out of minimize/zoomed/fullscreen diff --git a/src/plugins/platforms/cocoa/qmultitouch_mac.mm b/src/plugins/platforms/cocoa/qmultitouch_mac.mm index 79f8af7783..9eca4d2d43 100644 --- a/src/plugins/platforms/cocoa/qmultitouch_mac.mm +++ b/src/plugins/platforms/cocoa/qmultitouch_mac.mm @@ -39,6 +39,7 @@ #include "qmultitouch_mac_p.h" #include "qcocoahelpers.h" +#include "qcocoascreen.h" #include <private/qtouchdevice_p.h> QT_BEGIN_NAMESPACE @@ -83,7 +84,7 @@ void QCocoaTouch::updateTouchData(NSTouch *nstouch, NSTouchPhase phase) if (_touchPoint.id == 0 && phase == NSTouchPhaseBegan) { _trackpadReferencePos = qnpos; - _screenReferencePos = qt_mac_flipPoint([NSEvent mouseLocation]); + _screenReferencePos = QCocoaScreen::mapFromNative([NSEvent mouseLocation]); } QPointF screenPos = _screenReferencePos; diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 61f0012a2d..32f73759c2 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -42,6 +42,7 @@ #include "qnsview.h" #include "qcocoawindow.h" #include "qcocoahelpers.h" +#include "qcocoascreen.h" #include "qmultitouch_mac_p.h" #include "qcocoadrag.h" #include "qcocoainputcontext.h" @@ -442,8 +443,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") nsWindowPoint = windowRect.origin; // NSWindow coordinates NSPoint nsViewPoint = [self convertPoint: nsWindowPoint fromView: nil]; // NSView/QWindow coordinates *qtWindowPoint = QPointF(nsViewPoint.x, nsViewPoint.y); // NSView/QWindow coordinates - - *qtScreenPoint = QPointF(mouseLocation.x, qt_mac_flipYCoordinate(mouseLocation.y)); // Qt screen coordinates + *qtScreenPoint = QCocoaScreen::mapFromNative(mouseLocation); } - (void)resetMouseButtons @@ -554,7 +554,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil]; QPoint qtWindowPoint = QPoint(nsViewPoint.x, titleBarHeight + nsViewPoint.y); NSPoint screenPoint = [window convertRectToScreen:NSMakeRect(windowPoint.x, windowPoint.y, 0, 0)].origin; - QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y)); + QPoint qtScreenPoint = QCocoaScreen::mapFromNative(screenPoint).toPoint(); ulong timestamp = [theEvent timestamp] * 1000; QWindowSystemInterface::handleFrameStrutMouseEvent(m_platformWindow->window(), timestamp, qtWindowPoint, qtScreenPoint, m_frameStrutButtons); @@ -646,7 +646,7 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") if (!popups->isEmpty()) { // Check if the click is outside all popups. bool inside = false; - QPointF qtScreenPoint = qt_mac_flipPoint([self screenMousePoint:theEvent]); + QPointF qtScreenPoint = QCocoaScreen::mapFromNative([self screenMousePoint:theEvent]); for (QList<QCocoaWindow *>::const_iterator it = popups->begin(); it != popups->end(); ++it) { if ((*it)->geometry().contains(qtScreenPoint.toPoint())) { inside = true; @@ -689,7 +689,8 @@ Q_LOGGING_CATEGORY(lcQpaTablet, "qt.qpa.input.tablet") if ([self hasMarkedText]) { [[NSTextInputContext currentInputContext] handleEvent:theEvent]; } else { - if (!m_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & Qt::MetaModifier) { + auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier; + if (!m_dontOverrideCtrlLMB && [QNSView convertKeyModifiers:[theEvent modifierFlags]] & ctrlOrMetaModifier) { m_buttons |= Qt::RightButton; m_sendUpAsRightButton = true; } else { @@ -1314,15 +1315,16 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) + (Qt::KeyboardModifiers) convertKeyModifiers : (ulong)modifierFlags { + const bool dontSwapCtrlAndMeta = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta); Qt::KeyboardModifiers qtMods =Qt::NoModifier; if (modifierFlags & NSShiftKeyMask) qtMods |= Qt::ShiftModifier; if (modifierFlags & NSControlKeyMask) - qtMods |= Qt::MetaModifier; + qtMods |= dontSwapCtrlAndMeta ? Qt::ControlModifier : Qt::MetaModifier; if (modifierFlags & NSAlternateKeyMask) qtMods |= Qt::AltModifier; if (modifierFlags & NSCommandKeyMask) - qtMods |= Qt::ControlModifier; + qtMods |= dontSwapCtrlAndMeta ? Qt::MetaModifier : Qt::ControlModifier; if (modifierFlags & NSNumericPadKeyMask) qtMods |= Qt::KeypadModifier; return qtMods; @@ -1355,7 +1357,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) // ALT+E to be used as a shortcut with an English keyboard even though // pressing ALT+E will give a dead key while doing normal text input. if ([characters length] != 0 || [charactersIgnoringModifiers length] != 0) { - if (((modifiers & Qt::MetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0)) + auto ctrlOrMetaModifier = qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta) ? Qt::ControlModifier : Qt::MetaModifier; + if (((modifiers & ctrlOrMetaModifier) || (modifiers & Qt::AltModifier)) && ([charactersIgnoringModifiers length] != 0)) ch = QChar([charactersIgnoringModifiers characterAtIndex:0]); else if ([characters length] != 0) ch = QChar([characters characterAtIndex:0]); @@ -1504,10 +1507,17 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) if ((delta & mac_mask) == 0u) continue; + Qt::Key qtCode = modifier_key_symbols[i].qt_code; + if (qApp->testAttribute(Qt::AA_MacDontSwapCtrlAndMeta)) { + if (qtCode == Qt::Key_Meta) + qtCode = Qt::Key_Control; + else if (qtCode == Qt::Key_Control) + qtCode = Qt::Key_Meta; + } QWindowSystemInterface::handleKeyEvent(m_platformWindow->window(), timestamp, (lastKnownModifiers & mac_mask) ? QEvent::KeyRelease : QEvent::KeyPress, - modifier_key_symbols[i].qt_code, + qtCode, qmodifiers ^ [QNSView convertKeyModifiers:mac_mask]); } } @@ -1739,14 +1749,8 @@ static QTabletEvent::TabletDevice wacomTabletDevice(NSEvent *theEvent) // The returned rect is always based on the internal cursor. QRect mr = qApp->inputMethod()->cursorRectangle().toRect(); - QPoint mp = m_platformWindow->window()->mapToGlobal(mr.bottomLeft()); - - NSRect rect; - rect.origin.x = mp.x(); - rect.origin.y = qt_mac_flipYCoordinate(mp.y()); - rect.size.width = mr.width(); - rect.size.height = mr.height(); - return rect; + mr.moveBottomLeft(m_platformWindow->window()->mapToGlobal(mr.bottomLeft())); + return QCocoaScreen::mapToNative(mr); } - (NSUInteger)characterIndexForPoint:(NSPoint)aPoint @@ -2032,8 +2036,7 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin NSPoint windowPoint = [self.window convertRectFromScreen:NSMakeRect(screenPoint.x, screenPoint.y, 1, 1)].origin; NSPoint nsViewPoint = [self convertPoint: windowPoint fromView: nil]; // NSView/QWindow coordinates QPoint qtWindowPoint(nsViewPoint.x, nsViewPoint.y); - - QPoint qtScreenPoint = QPoint(screenPoint.x, qt_mac_flipYCoordinate(screenPoint.y)); + QPoint qtScreenPoint = QCocoaScreen::mapFromNative(screenPoint).toPoint(); QWindowSystemInterface::handleMouseEvent(target, mapWindowCoordinates(m_platformWindow->window(), target, qtWindowPoint), qtScreenPoint, m_buttons); } diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac.mm b/src/plugins/platforms/cocoa/qpaintengine_mac.mm index 7e241e3ae6..3f363b62d5 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qpaintengine_mac.mm @@ -108,7 +108,7 @@ CGAffineTransform qt_mac_convert_transform_to_cg(const QTransform &t) { return CGAffineTransformMake(t.m11(), t.m12(), t.m21(), t.m22(), t.dx(), t.dy()); } -inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col, QPaintDevice *pdev) +inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col) { CGFloat components[] = { qt_mac_convert_color_to_cg(col.red()), @@ -116,7 +116,8 @@ inline static QCFType<CGColorRef> cgColorForQColor(const QColor &col, QPaintDevi qt_mac_convert_color_to_cg(col.blue()), qt_mac_convert_color_to_cg(col.alpha()) }; - return CGColorCreate(qt_mac_colorSpaceForDeviceType(pdev), components); + QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); + return CGColorCreate(colorSpace, components); } // There's architectural problems with using native gradients @@ -239,81 +240,6 @@ static CGMutablePathRef qt_mac_compose_path(const QPainterPath &p, float off=0) return ret; } -CGColorSpaceRef QCoreGraphicsPaintEngine::m_genericColorSpace = 0; -QHash<CGDirectDisplayID, CGColorSpaceRef> QCoreGraphicsPaintEngine::m_displayColorSpaceHash; -bool QCoreGraphicsPaintEngine::m_postRoutineRegistered = false; - -CGColorSpaceRef QCoreGraphicsPaintEngine::macGenericColorSpace() -{ -#if 0 - if (!m_genericColorSpace) { - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_4) { - m_genericColorSpace = CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB); - } else - { - m_genericColorSpace = CGColorSpaceCreateDeviceRGB(); - } - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); - } - } - return m_genericColorSpace; -#else - // Just return the main display colorspace for the moment. - return macDisplayColorSpace(); -#endif -} - -/* - Ideally, we should pass the widget in here, and use CGGetDisplaysWithRect() etc. - to support multiple displays correctly. -*/ -CGColorSpaceRef QCoreGraphicsPaintEngine::macDisplayColorSpace(const QWidget *widget) -{ - CGColorSpaceRef colorSpace; - - CGDirectDisplayID displayID; - if (widget == 0) { - displayID = CGMainDisplayID(); - } else { - const QRect &qrect = widget->window()->geometry(); - CGRect rect = CGRectMake(qrect.x(), qrect.y(), qrect.width(), qrect.height()); - CGDisplayCount throwAway; - CGDisplayErr dErr = CGGetDisplaysWithRect(rect, 1, &displayID, &throwAway); - if (dErr != kCGErrorSuccess) - return macDisplayColorSpace(0); // fall back on main display - } - if ((colorSpace = m_displayColorSpaceHash.value(displayID))) - return colorSpace; - - colorSpace = CGDisplayCopyColorSpace(displayID); - if (colorSpace == 0) - colorSpace = CGColorSpaceCreateDeviceRGB(); - - m_displayColorSpaceHash.insert(displayID, colorSpace); - if (!m_postRoutineRegistered) { - m_postRoutineRegistered = true; - qAddPostRoutine(QCoreGraphicsPaintEngine::cleanUpMacColorSpaces); - } - return colorSpace; -} - -void QCoreGraphicsPaintEngine::cleanUpMacColorSpaces() -{ - if (m_genericColorSpace) { - CFRelease(m_genericColorSpace); - m_genericColorSpace = 0; - } - QHash<CGDirectDisplayID, CGColorSpaceRef>::const_iterator it = m_displayColorSpaceHash.constBegin(); - while (it != m_displayColorSpaceHash.constEnd()) { - if (it.value()) - CFRelease(it.value()); - ++it; - } - m_displayColorSpaceHash.clear(); -} - //pattern handling (tiling) #if 1 # define QMACPATTERN_MASK_MULTIPLIER 32 @@ -377,7 +303,7 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c) QPixmap pm(w*QMACPATTERN_MASK_MULTIPLIER, h*QMACPATTERN_MASK_MULTIPLIER); pm.fill(c0); QMacCGContext pm_ctx(&pm); - CGContextSetFillColorWithColor(c, cgColorForQColor(c1, pat->pdev)); + CGContextSetFillColorWithColor(c, cgColorForQColor(c1)); CGRect rect = CGRectMake(0, 0, w, h); for (int x = 0; x < QMACPATTERN_MASK_MULTIPLIER; ++x) { rect.origin.x = x * w; @@ -409,7 +335,7 @@ static void qt_mac_draw_pattern(void *info, CGContextRef c) bool needRestore = false; if (CGImageIsMask(pat->image)) { CGContextSaveGState(c); - CGContextSetFillColorWithColor(c, cgColorForQColor(pat->foreground, pat->pdev)); + CGContextSetFillColorWithColor(c, cgColorForQColor(pat->foreground)); } CGRect rect = CGRectMake(0, 0, w, h); qt_mac_drawCGImage(c, &rect, pat->image); @@ -871,7 +797,7 @@ void QCoreGraphicsPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, co d->saveGraphicsState(); const QColor &col = d->current.pen.color(); - CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col, d->pdev)); + CGContextSetFillColorWithColor(d->hd, cgColorForQColor(col)); image = qt_mac_create_imagemask(pm, sr); } else if (differentSize) { QCFType<CGImageRef> img = qt_mac_toCGImage(pm.toImage()); @@ -1233,7 +1159,7 @@ QCoreGraphicsPaintEnginePrivate::setStrokePen(const QPen &pen) CGContextSetLineDash(hd, pen.dashOffset() * cglinewidth, linedashes.data(), linedashes.size()); // color - CGContextSetStrokeColorWithColor(hd, cgColorForQColor(pen.color(), pdev)); + CGContextSetStrokeColorWithColor(hd, cgColorForQColor(pen.color())); } // Add our own patterns here to deal with the fact that the coordinate system @@ -1276,7 +1202,7 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset) CGFunctionRef fill_func = CGFunctionCreate(reinterpret_cast<void *>(¤t.brush), 1, domain, 4, 0, &callbacks); - CGColorSpaceRef colorspace = qt_mac_colorSpaceForDeviceType(pdev); + CGColorSpaceRef colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB) if (bs == Qt::LinearGradientPattern) { const QLinearGradient *linearGrad = static_cast<const QLinearGradient *>(grad); const QPointF start(linearGrad->start()); @@ -1315,7 +1241,7 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset) components[0] = qt_mac_convert_color_to_cg(col.red()); components[1] = qt_mac_convert_color_to_cg(col.green()); components[2] = qt_mac_convert_color_to_cg(col.blue()); - base_colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); + base_colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); } } else { qpattern->as_mask = true; @@ -1325,7 +1251,7 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset) components[0] = qt_mac_convert_color_to_cg(col.red()); components[1] = qt_mac_convert_color_to_cg(col.green()); components[2] = qt_mac_convert_color_to_cg(col.blue()); - base_colorspace = QCoreGraphicsPaintEngine::macGenericColorSpace(); + base_colorspace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB); } int width = qpattern->width(), height = qpattern->height(); qpattern->foreground = current.brush.color(); @@ -1346,10 +1272,12 @@ void QCoreGraphicsPaintEnginePrivate::setFillBrush(const QPointF &offset) !base_colorspace, &callbks); CGContextSetFillPattern(hd, fill_pattern, components); + CGPatternRelease(fill_pattern); + CGColorSpaceRelease(base_colorspace); CGColorSpaceRelease(fill_colorspace); } else if (bs != Qt::NoBrush) { - CGContextSetFillColorWithColor(hd, cgColorForQColor(current.brush.color(), pdev)); + CGContextSetFillColorWithColor(hd, cgColorForQColor(current.brush.color())); } } diff --git a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h index 57d985c399..c9519ac827 100644 --- a/src/plugins/platforms/cocoa/qpaintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qpaintengine_mac_p.h @@ -73,8 +73,6 @@ public: bool begin(QPaintDevice *pdev); bool end(); - static CGColorSpaceRef macGenericColorSpace(); - static CGColorSpaceRef macDisplayColorSpace(const QWidget *widget = 0); void updateState(const QPaintEngineState &state); @@ -126,10 +124,6 @@ protected: QCoreGraphicsPaintEngine(QPaintEnginePrivate &dptr); private: - static bool m_postRoutineRegistered; - static CGColorSpaceRef m_genericColorSpace; - static QHash<CGDirectDisplayID, CGColorSpaceRef> m_displayColorSpaceHash; - static void cleanUpMacColorSpaces(); Q_DISABLE_COPY(QCoreGraphicsPaintEngine) }; diff --git a/src/plugins/platforms/cocoa/qprintengine_mac.mm b/src/plugins/platforms/cocoa/qprintengine_mac.mm index c39af870d4..b3d48c1ec3 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac.mm +++ b/src/plugins/platforms/cocoa/qprintengine_mac.mm @@ -247,7 +247,7 @@ void QMacPrintEnginePrivate::initialize() QList<int> resolutions = m_printDevice->supportedResolutions(); if (!resolutions.isEmpty() && mode != QPrinter::ScreenResolution) { - qSort(resolutions); + std::sort(resolutions.begin(), resolutions.end()); if (resolutions.count() > 1 && mode == QPrinter::HighResolution) resolution.hRes = resolution.vRes = resolutions.last(); else diff --git a/src/plugins/platforms/cocoa/qprintengine_mac_p.h b/src/plugins/platforms/cocoa/qprintengine_mac_p.h index 2d46a250d5..9514f3e691 100644 --- a/src/plugins/platforms/cocoa/qprintengine_mac_p.h +++ b/src/plugins/platforms/cocoa/qprintengine_mac_p.h @@ -150,8 +150,8 @@ public: PMPrintSession session() const { return static_cast<PMPrintSession>([printInfo PMPrintSession]); } PMPrintSettings settings() const { return static_cast<PMPrintSettings>([printInfo PMPrintSettings]); } - QPaintEngine *aggregateEngine() Q_DECL_OVERRIDE { return paintEngine; } - Qt::HANDLE nativeHandle() Q_DECL_OVERRIDE { return q_func()->handle(); } + QPaintEngine *aggregateEngine() override { return paintEngine; } + Qt::HANDLE nativeHandle() override { return q_func()->handle(); } }; QT_END_NAMESPACE |