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