Cocoa: do not terminate applications prematurely
authorBradley T. Hughes <bradley.hughes@nokia.com>
Fri, 8 Jun 2012 11:32:22 +0000 (13:32 +0200)
committerQt by Nokia <qt-info@nokia.com>
Tue, 12 Jun 2012 02:29:56 +0000 (04:29 +0200)
Re-enable application termination as it was in Qt 4.
QApplication::exec() must return to main() so that the destructors in
main() are run.

The QApplicationPrivate::canQuit() function from Qt 4's
qapplication_mac.mm is gone, so bring back this function in
QCocoaApplicationDelegate instead.

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

index 3855563..e3b93af 100644 (file)
 
 #import "qcocoaapplicationdelegate.h"
 #import "qnswindowdelegate.h"
+#import "qcocoamenuloader.h"
 #include <qevent.h>
 #include <qurl.h>
 #include <qdebug.h>
 #include <qguiapplication.h>
+#include <private/qguiapplication_p.h>
 #include "qt_mac_p.h"
 #include <QtGui/QWindowSystemInterface>
 
@@ -169,28 +171,52 @@ static void cleanupCocoaApplicationDelegate()
     return [[qtMenuLoader retain] autorelease];
 }
 
-// This function will only be called when NSApp is actually running. Before
-// that, the kAEQuitApplication Apple event will be sent to
-// QApplicationPrivate::globalAppleEventProcessor in qapplication_mac.mm
+- (BOOL) canQuit
+{
+    [[NSApp mainMenu] cancelTracking];
+
+    bool handle_quit = true;
+    NSMenuItem *quitMenuItem = [[[QT_MANGLE_NAMESPACE(QCocoaApplicationDelegate) sharedDelegate] menuLoader] quitMenuItem];
+    if (!QGuiApplicationPrivate::instance()->modalWindowList.isEmpty()
+        && [quitMenuItem isEnabled]) {
+        int visible = 0;
+        const QWindowList tlws = QGuiApplication::topLevelWindows();
+        for (int i = 0; i < tlws.size(); ++i) {
+            if (tlws.at(i)->isVisible())
+                ++visible;
+        }
+        handle_quit = (visible <= 1);
+    }
+
+    if (handle_quit) {
+        QCloseEvent ev;
+        QGuiApplication::sendEvent(qGuiApp, &ev);
+        if (ev.isAccepted()) {
+            return YES;
+        }
+    }
+
+    return NO;
+}
+
+// This function will only be called when NSApp is actually running.
 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
 {
-    Q_UNUSED(sender);
-/*
     // The reflection delegate gets precedence
     if (reflectionDelegate
         && [reflectionDelegate respondsToSelector:@selector(applicationShouldTerminate:)]) {
         return [reflectionDelegate applicationShouldTerminate:sender];
     }
 
-    if (qtPrivate->canQuit()) {
+    if ([self canQuit]) {
         if (!startedQuit) {
             startedQuit = true;
-            qAppInstance()->quit();
+            QGuiApplication::exit(0);
             startedQuit = false;
         }
     }
 
-    if (qtPrivate->threadData->eventLoops.size() == 0) {
+    if (QGuiApplicationPrivate::instance()->threadData->eventLoops.isEmpty()) {
         // INVARIANT: No event loop is executing. This probably
         // means that Qt is used as a plugin, or as a part of a native
         // Cocoa application. In any case it should be fine to
@@ -199,8 +225,6 @@ static void cleanupCocoaApplicationDelegate()
     }
 
     return NSTerminateCancel;
-*/
-    return NSTerminateNow;
 }
 
 - (void)applicationDidFinishLaunching:(NSNotification *)aNotification