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:"), + ¬eStr[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")) }