mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
45da52cee7
The app and app/internal/wm packages are tightly coupled, requiring quite a bit of forwarding types, values and constants from the internal package to export it. Further, no other package imports package wm. This change merges the two packages. While here, drop the pre-Go 1.14 SIGPIPE workaround. Signed-off-by: Elias Naur <mail@eliasnaur.com>
275 lines
7.6 KiB
Objective-C
275 lines
7.6 KiB
Objective-C
// 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);
|
|
[[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.
|
|
}
|