1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci* Copyright 2017 Google Inc.
3cb93a386Sopenharmony_ci*
4cb93a386Sopenharmony_ci* Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci* found in the LICENSE file.
6cb93a386Sopenharmony_ci*/
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "tools/sk_app/ios/WindowContextFactory_ios.h"
9cb93a386Sopenharmony_ci#include "tools/sk_app/ios/Window_ios.h"
10cb93a386Sopenharmony_ci
11cb93a386Sopenharmony_ci#if __has_feature(objc_arc)
12cb93a386Sopenharmony_ci#error "File should not be compiled with ARC."
13cb93a386Sopenharmony_ci#endif
14cb93a386Sopenharmony_ci
15cb93a386Sopenharmony_ci@interface WindowViewController : UIViewController
16cb93a386Sopenharmony_ci
17cb93a386Sopenharmony_ci- (WindowViewController*)initWithWindow:(sk_app::Window_ios*)initWindow;
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci@end
20cb93a386Sopenharmony_ci
21cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
22cb93a386Sopenharmony_ci
23cb93a386Sopenharmony_ciusing sk_app::Window;
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_cinamespace sk_app {
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_ciWindow_ios* Window_ios::gWindow = nullptr;
28cb93a386Sopenharmony_ci
29cb93a386Sopenharmony_ciWindow* Window::CreateNativeWindow(void*) {
30cb93a386Sopenharmony_ci    // already have a window
31cb93a386Sopenharmony_ci    if (Window_ios::MainWindow()) {
32cb93a386Sopenharmony_ci        return nullptr;
33cb93a386Sopenharmony_ci    }
34cb93a386Sopenharmony_ci
35cb93a386Sopenharmony_ci    Window_ios* window = new Window_ios();
36cb93a386Sopenharmony_ci    if (!window->initWindow()) {
37cb93a386Sopenharmony_ci        delete window;
38cb93a386Sopenharmony_ci        return nullptr;
39cb93a386Sopenharmony_ci    }
40cb93a386Sopenharmony_ci
41cb93a386Sopenharmony_ci    return window;
42cb93a386Sopenharmony_ci}
43cb93a386Sopenharmony_ci
44cb93a386Sopenharmony_cibool Window_ios::initWindow() {
45cb93a386Sopenharmony_ci    // we already have a window
46cb93a386Sopenharmony_ci    if (fWindow) {
47cb93a386Sopenharmony_ci        return true;
48cb93a386Sopenharmony_ci    }
49cb93a386Sopenharmony_ci
50cb93a386Sopenharmony_ci    // Create a view controller to track certain events
51cb93a386Sopenharmony_ci    WindowViewController* viewController = [[WindowViewController alloc] initWithWindow:this];
52cb93a386Sopenharmony_ci    if (nil == viewController) {
53cb93a386Sopenharmony_ci        return false;
54cb93a386Sopenharmony_ci    }
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci    fWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
57cb93a386Sopenharmony_ci    if (nil == fWindow) {
58cb93a386Sopenharmony_ci        [viewController release];
59cb93a386Sopenharmony_ci        return false;
60cb93a386Sopenharmony_ci    }
61cb93a386Sopenharmony_ci    fWindow.backgroundColor = [UIColor whiteColor];
62cb93a386Sopenharmony_ci
63cb93a386Sopenharmony_ci    viewController.view = nil;
64cb93a386Sopenharmony_ci    [fWindow setRootViewController:viewController];
65cb93a386Sopenharmony_ci    [fWindow makeKeyAndVisible];
66cb93a386Sopenharmony_ci
67cb93a386Sopenharmony_ci    gWindow = this;
68cb93a386Sopenharmony_ci
69cb93a386Sopenharmony_ci    return true;
70cb93a386Sopenharmony_ci}
71cb93a386Sopenharmony_ci
72cb93a386Sopenharmony_civoid Window_ios::closeWindow() {
73cb93a386Sopenharmony_ci    if (nil != fWindow) {
74cb93a386Sopenharmony_ci        gWindow = nullptr;
75cb93a386Sopenharmony_ci        [fWindow release];
76cb93a386Sopenharmony_ci        fWindow = nil;
77cb93a386Sopenharmony_ci    }
78cb93a386Sopenharmony_ci}
79cb93a386Sopenharmony_ci
80cb93a386Sopenharmony_cibool Window_ios::attach(BackendType attachType) {
81cb93a386Sopenharmony_ci    this->initWindow();
82cb93a386Sopenharmony_ci
83cb93a386Sopenharmony_ci    window_context_factory::IOSWindowInfo info;
84cb93a386Sopenharmony_ci    info.fWindow = this;
85cb93a386Sopenharmony_ci    info.fViewController = fWindow.rootViewController;
86cb93a386Sopenharmony_ci    switch (attachType) {
87cb93a386Sopenharmony_ci#ifdef SK_METAL
88cb93a386Sopenharmony_ci        case kMetal_BackendType:
89cb93a386Sopenharmony_ci            fWindowContext = MakeMetalForIOS(info, fRequestedDisplayParams);
90cb93a386Sopenharmony_ci            break;
91cb93a386Sopenharmony_ci#endif
92cb93a386Sopenharmony_ci#ifdef SK_GL
93cb93a386Sopenharmony_ci        case kNativeGL_BackendType:
94cb93a386Sopenharmony_ci            fWindowContext = MakeGLForIOS(info, fRequestedDisplayParams);
95cb93a386Sopenharmony_ci            break;
96cb93a386Sopenharmony_ci        case kRaster_BackendType:
97cb93a386Sopenharmony_ci            fWindowContext = MakeRasterForIOS(info, fRequestedDisplayParams);
98cb93a386Sopenharmony_ci            break;
99cb93a386Sopenharmony_ci#endif
100cb93a386Sopenharmony_ci        default:
101cb93a386Sopenharmony_ci            SkASSERT_RELEASE(false);
102cb93a386Sopenharmony_ci    }
103cb93a386Sopenharmony_ci    this->onBackendCreated();
104cb93a386Sopenharmony_ci
105cb93a386Sopenharmony_ci    return (SkToBool(fWindowContext));
106cb93a386Sopenharmony_ci}
107cb93a386Sopenharmony_ci
108cb93a386Sopenharmony_civoid Window_ios::PaintWindow() {
109cb93a386Sopenharmony_ci    gWindow->onPaint();
110cb93a386Sopenharmony_ci}
111cb93a386Sopenharmony_ci
112cb93a386Sopenharmony_civoid Window_ios::onInval() {
113cb93a386Sopenharmony_ci    // TODO: send expose event
114cb93a386Sopenharmony_ci}
115cb93a386Sopenharmony_ci
116cb93a386Sopenharmony_ci}   // namespace sk_app
117cb93a386Sopenharmony_ci
118cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
119cb93a386Sopenharmony_ci
120cb93a386Sopenharmony_ci@implementation WindowViewController {
121cb93a386Sopenharmony_ci    sk_app::Window_ios* fWindow;
122cb93a386Sopenharmony_ci}
123cb93a386Sopenharmony_ci
124cb93a386Sopenharmony_ci- (WindowViewController*)initWithWindow:(sk_app::Window_ios *)initWindow {
125cb93a386Sopenharmony_ci    self = [super initWithNibName:nil bundle:nil];
126cb93a386Sopenharmony_ci    if (self) {
127cb93a386Sopenharmony_ci        fWindow = initWindow;
128cb93a386Sopenharmony_ci    }
129cb93a386Sopenharmony_ci    return self;
130cb93a386Sopenharmony_ci}
131cb93a386Sopenharmony_ci
132cb93a386Sopenharmony_ci- (void)viewDidLoad {
133cb93a386Sopenharmony_ci    // nothing yet
134cb93a386Sopenharmony_ci}
135cb93a386Sopenharmony_ci
136cb93a386Sopenharmony_ci- (void)didReceiveMemoryWarning {
137cb93a386Sopenharmony_ci    // nothing yet
138cb93a386Sopenharmony_ci}
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci- (void)viewWillTransitionToSize:(CGSize)size
141cb93a386Sopenharmony_ci       withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator {
142cb93a386Sopenharmony_ci    // handle rotations here
143cb93a386Sopenharmony_ci}
144cb93a386Sopenharmony_ci@end
145cb93a386Sopenharmony_ci
146cb93a386Sopenharmony_ci///////////////////////////////////////////////////////////////////////////////
147cb93a386Sopenharmony_ci
148cb93a386Sopenharmony_ci@implementation MainView {
149cb93a386Sopenharmony_ci    sk_app::Window_ios* fWindow;
150cb93a386Sopenharmony_ci}
151cb93a386Sopenharmony_ci
152cb93a386Sopenharmony_ci- (void)panGestureAction:(UIGestureRecognizer*)sender {
153cb93a386Sopenharmony_ci    CGPoint location = [sender locationInView:self];
154cb93a386Sopenharmony_ci    switch (sender.state) {
155cb93a386Sopenharmony_ci        case UIGestureRecognizerStateBegan:
156cb93a386Sopenharmony_ci            fWindow->onMouse(location.x, location.y,
157cb93a386Sopenharmony_ci                             skui::InputState::kDown, skui::ModifierKey::kNone);
158cb93a386Sopenharmony_ci            break;
159cb93a386Sopenharmony_ci        case UIGestureRecognizerStateChanged:
160cb93a386Sopenharmony_ci            fWindow->onMouse(location.x, location.y,
161cb93a386Sopenharmony_ci                             skui::InputState::kMove, skui::ModifierKey::kNone);
162cb93a386Sopenharmony_ci            break;
163cb93a386Sopenharmony_ci        case UIGestureRecognizerStateEnded:
164cb93a386Sopenharmony_ci            fWindow->onMouse(location.x, location.y,
165cb93a386Sopenharmony_ci                             skui::InputState::kUp, skui::ModifierKey::kNone);
166cb93a386Sopenharmony_ci            break;
167cb93a386Sopenharmony_ci        case UIGestureRecognizerStateCancelled:
168cb93a386Sopenharmony_ci            fWindow->onMouse(location.x, location.y,
169cb93a386Sopenharmony_ci                             skui::InputState::kUp, skui::ModifierKey::kNone);
170cb93a386Sopenharmony_ci            break;
171cb93a386Sopenharmony_ci        default:
172cb93a386Sopenharmony_ci            break;
173cb93a386Sopenharmony_ci    }
174cb93a386Sopenharmony_ci}
175cb93a386Sopenharmony_ci
176cb93a386Sopenharmony_ci- (void)tapGestureAction:(UIGestureRecognizer*)sender {
177cb93a386Sopenharmony_ci    CGPoint location = [sender locationInView:self];
178cb93a386Sopenharmony_ci    switch (sender.state) {
179cb93a386Sopenharmony_ci        case UIGestureRecognizerStateEnded:
180cb93a386Sopenharmony_ci            fWindow->onMouse(location.x, location.y,
181cb93a386Sopenharmony_ci                             skui::InputState::kDown, skui::ModifierKey::kNone);
182cb93a386Sopenharmony_ci            fWindow->onMouse(location.x, location.y,
183cb93a386Sopenharmony_ci                             skui::InputState::kUp, skui::ModifierKey::kNone);
184cb93a386Sopenharmony_ci            break;
185cb93a386Sopenharmony_ci        default:
186cb93a386Sopenharmony_ci            break;
187cb93a386Sopenharmony_ci    }
188cb93a386Sopenharmony_ci}
189cb93a386Sopenharmony_ci
190cb93a386Sopenharmony_ci- (void)pinchGestureAction:(UIGestureRecognizer*)sender {
191cb93a386Sopenharmony_ci    CGPoint location = [sender locationInView:self];
192cb93a386Sopenharmony_ci    UIPinchGestureRecognizer* pinchGestureRecognizer = (UIPinchGestureRecognizer*) sender;
193cb93a386Sopenharmony_ci    float scale = pinchGestureRecognizer.scale;
194cb93a386Sopenharmony_ci    switch (sender.state) {
195cb93a386Sopenharmony_ci        case UIGestureRecognizerStateBegan:
196cb93a386Sopenharmony_ci            fWindow->onPinch(skui::InputState::kDown, scale, location.x, location.y);
197cb93a386Sopenharmony_ci            break;
198cb93a386Sopenharmony_ci        case UIGestureRecognizerStateChanged:
199cb93a386Sopenharmony_ci            fWindow->onPinch(skui::InputState::kMove, scale, location.x, location.y);
200cb93a386Sopenharmony_ci            break;
201cb93a386Sopenharmony_ci        case UIGestureRecognizerStateEnded:
202cb93a386Sopenharmony_ci            fWindow->onPinch(skui::InputState::kUp, scale, location.x, location.y);
203cb93a386Sopenharmony_ci            break;
204cb93a386Sopenharmony_ci        case UIGestureRecognizerStateCancelled:
205cb93a386Sopenharmony_ci            fWindow->onPinch(skui::InputState::kUp, scale, location.x, location.y);
206cb93a386Sopenharmony_ci            break;
207cb93a386Sopenharmony_ci        default:
208cb93a386Sopenharmony_ci            break;
209cb93a386Sopenharmony_ci    }
210cb93a386Sopenharmony_ci}
211cb93a386Sopenharmony_ci
212cb93a386Sopenharmony_ci- (void)swipeRightGestureAction:(UIGestureRecognizer*)sender {
213cb93a386Sopenharmony_ci    if (UIGestureRecognizerStateEnded == sender.state) {
214cb93a386Sopenharmony_ci        fWindow->onFling(skui::InputState::kRight);
215cb93a386Sopenharmony_ci    }
216cb93a386Sopenharmony_ci}
217cb93a386Sopenharmony_ci
218cb93a386Sopenharmony_ci- (void)swipeLeftGestureAction:(UIGestureRecognizer*)sender {
219cb93a386Sopenharmony_ci    if (UIGestureRecognizerStateEnded == sender.state) {
220cb93a386Sopenharmony_ci        fWindow->onFling(skui::InputState::kLeft);
221cb93a386Sopenharmony_ci    }
222cb93a386Sopenharmony_ci}
223cb93a386Sopenharmony_ci
224cb93a386Sopenharmony_ci- (MainView*)initWithWindow:(sk_app::Window_ios *)initWindow {
225cb93a386Sopenharmony_ci    self = [super init];
226cb93a386Sopenharmony_ci
227cb93a386Sopenharmony_ci    UIPanGestureRecognizer* panGestureRecognizer = [[UIPanGestureRecognizer alloc] init];
228cb93a386Sopenharmony_ci    panGestureRecognizer.maximumNumberOfTouches = 1;
229cb93a386Sopenharmony_ci    [panGestureRecognizer addTarget:self action:@selector(panGestureAction:)];
230cb93a386Sopenharmony_ci    [self addGestureRecognizer:panGestureRecognizer];
231cb93a386Sopenharmony_ci
232cb93a386Sopenharmony_ci    UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc] init];
233cb93a386Sopenharmony_ci    [tapGestureRecognizer addTarget:self action:@selector(tapGestureAction:)];
234cb93a386Sopenharmony_ci    [self addGestureRecognizer:tapGestureRecognizer];
235cb93a386Sopenharmony_ci
236cb93a386Sopenharmony_ci    UIPinchGestureRecognizer* pinchGestureRecognizer = [[UIPinchGestureRecognizer alloc] init];
237cb93a386Sopenharmony_ci    [pinchGestureRecognizer addTarget:self action:@selector(pinchGestureAction:)];
238cb93a386Sopenharmony_ci    [self addGestureRecognizer:pinchGestureRecognizer];
239cb93a386Sopenharmony_ci
240cb93a386Sopenharmony_ci    UISwipeGestureRecognizer* swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] init];
241cb93a386Sopenharmony_ci    swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
242cb93a386Sopenharmony_ci    [swipeRightGestureRecognizer addTarget:self action:@selector(swipeRightGestureAction:)];
243cb93a386Sopenharmony_ci    [self addGestureRecognizer:swipeRightGestureRecognizer];
244cb93a386Sopenharmony_ci
245cb93a386Sopenharmony_ci    UISwipeGestureRecognizer* swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] init];
246cb93a386Sopenharmony_ci    swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
247cb93a386Sopenharmony_ci    [swipeLeftGestureRecognizer addTarget:self action:@selector(swipeLeftGestureAction:)];
248cb93a386Sopenharmony_ci    [self addGestureRecognizer:swipeLeftGestureRecognizer];
249cb93a386Sopenharmony_ci
250cb93a386Sopenharmony_ci    // disable pan recognition until swipes fail
251cb93a386Sopenharmony_ci    [panGestureRecognizer requireGestureRecognizerToFail:swipeLeftGestureRecognizer];
252cb93a386Sopenharmony_ci    [panGestureRecognizer requireGestureRecognizerToFail:swipeRightGestureRecognizer];
253cb93a386Sopenharmony_ci
254cb93a386Sopenharmony_ci    fWindow = initWindow;
255cb93a386Sopenharmony_ci
256cb93a386Sopenharmony_ci    return self;
257cb93a386Sopenharmony_ci}
258cb93a386Sopenharmony_ci
259cb93a386Sopenharmony_ci@end
260cb93a386Sopenharmony_ci
261