From 90a82c3846f7cb7e4061bda8fedc052c38304f20 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Mon, 18 Oct 2021 00:04:33 -0500 Subject: [PATCH 1/3] getters then setters --- src/windy/platforms/win32/platform.nim | 54 ++++++++++++++------------ 1 file changed, 30 insertions(+), 24 deletions(-) diff --git a/src/windy/platforms/win32/platform.nim b/src/windy/platforms/win32/platform.nim index 6a33181..7148a59 100644 --- a/src/windy/platforms/win32/platform.nim +++ b/src/windy/platforms/win32/platform.nim @@ -133,6 +133,12 @@ proc getDC(hWnd: HWND): HDC = if result == 0: raise newException(WindyError, "Error getting window DC") +proc getWindowStyle(hWnd: HWND): DWORD = + GetWindowLongW(hWnd, GWL_STYLE) + +proc setWindowStyle(hWnd: HWND, style: DWORD) = + SetWindowLongW(hWnd, style, GWL_STYLE) + proc makeContextCurrent(hdc: HDC, hglrc: HGLRC) = if wglMakeCurrent(hdc, hglrc) == 0: raise newException(WindyError, "Error activating OpenGL rendering context") @@ -396,16 +402,24 @@ proc newPlatformWindow*( proc visible*(window: PlatformWindow): bool = IsWindowVisible(window.hWnd) != 0 -proc `visible=`*(window: PlatformWindow, visible: bool) = - if visible: - window.show() - else: - window.hide() - proc decorated*(window: PlatformWindow): bool = - let style = GetWindowLongW(window.hWnd, GWL_STYLE) + let style = getWindowStyle(window.hWnd) (style and WS_BORDER) != 0 +proc resizable*(window: PlatformWindow): bool = + let style = getWindowStyle(window.hWnd) + (style and WS_THICKFRAME) != 0 + +proc size*(window: PlatformWindow): IVec2 = + var rect: RECT + discard GetClientRect(window.hWnd, rect.addr) + ivec2(rect.right, rect.bottom) + +proc pos*(window: PlatformWindow): IVec2 = + var pos: POINT + discard ClientToScreen(window.hWnd, pos.addr) + ivec2(pos.x, pos.y) + proc `decorated=`*(window: PlatformWindow, decorated: bool) = var style: DWORD if decorated: @@ -416,11 +430,13 @@ proc `decorated=`*(window: PlatformWindow, decorated: bool) = if window.visible: style = style or WS_VISIBLE - discard SetWindowLongW(window.hWnd, GWL_STYLE, style) + setWindowStyle(window.hWnd, style) -proc resizable*(window: PlatformWindow): bool = - let style = GetWindowLongW(window.hWnd, GWL_STYLE) - (style and WS_THICKFRAME) != 0 +proc `visible=`*(window: PlatformWindow, visible: bool) = + if visible: + window.show() + else: + window.hide() proc `resizable=`*(window: PlatformWindow, resizable: bool) = if not window.decorated: @@ -435,18 +451,13 @@ proc `resizable=`*(window: PlatformWindow, resizable: bool) = if window.visible: style = style or WS_VISIBLE - discard SetWindowLongW(window.hWnd, GWL_STYLE, style) - -proc size*(window: PlatformWindow): IVec2 = - var rect: RECT - discard GetClientRect(window.hWnd, rect.addr) - ivec2(rect.right, rect.bottom) + setWindowStyle(window.hWnd, style) proc `size=`*(window: PlatformWindow, size: IVec2) = var rect = RECT(top: 0, left: 0, right: size.x, bottom: size.y) discard AdjustWindowRectExForDpi( rect.addr, - decoratedWindowStyle, + getWindowStyle(window.hWnd), 0, WS_EX_APPWINDOW, GetDpiForWindow(window.hWnd) @@ -461,16 +472,11 @@ proc `size=`*(window: PlatformWindow, size: IVec2) = SWP_NOACTIVATE or SWP_NOZORDER or SWP_NOMOVE ) -proc pos*(window: PlatformWindow): IVec2 = - var pos: POINT - discard ClientToScreen(window.hWnd, pos.addr) - ivec2(pos.x, pos.y) - proc `pos=`*(window: PlatformWindow, pos: IVec2) = var rect = RECT(top: pos.x, left: pos.y, bottom: pos.x, right: pos.y) discard AdjustWindowRectExForDpi( rect.addr, - decoratedWindowStyle, + getWindowStyle(window.hWnd), 0, WS_EX_APPWINDOW, GetDpiForWindow(window.hWnd) From 595dc4357b7af0986ad98ef27760421ea02b2149 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Mon, 18 Oct 2021 00:04:49 -0500 Subject: [PATCH 2/3] macos2 --- src/windy.nim | 2 +- src/windy/platforms/macos2/macos.m | 235 ++++++++++++++++++++++++ src/windy/platforms/macos2/platform.nim | 120 ++++++++++++ 3 files changed, 356 insertions(+), 1 deletion(-) create mode 100644 src/windy/platforms/macos2/macos.m create mode 100644 src/windy/platforms/macos2/platform.nim diff --git a/src/windy.nim b/src/windy.nim index cb247ed..dc220fa 100644 --- a/src/windy.nim +++ b/src/windy.nim @@ -5,7 +5,7 @@ export common, vmath when defined(windows): import windy/platforms/win32/platform elif defined(macosx): - import windy/platforms/macos/platform + import windy/platforms/macos2/platform elif defined(linux): import windy/platforms/x11/platform diff --git a/src/windy/platforms/macos2/macos.m b/src/windy/platforms/macos2/macos.m new file mode 100644 index 0000000..a6df5ee --- /dev/null +++ b/src/windy/platforms/macos2/macos.m @@ -0,0 +1,235 @@ +#import + +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 +@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]; +} diff --git a/src/windy/platforms/macos2/platform.nim b/src/windy/platforms/macos2/platform.nim new file mode 100644 index 0000000..59f6905 --- /dev/null +++ b/src/windy/platforms/macos2/platform.nim @@ -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) From 708c5b990b0b02677c65e5c6ef81b9f6d6e2bf58 Mon Sep 17 00:00:00 2001 From: Ryan Oldenburg Date: Mon, 18 Oct 2021 00:07:51 -0500 Subject: [PATCH 3/3] f --- src/windy/platforms/win32/platform.nim | 12 ++++++------ windy.nimble | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/windy/platforms/win32/platform.nim b/src/windy/platforms/win32/platform.nim index 7148a59..b54b4a5 100644 --- a/src/windy/platforms/win32/platform.nim +++ b/src/windy/platforms/win32/platform.nim @@ -51,7 +51,7 @@ var initialized: bool windows*: seq[PlatformWindow] -proc wstr*(str: string): string = +proc wstr(str: string): string = let wlen = MultiByteToWideChar( CP_UTF8, 0, @@ -133,11 +133,11 @@ proc getDC(hWnd: HWND): HDC = if result == 0: raise newException(WindyError, "Error getting window DC") -proc getWindowStyle(hWnd: HWND): DWORD = +proc getWindowStyle(hWnd: HWND): LONG = GetWindowLongW(hWnd, GWL_STYLE) -proc setWindowStyle(hWnd: HWND, style: DWORD) = - SetWindowLongW(hWnd, style, GWL_STYLE) +proc setWindowStyle(hWnd: HWND, style: LONG) = + discard SetWindowLongW(hWnd, style, GWL_STYLE) proc makeContextCurrent(hdc: HDC, hglrc: HGLRC) = if wglMakeCurrent(hdc, hglrc) == 0: @@ -421,7 +421,7 @@ proc pos*(window: PlatformWindow): IVec2 = ivec2(pos.x, pos.y) proc `decorated=`*(window: PlatformWindow, decorated: bool) = - var style: DWORD + var style: LONG if decorated: style = decoratedWindowStyle else: @@ -442,7 +442,7 @@ proc `resizable=`*(window: PlatformWindow, resizable: bool) = if not window.decorated: return - var style = decoratedWindowStyle.DWORD + var style = decoratedWindowStyle.LONG if resizable: style = style or (WS_MAXIMIZEBOX or WS_THICKFRAME) else: diff --git a/windy.nimble b/windy.nimble index d8b69f4..6054449 100644 --- a/windy.nimble +++ b/windy.nimble @@ -11,7 +11,7 @@ requires "vmath >= 1.1.0" task bindings, "Generate bindings": proc compile(libName: string, flags = "") = - exec "nim c -f " & flags & " -d:release -d:noAutoGLerrorCheck --app:lib --gc:arc --tlsEmulation:off --out:" & libName & " --outdir:bindings/generated bindings/bindings.nim" + exec "nim c -f " & flags & " -d:release --app:lib --gc:arc --tlsEmulation:off --out:" & libName & " --outdir:bindings/generated bindings/bindings.nim" when defined(windows): compile "windy.dll"