Mac: Better handling when someone else is the app delegate.
authorJørgen P. Tjernø <jorgen@valvesoftware.com>
Mon, 07 Oct 2013 16:01:40 -0700
changeset 7801 f00cc0a8cd5d
parent 7800 76e4b6825efc
child 7802 d239ba573818
Mac: Better handling when someone else is the app delegate.
README-macosx.txt
src/video/cocoa/SDL_cocoaevents.m
--- a/README-macosx.txt	Thu Oct 10 02:37:36 2013 -0400
+++ b/README-macosx.txt	Mon Oct 07 16:01:40 2013 -0700
@@ -30,6 +30,42 @@
 use the traditional autoconf/automake/make method, or use Xcode.
 
 ==============================================================================
+Caveats for using SDL with Mac OS X
+==============================================================================
+
+Some things you have to be aware of when using SDL on Mac OS X:
+
+- If you register your own NSApplicationDelegate (using [NSApp setDelegate:]),
+  SDL will not register its own. This means that SDL will not terminate using
+  SDL_Quit if it receives a termination request, it will terminate like a 
+  normal app, and it will not send a SDL_DROPFILE when you request to open a
+  file with the app. To solve these issues, put the following code in your 
+  NSApplicationDelegate implementation:
+
+  - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
+  {
+      if (SDL_GetEventState(SDL_QUIT) == SDL_ENABLE) {
+          SDL_Event event;
+          event.type = SDL_QUIT;
+          SDL_PushEvent(&event);
+      }
+
+      return NSTerminateCancel;
+  }
+
+  - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename
+  {
+      if (SDL_GetEventState(SDL_DROPFILE) == SDL_ENABLE) {
+          SDL_Event event;
+          event.type = SDL_DROPFILE;
+          event.drop.file = SDL_strdup([filename UTF8String]);
+          return (SDL_PushEvent(&event) > 0);
+      }
+
+      return NO;
+  }
+
+==============================================================================
 Using the Simple DirectMedia Layer with a traditional Makefile
 ==============================================================================
 
--- a/src/video/cocoa/SDL_cocoaevents.m	Thu Oct 10 02:37:36 2013 -0400
+++ b/src/video/cocoa/SDL_cocoaevents.m	Mon Oct 07 16:01:40 2013 -0700
@@ -42,12 +42,11 @@
 @end
 
 @interface SDLAppDelegate : NSObject {
+@public
     BOOL seenFirstActivate;
 }
 
 - (id)init;
-- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
-- (void)applicationDidBecomeActive:(NSNotification *)aNotification;
 @end
 
 @implementation SDLAppDelegate : NSObject
@@ -57,18 +56,28 @@
 
     if (self) {
         seenFirstActivate = NO;
+        [[NSNotificationCenter defaultCenter] addObserver:self
+                                                 selector:@selector(focusSomeWindow:)
+                                                     name:NSApplicationDidBecomeActiveNotification
+                                                   object:nil];
     }
 
     return self;
 }
 
+- (void)dealloc
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:self];
+    [super dealloc];
+}
+
 - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
 {
     SDL_SendQuit();
     return NSTerminateCancel;
 }
 
-- (void)applicationDidBecomeActive:(NSNotification *)aNotification
+- (void)focusSomeWindow:(NSNotification *)aNotification
 {
     /* HACK: Ignore the first call. The application gets a
      * applicationDidBecomeActive: a little bit after the first window is
@@ -111,6 +120,8 @@
 }
 @end
 
+static SDLAppDelegate *appDelegate = nil;
+
 static NSString *
 GetApplicationName(void)
 {
@@ -235,8 +246,17 @@
         [[NSUserDefaults standardUserDefaults] registerDefaults:appDefaults];
 
     }
-    if (NSApp && ![NSApp delegate]) {
-        [NSApp setDelegate:[[SDLAppDelegate alloc] init]];
+    if (NSApp && !appDelegate) {
+        appDelegate = [[SDLAppDelegate alloc] init];
+
+        /* If someone else has an app delegate, it means we can't turn a
+         * termination into SDL_Quit, and we can't handle application:openFile:
+         */
+        if (![NSApp delegate]) {
+            [NSApp setDelegate:appDelegate];
+        } else {
+            appDelegate->seenFirstActivate = YES;
+        }
     }
     [pool release];
 }