summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bleh_darwin.m29
-rw-r--r--objc_darwin.h4
-rw-r--r--uitask_darwin.go17
3 files changed, 49 insertions, 1 deletions
diff --git a/bleh_darwin.m b/bleh_darwin.m
index ca9c91a..08b02bb 100644
--- a/bleh_darwin.m
+++ b/bleh_darwin.m
@@ -7,6 +7,7 @@ The main culprits are:
- data types listed as being defined in nonexistent headers
- 32-bit/64-bit type differences that are more than just a different typedef
- wrong documentation
+though this is not always the case.
Go wrapper functions (bleh_darwin.go) call these directly and take care of stdint.h -> Go type conversions.
*/
@@ -17,6 +18,7 @@ Go wrapper functions (bleh_darwin.go) call these directly and take care of stdin
#include <Foundation/NSGeometry.h>
#include <AppKit/NSKeyValueBinding.h>
+#include <AppKit/NSEvent.h>
/* exception to the above: cgo doesn't like Nil and delegate_darwin.go has //export so I can't have this there */
Class NilClass = Nil;
@@ -155,3 +157,30 @@ uintptr_t *NSIndexSetEntries(id indexset, uintptr_t count)
free(nsuints);
return ret;
}
+
+/*
+See uitask_darwin.go: we need to synthesize a NSEvent so -[NSApplication stop:] will work. We cannot simply init the default NSEvent though (it throws an exception) so we must do it "the right way". This involves a very convoluted initializer; we'll just do it here to keep things clean on the Go side (this will only be run once anyway, on program exit).
+*/
+
+static id c_NSEvent;
+static SEL s_newEvent;
+static BOOL newEvent_init = NO;
+
+id makeDummyEvent()
+{
+ if (newEvent_init == NO) {
+ c_NSEvent = objc_getClass("NSEvent");
+ s_newEvent = sel_getUid("otherEventWithType:location:modifierFlags:timestamp:windowNumber:context:subtype:data1:data2:");
+ newEvent_init = YES;
+ }
+ return objc_msgSend(c_NSEvent, s_newEvent,
+ (NSUInteger) NSApplicationDefined, /* otherEventWithType: */
+ NSMakePoint(0, 0), /* location: */
+ (NSUInteger) 0, /* modifierFlags: */
+ (double) 0, /* timestamp: */
+ (NSInteger) 0, /* windowNumber: */
+ nil, /* context: */
+ (short) 0, /* subtype: */
+ (NSInteger) 0, /* data1: */
+ (NSInteger) 0); /* data2: */
+}
diff --git a/objc_darwin.h b/objc_darwin.h
index e2d9d92..f73bc2b 100644
--- a/objc_darwin.h
+++ b/objc_darwin.h
@@ -89,6 +89,7 @@ m2(id_id, id, id)
extern id _objc_msgSend_rect_bool(id obj, SEL sel, int64_t x, int64_t y, int64_t w, int64_t h, BOOL b);
extern id objc_msgSend_id_int(id obj, SEL sel, id a, intptr_t b);
extern id objc_msgSend_id_uint(id obj, SEL sel, id a, uintptr_t b);
+m2(id_bool, id, BOOL)
m3(id_id_id, id, id, id)
m3(sel_id_bool, SEL, id, BOOL)
@@ -100,4 +101,7 @@ m4(id_id_id_id, id, id, id, id)
/* for listbox_darwin.go */
extern uintptr_t *NSIndexSetEntries(id, uintptr_t);
+/* for uitask_darwin.go */
+extern id makeDummyEvent();
+
#endif
diff --git a/uitask_darwin.go b/uitask_darwin.go
index 8a77dfa..6acf080 100644
--- a/uitask_darwin.go
+++ b/uitask_darwin.go
@@ -20,6 +20,8 @@ var (
_valueWithPointer = sel_getUid("valueWithPointer:")
_performSelectorOnMainThread =
sel_getUid("performSelectorOnMainThread:withObject:waitUntilDone:")
+ _stop = sel_getUid("stop:")
+ _postEventAtStart = sel_getUid("postEvent:atStart:")
_pointerValue = sel_getUid("pointerValue")
_run = sel_getUid("run")
)
@@ -51,7 +53,20 @@ func ui(main func()) error {
}
}()
- go main()
+ go func() {
+ main()
+ uitask <- func() {
+ // -[NSApplication stop:] stops the event loop; it won't do a clean termination, but we're not too concerned with that (at least not on the other platforms either so)
+ // we can't call -[NSApplication terminate:] because that will just quit the program, ensuring we never leave ui.Go()
+ C.objc_msgSend_id(NSApp, _stop, NSApp)
+ // simply calling -[NSApplication stop:] is not good enough, as the stop flag is only checked when an event comes in
+ // we have to create a "proper" event; a blank event will just throw an exception
+ C.objc_msgSend_id_bool(NSApp,
+ _postEventAtStart,
+ C.makeDummyEvent(),
+ C.BOOL(C.NO)) // not at start, just in case there are other events pending (TODO is this correct?)
+ }
+ }()
C.objc_msgSend_noargs(NSApp, _run)
return nil