On Web, cache commonly used values (#2947)

This commit is contained in:
daxpedda 2023-07-11 00:11:06 +02:00 committed by GitHub
parent c4d70d75c1
commit af26f01b95
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 131 additions and 126 deletions

View file

@ -4,4 +4,6 @@ disallowed-methods = [
{ path = "web_sys::HtmlCanvasElement::height", reason = "Winit shouldn't touch the internal canvas size" }, { path = "web_sys::HtmlCanvasElement::height", reason = "Winit shouldn't touch the internal canvas size" },
{ path = "web_sys::HtmlCanvasElement::set_width", reason = "Winit shouldn't touch the internal canvas size" }, { path = "web_sys::HtmlCanvasElement::set_width", reason = "Winit shouldn't touch the internal canvas size" },
{ path = "web_sys::HtmlCanvasElement::set_height", reason = "Winit shouldn't touch the internal canvas size" }, { path = "web_sys::HtmlCanvasElement::set_height", reason = "Winit shouldn't touch the internal canvas size" },
{ path = "web_sys::Window::document", reason = "cache this to reduce calls to JS" },
{ path = "web_sys::Window::get_computed_style", reason = "cache this to reduce calls to JS" },
] ]

View file

@ -19,7 +19,7 @@ use std::{
rc::{Rc, Weak}, rc::{Rc, Weak},
}; };
use wasm_bindgen::prelude::Closure; use wasm_bindgen::prelude::Closure;
use web_sys::{KeyboardEvent, PageTransitionEvent, PointerEvent, WheelEvent}; use web_sys::{Document, KeyboardEvent, PageTransitionEvent, PointerEvent, WheelEvent};
use web_time::{Duration, Instant}; use web_time::{Duration, Instant};
pub struct Shared<T: 'static>(Rc<Execution<T>>); pub struct Shared<T: 'static>(Rc<Execution<T>>);
@ -41,6 +41,7 @@ pub struct Execution<T: 'static> {
events: RefCell<VecDeque<EventWrapper<T>>>, events: RefCell<VecDeque<EventWrapper<T>>>,
id: RefCell<u32>, id: RefCell<u32>,
window: web_sys::Window, window: web_sys::Window,
document: Document,
all_canvases: RefCell<Vec<(WindowId, Weak<RefCell<backend::Canvas>>)>>, all_canvases: RefCell<Vec<(WindowId, Weak<RefCell<backend::Canvas>>)>>,
redraw_pending: RefCell<HashSet<WindowId>>, redraw_pending: RefCell<HashSet<WindowId>>,
destroy_pending: RefCell<VecDeque<WindowId>>, destroy_pending: RefCell<VecDeque<WindowId>>,
@ -141,13 +142,18 @@ impl<T: 'static> Runner<T> {
impl<T: 'static> Shared<T> { impl<T: 'static> Shared<T> {
pub fn new() -> Self { pub fn new() -> Self {
#[allow(clippy::disallowed_methods)]
let window = web_sys::window().expect("only callable from inside the `Window`");
#[allow(clippy::disallowed_methods)]
let document = window.document().expect("Failed to obtain document");
Shared(Rc::new(Execution { Shared(Rc::new(Execution {
runner: RefCell::new(RunnerEnum::Pending), runner: RefCell::new(RunnerEnum::Pending),
suspended: Cell::new(false), suspended: Cell::new(false),
event_loop_recreation: Cell::new(false), event_loop_recreation: Cell::new(false),
events: RefCell::new(VecDeque::new()), events: RefCell::new(VecDeque::new()),
#[allow(clippy::disallowed_methods)] window,
window: web_sys::window().expect("only callable from inside the `Window`"), document,
id: RefCell::new(0), id: RefCell::new(0),
all_canvases: RefCell::new(Vec::new()), all_canvases: RefCell::new(Vec::new()),
redraw_pending: RefCell::new(HashSet::new()), redraw_pending: RefCell::new(HashSet::new()),
@ -168,6 +174,10 @@ impl<T: 'static> Shared<T> {
&self.0.window &self.0.window
} }
pub fn document(&self) -> &Document {
&self.0.document
}
pub fn add_canvas(&self, id: WindowId, canvas: &Rc<RefCell<backend::Canvas>>) { pub fn add_canvas(&self, id: WindowId, canvas: &Rc<RefCell<backend::Canvas>>) {
self.0 self.0
.all_canvases .all_canvases
@ -394,13 +404,13 @@ impl<T: 'static> Shared<T> {
let runner = self.clone(); let runner = self.clone();
*self.0.on_visibility_change.borrow_mut() = Some(EventListenerHandle::new( *self.0.on_visibility_change.borrow_mut() = Some(EventListenerHandle::new(
// Safari <14 doesn't support the `visibilitychange` event on `Window`. // Safari <14 doesn't support the `visibilitychange` event on `Window`.
&self.window().document().expect("Failed to obtain document"), self.document(),
"visibilitychange", "visibilitychange",
Closure::new(move |_| { Closure::new(move |_| {
if !runner.0.suspended.get() { if !runner.0.suspended.get() {
for (id, canvas) in &*runner.0.all_canvases.borrow() { for (id, canvas) in &*runner.0.all_canvases.borrow() {
if let Some(canvas) = canvas.upgrade() { if let Some(canvas) = canvas.upgrade() {
let is_visible = backend::is_visible(runner.window()); let is_visible = backend::is_visible(runner.document());
// only fire if: // only fire if:
// - not visible and intersects // - not visible and intersects
// - not visible and we don't know if it intersects yet // - not visible and we don't know if it intersects yet

View file

@ -725,7 +725,7 @@ impl<T> EventLoopWindowTarget<T> {
let runner = self.runner.clone(); let runner = self.runner.clone();
canvas.on_intersection(move |is_intersecting| { canvas.on_intersection(move |is_intersecting| {
// only fire if visible while skipping the first event if it's intersecting // only fire if visible while skipping the first event if it's intersecting
if backend::is_visible(runner.window()) if backend::is_visible(runner.document())
&& !(is_intersecting && canvas_clone.borrow().is_intersecting.is_none()) && !(is_intersecting && canvas_clone.borrow().is_intersecting.is_none())
{ {
runner.send_event(Event::WindowEvent { runner.send_event(Event::WindowEvent {

View file

@ -21,7 +21,9 @@ use smol_str::SmolStr;
use wasm_bindgen::prelude::wasm_bindgen; use wasm_bindgen::prelude::wasm_bindgen;
use wasm_bindgen::{closure::Closure, JsCast, JsValue}; use wasm_bindgen::{closure::Closure, JsCast, JsValue};
use wasm_bindgen_futures::JsFuture; use wasm_bindgen_futures::JsFuture;
use web_sys::{Event, FocusEvent, HtmlCanvasElement, KeyboardEvent, WheelEvent}; use web_sys::{
CssStyleDeclaration, Document, Event, FocusEvent, HtmlCanvasElement, KeyboardEvent, WheelEvent,
};
#[allow(dead_code)] #[allow(dead_code)]
pub struct Canvas { pub struct Canvas {
@ -44,8 +46,10 @@ pub struct Canvas {
pub struct Common { pub struct Common {
pub window: web_sys::Window, pub window: web_sys::Window,
pub document: Document,
/// Note: resizing the HTMLCanvasElement should go through `backend::set_canvas_size` to ensure the DPI factor is maintained. /// Note: resizing the HTMLCanvasElement should go through `backend::set_canvas_size` to ensure the DPI factor is maintained.
pub raw: HtmlCanvasElement, pub raw: HtmlCanvasElement,
style: CssStyleDeclaration,
old_size: Rc<Cell<PhysicalSize<u32>>>, old_size: Rc<Cell<PhysicalSize<u32>>>,
current_size: Rc<Cell<PhysicalSize<u32>>>, current_size: Rc<Cell<PhysicalSize<u32>>>,
wants_fullscreen: Rc<RefCell<bool>>, wants_fullscreen: Rc<RefCell<bool>>,
@ -55,21 +59,16 @@ impl Canvas {
pub fn create( pub fn create(
id: WindowId, id: WindowId,
window: web_sys::Window, window: web_sys::Window,
document: Document,
attr: &WindowAttributes, attr: &WindowAttributes,
platform_attr: PlatformSpecificWindowBuilderAttributes, platform_attr: PlatformSpecificWindowBuilderAttributes,
) -> Result<Self, RootOE> { ) -> Result<Self, RootOE> {
let canvas = match platform_attr.canvas { let canvas = match platform_attr.canvas {
Some(canvas) => canvas, Some(canvas) => canvas,
None => { None => document
let document = window .create_element("canvas")
.document() .map_err(|_| os_error!(OsError("Failed to create canvas element".to_owned())))?
.ok_or_else(|| os_error!(OsError("Failed to obtain document".to_owned())))?; .unchecked_into(),
document
.create_element("canvas")
.map_err(|_| os_error!(OsError("Failed to create canvas element".to_owned())))?
.unchecked_into()
}
}; };
// A tabindex is needed in order to capture local keyboard events. // A tabindex is needed in order to capture local keyboard events.
@ -83,15 +82,24 @@ impl Canvas {
.map_err(|_| os_error!(OsError("Failed to set a tabindex".to_owned())))?; .map_err(|_| os_error!(OsError("Failed to set a tabindex".to_owned())))?;
} }
#[allow(clippy::disallowed_methods)]
let style = window
.get_computed_style(&canvas)
.expect("Failed to obtain computed style")
// this can't fail: we aren't using a pseudo-element
.expect("Invalid pseudo-element");
if let Some(size) = attr.inner_size { if let Some(size) = attr.inner_size {
let size = size.to_logical(super::scale_factor(&window)); let size = size.to_logical(super::scale_factor(&window));
super::set_canvas_size(&window, &canvas, size); super::set_canvas_size(&document, &canvas, &style, size);
} }
Ok(Canvas { Ok(Canvas {
common: Common { common: Common {
window, window,
document,
raw: canvas, raw: canvas,
style,
old_size: Rc::default(), old_size: Rc::default(),
current_size: Rc::default(), current_size: Rc::default(),
wants_fullscreen: Rc::new(RefCell::new(false)), wants_fullscreen: Rc::new(RefCell::new(false)),
@ -117,12 +125,7 @@ impl Canvas {
if lock { if lock {
self.raw().request_pointer_lock(); self.raw().request_pointer_lock();
} else { } else {
let document = self self.common.document.exit_pointer_lock();
.common
.window
.document()
.ok_or_else(|| os_error!(OsError("Failed to obtain document".to_owned())))?;
document.exit_pointer_lock();
} }
Ok(()) Ok(())
} }
@ -141,50 +144,58 @@ impl Canvas {
y: bounds.y(), y: bounds.y(),
}; };
let document = self.window().document().expect("Failed to obtain document"); if self.document().contains(Some(self.raw()))
&& self.style().get_property_value("display").unwrap() != "none"
if document.contains(Some(self.raw())) { {
let style = self position.x += super::style_size_property(self.style(), "border-left-width")
.window() + super::style_size_property(self.style(), "padding-left");
.get_computed_style(self.raw()) position.y += super::style_size_property(self.style(), "border-top-width")
.expect("Failed to obtain computed style") + super::style_size_property(self.style(), "padding-top");
// this can't fail: we aren't using a pseudo-element
.expect("Invalid pseudo-element");
if style.get_property_value("display").unwrap() != "none" {
position.x += super::style_size_property(&style, "border-left-width")
+ super::style_size_property(&style, "padding-left");
position.y += super::style_size_property(&style, "border-top-width")
+ super::style_size_property(&style, "padding-top");
}
} }
position position
} }
#[inline]
pub fn old_size(&self) -> PhysicalSize<u32> { pub fn old_size(&self) -> PhysicalSize<u32> {
self.common.old_size.get() self.common.old_size.get()
} }
#[inline]
pub fn inner_size(&self) -> PhysicalSize<u32> { pub fn inner_size(&self) -> PhysicalSize<u32> {
self.common.current_size.get() self.common.current_size.get()
} }
#[inline]
pub fn set_old_size(&self, size: PhysicalSize<u32>) { pub fn set_old_size(&self, size: PhysicalSize<u32>) {
self.common.old_size.set(size) self.common.old_size.set(size)
} }
#[inline]
pub fn set_current_size(&self, size: PhysicalSize<u32>) { pub fn set_current_size(&self, size: PhysicalSize<u32>) {
self.common.current_size.set(size) self.common.current_size.set(size)
} }
#[inline]
pub fn window(&self) -> &web_sys::Window { pub fn window(&self) -> &web_sys::Window {
&self.common.window &self.common.window
} }
#[inline]
pub fn document(&self) -> &Document {
&self.common.document
}
#[inline]
pub fn raw(&self) -> &HtmlCanvasElement { pub fn raw(&self) -> &HtmlCanvasElement {
&self.common.raw &self.common.raw
} }
#[inline]
pub fn style(&self) -> &CssStyleDeclaration {
&self.common.style
}
pub fn on_touch_start(&mut self, prevent_default: bool) { pub fn on_touch_start(&mut self, prevent_default: bool) {
self.on_touch_start = Some(self.common.add_event("touchstart", move |event: Event| { self.on_touch_start = Some(self.common.add_event("touchstart", move |event: Event| {
if prevent_default { if prevent_default {
@ -382,7 +393,9 @@ impl Canvas {
{ {
self.on_resize_scale = Some(ResizeScaleHandle::new( self.on_resize_scale = Some(ResizeScaleHandle::new(
self.window().clone(), self.window().clone(),
self.document().clone(),
self.raw().clone(), self.raw().clone(),
self.style().clone(),
scale_handler, scale_handler,
size_handler, size_handler,
)); ));
@ -425,7 +438,7 @@ impl Canvas {
// Then we resize the canvas to the new size, a new // Then we resize the canvas to the new size, a new
// `Resized` event will be sent by the `ResizeObserver`: // `Resized` event will be sent by the `ResizeObserver`:
let new_size = new_size.to_logical(scale); let new_size = new_size.to_logical(scale);
super::set_canvas_size(self.window(), self.raw(), new_size); super::set_canvas_size(self.document(), self.raw(), self.style(), new_size);
// Set the size might not trigger the event because the calculation is inaccurate. // Set the size might not trigger the event because the calculation is inaccurate.
self.on_resize_scale self.on_resize_scale
@ -527,6 +540,6 @@ impl Common {
} }
pub fn is_fullscreen(&self) -> bool { pub fn is_fullscreen(&self) -> bool {
super::is_fullscreen(&self.window, &self.raw) super::is_fullscreen(&self.document, &self.raw)
} }
} }

View file

@ -18,16 +18,14 @@ use crate::platform::web::WindowExtWebSys;
use crate::window::Window; use crate::window::Window;
use wasm_bindgen::closure::Closure; use wasm_bindgen::closure::Closure;
use web_sys::{ use web_sys::{
CssStyleDeclaration, Element, HtmlCanvasElement, PageTransitionEvent, VisibilityState, CssStyleDeclaration, Document, Element, HtmlCanvasElement, PageTransitionEvent, VisibilityState,
}; };
pub fn throw(msg: &str) { pub fn throw(msg: &str) {
wasm_bindgen::throw_str(msg); wasm_bindgen::throw_str(msg);
} }
pub fn exit_fullscreen(window: &web_sys::Window) { pub fn exit_fullscreen(document: &Document) {
let document = window.document().expect("Failed to obtain document");
document.exit_fullscreen(); document.exit_fullscreen();
} }
@ -69,35 +67,28 @@ pub fn scale_factor(window: &web_sys::Window) -> f64 {
} }
pub fn set_canvas_size( pub fn set_canvas_size(
window: &web_sys::Window, document: &Document,
raw: &HtmlCanvasElement, raw: &HtmlCanvasElement,
style: &CssStyleDeclaration,
mut new_size: LogicalSize<f64>, mut new_size: LogicalSize<f64>,
) { ) {
let document = window.document().expect("Failed to obtain document");
if !document.contains(Some(raw)) { if !document.contains(Some(raw)) {
return; return;
} }
let style = window
.get_computed_style(raw)
.expect("Failed to obtain computed style")
// this can't fail: we aren't using a pseudo-element
.expect("Invalid pseudo-element");
if style.get_property_value("display").unwrap() == "none" { if style.get_property_value("display").unwrap() == "none" {
return; return;
} }
if style.get_property_value("box-sizing").unwrap() == "border-box" { if style.get_property_value("box-sizing").unwrap() == "border-box" {
new_size.width += style_size_property(&style, "border-left-width") new_size.width += style_size_property(style, "border-left-width")
+ style_size_property(&style, "border-right-width") + style_size_property(style, "border-right-width")
+ style_size_property(&style, "padding-left") + style_size_property(style, "padding-left")
+ style_size_property(&style, "padding-right"); + style_size_property(style, "padding-right");
new_size.height += style_size_property(&style, "border-top-width") new_size.height += style_size_property(style, "border-top-width")
+ style_size_property(&style, "border-bottom-width") + style_size_property(style, "border-bottom-width")
+ style_size_property(&style, "padding-top") + style_size_property(style, "padding-top")
+ style_size_property(&style, "padding-bottom"); + style_size_property(style, "padding-bottom");
} }
set_canvas_style_property(raw, "width", &format!("{}px", new_size.width)); set_canvas_style_property(raw, "width", &format!("{}px", new_size.width));
@ -123,9 +114,7 @@ pub fn set_canvas_style_property(raw: &HtmlCanvasElement, property: &str, value:
.unwrap_or_else(|err| panic!("error: {err:?}\nFailed to set {property}")) .unwrap_or_else(|err| panic!("error: {err:?}\nFailed to set {property}"))
} }
pub fn is_fullscreen(window: &web_sys::Window, canvas: &HtmlCanvasElement) -> bool { pub fn is_fullscreen(document: &Document, canvas: &HtmlCanvasElement) -> bool {
let document = window.document().expect("Failed to obtain document");
match document.fullscreen_element() { match document.fullscreen_element() {
Some(elem) => { Some(elem) => {
let canvas: &Element = canvas; let canvas: &Element = canvas;
@ -143,8 +132,7 @@ pub fn is_dark_mode(window: &web_sys::Window) -> Option<bool> {
.map(|media| media.matches()) .map(|media| media.matches())
} }
pub fn is_visible(window: &web_sys::Window) -> bool { pub fn is_visible(document: &Document) -> bool {
let document = window.document().expect("Failed to obtain document");
document.visibility_state() == VisibilityState::Visible document.visibility_state() == VisibilityState::Visible
} }

View file

@ -3,8 +3,9 @@ use once_cell::unsync::Lazy;
use wasm_bindgen::prelude::{wasm_bindgen, Closure}; use wasm_bindgen::prelude::{wasm_bindgen, Closure};
use wasm_bindgen::{JsCast, JsValue}; use wasm_bindgen::{JsCast, JsValue};
use web_sys::{ use web_sys::{
HtmlCanvasElement, MediaQueryList, ResizeObserver, ResizeObserverBoxOptions, CssStyleDeclaration, Document, HtmlCanvasElement, MediaQueryList, ResizeObserver,
ResizeObserverEntry, ResizeObserverOptions, ResizeObserverSize, Window, ResizeObserverBoxOptions, ResizeObserverEntry, ResizeObserverOptions, ResizeObserverSize,
Window,
}; };
use crate::dpi::{LogicalSize, PhysicalSize}; use crate::dpi::{LogicalSize, PhysicalSize};
@ -20,7 +21,9 @@ pub struct ResizeScaleHandle(Rc<RefCell<ResizeScaleInternal>>);
impl ResizeScaleHandle { impl ResizeScaleHandle {
pub(crate) fn new<S, R>( pub(crate) fn new<S, R>(
window: Window, window: Window,
document: Document,
canvas: HtmlCanvasElement, canvas: HtmlCanvasElement,
style: CssStyleDeclaration,
scale_handler: S, scale_handler: S,
resize_handler: R, resize_handler: R,
) -> Self ) -> Self
@ -30,7 +33,9 @@ impl ResizeScaleHandle {
{ {
Self(ResizeScaleInternal::new( Self(ResizeScaleInternal::new(
window, window,
document,
canvas, canvas,
style,
scale_handler, scale_handler,
resize_handler, resize_handler,
)) ))
@ -45,7 +50,9 @@ impl ResizeScaleHandle {
/// changes of the `devicePixelRatio`. /// changes of the `devicePixelRatio`.
struct ResizeScaleInternal { struct ResizeScaleInternal {
window: Window, window: Window,
document: Document,
canvas: HtmlCanvasElement, canvas: HtmlCanvasElement,
style: CssStyleDeclaration,
mql: MediaQueryListHandle, mql: MediaQueryListHandle,
observer: ResizeObserver, observer: ResizeObserver,
_observer_closure: Closure<dyn FnMut(Array, ResizeObserver)>, _observer_closure: Closure<dyn FnMut(Array, ResizeObserver)>,
@ -57,7 +64,9 @@ struct ResizeScaleInternal {
impl ResizeScaleInternal { impl ResizeScaleInternal {
fn new<S, R>( fn new<S, R>(
window: Window, window: Window,
document: Document,
canvas: HtmlCanvasElement, canvas: HtmlCanvasElement,
style: CssStyleDeclaration,
scale_handler: S, scale_handler: S,
resize_handler: R, resize_handler: R,
) -> Rc<RefCell<Self>> ) -> Rc<RefCell<Self>>
@ -80,7 +89,7 @@ impl ResizeScaleInternal {
if let Some(rc_self) = weak_self.upgrade() { if let Some(rc_self) = weak_self.upgrade() {
let mut this = rc_self.borrow_mut(); let mut this = rc_self.borrow_mut();
let size = Self::process_entry(&this.window, &this.canvas, entries); let size = this.process_entry(entries);
if this.notify_scale.replace(false) { if this.notify_scale.replace(false) {
let scale = backend::scale_factor(&this.window); let scale = backend::scale_factor(&this.window);
@ -94,7 +103,9 @@ impl ResizeScaleInternal {
RefCell::new(Self { RefCell::new(Self {
window, window,
document,
canvas, canvas,
style,
mql, mql,
observer, observer,
_observer_closure: observer_closure, _observer_closure: observer_closure,
@ -142,17 +153,8 @@ impl ResizeScaleInternal {
} }
fn notify(&mut self) { fn notify(&mut self) {
let style = self if !self.document.contains(Some(&self.canvas))
.window || self.style.get_property_value("display").unwrap() == "none"
.get_computed_style(&self.canvas)
.expect("Failed to obtain computed style")
// this can't fail: we aren't using a pseudo-element
.expect("Invalid pseudo-element");
let document = self.window.document().expect("Failed to obtain document");
if !document.contains(Some(&self.canvas))
|| style.get_property_value("display").unwrap() == "none"
{ {
let size = PhysicalSize::new(0, 0); let size = PhysicalSize::new(0, 0);
@ -175,19 +177,19 @@ impl ResizeScaleInternal {
} }
let mut size = LogicalSize::new( let mut size = LogicalSize::new(
backend::style_size_property(&style, "width"), backend::style_size_property(&self.style, "width"),
backend::style_size_property(&style, "height"), backend::style_size_property(&self.style, "height"),
); );
if style.get_property_value("box-sizing").unwrap() == "border-box" { if self.style.get_property_value("box-sizing").unwrap() == "border-box" {
size.width -= backend::style_size_property(&style, "border-left-width") size.width -= backend::style_size_property(&self.style, "border-left-width")
+ backend::style_size_property(&style, "border-right-width") + backend::style_size_property(&self.style, "border-right-width")
+ backend::style_size_property(&style, "padding-left") + backend::style_size_property(&self.style, "padding-left")
+ backend::style_size_property(&style, "padding-right"); + backend::style_size_property(&self.style, "padding-right");
size.height -= backend::style_size_property(&style, "border-top-width") size.height -= backend::style_size_property(&self.style, "border-top-width")
+ backend::style_size_property(&style, "border-bottom-width") + backend::style_size_property(&self.style, "border-bottom-width")
+ backend::style_size_property(&style, "padding-top") + backend::style_size_property(&self.style, "padding-top")
+ backend::style_size_property(&style, "padding-bottom"); + backend::style_size_property(&self.style, "padding-bottom");
} }
let size = size.to_physical(backend::scale_factor(&self.window)); let size = size.to_physical(backend::scale_factor(&self.window));
@ -229,11 +231,7 @@ impl ResizeScaleInternal {
this.notify(); this.notify();
} }
fn process_entry( fn process_entry(&self, entries: Array) -> PhysicalSize<u32> {
window: &Window,
canvas: &HtmlCanvasElement,
entries: Array,
) -> PhysicalSize<u32> {
let entry: ResizeObserverEntry = entries.get(0).unchecked_into(); let entry: ResizeObserverEntry = entries.get(0).unchecked_into();
// Safari doesn't support `devicePixelContentBoxSize` // Safari doesn't support `devicePixelContentBoxSize`
@ -241,7 +239,7 @@ impl ResizeScaleInternal {
let rect = entry.content_rect(); let rect = entry.content_rect();
return LogicalSize::new(rect.width(), rect.height()) return LogicalSize::new(rect.width(), rect.height())
.to_physical(backend::scale_factor(window)); .to_physical(backend::scale_factor(&self.window));
} }
let entry: ResizeObserverSize = entry let entry: ResizeObserverSize = entry
@ -249,13 +247,8 @@ impl ResizeScaleInternal {
.get(0) .get(0)
.unchecked_into(); .unchecked_into();
let style = window let writing_mode = self
.get_computed_style(canvas) .style
.expect("Failed to get computed style of canvas")
// this can only be empty if we provided an invalid `pseudoElt`
.expect("`getComputedStyle` can not be empty");
let writing_mode = style
.get_property_value("writing-mode") .get_property_value("writing-mode")
.expect("`writing-mode` is a valid CSS property"); .expect("`writing-mode` is a valid CSS property");

View file

@ -7,7 +7,7 @@ use crate::window::{
}; };
use raw_window_handle::{RawDisplayHandle, RawWindowHandle, WebDisplayHandle, WebWindowHandle}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle, WebDisplayHandle, WebWindowHandle};
use web_sys::HtmlCanvasElement; use web_sys::{CssStyleDeclaration, Document, HtmlCanvasElement};
use super::r#async::Dispatcher; use super::r#async::Dispatcher;
use super::{backend, monitor::MonitorHandle, EventLoopWindowTarget, Fullscreen}; use super::{backend, monitor::MonitorHandle, EventLoopWindowTarget, Fullscreen};
@ -27,6 +27,8 @@ pub struct Window {
pub struct Inner { pub struct Inner {
pub window: web_sys::Window, pub window: web_sys::Window,
document: Document,
style: CssStyleDeclaration,
canvas: Rc<RefCell<backend::Canvas>>, canvas: Rc<RefCell<backend::Canvas>>,
previous_pointer: RefCell<&'static str>, previous_pointer: RefCell<&'static str>,
register_redraw_request: Box<dyn Fn()>, register_redraw_request: Box<dyn Fn()>,
@ -46,7 +48,10 @@ impl Window {
let prevent_default = platform_attr.prevent_default; let prevent_default = platform_attr.prevent_default;
let window = target.runner.window(); let window = target.runner.window();
let canvas = backend::Canvas::create(id, window.clone(), &attr, platform_attr)?; let document = target.runner.document();
let canvas =
backend::Canvas::create(id, window.clone(), document.clone(), &attr, platform_attr)?;
let style = canvas.style().clone();
let canvas = Rc::new(RefCell::new(canvas)); let canvas = Rc::new(RefCell::new(canvas));
let register_redraw_request = Box::new(move || runner.request_redraw(RootWI(id))); let register_redraw_request = Box::new(move || runner.request_redraw(RootWI(id)));
@ -62,6 +67,8 @@ impl Window {
has_focus, has_focus,
inner: Dispatcher::new(Inner { inner: Dispatcher::new(Inner {
window: window.clone(), window: window.clone(),
document: document.clone(),
style,
canvas, canvas,
previous_pointer: RefCell::new("auto"), previous_pointer: RefCell::new("auto"),
register_redraw_request, register_redraw_request,
@ -130,24 +137,16 @@ impl Window {
let mut position = position.to_logical::<f64>(inner.scale_factor()); let mut position = position.to_logical::<f64>(inner.scale_factor());
let canvas = inner.canvas.borrow(); let canvas = inner.canvas.borrow();
let document = inner.window.document().expect("Failed to obtain document");
if document.contains(Some(canvas.raw())) { if inner.document.contains(Some(canvas.raw()))
let style = inner && inner.style.get_property_value("display").unwrap() != "none"
.window {
.get_computed_style(canvas.raw()) position.x -= backend::style_size_property(&inner.style, "margin-left")
.expect("Failed to obtain computed style") + backend::style_size_property(&inner.style, "border-left-width")
// this can't fail: we aren't using a pseudo-element + backend::style_size_property(&inner.style, "padding-left");
.expect("Invalid pseudo-element"); position.y -= backend::style_size_property(&inner.style, "margin-top")
+ backend::style_size_property(&inner.style, "border-top-width")
if style.get_property_value("display").unwrap() != "none" { + backend::style_size_property(&inner.style, "padding-top");
position.x -= backend::style_size_property(&style, "margin-left")
+ backend::style_size_property(&style, "border-left-width")
+ backend::style_size_property(&style, "padding-left");
position.y -= backend::style_size_property(&style, "margin-top")
+ backend::style_size_property(&style, "border-top-width")
+ backend::style_size_property(&style, "padding-top");
}
} }
canvas.set_attribute("position", "fixed"); canvas.set_attribute("position", "fixed");
@ -172,7 +171,7 @@ impl Window {
self.inner.dispatch(move |inner| { self.inner.dispatch(move |inner| {
let size = size.to_logical(inner.scale_factor()); let size = size.to_logical(inner.scale_factor());
let canvas = inner.canvas.borrow(); let canvas = inner.canvas.borrow();
backend::set_canvas_size(canvas.window(), canvas.raw(), size); backend::set_canvas_size(canvas.document(), canvas.raw(), canvas.style(), size);
}); });
None None
@ -324,7 +323,7 @@ impl Window {
if fullscreen.is_some() { if fullscreen.is_some() {
inner.canvas.borrow().request_fullscreen(); inner.canvas.borrow().request_fullscreen();
} else if inner.canvas.borrow().is_fullscreen() { } else if inner.canvas.borrow().is_fullscreen() {
backend::exit_fullscreen(&inner.window); backend::exit_fullscreen(&inner.document);
} }
}); });
} }