Browse Source

Mac: Better handling when someone else is the app delegate.

J?rgen P. Tjern? 12 years ago
parent
commit
2568a367c8
2 changed files with 61 additions and 5 deletions
  1. 36 0
      README-macosx.txt
  2. 25 5
      src/video/cocoa/SDL_cocoaevents.m

+ 36 - 0
README-macosx.txt

@@ -29,6 +29,42 @@ gcc to make this easy is provided in test/gcc-fat.sh
 To use the library once it's built, you essential have two possibilities:
 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
 ==============================================================================

+ 25 - 5
src/video/cocoa/SDL_cocoaevents.m

@@ -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 @@ Cocoa_RegisterApp(void)
         [[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];
 }