aboutsummaryrefslogtreecommitdiff
path: root/vendor/gioui.org/app/os_ios.m
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gioui.org/app/os_ios.m')
-rw-r--r--vendor/gioui.org/app/os_ios.m274
1 files changed, 274 insertions, 0 deletions
diff --git a/vendor/gioui.org/app/os_ios.m b/vendor/gioui.org/app/os_ios.m
new file mode 100644
index 0000000..94f254b
--- /dev/null
+++ b/vendor/gioui.org/app/os_ios.m
@@ -0,0 +1,274 @@
+// SPDX-License-Identifier: Unlicense OR MIT
+
+// +build darwin,ios
+
+@import UIKit;
+
+#include <stdint.h>
+#include "_cgo_export.h"
+#include "framework_ios.h"
+
+__attribute__ ((visibility ("hidden"))) Class gio_layerClass(void);
+
+@interface GioView: UIView <UIKeyInput>
+@end
+
+@implementation GioViewController
+
+CGFloat _keyboardHeight;
+
+- (void)loadView {
+ gio_runMain();
+
+ CGRect zeroFrame = CGRectMake(0, 0, 0, 0);
+ self.view = [[UIView alloc] initWithFrame:zeroFrame];
+ self.view.layoutMargins = UIEdgeInsetsMake(0, 0, 0, 0);
+ UIView *drawView = [[GioView alloc] initWithFrame:zeroFrame];
+ [self.view addSubview: drawView];
+#ifndef TARGET_OS_TV
+ drawView.multipleTouchEnabled = YES;
+#endif
+ drawView.preservesSuperviewLayoutMargins = YES;
+ drawView.layoutMargins = UIEdgeInsetsMake(0, 0, 0, 0);
+ onCreate((__bridge CFTypeRef)drawView, (__bridge CFTypeRef)self);
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(keyboardWillChange:)
+ name:UIKeyboardWillShowNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(keyboardWillChange:)
+ name:UIKeyboardWillChangeFrameNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(keyboardWillHide:)
+ name:UIKeyboardWillHideNotification
+ object:nil];
+ [[NSNotificationCenter defaultCenter] addObserver: self
+ selector: @selector(applicationDidEnterBackground:)
+ name: UIApplicationDidEnterBackgroundNotification
+ object: nil];
+ [[NSNotificationCenter defaultCenter] addObserver: self
+ selector: @selector(applicationWillEnterForeground:)
+ name: UIApplicationWillEnterForegroundNotification
+ object: nil];
+}
+
+- (void)applicationWillEnterForeground:(UIApplication *)application {
+ UIView *drawView = self.view.subviews[0];
+ if (drawView != nil) {
+ gio_onDraw((__bridge CFTypeRef)drawView);
+ }
+}
+
+- (void)applicationDidEnterBackground:(UIApplication *)application {
+ UIView *drawView = self.view.subviews[0];
+ if (drawView != nil) {
+ onStop((__bridge CFTypeRef)drawView);
+ }
+}
+
+- (void)viewDidDisappear:(BOOL)animated {
+ [super viewDidDisappear:animated];
+ CFTypeRef viewRef = (__bridge CFTypeRef)self.view.subviews[0];
+ onDestroy(viewRef);
+}
+
+- (void)viewDidLayoutSubviews {
+ [super viewDidLayoutSubviews];
+ UIView *view = self.view.subviews[0];
+ CGRect frame = self.view.bounds;
+ // Adjust view bounds to make room for the keyboard.
+ frame.size.height -= _keyboardHeight;
+ view.frame = frame;
+ gio_onDraw((__bridge CFTypeRef)view);
+}
+
+- (void)didReceiveMemoryWarning {
+ onLowMemory();
+ [super didReceiveMemoryWarning];
+}
+
+- (void)keyboardWillChange:(NSNotification *)note {
+ NSDictionary *userInfo = note.userInfo;
+ CGRect f = [userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
+ _keyboardHeight = f.size.height;
+ [self.view setNeedsLayout];
+}
+
+- (void)keyboardWillHide:(NSNotification *)note {
+ _keyboardHeight = 0.0;
+ [self.view setNeedsLayout];
+}
+@end
+
+static void handleTouches(int last, UIView *view, NSSet<UITouch *> *touches, UIEvent *event) {
+ CGFloat scale = view.contentScaleFactor;
+ NSUInteger i = 0;
+ NSUInteger n = [touches count];
+ CFTypeRef viewRef = (__bridge CFTypeRef)view;
+ for (UITouch *touch in touches) {
+ CFTypeRef touchRef = (__bridge CFTypeRef)touch;
+ i++;
+ NSArray<UITouch *> *coalescedTouches = [event coalescedTouchesForTouch:touch];
+ NSUInteger j = 0;
+ NSUInteger m = [coalescedTouches count];
+ for (UITouch *coalescedTouch in [event coalescedTouchesForTouch:touch]) {
+ CGPoint loc = [coalescedTouch locationInView:view];
+ j++;
+ int lastTouch = last && i == n && j == m;
+ onTouch(lastTouch, viewRef, touchRef, touch.phase, loc.x*scale, loc.y*scale, [coalescedTouch timestamp]);
+ }
+ }
+}
+
+@implementation GioView
+NSArray<UIKeyCommand *> *_keyCommands;
++ (void)onFrameCallback:(CADisplayLink *)link {
+ gio_onFrameCallback((__bridge CFTypeRef)link);
+}
+
++ (Class)layerClass {
+ return gio_layerClass();
+}
+- (void)willMoveToWindow:(UIWindow *)newWindow {
+ if (self.window != nil) {
+ [[NSNotificationCenter defaultCenter] removeObserver:self
+ name:UIWindowDidBecomeKeyNotification
+ object:self.window];
+ [[NSNotificationCenter defaultCenter] removeObserver:self
+ name:UIWindowDidResignKeyNotification
+ object:self.window];
+ }
+ self.contentScaleFactor = newWindow.screen.nativeScale;
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(onWindowDidBecomeKey:)
+ name:UIWindowDidBecomeKeyNotification
+ object:newWindow];
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(onWindowDidResignKey:)
+ name:UIWindowDidResignKeyNotification
+ object:newWindow];
+}
+
+- (void)onWindowDidBecomeKey:(NSNotification *)note {
+ if (self.isFirstResponder) {
+ onFocus((__bridge CFTypeRef)self, YES);
+ }
+}
+
+- (void)onWindowDidResignKey:(NSNotification *)note {
+ if (self.isFirstResponder) {
+ onFocus((__bridge CFTypeRef)self, NO);
+ }
+}
+
+- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+ handleTouches(0, self, touches, event);
+}
+
+- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+ handleTouches(0, self, touches, event);
+}
+
+- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+ handleTouches(1, self, touches, event);
+}
+
+- (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+ handleTouches(1, self, touches, event);
+}
+
+- (void)insertText:(NSString *)text {
+ onText((__bridge CFTypeRef)self, (char *)text.UTF8String);
+}
+
+- (BOOL)canBecomeFirstResponder {
+ return YES;
+}
+
+- (BOOL)hasText {
+ return YES;
+}
+
+- (void)deleteBackward {
+ onDeleteBackward((__bridge CFTypeRef)self);
+}
+
+- (void)onUpArrow {
+ onUpArrow((__bridge CFTypeRef)self);
+}
+
+- (void)onDownArrow {
+ onDownArrow((__bridge CFTypeRef)self);
+}
+
+- (void)onLeftArrow {
+ onLeftArrow((__bridge CFTypeRef)self);
+}
+
+- (void)onRightArrow {
+ onRightArrow((__bridge CFTypeRef)self);
+}
+
+- (NSArray<UIKeyCommand *> *)keyCommands {
+ if (_keyCommands == nil) {
+ _keyCommands = @[
+ [UIKeyCommand keyCommandWithInput:UIKeyInputUpArrow
+ modifierFlags:0
+ action:@selector(onUpArrow)],
+ [UIKeyCommand keyCommandWithInput:UIKeyInputDownArrow
+ modifierFlags:0
+ action:@selector(onDownArrow)],
+ [UIKeyCommand keyCommandWithInput:UIKeyInputLeftArrow
+ modifierFlags:0
+ action:@selector(onLeftArrow)],
+ [UIKeyCommand keyCommandWithInput:UIKeyInputRightArrow
+ modifierFlags:0
+ action:@selector(onRightArrow)]
+ ];
+ }
+ return _keyCommands;
+}
+@end
+
+CFTypeRef gio_createDisplayLink(void) {
+ CADisplayLink *dl = [CADisplayLink displayLinkWithTarget:[GioView class] selector:@selector(onFrameCallback:)];
+ dl.paused = YES;
+ NSRunLoop *runLoop = [NSRunLoop mainRunLoop];
+ [dl addToRunLoop:runLoop forMode:[runLoop currentMode]];
+ return (__bridge_retained CFTypeRef)dl;
+}
+
+int gio_startDisplayLink(CFTypeRef dlref) {
+ CADisplayLink *dl = (__bridge CADisplayLink *)dlref;
+ dl.paused = NO;
+ return 0;
+}
+
+int gio_stopDisplayLink(CFTypeRef dlref) {
+ CADisplayLink *dl = (__bridge CADisplayLink *)dlref;
+ dl.paused = YES;
+ return 0;
+}
+
+void gio_releaseDisplayLink(CFTypeRef dlref) {
+ CADisplayLink *dl = (__bridge CADisplayLink *)dlref;
+ [dl invalidate];
+ CFRelease(dlref);
+}
+
+void gio_setDisplayLinkDisplay(CFTypeRef dl, uint64_t did) {
+ // Nothing to do on iOS.
+}
+
+void gio_hideCursor() {
+ // Not supported.
+}
+
+void gio_showCursor() {
+ // Not supported.
+}
+
+void gio_setCursor(NSUInteger curID) {
+ // Not supported.
+}