Skip to content
Open
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
36 changes: 35 additions & 1 deletion src/windy/platforms/emscripten/platform.nim
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,16 @@ var
httpRequests: Table[HttpRequestHandle, EmsHttpRequestState]
webSockets: Table[WebSocketHandle, EmsWebSocketState]

# Browser events can arrive while Asyncify has suspended onFrame.
frameDispatchActive: bool
pendingResize: bool
pendingFocusChange: bool

proc handleButtonPress(window: Window, button: Button)
proc handleButtonRelease(window: Window, button: Button)
proc handleRune(window: Window, rune: Rune)
proc setupEventHandlers(window: Window) # Forward declaration
proc drainDeferredWindowEvents() # Forward declaration

proc close*(handle: WebSocketHandle) {.raises: [].}

Expand Down Expand Up @@ -126,8 +132,13 @@ proc pollEvents*() =
## Note: Will block to match frames per second.
if mainWindow != nil:
if mainWindow.onFrame != nil:
mainWindow.onFrame()
frameDispatchActive = true
try:
mainWindow.onFrame()
finally:
frameDispatchActive = false
mainWindow.state.perFrame = PerFrame()
drainDeferredWindowEvents()
pollHttp()
emscripten_sleep(0)

Expand Down Expand Up @@ -639,24 +650,47 @@ proc onKeyPress(eventType: cint, keyEvent: ptr EmscriptenKeyboardEvent, userData

proc onFocus(eventType: cint, focusEvent: ptr EmscriptenFocusEvent, userData: pointer): EM_BOOL {.cdecl.} =
let window = cast[Window](userData)
if frameDispatchActive:
pendingFocusChange = true
return 1
if window.onFocusChange != nil:
window.onFocusChange()
return 1

proc onBlur(eventType: cint, focusEvent: ptr EmscriptenFocusEvent, userData: pointer): EM_BOOL {.cdecl.} =
let window = cast[Window](userData)
if frameDispatchActive:
pendingFocusChange = true
return 1
if window.onFocusChange != nil:
window.onFocusChange()
return 1

proc onResize(eventType: cint, uiEvent: ptr EmscriptenUiEvent, userData: pointer): EM_BOOL {.cdecl.} =
let window = cast[Window](userData)
if frameDispatchActive:
pendingResize = true
return 1
window.updateCanvasSize()

if window.onResize != nil:
window.onResize()
return 1

proc drainDeferredWindowEvents() =
## Runs window callbacks deferred while onFrame was suspended.
if mainWindow == nil:
return
if pendingResize:
pendingResize = false
mainWindow.updateCanvasSize()
if mainWindow.onResize != nil:
mainWindow.onResize()
if pendingFocusChange:
pendingFocusChange = false
if mainWindow.onFocusChange != nil:
mainWindow.onFocusChange()

proc setupEventHandlers(window: Window) =
# Mouse events
discard emscripten_set_mousedown_callback_on_thread(window.canvas, cast[pointer](window), 1, onMouseDown, EM_CALLBACK_THREAD_CONTEXT)
Expand Down