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