Remove T from EventLoopTargetWindow (#3081)

Co-authored-by: nerditation <12248559+nerditation@users.noreply.github.com>
This commit is contained in:
daxpedda 2023-09-03 02:26:53 +02:00 committed by GitHub
parent d68d9eab38
commit 7a2a2341c2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 78 additions and 48 deletions

View file

@ -1,4 +1,5 @@
use std::marker::PhantomData; use std::marker::PhantomData;
use std::sync::mpsc::{self, Receiver, Sender};
use crate::error::EventLoopError; use crate::error::EventLoopError;
use crate::event::Event; use crate::event::Event;
@ -16,6 +17,8 @@ pub use window_target::EventLoopWindowTarget;
pub struct EventLoop<T: 'static> { pub struct EventLoop<T: 'static> {
elw: RootEventLoopWindowTarget<T>, elw: RootEventLoopWindowTarget<T>,
user_event_sender: Sender<T>,
user_event_receiver: Receiver<T>,
} }
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)]
@ -23,11 +26,14 @@ pub(crate) struct PlatformSpecificEventLoopAttributes {}
impl<T> EventLoop<T> { impl<T> EventLoop<T> {
pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> { pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result<Self, EventLoopError> {
let (user_event_sender, user_event_receiver) = mpsc::channel();
Ok(EventLoop { Ok(EventLoop {
elw: RootEventLoopWindowTarget { elw: RootEventLoopWindowTarget {
p: EventLoopWindowTarget::new(), p: EventLoopWindowTarget::new(),
_marker: PhantomData, _marker: PhantomData,
}, },
user_event_sender,
user_event_receiver,
}) })
} }
@ -41,8 +47,18 @@ impl<T> EventLoop<T> {
}; };
// SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`. // SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`.
let handler: Box<dyn FnMut(_, _)> = let handler: Box<dyn FnMut(Event<()>, _)> = Box::new(|event, flow| {
Box::new(|event, flow| event_handler(event, &target, flow)); let event = match event.map_nonuser_event() {
Ok(event) => event,
Err(Event::UserEvent(())) => Event::UserEvent(
self.user_event_receiver
.try_recv()
.expect("handler woken up without user event"),
),
Err(_) => unreachable!(),
};
event_handler(event, &target, flow)
});
// SAFETY: The `transmute` is necessary because `run()` requires `'static`. This is safe // SAFETY: The `transmute` is necessary because `run()` requires `'static`. This is safe
// because this function will never return and all resources not cleaned up by the point we // because this function will never return and all resources not cleaned up by the point we
// `throw` will leak, making this actually `'static`. // `throw` will leak, making this actually `'static`.
@ -68,13 +84,24 @@ impl<T> EventLoop<T> {
}; };
self.elw.p.run( self.elw.p.run(
Box::new(move |event, flow| event_handler(event, &target, flow)), Box::new(move |event, flow| {
let event = match event.map_nonuser_event() {
Ok(event) => event,
Err(Event::UserEvent(())) => Event::UserEvent(
self.user_event_receiver
.try_recv()
.expect("handler woken up without user event"),
),
Err(_) => unreachable!(),
};
event_handler(event, &target, flow)
}),
true, true,
); );
} }
pub fn create_proxy(&self) -> EventLoopProxy<T> { pub fn create_proxy(&self) -> EventLoopProxy<T> {
self.elw.p.proxy() EventLoopProxy::new(self.elw.p.runner.clone(), self.user_event_sender.clone())
} }
pub fn window_target(&self) -> &RootEventLoopWindowTarget<T> { pub fn window_target(&self) -> &RootEventLoopWindowTarget<T> {

View file

@ -1,24 +1,30 @@
use std::sync::mpsc::Sender;
use super::runner; use super::runner;
use crate::event::Event; use crate::event::Event;
use crate::event_loop::EventLoopClosed; use crate::event_loop::EventLoopClosed;
use crate::platform_impl::platform::r#async::Channel; use crate::platform_impl::platform::r#async::Channel;
pub struct EventLoopProxy<T: 'static> { pub struct EventLoopProxy<T: 'static> {
runner: Channel<runner::Shared<T>, T>, // used to wake the event loop handler, not to actually pass data
runner: Channel<runner::Shared, ()>,
sender: Sender<T>,
} }
impl<T: 'static> EventLoopProxy<T> { impl<T: 'static> EventLoopProxy<T> {
pub fn new(runner: runner::Shared<T>) -> Self { pub fn new(runner: runner::Shared, sender: Sender<T>) -> Self {
Self { Self {
runner: Channel::new(runner, |runner, event| { runner: Channel::new(runner, |runner, event| {
runner.send_event(Event::UserEvent(event)) runner.send_event(Event::UserEvent(event))
}) })
.unwrap(), .unwrap(),
sender,
} }
} }
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> { pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
self.runner.send(event); self.sender.send(event).unwrap();
self.runner.send(());
Ok(()) Ok(())
} }
} }
@ -27,6 +33,7 @@ impl<T: 'static> Clone for EventLoopProxy<T> {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
runner: self.runner.clone(), runner: self.runner.clone(),
sender: self.sender.clone(),
} }
} }
} }

