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 4, 2023
1 parent 7500a88 commit 519790c
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 47 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

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
10 changes: 4 additions & 6 deletions src/platform_impl/web/event_loop/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -316,16 +316,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 Down
21 changes: 8 additions & 13 deletions src/platform_impl/web/event_loop/window_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -87,6 +87,7 @@ impl<T> EventLoopWindowTarget<T> {
has_focus: Rc<Cell<bool>>,
) {
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 @@ -440,28 +441,22 @@ impl<T> EventLoopWindowTarget<T> {
);

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),
Expand Down
42 changes: 30 additions & 12 deletions src/platform_impl/web/web_sys/canvas.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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<Cell<PhysicalSize<u32>>>,
wants_fullscreen: Rc<RefCell<bool>>,
}

impl Canvas {
pub fn create(attr: PlatformSpecificWindowBuilderAttributes) -> Result<Self, RootOE> {
let canvas = match attr.canvas {
pub fn create(
attr: &WindowAttributes,
platform_attr: PlatformSpecificWindowBuilderAttributes,
) -> Result<Self, RootOE> {
let canvas = match platform_attr.canvas {
Some(canvas) => canvas,
None => {
let window = web_sys::window()
Expand All @@ -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())))?;
Expand All @@ -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,
Expand All @@ -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> {
Expand Down Expand Up @@ -128,11 +149,8 @@ impl Canvas {
}
}

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

pub fn raw(&self) -> &HtmlCanvasElement {
Expand Down
15 changes: 11 additions & 4 deletions src/platform_impl/web/web_sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<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));
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
15 changes: 4 additions & 11 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 @@ -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)));
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -129,7 +122,7 @@ impl Window {

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

#[inline]
Expand All @@ -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);
Expand Down

0 comments on commit 519790c

Please sign in to comment.