Skip to content

Latest commit

 

History

History
527 lines (434 loc) · 17.3 KB

SDL_uikitappdelegate.m

File metadata and controls

527 lines (434 loc) · 17.3 KB
 
1
2
/*
Simple DirectMedia Layer
Jan 17, 2020
Jan 17, 2020
3
Copyright (C) 1997-2020 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
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
Mar 19, 2019
Mar 19, 2019
41
static SDL_main_func forward_main;
42
43
44
45
static int forward_argc;
static char **forward_argv;
static int exit_status;
Mar 19, 2019
Mar 19, 2019
46
47
48
49
50
51
52
53
54
#if defined(SDL_MAIN_NEEDED) && !defined(IOS_DYLIB)
/* SDL is being built as a static library, include main() */
int main(int argc, char *argv[])
{
return SDL_UIKitRunApp(argc, argv, SDL_main);
}
#endif /* SDL_MAIN_NEEDED && !IOS_DYLIB */
int SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction)
55
56
57
58
{
int i;
/* store arguments */
Mar 19, 2019
Mar 19, 2019
59
forward_main = mainFunction;
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
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
82
static void SDLCALL
83
84
85
86
87
88
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
89
#if !TARGET_OS_TV
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
118
119
120
121
122
123
124
125
126
127
/* 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
128
129
130
131
132
133
134
135
136
#endif /* !TARGET_OS_TV */
@interface SDLLaunchScreenController ()
#if !TARGET_OS_TV
- (NSUInteger)supportedInterfaceOrientations;
#endif
@end
137
138
139
140
@implementation SDLLaunchScreenController
- (instancetype)init
Sep 25, 2016
Sep 25, 2016
141
142
143
144
145
{
return [self initWithNibName:nil bundle:[NSBundle mainBundle]];
}
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
146
147
148
149
150
{
if (!(self = [super initWithNibName:nil bundle:nil])) {
return nil;
}
Sep 25, 2016
Sep 25, 2016
151
152
NSString *screenname = nibNameOrNil;
NSBundle *bundle = nibBundleOrNil;
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
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
175
176
177
#if !TARGET_OS_TV
UIInterfaceOrientation curorient = [UIApplication sharedApplication].statusBarOrientation;
178
179
180
181
182
183
/* 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
184
#endif
185
186
187
188
/* Xcode 5 introduced a dictionary of launch images in Info.plist. */
if (launchimages) {
for (NSDictionary *dict in launchimages) {
Sep 25, 2016
Sep 25, 2016
189
190
NSString *minversion = dict[@"UILaunchImageMinimumOSVersion"];
NSString *sizestring = dict[@"UILaunchImageSize"];
191
192
193
194
195
196
197
198
199
200
201
202
203
204
/* 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
205
206
207
208
#if !TARGET_OS_TV
UIInterfaceOrientationMask orientmask = UIInterfaceOrientationMaskPortrait | UIInterfaceOrientationMaskPortraitUpsideDown;
NSString *orientstring = dict[@"UILaunchImageOrientation"];
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
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
225
#endif
226
227
228
229
230
231
232
imagename = dict[@"UILaunchImageName"];
}
if (imagename) {
image = [UIImage imageNamed:imagename];
}
Sep 25, 2016
Sep 25, 2016
233
234
235
}
#if !TARGET_OS_TV
else {
236
237
238
239
240
241
242
243
244
245
imagename = [bundle objectForInfoDictionaryKey:@"UILaunchImageFile"];
if (imagename) {
image = SDL_LoadLaunchImageNamed(imagename, screenh);
}
if (!image) {
image = SDL_LoadLaunchImageNamed(@"Default", screenh);
}
}
Sep 25, 2016
Sep 25, 2016
246
#endif
247
248
249
250
251
if (image) {
UIImageView *view = [[UIImageView alloc] initWithFrame:[UIScreen mainScreen].bounds];
UIImageOrientation imageorient = UIImageOrientationUp;
Sep 25, 2016
Sep 25, 2016
252
#if !TARGET_OS_TV
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
/* 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
276
#endif
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
/* 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
293
#if !TARGET_OS_TV
294
295
296
297
298
299
300
301
302
303
304
305
306
- (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
307
#endif /* !TARGET_OS_TV */
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
@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;
Jun 9, 2019
Jun 9, 2019
346
UIKit_ForceUpdateHomeIndicator(); /* Wait for launch screen to hide so settings are applied to the actual view controller. */
347
348
349
350
351
352
353
354
355
356
357
}];
}
- (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);
Mar 19, 2019
Mar 19, 2019
358
exit_status = forward_main(forward_argc, forward_argv);
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
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
383
UIViewController *vc = nil;
Sep 25, 2016
Sep 25, 2016
384
NSString *screenname = nil;
Sep 25, 2016
Sep 25, 2016
385
Sep 25, 2016
Sep 25, 2016
386
/* tvOS only uses a plain launch image. */
Sep 25, 2016
Sep 25, 2016
387
#if !TARGET_OS_TV
Sep 25, 2016
Sep 25, 2016
388
screenname = [bundle objectForInfoDictionaryKey:@"UILaunchStoryboardName"];
Sep 25, 2016
Sep 25, 2016
389
390
391
392
393
394
395
396
397
398
399
400
401
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
402
#endif
Sep 25, 2016
Sep 25, 2016
403
404
405
406
if (vc == nil) {
vc = [[SDLLaunchScreenController alloc] initWithNibName:screenname bundle:bundle];
}
Sep 25, 2016
Sep 25, 2016
408
if (vc.view) {
409
410
411
412
413
414
415
416
417
418
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
419
launchWindow.rootViewController = vc;
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
}
#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
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
- (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
456
#if !TARGET_OS_TV
457
458
- (void)application:(UIApplication *)application didChangeStatusBarOrientation:(UIInterfaceOrientation)oldStatusBarOrientation
{
Sep 24, 2018
Sep 24, 2018
459
SDL_OnApplicationDidChangeStatusBarOrientation();
Sep 14, 2016
Sep 14, 2016
461
#endif
May 9, 2017
May 9, 2017
463
464
465
466
467
468
469
470
471
472
- (void)applicationWillTerminate:(UIApplication *)application
{
SDL_OnApplicationWillTerminate();
}
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
SDL_OnApplicationDidReceiveMemoryWarning();
}
473
474
- (void)applicationWillResignActive:(UIApplication*)application
{
May 9, 2017
May 9, 2017
475
SDL_OnApplicationWillResignActive();
476
477
478
479
}
- (void)applicationDidEnterBackground:(UIApplication*)application
{
May 9, 2017
May 9, 2017
480
SDL_OnApplicationDidEnterBackground();
481
482
483
484
}
- (void)applicationWillEnterForeground:(UIApplication*)application
{
May 9, 2017
May 9, 2017
485
SDL_OnApplicationWillEnterForeground();
486
487
488
489
}
- (void)applicationDidBecomeActive:(UIApplication*)application
{
May 9, 2017
May 9, 2017
490
SDL_OnApplicationDidBecomeActive();
Sep 16, 2016
Sep 16, 2016
493
- (void)sendDropFileForURL:(NSURL *)url
494
495
496
{
NSURL *fileURL = url.filePathURL;
if (fileURL != nil) {
Sep 16, 2016
Sep 16, 2016
497
SDL_SendDropFile(NULL, fileURL.path.UTF8String);
Sep 16, 2016
Sep 16, 2016
499
SDL_SendDropFile(NULL, url.absoluteString.UTF8String);
Jan 5, 2016
Jan 5, 2016
501
SDL_SendDropComplete(NULL);
Sep 16, 2016
Sep 16, 2016
502
503
}
Jul 15, 2017
Jul 15, 2017
504
505
#if TARGET_OS_TV || (defined(__IPHONE_9_0) && __IPHONE_OS_VERSION_MIN_REQUIRED >= __IPHONE_9_0)
Sep 16, 2016
Sep 16, 2016
506
507
508
509
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options
{
/* TODO: Handle options */
[self sendDropFileForURL:url];
Sep 16, 2016
Sep 16, 2016
512
Jul 15, 2017
Jul 15, 2017
513
514
#else
Sep 16, 2016
Sep 16, 2016
515
516
517
518
519
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
[self sendDropFileForURL:url];
return YES;
}
Jul 15, 2017
Jul 15, 2017
520
521
#endif
522
523
524
525
526
527
@end
#endif /* SDL_VIDEO_DRIVER_UIKIT */
/* vi: set ts=4 sw=4 expandtab: */