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