On Web, implement Send and Sync where appropriate (#2834)
This commit is contained in:
parent
eb2d3894ef
commit
8f7f3efc0d
21 changed files with 609 additions and 196 deletions
|
|
@ -1,18 +1,24 @@
|
|||
use super::runner;
|
||||
use crate::event::Event;
|
||||
use crate::event_loop::EventLoopClosed;
|
||||
use crate::platform_impl::platform::r#async::Channel;
|
||||
|
||||
pub struct EventLoopProxy<T: 'static> {
|
||||
runner: runner::Shared<T>,
|
||||
runner: Channel<runner::Shared<T>, T>,
|
||||
}
|
||||
|
||||
impl<T: 'static> EventLoopProxy<T> {
|
||||
pub fn new(runner: runner::Shared<T>) -> Self {
|
||||
Self { runner }
|
||||
Self {
|
||||
runner: Channel::new(runner, |runner, event| {
|
||||
runner.send_event(Event::UserEvent(event))
|
||||
})
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
|
||||
self.runner.send_event(Event::UserEvent(event));
|
||||
self.runner.send(event);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ pub struct Execution<T: 'static> {
|
|||
runner: RefCell<RunnerEnum<T>>,
|
||||
events: RefCell<VecDeque<Event<'static, T>>>,
|
||||
id: RefCell<u32>,
|
||||
window: web_sys::Window,
|
||||
all_canvases: RefCell<Vec<(WindowId, Weak<RefCell<backend::Canvas>>)>>,
|
||||
redraw_pending: RefCell<HashSet<WindowId>>,
|
||||
destroy_pending: RefCell<VecDeque<WindowId>>,
|
||||
|
|
@ -102,6 +103,8 @@ impl<T: 'static> Shared<T> {
|
|||
Shared(Rc::new(Execution {
|
||||
runner: RefCell::new(RunnerEnum::Pending),
|
||||
events: RefCell::new(VecDeque::new()),
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
window: web_sys::window().expect("only callable from inside the `Window`"),
|
||||
id: RefCell::new(0),
|
||||
all_canvases: RefCell::new(Vec::new()),
|
||||
redraw_pending: RefCell::new(HashSet::new()),
|
||||
|
|
@ -111,6 +114,10 @@ impl<T: 'static> Shared<T> {
|
|||
}))
|
||||
}
|
||||
|
||||
pub fn window(&self) -> &web_sys::Window {
|
||||
&self.0.window
|
||||
}
|
||||
|
||||
pub fn add_canvas(&self, id: WindowId, canvas: &Rc<RefCell<backend::Canvas>>) {
|
||||
self.0
|
||||
.all_canvases
|
||||
|
|
@ -135,15 +142,19 @@ impl<T: 'static> Shared<T> {
|
|||
|
||||
let close_instance = self.clone();
|
||||
*self.0.unload_event_handle.borrow_mut() =
|
||||
Some(backend::on_unload(move || close_instance.handle_unload()));
|
||||
Some(backend::on_unload(self.window(), move || {
|
||||
close_instance.handle_unload()
|
||||
}));
|
||||
}
|
||||
|
||||
pub(crate) fn set_on_scale_change<F>(&self, handler: F)
|
||||
where
|
||||
F: 'static + FnMut(ScaleChangeArgs),
|
||||
{
|
||||
*self.0.scale_change_detector.borrow_mut() =
|
||||
Some(backend::ScaleChangeDetector::new(handler));
|
||||
*self.0.scale_change_detector.borrow_mut() = Some(backend::ScaleChangeDetector::new(
|
||||
self.window().clone(),
|
||||
handler,
|
||||
));
|
||||
}
|
||||
|
||||
// Generate a strictly increasing ID
|
||||
|
|
@ -340,7 +351,7 @@ impl<T: 'static> Shared<T> {
|
|||
);
|
||||
|
||||
// Then we resize the canvas to the new size and send a `Resized` event:
|
||||
backend::set_canvas_size(&canvas, crate::dpi::Size::Physical(new_size));
|
||||
backend::set_canvas_size(self.window(), &canvas, crate::dpi::Size::Physical(new_size));
|
||||
self.handle_single_event_sync(
|
||||
Event::WindowEvent {
|
||||
window_id: id,
|
||||
|
|
@ -431,7 +442,10 @@ impl<T: 'static> Shared<T> {
|
|||
ControlFlow::Poll => {
|
||||
let cloned = self.clone();
|
||||
State::Poll {
|
||||
request: backend::AnimationFrameRequest::new(move || cloned.poll()),
|
||||
request: backend::AnimationFrameRequest::new(
|
||||
self.window().clone(),
|
||||
move || cloned.poll(),
|
||||
),
|
||||
}
|
||||
}
|
||||
ControlFlow::Wait => State::Wait {
|
||||
|
|
@ -452,6 +466,7 @@ impl<T: 'static> Shared<T> {
|
|||
start,
|
||||
end,
|
||||
timeout: backend::Timeout::new(
|
||||
self.window().clone(),
|
||||
move || cloned.resume_time_reached(start, end),
|
||||
delay,
|
||||
),
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@ use std::clone::Clone;
|
|||
use std::collections::{vec_deque::IntoIter as VecDequeIter, VecDeque};
|
||||
use std::iter;
|
||||
use std::rc::Rc;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::Arc;
|
||||
|
||||
use raw_window_handle::{RawDisplayHandle, WebDisplayHandle};
|
||||
|
||||
|
|
@ -84,7 +86,7 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
canvas: &Rc<RefCell<backend::Canvas>>,
|
||||
id: WindowId,
|
||||
prevent_default: bool,
|
||||
has_focus: Rc<Cell<bool>>,
|
||||
has_focus: Arc<AtomicBool>,
|
||||
) {
|
||||
self.runner.add_canvas(RootWindowId(id), canvas);
|
||||
let mut canvas = canvas.borrow_mut();
|
||||
|
|
@ -96,7 +98,7 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
let has_focus_clone = has_focus.clone();
|
||||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_blur(move || {
|
||||
has_focus_clone.set(false);
|
||||
has_focus_clone.store(false, Ordering::Relaxed);
|
||||
|
||||
let clear_modifiers = (!modifiers.get().is_empty()).then(|| {
|
||||
modifiers.set(ModifiersState::empty());
|
||||
|
|
@ -119,7 +121,7 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
let runner = self.runner.clone();
|
||||
let has_focus_clone = has_focus.clone();
|
||||
canvas.on_focus(move || {
|
||||
if !has_focus_clone.replace(true) {
|
||||
if !has_focus_clone.swap(true, Ordering::Relaxed) {
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Focused(true),
|
||||
|
|
@ -204,7 +206,7 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers| {
|
||||
if has_focus.get() && modifiers.get() != active_modifiers {
|
||||
if has_focus.load(Ordering::Relaxed) && modifiers.get() != active_modifiers {
|
||||
modifiers.set(active_modifiers);
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
|
|
@ -234,7 +236,7 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers| {
|
||||
if has_focus.get() && modifiers.get() != active_modifiers {
|
||||
if has_focus.load(Ordering::Relaxed) && modifiers.get() != active_modifiers {
|
||||
modifiers.set(active_modifiers);
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
|
|
@ -264,7 +266,7 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers| {
|
||||
if has_focus.get() && modifiers.get() != active_modifiers {
|
||||
if has_focus.load(Ordering::Relaxed) && modifiers.get() != active_modifiers {
|
||||
modifiers.set(active_modifiers);
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
|
|
@ -419,7 +421,7 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
let modifiers = self.modifiers.clone();
|
||||
|
||||
move |active_modifiers| {
|
||||
if has_focus.get() && modifiers.get() != active_modifiers {
|
||||
if has_focus.load(Ordering::Relaxed) && modifiers.get() != active_modifiers {
|
||||
modifiers.set(active_modifiers);
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
|
|
@ -476,7 +478,8 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
let modifiers = self.modifiers.clone();
|
||||
canvas.on_mouse_wheel(
|
||||
move |pointer_id, delta, active_modifiers| {
|
||||
let modifiers_changed = (has_focus.get() && modifiers.get() != active_modifiers)
|
||||
let modifiers_changed = (has_focus.load(Ordering::Relaxed)
|
||||
&& modifiers.get() != active_modifiers)
|
||||
.then(|| {
|
||||
modifiers.set(active_modifiers);
|
||||
Event::WindowEvent {
|
||||
|
|
@ -507,26 +510,30 @@ impl<T> EventLoopWindowTarget<T> {
|
|||
width: raw.width(),
|
||||
height: raw.height(),
|
||||
};
|
||||
canvas.on_fullscreen_change(move || {
|
||||
// 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(),
|
||||
|
||||
canvas.on_fullscreen_change({
|
||||
let window = self.runner.window().clone();
|
||||
move || {
|
||||
// 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(&window, &raw) {
|
||||
intended_size = PhysicalSize {
|
||||
width: raw.width(),
|
||||
height: raw.height(),
|
||||
};
|
||||
|
||||
backend::window_size(&window).to_physical(backend::scale_factor(&window))
|
||||
} else {
|
||||
intended_size
|
||||
};
|
||||
|
||||
backend::window_size().to_physical(backend::scale_factor())
|
||||
} else {
|
||||
intended_size
|
||||
};
|
||||
|
||||
backend::set_canvas_size(&raw, Size::Physical(new_size));
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Resized(new_size),
|
||||
});
|
||||
runner.request_redraw(RootWindowId(id));
|
||||
backend::set_canvas_size(&window, &raw, Size::Physical(new_size));
|
||||
runner.send_event(Event::WindowEvent {
|
||||
window_id: RootWindowId(id),
|
||||
event: WindowEvent::Resized(new_size),
|
||||
});
|
||||
runner.request_redraw(RootWindowId(id));
|
||||
}
|
||||
});
|
||||
|
||||
let runner = self.runner.clone();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue