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:
alvinhochun 2020-09-21 06:42:07 +08:00 committed by GitHub
parent 1c97a310b1
commit 47e7aa4209
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 436 additions and 162 deletions

View file

@ -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);