generated from treeform/nimtemplate
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #9 from guzba/master
macos2
- Loading branch information
Showing
5 changed files
with
390 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
#import <Cocoa/Cocoa.h> | ||
|
||
NSInteger const decoratedWindowMask = NSTitledWindowMask | NSClosableWindowMask | NSResizableWindowMask | NSMiniaturizableWindowMask; | ||
NSInteger const undecoratedWindowMask = NSBorderlessWindowMask | NSMiniaturizableWindowMask; | ||
|
||
static void postEmptyEvent(void) { | ||
NSEvent* event = [NSEvent otherEventWithType:NSEventTypeApplicationDefined | ||
location:NSMakePoint(0, 0) | ||
modifierFlags:0 | ||
timestamp:0 | ||
windowNumber:0 | ||
context:nil | ||
subtype:0 | ||
data1:0 | ||
data2:0]; | ||
[NSApp postEvent:event atStart:YES]; | ||
} | ||
|
||
static void createMenuBar(void) { | ||
[NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; | ||
|
||
id menubar = [NSMenu new]; | ||
id appMenuItem = [NSMenuItem new]; | ||
[menubar addItem:appMenuItem]; | ||
[NSApp setMainMenu:menubar]; | ||
|
||
id appMenu = [NSMenu new]; | ||
NSString* appName = [[NSProcessInfo processInfo] processName]; | ||
id quitTitle = [@"Quit " stringByAppendingString:appName]; | ||
id quitMenuItem = [[NSMenuItem alloc] initWithTitle:quitTitle | ||
action:@selector(terminate:) keyEquivalent:@"q"]; | ||
[appMenu addItem:quitMenuItem]; | ||
[appMenuItem setSubmenu:appMenu]; | ||
} | ||
|
||
static int pickOpenGLProfile(int majorVersion) { | ||
if (majorVersion == 4) { | ||
return NSOpenGLProfileVersion4_1Core; | ||
} | ||
if (majorVersion == 3) { | ||
return NSOpenGLProfileVersion3_2Core; | ||
} | ||
return NSOpenGLProfileVersionLegacy; | ||
} | ||
|
||
@interface WindyApplicationDelegate : NSObject <NSApplicationDelegate> | ||
@end | ||
|
||
@implementation WindyApplicationDelegate | ||
|
||
- (void)applicationWillFinishLaunching:(NSNotification*)notification { | ||
createMenuBar(); | ||
} | ||
|
||
- (void)applicationDidFinishLaunching:(NSNotification*)notification { | ||
// Post an empty event then stop the NSApp run from innerInit() | ||
postEmptyEvent(); | ||
[NSApp stop:nil]; | ||
} | ||
|
||
@end | ||
|
||
@interface WindyWindow : NSWindow | ||
@end | ||
|
||
@implementation WindyWindow | ||
@end | ||
|
||
@interface WindyContentView : NSOpenGLView | ||
@end | ||
|
||
@implementation WindyContentView | ||
|
||
- (id) initWithFrameAndConfig:(NSRect)frame | ||
vsync:(bool)vsync | ||
openglMajorVersion:(int)openglMajorVersion | ||
openglMinorVersion:(int)openglMinorVersion | ||
msaa:(int)msaa | ||
depthBits:(int)depthBits | ||
stencilBits:(int)stencilBits { | ||
NSOpenGLPixelFormatAttribute attribs[] = | ||
{ | ||
NSOpenGLPFAMultisample, | ||
NSOpenGLPFASampleBuffers, msaa > 0 ? 1 : 0, | ||
NSOpenGLPFASamples, msaa, | ||
NSOpenGLPFAAccelerated, | ||
NSOpenGLPFADoubleBuffer, | ||
NSOpenGLPFAColorSize, 32, | ||
NSOpenGLPFAAlphaSize, 8, | ||
NSOpenGLPFADepthSize, depthBits, | ||
NSOpenGLPFAStencilSize, stencilBits, | ||
NSOpenGLPFAOpenGLProfile, pickOpenGLProfile(openglMajorVersion), | ||
0 | ||
}; | ||
|
||
NSOpenGLPixelFormat* pf = [[NSOpenGLPixelFormat alloc] initWithAttributes:attribs]; | ||
|
||
self = [super initWithFrame:frame pixelFormat:pf]; | ||
|
||
[[self openGLContext] makeCurrentContext]; | ||
|
||
GLint swapInterval = vsync ? 1 : 0; | ||
[[self openGLContext] setValues:&swapInterval forParameter:NSOpenGLCPSwapInterval]; | ||
|
||
return self; | ||
} | ||
|
||
@end | ||
|
||
WindyApplicationDelegate* appDelegate; | ||
|
||
void innerInit() { | ||
[NSApplication sharedApplication]; | ||
|
||
appDelegate = [[WindyApplicationDelegate alloc] init]; | ||
[NSApp setDelegate:appDelegate]; | ||
|
||
[NSApp run]; // We will break out of this in applicationDidFinishLaunching | ||
} | ||
|
||
void innerNewPlatformWindow( | ||
char* title, | ||
int width, | ||
int height, | ||
bool vsync, | ||
int openglMajorVersion, | ||
int openglMinorVersion, | ||
int msaa, | ||
int depthBits, | ||
int stencilBits, | ||
WindyWindow** windowRet | ||
) { | ||
NSRect contentRect = NSMakeRect(0, 0, width, height); | ||
|
||
WindyWindow* window = [[WindyWindow alloc] initWithContentRect:contentRect | ||
styleMask:decoratedWindowMask | ||
backing:NSBackingStoreBuffered | ||
defer:NO]; | ||
|
||
WindyContentView* view = [[WindyContentView alloc] initWithFrameAndConfig:contentRect | ||
vsync:vsync | ||
openglMajorVersion:openglMajorVersion | ||
openglMinorVersion:openglMinorVersion | ||
msaa:msaa | ||
depthBits:depthBits | ||
stencilBits:stencilBits]; | ||
|
||
[window setContentView:view]; | ||
[window setTitle:[NSString stringWithUTF8String:title]]; | ||
|
||
*windowRet = window; | ||
} | ||
|
||
void innerMakeContextCurrent(WindyWindow* window) { | ||
[[[window contentView] openGLContext] makeCurrentContext]; | ||
} | ||
|
||
void innerSwapBuffers(WindyWindow* window) { | ||
[[[window contentView] openGLContext] flushBuffer]; | ||
} | ||
|
||
void innerPollEvents() { | ||
while (true) { | ||
NSEvent* event = [NSApp nextEventMatchingMask:NSEventMaskAny | ||
untilDate:[NSDate distantPast] | ||
inMode:NSDefaultRunLoopMode | ||
dequeue:YES]; | ||
if (event == nil) { | ||
break; | ||
} | ||
|
||
[NSApp sendEvent:event]; | ||
} | ||
} | ||
|
||
bool innerGetVisible(WindyWindow* window) { | ||
return window.isVisible; | ||
} | ||
|
||
bool innerGetDecorated(WindyWindow* window) { | ||
return (window.styleMask & NSTitledWindowMask) != 0; | ||
} | ||
|
||
bool innerGetResizable(WindyWindow* window) { | ||
return (window.styleMask & NSResizableWindowMask) != 0; | ||
} | ||
|
||
void innerGetSize(WindyWindow* window, int* width, int* height) { | ||
NSRect contentRect = [[window contentView] frame]; | ||
*width = contentRect.size.width; | ||
*height = contentRect.size.height; | ||
} | ||
|
||
void innerGetPos(WindyWindow* window, int* x, int* y) { | ||
NSRect contentRect = [window contentRectForFrameRect:[window frame]]; | ||
*x = contentRect.origin.x; | ||
*y = contentRect.origin.y; | ||
} | ||
|
||
void innerSetVisible(WindyWindow* window, bool visible) { | ||
if (visible) { | ||
[window orderFront:nil]; | ||
} else { | ||
[window orderOut:nil]; | ||
} | ||
} | ||
|
||
void innerSetDecorated(WindyWindow* window, bool decorated) { | ||
window.styleMask = decorated ? decoratedWindowMask : undecoratedWindowMask; | ||
} | ||
|
||
void innerSetResizable(WindyWindow* window, bool resizable) { | ||
if (!innerGetDecorated(window)) { | ||
return; | ||
} | ||
|
||
if (resizable) { | ||
window.styleMask |= NSResizableWindowMask; | ||
} else { | ||
window.styleMask &= ~NSResizableWindowMask; | ||
} | ||
} | ||
|
||
void innerSetSize(WindyWindow* window, int width, int height) { | ||
NSRect contentRect = [window contentRectForFrameRect:[window frame]]; | ||
contentRect.origin.y += contentRect.size.height - height; | ||
contentRect.size = NSMakeSize(width, height); | ||
[window setFrame:[window frameRectForContentRect:contentRect] | ||
display:YES]; | ||
} | ||
|
||
void innerSetPos(WindyWindow* window, int x, int y) { | ||
NSRect rect = NSMakeRect(x, y, 0, 0); | ||
[window setFrameOrigin:rect.origin]; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
{. | ||
passL: "-framework Cocoa", | ||
compile: "macos.m", | ||
.} | ||
|
||
import ../../common, vmath | ||
|
||
type PlatformWindow* = ref object | ||
windowPtr: pointer | ||
|
||
proc innerInit() {.importc.} | ||
|
||
proc innerNewPlatformWindow( | ||
title: cstring, | ||
width: int32, | ||
height: int32, | ||
vsync: bool, | ||
openglMajorVersion: int32, | ||
openglMinorVersion: int32, | ||
msaa: int32, | ||
depthBits: int32, | ||
stencilBits: int32, | ||
windowRet: ptr pointer | ||
) {.importc.} | ||
|
||
proc innerMakeContextCurrent(windowPtr: pointer) {.importc.} | ||
|
||
proc innerSwapBuffers(windowPtr: pointer) {.importc.} | ||
|
||
proc innerPollEvents() {.importc.} | ||
|
||
proc innerGetVisible(windowPtr: pointer): bool {.importc.} | ||
|
||
proc innerSetVisible(windowPtr: pointer, visible: bool) {.importc.} | ||
|
||
proc innerGetDecorated(windowPtr: pointer): bool {.importc.} | ||
|
||
proc innerSetDecorated(windowPtr: pointer, decorated: bool) {.importc.} | ||
|
||
proc innerGetResizable(windowPtr: pointer): bool {.importc.} | ||
|
||
proc innerSetResizable(windowPtr: pointer, resizable: bool) {.importc.} | ||
|
||
proc innerGetSize(windowPtr: pointer, width, height: ptr int32) {.importc.} | ||
|
||
proc innerSetSize(windowPtr: pointer, width, height: int32) {.importc.} | ||
|
||
proc innerGetPos(windowPtr: pointer, x, y: ptr int32) {.importc.} | ||
|
||
proc innerSetPos(windowPtr: pointer, x, y: int32) {.importc.} | ||
|
||
proc platformInit*() = | ||
innerInit() | ||
|
||
proc newPlatformWindow*( | ||
title: string, | ||
size: IVec2, | ||
vsync: bool, | ||
openglMajorVersion: int, | ||
openglMinorVersion: int, | ||
msaa: MSAA, | ||
depthBits: int, | ||
stencilBits: int | ||
): PlatformWindow = | ||
result = PlatformWindow() | ||
innerNewPlatformWindow( | ||
title, | ||
size.x, | ||
size.y, | ||
vsync, | ||
openglMajorVersion.int32, | ||
openglMinorVersion.int32, | ||
msaa.int32, | ||
depthBits.int32, | ||
stencilBits.int32, | ||
result.windowPtr.addr | ||
) | ||
|
||
proc makeContextCurrent*(window: PlatformWindow) = | ||
innerMakeContextCurrent(window.windowPtr) | ||
|
||
proc swapBuffers*(window: PlatformWindow) = | ||
innerSwapBuffers(window.windowPtr) | ||
|
||
proc platformPollEvents*() = | ||
innerPollEvents() | ||
|
||
proc visible*(window: PlatformWindow): bool = | ||
innerGetVisible(window.windowPtr) | ||
|
||
proc `visible=`*(window: PlatformWindow, visible: bool) = | ||
innerSetVisible(window.windowPtr, visible) | ||
|
||
proc decorated*(window: PlatformWindow): bool = | ||
innerGetDecorated(window.windowPtr) | ||
|
||
proc `decorated=`*(window: PlatformWindow, decorated: bool) = | ||
innerSetDecorated(window.windowPtr, decorated) | ||
|
||
proc resizable*(window: PlatformWindow): bool = | ||
innerGetResizable(window.windowPtr) | ||
|
||
proc `resizable=`*(window: PlatformWindow, resizable: bool) = | ||
innerSetResizable(window.windowPtr, resizable) | ||
|
||
proc size*(window: PlatformWindow): IVec2 = | ||
var width, height: int32 | ||
innerGetSize(window.windowPtr, width.addr, height.addr) | ||
ivec2(width, height) | ||
|
||
proc `size=`*(window: PlatformWindow, size: IVec2) = | ||
innerSetSize(window.windowPtr, size.x, size.y) | ||
|
||
proc pos*(window: PlatformWindow): IVec2 = | ||
var x, y: int32 | ||
innerGetPos(window.windowPtr, x.addr, y.addr) | ||
ivec2(x, y) | ||
|
||
proc `pos=`*(window: PlatformWindow, pos: Ivec2) = | ||
innerSetPos(window.windowPtr, pos.x, pos.y) |
Oops, something went wrong.