View file

@ -22,11 +22,11 @@ use wasm_bindgen::prelude::Closure;
use web_sys::{Document, KeyboardEvent, PageTransitionEvent, PointerEvent, WheelEvent}; use web_sys::{Document, KeyboardEvent, PageTransitionEvent, PointerEvent, WheelEvent};
use web_time::{Duration, Instant}; use web_time::{Duration, Instant};
pub struct Shared<T: 'static>(Rc<Execution<T>>); pub struct Shared(Rc<Execution>);
pub(super) type EventHandler<T> = dyn FnMut(Event<T>, &mut ControlFlow); pub(super) type EventHandler = dyn FnMut(Event<()>, &mut ControlFlow);
impl<T> Clone for Shared<T> { impl Clone for Shared {
fn clone(&self) -> Self { fn clone(&self) -> Self {
Shared(self.0.clone()) Shared(self.0.clone())
} }
@ -34,11 +34,11 @@ impl<T> Clone for Shared<T> {
type OnEventHandle<T> = RefCell<Option<EventListenerHandle<dyn FnMut(T)>>>; type OnEventHandle<T> = RefCell<Option<EventListenerHandle<dyn FnMut(T)>>>;
pub struct Execution<T: 'static> { pub struct Execution {
runner: RefCell<RunnerEnum<T>>, runner: RefCell<RunnerEnum>,
suspended: Cell<bool>, suspended: Cell<bool>,
event_loop_recreation: Cell<bool>, event_loop_recreation: Cell<bool>,
events: RefCell<VecDeque<EventWrapper<T>>>, events: RefCell<VecDeque<EventWrapper>>,
id: RefCell<u32>, id: RefCell<u32>,
window: web_sys::Window, window: web_sys::Window,
document: Document, document: Document,
@ -57,19 +57,19 @@ pub struct Execution<T: 'static> {
on_touch_end: OnEventHandle<web_sys::Event>, on_touch_end: OnEventHandle<web_sys::Event>,
} }
enum RunnerEnum<T: 'static> { enum RunnerEnum {
/// The `EventLoop` is created but not being run. /// The `EventLoop` is created but not being run.
Pending, Pending,
/// The `EventLoop` is being run. /// The `EventLoop` is being run.
Running(Runner<T>), Running(Runner),
/// The `EventLoop` is exited after being started with `EventLoop::run`. Since /// The `EventLoop` is exited after being started with `EventLoop::run`. Since
/// `EventLoop::run` takes ownership of the `EventLoop`, we can be certain /// `EventLoop::run` takes ownership of the `EventLoop`, we can be certain
/// that this event loop will never be run again. /// that this event loop will never be run again.
Destroyed, Destroyed,
} }
impl<T: 'static> RunnerEnum<T> { impl RunnerEnum {
fn maybe_runner(&self) -> Option<&Runner<T>> { fn maybe_runner(&self) -> Option<&Runner> {
match self { match self {
RunnerEnum::Running(runner) => Some(runner), RunnerEnum::Running(runner) => Some(runner),
_ => None, _ => None,
@ -77,13 +77,13 @@ impl<T: 'static> RunnerEnum<T> {
} }
} }
struct Runner<T: 'static> { struct Runner {
state: State, state: State,
event_handler: Box<EventHandler<T>>, event_handler: Box<EventHandler>,
} }
impl<T: 'static> Runner<T> { impl Runner {
pub fn new(event_handler: Box<EventHandler<T>>) -> Self { pub fn new(event_handler: Box<EventHandler>) -> Self {
Runner { Runner {
state: State::Init, state: State::Init,
event_handler, event_handler,
@ -110,8 +110,8 @@ impl<T: 'static> Runner<T> {
fn handle_single_event( fn handle_single_event(
&mut self, &mut self,
runner: &Shared<T>, runner: &Shared,
event: impl Into<EventWrapper<T>>, event: impl Into<EventWrapper>,
control: &mut ControlFlow, control: &mut ControlFlow,
) { ) {
let is_closed = matches!(*control, ControlFlow::ExitWithCode(_)); let is_closed = matches!(*control, ControlFlow::ExitWithCode(_));
@ -141,7 +141,7 @@ impl<T: 'static> Runner<T> {
} }
} }
impl<T: 'static> Shared<T> { impl Shared {
pub fn new() -> Self { pub fn new() -> Self {
#[allow(clippy::disallowed_methods)] #[allow(clippy::disallowed_methods)]
let window = web_sys::window().expect("only callable from inside the `Window`"); let window = web_sys::window().expect("only callable from inside the `Window`");
@ -194,7 +194,7 @@ impl<T: 'static> Shared<T> {
// Set the event callback to use for the event loop runner // Set the event callback to use for the event loop runner
// This the event callback is a fairly thin layer over the user-provided callback that closes // This the event callback is a fairly thin layer over the user-provided callback that closes
// over a RootEventLoopWindowTarget reference // over a RootEventLoopWindowTarget reference
pub fn set_listener(&self, event_handler: Box<EventHandler<T>>) { pub fn set_listener(&self, event_handler: Box<EventHandler>) {
{ {
let mut runner = self.0.runner.borrow_mut(); let mut runner = self.0.runner.borrow_mut();
assert!(matches!(*runner, RunnerEnum::Pending)); assert!(matches!(*runner, RunnerEnum::Pending));
@ -457,7 +457,7 @@ impl<T: 'static> Shared<T> {
pub fn request_redraw(&self, id: WindowId) { pub fn request_redraw(&self, id: WindowId) {
self.0.redraw_pending.borrow_mut().insert(id); self.0.redraw_pending.borrow_mut().insert(id);
self.send_events::<EventWrapper<T>>(iter::empty()); self.send_events::<EventWrapper>(iter::empty());
} }
pub fn init(&self) { pub fn init(&self) {
@ -485,17 +485,14 @@ impl<T: 'static> Shared<T> {
// Add an event to the event loop runner, from the user or an event handler // Add an event to the event loop runner, from the user or an event handler
// //
// It will determine if the event should be immediately sent to the user or buffered for later // It will determine if the event should be immediately sent to the user or buffered for later
pub(crate) fn send_event<E: Into<EventWrapper<T>>>(&self, event: E) { pub(crate) fn send_event<E: Into<EventWrapper>>(&self, event: E) {
self.send_events(iter::once(event)); self.send_events(iter::once(event));
} }
// Add a series of events to the event loop runner // Add a series of events to the event loop runner
// //
// It will determine if the event should be immediately sent to the user or buffered for later // It will determine if the event should be immediately sent to the user or buffered for later
pub(crate) fn send_events<E: Into<EventWrapper<T>>>( pub(crate) fn send_events<E: Into<EventWrapper>>(&self, events: impl IntoIterator<Item = E>) {
&self,
events: impl IntoIterator<Item = E>,
) {
// If the event loop is closed, it should discard any new events // If the event loop is closed, it should discard any new events
if self.is_closed() { if self.is_closed() {
return; return;
@ -573,7 +570,7 @@ impl<T: 'static> Shared<T> {
// cleared // cleared
// //
// This will also process any events that have been queued or that are queued during processing // This will also process any events that have been queued or that are queued during processing
fn run_until_cleared<E: Into<EventWrapper<T>>>(&self, events: impl Iterator<Item = E>) { fn run_until_cleared<E: Into<EventWrapper>>(&self, events: impl Iterator<Item = E>) {
let mut control = self.current_control_flow(); let mut control = self.current_control_flow();
for event in events { for event in events {
self.handle_event(event.into(), &mut control); self.handle_event(event.into(), &mut control);
@ -613,7 +610,7 @@ impl<T: 'static> Shared<T> {
// handle_event takes in events and either queues them or applies a callback // handle_event takes in events and either queues them or applies a callback
// //
// It should only ever be called from `run_until_cleared`. // It should only ever be called from `run_until_cleared`.
fn handle_event(&self, event: impl Into<EventWrapper<T>>, control: &mut ControlFlow) { fn handle_event(&self, event: impl Into<EventWrapper>, control: &mut ControlFlow) {
if self.is_closed() { if self.is_closed() {
*control = ControlFlow::Exit; *control = ControlFlow::Exit;
} }
@ -721,7 +718,7 @@ impl<T: 'static> Shared<T> {
// * The `register_redraw_request` closure. // * The `register_redraw_request` closure.
// * The `destroy_fn` closure. // * The `destroy_fn` closure.
if self.0.event_loop_recreation.get() { if self.0.event_loop_recreation.get() {
crate::event_loop::EventLoopBuilder::<T>::allow_event_loop_recreation(); crate::event_loop::EventLoopBuilder::<()>::allow_event_loop_recreation();
} }
} }
@ -779,8 +776,8 @@ impl<T: 'static> Shared<T> {
} }
} }
pub(crate) enum EventWrapper<T: 'static> { pub(crate) enum EventWrapper {
Event(Event<T>), Event(Event<()>),
ScaleChange { ScaleChange {
canvas: Weak<RefCell<backend::Canvas>>, canvas: Weak<RefCell<backend::Canvas>>,
size: PhysicalSize<u32>, size: PhysicalSize<u32>,
@ -788,8 +785,8 @@ pub(crate) enum EventWrapper<T: 'static> {
}, },
} }
impl<T> From<Event<T>> for EventWrapper<T> { impl From<Event<()>> for EventWrapper {
fn from(value: Event<T>) -> Self { fn from(value: Event<()>) -> Self {
Self::Event(value) Self::Event(value)
} }
} }

View file

@ -2,6 +2,7 @@ use std::cell::{Cell, RefCell};
use std::clone::Clone; use std::clone::Clone;
use std::collections::{vec_deque::IntoIter as VecDequeIter, VecDeque}; use std::collections::{vec_deque::IntoIter as VecDequeIter, VecDeque};
use std::iter; use std::iter;
use std::marker::PhantomData;
use std::rc::Rc; use std::rc::Rc;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
@ -12,7 +13,6 @@ use super::{
super::{monitor::MonitorHandle, KeyEventExtra}, super::{monitor::MonitorHandle, KeyEventExtra},
backend, backend,
device::DeviceId, device::DeviceId,
proxy::EventLoopProxy,
runner, runner,
window::WindowId, window::WindowId,
}; };
@ -43,8 +43,9 @@ impl Clone for ModifiersShared {
} }
pub struct EventLoopWindowTarget<T: 'static> { pub struct EventLoopWindowTarget<T: 'static> {
pub(crate) runner: runner::Shared<T>, pub(crate) runner: runner::Shared,
modifiers: ModifiersShared, modifiers: ModifiersShared,
_marker: PhantomData<T>,
} }
impl<T> Clone for EventLoopWindowTarget<T> { impl<T> Clone for EventLoopWindowTarget<T> {
@ -52,6 +53,7 @@ impl<T> Clone for EventLoopWindowTarget<T> {
Self { Self {
runner: self.runner.clone(), runner: self.runner.clone(),
modifiers: self.modifiers.clone(), modifiers: self.modifiers.clone(),
_marker: PhantomData,
} }
} }
} }
@ -61,14 +63,11 @@ impl<T> EventLoopWindowTarget<T> {
Self { Self {
runner: runner::Shared::new(), runner: runner::Shared::new(),
modifiers: ModifiersShared::default(), modifiers: ModifiersShared::default(),
_marker: PhantomData,
} }
} }
pub fn proxy(&self) -> EventLoopProxy<T> { pub fn run(&self, event_handler: Box<runner::EventHandler>, event_loop_recreation: bool) {
EventLoopProxy::new(self.runner.clone())
}
pub fn run(&self, event_handler: Box<runner::EventHandler<T>>, event_loop_recreation: bool) {
self.runner.event_loop_recreation(event_loop_recreation); self.runner.event_loop_recreation(event_loop_recreation);
self.runner.set_listener(event_handler); self.runner.set_listener(event_handler);
} }

View file

@ -463,10 +463,10 @@ impl Canvas {
self.animation_frame_handler.request(); self.animation_frame_handler.request();
} }
pub(crate) fn handle_scale_change<T: 'static>( pub(crate) fn handle_scale_change(
&self, &self,
runner: &super::super::event_loop::runner::Shared<T>, runner: &super::super::event_loop::runner::Shared,
event_handler: impl FnOnce(crate::event::Event<T>), event_handler: impl FnOnce(crate::event::Event<()>),
current_size: PhysicalSize<u32>, current_size: PhysicalSize<u32>,
scale: f64, scale: f64,
) { ) {