Skip to content

Commit dd6762f

Browse files
authored
Add runners, nimby lock, and mac state fixes (#169)
* fix full screen * add runners * Fix full screen tracking on mac. * ci install boxy only in workflow Made-with: Cursor
1 parent c167063 commit dd6762f

7 files changed

Lines changed: 380 additions & 23 deletions

File tree

.github/workflows/build.yml

Lines changed: 41 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,51 +12,80 @@ jobs:
1212
runs-on: ${{ matrix.os }}
1313

1414
steps:
15-
- uses: actions/checkout@v3
16-
- uses: treeform/setup-nim-action@v2
17-
- uses: mymindstorm/setup-emsdk@v14
15+
- uses: actions/checkout@v5
16+
- uses: treeform/setup-nim-action@v6
17+
18+
- run: nimby sync -g nimby.lock
19+
- run: nimby install -g boxy
1820

19-
- run: nimble install -y
20-
- run: nimble install boxy
21+
# Run tests.
22+
- run: nim c tests/test.nim
2123

24+
# Build native examples.
2225
- run: nim c examples/basic.nim
2326
- run: nim c examples/basic_boxy.nim
2427
- run: nim c examples/basic_textured_quad.nim
2528
- run: nim c examples/basic_triangle.nim
2629
- run: nim c examples/callbacks.nim
2730
- run: nim c examples/clipboard.nim
31+
- run: nim c examples/content_scale.nim
2832
- run: nim c examples/cursor_position_test.nim
2933
- run: nim c examples/custom_cursor.nim
34+
- run: nim c examples/dragdrop.nim
3035
- run: nim c examples/fixedsize.nim
3136
- run: nim c examples/fullscreen.nim
32-
- run: nim c examples/content_scale.nim
33-
# - run: nim c examples/httprequest.nim
3437
- run: nim c examples/icon.nim
3538
- run: nim c examples/opengl_version.nim
39+
- run: nim c examples/openurl.nim
3640
- run: nim c examples/property_changes.nim
3741
- run: nim c examples/screens.nim
42+
- run: nim c examples/scrollwheel.nim
3843
- run: nim c examples/system_cursors.nim
3944
- run: nim c examples/tray.nim
4045
- run: nim c examples/websocket.nim
41-
- run: nim c examples/openurl.nim
4246

47+
# Install Emscripten only after native checks pass.
48+
- uses: mymindstorm/setup-emsdk@v14
49+
if: matrix.os == 'ubuntu-latest'
50+
51+
# Build Emscripten examples on Ubuntu only.
4352
- run: nim c -d:emscripten examples/basic.nim
53+
if: matrix.os == 'ubuntu-latest'
4454
- run: nim c -d:emscripten examples/basic_boxy.nim
55+
if: matrix.os == 'ubuntu-latest'
4556
- run: nim c -d:emscripten examples/basic_textured_quad.nim
57+
if: matrix.os == 'ubuntu-latest'
4658
- run: nim c -d:emscripten examples/basic_triangle.nim
59+
if: matrix.os == 'ubuntu-latest'
4760
- run: nim c -d:emscripten examples/callbacks.nim
61+
if: matrix.os == 'ubuntu-latest'
4862
- run: nim c -d:emscripten examples/clipboard.nim
63+
if: matrix.os == 'ubuntu-latest'
64+
- run: nim c -d:emscripten examples/content_scale.nim
65+
if: matrix.os == 'ubuntu-latest'
4966
- run: nim c -d:emscripten examples/cursor_position_test.nim
67+
if: matrix.os == 'ubuntu-latest'
5068
- run: nim c -d:emscripten examples/custom_cursor.nim
69+
if: matrix.os == 'ubuntu-latest'
70+
- run: nim c -d:emscripten examples/dragdrop.nim
71+
if: matrix.os == 'ubuntu-latest'
5172
- run: nim c -d:emscripten examples/fixedsize.nim
73+
if: matrix.os == 'ubuntu-latest'
5274
- run: nim c -d:emscripten examples/fullscreen.nim
53-
- run: nim c -d:emscripten examples/content_scale.nim
54-
- run: nim c -d:emscripten examples/httprequest.nim
75+
if: matrix.os == 'ubuntu-latest'
5576
- run: nim c -d:emscripten examples/icon.nim
77+
if: matrix.os == 'ubuntu-latest'
5678
- run: nim c -d:emscripten examples/opengl_version.nim
79+
if: matrix.os == 'ubuntu-latest'
80+
- run: nim c -d:emscripten examples/openurl.nim
81+
if: matrix.os == 'ubuntu-latest'
5782
- run: nim c -d:emscripten examples/property_changes.nim
83+
if: matrix.os == 'ubuntu-latest'
5884
- run: nim c -d:emscripten examples/screens.nim
85+
if: matrix.os == 'ubuntu-latest'
86+
- run: nim c -d:emscripten examples/scrollwheel.nim
87+
if: matrix.os == 'ubuntu-latest'
5988
- run: nim c -d:emscripten examples/system_cursors.nim
89+
if: matrix.os == 'ubuntu-latest'
6090
- run: nim c -d:emscripten examples/tray.nim
61-
# - run: nim c -d:emscripten examples/websocket.nim
62-
- run: nim c -d:emscripten examples/openurl.nim
91+
if: matrix.os == 'ubuntu-latest'

examples/property_changes.nim

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ window.onFrame = proc() =
1010
# Your OpenGL display code here
1111
window.swapBuffers()
1212

13+
template waitFor(condition: untyped, maxTries: int) =
14+
## Waits for an asynchronous window state transition.
15+
when defined(macosx):
16+
var tries = 0
17+
while not (condition) and tries < maxTries:
18+
pollEvents()
19+
sleep(16)
20+
inc tries
21+
1322
while not window.closeRequested:
1423
sleep(100)
1524

@@ -61,17 +70,24 @@ while not window.closeRequested:
6170
doAssert not window.minimized
6271

6372
window.minimized = true
73+
waitFor(window.minimized, 30)
6474
doAssert window.minimized
6575

66-
when not defined(macosx):
67-
window.fullscreen = false
68-
doAssert not window.fullscreen
76+
window.minimized = false
77+
waitFor(not window.minimized, 30)
78+
doAssert not window.minimized
79+
80+
window.fullscreen = false
81+
waitFor(not window.fullscreen, 60)
82+
doAssert not window.fullscreen
6983

70-
window.fullscreen = true
71-
doAssert window.fullscreen
84+
window.fullscreen = true
85+
waitFor(window.fullscreen, 600)
86+
doAssert window.fullscreen
7287

73-
window.fullscreen = false
74-
doAssert not window.fullscreen
88+
window.fullscreen = false
89+
waitFor(not window.fullscreen, 600)
90+
doAssert not window.fullscreen
7591

7692
echo "SUCCESS!"
7793
quit()

nimby.lock

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
opengl 1.2.9 https://github.com/nim-lang/opengl 8e2e098f82dc5eefd874488c37b5830233cd18f4
2+
pixie 5.1.0 https://github.com/treeform/pixie 5eda4949a3c8bea318cfac8e42060a8f90f3f35d
3+
vmath 2.0.1 https://github.com/treeform/vmath b1cb7ec85f6e7690cf1261227cd2d552275e3e53
4+
chroma 1.0.0 https://github.com/treeform/chroma 2381748f92e5ea16cb2403ff7e20c6dd5443a59d
5+
zippy 0.10.16 https://github.com/guzba/zippy a99f6a7d8a8e3e0213b3cad0daf0ea974bf58e3f
6+
flatty 0.3.4 https://github.com/treeform/flatty 05d878b397933331966a7f80dd0c55664559201f
7+
nimsimd 1.3.2 https://github.com/guzba/nimsimd 3f6b2668ffb0867d0bf786a658b817763e611350
8+
bumpy 1.1.3 https://github.com/treeform/bumpy dc9a3d6d15680ec7f603959d65ba8ee4f1ddbc72
9+
crunchy 0.1.11 https://github.com/guzba/crunchy 98eb6526982bb8aae8eec6e8781f4539fa19e049
10+
urlly 1.1.1 https://github.com/treeform/urlly 99784779f05649df25fd9c33003d8ef6de027345
11+
ws 0.5.0 https://github.com/treeform/ws cbb8f763b436669392d10baec2a45778395395cc

src/windy/platforms/macos/macdefs.nim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ objc:
228228
proc makeFirstResponder*(self: NSWindow, x: NSView): bool
229229
proc styleMask*(self: NSWindow): NSWindowStyleMask
230230
proc setStyleMask*(self: NSWindow, x: NSWindowStyleMask)
231-
proc toggleFullscreen*(self: NSWindow, x: ID)
231+
proc toggleFullScreen*(self: NSWindow, x: ID)
232232
proc invalidateCursorRectsForView*(self: NSWindow, x: NSView)
233233
proc mouseLocationOutsideOfEventStream*(self: NSWindow): NSPoint
234234
proc level*(self: NSWindow): NSWindowLevel

src/windy/platforms/macos/platform.nim

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ type
2828
inner: NSWindow
2929
trackingArea: NSTrackingArea
3030
markedText: NSString
31+
# AppKit applies this state asynchronously via delegate callbacks.
32+
fullscreenState: bool
33+
minimizedState: bool
3134

3235
const
3336
decoratedResizableWindowMask =
@@ -79,7 +82,7 @@ proc style*(window: Window): WindowStyle =
7982
Undecorated
8083

8184
proc fullscreen*(window: Window): bool =
82-
(window.inner.styleMask and NSWindowStyleMaskFullScreen) != 0
85+
window.fullscreenState
8386

8487
proc floating*(window: Window): bool =
8588
window.inner.level == NSFloatingWindowLevel
@@ -111,7 +114,7 @@ proc pos*(window: Window): IVec2 =
111114
).ivec2
112115

