diff options
author | Gabriel de Dietrich <gabriel.dedietrich@qt.io> | 2016-07-21 18:03:27 -0700 |
---|---|---|
committer | Gabriel de Dietrich <gabriel.dedietrich@qt.io> | 2016-07-22 20:07:58 +0000 |
commit | 8ea51f8aaa426fa14393b83082f9eec076d7d72a (patch) | |
tree | 1eab4329fa9910ae5456e7c6ca3b5388494547f4 /src/plugins/platforms | |
parent | 4bbcc054e03152923938adbd610e954578741755 (diff) |
Make QCocoaMenuLoader a singleton
In some auto-tests, we create several instances of
QGuiApplication (though seldom, if ever, simultaneously).
However, the QCocoaMenuLoader instance was never properly
deallocated, resulting in NSApplication.servicesMenu
to still be assigned. This resulted in an exception being
raised (NSInternalInconsistencyException) the second time
we would construct a QCocoaMenuLoader.
The CPU cycles saving solution is to make QCocoaMenuLoader
a singleton. This approach is also safe since this class'
initialization doesn't depend on any state in QGuiApplication
(even the application name is fetched from either the main
bundle or the app's args).
This also allows us to clean up some code in QCocoaApplication
and QCocoaApplicationDelegate who have suffered from lack of
attention over the years.
Change-Id: Ic4c859d628ab8abd9b469b99c64293582f8e363d
Reviewed-by: Morten Johan Sørvig <morten.sorvig@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms')
5 files changed, 19 insertions, 12 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h index 68a028ed8a..68ee92ad05 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h @@ -95,7 +95,6 @@ @interface QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) : NSObject <NSApplicationDelegate> { bool startedQuit; NSMenu *dockMenu; - QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader; NSObject <NSApplicationDelegate> *reflectionDelegate; bool inLaunch; } diff --git a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm index d18df35b80..d32a6fede4 100644 --- a/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm +++ b/src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm @@ -122,7 +122,6 @@ QT_END_NAMESPACE { sharedCocoaApplicationDelegate = nil; [dockMenu release]; - [qtMenuLoader release]; if (reflectionDelegate) { [[NSApplication sharedApplication] setDelegate:reflectionDelegate]; [reflectionDelegate release]; @@ -171,14 +170,13 @@ QT_END_NAMESPACE - (void)setMenuLoader:(QCocoaMenuLoader *)menuLoader { - [menuLoader retain]; - [qtMenuLoader release]; - qtMenuLoader = menuLoader; + Q_UNUSED(menuLoader); + qWarning("-[QCocoaApplicationDelegate setMenuLoader:] is deprecated and is currently a no-op."); } - (QCocoaMenuLoader *)menuLoader { - return [[qtMenuLoader retain] autorelease]; + return [QT_MANGLE_NAMESPACE(QCocoaMenuLoader) sharedMenuLoader]; } - (BOOL) canQuit @@ -450,7 +448,7 @@ QT_END_NAMESPACE - (void)qtDispatcherToQAction:(id)sender { Q_UNUSED(sender); - [qtMenuLoader qtDispatcherToQPAMenuItem:sender]; + [[self menuLoader] qtDispatcherToQPAMenuItem:sender]; } @end diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 21a2ba3611..c3890bcd46 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -331,9 +331,8 @@ QCocoaIntegration::QCocoaIntegration(const QStringList ¶mList) [cocoaApplication setDelegate:newDelegate]; // Load the application menu. This menu contains Preferences, Hide, Quit. - QCocoaMenuLoader *qtMenuLoader = [[QCocoaMenuLoader alloc] init]; + QCocoaMenuLoader *qtMenuLoader = [QCocoaMenuLoader sharedMenuLoader]; [cocoaApplication setMenu:[qtMenuLoader menu]]; - [newDelegate setMenuLoader:qtMenuLoader]; } // The presentation options such as whether or not the dock and/or menu bar is diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.h b/src/plugins/platforms/cocoa/qcocoamenuloader.h index d1f47b18f0..95f347646c 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.h +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.h @@ -68,6 +68,7 @@ NSMenuItem *hideAllOthersItem; NSMenuItem *showAllItem; } ++ (instancetype)sharedMenuLoader; - (instancetype)init; - (void)ensureAppMenuInMenu:(NSMenu *)menu; - (void)removeActionsFromAppMenu; diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index 9b16999d48..22e90f8dc8 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -57,6 +57,16 @@ QT_FORWARD_DECLARE_CLASS(QString) @implementation QCocoaMenuLoader ++ (instancetype)sharedMenuLoader +{ + static QCocoaMenuLoader *shared = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + shared = [[self alloc] init]; + }); + return shared; +} + - (instancetype)init { if ((self = [super init])) { @@ -108,9 +118,9 @@ QT_FORWARD_DECLARE_CLASS(QString) // Services item and menu servicesItem = [[NSMenuItem alloc] init]; servicesItem.title = @"Services"; - NSApplication *app = [NSApplication sharedApplication]; - app.servicesMenu = [[[NSMenu alloc] initWithTitle:@"Services"] autorelease]; - servicesItem.submenu = app.servicesMenu; + NSMenu *servicesMenu = [[[NSMenu alloc] initWithTitle:@"Services"] autorelease]; + servicesItem.submenu = servicesMenu; + [NSApplication sharedApplication].servicesMenu = servicesMenu; [appMenu addItem:servicesItem]; [appMenu addItem:[NSMenuItem separatorItem]]; |