diff --git a/app/os_darwin.go b/app/os_darwin.go index fb96eaf2..36636119 100644 --- a/app/os_darwin.go +++ b/app/os_darwin.go @@ -6,7 +6,7 @@ package app #include __attribute__ ((visibility ("hidden"))) void gio_wakeupMainThread(void); -__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createDisplayLink(uintptr_t handle); +__attribute__ ((visibility ("hidden"))) CFTypeRef gio_createDisplayLink(void); __attribute__ ((visibility ("hidden"))) void gio_releaseDisplayLink(CFTypeRef dl); __attribute__ ((visibility ("hidden"))) int gio_startDisplayLink(CFTypeRef dl); __attribute__ ((visibility ("hidden"))) int gio_stopDisplayLink(CFTypeRef dl); @@ -42,7 +42,7 @@ static CFTypeRef newNSString(unichar *chars, NSUInteger length) { import "C" import ( "errors" - "runtime/cgo" + "sync" "sync/atomic" "time" "unicode/utf16" @@ -70,6 +70,9 @@ type displayLink struct { running uint32 } +// displayLinks maps CFTypeRefs to *displayLinks. +var displayLinks sync.Map + var mainFuncs = make(chan func(), 1) // runOnMain runs the function on the main thread. @@ -128,18 +131,18 @@ func NewDisplayLink(callback func()) (*displayLink, error) { states: make(chan bool), dids: make(chan uint64), } - h := cgo.NewHandle(d) - dl := C.gio_createDisplayLink(C.uintptr_t(h)) + dl := C.gio_createDisplayLink() if dl == 0 { return nil, errors.New("app: failed to create display link") } - go d.run(dl, h) + go d.run(dl) return d, nil } -func (d *displayLink) run(dl C.CFTypeRef, h cgo.Handle) { +func (d *displayLink) run(dl C.CFTypeRef) { defer C.gio_releaseDisplayLink(dl) - defer h.Delete() + displayLinks.Store(dl, d) + defer displayLinks.Delete(dl) var stopTimer *time.Timer var tchan <-chan time.Time started := false @@ -200,10 +203,14 @@ func (d *displayLink) SetDisplayID(did uint64) { } //export gio_onFrameCallback -func gio_onFrameCallback(dl C.CFTypeRef, handle C.uintptr_t) { - d := cgo.Handle(handle).Value().(*displayLink) - if atomic.LoadUint32(&d.running) != 0 { - d.callback() +func gio_onFrameCallback(ref C.CFTypeRef) { + d, exists := displayLinks.Load(ref) + if !exists { + return + } + dl := d.(*displayLink) + if atomic.LoadUint32(&dl.running) != 0 { + dl.callback() } } diff --git a/app/os_ios.m b/app/os_ios.m index 3ca4892e..7bc2524d 100644 --- a/app/os_ios.m +++ b/app/os_ios.m @@ -123,6 +123,9 @@ static void handleTouches(int last, UIView *view, NSSet *touches, UIE @implementation GioView NSArray *_keyCommands; ++ (void)onFrameCallback:(CADisplayLink *)link { + gio_onFrameCallback((__bridge CFTypeRef)link); +} + (Class)layerClass { return gio_layerClass(); } @@ -227,23 +230,8 @@ NSArray *_keyCommands; } @end -@interface DisplayLinkHandle : NSObject { -} -@property uintptr_t handle; -@end - -@implementation DisplayLinkHandle { -} - -- (void)onFrameCallback:(CADisplayLink *)link { - gio_onFrameCallback((__bridge CFTypeRef)link, _handle); -} -@end - -CFTypeRef gio_createDisplayLink(uintptr_t handle) { - DisplayLinkHandle *h = [DisplayLinkHandle alloc]; - h.handle = handle; - CADisplayLink *dl = [CADisplayLink displayLinkWithTarget:h selector:@selector(onFrameCallback:)]; +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]]; diff --git a/app/os_macos.m b/app/os_macos.m index 49964fbf..ca37371f 100644 --- a/app/os_macos.m +++ b/app/os_macos.m @@ -193,14 +193,14 @@ static void handleMouse(NSView *view, NSEvent *event, int typ, CGFloat dx, CGFlo static GioWindowDelegate *globalWindowDel; static CVReturn displayLinkCallback(CVDisplayLinkRef dl, const CVTimeStamp *inNow, const CVTimeStamp *inOutputTime, CVOptionFlags flagsIn, CVOptionFlags *flagsOut, void *handle) { - gio_onFrameCallback(dl, (uintptr_t)handle); + gio_onFrameCallback(dl); return kCVReturnSuccess; } -CFTypeRef gio_createDisplayLink(uintptr_t handle) { +CFTypeRef gio_createDisplayLink(void) { CVDisplayLinkRef dl; CVDisplayLinkCreateWithActiveCGDisplays(&dl); - CVDisplayLinkSetOutputCallback(dl, displayLinkCallback, (void *)(handle)); + CVDisplayLinkSetOutputCallback(dl, displayLinkCallback, nil); return dl; }