summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPietro Gagliardi <[email protected]>2014-02-28 15:08:07 -0500
committerPietro Gagliardi <[email protected]>2014-02-28 15:37:59 -0500
commit6982912a58f03b7974a8718e7cb11a3cd9e877e4 (patch)
treee1fa505bbbe30bb92cabd30aedea8d3639527afd
parent3b9e26ab38cab5718f8ca370afd53141511beb78 (diff)
Added a notification system, hopefully allowing us to merge AppKit requests onto a single thread. In practice, this generates autorelease pool leak messages; it appears notifications are not for this...
-rw-r--r--darwintest/newtypes.go27
-rw-r--r--darwintest/runtimetest.go65
2 files changed, 85 insertions, 7 deletions
diff --git a/darwintest/newtypes.go b/darwintest/newtypes.go
index a4e5a68..7bcb898 100644
--- a/darwintest/newtypes.go
+++ b/darwintest/newtypes.go
@@ -15,8 +15,12 @@ import (
// extern void windowShouldClose(id, SEL, id);
// extern id objc_msgSend_id(id, SEL, id);
// extern void buttonClicked(id, SEL, id);
-// /* cgo doesn't like Nil */
+// extern void gotNotification(id, SEL, id);
+// extern id objc_msgSend_id_id_id(id, SEL, id, id, id);
+// /* cgo doesn't like nil or Nil */
+// extern id objc_msgSend_noargs(id, SEL);
// extern Class NilClass; /* in runtimetest.go because of cgo limitations */
+// extern id Nilid;
import "C"
var NSObject = C.object_getClass(objc_getClass("NSObject"))
@@ -42,7 +46,22 @@ func windowShouldClose(self C.id, sel C.SEL, sender C.id) {
//export buttonClicked
func buttonClicked(self C.id, sel C.SEL, sender C.id) {
- fmt.Println("button clicked")
+ fmt.Println("button clicked; sending notification...")
+ notify("button")
+}
+
+//export gotNotification
+func gotNotification(self C.id, sel C.SEL, note C.id) {
+ data := C.objc_msgSend_noargs(note,
+ sel_getUid("userInfo"))
+ val := C.objc_msgSend_id(data,
+ sel_getUid("objectForKey:"),
+ notekey)
+ source := (*C.char)(unsafe.Pointer(
+ C.objc_msgSend_noargs(val,
+ sel_getUid("UTF8String"))))
+ fmt.Println("got notification from %s",
+ C.GoString(source))
}
func addOurMethod(class C.Class, sel C.SEL, imp C.IMP) {
@@ -61,7 +80,7 @@ func addOurMethod(class C.Class, sel C.SEL, imp C.IMP) {
}
}
-func mk(name string, selW C.SEL, selB C.SEL) C.id {
+func mk(name string, selW C.SEL, selB C.SEL, selN C.SEL) C.id {
class := newClass(name)
addOurMethod(class, selW,
// using &C.ourMethod causes faults for some reason
@@ -69,5 +88,7 @@ func mk(name string, selW C.SEL, selB C.SEL) C.id {
C.objc_registerClassPair(class)
addOurMethod(class, selB,
C.IMP(unsafe.Pointer(C.buttonClicked)))
+ addOurMethod(class, selN,
+ C.IMP(unsafe.Pointer(C.gotNotification)))
return objc_getClass(name)
}
diff --git a/darwintest/runtimetest.go b/darwintest/runtimetest.go
index 9145a74..c19d326 100644
--- a/darwintest/runtimetest.go
+++ b/darwintest/runtimetest.go
@@ -4,6 +4,7 @@ package main
import (
"fmt"
"unsafe"
+ "time"
)
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
@@ -24,7 +25,11 @@ import (
// id objc_msgSend_NSRect(id obj, SEL sel, CGRect a) { return objc_msgSend(obj, sel, a); }
// id objc_msgSend_sel(id obj, SEL sel, SEL a) { return objc_msgSend(obj, sel, a); }
// id objc_msgSend_uint(id obj, SEL sel, NSUInteger a) { return objc_msgSend(obj, sel, a); }
+// id objc_msgSend_id_sel_id_id(id obj, SEL sel, id a, SEL b, id c, id d) { return objc_msgSend(obj, sel, a, b, c, d); }
+// id objc_msgSend_id_id_id(id obj, SEL sel, id a, id b, id c) { return objc_msgSend(obj, sel, a, b, c); }
+// id objc_msgSend_id_id(id obj, SEL sel, id a, id b) { return objc_msgSend(obj, sel, a, b); }
// Class NilClass = Nil; /* for newtypes.go */
+// id Nilid = nil;
import "C"
func objc_getClass(class string) C.id {
@@ -42,6 +47,10 @@ func sel_getUid(sel string) C.SEL {
}
var NSApp C.id
+var defNC C.id
+var delegate C.id
+var note C.id
+var notekey C.id
func init() {
// need an NSApplication first - see https://github.com/TooTallNate/NodObjC/issues/21
@@ -49,9 +58,31 @@ func init() {
sharedApplication := sel_getUid("sharedApplication")
NSApp = C.objc_msgSend_noargs(NSApplication, sharedApplication)
+ defNC = C.objc_msgSend_noargs(
+ objc_getClass("NSNotificationCenter"),
+ sel_getUid("defaultCenter"))
+
selW := sel_getUid("windowShouldClose:")
selB := sel_getUid("buttonClicked:")
- mk("hello", selW, selB)
+ selN := sel_getUid("gotNotification:")
+ mk("hello", selW, selB, selN)
+ delegate = C.objc_msgSend_noargs(
+ objc_getClass("hello"),
+ alloc)
+
+ noteStr := []C.char{'g', 'o', 'n', 'o', 't', 'e', 0}
+ note = C.objc_msgSend_strarg(
+ objc_getClass("NSString"),
+ sel_getUid("stringWithUTF8String:"),
+ &noteStr[0])
+ notekey = note
+ C.objc_msgSend_id_sel_id_id(
+ defNC,
+ sel_getUid("addObserver:selector:name:object:"),
+ delegate,
+ selN,
+ note,
+ C.Nilid)
}
const (
@@ -75,6 +106,27 @@ const (
var alloc = sel_getUid("alloc")
+func notify(source string) {
+ csource := C.CString(source)
+ defer C.free(unsafe.Pointer(csource))
+
+ src := C.objc_msgSend_strarg(
+ objc_getClass("NSString"),
+ sel_getUid("stringWithUTF8String:"),
+ csource)
+ dict := C.objc_msgSend_id_id(
+ objc_getClass("NSDictionary"),
+ sel_getUid("dictionaryWithObject:forKey:"),
+ src,
+ notekey)
+ C.objc_msgSend_id_id_id(
+ defNC,
+ sel_getUid("postNotificationName:object:userInfo:"),
+ note,
+ C.Nilid,
+ dict)
+}
+
func main() {
NSWindow := objc_getClass("NSWindow")
NSWindowinit :=
@@ -92,9 +144,6 @@ func main() {
window := C.objc_msgSend_noargs(NSWindow, alloc)
window = C.objc_msgSend_NSRect_uint_uint_bool(window, NSWindowinit, rect, style, backing, deferx)
C.objc_msgSend_id(window, makeKeyAndOrderFront, window)
- delegate := C.objc_msgSend_noargs(
- objc_getClass("hello"),
- alloc)
C.objc_msgSend_id(window, setDelegate,
delegate)
windowView := C.objc_msgSend_noargs(window,
@@ -121,6 +170,14 @@ func main() {
sel_getUid("addSubview:"),
button)
+ go func() {
+ for {
+ <-time.After(5 * time.Second)
+ fmt.Println("five seconds passed; sending notification...")
+ notify("timer")
+ }
+ }()
+
C.objc_msgSend_noargs(NSApp,
sel_getUid("run"))
}