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