summaryrefslogtreecommitdiffstats
path: root/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm95
1 files changed, 69 insertions, 26 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
index a94e0dc517..221a8b0866 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,9 +73,12 @@
#import "qcocoaapplicationdelegate.h"
-#import "qnswindowdelegate.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>
@@ -86,7 +89,11 @@
QT_USE_NAMESPACE
-@implementation QCocoaApplicationDelegate
+@implementation QCocoaApplicationDelegate {
+ bool startedQuit;
+ NSObject <NSApplicationDelegate> *reflectionDelegate;
+ bool inLaunch;
+}
+ (instancetype)sharedDelegate
{
@@ -102,7 +109,7 @@ QT_USE_NAMESPACE
return shared;
}
-- (id)init
+- (instancetype)init
{
self = [super init];
if (self) {
@@ -125,7 +132,7 @@ QT_USE_NAMESPACE
- (void)dealloc
{
- [dockMenu release];
+ [_dockMenu release];
if (reflectionDelegate) {
[[NSApplication sharedApplication] setDelegate:reflectionDelegate];
[reflectionDelegate release];
@@ -135,23 +142,16 @@ 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
+- (BOOL)canQuit
{
[[NSApp mainMenu] cancelTracking];
@@ -219,7 +219,7 @@ QT_USE_NAMESPACE
return NSTerminateCancel;
}
-- (void) applicationWillFinishLaunching:(NSNotification *)notification
+- (void)applicationWillFinishLaunching:(NSNotification *)notification
{
Q_UNUSED(notification);
@@ -249,14 +249,14 @@ QT_USE_NAMESPACE
}
// called by QCocoaIntegration's destructor before resetting the application delegate to nil
-- (void) removeAppleEventHandlers
+- (void)removeAppleEventHandlers
{
NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
[eventManager removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEQuitApplication];
[eventManager removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL];
}
-- (bool) inLaunch
+- (bool)inLaunch
{
return inLaunch;
}
@@ -267,13 +267,11 @@ QT_USE_NAMESPACE
inLaunch = false;
if (qEnvironmentVariableIsEmpty("QT_MAC_DISABLE_FOREGROUND_APPLICATION_TRANSFORM")) {
- if (__builtin_available(macOS 10.12, *)) {
- // Move the application window to front to avoid launching behind the terminal.
- // Ignoring other apps is necessary (we must ignore the terminal), but makes
- // Qt apps play slightly less nice with other apps when lanching from Finder
- // (See the activateIgnoringOtherApps docs.)
- [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
- }
+ // Move the application window to front to avoid launching behind the terminal.
+ // Ignoring other apps is necessary (we must ignore the terminal), but makes
+ // Qt apps play slightly less nice with other apps when lanching from Finder
+ // (See the activateIgnoringOtherApps docs.)
+ [[NSApplication sharedApplication] activateIgnoringOtherApps:YES];
}
}
@@ -440,3 +438,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