Skip to content

Latest commit

 

History

History
516 lines (424 loc) · 16.8 KB

SDL_uikitappdelegate.m

File metadata and controls

516 lines (424 loc) · 16.8 KB
 
1
2
/*
Simple DirectMedia Layer
Jan 3, 2018
Jan 3, 2018
3
Copyright (C) 1997-2018 Sam Lantinga <slouken@libsdl.org>
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
#include "../../SDL_internal.h"
#if SDL_VIDEO_DRIVER_UIKIT
#include "../SDL_sysvideo.h"
#include "SDL_assert.h"
#include "SDL_hints.h"
#include "SDL_system.h"
#include "SDL_main.h"
#import "SDL_uikitappdelegate.h"
#import "SDL_uikitmodes.h"
#import "SDL_uikitwindow.h"
#include "../../events/SDL_events_c.h"
#ifdef main
#undef main
#endif
static int forward_argc;
static char **forward_argv;
static int exit_status;
int main(int argc, char **argv)
{
int i;
/* store arguments */
forward_argc = argc;
forward_argv = (char **)malloc((argc+1) * sizeof(char *));
for (i = 0; i < argc; i++) {
forward_argv[i] = malloc( (strlen(argv[i])+1) * sizeof(char));
strcpy(forward_argv[i], argv[i]);
}
forward_argv[i] = NULL;
/* Give over control to run loop, SDLUIKitDelegate will handle most things from here */
@autoreleasepool {
UIApplicationMain(argc, argv, nil, [SDLUIKitDelegate getAppDelegateClassName]);
}
/* free the memory we used to hold copies of argc and argv */
for (i = 0; i < forward_argc; i++) {
free(forward_argv[i]);
}
free(forward_argv);
return exit_status;
}
Aug 14, 2017
Aug 14, 2017
72
static void SDLCALL
73
74
75
76
77
78
SDL_IdleTimerDisabledChanged(void *userdata, const char *name, const char *oldValue, const char *hint)
{
BOOL disable = (hint && *hint != '0');
[UIApplication sharedApplication].idleTimerDisabled = disable;
}
Sep 14, 2016
Sep 14, 2016
79
#if !TARGET_OS_TV
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
/* Load a launch image using the old UILaunchImageFile-era naming rules. */
static UIImage *
SDL_LoadLaunchImageNamed(NSString *name, int screenh)
{
UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
UIUserInterfaceIdiom idiom = [UIDevice currentDevice].userInterfaceIdiom;
UIImage *image = nil;
if (idiom == UIUserInterfaceIdiomPhone && screenh == 568) {
/* The image name for the iPhone 5 uses its height as a suffix. */
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-568h", name]];
} else if (idiom == UIUserInterfaceIdiomPad) {
/* iPad apps can launch in any orientation. */
if (UIInterfaceOrientationIsLandscape(curorient)) {
if (curorient == UIInterfaceOrientationLandscapeLeft) {
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-LandscapeLeft", name]];
} else {
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-LandscapeRight", name]];
}
if (!image) {
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-Landscape", name]];
}
} else {
if (curorient == UIInterfaceOrientationPortraitUpsideDown) {
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-PortraitUpsideDown", name]];
}
if (!image) {
image = [UIImage imageNamed:[NSString stringWithFormat:@"%@-Portrait", name]];
}
}
}
if (!image) {
image = [UIImage imageNamed:name];
}
return image;
}
Sep 14, 2016
Sep 14, 2016
118
119
120
121
122
123
124
125
126
#endif /* !TARGET_OS_TV */
@interface SDLLaunchScreenController ()
#if !TARGET_OS_TV
- (NSUInteger)supportedInterfaceOrientations;
#endif
@end
127
128
129
130
@implementation SDLLaunchScreenController
- (instancetype)init
Sep 25, 2016
Sep 25, 2016
131
132
133
134
135
{
return [self initWithNibName:nil bundle:[NSBundle mainBundle]];
}
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
136
137
138
139
140
{
if (!(self = [super initWithNibName:nil bundle:nil])) {
return nil;
}
Sep 25, 2016
Sep 25, 2016
141
142
NSString *screenname = nibNameOrNil;
NSBundle *bundle = nibBundleOrNil;
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
BOOL atleastiOS8 = UIKit_IsSystemVersionAtLeast(8.0);
/* Launch screens were added in iOS 8. Otherwise we use launch images. */
if (screenname && atleastiOS8) {
@try {
self.view = [bundle loadNibNamed:screenname owner:self options:nil][0];
}
@catch (NSException *exception) {
/* If a launch screen name is specified but it fails to load, iOS
* displays a blank screen rather than falling back to an image. */
return nil;
}
}
if (!self.view) {
NSArray *launchimages = [bundle objectForInfoDictionaryKey:@"UILaunchImages"];
NSString *imagename = nil;
UIImage *image = nil;
int screenw = (int)([UIScreen mainScreen].bounds.size.width + 0.5);
int screenh = (int)([UIScreen mainScreen].bounds.size.height + 0.5);
Sep 25, 2016
Sep 25, 2016
165
166
167
#if !TARGET_OS_TV
UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
168
169
170
171
172
173
/* We always want portrait-oriented size, to match UILaunchImageSize. */
if (screenw > screenh) {
int width = screenw;
screenw = screenh;
screenh = width;
}
Sep 25, 2016
Sep 25, 2016
174
#endif
175
176
177
178
/* Xcode 5 introduced a dictionary of launch images in Info.plist. */
if (launchimages) {
for (NSDictionary *dict in launchimages) {
Sep 25, 2016
Sep 25, 2016
179
180
NSString *minversion = dict[@"UILaunchImageMinimumOSVersion"];
NSString *sizestring = dict[@"UILaunchImageSize"];
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/* Ignore this image if the current version is too low. */
if (minversion && !UIKit_IsSystemVersionAtLeast(minversion.doubleValue)) {
continue;
}
/* Ignore this image if the size doesn't match. */
if (sizestring) {
CGSize size = CGSizeFromString(sizestring);
if ((int)(size.width + 0.5) != screenw || (int)(size.height + 0.5) != screenh) {
continue;
}
}
Sep 25, 2016
Sep 25, 2016
195
196
197
198
#if !TARGET_OS_TV
UIInterfaceOrientationMask orientmask = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
NSString *orientstring = dict[@"UILaunchImageOrientation"];
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
if (orientstring) {
if ([orientstring isEqualToString:@"PortraitUpsideDown"]) {
orientmask = UIInterfaceOrientationMaskPortraitUpsideDown;
} else if ([orientstring isEqualToString:@"Landscape"]) {
orientmask = UIInterfaceOrientationMaskLandscape;
} else if ([orientstring isEqualToString:@"LandscapeLeft"]) {
orientmask = UIInterfaceOrientationMaskLandscapeLeft;
} else if ([orientstring isEqualToString:@"LandscapeRight"]) {
orientmask = UIInterfaceOrientationMaskLandscapeRight;
}
}
/* Ignore this image if the orientation doesn't match. */
if ((orientmask & (1 << curorient)) == 0) {
continue;
}
Sep 25, 2016
Sep 25, 2016
215
#endif
216
217
218
219
220
221
222
imagename = dict[@"UILaunchImageName"];
}
if (imagename) {
image = [UIImage imageNamed:imagename];
}
Sep 25, 2016
Sep 25, 2016
223
224
225
}
#if !TARGET_OS_TV
else {
226
227
228
229
230
231
232
233
234
235
imagename = [bundle objectForInfoDictionaryKey:@"UILaunchImageFile"];
if (imagename) {
image = SDL_LoadLaunchImageNamed(imagename, screenh);
}
if (!image) {
image = SDL_LoadLaunchImageNamed(@"Default", screenh);
}
}
Sep 25, 2016
Sep 25, 2016
236
#endif
237
238
239
240
241
if (image) {
UIImageView *view = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIImageOrientation imageorient = UIImageOrientationUp;
Sep 25, 2016
Sep 25, 2016
242
#if !TARGET_OS_TV
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/* Bugs observed / workaround tested in iOS 8.3, 7.1, and 6.1. */
if (UIInterfaceOrientationIsLandscape(curorient)) {
if (atleastiOS8 && image.size.width < image.size.height) {
/* On iOS 8, portrait launch images displayed in forced-
* landscape mode (e.g. a standard Default.png on an iPhone
* when Info.plist only supports landscape orientations) need
* to be rotated to display in the expected orientation. */
if (curorient == UIInterfaceOrientationLandscapeLeft) {
imageorient = UIImageOrientationRight;
} else if (curorient == UIInterfaceOrientationLandscapeRight) {
imageorient = UIImageOrientationLeft;
}
} else if (!atleastiOS8 && image.size.width > image.size.height) {
/* On iOS 7 and below, landscape launch images displayed in
* landscape mode (e.g. landscape iPad launch images) need
* to be rotated to display in the expected orientation. */
if (curorient == UIInterfaceOrientationLandscapeLeft) {
imageorient = UIImageOrientationLeft;
} else if (curorient == UIInterfaceOrientationLandscapeRight) {
imageorient = UIImageOrientationRight;
}
}
}
Sep 25, 2016
Sep 25, 2016
266
#endif
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
/* Create the properly oriented image. */
view.image = [[UIImage alloc] initWithCGImage:image.CGImage scale:image.scale orientation:imageorient];
self.view = view;
}
}
return self;
}
- (void)loadView
{
/* Do nothing. */
}
Sep 14, 2016
Sep 14, 2016
283
#if !TARGET_OS_TV
284
285
286
287
288
289
290
291
292
293
294
295
296
- (BOOL)shouldAutorotate
{
/* If YES, the launch image will be incorrectly rotated in some cases. */
return NO;
}
- (NSUInteger)supportedInterfaceOrientations
{
/* We keep the supported orientations unrestricted to avoid the case where
* there are no common orientations between the ones set in Info.plist and
* the ones set here (it will cause an exception in that case.) */
return UIInterfaceOrientationMaskAll;
}
Sep 14, 2016
Sep 14, 2016
297
#endif /* !TARGET_OS_TV */
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
@end
@implementation SDLUIKitDelegate {
UIWindow *launchWindow;
}
/* convenience method */
+ (id)sharedAppDelegate
{
/* the delegate is set in UIApplicationMain(), which is guaranteed to be
* called before this method */
return [UIApplication sharedApplication].delegate;
}
+ (NSString *)getAppDelegateClassName
{
/* subclassing notice: when you subclass this appdelegate, make sure to add
* a category to override this method and return the actual name of the
* delegate */
return @"SDLUIKitDelegate";
}
- (void)hideLaunchScreen
{
UIWindow *window = launchWindow;
if (!window || window.hidden) {
return;
}
launchWindow = nil;
/* Do a nice animated fade-out (roughly matches the real launch behavior.) */
[UIView animateWithDuration:0.2 animations:^{
window.alpha = 0.0;
} completion:^(BOOL finished) {
window.hidden = YES;
}];
}
- (void)postFinishLaunch
{
/* Hide the launch screen the next time the run loop is run. SDL apps will
* have a chance to load resources while the launch screen is still up. */
[self performSelector:@selector(hideLaunchScreen) withObject:nil afterDelay:0.0];
/* run the user's application, passing argc and argv */
SDL_iPhoneSetEventPump(SDL_TRUE);
exit_status = SDL_main(forward_argc, forward_argv);
SDL_iPhoneSetEventPump(SDL_FALSE);
if (launchWindow) {
launchWindow.hidden = YES;
launchWindow = nil;
}
/* exit, passing the return status from the user's application */
/* We don't actually exit to support applications that do setup in their
* main function and then allow the Cocoa event loop to run. */
/* exit(exit_status); */
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSBundle *bundle = [NSBundle mainBundle];
#if SDL_IPHONE_LAUNCHSCREEN
/* The normal launch screen is displayed until didFinishLaunching returns,
* but SDL_main is called after that happens and there may be a noticeable
* delay between the start of SDL_main and when the first real frame is
* displayed (e.g. if resources are loaded before SDL_GL_SwapWindow is
* called), so we show the launch screen programmatically until the first
* time events are pumped. */
Sep 25, 2016
Sep 25, 2016
372
UIViewController *vc = nil;
Sep 25, 2016
Sep 25, 2016
373
NSString *screenname = nil;
Sep 25, 2016
Sep 25, 2016
374
Sep 25, 2016
Sep 25, 2016
375
/* tvOS only uses a plain launch image. */
Sep 25, 2016
Sep 25, 2016
376
#if !TARGET_OS_TV
Sep 25, 2016
Sep 25, 2016
377
screenname = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
Sep 25, 2016
Sep 25, 2016
378
379
380
381
382
383
384
385
386
387
388
389
390
if (screenname && UIKit_IsSystemVersionAtLeast(8.0)) {
@try {
/* The launch storyboard is actually a nib in some older versions of
* Xcode. We'll try to load it as a storyboard first, as it's more
* modern. */
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:screenname bundle:bundle];
vc = [storyboard instantiateInitialViewController];
}
@catch (NSException *exception) {
/* Do nothing (there's more code to execute below). */
}
}
Sep 25, 2016
Sep 25, 2016
391
#endif
Sep 25, 2016
Sep 25, 2016
392
393
394
395
if (vc == nil) {
vc = [[SDLLaunchScreenController alloc] initWithNibName:screenname bundle:bundle];
}
Sep 25, 2016
Sep 25, 2016
397
if (vc.view) {
398
399
400
401
402
403
404
405
406
407
launchWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
/* We don't want the launch window immediately hidden when a real SDL
* window is shown - we fade it out ourselves when we're ready. */
launchWindow.windowLevel = UIWindowLevelNormal + 1.0;
/* Show the window but don't make it key. Events should always go to
* other windows when possible. */
launchWindow.hidden = NO;
Sep 25, 2016
Sep 25, 2016
408
launchWindow.rootViewController = vc;
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
}
#endif
/* Set working directory to resource path */
[[NSFileManager defaultManager] changeCurrentDirectoryPath:[bundle resourcePath]];
/* register a callback for the idletimer hint */
SDL_AddHintCallback(SDL_HINT_IDLE_TIMER_DISABLED,
SDL_IdleTimerDisabledChanged, NULL);
SDL_SetMainReady();
[self performSelector:@selector(postFinishLaunch) withObject:nil afterDelay:0.0];
return YES;
}
Dec 18, 2016
Dec 18, 2016
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
- (UIWindow *)window
{
SDL_VideoDevice *_this = SDL_GetVideoDevice();
if (_this) {
SDL_Window *window = NULL;
for (window = _this->windows; window != NULL; window = window->next) {
SDL_WindowData *data = (__bridge SDL_WindowData *) window->driverdata;
if (data != nil) {
return data.uiwindow;
}
}
}
return nil;
}
- (void)setWindow:(UIWindow *)window
{
/* Do nothing. */
}
Sep 14, 2016
Sep 14, 2016
445
#if !TARGET_OS_TV
446
447
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation
{
Aug 23, 2018
Aug 23, 2018
448
SDL_OnApplicationDidChangeStatusBarOrientation();
Sep 14, 2016
Sep 14, 2016
450
#endif
May 9, 2017
May 9, 2017
452
453
454
455
456
457
458
459
460
461
- (void)applicationWillTerminate:(UIApplication *)application
{
SDL_OnApplicationWillTerminate();
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
SDL_OnApplicationDidReceiveMemoryWarning();
}
462
463
- (void)applicationWillResignActive:(UIApplication*)application
{
May 9, 2017
May 9, 2017
464
SDL_OnApplicationWillResignActive();
465
466
467
468
}
- (void)applicationDidEnterBackground:(UIApplication*)application
{
May 9, 2017
May 9, 2017
469
SDL_OnApplicationDidEnterBackground();
470
471
472
473
}
- (void)applicationWillEnterForeground:(UIApplication*)application
{
May 9, 2017
May 9, 2017
474
SDL_OnApplicationWillEnterForeground();
475
476
477
478
}
- (void)applicationDidBecomeActive:(UIApplication*)application
{
May 9, 2017
May 9, 2017
479
SDL_OnApplicationDidBecomeActive();
Sep 16, 2016
Sep 16, 2016
482
- (void)sendDropFileForURL:(NSURL *)url
483
484
485
{
NSURL *fileURL = url.filePathURL;
if (fileURL != nil) {
Sep 16, 2016
Sep 16, 2016
486
SDL_SendDropFile(NULL, fileURL.path.UTF8String);
Sep 16, 2016
Sep 16, 2016
488
SDL_SendDropFile(NULL, url.absoluteString.UTF8String);
Jan 5, 2016
Jan 5, 2016
490
SDL_SendDropComplete(NULL);
Sep 16, 2016
Sep 16, 2016
491
492
}
Jul 15, 2017
Jul 15, 2017
493
494
#if TARGET_OS_TV || (defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0)
Sep 16, 2016
Sep 16, 2016
495
496
497
498
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
/* TODO: Handle options */
[self sendDropFileForURL:url];
Sep 16, 2016
Sep 16, 2016
501
Jul 15, 2017
Jul 15, 2017
502
503
#else
Sep 16, 2016
Sep 16, 2016
504
505
506
507
508
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
[self sendDropFileForURL:url];
return YES;
}
Jul 15, 2017
Jul 15, 2017
509
510
#endif
511
512
513
514
515
516
@end
#endif /* SDL_VIDEO_DRIVER_UIKIT */
/* vi: set ts=4 sw=4 expandtab: */