Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 41 additions & 12 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,51 +12,80 @@ jobs:
runs-on: ${{ matrix.os }}

steps:
- uses: actions/checkout@v3
- uses: treeform/setup-nim-action@v2
- uses: mymindstorm/setup-emsdk@v14
- uses: actions/checkout@v5
- uses: treeform/setup-nim-action@v6

- run: nimby sync -g nimby.lock
- run: nimby install -g boxy

- run: nimble install -y
- run: nimble install boxy
# Run tests.
- run: nim c tests/test.nim

# Build native examples.
- run: nim c examples/basic.nim
- run: nim c examples/basic_boxy.nim
- run: nim c examples/basic_textured_quad.nim
- run: nim c examples/basic_triangle.nim
- run: nim c examples/callbacks.nim
- run: nim c examples/clipboard.nim
- run: nim c examples/content_scale.nim
- run: nim c examples/cursor_position_test.nim
- run: nim c examples/custom_cursor.nim
- run: nim c examples/dragdrop.nim
- run: nim c examples/fixedsize.nim
- run: nim c examples/fullscreen.nim
- run: nim c examples/content_scale.nim
# - run: nim c examples/httprequest.nim
- run: nim c examples/icon.nim
- run: nim c examples/opengl_version.nim
- run: nim c examples/openurl.nim
- run: nim c examples/property_changes.nim
- run: nim c examples/screens.nim
- run: nim c examples/scrollwheel.nim
- run: nim c examples/system_cursors.nim
- run: nim c examples/tray.nim
- run: nim c examples/websocket.nim
- run: nim c examples/openurl.nim

# Install Emscripten only after native checks pass.
- uses: mymindstorm/setup-emsdk@v14
if: matrix.os == 'ubuntu-latest'

# Build Emscripten examples on Ubuntu only.
- run: nim c -d:emscripten examples/basic.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/basic_boxy.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/basic_textured_quad.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/basic_triangle.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/callbacks.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/clipboard.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/content_scale.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/cursor_position_test.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/custom_cursor.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/dragdrop.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/fixedsize.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/fullscreen.nim
- run: nim c -d:emscripten examples/content_scale.nim
- run: nim c -d:emscripten examples/httprequest.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/icon.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/opengl_version.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/openurl.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/property_changes.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/screens.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/scrollwheel.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/system_cursors.nim
if: matrix.os == 'ubuntu-latest'
- run: nim c -d:emscripten examples/tray.nim
# - run: nim c -d:emscripten examples/websocket.nim
- run: nim c -d:emscripten examples/openurl.nim
if: matrix.os == 'ubuntu-latest'
30 changes: 23 additions & 7 deletions examples/property_changes.nim
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,15 @@ window.onFrame = proc() =
# Your OpenGL display code here
window.swapBuffers()

template waitFor(condition: untyped, maxTries: int) =
## Waits for an asynchronous window state transition.
when defined(macosx):
var tries = 0
while not (condition) and tries < maxTries:
pollEvents()
sleep(16)
inc tries

while not window.closeRequested:
sleep(100)

Expand Down Expand Up @@ -61,17 +70,24 @@ while not window.closeRequested:
doAssert not window.minimized

window.minimized = true
waitFor(window.minimized, 30)
doAssert window.minimized

when not defined(macosx):
window.fullscreen = false
doAssert not window.fullscreen
window.minimized = false
waitFor(not window.minimized, 30)
doAssert not window.minimized

window.fullscreen = false
waitFor(not window.fullscreen, 60)
doAssert not window.fullscreen

window.fullscreen = true
doAssert window.fullscreen
window.fullscreen = true
waitFor(window.fullscreen, 600)
doAssert window.fullscreen

window.fullscreen = false
doAssert not window.fullscreen
window.fullscreen = false
waitFor(not window.fullscreen, 600)
doAssert not window.fullscreen

