From c37cb7eac80a8097e44084a9325765bb3abaa8ff Mon Sep 17 00:00:00 2001 From: Thierry Berger Date: Tue, 9 Jan 2024 23:15:43 +0100 Subject: [PATCH] Follow up to #11057 ; fix fit_canvas_to_parent Implemented suggestions from reviewers: a simpler fit_canvas_to_parent leads to an explicit CSS setting to the canvas. It has do be set after wgpu creation due to wgpu overriding the canvas width/height: https://github.com/gfx-rs/wgpu/blob/4400a5847080d1164bdca93a90622414963ed9f3/examples/src/utils.rs#L68-L74 --- crates/bevy_window/src/window.rs | 9 ++++++++ crates/bevy_winit/Cargo.toml | 10 +++++++-- crates/bevy_winit/src/system.rs | 21 ++++++++++++++++++- examples/2d/2d_gizmos.rs | 9 +++++++- examples/wasm/index.html | 2 -- examples/window/window_settings.rs | 2 ++ .../window-settings-wasm.patch | 6 ++++-- 7 files changed, 51 insertions(+), 8 deletions(-) diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs index ee05635fac6e1a..87cdfb050e1086 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs @@ -191,6 +191,14 @@ pub struct Window { /// /// This value has no effect on non-web platforms. pub canvas: Option, + /// Whether or not to fit the canvas element's size to its parent element's size. + /// + /// **Warning**: this will not behave as expected for parents that set their size according to the size of their + /// children. This creates a "feedback loop" that will result in the canvas growing on each resize. When using this + /// feature, ensure the parent's size is not affected by its children. + /// + /// This value has no effect on non-web platforms. + pub fit_canvas_to_parent: bool, /// Whether or not to stop events from propagating out of the canvas element /// /// When `true`, this will prevent common browser hotkeys like F5, F12, Ctrl+R, tab, etc. @@ -258,6 +266,7 @@ impl Default for Window { transparent: false, focused: true, window_level: Default::default(), + fit_canvas_to_parent: false, prevent_default_event_handling: true, canvas: None, window_theme: None, diff --git a/crates/bevy_winit/Cargo.toml b/crates/bevy_winit/Cargo.toml index 1619d027776586..0ab7f424862e86 100644 --- a/crates/bevy_winit/Cargo.toml +++ b/crates/bevy_winit/Cargo.toml @@ -44,9 +44,15 @@ winit = { version = "0.29", default-features = false, features = [ ] } [target.'cfg(target_arch = "wasm32")'.dependencies] +web-sys = { version = "0.3", features = [ + # features used by fit_canvas_to_parent + "CssStyleDeclaration", + "Document", + "HtmlCanvasElement", + "Window", + # +] } wasm-bindgen = { version = "0.2" } -web-sys = "0.3" - crossbeam-channel = "0.5" [package.metadata.docs.rs] diff --git a/crates/bevy_winit/src/system.rs b/crates/bevy_winit/src/system.rs index 4ae4b5bd1db54a..bc37a5d091c380 100644 --- a/crates/bevy_winit/src/system.rs +++ b/crates/bevy_winit/src/system.rs @@ -12,13 +12,16 @@ use bevy_utils::{ HashMap, }; use bevy_window::{RawHandleWrapper, Window, WindowClosed, WindowCreated}; -use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; +use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle}; use winit::{ dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}, event_loop::EventLoopWindowTarget, }; +#[cfg(target_arch = "wasm32")] +use {wasm_bindgen::JsCast, web_sys::HtmlCanvasElement}; + use crate::{ accessibility::{AccessKitAdapters, WinitActionHandlers}, converters::{ @@ -81,6 +84,22 @@ pub(crate) fn create_windows<'a>( window: window.clone(), }); + #[cfg(target_arch = "wasm32")] + { + if window.fit_canvas_to_parent { + let canvas: HtmlCanvasElement = web_sys::window() + .unwrap() + .document() + .unwrap() + .query_selector("canvas") + .unwrap() + .unwrap() + .unchecked_into(); + let style = canvas.style(); + style.set_property("width", "100%").unwrap(); + style.set_property("height", "100%").unwrap(); + } + } event_writer.send(WindowCreated { window: entity }); } } diff --git a/examples/2d/2d_gizmos.rs b/examples/2d/2d_gizmos.rs index d3dcd7c960f6a4..38318e9550eb9e 100644 --- a/examples/2d/2d_gizmos.rs +++ b/examples/2d/2d_gizmos.rs @@ -6,7 +6,14 @@ use bevy::prelude::*; fn main() { App::new() - .add_plugins(DefaultPlugins) + .add_plugins(DefaultPlugins.set(WindowPlugin { + primary_window: Some(Window { + fit_canvas_to_parent: true, + title: "game".to_string(), + ..default() + }), + ..default() + })) .add_systems(Startup, setup) .add_systems(Update, (system, update_config)) .run(); diff --git a/examples/wasm/index.html b/examples/wasm/index.html index 0fa46de41877f6..16889626692410 100644 --- a/examples/wasm/index.html +++ b/examples/wasm/index.html @@ -15,8 +15,6 @@ background-size: 20px 20px; } canvas { - width: 100%; - height: 100%; background-color: white; } diff --git a/examples/window/window_settings.rs b/examples/window/window_settings.rs index 77e24cef1f7042..2ed4302ad5ad83 100644 --- a/examples/window/window_settings.rs +++ b/examples/window/window_settings.rs @@ -16,6 +16,8 @@ fn main() { title: "I am a window!".into(), resolution: (500., 300.).into(), present_mode: PresentMode::AutoVsync, + // Tells wasm to resize the window according to the available canvas + fit_canvas_to_parent: true, // Tells wasm not to override default event handling, like F5, Ctrl+R etc. prevent_default_event_handling: false, window_theme: Some(WindowTheme::Dark), diff --git a/tools/example-showcase/window-settings-wasm.patch b/tools/example-showcase/window-settings-wasm.patch index 02e89659018696..5fcb1fba9556c7 100644 --- a/tools/example-showcase/window-settings-wasm.patch +++ b/tools/example-showcase/window-settings-wasm.patch @@ -1,11 +1,13 @@ diff --git a/crates/bevy_window/src/window.rs b/crates/bevy_window/src/window.rs -index 7b5c75d38..8e9404b93 100644 +index 87cdfb050..1d87a0bf5 100644 --- a/crates/bevy_window/src/window.rs +++ b/crates/bevy_window/src/window.rs -@@ -245,8 +245,8 @@ impl Default for Window { +@@ -266,9 +266,9 @@ impl Default for Window { transparent: false, focused: true, window_level: Default::default(), +- fit_canvas_to_parent: false, ++ fit_canvas_to_parent: true, prevent_default_event_handling: true, - canvas: None, + canvas: Some("#bevy".to_string()),