summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--delegate_darwin.go100
-rw-r--r--delegatetypes_darwin.go49
-rw-r--r--uitask_darwin.go35
3 files changed, 103 insertions, 81 deletions
diff --git a/delegate_darwin.go b/delegate_darwin.go
new file mode 100644
index 0000000..e903a13
--- /dev/null
+++ b/delegate_darwin.go
@@ -0,0 +1,100 @@
+// 27 february 2014
+package ui
+
+import (
+ "fmt"
+ "unsafe"
+)
+
+/*
+This creates a class goAppDelegate that will be used as the delegate for /everything/. Specifically, it:
+ - runs uitask requests (uitask:)
+ - handles window close events (windowShouldClose:)
+ - handles window resize events (xxxx:)
+ - handles button click events (buttonClick:)
+*/
+
+// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
+// #include <stdlib.h>
+// #include "objc_darwin.h"
+// extern void appDelegate_uitask(id, SEL, id); /* from uitask_darwin.go */
+// extern BOOL appDelegate_windowShouldClose(id, SEL, id);
+// /* because cgo doesn't like Nil */
+// static Class NilClass = Nil;
+import "C"
+
+var (
+ appDelegate C.id
+)
+
+const (
+ _goAppDelegate = "goAppDelegate"
+)
+
+var (
+ _uitask = sel_getUid("uitask:")
+ _windowShouldClose = sel_getUid("windowShouldClose:")
+)
+
+func mkAppDelegate() error {
+ var appdelegateclass C.Class
+
+ appdelegateclass, err = makeDelegateClass(_goAppDelegate)
+ if err != nil {
+ return fmt.Errorf("error creating NSApplication delegate: %v", err)
+ }
+ err = addDelegateMethod(appdelegateclass, _uitask,
+ C.appDelegate_uitask, delegate_void)
+ if err != nil {
+ return fmt.Errorf("error adding NSApplication delegate uitask: method (to do UI tasks): %v", err)
+ }
+ err = addDelegateMethod(appdelegateclass, _windowShouldClose,
+ C.appDelegate_windowShouldClose, delegate_bool)
+ if err != nil {
+ return fmt.Errorf("error adding NSApplication delegate windowShouldClose: method (to handle window close button events): %v", err)
+ }
+ // TODO using objc_new() causes a segfault; find out why
+ // TODO make alloc followed by init (I thought NSObject provided its own init?)
+ appDelegate = objc_alloc(objc_getClass(_goAppDelegate))
+ return nil
+}
+
+//export appDelegate_windowShouldClose
+func appDelegate_windowShouldClose(self C.id, sel C.SEL, win C.id) C.BOOL {
+ sysData := getSysData(win)
+ sysData.signal()
+ return C.BOOL(C.NO) // don't close
+}
+
+// this actually constructs the delegate class
+
+var (
+ _NSObject_Class = C.object_getClass(_NSObject)
+)
+
+func makeDelegateClass(name string) (C.Class, error) {
+ cname := C.CString(name)
+ defer C.free(unsafe.Pointer(cname))
+
+ c := C.objc_allocateClassPair(_NSObject_Class, cname, 0)
+ if c == C.NilClass {
+ return C.NilClass, fmt.Errorf("unable to create Objective-C class %s; reason unknown", name)
+ }
+ C.objc_registerClassPair(c)
+ return c, nil
+}
+
+var (
+ delegate_void = []C.char{'v', '@', ':', '@', 0} // void (*)(id, SEL, id)
+ delegate_bool = []C.char{'#', '@', ':', '@', 0} // BOOL (*)(id, SEL, id)
+)
+
+// according to errors spit out by cgo, C function pointers are unsafe.Pointer
+func addDelegateMethod(class C.Class, sel C.SEL, imp unsafe.Pointer, ty []C.char) error {
+ ok := C.class_addMethod(class, sel, C.IMP(imp), &ty[0])
+ if ok == C.BOOL(C.NO) {
+ // TODO get function name
+ return fmt.Errorf("unable to add selector %v/imp %v (reason unknown)", sel, imp)
+ }
+ return nil
+}
diff --git a/delegatetypes_darwin.go b/delegatetypes_darwin.go
deleted file mode 100644
index 2bc3498..0000000
--- a/delegatetypes_darwin.go
+++ /dev/null
@@ -1,49 +0,0 @@
-// 27 february 2014
-package ui
-
-import (
- "fmt"
- "unsafe"
-)
-
-// #cgo LDFLAGS: -lobjc -framework Foundation
-// #include <stdlib.h>
-// #include "objc_darwin.h"
-// /* because cgo doesn't like Nil */
-// Class NilClass = Nil;
-import "C"
-
-var (
- _NSObject_Class = C.object_getClass(_NSObject)
-)
-
-func makeDelegateClass(name string) (C.Class, error) {
- cname := C.CString(name)
- defer C.free(unsafe.Pointer(cname))
-
- c := C.objc_allocateClassPair(_NSObject_Class, cname, 0)
- if c == C.NilClass {
- return C.NilClass, fmt.Errorf("unable to create Objective-C class %s; reason unknown", name)
- }
- C.objc_registerClassPair(c)
- return c, nil
-}
-
-// according to errors spit out by cgo, C function pointers are unsafe.Pointer
-func addDelegateMethod(class C.Class, sel C.SEL, imp unsafe.Pointer) error {
- // maps to void (*)(id, SEL, id)
- ty := []C.char{'v', '@', ':', '@', 0}
-
- // clas methods get stored in the metaclass; the objc_allocateClassPair() docs say this will work
- // metaclass := C.object_getClass(C.id(unsafe.Pointer(class)))
- // we're adding instance methods, so just class will do
- ok := C.class_addMethod(class,
- sel,
- C.IMP(imp),
- &ty[0])
- if ok == C.BOOL(C.NO) {
- // TODO get function name
- return fmt.Errorf("unable to add selector %v/imp %v (reason unknown)", sel, imp)
- }
- return nil
-}
diff --git a/uitask_darwin.go b/uitask_darwin.go
index 2a32f86..493fd8c 100644
--- a/uitask_darwin.go
+++ b/uitask_darwin.go
@@ -7,17 +7,8 @@ import (
"unsafe"
)
-/*
-We will create an Objective-C class goAppDelegate. It contains two methods:
- - (void)applicationDidFinishLoading:(NSNotification *)unused
- will signal to ui() that we are now in the Cocoa event loop; we make our goAppDelegate instance the NSApplication delegate
- - (void)uitask:(NSValue *)functionPointer
- the function that actually performs our UI task functions; it is called with NSObject's performSelectorOnMainThread system
-*/
-
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
// #include "objc_darwin.h"
-// extern void appDelegate_uitask(id, SEL, id);
import "C"
// temporary for now
@@ -30,7 +21,6 @@ var (
_NSAutoreleasePool = objc_getClass("NSAutoreleasePool")
_NSValue = objc_getClass("NSValue")
- _uitask = sel_getUid("uitask:")
_valueWithPointer = sel_getUid("valueWithPointer:")
_performSelectorOnMainThread =
sel_getUid("performSelectorOnMainThread:withObject:waitUntilDone:")
@@ -43,7 +33,7 @@ func ui(main func()) error {
uitask = make(chan func())
- NSApp, appDelegate, err := initCocoa()
+ NSApp, err := initCocoa()
if err != nil {
return err
}
@@ -73,34 +63,15 @@ func ui(main func()) error {
// TODO move to init_darwin.go?
-const (
- _goAppDelegate = "goAppDelegate"
-)
-
var (
_NSApplication = objc_getClass("NSApplication")
_sharedApplication = sel_getUid("sharedApplication")
)
-func initCocoa() (NSApp C.id, appDelegate C.id, err error) {
- var appdelegateclass C.Class
-
+func initCocoa() (NSApp C.id, err error) {
NSApp = C.objc_msgSend_noargs(_NSApplication, _sharedApplication)
- appdelegateclass, err = makeDelegateClass(_goAppDelegate)
- if err != nil {
- err = fmt.Errorf("error creating NSApplication delegate: %v", err)
- return
- }
- err = addDelegateMethod(appdelegateclass, _uitask, C.appDelegate_uitask)
- if err != nil {
- err = fmt.Errorf("error adding NSApplication delegate uitask: method (to do UI tasks): %v", err)
- return
- }
- // TODO using objc_new() causes a segfault; find out why
- // TODO make alloc followed by init (I thought NSObject provided its own init?)
- appDelegate = objc_alloc(objc_getClass(_goAppDelegate))
-
+ err = mkAppDelegate()
return
}