echo "SUCCESS!"
quit()
11 changes: 11 additions & 0 deletions nimby.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
opengl 1.2.9 https://github.com/nim-lang/opengl 8e2e098f82dc5eefd874488c37b5830233cd18f4
pixie 5.1.0 https://github.com/treeform/pixie 5eda4949a3c8bea318cfac8e42060a8f90f3f35d
vmath 2.0.1 https://github.com/treeform/vmath b1cb7ec85f6e7690cf1261227cd2d552275e3e53
chroma 1.0.0 https://github.com/treeform/chroma 2381748f92e5ea16cb2403ff7e20c6dd5443a59d
zippy 0.10.16 https://github.com/guzba/zippy a99f6a7d8a8e3e0213b3cad0daf0ea974bf58e3f
flatty 0.3.4 https://github.com/treeform/flatty 05d878b397933331966a7f80dd0c55664559201f
nimsimd 1.3.2 https://github.com/guzba/nimsimd 3f6b2668ffb0867d0bf786a658b817763e611350
bumpy 1.1.3 https://github.com/treeform/bumpy dc9a3d6d15680ec7f603959d65ba8ee4f1ddbc72
crunchy 0.1.11 https://github.com/guzba/crunchy 98eb6526982bb8aae8eec6e8781f4539fa19e049
urlly 1.1.1 https://github.com/treeform/urlly 99784779f05649df25fd9c33003d8ef6de027345
ws 0.5.0 https://github.com/treeform/ws cbb8f763b436669392d10baec2a45778395395cc
2 changes: 1 addition & 1 deletion src/windy/platforms/macos/macdefs.nim
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ objc:
proc makeFirstResponder*(self: NSWindow, x: NSView): bool
proc styleMask*(self: NSWindow): NSWindowStyleMask
proc setStyleMask*(self: NSWindow, x: NSWindowStyleMask)
proc toggleFullscreen*(self: NSWindow, x: ID)
proc toggleFullScreen*(self: NSWindow, x: ID)
proc invalidateCursorRectsForView*(self: NSWindow, x: NSView)
proc mouseLocationOutsideOfEventStream*(self: NSWindow): NSPoint
proc level*(self: NSWindow): NSWindowLevel
Expand Down
56 changes: 53 additions & 3 deletions src/windy/platforms/macos/platform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type
inner: NSWindow
trackingArea: NSTrackingArea
markedText: NSString
# AppKit applies this state asynchronously via delegate callbacks.
fullscreenState: bool
minimizedState: bool

const
decoratedResizableWindowMask =
Expand Down Expand Up @@ -79,7 +82,7 @@ proc style*(window: Window): WindowStyle =
Undecorated

proc fullscreen*(window: Window): bool =
(window.inner.styleMask and NSWindowStyleMaskFullScreen) != 0
window.fullscreenState

proc floating*(window: Window): bool =
window.inner.level == NSFloatingWindowLevel
Expand Down Expand Up @@ -111,7 +114,7 @@ proc pos*(window: Window): IVec2 =
).ivec2

proc minimized*(window: Window): bool =
window.inner.isMiniaturized
window.minimizedState

proc maximized*(window: Window): bool =
window.inner.isZoomed
Expand Down Expand Up @@ -174,7 +177,7 @@ proc `fullscreen=`*(window: Window, fullscreen: bool) =
if window.fullscreen == fullscreen:
return
autoreleasepool:
window.inner.toggleFullscreen(0.ID)
window.inner.toggleFullScreen(0.ID)

