Skip to content

Fix wasm window compilation, initial state, and scaling - #1086

Open
umitsukidev wants to merge 4 commits into
nannou-org:masterfrom
umitsukidev:umitsukidev/fix-wasm-window-resolution
Open

Fix wasm window compilation, initial state, and scaling#1086
umitsukidev wants to merge 4 commits into
nannou-org:masterfrom
umitsukidev:umitsukidev/fix-wasm-window-resolution

Conversation

@umitsukidev

@umitsukidev umitsukidev commented Jul 27, 2026

Copy link
Copy Markdown

Motivation

nannou 0.20.0 does not compile for wasm32-unknown-unknown.

After fixing the compilation failure locally, I noticed that the application
reacted to mouse input at a different position from the visible cursor.
app.window_rect() returned the 1024×768 bootstrap size inside fn model(),
even though the application requested a 1920×1080 window.

Changes

1. Restore wasm compilation

In a downstream application using nannou 0.20.0, the error can be reproduced
with:

cargo check --target wasm32-unknown-unknown
error[E0277]: the trait bound
    `WindowResolution: From<({float}, {float})>`
is not satisfied

resolution: (1024.0, 768.0).into(),
                             ^^^^

help: `WindowResolution` implements `From<(u32, u32)>`

Bevy 0.19 does not convert a floating-point tuple into WindowResolution.
The wasm bootstrap dimensions now use integers:

resolution: (1024_u32, 768_u32).into(),

2. Return the requested window state during creation

On wasm, nannou reuses the existing bootstrap window entity and applies the
requested configuration through deferred commands. App::with_window previously
read the existing component first, so it returned the old 1024×768 state instead
of the pending configuration.

Pending window state now records its creation frame. It takes precedence during
that frame, then later reads return to the live window component so resize,
focus, and cursor state cannot become stale.

3. Preserve logical window size on high-DPI displays

On wasm, a new window builder started with a scale factor of 1.0 instead of
inheriting the scale factor already reported by the bootstrap window. On a
Retina display, .size(1200, 900) therefore produced a 1200×900 physical
canvas that appeared as 600×450 CSS pixels.

The wasm window builder now inherits the bootstrap window's scale factor before
applying logical dimensions. This keeps .size(...) in logical points while
the canvas uses the appropriate physical resolution for the display.

Testing

The following targeted checks pass:

cargo check -p nannou
cargo check -p nannou --features egui --target wasm32-unknown-unknown

The egui feature is enabled for the targeted wasm check because bevy_egui
enables getrandom's wasm_js backend. Without it, compilation stops in
getrandom before reaching nannou's wasm window code. This feature is used only
to ensure that the check reaches the code changed by this PR; changing the
workspace's getrandom configuration is outside the scope of this PR.

The full example runner was also executed on macOS:

cargo run --bin run_all_examples

All examples completed successfully except laser_frame_stream_gui, which
panicked during startup with no camera found for window. The affected example
and egui camera lookup are unchanged by this PR.

I also tested a 1920×1080 downstream nannou application with Trunk. Window
coordinates, nannou mouse input, and egui input remained aligned.

I also tested .size(1200, 900) in a downstream application with Trunk on a
Retina display. The canvas used the requested logical size, and nannou mouse
input and egui input remained aligned.

I also tried checking the entire workspace with
--target wasm32-unknown-unknown, but it currently fails while compiling
nannou_webcam and nannou_video due to errors unrelated to this PR.
I therefore used the targeted -p nannou check above to test these changes.

Bevy 0.19 implements WindowResolution conversion for (u32, u32),
so floating-point literals prevent nannou from compiling for wasm32.
On wasm, creating the primary window reuses the bootstrap window entity, so world-first reads returned its stale resolution before deferred commands were applied. Track the creation frame and prefer pending state only for that frame, then fall back to the live window.
@umitsukidev umitsukidev changed the title Fix wasm window compilation and initial state reads Fix wasm window compilation, initial state, and scaling Jul 27, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant