diff options
Diffstat (limited to 'src/plugins/platforms/cocoa')
4 files changed, 65 insertions, 30 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h index 3073cb6b44..0816730c54 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -90,14 +90,18 @@ #include <qglobal.h> #include <private/qcore_mac_p.h> -@class QT_MANGLE_NAMESPACE(QCocoaMenuLoader); +Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QCocoaNSMenuItem)); @interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) : NSObject <NSApplicationDelegate> +@property (nonatomic, retain) NSMenu *dockMenu; + (instancetype)sharedDelegate; -- (void)setDockMenu:(NSMenu *)newMenu; - (void)setReflectionDelegate:(NSObject<NSApplicationDelegate> *)oldDelegate; - (void)removeAppleEventHandlers; - (bool)inLaunch; @end +@interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) (MenuAPI) +- (void)qt_itemFired:(QT_MANGLE_NAMESPACE(QCocoaNSMenuItem) *)item; +@end + QT_NAMESPACE_ALIAS_OBJC_CLASS(QCocoaApplicationDelegate); diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index 53407d8b62..7601fb7e17 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2018 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -73,8 +73,12 @@ #import "qcocoaapplicationdelegate.h" -#import "qcocoamenuloader.h" #include "qcocoaintegration.h" +#include "qcocoamenu.h" +#include "qcocoamenuloader.h" +#include "qcocoamenuitem.h" +#include "qcocoansmenu.h" + #include <qevent.h> #include <qurl.h> #include <qdebug.h> @@ -87,7 +91,6 @@ QT_USE_NAMESPACE @implementation QCocoaApplicationDelegate { bool startedQuit; - NSMenu *dockMenu; NSObject <NSApplicationDelegate> *reflectionDelegate; bool inLaunch; } @@ -129,7 +132,7 @@ QT_USE_NAMESPACE - (void)dealloc { - [dockMenu release]; + [_dockMenu release]; if (reflectionDelegate) { [[NSApplication sharedApplication] setDelegate:reflectionDelegate]; [reflectionDelegate release]; @@ -139,20 +142,13 @@ QT_USE_NAMESPACE [super dealloc]; } -- (void)setDockMenu:(NSMenu*)newMenu -{ - [newMenu retain]; - [dockMenu release]; - dockMenu = newMenu; -} - - (NSMenu *)applicationDockMenu:(NSApplication *)sender { Q_UNUSED(sender); // Manually invoke the delegate's -menuWillOpen: method. // See QTBUG-39604 (and its fix) for details. - [[dockMenu delegate] menuWillOpen:dockMenu]; - return [[dockMenu retain] autorelease]; + [self.dockMenu.delegate menuWillOpen:self.dockMenu]; + return [[self.dockMenu retain] autorelease]; } - (BOOL)canQuit @@ -444,3 +440,48 @@ QT_USE_NAMESPACE } @end + +@implementation QCocoaApplicationDelegate (Menus) + +- (BOOL)validateMenuItem:(NSMenuItem*)item +{ + auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(item); + if (!nativeItem) + return item.enabled; // FIXME Test with with Qt as plugin or embedded QWindow. + + auto *platformItem = nativeItem.platformMenuItem; + if (!platformItem) // Try a bit harder with orphan menu itens + return item.hasSubmenu || (item.enabled && (item.action != @selector(qt_itemFired:))); + + // Menu-holding items are always enabled, as it's conventional in Cocoa + if (platformItem->menu()) + return YES; + + return platformItem->isEnabled(); +} + +@end + +@implementation QCocoaApplicationDelegate (MenuAPI) + +- (void)qt_itemFired:(QCocoaNSMenuItem *)item +{ + if (item.hasSubmenu) + return; + + auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(item); + Q_ASSERT_X(nativeItem, qPrintable(__FUNCTION__), "Triggered menu item is not a QCocoaNSMenuItem."); + auto *platformItem = nativeItem.platformMenuItem; + // Menu-holding items also get a target to play nicely + // with NSMenuValidation but should not trigger. + if (!platformItem || platformItem->menu()) + return; + + QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData); + QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]]; + + static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated); + activatedSignal.invoke(platformItem, Qt::QueuedConnection); +} + +@end diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 2a6c25ed75..3c5f4e68db 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -265,7 +265,7 @@ void QCocoaNativeInterface::setDockMenu(QPlatformMenu *platformMenu) QMacAutoReleasePool pool; QCocoaMenu *cocoaPlatformMenu = static_cast<QCocoaMenu *>(platformMenu); NSMenu *menu = cocoaPlatformMenu->nsMenu(); - [[QCocoaApplicationDelegate sharedDelegate] setDockMenu:menu]; + [QCocoaApplicationDelegate sharedDelegate].dockMenu = menu; } void *QCocoaNativeInterface::qMenuToNSMenu(QPlatformMenu *platformMenu) diff --git a/src/plugins/platforms/cocoa/qnsview_menus.mm b/src/plugins/platforms/cocoa/qnsview_menus.mm index db3d356f2e..f0489552aa 100644 --- a/src/plugins/platforms/cocoa/qnsview_menus.mm +++ b/src/plugins/platforms/cocoa/qnsview_menus.mm @@ -39,6 +39,7 @@ // This file is included from qnsview.mm, and only used to organize the code +#include <qcocoaapplicationdelegate.h> #include <qcocoansmenu.h> #include <qcocoamenuitem.h> #include <qcocoamenu.h> @@ -101,19 +102,8 @@ static bool selectorIsCutCopyPaste(SEL selector) - (void)qt_itemFired:(QCocoaNSMenuItem *)item { - auto *nativeItem = qt_objc_cast<QCocoaNSMenuItem *>(item); - Q_ASSERT_X(nativeItem, qPrintable(__FUNCTION__), "Triggered menu item is not a QCocoaNSMenuItem."); - auto *platformItem = nativeItem.platformMenuItem; - // Menu-holding items also get a target to play nicely - // with NSMenuValidation but should not trigger. - if (!platformItem || platformItem->menu()) - return; - - QScopedScopeLevelCounter scopeLevelCounter(QGuiApplicationPrivate::instance()->threadData); - QGuiApplicationPrivate::modifier_buttons = [QNSView convertKeyModifiers:[NSEvent modifierFlags]]; - - static QMetaMethod activatedSignal = QMetaMethod::fromSignal(&QCocoaMenuItem::activated); - activatedSignal.invoke(platformItem, Qt::QueuedConnection); + auto *appDelegate = [QCocoaApplicationDelegate sharedDelegate]; + [appDelegate qt_itemFired:item]; } - (NSMethodSignature *)methodSignatureForSelector:(SEL)selector |