rust-windowing / rust-windowing/winit
[wasm] `common.{current,old}_size` is not updated until after `resize` event.
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 6.2k
- Forks
- 1.3k
- Avg merge
- 2d 19h
- Merged PRs (30d)
- 9
Description
Description
on wasm, window.surface_size() returns 0x0 immediately after create_window(), even when the canvas has explicit dimensions and with_surface_size() is used. the size only updates after the first resize event.
in winit-web/src/web_sys/canvas.rs, Canvas::create() calls set_canvas_size() to update the dom but never updates the current_size cache that surface_size() returns.
i think the fix would be to update the cache after setting the canvas size:
if let Some(size) = attr.surface_size {
let logical_size = size.to_logical(super::scale_factor(&common.window));
super::set_canvas_size(&common.document, &common.raw, &common.style, logical_size);
// can we update common.current_size and common.old_size here?
}
minimally reproducible example
// src/main.rs
use wasm_bindgen::prelude::*;
use winit::{
application::ApplicationHandler,
dpi::{PhysicalSize, Size},
event::WindowEvent,
event_loop::{ActiveEventLoop, EventLoop},
platform::web::{WindowAttributesWeb},
window::{Window, WindowId}
};
#[wasm_bindgen]
extern "C" {
#[wasm_bindgen(js_namespace = console)]
fn log(s: &str);
}
#[derive(Default)]
struct App(Option<Box<dyn Window>>);
impl ApplicationHandler for App {
fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) {
let mut attribs = winit::window::WindowAttributes::default()
.with_surface_size(Size::Physical(PhysicalSize::new(1280, 720)));
let window = web_sys::window().unwrap();
let document = window.document().unwrap();
let canvas = document
.get_element_by_id("canvas")
.expect("no #canvas found")
.dyn_into::<web_sys::HtmlCanvasElement>()
.unwrap();
log(&format!("canvas size according to html/web_sys: {}x{}", canvas.width(), canvas.height()));
attribs = attribs.with_platform_attributes(Box::new(
WindowAttributesWeb::default().with_canvas(Some(canvas.into())),
));
let window = event_loop.create_window(attribs).unwrap();
let surface_size = window.surface_size();
log(&format!("window.surface_size() returns: {}x{}", surface_size.width, surface_size.height));
self.0 = Some(window);
}
fn window_event(&mut self, _: &dyn ActiveEventLoop, _: WindowId, event: WindowEvent) {
if let WindowEvent::SurfaceResized(new_size) = event {
let window = self.0.as_ref().unwrap();
let size = window.surface_size();
log(&format!("SurfaceResized -> surface_size() now returns: {}x{}", size.width, size.height));
}
}
}
fn main() {
use winit::platform::web::EventLoopExtWeb;
let event_loop = EventLoop::new().unwrap();
let app = App::default();
event_loop.spawn_app(app);
}
# Cargo.toml
[package]
name = "winit-surface-size-bug"
version = "0.1.0"
edition = "2021"
[dependencies]
winit = { git = "https://github.com/rust-windowing/winit" }
[target.'cfg(target_arch = "wasm32")'.dependencies]
web-sys = { version = "0.3", features = ["Window", "Document", "HtmlCanvasElement", "console"] }
wasm-bindgen = "0.2"
<!doctype html>
<html lang="en">
<body>
<canvas id="canvas" width="800" height="600"></canvas>
<script type="module">
import init from './winit-surface-size-bug.js';
init()
</script>
</body>
</html>
#!/bin/bash
set -e
cargo build --target wasm32-unknown-unknown --release
mkdir -p pkg
wasm-bindgen --out-dir pkg --target web target/wasm32-unknown-unknown/release/winit-surface-size-bug.wasm
cp index.html pkg/
cd pkg && python3 -m http.server 8080
Tested browsers
Chrome, Safari (newer than listed)
Tested devices
iPhone 12 Pro Max Safari, iPad Pro Safari
Winit version
latest development version at the time of this pull request a9c189a4
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in winit-web/src/web_sys/canvas.rs at Canvas::create(), where set_canvas_size() is called, and inspect the current surface_size() cache behavior. Reproduce the wasm example and verify that surface_size() reports the configured dimensions immediately after create_window(), before any resize event.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, wasm
- Domain
- web-dev
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Stale
- Clarity
- Clearly specified
- Newbie friendliness
- 54/100