From 519790c94e94f2f90be1c27cb0dc7062d314870a Mon Sep 17 00:00:00 2001 From: dAxpeDDa Date: Sun, 4 Jun 2023 14:29:59 +0200 Subject: [PATCH] Use correct canvas size for scale factor change --- CHANGELOG.md | 2 + examples/web.rs | 5 ++- src/platform_impl/web/event_loop/runner.rs | 10 ++--- .../web/event_loop/window_target.rs | 21 ++++------ src/platform_impl/web/web_sys/canvas.rs | 42 +++++++++++++------ src/platform_impl/web/web_sys/mod.rs | 15 +++++-- src/platform_impl/web/window.rs | 15 ++----- 7 files changed, 63 insertions(+), 47 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 10961a728fe..6cf5de517c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,8 @@ And please only add new entries to the top of this list, right below the `# Unre - **Breaking:** On Web, `instant` is now replaced by `web_time`. - On Windows, port to `windows-sys` version 0.48.0. - On Web, fix pen treated as mouse input. +- On Web, use the correct canvas size when calculating the new size during scale factor change, + instead of using the output bitmap size. # 0.28.6 diff --git a/examples/web.rs b/examples/web.rs index 5be8af29de4..65181cd5b3e 100644 --- a/examples/web.rs +++ b/examples/web.rs @@ -59,7 +59,10 @@ mod wasm { let body = document.body().unwrap(); // Set a background color for the canvas to make it easier to tell where the canvas is for debugging purposes. - canvas.style().set_css_text("background-color: crimson;"); + canvas + .style() + .set_property("background-color", "crimson") + .unwrap(); body.append_child(&canvas).unwrap(); let log_header = document.create_element("h2").unwrap(); diff --git a/src/platform_impl/web/event_loop/runner.rs b/src/platform_impl/web/event_loop/runner.rs index c28a28e5766..61142a49c00 100644 --- a/src/platform_impl/web/event_loop/runner.rs +++ b/src/platform_impl/web/event_loop/runner.rs @@ -316,16 +316,14 @@ impl Shared { // Now handle the `ScaleFactorChanged` events. for &(id, ref canvas) in &*self.0.all_canvases.borrow() { - let canvas = match canvas.upgrade() { - Some(rc) => rc.borrow().raw().clone(), + let rc = match canvas.upgrade() { + Some(rc) => rc, // This shouldn't happen, but just in case... None => continue, }; + let canvas = rc.borrow(); // First, we send the `ScaleFactorChanged` event: - let current_size = crate::dpi::PhysicalSize { - width: canvas.width(), - height: canvas.height(), - }; + let current_size = canvas.size().get(); let logical_size = current_size.to_logical::(old_scale); let mut new_size = logical_size.to_physical(new_scale); self.handle_single_event_sync( diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index c21b8b06602..8ede1b6e587 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -14,7 +14,7 @@ use super::{ runner, window::WindowId, }; -use crate::dpi::{PhysicalSize, Size}; +use crate::dpi::Size; use crate::event::{ DeviceEvent, DeviceId as RootDeviceId, ElementState, Event, KeyEvent, Touch, TouchPhase, WindowEvent, @@ -87,6 +87,7 @@ impl EventLoopWindowTarget { has_focus: Rc>, ) { self.runner.add_canvas(RootWindowId(id), canvas); + let canvas_clone = canvas.clone(); let mut canvas = canvas.borrow_mut(); canvas.set_attribute("data-raw-handle", &id.0.to_string()); @@ -440,28 +441,22 @@ impl EventLoopWindowTarget { ); let runner = self.runner.clone(); - let raw = canvas.raw().clone(); - // The size to restore to after exiting fullscreen. - let mut intended_size = PhysicalSize { - width: raw.width(), - height: raw.height(), - }; + let mut intended_size = canvas.size().get(); canvas.on_fullscreen_change(move || { + let canvas = canvas_clone.borrow(); + // If the canvas is marked as fullscreen, it is moving *into* fullscreen // If it is not, it is moving *out of* fullscreen - let new_size = if backend::is_fullscreen(&raw) { - intended_size = PhysicalSize { - width: raw.width(), - height: raw.height(), - }; + let new_size = if backend::is_fullscreen(canvas.raw()) { + intended_size = canvas.size().get(); backend::window_size().to_physical(backend::scale_factor()) } else { intended_size }; - backend::set_canvas_size(&raw, Size::Physical(new_size)); + backend::set_canvas_size(&canvas, Size::Physical(new_size)); runner.send_event(Event::WindowEvent { window_id: RootWindowId(id), event: WindowEvent::Resized(new_size), diff --git a/src/platform_impl/web/web_sys/canvas.rs b/src/platform_impl/web/web_sys/canvas.rs index 5ad9456b5ed..da28225d962 100644 --- a/src/platform_impl/web/web_sys/canvas.rs +++ b/src/platform_impl/web/web_sys/canvas.rs @@ -1,13 +1,14 @@ use super::event_handle::EventListenerHandle; use super::media_query_handle::MediaQueryListHandle; use super::{event, ButtonsState}; -use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; +use crate::dpi::{LogicalPosition, LogicalSize, PhysicalPosition, PhysicalSize}; use crate::error::OsError as RootOE; use crate::event::{Force, MouseButton, MouseScrollDelta}; use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState}; use crate::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes}; +use crate::window::WindowAttributes; -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::rc::Rc; use js_sys::Promise; @@ -41,12 +42,16 @@ pub struct Canvas { struct Common { /// Note: resizing the HTMLCanvasElement should go through `backend::set_canvas_size` to ensure the DPI factor is maintained. raw: HtmlCanvasElement, + size: Rc>>, wants_fullscreen: Rc>, } impl Canvas { - pub fn create(attr: PlatformSpecificWindowBuilderAttributes) -> Result { - let canvas = match attr.canvas { + pub fn create( + attr: &WindowAttributes, + platform_attr: PlatformSpecificWindowBuilderAttributes, + ) -> Result { + let canvas = match platform_attr.canvas { Some(canvas) => canvas, None => { let window = web_sys::window() @@ -68,7 +73,7 @@ impl Canvas { // sequential keyboard navigation, but its order is defined by the // document's source order. // https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex - if attr.focusable { + if platform_attr.focusable { canvas .set_attribute("tabindex", "0") .map_err(|_| os_error!(OsError("Failed to set a tabindex".to_owned())))?; @@ -80,9 +85,21 @@ impl Canvas { MouseState::NoPointerEvent(mouse_handler::MouseHandler::new()) }; - Ok(Canvas { + let size = attr + .inner_size + .unwrap_or( + LogicalSize { + width: 1024.0, + height: 768.0, + } + .into(), + ) + .to_physical(super::scale_factor()); + + let canvas = Canvas { common: Common { raw: canvas, + size: Rc::new(Cell::new(size)), wants_fullscreen: Rc::new(RefCell::new(false)), }, on_touch_start: None, @@ -95,7 +112,11 @@ impl Canvas { on_fullscreen_change: None, on_dark_mode: None, mouse_state, - }) + }; + + super::set_canvas_size(&canvas, size.into()); + + Ok(canvas) } pub fn set_cursor_lock(&self, lock: bool) -> Result<(), RootOE> { @@ -128,11 +149,8 @@ impl Canvas { } } - pub fn size(&self) -> PhysicalSize { - PhysicalSize { - width: self.common.raw.width(), - height: self.common.raw.height(), - } + pub fn size(&self) -> &Rc>> { + &self.common.size } pub fn raw(&self) -> &HtmlCanvasElement { diff --git a/src/platform_impl/web/web_sys/mod.rs b/src/platform_impl/web/web_sys/mod.rs index 454204c79b0..40c7c392b4a 100644 --- a/src/platform_impl/web/web_sys/mod.rs +++ b/src/platform_impl/web/web_sys/mod.rs @@ -82,12 +82,19 @@ pub fn scale_factor() -> f64 { window.device_pixel_ratio() } -pub fn set_canvas_size(raw: &HtmlCanvasElement, size: Size) { +pub fn set_canvas_size(canvas: &Canvas, new_size: Size) { let scale_factor = scale_factor(); - let logical_size = size.to_logical::(scale_factor); - set_canvas_style_property(raw, "width", &format!("{}px", logical_size.width)); - set_canvas_style_property(raw, "height", &format!("{}px", logical_size.height)); + let physical_size = new_size.to_physical(scale_factor); + canvas.size().set(physical_size); + + let logical_size = new_size.to_logical::(scale_factor); + set_canvas_style_property(canvas.raw(), "width", &format!("{}px", logical_size.width)); + set_canvas_style_property( + canvas.raw(), + "height", + &format!("{}px", logical_size.height), + ); } pub fn set_canvas_style_property(raw: &HtmlCanvasElement, property: &str, value: &str) { diff --git a/src/platform_impl/web/window.rs b/src/platform_impl/web/window.rs index 6401fc0fa27..0b7b08617ed 100644 --- a/src/platform_impl/web/window.rs +++ b/src/platform_impl/web/window.rs @@ -1,4 +1,4 @@ -use crate::dpi::{LogicalSize, PhysicalPosition, PhysicalSize, Position, Size}; +use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size}; use crate::error::{ExternalError, NotSupportedError, OsError as RootOE}; use crate::event; use crate::icon::Icon; @@ -38,7 +38,7 @@ impl Window { let prevent_default = platform_attr.prevent_default; - let canvas = backend::Canvas::create(platform_attr)?; + let canvas = backend::Canvas::create(&attr, platform_attr)?; let canvas = Rc::new(RefCell::new(canvas)); let register_redraw_request = Box::new(move || runner.request_redraw(RootWI(id))); @@ -67,13 +67,6 @@ impl Window { has_focus, }; - backend::set_canvas_size( - window.canvas.borrow().raw(), - attr.inner_size.unwrap_or(Size::Logical(LogicalSize { - width: 1024.0, - height: 768.0, - })), - ); window.set_title(&attr.title); window.set_maximized(attr.maximized); window.set_visible(attr.visible); @@ -129,7 +122,7 @@ impl Window { #[inline] pub fn inner_size(&self) -> PhysicalSize { - self.canvas.borrow().size() + self.canvas.borrow().size().get() } #[inline] @@ -141,7 +134,7 @@ impl Window { #[inline] pub fn set_inner_size(&self, size: Size) { let old_size = self.inner_size(); - backend::set_canvas_size(self.canvas.borrow().raw(), size); + backend::set_canvas_size(&self.canvas.borrow(), size); let new_size = self.inner_size(); if old_size != new_size { (self.resize_notify_fn)(new_size);