Moved uitask_darwin.go to be Objective-C-based. Both delegate_darwin.go and uitask_darwin.go will share the same .m file.
This commit is contained in:
parent
de97125c54
commit
3e712db2e0
|
@ -18,9 +18,7 @@ This creates a class goAppDelegate that will be used as the delegate for /everyt
|
||||||
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
|
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
|
||||||
// #include <stdlib.h>
|
// #include <stdlib.h>
|
||||||
// #include "objc_darwin.h"
|
// #include "objc_darwin.h"
|
||||||
// /* TODO this goes in objc_darwin.h once I take care of everything else */
|
// #include "delegateuitask_darwin.h"
|
||||||
// extern id makeAppDelegate(void);
|
|
||||||
// extern id windowGetContentView(id);
|
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
|
@ -1,53 +0,0 @@
|
||||||
// 13 may 2014
|
|
||||||
|
|
||||||
#include "objc_darwin.h"
|
|
||||||
#include "_cgo_export.h"
|
|
||||||
#include <Foundation/NSObject.h>
|
|
||||||
#include <Foundation/NSValue.h>
|
|
||||||
#include <Foundation/NSNotification.h>
|
|
||||||
#include <AppKit/NSApplication.h>
|
|
||||||
#include <AppKit/NSWindow.h>
|
|
||||||
|
|
||||||
@interface appDelegate : NSObject
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation appDelegate
|
|
||||||
|
|
||||||
- (void)uitask:(NSValue *)fp
|
|
||||||
{
|
|
||||||
appDelegate_uitask([fp pointerValue]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL)windowShouldClose:(id)win
|
|
||||||
{
|
|
||||||
appDelegate_windowShouldClose(win);
|
|
||||||
return NO; // don't close
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)windowDidResize:(NSNotification *)n
|
|
||||||
{
|
|
||||||
appDelegate_windowDidResize([n object]);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)buttonClicked:(id)button
|
|
||||||
{
|
|
||||||
appDelegate_buttonClicked(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app
|
|
||||||
{
|
|
||||||
appDelegate_applicationShouldTerminate();
|
|
||||||
return NSTerminateCancel;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
id makeAppDelegate(void)
|
|
||||||
{
|
|
||||||
return [appDelegate new];
|
|
||||||
}
|
|
||||||
|
|
||||||
id windowGetContentView(id window)
|
|
||||||
{
|
|
||||||
return [((NSWindow *) window) contentView];
|
|
||||||
}
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
/* 13 may 2014 */
|
||||||
|
|
||||||
|
//#include "common_darwin.h"
|
||||||
|
|
||||||
|
extern id makeAppDelegate(void);
|
||||||
|
extern id windowGetContentView(id);
|
||||||
|
extern BOOL initCocoa(id);
|
||||||
|
extern void douitask(id, void *);
|
||||||
|
extern void breakMainLoop(void);
|
||||||
|
extern void cocoaMainLoop(void);
|
|
@ -0,0 +1,95 @@
|
||||||
|
// 13 may 2014
|
||||||
|
|
||||||
|
#include "objc_darwin.h"
|
||||||
|
#include "delegateuitask_darwin.h"
|
||||||
|
#include "_cgo_export.h"
|
||||||
|
#include <Foundation/NSObject.h>
|
||||||
|
#include <Foundation/NSValue.h>
|
||||||
|
#include <Foundation/NSNotification.h>
|
||||||
|
#include <AppKit/NSApplication.h>
|
||||||
|
#include <AppKit/NSWindow.h>
|
||||||
|
#include <Foundation/NSAutoreleasePool.h>
|
||||||
|
|
||||||
|
@interface appDelegate : NSObject
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation appDelegate
|
||||||
|
|
||||||
|
- (void)uitask:(NSValue *)fp
|
||||||
|
{
|
||||||
|
appDelegate_uitask([fp pointerValue]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)windowShouldClose:(id)win
|
||||||
|
{
|
||||||
|
appDelegate_windowShouldClose(win);
|
||||||
|
return NO; // don't close
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)windowDidResize:(NSNotification *)n
|
||||||
|
{
|
||||||
|
appDelegate_windowDidResize([n object]);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)buttonClicked:(id)button
|
||||||
|
{
|
||||||
|
appDelegate_buttonClicked(button);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)app
|
||||||
|
{
|
||||||
|
appDelegate_applicationShouldTerminate();
|
||||||
|
return NSTerminateCancel;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
id makeAppDelegate(void)
|
||||||
|
{
|
||||||
|
return [appDelegate new];
|
||||||
|
}
|
||||||
|
|
||||||
|
id windowGetContentView(id window)
|
||||||
|
{
|
||||||
|
return [((NSWindow *) window) contentView];
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOL initCocoa(id appDelegate)
|
||||||
|
{
|
||||||
|
[NSApplication sharedApplication];
|
||||||
|
if ([NSApp setActivationPolicy:NSApplicationActivationPolicyRegular] != YES)
|
||||||
|
return NO;
|
||||||
|
[NSApp activateIgnoringOtherApps:YES]; // TODO actually do C.NO here? Russ Cox does YES in his devdraw; the docs say the Finder does NO
|
||||||
|
[NSApp setDelegate:appDelegate];
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
void douitask(id appDelegate, void *p)
|
||||||
|
{
|
||||||
|
NSAutoreleasePool *pool;
|
||||||
|
NSValue *fp;
|
||||||
|
|
||||||
|
// we need to make an NSAutoreleasePool, otherwise we get leak warnings on stderr
|
||||||
|
pool = [NSAutoreleasePool new];
|
||||||
|
fp = [NSValue valueWithPointer:p];
|
||||||
|
[appDelegate performSelectorOnMainThread:@selector(uitask:)
|
||||||
|
withObject:fp
|
||||||
|
waitUntilDone:YES]; // wait so we can properly drain the autorelease pool; on other platforms we wind up waiting anyway (since the main thread can only handle one thing at a time) so
|
||||||
|
[pool release];
|
||||||
|
}
|
||||||
|
|
||||||
|
void breakMainLoop(void)
|
||||||
|
{
|
||||||
|
// -[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()
|
||||||
|
[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
|
||||||
|
[NSApp postEvent:makeDummyEvent() // TODO inline this
|
||||||
|
atStart:NO]; // not at start, just in case there are other events pending (TODO is this correct?)
|
||||||
|
}
|
||||||
|
|
||||||
|
void cocoaMainLoop(void)
|
||||||
|
{
|
||||||
|
[NSApp run];
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ import (
|
||||||
|
|
||||||
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
|
// #cgo LDFLAGS: -lobjc -framework Foundation -framework AppKit
|
||||||
// #include "objc_darwin.h"
|
// #include "objc_darwin.h"
|
||||||
|
// #include "delegateuitask_darwin.h"
|
||||||
import "C"
|
import "C"
|
||||||
|
|
||||||
var uitask chan func()
|
var uitask chan func()
|
||||||
|
@ -32,7 +33,7 @@ func ui(main func()) error {
|
||||||
|
|
||||||
uitask = make(chan func())
|
uitask = make(chan func())
|
||||||
|
|
||||||
NSApp, err := initCocoa()
|
err := initCocoa()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -40,36 +41,18 @@ func ui(main func()) error {
|
||||||
// Cocoa must run on the first thread created by the program, so we run our dispatcher on another thread instead
|
// Cocoa must run on the first thread created by the program, so we run our dispatcher on another thread instead
|
||||||
go func() {
|
go func() {
|
||||||
for f := range uitask {
|
for f := range uitask {
|
||||||
// we need to make an NSAutoreleasePool, otherwise we get leak warnings on stderr
|
C.douitask(appDelegate, unsafe.Pointer(&f))
|
||||||
pool := C.objc_msgSend_noargs(_NSAutoreleasePool, _new)
|
|
||||||
fp := C.objc_msgSend_ptr(_NSValue, _valueWithPointer,
|
|
||||||
unsafe.Pointer(&f))
|
|
||||||
C.objc_msgSend_sel_id_bool(
|
|
||||||
appDelegate,
|
|
||||||
_performSelectorOnMainThread,
|
|
||||||
_uitask,
|
|
||||||
fp,
|
|
||||||
C.BOOL(C.YES)) // wait so we can properly drain the autorelease pool; on other platforms we wind up waiting anyway (since the main thread can only handle one thing at a time) so
|
|
||||||
C.objc_msgSend_noargs(pool, _release)
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
main()
|
main()
|
||||||
uitask <- func() {
|
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)
|
C.breakMainLoop()
|
||||||
// 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)
|
C.cocoaMainLoop()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,21 +67,16 @@ var (
|
||||||
// _setDelegate in sysdata_darwin.go
|
// _setDelegate in sysdata_darwin.go
|
||||||
)
|
)
|
||||||
|
|
||||||
func initCocoa() (NSApp C.id, err error) {
|
func initCocoa() (err error) {
|
||||||
C.initBleh() // initialize bleh_darwin.m functions
|
C.initBleh() // initialize bleh_darwin.m functions
|
||||||
NSApp = C.objc_msgSend_noargs(_NSApplication, _sharedApplication)
|
|
||||||
r := C.objc_msgSend_int(NSApp, _setActivationPolicy,
|
|
||||||
0) // NSApplicationActivationPolicyRegular
|
|
||||||
if C.BOOL(uintptr(unsafe.Pointer(r))) != C.BOOL(C.YES) {
|
|
||||||
err = fmt.Errorf("error setting NSApplication activation policy (basically identifies our program as a separate program; needed for several things, such as Dock icon, application menu, window resizing, etc.) (unknown reason)")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
C.objc_msgSend_bool(NSApp, _activateIgnoringOtherApps, C.BOOL(C.YES)) // TODO actually do C.NO here? Russ Cox does YES in his devdraw; the docs say the Finder does NO
|
|
||||||
err = mkAppDelegate()
|
err = mkAppDelegate()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
C.objc_msgSend_id(NSApp, _setDelegate, appDelegate)
|
if C.initCocoa(appDelegate) != C.YES {
|
||||||
|
err = fmt.Errorf("error setting NSApplication activation policy (basically identifies our program as a separate program; needed for several things, such as Dock icon, application menu, window resizing, etc.) (unknown reason)")
|
||||||
|
return
|
||||||
|
}
|
||||||
err = mkAreaClass()
|
err = mkAreaClass()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue