2013-01-16 08:37:07 +04:00
|
|
|
/*
|
2014-02-11 10:18:39 +04:00
|
|
|
* Copyright 2011-2014 Branimir Karadzic. All rights reserved.
|
2013-01-16 08:37:07 +04:00
|
|
|
* License: http://www.opensource.org/licenses/BSD-2-Clause
|
|
|
|
*/
|
|
|
|
|
2013-08-15 08:08:46 +04:00
|
|
|
#include "entry_p.h"
|
2013-01-16 08:37:07 +04:00
|
|
|
|
2013-08-15 08:08:46 +04:00
|
|
|
#if ENTRY_CONFIG_USE_NATIVE && BX_PLATFORM_OSX
|
2013-01-16 08:37:07 +04:00
|
|
|
|
2013-08-08 09:50:01 +04:00
|
|
|
#import <Cocoa/Cocoa.h>
|
2013-01-16 08:37:07 +04:00
|
|
|
|
2013-08-08 10:11:20 +04:00
|
|
|
#include <bgfxplatform.h>
|
|
|
|
|
2013-08-08 09:50:01 +04:00
|
|
|
#include <bx/uint32_t.h>
|
|
|
|
#include <bx/thread.h>
|
2013-11-19 08:43:17 +04:00
|
|
|
#include <bx/os.h>
|
2013-01-16 08:37:07 +04:00
|
|
|
|
|
|
|
#define DEFAULT_WIDTH 1280
|
|
|
|
#define DEFAULT_HEIGHT 720
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
@interface AppDelegate : NSObject<NSApplicationDelegate>
|
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
bool terminated;
|
|
|
|
}
|
2013-07-22 08:53:20 +04:00
|
|
|
|
|
|
|
+ (AppDelegate *)sharedDelegate;
|
2013-01-16 08:37:07 +04:00
|
|
|
- (id)init;
|
|
|
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender;
|
|
|
|
- (bool)applicationHasTerminated;
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
@end
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
@implementation AppDelegate
|
|
|
|
|
|
|
|
+ (AppDelegate *)sharedDelegate
|
|
|
|
{
|
|
|
|
static id delegate = [AppDelegate new];
|
2013-01-16 08:37:07 +04:00
|
|
|
return delegate;
|
|
|
|
}
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
- (id)init
|
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
self = [super init];
|
2013-07-22 08:53:20 +04:00
|
|
|
|
|
|
|
if (nil == self)
|
|
|
|
{
|
|
|
|
return nil;
|
2013-01-16 08:37:07 +04:00
|
|
|
}
|
2013-07-22 08:53:20 +04:00
|
|
|
|
|
|
|
self->terminated = false;
|
2013-01-16 08:37:07 +04:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
|
|
|
{
|
2013-12-07 22:19:54 +04:00
|
|
|
BX_UNUSED(sender);
|
2013-01-16 08:37:07 +04:00
|
|
|
self->terminated = true;
|
|
|
|
return NSTerminateCancel;
|
|
|
|
}
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
- (bool)applicationHasTerminated
|
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
return self->terminated;
|
|
|
|
}
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
@end
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
@interface Window : NSObject<NSWindowDelegate>
|
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
unsigned int windowCount;
|
|
|
|
}
|
2013-07-22 08:53:20 +04:00
|
|
|
|
|
|
|
+ (Window *)sharedDelegate;
|
2013-01-16 08:37:07 +04:00
|
|
|
- (id)init;
|
|
|
|
- (void)windowCreated:(NSWindow *)window;
|
|
|
|
- (BOOL)windowShouldClose:(NSWindow *)window;
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
@end
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
@implementation Window
|
|
|
|
|
|
|
|
+ (Window *)sharedDelegate
|
|
|
|
{
|
|
|
|
static id windowDelegate = [Window new];
|
2013-01-16 08:37:07 +04:00
|
|
|
return windowDelegate;
|
|
|
|
}
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
- (id)init
|
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
self = [super init];
|
2013-07-22 08:53:20 +04:00
|
|
|
if (nil == self)
|
|
|
|
{
|
|
|
|
return nil;
|
2013-01-16 08:37:07 +04:00
|
|
|
}
|
2013-07-22 08:53:20 +04:00
|
|
|
|
|
|
|
self->windowCount = 0;
|
2013-01-16 08:37:07 +04:00
|
|
|
return self;
|
|
|
|
}
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
- (void)windowCreated:(NSWindow *)window
|
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
assert(window);
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
[window setDelegate:self];
|
|
|
|
|
|
|
|
assert(self->windowCount < ~0u);
|
|
|
|
self->windowCount += 1;
|
|
|
|
}
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
- (BOOL)windowShouldClose:(NSWindow *)window
|
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
assert(window);
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
[window setDelegate:nil];
|
|
|
|
|
|
|
|
assert(self->windowCount);
|
|
|
|
self->windowCount -= 1;
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
if (self->windowCount == 0)
|
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
[NSApp terminate:self];
|
|
|
|
return false;
|
|
|
|
}
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
|
|
namespace entry
|
|
|
|
{
|
|
|
|
struct MainThreadEntry
|
|
|
|
{
|
|
|
|
int m_argc;
|
|
|
|
char** m_argv;
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
static int32_t threadFunc(void* _userData)
|
|
|
|
{
|
|
|
|
MainThreadEntry* self = (MainThreadEntry*)_userData;
|
2013-08-08 09:50:01 +04:00
|
|
|
return main(self->m_argc, self->m_argv);
|
2013-01-16 08:37:07 +04:00
|
|
|
}
|
|
|
|
};
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
struct Context
|
|
|
|
{
|
|
|
|
Context()
|
|
|
|
: m_exit(false)
|
|
|
|
{
|
|
|
|
}
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
NSEvent* WaitEvent()
|
|
|
|
{
|
|
|
|
return [NSApp
|
2013-07-22 01:44:53 +04:00
|
|
|
nextEventMatchingMask:NSAnyEventMask
|
|
|
|
untilDate:[NSDate distantFuture] // wait for event
|
|
|
|
inMode:NSDefaultRunLoopMode
|
2013-07-22 08:53:20 +04:00
|
|
|
dequeue:YES
|
|
|
|
];
|
2013-01-16 08:37:07 +04:00
|
|
|
}
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
NSEvent* PeekEvent()
|
|
|
|
{
|
|
|
|
return [NSApp
|
2013-07-22 01:44:53 +04:00
|
|
|
nextEventMatchingMask:NSAnyEventMask
|
|
|
|
untilDate:[NSDate distantPast] // do not wait for event
|
|
|
|
inMode:NSDefaultRunLoopMode
|
2013-07-22 08:53:20 +04:00
|
|
|
dequeue:YES
|
|
|
|
];
|
2013-01-16 08:37:07 +04:00
|
|
|
}
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
bool DispatchEvent(NSEvent* event)
|
|
|
|
{
|
|
|
|
if (event)
|
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
[NSApp sendEvent:event];
|
|
|
|
[NSApp updateWindows];
|
|
|
|
return true;
|
|
|
|
}
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
return false;
|
|
|
|
}
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
int32_t run(int _argc, char** _argv)
|
2013-01-16 08:37:07 +04:00
|
|
|
{
|
2013-07-22 01:44:53 +04:00
|
|
|
[NSApplication sharedApplication];
|
2013-07-22 08:53:20 +04:00
|
|
|
|
|
|
|
id dg = [AppDelegate sharedDelegate];
|
2013-01-16 08:37:07 +04:00
|
|
|
[NSApp setDelegate:dg];
|
|
|
|
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular];
|
|
|
|
[NSApp activateIgnoringOtherApps:YES];
|
|
|
|
[NSApp finishLaunching];
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
[[NSNotificationCenter defaultCenter]
|
2013-07-22 01:44:53 +04:00
|
|
|
postNotificationName:NSApplicationWillFinishLaunchingNotification
|
|
|
|
object:NSApp];
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
[[NSNotificationCenter defaultCenter]
|
2013-07-22 01:44:53 +04:00
|
|
|
postNotificationName:NSApplicationDidFinishLaunchingNotification
|
|
|
|
object:NSApp];
|
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
id quitMenuItem = [NSMenuItem new];
|
|
|
|
[quitMenuItem
|
|
|
|
initWithTitle:@"Quit"
|
|
|
|
action:@selector(terminate:)
|
|
|
|
keyEquivalent:@"q"];
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
id appMenu = [NSMenu new];
|
|
|
|
[appMenu addItem:quitMenuItem];
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
id appMenuItem = [NSMenuItem new];
|
|
|
|
[appMenuItem setSubmenu:appMenu];
|
2013-07-22 08:53:20 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
id menubar = [[NSMenu new] autorelease];
|
|
|
|
[menubar addItem:appMenuItem];
|
|
|
|
[NSApp setMainMenu:menubar];
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
NSRect rect = NSMakeRect(0, 0, DEFAULT_WIDTH, DEFAULT_HEIGHT);
|
|
|
|
NSWindow* window = [NSWindow alloc];
|
|
|
|
[window
|
2013-07-22 01:44:53 +04:00
|
|
|
initWithContentRect:rect
|
|
|
|
styleMask:0
|
|
|
|
|NSTitledWindowMask
|
|
|
|
|NSClosableWindowMask
|
|
|
|
|NSMiniaturizableWindowMask
|
|
|
|
|NSResizableWindowMask
|
|
|
|
backing:NSBackingStoreBuffered defer:NO
|
|
|
|
];
|
|
|
|
NSString* appName = [[NSProcessInfo processInfo] processName];
|
2013-01-16 08:37:07 +04:00
|
|
|
[window setTitle:appName];
|
|
|
|
[window cascadeTopLeftFromPoint:NSMakePoint(20,20)];
|
2013-11-19 08:43:17 +04:00
|
|
|
[window makeKeyAndOrderFront:window];
|
|
|
|
[window setContentView:nil];
|
2013-07-22 08:53:20 +04:00
|
|
|
[[Window sharedDelegate] windowCreated:window];
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
bgfx::osxSetNSWindow(window);
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
MainThreadEntry mte;
|
|
|
|
mte.m_argc = _argc;
|
|
|
|
mte.m_argv = _argv;
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
bx::Thread thread;
|
|
|
|
thread.init(mte.threadFunc, &mte);
|
|
|
|
|
2013-07-22 08:53:20 +04:00
|
|
|
while (!(m_exit = [dg applicationHasTerminated]) )
|
2013-01-16 08:37:07 +04:00
|
|
|
{
|
2013-11-19 08:43:17 +04:00
|
|
|
//DispatchEvent(WaitEvent() );
|
|
|
|
if (bgfx::RenderFrame::Exiting == bgfx::renderFrame() )
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2013-12-07 22:19:54 +04:00
|
|
|
while (DispatchEvent(PeekEvent() ) ) {};
|
2013-01-16 08:37:07 +04:00
|
|
|
}
|
2013-11-19 08:43:17 +04:00
|
|
|
|
|
|
|
|
2013-02-04 01:33:25 +04:00
|
|
|
m_eventQueue.postExitEvent();
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-12-07 22:19:54 +04:00
|
|
|
while (bgfx::RenderFrame::NoContext != bgfx::renderFrame() ) {};
|
2013-01-16 08:37:07 +04:00
|
|
|
thread.shutdown();
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
return 0;
|
|
|
|
}
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-02-04 01:33:25 +04:00
|
|
|
EventQueue m_eventQueue;
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
bool m_exit;
|
|
|
|
};
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
static Context s_ctx;
|
2013-07-22 01:44:53 +04:00
|
|
|
|
2013-01-17 10:44:51 +04:00
|
|
|
const Event* poll()
|
2013-01-16 08:37:07 +04:00
|
|
|
{
|
2013-02-04 01:33:25 +04:00
|
|
|
return s_ctx.m_eventQueue.poll();
|
2013-01-17 10:44:51 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void release(const Event* _event)
|
|
|
|
{
|
2013-02-04 01:33:25 +04:00
|
|
|
s_ctx.m_eventQueue.release(_event);
|
2013-01-17 10:44:51 +04:00
|
|
|
}
|
|
|
|
|
2013-02-04 01:33:25 +04:00
|
|
|
void setWindowSize(uint32_t _width, uint32_t _height)
|
|
|
|
{
|
2013-12-07 22:19:54 +04:00
|
|
|
BX_UNUSED(_width, _height);
|
2013-01-17 10:44:51 +04:00
|
|
|
}
|
|
|
|
|
2014-08-10 18:59:22 +04:00
|
|
|
void setWindowTitle(const char* _title)
|
2014-08-05 23:57:52 +04:00
|
|
|
{
|
|
|
|
BX_UNUSED(_title);
|
|
|
|
}
|
|
|
|
|
2013-01-17 10:44:51 +04:00
|
|
|
void toggleWindowFrame()
|
2013-02-04 01:33:25 +04:00
|
|
|
{
|
2013-01-16 08:37:07 +04:00
|
|
|
}
|
|
|
|
|
2013-01-19 12:22:25 +04:00
|
|
|
void setMouseLock(bool _lock)
|
|
|
|
{
|
2013-12-07 22:19:54 +04:00
|
|
|
BX_UNUSED(_lock);
|
2013-01-19 12:22:25 +04:00
|
|
|
}
|
|
|
|
|
2013-01-16 08:37:07 +04:00
|
|
|
} // namespace entry
|
|
|
|
|
|
|
|
int main(int _argc, char** _argv)
|
|
|
|
{
|
|
|
|
using namespace entry;
|
2013-07-22 08:53:20 +04:00
|
|
|
return s_ctx.run(_argc, _argv);
|
2013-01-16 08:37:07 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // BX_PLATFORM_OSX
|