Make canvas in WindowBuilder safe (#3320)

This commit is contained in:
daxpedda 2023-12-26 01:22:10 +01:00 committed by GitHub
parent 843d7904d6
commit e0fea25b06
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 214 additions and 169 deletions

View file

@ -5,9 +5,9 @@ use crate::window::{
Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType,
WindowAttributes, WindowButtons, WindowId as RootWI, WindowLevel,
};
use crate::SendSyncWrapper;
use super::cursor::CursorState;
use super::main_thread::{MainThreadMarker, MainThreadSafe};
use super::r#async::Dispatcher;
use super::{backend, monitor::MonitorHandle, EventLoopWindowTarget, Fullscreen};
use web_sys::HtmlCanvasElement;
@ -15,6 +15,7 @@ use web_sys::HtmlCanvasElement;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;
use std::sync::Arc;
pub struct Window {
inner: Dispatcher<Inner>,
@ -38,10 +39,16 @@ impl Window {
let window = target.runner.window();
let document = target.runner.document();
let canvas =
backend::Canvas::create(id, window.clone(), document.clone(), &attr, platform_attr)?;
let canvas = backend::Canvas::create(
target.runner.main_thread(),
id,
window.clone(),
document.clone(),
&attr,
platform_attr,
)?;
let canvas = Rc::new(RefCell::new(canvas));
let cursor = CursorState::new(canvas.borrow().style().clone());
let cursor = CursorState::new(target.runner.main_thread(), canvas.borrow().style().clone());
target.register(&canvas, id);
@ -62,7 +69,7 @@ impl Window {
inner.set_window_icon(attr.window_icon);
let canvas = Rc::downgrade(&inner.canvas);
let (dispatcher, runner) = Dispatcher::new(inner).unwrap();
let (dispatcher, runner) = Dispatcher::new(target.runner.main_thread(), inner).unwrap();
target.runner.add_canvas(RootWI(id), canvas, runner);
Ok(Window { inner: dispatcher })
@ -465,16 +472,30 @@ impl From<u64> for WindowId {
#[derive(Clone)]
pub struct PlatformSpecificWindowBuilderAttributes {
pub(crate) canvas: SendSyncWrapper<Option<backend::RawCanvasType>>,
pub(crate) canvas: Option<Arc<MainThreadSafe<backend::RawCanvasType>>>,
pub(crate) prevent_default: bool,
pub(crate) focusable: bool,
pub(crate) append: bool,
}
impl PlatformSpecificWindowBuilderAttributes {
pub(crate) fn set_canvas(&mut self, canvas: Option<backend::RawCanvasType>) {
let Some(canvas) = canvas else {
self.canvas = None;
return;
};
let main_thread = MainThreadMarker::new()
.expect("received a `HtmlCanvasElement` outside the window context");
self.canvas = Some(Arc::new(MainThreadSafe::new(main_thread, canvas)));
}
}
impl Default for PlatformSpecificWindowBuilderAttributes {
fn default() -> Self {
Self {
canvas: SendSyncWrapper(None),
canvas: None,
prevent_default: true,
focusable: true,
append: false,