xref: /aosp_15_r20/external/skia/tools/sk_app/ios/Window_ios.mm (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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