diff --git a/alloc_darwin.m b/alloc_darwin.m new file mode 100644 index 00000000..48b2a12f --- /dev/null +++ b/alloc_darwin.m @@ -0,0 +1,31 @@ +// 4 december 2014 +#include "ui_darwin.h" + +void *uiAlloc(size_t size) +{ + void *out; + + out = malloc(size); + NSAssert(out != NULL, @"out of memory in uiAlloc()"); + memset(out, 0, size); + return out; +} + +void *uiRealloc(void *p, size_t size) +{ + void *out; + + if (p == NULL) + return uiAlloc(size); + out = realloc(p, size); + NSAssert(out != NULL, @"out of memory in uiRealloc()"); + // TODO zero the extra memory + return out; +} + +void uiFree(void *p) +{ + if (p == NULL) + return; + free(p); +} diff --git a/init_darwin.m b/init_darwin.m new file mode 100644 index 00000000..86f271c5 --- /dev/null +++ b/init_darwin.m @@ -0,0 +1,38 @@ +// 6 april 2015 +#include "ui_darwin.m" + +@interface uiApplication : NSApplication +@end + +@implementation uiApplication + +// hey look! we're overriding terminate:! +// we're going to make sure we can go back to main() whether Cocoa likes it or not! +// and just how are we going to do that, hm? +// (note: this is called after applicationShouldTerminate:) +- (void)terminate:(id)sender +{ + // yes that's right folks: DO ABSOLUTELY NOTHING. + // the magic is [NSApp run] will just... stop. +} + +@end + +// TODO applicationShouldTerminateAfterLastWindowClosed + +uiInitError *uiInit(uiInitOptions *o) +{ + [uiApplication sharedApplication]; + // don't check for a NO return; something (launch services?) causes running from application bundles to always return NO when asking to change activation policy, even if the change is to the same activation policy! + // see https://github.com/andlabs/ui/issues/6 + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; + return NULL; +} + +const char *uiInitErrorMessage(uiInitError *err) +{ +} + +void uiInitErrorFree(uiInitError *err) +{ +} diff --git a/main_darwin.m b/main_darwin.m new file mode 100644 index 00000000..be9b5998 --- /dev/null +++ b/main_darwin.m @@ -0,0 +1,28 @@ +// 6 april 2015 +#include "ui_darwin.h" + +// TODO merge with init_darwin.m? + +void uiMain(void) +{ + [NSApp run]; +} + +void uiQuit(void) +{ + NSEvent *e; + + [NSApp stop:NSApp]; + // stop: won't register until another event has passed; let's synthesize one + e = [NSEvent otherEventWithType:NSApplicationDefined + location:NSZeroPoint + modifierFlags:0 + timestamp:[[NSProcessInfo processInfo] systemUptime] + windowNumber:0 + context:[NSGraphicsContext currentContext] + subtype:0 + data1:0 + data2:0]; + [NSApp postEvent:e atStart:NO]; // let pending events take priority + // TODO really wait? +} diff --git a/ui_darwin.h b/ui_darwin.h new file mode 100644 index 00000000..60826e4e --- /dev/null +++ b/ui_darwin.h @@ -0,0 +1,16 @@ +// 6 january 2015 + +#ifndef __UI_UI_DARWIN_H__ +#define __UI_UI_DARWIN_H__ + +#define MAC_OS_X_VERSION_MIN_REQUIRED MAC_OS_X_VERSION_10_7 +#define MAC_OS_X_VERSION_MAX_ALLOWED MAC_OS_X_VERSION_10_7 +#import +#import "ui.h" + +// alloc_darwin.m +extern void *uiAlloc(size_t); +extern void *uiRealloc(void *, size_t); +extern void uiFree(void *); + +#endif diff --git a/window_darwin.m b/window_darwin.m new file mode 100644 index 00000000..44696901 --- /dev/null +++ b/window_darwin.m @@ -0,0 +1,78 @@ +// 6 april 2015 +#include "ui_darwin.h" + +@interface uiWindowDelegate : NSWindowDelegate +@property void (*onClosing)(uiWindow *, void *); +@property void *onClosingData; +@end + +@implementation uiWindowDelegate + +// TODO will this *destroy* the window? +- (BOOL)windowShouldClose:(id)win +{ + // return exact constants to be safe + if ((*(self.onClosing))(self.onClosingData)) + return YES; + return NO; +} + +@end + +struct uiWindow { + NSWindow *w; + uiWindowDelegate *d; +}; + +static int defaultOnClosing(uiWindow *w, void *data) +{ + return 1; +} + +uiWindow *uiNewWindow(char *title, int width, int height) +{ + uiWindow *w; + + w = (uiWindow *) uiAlloc(sizeof (uiWindow)); + + w->w = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, (CGFloat) width, (CGFloat) height) + styleMask:(NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask) + backing:NSBackingStoreBuffered + defer:YES]; + // TODO substitutions + + w->d = [uiWindowDelegate new]; + w->d.onClosing = defaultOnClosing; + [w->w setDelegate:w->d]; + + return w; +} + +void uiWindowDestroy(uiWindow *w) +{ + // TODO + // TODO will w->d be destroyed? +} + +uintptr_t uiWindowHandle(uiWindow *w) +{ + return (uintptr_t) (w->w); +} + +// TODO titles + +void uiWindowShow(uiWindow *w) +{ + [w->w makeKeyAndOrderFront:w->w]; +} + +void uiWindowHide(uiWindow *w) +{ + [w->w orderOut:w->w]; +} + +void uiWindowOnClosing(uiWindow *w, int (*)(uiWindow *f, void *), void *data) +{ + w->d.onClosing = f; + w->d.onClosingData = data; +}