Cocoa: re-enable getUrl: and appleEventQuit: AppleEvent handlers
authorBradley T. Hughes <bradley.hughes@nokia.com>
Fri, 8 Jun 2012 11:37:27 +0000 (13:37 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 12 Jun 2012 09:19:29 +0000 (11:19 +0200)
The getUrl: and appleEventQuit: handlers are only called if we register
them with the NSAppleEventManager. The Cocoa documentation says the best
place to do this is in the applicationWillFinishLaunching: delegate
method, so add this method and move the code from
qcocoaeventdispatcher.mm to there. Since QCocoaApplicationDelegate is
only used when AA_MacPluginApplication is not set, we do not need to
check again in the delegate code. Be sure to remove these event handlers
when shutting down the application.

For the getUrl: handler, send file open events when receiving this
event. This restores Qt 4 behavior.

Remove the qDebug() from the appleEventQuit: handler.

Change-Id: Ibcbdd541695176e3d236366d4d541e4811882d6c
Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
src/plugins/platforms/cocoa/qcocoaapplicationdelegate.h
src/plugins/platforms/cocoa/qcocoaapplicationdelegate.mm
src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
src/plugins/platforms/cocoa/qcocoaintegration.mm

index 7fa1779..8627153 100644 (file)
 - (QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *)menuLoader;
 - (void)setReflectionDelegate:(NSObject <NSApplicationDelegate> *)oldDelegate;
 - (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent;
+- (void) removeAppleEventHandlers;
 @end
index a2b5374..09dec60 100644 (file)
@@ -217,6 +217,43 @@ static void cleanupCocoaApplicationDelegate()
     return NSTerminateCancel;
 }
 
+- (void) applicationWillFinishLaunching:(NSNotification *)notification
+{
+    Q_UNUSED(notification);
+
+    /*
+        From the Cocoa documentation: "A good place to install event handlers
+        is in the applicationWillFinishLaunching: method of the application
+        delegate. At that point, the Application Kit has installed its default
+        event handlers, so if you install a handler for one of the same events,
+        it will replace the Application Kit version."
+    */
+
+    /*
+        If Qt is used as a plugin, we let the 3rd party application handle
+        events like quit and open file events. Otherwise, if we install our own
+        handlers, we easily end up breaking functionality the 3rd party
+        application depends on.
+     */
+    NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
+    [eventManager setEventHandler:self
+                      andSelector:@selector(appleEventQuit:withReplyEvent:)
+                    forEventClass:kCoreEventClass
+                       andEventID:kAEQuitApplication];
+    [eventManager setEventHandler:self
+                      andSelector:@selector(getUrl:withReplyEvent:)
+                    forEventClass:kInternetEventClass
+                       andEventID:kAEGetURL];
+}
+
+// called by QCocoaIntegration's destructor before resetting the application delegate to nil
+- (void) removeAppleEventHandlers
+{
+    NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
+    [eventManager removeEventHandlerForEventClass:kCoreEventClass andEventID:kAEQuitApplication];
+    [eventManager removeEventHandlerForEventClass:kInternetEventClass andEventID:kAEGetURL];
+}
+
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification
 {
     Q_UNUSED(aNotification);
@@ -347,22 +384,15 @@ static void cleanupCocoaApplicationDelegate()
 
 - (void)getUrl:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
 {
-    Q_UNUSED(event);
     Q_UNUSED(replyEvent);
-/*
     NSString *urlString = [[event paramDescriptorForKeyword:keyDirectObject] stringValue];
-    QUrl url(QCFString::toQString(urlString));
-    QFileOpenEvent qtEvent(url);
-    qt_sendSpontaneousEvent(qAppInstance(), &qtEvent);
-*/
+    QWindowSystemInterface::handleFileOpenEvent(QCFString::toQString(urlString));
 }
 
 - (void)appleEventQuit:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent
 {
     Q_UNUSED(event);
     Q_UNUSED(replyEvent);
-    qDebug() << "appleEventQuit";
-
     [NSApp terminate:self];
 }
 
index ddaa7a7..a00f3eb 100644 (file)
@@ -1042,26 +1042,6 @@ void QCocoaEventDispatcherPrivate::firstLoopEntry(CFRunLoopObserverRef ref,
 {
     Q_UNUSED(ref);
     Q_UNUSED(activity);
-/*
-    // This function is called when NSApplication has finished initialization,
-    // which appears to be just after [NSApplication run] has started to execute.
-    // By setting up our apple events handlers this late, we override the ones
-    // set up by NSApplication.
-
-    // If Qt is used as a plugin, we let the 3rd party application handle events
-    // like quit and open file events. Otherwise, if we install our own handlers, we
-    // easily end up breaking functionallity the 3rd party application depend on:
-    if (QGuiApplication::testAttribute(Qt::AA_MacPluginApplication))
-        return;
-
-    QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *newDelegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
-    NSAppleEventManager *eventManager = [NSAppleEventManager sharedAppleEventManager];
-    [eventManager setEventHandler:newDelegate andSelector:@selector(appleEventQuit:withReplyEvent:)
-     forEventClass:kCoreEventClass andEventID:kAEQuitApplication];
-    [eventManager setEventHandler:newDelegate andSelector:@selector(getUrl:withReplyEvent:)
-      forEventClass:kInternetEventClass andEventID:kAEGetURL];
-*/
-
     static_cast<QCocoaEventDispatcherPrivate *>(info)->processPostedEvents();
 }
 
index 9ea00d3..29c5ec7 100644 (file)
@@ -148,7 +148,13 @@ QCocoaIntegration::QCocoaIntegration()
 
 QCocoaIntegration::~QCocoaIntegration()
 {
-    [[NSApplication sharedApplication] setDelegate: 0];
+    if (!QCoreApplication::testAttribute(Qt::AA_MacPluginApplication)) {
+        // remove the apple event handlers installed by QCocoaApplicationDelegate
+        QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) *delegate = [QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate];
+        [delegate removeAppleEventHandlers];
+        // reset the application delegate
+        [[NSApplication sharedApplication] setDelegate: 0];
+    }
 
     // Delete the clipboard integration and destroy mime type converters.
     // Deleting the clipboard integration flushes promised pastes using