diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index dbd867268f..d0b7f5d37b 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -1,4 +1,3 @@ -use std::iter; use std::marker::PhantomData; use std::sync::mpsc::{self, Receiver, Sender}; @@ -6,7 +5,6 @@ use crate::error::EventLoopError; use crate::event::Event; use crate::event_loop::EventLoopWindowTarget as RootEventLoopWindowTarget; -use super::r#async::WakerSpawner; use super::{backend, device, window}; mod proxy; @@ -19,7 +17,6 @@ pub use window_target::EventLoopWindowTarget; pub struct EventLoop { elw: RootEventLoopWindowTarget, - proxy_spawner: WakerSpawner, user_event_sender: Sender, user_event_receiver: Receiver, } @@ -34,13 +31,8 @@ impl EventLoop { p: EventLoopWindowTarget::new(), _marker: PhantomData, }; - let proxy_spawner = WakerSpawner::new(elw.p.runner.clone(), |runner, count| { - runner.send_events(iter::repeat(Event::UserEvent(())).take(count)) - }) - .expect("`EventLoop` has to be created in the main thread"); Ok(EventLoop { elw, - proxy_spawner, user_event_sender, user_event_receiver, }) @@ -110,7 +102,7 @@ impl EventLoop { } pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy::new(self.proxy_spawner.waker(), self.user_event_sender.clone()) + EventLoopProxy::new(self.elw.p.waker(), self.user_event_sender.clone()) } pub fn window_target(&self) -> &RootEventLoopWindowTarget { diff --git a/src/platform_impl/web/event_loop/proxy.rs b/src/platform_impl/web/event_loop/proxy.rs index 072a6aa4b3..691efa32b8 100644 --- a/src/platform_impl/web/event_loop/proxy.rs +++ b/src/platform_impl/web/event_loop/proxy.rs @@ -1,16 +1,17 @@ +use std::rc::Weak; use std::sync::mpsc::{SendError, Sender}; -use super::runner; +use super::runner::Execution; use crate::event_loop::EventLoopClosed; use crate::platform_impl::platform::r#async::Waker; pub struct EventLoopProxy { - runner: Waker, + runner: Waker>, sender: Sender, } impl EventLoopProxy { - pub fn new(runner: Waker, sender: Sender) -> Self { + pub fn new(runner: Waker>, sender: Sender) -> Self { Self { runner, sender } } diff --git a/src/platform_impl/web/event_loop/runner.rs b/src/platform_impl/web/event_loop/runner.rs index 038cb9baf0..2018ba171d 100644 --- a/src/platform_impl/web/event_loop/runner.rs +++ b/src/platform_impl/web/event_loop/runner.rs @@ -8,6 +8,7 @@ use crate::event::{ use crate::event_loop::{ControlFlow, DeviceEvents}; use crate::platform::web::PollStrategy; use crate::platform_impl::platform::backend::EventListenerHandle; +use crate::platform_impl::platform::r#async::{Waker, WakerSpawner}; use crate::window::WindowId; use std::{ @@ -35,6 +36,7 @@ impl Clone for Shared { type OnEventHandle = RefCell>>; pub struct Execution { + proxy_spawner: WakerSpawner>, control_flow: Cell, poll_strategy: Cell, exit: Cell, @@ -139,30 +141,40 @@ impl Shared { #[allow(clippy::disallowed_methods)] let document = window.document().expect("Failed to obtain document"); - Shared(Rc::new(Execution { - control_flow: Cell::new(ControlFlow::default()), - poll_strategy: Cell::new(PollStrategy::default()), - exit: Cell::new(false), - runner: RefCell::new(RunnerEnum::Pending), - suspended: Cell::new(false), - event_loop_recreation: Cell::new(false), - events: RefCell::new(VecDeque::new()), - window, - document, - id: RefCell::new(0), - all_canvases: RefCell::new(Vec::new()), - redraw_pending: RefCell::new(HashSet::new()), - destroy_pending: RefCell::new(VecDeque::new()), - page_transition_event_handle: RefCell::new(None), - device_events: Cell::default(), - on_mouse_move: RefCell::new(None), - on_wheel: RefCell::new(None), - on_mouse_press: RefCell::new(None), - on_mouse_release: RefCell::new(None), - on_key_press: RefCell::new(None), - on_key_release: RefCell::new(None), - on_visibility_change: RefCell::new(None), - on_touch_end: RefCell::new(None), + Shared(Rc::::new_cyclic(|weak| { + let proxy_spawner = WakerSpawner::new(weak.clone(), |runner, count| { + if let Some(runner) = runner.upgrade() { + Shared(runner).send_events(iter::repeat(Event::UserEvent(())).take(count)) + } + }) + .expect("`EventLoop` has to be created in the main thread"); + + Execution { + proxy_spawner, + control_flow: Cell::new(ControlFlow::default()), + poll_strategy: Cell::new(PollStrategy::default()), + exit: Cell::new(false), + runner: RefCell::new(RunnerEnum::Pending), + suspended: Cell::new(false), + event_loop_recreation: Cell::new(false), + events: RefCell::new(VecDeque::new()), + window, + document, + id: RefCell::new(0), + all_canvases: RefCell::new(Vec::new()), + redraw_pending: RefCell::new(HashSet::new()), + destroy_pending: RefCell::new(VecDeque::new()), + page_transition_event_handle: RefCell::new(None), + device_events: Cell::default(), + on_mouse_move: RefCell::new(None), + on_wheel: RefCell::new(None), + on_mouse_press: RefCell::new(None), + on_mouse_release: RefCell::new(None), + on_key_press: RefCell::new(None), + on_key_release: RefCell::new(None), + on_visibility_change: RefCell::new(None), + on_touch_end: RefCell::new(None), + } })) } @@ -779,6 +791,10 @@ impl Shared { pub(crate) fn poll_strategy(&self) -> PollStrategy { self.0.poll_strategy.get() } + + pub(crate) fn waker(&self) -> Waker> { + self.0.proxy_spawner.waker() + } } pub(crate) enum EventWrapper { diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index 066195de96..3690b33a45 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -3,9 +3,9 @@ use std::clone::Clone; use std::collections::{vec_deque::IntoIter as VecDequeIter, VecDeque}; use std::iter; use std::marker::PhantomData; -use std::rc::Rc; +use std::rc::{Rc, Weak}; -use super::runner::EventWrapper; +use super::runner::{EventWrapper, Execution}; use super::{ super::{monitor::MonitorHandle, KeyEventExtra}, backend, @@ -19,6 +19,7 @@ use crate::event::{ use crate::event_loop::{ControlFlow, DeviceEvents}; use crate::keyboard::ModifiersState; use crate::platform::web::PollStrategy; +use crate::platform_impl::platform::r#async::Waker; use crate::window::{Theme, WindowId as RootWindowId}; #[derive(Default)] @@ -702,4 +703,8 @@ impl EventLoopWindowTarget { pub(crate) fn poll_strategy(&self) -> PollStrategy { self.runner.poll_strategy() } + + pub(crate) fn waker(&self) -> Waker> { + self.runner.waker() + } }