Skip to content

Commit

Permalink
Use correct canvas size for scale factor change
Browse files Browse the repository at this point in the history
  • Loading branch information
daxpedda committed Jun 5, 2023
1 parent 8f7f3ef commit a5f040b
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 54 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ And please only add new entries to the top of this list, right below the `# Unre
- On Web, `EventLoopProxy` now implements `Send`.
- On Web, `Window` now implements `Send` and `Sync`.
- **Breaking:** `WindowExtWebSys::canvas()` now returns an `Option`.
- 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

Expand Down
5 changes: 4 additions & 1 deletion examples/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
12 changes: 5 additions & 7 deletions src/platform_impl/web/event_loop/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,16 +327,14 @@ impl<T: 'static> Shared<T> {

// 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::<f64>(old_scale);
let mut new_size = logical_size.to_physical(new_scale);
self.handle_single_event_sync(
Expand All @@ -351,7 +349,7 @@ impl<T: 'static> Shared<T> {
);

// Then we resize the canvas to the new size and send a `Resized` event:
backend::set_canvas_size(self.window(), &canvas, crate::dpi::Size::Physical(new_size));
backend::set_canvas_size(&canvas, crate::dpi::Size::Physical(new_size));
self.handle_single_event_sync(
Event::WindowEvent {
window_id: id,
Expand Down
24 changes: 10 additions & 14 deletions src/platform_impl/web/event_loop/window_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,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,
Expand Down Expand Up @@ -89,6 +89,7 @@ impl<T> EventLoopWindowTarget<T> {
has_focus: Arc<AtomicBool>,
) {
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());

Expand Down Expand Up @@ -502,32 +503,27 @@ impl<T> EventLoopWindowTarget<T> {
prevent_default,
);

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({
let window = self.runner.window().clone();
let runner = self.runner.clone();

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(&window, &raw) {
intended_size = PhysicalSize {
width: raw.width(),
height: raw.height(),
};
let new_size = if backend::is_fullscreen(&window, canvas.raw()) {
intended_size = canvas.size().get();

backend::window_size(&window).to_physical(backend::scale_factor(&window))
} else {
intended_size
};

backend::set_canvas_size(&window, &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),
Expand Down
44 changes: 32 additions & 12 deletions src/platform_impl/web/web_sys/canvas.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ use super::event_handle::EventListenerHandle;
use super::media_query_handle::MediaQueryListHandle;
use super::pointer::PointerHandler;
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;
Expand Down Expand Up @@ -39,15 +40,17 @@ pub struct Common {
pub window: web_sys::Window,
/// Note: resizing the HTMLCanvasElement should go through `backend::set_canvas_size` to ensure the DPI factor is maintained.
pub raw: HtmlCanvasElement,
size: Rc<Cell<PhysicalSize<u32>>>,
wants_fullscreen: Rc<RefCell<bool>>,
}

impl Canvas {
pub fn create(
window: web_sys::Window,
attr: PlatformSpecificWindowBuilderAttributes,
attr: &WindowAttributes,
platform_attr: PlatformSpecificWindowBuilderAttributes,
) -> Result<Self, RootOE> {
let canvas = match attr.canvas {
let canvas = match platform_attr.canvas {
Some(canvas) => canvas,
None => {
let document = window
Expand All @@ -66,16 +69,28 @@ 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())))?;
}

Ok(Canvas {
let size = attr
.inner_size
.unwrap_or(
LogicalSize {
width: 1024.0,
height: 768.0,
}
.into(),
)
.to_physical(super::scale_factor(&window));

let canvas = Canvas {
common: Common {
window,
raw: canvas,
size: Rc::new(Cell::new(size)),
wants_fullscreen: Rc::new(RefCell::new(false)),
},
on_touch_start: None,
Expand All @@ -88,7 +103,11 @@ impl Canvas {
on_fullscreen_change: None,
on_dark_mode: None,
pointer_handler: PointerHandler::new(),
})
};

super::set_canvas_size(&canvas, size.into());

Ok(canvas)
}

pub fn set_cursor_lock(&self, lock: bool) -> Result<(), RootOE> {
Expand Down Expand Up @@ -121,11 +140,12 @@ impl Canvas {
}
}

pub fn size(&self) -> PhysicalSize<u32> {
PhysicalSize {
width: self.common.raw.width(),
height: self.common.raw.height(),
}
pub fn window(&self) -> &web_sys::Window {
&self.common.window
}

pub fn size(&self) -> &Rc<Cell<PhysicalSize<u32>>> {
&self.common.size
}

pub fn raw(&self) -> &HtmlCanvasElement {
Expand Down
19 changes: 13 additions & 6 deletions src/platform_impl/web/web_sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,19 @@ pub fn scale_factor(window: &web_sys::Window) -> f64 {
window.device_pixel_ratio()
}

pub fn set_canvas_size(window: &web_sys::Window, raw: &HtmlCanvasElement, size: Size) {
let scale_factor = scale_factor(window);
let logical_size = size.to_logical::<f64>(scale_factor);

set_canvas_style_property(raw, "width", &format!("{}px", logical_size.width));
set_canvas_style_property(raw, "height", &format!("{}px", logical_size.height));
pub fn set_canvas_size(canvas: &Canvas, new_size: Size) {
let scale_factor = scale_factor(canvas.window());

let physical_size = new_size.to_physical(scale_factor);
canvas.size().set(physical_size);

let logical_size = new_size.to_logical::<f64>(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) {
Expand Down
19 changes: 5 additions & 14 deletions src/platform_impl/web/window.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -48,7 +48,7 @@ impl Window {
let prevent_default = platform_attr.prevent_default;

let window = target.runner.window();
let canvas = backend::Canvas::create(window.clone(), platform_attr)?;
let canvas = backend::Canvas::create(window.clone(), &attr, platform_attr)?;
let canvas = Rc::new(RefCell::new(canvas));

let register_redraw_request = Box::new(move || runner.request_redraw(RootWI(id)));
Expand All @@ -67,15 +67,6 @@ impl Window {
let runner = target.runner.clone();
let destroy_fn = Box::new(move || runner.notify_destroy_window(RootWI(id)));

backend::set_canvas_size(
window,
canvas.borrow().raw(),
attr.inner_size.unwrap_or(Size::Logical(LogicalSize {
width: 1024.0,
height: 768.0,
})),
);

let window = Window {
id,
has_focus,
Expand Down Expand Up @@ -158,7 +149,7 @@ impl Window {

#[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> {
self.inner.queue(|inner| inner.inner_size())
self.inner.queue(|inner| inner.canvas.borrow().size().get())
}

#[inline]
Expand All @@ -171,7 +162,7 @@ impl Window {
pub fn set_inner_size(&self, size: Size) {
self.inner.dispatch(move |inner| {
let old_size = inner.inner_size();
backend::set_canvas_size(&inner.window, inner.canvas.borrow().raw(), size);
backend::set_canvas_size(&inner.canvas.borrow(), size);
let new_size = inner.inner_size();
if old_size != new_size {
(inner.resize_notify_fn)(new_size);
Expand Down Expand Up @@ -454,7 +445,7 @@ impl Inner {

#[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> {
self.canvas.borrow().size()
self.canvas.borrow().size().get()
}
}

Expand Down

0 comments on commit a5f040b

Please sign in to comment.