#import #import #import #import #import #import #import #import #import #import #import #import #import // Workaround for Apple NSScreen bug :( @interface NSScreen (NSScreenAccess) - (void) setFrame:(NSRect)frame; @end @implementation NSScreen (NSScreenAccess) - (void) setFrame:(NSRect)frame; { _frame = frame; } @end // Necessary to catch input events in fullscreen mode @interface GosuApplication : NSApplication { Gosu::Input* input; } - (void)sendEvent:(NSEvent *)anEvent; - (void)setInput:(Gosu::Input&)ipt; @end @implementation GosuApplication - (void)sendEvent:(NSEvent *)anEvent { switch ([anEvent type]) { case NSLeftMouseDown: case NSLeftMouseUp: case NSRightMouseDown: case NSRightMouseUp: case NSScrollWheel: case NSKeyUp: case NSKeyDown: case NSFlagsChanged: input->feedNSEvent(anEvent); break; default: [super sendEvent:anEvent]; } } - (void)setInput:(Gosu::Input&)ipt { input = &ipt; } @end namespace { void cgCheck(CGDisplayErr err, const char* action) { if (err != CGDisplayNoErr) throw std::runtime_error(std::string("Core Graphics error while ") + action); } } typedef void (*WindowProc)(Gosu::Window&); @interface GosuForwarder : NSObject { Gosu::Window* win; WindowProc pr; } - (id)initWithWindow: (Gosu::Window*)window withProc:(WindowProc)proc; - (void)doTick: (NSTimer*)timer; - (BOOL)windowShouldClose: (id)sender; @end @implementation GosuForwarder - (id)initWithWindow: (Gosu::Window*)window withProc:(WindowProc)proc { if (![super init]) return nil; win = window; pr = proc; return self; } - (void)doTick: (NSTimer*)timer { pr(*win); } - (BOOL)windowShouldClose: (id)sender { [NSApp stop: nil]; return YES; } @end #define OVERRIDE_METHOD(method) \ - (void) method: (NSEvent*) event \ { \ _input->feedNSEvent(event); \ } @interface GosuWindow : NSWindow { Gosu::Input* _input; } @end @implementation GosuWindow - (void) setInput: (Gosu::Input*)input { _input = input; } OVERRIDE_METHOD(keyDown); OVERRIDE_METHOD(keyUp); OVERRIDE_METHOD(flagsChanged); OVERRIDE_METHOD(mouseDown); OVERRIDE_METHOD(mouseUp); OVERRIDE_METHOD(rightMouseDown); OVERRIDE_METHOD(rightMouseUp); OVERRIDE_METHOD(scrollWheel); @end @interface GosuView : NSView { Gosu::Input* _input; } @end @implementation GosuView - (void) setInput: (Gosu::Input*)input { _input = input; } - (BOOL)acceptsFirstResponder { return YES; } OVERRIDE_METHOD(keyDown); OVERRIDE_METHOD(keyUp); OVERRIDE_METHOD(flagsChanged); OVERRIDE_METHOD(mouseDown); OVERRIDE_METHOD(mouseUp); OVERRIDE_METHOD(rightMouseDown); OVERRIDE_METHOD(rightMouseUp); OVERRIDE_METHOD(scrollWheel); @end #undef OVERRIDE_METHOD struct Gosu::Window::Impl { ObjRef pool; // Windowed mode: NSWindow subclass and delegate that forwards events to it. ObjRef window; ObjRef forwarder; // Fullscreen mode. Also remember old display mode. CFDictionaryRef newMode, savedMode; NSRect savedFrame; ObjRef context; boost::scoped_ptr graphics; boost::scoped_ptr