Have ui.Go() return on main() return on Mac OS X.

This commit is contained in:
Pietro Gagliardi 2014-03-05 20:09:15 -05:00
parent 011836e94d
commit d29e1b8710
3 changed files with 49 additions and 1 deletions

View File

@ -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: */
}

View File

@ -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

View File

@ -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