113116
proc minimized*(window: Window): bool =
114-
window.inner.isMiniaturized
117+
window.minimizedState
115118

116119
proc maximized*(window: Window): bool =
117120
window.inner.isZoomed
@@ -174,7 +177,7 @@ proc `fullscreen=`*(window: Window, fullscreen: bool) =
174177
if window.fullscreen == fullscreen:
175178
return
176179
autoreleasepool:
177-
window.inner.toggleFullscreen(0.ID)
180+
window.inner.toggleFullScreen(0.ID)
178181

179182
proc `floating=`*(window: Window, floating: bool) =
180183
if window.floating == floating:
@@ -326,6 +329,45 @@ proc windowDidMove(
326329
if window != nil and window.onMove != nil:
327330
window.onMove()
328331

332+
proc windowDidMiniaturize(
333+
self: ID,
334+
cmd: SEL,
335+
notification: NSNotification
336+
): ID {.cdecl.} =
337+
let window = windows.forNSWindow(self.NSWindow)
338+
if window == nil:
339+
return
340+
window.minimizedState = true
341+
342+
proc windowDidDeminiaturize(
343+
self: ID,
344+
cmd: SEL,
345+
notification: NSNotification
346+
): ID {.cdecl.} =
347+
let window = windows.forNSWindow(self.NSWindow)
348+
if window == nil:
349+
return
350+
window.minimizedState = false
351+
352+
proc windowDidEnterFullScreen(
353+
self: ID,
354+
cmd: SEL,
355+
notification: NSNotification
356+
): ID {.cdecl.} =
357+
let window = windows.forNSWindow(self.NSWindow)
358+
if window == nil:
359+
return
360+
window.fullscreenState = true
361+
362+
proc windowDidExitFullScreen(
363+
self: ID,
364+
cmd: SEL,
365+
notification: NSNotification
366+
): ID {.cdecl.} =
367+
let window = windows.forNSWindow(self.NSWindow)
368+
if window == nil:
369+
return
370+
window.fullscreenState = false
329371

330372
proc canBecomeKeyWindow(
331373
self: ID,
@@ -716,6 +758,10 @@ proc init() {.raises: [].} =
716758
addClass "WindyWindow", "NSWindow", WindyWindow:
717759
addMethod "windowDidResize:", windowDidResize
718760
addMethod "windowDidMove:", windowDidMove
761+
addMethod "windowDidMiniaturize:", windowDidMiniaturize
762+
addMethod "windowDidDeminiaturize:", windowDidDeminiaturize
763+
addMethod "windowDidEnterFullScreen:", windowDidEnterFullScreen
764+
addMethod "windowDidExitFullScreen:", windowDidExitFullScreen
719765
addMethod "canBecomeKeyWindow:", canBecomeKeyWindow
720766
addMethod "windowDidBecomeKey:", windowDidBecomeKey
721767
addMethod "windowDidResignKey:", windowDidResignKey
@@ -956,6 +1002,10 @@ proc newWindow*(
9561002
result.style = style
9571003
result.visible = visible
9581004

1005+
result.minimizedState = result.inner.isMiniaturized
1006+
result.fullscreenState =
1007+
(result.inner.styleMask and NSWindowStyleMaskFullScreen) != 0
1008+
9591009
pollEvents() # This can cause lots of issues, potential workaround needed
9601010

9611011
proc title*(window: Window): string =

tests/run_all.nim

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
## Compiles all examples first, then runs them sequentially.
2+
3+
import std/[osproc, os, strformat]
4+
5+
const Examples = [
6+
"basic",
7+
"basic_boxy",
8+
"basic_textured_quad",
9+
"basic_triangle",
10+
"callbacks",
11+
"clipboard",
12+
"content_scale",
13+
"cursor_position_test",
14+
"custom_cursor",
15+
"dragdrop",
16+
"fixedsize",
17+
"fullscreen",
18+
"icon",
19+
"opengl_version",
20+
"openurl",
21+
"property_changes",
22+
"screens",
23+
"scrollwheel",
24+
"system_cursors",
25+
"tray",
26+
"websocket",
27+
]
28+
29+
proc main() =
30+
## Compile all examples, then run all examples in sequence.
31+
let
32+
startDir = getCurrentDir()
33+
rootDir = currentSourcePath().parentDir.parentDir
34+
defer:
35+
setCurrentDir(startDir)
36+
37+
echo "=== Windy Examples Runner ==="
38+
echo "Compiling all examples first."
39+
echo "Running all examples after successful compilation."
40+
echo "Close each window to proceed to the next example.\n"
41+
42+
for i, name in Examples:
43+
let nimFile = "examples" / (name & ".nim")
44+
echo fmt"[{i + 1}/{Examples.len}] Compiling: {name}"
45+
46+
setCurrentDir(rootDir)
47+
let exitCode = execCmd(fmt"nim c {nimFile}")
48+
if exitCode != 0:
49+
echo fmt" ERROR: {name} failed to compile with exit code {exitCode}"
50+
quit(exitCode)
51+
echo ""
52+
53+
echo "=== Compilation complete ===\n"
54+
55+
for i, name in Examples:
56+
when defined(macosx):
57+
if name == "opengl_version":
58+
echo fmt"[{i + 1}/{Examples.len}] Skipping on macOS: {name}"
59+
echo ""
60+
continue
61+
62+
let binaryPath = "examples" / name
63+
echo fmt"[{i + 1}/{Examples.len}] Running: {name}"
64+
65+
setCurrentDir(rootDir)
66+
let exitCode = execCmd(binaryPath)
67+
if exitCode != 0:
68+
echo fmt" ERROR: {name} failed with exit code {exitCode}"
69+
quit(exitCode)
70+
echo ""
71+
72+
echo "=== All examples completed ==="
73+
74+
when isMainModule:
75+
main()

0 commit comments

Comments
 (0)