Migrated the Mac OS X backend to the new uitask system.
This commit is contained in:
parent
2a7152339f
commit
37051f5c15
|
@ -56,11 +56,15 @@ extern NSRect dummyRect;
|
||||||
|
|
||||||
@implementation appDelegate
|
@implementation appDelegate
|
||||||
|
|
||||||
- (void)uitask:(NSValue *)fp
|
// these are the uitask actions
|
||||||
|
|
||||||
|
- (void)createWindow:(NSValue *)fp
|
||||||
{
|
{
|
||||||
appDelegate_uitask([fp pointerValue]);
|
uitask_createWindow([fp pointerValue]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// these are the other delegate functions
|
||||||
|
|
||||||
- (BOOL)windowShouldClose:(id)win
|
- (BOOL)windowShouldClose:(id)win
|
||||||
{
|
{
|
||||||
return appDelegate_windowShouldClose(win);
|
return appDelegate_windowShouldClose(win);
|
||||||
|
@ -111,6 +115,9 @@ id windowGetContentView(id window)
|
||||||
return [((NSWindow *) window) contentView];
|
return [((NSWindow *) window) contentView];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// these are for douitask() but are here because @selector() is not a constant expression
|
||||||
|
SEL createWindow;
|
||||||
|
|
||||||
BOOL initCocoa(id appDelegate)
|
BOOL initCocoa(id appDelegate)
|
||||||
{
|
{
|
||||||
// on 10.6 the -[NSApplication setDelegate:] method complains if we don't have one
|
// on 10.6 the -[NSApplication setDelegate:] method complains if we don't have one
|
||||||
|
@ -124,11 +131,13 @@ BOOL initCocoa(id appDelegate)
|
||||||
return NO;
|
return NO;
|
||||||
[NSApp activateIgnoringOtherApps:YES]; // TODO actually do C.NO here? Russ Cox does YES in his devdraw; the docs say the Finder does NO
|
[NSApp activateIgnoringOtherApps:YES]; // TODO actually do C.NO here? Russ Cox does YES in his devdraw; the docs say the Finder does NO
|
||||||
[NSApp setDelegate:appDelegate];
|
[NSApp setDelegate:appDelegate];
|
||||||
|
// uitask selectors
|
||||||
|
createWindow = @selector(createWindow:);
|
||||||
[pool release];
|
[pool release];
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
void douitask(id appDelegate, void *p)
|
void douitask(id appDelegate, SEL sel, void *p)
|
||||||
{
|
{
|
||||||
NSAutoreleasePool *pool;
|
NSAutoreleasePool *pool;
|
||||||
NSValue *fp;
|
NSValue *fp;
|
||||||
|
@ -136,7 +145,7 @@ void douitask(id appDelegate, void *p)
|
||||||
// we need to make an NSAutoreleasePool, otherwise we get leak warnings on stderr
|
// we need to make an NSAutoreleasePool, otherwise we get leak warnings on stderr
|
||||||
pool = [NSAutoreleasePool new];
|
pool = [NSAutoreleasePool new];
|
||||||
fp = [NSValue valueWithPointer:p];
|
fp = [NSValue valueWithPointer:p];
|
||||||
[appDelegate performSelectorOnMainThread:@selector(uitask:)
|
[appDelegate performSelectorOnMainThread:sel
|
||||||
withObject:fp
|
withObject:fp
|
||||||
waitUntilDone:YES]; // wait so we can properly drain the autorelease pool; on other platforms we wind up waiting anyway (since the main thread can only handle one thing at a time) so
|
waitUntilDone:YES]; // wait so we can properly drain the autorelease pool; on other platforms we wind up waiting anyway (since the main thread can only handle one thing at a time) so
|
||||||
[pool release];
|
[pool release];
|
||||||
|
|
|
@ -63,7 +63,8 @@ extern uintptr_t keyCode(id);
|
||||||
extern id makeAppDelegate(void);
|
extern id makeAppDelegate(void);
|
||||||
extern id windowGetContentView(id);
|
extern id windowGetContentView(id);
|
||||||
extern BOOL initCocoa(id);
|
extern BOOL initCocoa(id);
|
||||||
extern void douitask(id, void *);
|
extern SEL createWindow;
|
||||||
|
extern void douitask(id, SEL, void *);
|
||||||
extern void breakMainLoop(void);
|
extern void breakMainLoop(void);
|
||||||
extern void cocoaMainLoop(void);
|
extern void cocoaMainLoop(void);
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,28 @@ import (
|
||||||
// #include "objc_darwin.h"
|
// #include "objc_darwin.h"
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
var uitask chan func()
|
// the performSelectorOnMainThread: in our uitask functions is told to wait until the action is done before it returns
|
||||||
|
// so we're fine keeping this on the Go side since the GC won't collect it from under us
|
||||||
|
type uitaskParams struct {
|
||||||
|
window *Window // createWindow
|
||||||
|
control Control // createWindow
|
||||||
|
show bool // createWindow
|
||||||
|
}
|
||||||
|
|
||||||
|
//export uitask_createWindow
|
||||||
|
func uitask_createWindow(data unsafe.Pointer) {
|
||||||
|
uc := (*uitaskParams)(data)
|
||||||
|
uc.window.create(uc.control, uc.show)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (_uitask) createWindow(w *Window, c Control, s bool) {
|
||||||
|
uc := &uitaskParams{
|
||||||
|
window: w,
|
||||||
|
control: c,
|
||||||
|
show: s,
|
||||||
|
}
|
||||||
|
C.douitask(appDelegate, C.createWindow, unsafe.Pointer(uc))
|
||||||
|
}
|
||||||
|
|
||||||
func uiinit() error {
|
func uiinit() error {
|
||||||
err := initCocoa()
|
err := initCocoa()
|
||||||
|
@ -21,22 +42,15 @@ func uiinit() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// do this at the end in case something goes wrong
|
|
||||||
uitask = make(chan func())
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ui() {
|
func ui() {
|
||||||
// Cocoa must run on the first thread created by the program, so we run our dispatcher on another thread instead
|
// Cocoa must run on the first thread created by the program, so we run our dispatcher on another thread instead
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
<-Stop
|
||||||
select {
|
// TODO is this function thread-safe?
|
||||||
case f := <-uitask:
|
|
||||||
C.douitask(appDelegate, unsafe.Pointer(&f))
|
|
||||||
case <-Stop:
|
|
||||||
C.breakMainLoop()
|
C.breakMainLoop()
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
C.cocoaMainLoop()
|
C.cocoaMainLoop()
|
||||||
|
|
Loading…
Reference in New Issue