Add cleanup code to web backend, mostly web-sys (#1715)
* web-sys: Impl. event listeners removal for canvas * web-sys: Impl. media query listeners cleanup * web: Emit WindowEvent::Destroyed after Window is dropped * web-sys: Fix unload event closure being dropped early * web: Impl. cleanup on ControlFlow::Exit - Drops the Runner, which causes the event handler closure to be dropped. - (web-sys only:) Remove event listeners from DOM. * web: Do not remove canvas from DOM when dropping Window The canvas was inserted by the user, so it should be up to the user whether the canvas should be removed. * Update changelog
This commit is contained in:
parent
1c97a310b1
commit
47e7aa4209
13 changed files with 436 additions and 162 deletions
|
|
@ -8,15 +8,17 @@ use raw_window_handle::web::WebHandle;
|
|||
|
||||
use super::{backend, monitor, EventLoopWindowTarget};
|
||||
|
||||
use std::cell::RefCell;
|
||||
use std::cell::{Ref, RefCell};
|
||||
use std::collections::vec_deque::IntoIter as VecDequeIter;
|
||||
use std::collections::VecDeque;
|
||||
use std::rc::Rc;
|
||||
|
||||
pub struct Window {
|
||||
canvas: backend::Canvas,
|
||||
canvas: Rc<RefCell<backend::Canvas>>,
|
||||
previous_pointer: RefCell<&'static str>,
|
||||
id: Id,
|
||||
register_redraw_request: Box<dyn Fn()>,
|
||||
destroy_fn: Option<Box<dyn FnOnce()>>,
|
||||
}
|
||||
|
||||
impl Window {
|
||||
|
|
@ -29,17 +31,22 @@ impl Window {
|
|||
|
||||
let id = target.generate_id();
|
||||
|
||||
let mut canvas = backend::Canvas::create(platform_attr)?;
|
||||
let canvas = backend::Canvas::create(platform_attr)?;
|
||||
let mut canvas = Rc::new(RefCell::new(canvas));
|
||||
|
||||
let register_redraw_request = Box::new(move || runner.request_redraw(RootWI(id)));
|
||||
|
||||
target.register(&mut canvas, id);
|
||||
|
||||
let runner = target.runner.clone();
|
||||
let destroy_fn = Box::new(move || runner.notify_destroy_window(RootWI(id)));
|
||||
|
||||
let window = Window {
|
||||
canvas,
|
||||
previous_pointer: RefCell::new("auto"),
|
||||
id,
|
||||
register_redraw_request,
|
||||
destroy_fn: Some(destroy_fn),
|
||||
};
|
||||
|
||||
window.set_inner_size(attr.inner_size.unwrap_or(Size::Logical(LogicalSize {
|
||||
|
|
@ -54,12 +61,12 @@ impl Window {
|
|||
Ok(window)
|
||||
}
|
||||
|
||||
pub fn canvas(&self) -> &backend::Canvas {
|
||||
&self.canvas
|
||||
pub fn canvas<'a>(&'a self) -> Ref<'a, backend::Canvas> {
|
||||
self.canvas.borrow()
|
||||
}
|
||||
|
||||
pub fn set_title(&self, title: &str) {
|
||||
self.canvas.set_attribute("alt", title);
|
||||
self.canvas.borrow().set_attribute("alt", title);
|
||||
}
|
||||
|
||||
pub fn set_visible(&self, _visible: bool) {
|
||||
|
|
@ -71,7 +78,11 @@ impl Window {
|
|||
}
|
||||
|
||||
pub fn outer_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
|
||||
Ok(self.canvas.position().to_physical(self.scale_factor()))
|
||||
Ok(self
|
||||
.canvas
|
||||
.borrow()
|
||||
.position()
|
||||
.to_physical(self.scale_factor()))
|
||||
}
|
||||
|
||||
pub fn inner_position(&self) -> Result<PhysicalPosition<i32>, NotSupportedError> {
|
||||
|
|
@ -82,14 +93,15 @@ impl Window {
|
|||
pub fn set_outer_position(&self, position: Position) {
|
||||
let position = position.to_logical::<f64>(self.scale_factor());
|
||||
|
||||
self.canvas.set_attribute("position", "fixed");
|
||||
self.canvas.set_attribute("left", &position.x.to_string());
|
||||
self.canvas.set_attribute("top", &position.y.to_string());
|
||||
let canvas = self.canvas.borrow();
|
||||
canvas.set_attribute("position", "fixed");
|
||||
canvas.set_attribute("left", &position.x.to_string());
|
||||
canvas.set_attribute("top", &position.y.to_string());
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn inner_size(&self) -> PhysicalSize<u32> {
|
||||
self.canvas.size()
|
||||
self.canvas.borrow().size()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -100,7 +112,7 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn set_inner_size(&self, size: Size) {
|
||||
backend::set_canvas_size(self.canvas.raw(), size);
|
||||
backend::set_canvas_size(self.canvas.borrow().raw(), size);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -165,7 +177,7 @@ impl Window {
|
|||
CursorIcon::RowResize => "row-resize",
|
||||
};
|
||||
*self.previous_pointer.borrow_mut() = text;
|
||||
backend::set_canvas_style_property(self.canvas.raw(), "cursor", text);
|
||||
backend::set_canvas_style_property(self.canvas.borrow().raw(), "cursor", text);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
@ -181,9 +193,10 @@ impl Window {
|
|||
#[inline]
|
||||
pub fn set_cursor_visible(&self, visible: bool) {
|
||||
if !visible {
|
||||
self.canvas.set_attribute("cursor", "none");
|
||||
self.canvas.borrow().set_attribute("cursor", "none");
|
||||
} else {
|
||||
self.canvas
|
||||
.borrow()
|
||||
.set_attribute("cursor", *self.previous_pointer.borrow());
|
||||
}
|
||||
}
|
||||
|
|
@ -200,7 +213,7 @@ impl Window {
|
|||
|
||||
#[inline]
|
||||
pub fn fullscreen(&self) -> Option<Fullscreen> {
|
||||
if self.canvas.is_fullscreen() {
|
||||
if self.canvas.borrow().is_fullscreen() {
|
||||
Some(Fullscreen::Borderless(self.current_monitor_inner()))
|
||||
} else {
|
||||
None
|
||||
|
|
@ -210,8 +223,8 @@ impl Window {
|
|||
#[inline]
|
||||
pub fn set_fullscreen(&self, monitor: Option<Fullscreen>) {
|
||||
if monitor.is_some() {
|
||||
self.canvas.request_fullscreen();
|
||||
} else if self.canvas.is_fullscreen() {
|
||||
self.canvas.borrow().request_fullscreen();
|
||||
} else if self.canvas.borrow().is_fullscreen() {
|
||||
backend::exit_fullscreen();
|
||||
}
|
||||
}
|
||||
|
|
@ -277,6 +290,14 @@ impl Window {
|
|||
}
|
||||
}
|
||||
|
||||
impl Drop for Window {
|
||||
fn drop(&mut self) {
|
||||
if let Some(destroy_fn) = self.destroy_fn.take() {
|
||||
destroy_fn();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct Id(pub(crate) u32);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue