/* * Copyright 2011-2013 Branimir Karadzic. All rights reserved. * License: http://www.opensource.org/licenses/BSD-2-Clause */ #include #if BX_PLATFORM_OSX #include #include #include #include "entry.h" #include "dbg.h" #define DEFAULT_WIDTH 1280 #define DEFAULT_HEIGHT 720 extern int _main_(int _argc, char** _argv); @interface bgfxApplicationDelegate : NSObject { bool terminated; } + (bgfxApplicationDelegate *)sharedDelegate; - (id)init; - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender; - (bool)applicationHasTerminated; @end @implementation bgfxApplicationDelegate + (bgfxApplicationDelegate *)sharedDelegate { static id delegate = [bgfxApplicationDelegate new]; return delegate; } - (id)init { self = [super init]; if (self) { self->terminated = false; } return self; } - (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { self->terminated = true; return NSTerminateCancel; } - (bool)applicationHasTerminated { return self->terminated; } @end @interface bgfxWindowDelegate : NSObject { unsigned int windowCount; } + (bgfxWindowDelegate *)sharedDelegate; - (id)init; - (void)windowCreated:(NSWindow *)window; - (BOOL)windowShouldClose:(NSWindow *)window; @end @implementation bgfxWindowDelegate + (bgfxWindowDelegate *)sharedDelegate { static id windowDelegate = [bgfxWindowDelegate new]; return windowDelegate; } - (id)init { self = [super init]; if (self) { self->windowCount = 0; } return self; } - (void)windowCreated:(NSWindow *)window { assert(window); [window setDelegate:self]; assert(self->windowCount < ~0u); self->windowCount += 1; } - (BOOL)windowShouldClose:(NSWindow *)window { assert(window); [window setDelegate:nil]; assert(self->windowCount); self->windowCount -= 1; if (self->windowCount == 0) { [NSApp terminate:self]; return false; } return true; } @end namespace entry { struct MainThreadEntry { int m_argc; char** m_argv; static int32_t threadFunc(void* _userData) { MainThreadEntry* self = (MainThreadEntry*)_userData; return _main_(self->m_argc, self->m_argv); } }; struct Context { Context() : m_exit(false) { } NSEvent* WaitEvent () { return [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantFuture] // wait for event inMode:NSDefaultRunLoopMode dequeue:YES]; } NSEvent* PeekEvent () { return [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:[NSDate distantPast] // do not wait for event inMode:NSDefaultRunLoopMode dequeue:YES]; } bool DispatchEvent (NSEvent* event) { if (event) { [NSApp sendEvent:event]; [NSApp updateWindows]; return true; } return false; } int32_t main(int _argc, char** _argv) { [NSApplication sharedApplication]; id dg = [bgfxApplicationDelegate sharedDelegate]; [NSApp setDelegate:dg]; [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; [NSApp activateIgnoringOtherApps:YES]; [NSApp finishLaunching]; [[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationWillFinishLaunchingNotification object:NSApp]; [[NSNotificationCenter defaultCenter] postNotificationName:NSApplicationDidFinishLaunchingNotification object:NSApp]; id quitMenuItem = [NSMenuItem new]; [quitMenuItem initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"]; id appMenu = [NSMenu new]; [appMenu addItem:quitMenuItem]; id appMenuItem = [NSMenuItem new]; [appMenuItem setSubmenu:appMenu]; id menubar = [[NSMenu new] autorelease]; [menubar addItem:appMenuItem]; [NSApp setMainMenu:menubar]; NSRect rect = NSMakeRect(0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT); NSWindow* window = [NSWindow alloc]; [window initWithContentRect:rect styleMask:0 |NSTitledWindowMask |NSClosableWindowMask |NSMiniaturizableWindowMask |NSResizableWindowMask backing:NSBackingStoreBuffered defer:NO ]; NSString* appName = [[NSProcessInfo processInfo] processName]; [window setTitle:appName]; [window cascadeTopLeftFromPoint:NSMakePoint(20,20)]; [window makeKeyAndOrderFront:nil]; [[bgfxWindowDelegate sharedDelegate] windowCreated:window]; bgfx::osxSetNSWindow(window); MainThreadEntry mte; mte.m_argc = _argc; mte.m_argv = _argv; bx::Thread thread; thread.init(mte.threadFunc, &mte); while (!(m_exit = [dg applicationHasTerminated])) { DispatchEvent(WaitEvent()); while (DispatchEvent(PeekEvent())); } thread.shutdown(); return 0; } bool m_exit; }; static Context s_ctx; const Event* poll() { return NULL; } void release(const Event* _event) { } void setWindowSize(uint32_t _width, uint32_t _height) { } void toggleWindowFrame() { } void setMouseLock(bool _lock) { } } // namespace entry int main(int _argc, char** _argv) { using namespace entry; return s_ctx.main(_argc, _argv); } #endif // BX_PLATFORM_OSX