diff --git a/crates/bevy_window/Cargo.toml b/crates/bevy_window/Cargo.toml index 5ee03dc701..2323e9f0ce 100644 --- a/crates/bevy_window/Cargo.toml +++ b/crates/bevy_window/Cargo.toml @@ -24,3 +24,4 @@ uuid = { version = "0.8", features = ["v4", "serde"] } [target.'cfg(target_arch = "wasm32")'.dependencies] uuid = { version = "0.8", features = ["wasm-bindgen"] } +web-sys = "0.3" diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index 9cfcdf581f..b5cdf9aede 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -40,6 +40,8 @@ pub struct Window { pub vsync: bool, pub resizable: bool, pub mode: WindowMode, + #[cfg(target_arch = "wasm32")] + pub canvas: Option, } /// Defines the way a window is displayed @@ -64,6 +66,8 @@ impl Window { vsync: window_descriptor.vsync, resizable: window_descriptor.resizable, mode: window_descriptor.mode, + #[cfg(target_arch = "wasm32")] + canvas: window_descriptor.canvas.clone(), } } } @@ -77,6 +81,8 @@ pub struct WindowDescriptor { pub vsync: bool, pub resizable: bool, pub mode: WindowMode, + #[cfg(target_arch = "wasm32")] + pub canvas: Option, // this is a manual implementation of the non exhaustive pattern, // especially made to allow ..Default::default() @@ -93,6 +99,8 @@ impl Default for WindowDescriptor { vsync: true, resizable: true, mode: WindowMode::Windowed, + #[cfg(target_arch = "wasm32")] + canvas: None, __non_exhaustive: (), } } diff --git a/crates/bevy_winit/Cargo.toml b/crates/bevy_winit/Cargo.toml index ac286e0300..466acb2276 100644 --- a/crates/bevy_winit/Cargo.toml +++ b/crates/bevy_winit/Cargo.toml @@ -31,4 +31,5 @@ log = { version = "0.4", features = ["release_max_level_info"] } [target.'cfg(target_arch = "wasm32")'.dependencies] winit = { version = "0.22.2", package = "cart-tmp-winit", features = ["web-sys"] } +wasm-bindgen = { version = "0.2" } web-sys = "0.3" diff --git a/crates/bevy_winit/src/winit_windows.rs b/crates/bevy_winit/src/winit_windows.rs index 9ec2c88e15..93a21dfe05 100644 --- a/crates/bevy_winit/src/winit_windows.rs +++ b/crates/bevy_winit/src/winit_windows.rs @@ -38,10 +38,30 @@ impl WinitWindows { .with_resizable(window.resizable), }; - let winit_window = winit_window_builder - .with_title(&window.title) - .build(&event_loop) - .unwrap(); + #[allow(unused_mut)] + let mut winit_window_builder = winit_window_builder.with_title(&window.title); + + #[cfg(target_arch = "wasm32")] + { + use wasm_bindgen::JsCast; + use winit::platform::web::WindowBuilderExtWebSys; + + if let Some(selector) = &window.canvas { + let window = web_sys::window().unwrap(); + let document = window.document().unwrap(); + let canvas = document + .query_selector(&selector) + .expect("Cannot query for canvas element"); + if let Some(canvas) = canvas { + let canvas = canvas.dyn_into::().ok(); + winit_window_builder = winit_window_builder.with_canvas(canvas); + } else { + panic!("Cannot find element: {}", selector); + } + } + } + + let winit_window = winit_window_builder.build(&event_loop).unwrap(); self.window_id_to_winit.insert(window.id, winit_window.id()); self.winit_to_window_id.insert(winit_window.id(), window.id); @@ -50,14 +70,16 @@ impl WinitWindows { { use winit::platform::web::WindowExtWebSys; - let canvas = winit_window.canvas(); + if window.canvas.is_none() { + let canvas = winit_window.canvas(); - let window = web_sys::window().unwrap(); - let document = window.document().unwrap(); - let body = document.body().unwrap(); + let window = web_sys::window().unwrap(); + let document = window.document().unwrap(); + let body = document.body().unwrap(); - body.append_child(&canvas) - .expect("Append canvas to HTML body"); + body.append_child(&canvas) + .expect("Append canvas to HTML body"); + } } self.windows.insert(winit_window.id(), winit_window);