• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright 2017 Google Inc.
3*
4* Use of this source code is governed by a BSD-style license that can be
5* found in the LICENSE file.
6*/
7
8#include "include/core/SkTypes.h"
9#include "include/private/SkTHash.h"
10#include "tools/sk_app/Application.h"
11#include "tools/sk_app/ios/Window_ios.h"
12#include "tools/timer/Timer.h"
13
14#import <UIKit/UIKit.h>
15
16using sk_app::Application;
17
18////////////////////////////////////////////////////////////////////
19
20@interface AppDelegate : UIResponder<UIApplicationDelegate>
21
22@property (nonatomic, assign) BOOL done;
23@property (strong, nonatomic) UIWindow *window;
24
25@end
26
27@implementation AppDelegate
28
29@synthesize done = _done;
30@synthesize window = _window;
31
32- (void)applicationWillTerminate:(UIApplication *)sender {
33    _done = TRUE;
34}
35
36- (void)launchApp {
37    // Extract argc and argv from NSProcessInfo
38    NSArray *arguments = [[NSProcessInfo processInfo] arguments];
39    int argc = arguments.count;
40    char** argv = (char **)malloc((argc+1) * sizeof(char *));
41    int i = 0;
42    for (NSString* string in arguments) {
43        size_t bufferSize = (string.length+1) * sizeof(char);
44        argv[i] = (char*)malloc(bufferSize);
45        [string getCString:argv[i]
46                 maxLength:bufferSize
47                  encoding:NSUTF8StringEncoding];
48        ++i;
49    }
50    argv[i] = NULL;
51    [arguments release];
52
53    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
54
55    Application* app = Application::Create(argc, argv, nullptr);
56
57    // Free the memory we used for argc and argv
58    for (i = 0; i < argc; i++) {
59        free(argv[i]);
60    }
61    free(argv);
62
63    sk_app::Window_ios* mainWindow = sk_app::Window_ios::MainWindow();
64    if (!mainWindow) {
65        return;
66    }
67    self.window = mainWindow->uiWindow();
68
69    // take over the main event loop
70    bool done = false;
71    while (!done) {
72        // TODO: consider using a dispatch queue or CADisplayLink instead of this
73        const CFTimeInterval kSeconds = 0.000002;
74        CFRunLoopRunResult result;
75        do {
76            result = CFRunLoopRunInMode(kCFRunLoopDefaultMode, kSeconds, TRUE);
77        } while (result == kCFRunLoopRunHandledSource);
78
79        [pool drain];
80        pool = [[NSAutoreleasePool alloc] init];
81
82        // TODO: is this the right approach for iOS?
83        // Rather than depending on an iOS event to drive this, we treat our window
84        // invalidation flag as a separate event stream. Window::onPaint() will clear
85        // the invalidation flag, effectively removing it from the stream.
86        sk_app::Window_ios::PaintWindow();
87
88        app->onIdle();
89    }
90    delete app;
91}
92
93- (BOOL)application:(UIApplication *)application
94        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
95    // let the system event loop run once, then launch into our main loop
96    [self performSelector:@selector(launchApp) withObject:nil afterDelay:0.0];
97
98    return YES;
99}
100
101@end
102
103///////////////////////////////////////////////////////////////////
104
105int main(int argc, char **argv) {
106    /* Give over control to run loop, AppDelegate will handle most things from here */
107    @autoreleasepool {
108        UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
109    }
110
111    return EXIT_SUCCESS;
112}
113