proc `floating=`*(window: Window, floating: bool) =
if window.floating == floating:
Expand Down Expand Up @@ -326,6 +329,45 @@ proc windowDidMove(
if window != nil and window.onMove != nil:
window.onMove()

proc windowDidMiniaturize(
self: ID,
cmd: SEL,
notification: NSNotification
): ID {.cdecl.} =
let window = windows.forNSWindow(self.NSWindow)
if window == nil:
return
window.minimizedState = true

proc windowDidDeminiaturize(
self: ID,
cmd: SEL,
notification: NSNotification
): ID {.cdecl.} =
let window = windows.forNSWindow(self.NSWindow)
if window == nil:
return
window.minimizedState = false

proc windowDidEnterFullScreen(
self: ID,
cmd: SEL,
notification: NSNotification
): ID {.cdecl.} =
let window = windows.forNSWindow(self.NSWindow)
if window == nil:
return
window.fullscreenState = true

proc windowDidExitFullScreen(
self: ID,
cmd: SEL,
notification: NSNotification
): ID {.cdecl.} =
let window = windows.forNSWindow(self.NSWindow)
if window == nil:
return
window.fullscreenState = false

proc canBecomeKeyWindow(
self: ID,
Expand Down Expand Up @@ -716,6 +758,10 @@ proc init() {.raises: [].} =
addClass "WindyWindow", "NSWindow", WindyWindow:
addMethod "windowDidResize:", windowDidResize
addMethod "windowDidMove:", windowDidMove
addMethod "windowDidMiniaturize:", windowDidMiniaturize
addMethod "windowDidDeminiaturize:", windowDidDeminiaturize
addMethod "windowDidEnterFullScreen:", windowDidEnterFullScreen
addMethod "windowDidExitFullScreen:", windowDidExitFullScreen
addMethod "canBecomeKeyWindow:", canBecomeKeyWindow
addMethod "windowDidBecomeKey:", windowDidBecomeKey
addMethod "windowDidResignKey:", windowDidResignKey
Expand Down Expand Up @@ -956,6 +1002,10 @@ proc newWindow*(
result.style = style
result.visible = visible

result.minimizedState = result.inner.isMiniaturized
result.fullscreenState =
(result.inner.styleMask and NSWindowStyleMaskFullScreen) != 0

pollEvents() # This can cause lots of issues, potential workaround needed

proc title*(window: Window): string =
Expand Down
75 changes: 75 additions & 0 deletions tests/run_all.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
## Compiles all examples first, then runs them sequentially.

import std/[osproc, os, strformat]

const Examples = [
"basic",
"basic_boxy",
"basic_textured_quad",
"basic_triangle",
"callbacks",
"clipboard",
"content_scale",
"cursor_position_test",
"custom_cursor",
"dragdrop",
"fixedsize",
"fullscreen",
"icon",
"opengl_version",
"openurl",
"property_changes",
"screens",
"scrollwheel",
"system_cursors",
"tray",
"websocket",
]

proc main() =
## Compile all examples, then run all examples in sequence.
let
startDir = getCurrentDir()
rootDir = currentSourcePath().parentDir.parentDir
defer:
setCurrentDir(startDir)

echo "=== Windy Examples Runner ==="
echo "Compiling all examples first."
echo "Running all examples after successful compilation."
echo "Close each window to proceed to the next example.\n"

for i, name in Examples:
let nimFile = "examples" / (name & ".nim")
echo fmt"[{i + 1}/{Examples.len}] Compiling: {name}"

setCurrentDir(rootDir)
let exitCode = execCmd(fmt"nim c {nimFile}")
if exitCode != 0:
echo fmt" ERROR: {name} failed to compile with exit code {exitCode}"
quit(exitCode)
echo ""

echo "=== Compilation complete ===\n"

for i, name in Examples:
when defined(macosx):
if name == "opengl_version":
echo fmt"[{i + 1}/{Examples.len}] Skipping on macOS: {name}"
echo ""
continue

let binaryPath = "examples" / name
echo fmt"[{i + 1}/{Examples.len}] Running: {name}"

setCurrentDir(rootDir)
let exitCode = execCmd(binaryPath)
if exitCode != 0:
echo fmt" ERROR: {name} failed with exit code {exitCode}"
quit(exitCode)
echo ""

echo "=== All examples completed ==="

when isMainModule:
main()
Loading