src/video/uikit/SDL_uikitappdelegate.m
author Sam Lantinga <slouken@libsdl.org>
Sun, 14 Oct 2012 01:05:04 -0700
changeset 6587 4ef7c70295c9
parent 6557 87ba88e3f2a9
child 6885 700f1b25f77f
permissions -rw-r--r--
Implemented drop events in iOS
     1 /*
     2   Simple DirectMedia Layer
     3   Copyright (C) 1997-2012 Sam Lantinga <slouken@libsdl.org>
     4 
     5   This software is provided 'as-is', without any express or implied
     6   warranty.  In no event will the authors be held liable for any damages
     7   arising from the use of this software.
     8 
     9   Permission is granted to anyone to use this software for any purpose,
    10   including commercial applications, and to alter it and redistribute it
    11   freely, subject to the following restrictions:
    12 
    13   1. The origin of this software must not be misrepresented; you must not
    14      claim that you wrote the original software. If you use this software
    15      in a product, an acknowledgment in the product documentation would be
    16      appreciated but is not required.
    17   2. Altered source versions must be plainly marked as such, and must not be
    18      misrepresented as being the original software.
    19   3. This notice may not be removed or altered from any source distribution.
    20 */
    21 #include "SDL_config.h"
    22 
    23 #if SDL_VIDEO_DRIVER_UIKIT
    24 
    25 #include "../SDL_sysvideo.h"
    26 #include "SDL_assert.h"
    27 #include "SDL_hints.h"
    28 #include "../../SDL_hints_c.h"
    29 #include "SDL_system.h"
    30 
    31 #include "SDL_uikitappdelegate.h"
    32 #include "SDL_uikitmodes.h"
    33 #include "../../events/SDL_events_c.h"
    34 #include "jumphack.h"
    35 
    36 #ifdef main
    37 #undef main
    38 #endif
    39 
    40 extern int SDL_main(int argc, char *argv[]);
    41 static int forward_argc;
    42 static char **forward_argv;
    43 static int exit_status;
    44 static UIWindow *launch_window;
    45 
    46 int main(int argc, char **argv)
    47 {
    48     int i;
    49     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    50 
    51     /* store arguments */
    52     forward_argc = argc;
    53     forward_argv = (char **)malloc((argc+1) * sizeof(char *));
    54     for (i = 0; i < argc; i++) {
    55         forward_argv[i] = malloc( (strlen(argv[i])+1) * sizeof(char));
    56         strcpy(forward_argv[i], argv[i]);
    57     }
    58     forward_argv[i] = NULL;
    59 
    60     /* Give over control to run loop, SDLUIKitDelegate will handle most things from here */
    61     UIApplicationMain(argc, argv, NULL, [SDLUIKitDelegate getAppDelegateClassName]);
    62 
    63     /* free the memory we used to hold copies of argc and argv */
    64     for (i = 0; i < forward_argc; i++) {
    65         free(forward_argv[i]);
    66     }
    67     free(forward_argv);
    68 
    69     [pool release];
    70     return exit_status;
    71 }
    72 
    73 static void SDL_IdleTimerDisabledChanged(const char *name, const char *oldValue, const char *newValue)
    74 {
    75     SDL_assert(SDL_strcmp(name, SDL_HINT_IDLE_TIMER_DISABLED) == 0);
    76 
    77     BOOL disable = (*newValue != '0');
    78     [UIApplication sharedApplication].idleTimerDisabled = disable;
    79 }
    80 
    81 @interface SDL_splashviewcontroller : UIViewController {
    82     UIImageView *splash;
    83     UIImage *splashPortrait;
    84     UIImage *splashLandscape;
    85 }
    86 
    87 - (void)updateSplashImage:(UIInterfaceOrientation)interfaceOrientation;
    88 @end
    89 
    90 @implementation SDL_splashviewcontroller
    91 
    92 - (id)init
    93 {
    94     self = [super init];
    95     if (self == nil) {
    96         return nil;
    97     }
    98 
    99     self->splash = [[UIImageView alloc] init];
   100     [self setView:self->splash];
   101 
   102     CGSize size = [UIScreen mainScreen].bounds.size;
   103     float height = SDL_max(size.width, size.height);
   104     self->splashPortrait = [UIImage imageNamed:[NSString stringWithFormat:@"Default-%dh.png", (int)height]];
   105     if (!self->splashPortrait) {
   106         self->splashPortrait = [UIImage imageNamed:@"Default.png"];
   107     }
   108     self->splashLandscape = [UIImage imageNamed:@"Default-Landscape.png"];
   109     if (!self->splashLandscape && self->splashPortrait) {
   110         self->splashLandscape = [[UIImage alloc] initWithCGImage: self->splashPortrait.CGImage
   111                                                            scale: 1.0
   112                                                      orientation: UIImageOrientationRight];
   113     }
   114     if (self->splashPortrait) {
   115         [self->splashPortrait retain];
   116     }
   117     if (self->splashLandscape) {
   118         [self->splashLandscape retain];
   119     }
   120  
   121     [self updateSplashImage:[[UIApplication sharedApplication] statusBarOrientation]];
   122 
   123     return self;
   124 }
   125 
   126 - (NSUInteger)supportedInterfaceOrientations
   127 {
   128     NSUInteger orientationMask = UIInterfaceOrientationMaskAll;
   129     
   130     // Don't allow upside-down orientation on the phone, so answering calls is in the natural orientation
   131     if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
   132         orientationMask &= ~UIInterfaceOrientationMaskPortraitUpsideDown;
   133     }
   134     return orientationMask;
   135 }
   136 
   137 - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orient
   138 {
   139     NSUInteger orientationMask = [self supportedInterfaceOrientations];
   140     return (orientationMask & (1 << orient));
   141 }
   142 
   143 - (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation duration:(NSTimeInterval)duration
   144 {
   145     [self updateSplashImage:interfaceOrientation];
   146 }
   147 
   148 - (void)updateSplashImage:(UIInterfaceOrientation)interfaceOrientation
   149 {
   150     UIImage *image;
   151     
   152     if (UIInterfaceOrientationIsLandscape(interfaceOrientation)) {
   153         image = self->splashLandscape;
   154     } else {
   155         image = self->splashPortrait;
   156     }
   157     if (image)
   158     {
   159         splash.image = image;
   160     }
   161 }
   162 
   163 @end
   164 
   165 
   166 @implementation SDLUIKitDelegate
   167 
   168 /* convenience method */
   169 + (id) sharedAppDelegate
   170 {
   171     /* the delegate is set in UIApplicationMain(), which is garaunteed to be called before this method */
   172     return [[UIApplication sharedApplication] delegate];
   173 }
   174 
   175 + (NSString *)getAppDelegateClassName
   176 {
   177     /* subclassing notice: when you subclass this appdelegate, make sure to add a category to override
   178        this method and return the actual name of the delegate */
   179     return @"SDLUIKitDelegate";
   180 }
   181 
   182 - (id)init
   183 {
   184     self = [super init];
   185     return self;
   186 }
   187 
   188 - (void)postFinishLaunch
   189 {
   190     /* run the user's application, passing argc and argv */
   191     SDL_iPhoneSetEventPump(SDL_TRUE);
   192     exit_status = SDL_main(forward_argc, forward_argv);
   193     SDL_iPhoneSetEventPump(SDL_FALSE);
   194 
   195     /* If we showed a splash image, clean it up */
   196     if (launch_window) {
   197         [launch_window release];
   198         launch_window = NULL;
   199     }
   200 
   201     /* exit, passing the return status from the user's application */
   202     // We don't actually exit to support applications that do setup in
   203     // their main function and then allow the Cocoa event loop to run.
   204     // exit(exit_status);
   205 }
   206 
   207 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
   208 {
   209     /* Keep the launch image up until we set a video mode */
   210     launch_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
   211 
   212     UIViewController *splashViewController = [[SDL_splashviewcontroller alloc] init];
   213     launch_window.rootViewController = splashViewController;
   214     [launch_window addSubview:splashViewController.view];
   215     [launch_window makeKeyAndVisible];
   216 
   217     /* Set working directory to resource path */
   218     [[NSFileManager defaultManager] changeCurrentDirectoryPath: [[NSBundle mainBundle] resourcePath]];
   219 
   220     /* register a callback for the idletimer hint */
   221     SDL_SetHint(SDL_HINT_IDLE_TIMER_DISABLED, "0");
   222     SDL_RegisterHintChangedCb(SDL_HINT_IDLE_TIMER_DISABLED, &SDL_IdleTimerDisabledChanged);
   223 
   224     [self performSelector:@selector(postFinishLaunch) withObject:nil afterDelay:0.0];
   225 
   226     return YES;
   227 }
   228 
   229 - (void)applicationWillTerminate:(UIApplication *)application
   230 {
   231     SDL_SendQuit();
   232      /* hack to prevent automatic termination.  See SDL_uikitevents.m for details */
   233     longjmp(*(jump_env()), 1);
   234 }
   235 
   236 - (void) applicationWillResignActive:(UIApplication*)application
   237 {
   238     //NSLog(@"%@", NSStringFromSelector(_cmd));
   239 
   240     // Send every window on every screen a MINIMIZED event.
   241     SDL_VideoDevice *_this = SDL_GetVideoDevice();
   242     if (!_this) {
   243         return;
   244     }
   245 
   246     SDL_Window *window;
   247     for (window = _this->windows; window != nil; window = window->next) {
   248         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
   249         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
   250     }
   251 }
   252 
   253 - (void) applicationDidBecomeActive:(UIApplication*)application
   254 {
   255     //NSLog(@"%@", NSStringFromSelector(_cmd));
   256 
   257     // Send every window on every screen a RESTORED event.
   258     SDL_VideoDevice *_this = SDL_GetVideoDevice();
   259     if (!_this) {
   260         return;
   261     }
   262 
   263     SDL_Window *window;
   264     for (window = _this->windows; window != nil; window = window->next) {
   265         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
   266         SDL_SendWindowEvent(window, SDL_WINDOWEVENT_RESTORED, 0, 0);
   267     }
   268 }
   269 
   270 - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
   271 {
   272     NSURL *fileURL = [url filePathURL];
   273     if (fileURL != nil) {
   274         SDL_SendDropFile([[fileURL path] UTF8String]);
   275     } else {
   276         SDL_SendDropFile([[url absoluteString] UTF8String]);
   277     }
   278     return YES;
   279 }
   280 
   281 @end
   282 
   283 #endif /* SDL_VIDEO_DRIVER_UIKIT */
   284 
   285 /* vi: set ts=4 sw=4 expandtab: */