mirror of
https://git.sr.ht/~eliasnaur/gio
synced 2026-07-01 07:35:40 +00:00
app: [iOS] use cgo.Handle for referring to Go windows from native code
Signed-off-by: Elias Naur <mail@eliasnaur.com>
This commit is contained in:
+33
-28
@@ -12,6 +12,8 @@ package app
|
||||
#include <UIKit/UIKit.h>
|
||||
#include <stdint.h>
|
||||
|
||||
__attribute__ ((visibility ("hidden"))) void gio_viewSetHandle(CFTypeRef viewRef, uintptr_t handle);
|
||||
|
||||
struct drawParams {
|
||||
CGFloat dpi, sdpi;
|
||||
CGFloat width, height;
|
||||
@@ -74,6 +76,7 @@ import (
|
||||
"image"
|
||||
"io"
|
||||
"runtime"
|
||||
"runtime/cgo"
|
||||
"runtime/debug"
|
||||
"strings"
|
||||
"time"
|
||||
@@ -110,8 +113,6 @@ type window struct {
|
||||
|
||||
var mainWindow = newWindowRendezvous()
|
||||
|
||||
var views = make(map[C.CFTypeRef]*window)
|
||||
|
||||
func init() {
|
||||
// Darwin requires UI operations happen on the main thread only.
|
||||
runtime.LockOSThread()
|
||||
@@ -135,15 +136,19 @@ func onCreate(view, controller C.CFTypeRef) {
|
||||
return
|
||||
}
|
||||
w.displayLink = dl
|
||||
views[view] = w
|
||||
C.gio_viewSetHandle(view, C.uintptr_t(cgo.NewHandle(w)))
|
||||
w.Configure(wopts.options)
|
||||
w.ProcessEvent(StageEvent{Stage: StageRunning})
|
||||
w.ProcessEvent(ViewEvent{ViewController: uintptr(controller)})
|
||||
}
|
||||
|
||||
func viewFor(h C.uintptr_t) *window {
|
||||
return cgo.Handle(h).Value().(*window)
|
||||
}
|
||||
|
||||
//export gio_onDraw
|
||||
func gio_onDraw(view C.CFTypeRef) {
|
||||
w := views[view]
|
||||
func gio_onDraw(h C.uintptr_t) {
|
||||
w := viewFor(h)
|
||||
w.draw(true)
|
||||
}
|
||||
|
||||
@@ -181,34 +186,34 @@ func (w *window) draw(sync bool) {
|
||||
}
|
||||
|
||||
//export onStop
|
||||
func onStop(view C.CFTypeRef) {
|
||||
w := views[view]
|
||||
func onStop(h C.uintptr_t) {
|
||||
w := viewFor(h)
|
||||
w.hidden = true
|
||||
w.ProcessEvent(StageEvent{Stage: StagePaused})
|
||||
}
|
||||
|
||||
//export onStart
|
||||
func onStart(view C.CFTypeRef) {
|
||||
w := views[view]
|
||||
func onStart(h C.uintptr_t) {
|
||||
w := viewFor(h)
|
||||
w.hidden = false
|
||||
w.ProcessEvent(StageEvent{Stage: StageRunning})
|
||||
w.draw(true)
|
||||
}
|
||||
|
||||
//export onDestroy
|
||||
func onDestroy(view C.CFTypeRef) {
|
||||
w := views[view]
|
||||
func onDestroy(h C.uintptr_t) {
|
||||
w := viewFor(h)
|
||||
w.ProcessEvent(ViewEvent{})
|
||||
w.ProcessEvent(DestroyEvent{})
|
||||
w.displayLink.Close()
|
||||
w.displayLink = nil
|
||||
delete(views, view)
|
||||
cgo.Handle(h).Delete()
|
||||
w.view = 0
|
||||
}
|
||||
|
||||
//export onFocus
|
||||
func onFocus(view C.CFTypeRef, focus int) {
|
||||
w := views[view]
|
||||
func onFocus(h C.uintptr_t, focus int) {
|
||||
w := viewFor(h)
|
||||
w.ProcessEvent(key.FocusEvent{Focus: focus != 0})
|
||||
}
|
||||
|
||||
@@ -219,38 +224,38 @@ func onLowMemory() {
|
||||
}
|
||||
|
||||
//export onUpArrow
|
||||
func onUpArrow(view C.CFTypeRef) {
|
||||
views[view].onKeyCommand(key.NameUpArrow)
|
||||
func onUpArrow(h C.uintptr_t) {
|
||||
viewFor(h).onKeyCommand(key.NameUpArrow)
|
||||
}
|
||||
|
||||
//export onDownArrow
|
||||
func onDownArrow(view C.CFTypeRef) {
|
||||
views[view].onKeyCommand(key.NameDownArrow)
|
||||
func onDownArrow(h C.uintptr_t) {
|
||||
viewFor(h).onKeyCommand(key.NameDownArrow)
|
||||
}
|
||||
|
||||
//export onLeftArrow
|
||||
func onLeftArrow(view C.CFTypeRef) {
|
||||
views[view].onKeyCommand(key.NameLeftArrow)
|
||||
func onLeftArrow(h C.uintptr_t) {
|
||||
viewFor(h).onKeyCommand(key.NameLeftArrow)
|
||||
}
|
||||
|
||||
//export onRightArrow
|
||||
func onRightArrow(view C.CFTypeRef) {
|
||||
views[view].onKeyCommand(key.NameRightArrow)
|
||||
func onRightArrow(h C.uintptr_t) {
|
||||
viewFor(h).onKeyCommand(key.NameRightArrow)
|
||||
}
|
||||
|
||||
//export onDeleteBackward
|
||||
func onDeleteBackward(view C.CFTypeRef) {
|
||||
views[view].onKeyCommand(key.NameDeleteBackward)
|
||||
func onDeleteBackward(h C.uintptr_t) {
|
||||
viewFor(h).onKeyCommand(key.NameDeleteBackward)
|
||||
}
|
||||
|
||||
//export onText
|
||||
func onText(view, str C.CFTypeRef) {
|
||||
w := views[view]
|
||||
func onText(h C.uintptr_t, str C.CFTypeRef) {
|
||||
w := viewFor(h)
|
||||
w.w.EditorInsert(nsstringToString(str))
|
||||
}
|
||||
|
||||
//export onTouch
|
||||
func onTouch(last C.int, view, touchRef C.CFTypeRef, phase C.NSInteger, x, y C.CGFloat, ti C.double) {
|
||||
func onTouch(h C.uintptr_t, last C.int, touchRef C.CFTypeRef, phase C.NSInteger, x, y C.CGFloat, ti C.double) {
|
||||
var kind pointer.Kind
|
||||
switch phase {
|
||||
case C.UITouchPhaseBegan:
|
||||
@@ -264,7 +269,7 @@ func onTouch(last C.int, view, touchRef C.CFTypeRef, phase C.NSInteger, x, y C.C
|
||||
default:
|
||||
return
|
||||
}
|
||||
w := views[view]
|
||||
w := viewFor(h)
|
||||
t := time.Duration(float64(ti) * float64(time.Second))
|
||||
p := f32.Point{X: float32(x), Y: float32(y)}
|
||||
w.ProcessEvent(pointer.Event{
|
||||
|
||||
+26
-21
@@ -11,6 +11,7 @@
|
||||
__attribute__ ((visibility ("hidden"))) Class gio_layerClass(void);
|
||||
|
||||
@interface GioView: UIView <UIKeyInput>
|
||||
@property uintptr_t handle;
|
||||
@end
|
||||
|
||||
@implementation GioViewController
|
||||
@@ -54,33 +55,33 @@ CGFloat _keyboardHeight;
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application {
|
||||
UIView *drawView = self.view.subviews[0];
|
||||
if (drawView != nil) {
|
||||
onStart((__bridge CFTypeRef)drawView);
|
||||
GioView *view = (GioView *)self.view.subviews[0];
|
||||
if (view != nil) {
|
||||
onStart(view.handle);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application {
|
||||
UIView *drawView = self.view.subviews[0];
|
||||
if (drawView != nil) {
|
||||
onStop((__bridge CFTypeRef)drawView);
|
||||
GioView *view = (GioView *)self.view.subviews[0];
|
||||
if (view != nil) {
|
||||
onStop(view.handle);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidDisappear:(BOOL)animated {
|
||||
[super viewDidDisappear:animated];
|
||||
CFTypeRef viewRef = (__bridge CFTypeRef)self.view.subviews[0];
|
||||
onDestroy(viewRef);
|
||||
GioView *view = (GioView *)self.view.subviews[0];
|
||||
onDestroy(view.handle);
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews {
|
||||
[super viewDidLayoutSubviews];
|
||||
UIView *view = self.view.subviews[0];
|
||||
GioView *view = (GioView *)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);
|
||||
gio_onDraw(view.handle);
|
||||
}
|
||||
|
||||
- (void)didReceiveMemoryWarning {
|
||||
@@ -101,11 +102,10 @@ CGFloat _keyboardHeight;
|
||||
}
|
||||
@end
|
||||
|
||||
static void handleTouches(int last, UIView *view, NSSet<UITouch *> *touches, UIEvent *event) {
|
||||
static void handleTouches(int last, GioView *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++;
|
||||
@@ -116,7 +116,7 @@ static void handleTouches(int last, UIView *view, NSSet<UITouch *> *touches, UIE
|
||||
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]);
|
||||
onTouch(view.handle, lastTouch, touchRef, touch.phase, loc.x*scale, loc.y*scale, [coalescedTouch timestamp]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -151,13 +151,13 @@ NSArray<UIKeyCommand *> *_keyCommands;
|
||||
|
||||
- (void)onWindowDidBecomeKey:(NSNotification *)note {
|
||||
if (self.isFirstResponder) {
|
||||
onFocus((__bridge CFTypeRef)self, YES);
|
||||
onFocus(self.handle, YES);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onWindowDidResignKey:(NSNotification *)note {
|
||||
if (self.isFirstResponder) {
|
||||
onFocus((__bridge CFTypeRef)self, NO);
|
||||
onFocus(self.handle, NO);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,7 +178,7 @@ NSArray<UIKeyCommand *> *_keyCommands;
|
||||
}
|
||||
|
||||
- (void)insertText:(NSString *)text {
|
||||
onText((__bridge CFTypeRef)self, (__bridge CFTypeRef)text);
|
||||
onText(self.handle, (__bridge CFTypeRef)text);
|
||||
}
|
||||
|
||||
- (BOOL)canBecomeFirstResponder {
|
||||
@@ -190,23 +190,23 @@ NSArray<UIKeyCommand *> *_keyCommands;
|
||||
}
|
||||
|
||||
- (void)deleteBackward {
|
||||
onDeleteBackward((__bridge CFTypeRef)self);
|
||||
onDeleteBackward(self.handle);
|
||||
}
|
||||
|
||||
- (void)onUpArrow {
|
||||
onUpArrow((__bridge CFTypeRef)self);
|
||||
onUpArrow(self.handle);
|
||||
}
|
||||
|
||||
- (void)onDownArrow {
|
||||
onDownArrow((__bridge CFTypeRef)self);
|
||||
onDownArrow(self.handle);
|
||||
}
|
||||
|
||||
- (void)onLeftArrow {
|
||||
onLeftArrow((__bridge CFTypeRef)self);
|
||||
onLeftArrow(self.handle);
|
||||
}
|
||||
|
||||
- (void)onRightArrow {
|
||||
onRightArrow((__bridge CFTypeRef)self);
|
||||
onRightArrow(self.handle);
|
||||
}
|
||||
|
||||
- (NSArray<UIKeyCommand *> *)keyCommands {
|
||||
@@ -271,3 +271,8 @@ void gio_showCursor() {
|
||||
void gio_setCursor(NSUInteger curID) {
|
||||
// Not supported.
|
||||
}
|
||||
|
||||
void gio_viewSetHandle(CFTypeRef viewRef, uintptr_t handle) {
|
||||
GioView *v = (__bridge GioView *)viewRef;
|
||||
v.handle = handle;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user