2020-08-30 21:15:44 +08:00
|
|
|
use super::{super::ScaleChangeArgs, backend, state::State};
|
2019-12-03 18:16:06 +01:00
|
|
|
use crate::event::{Event, StartCause};
|
2022-03-18 14:09:39 +01:00
|
|
|
use crate::event_loop::ControlFlow;
|
2019-09-23 09:14:26 -04:00
|
|
|
use crate::window::WindowId;
|
2019-06-25 03:15:34 +02:00
|
|
|
|
|
|
|
|
use instant::{Duration, Instant};
|
2019-09-23 09:14:26 -04:00
|
|
|
use std::{
|
|
|
|
|
cell::RefCell,
|
|
|
|
|
clone::Clone,
|
|
|
|
|
collections::{HashSet, VecDeque},
|
2020-01-25 19:04:03 -05:00
|
|
|
iter,
|
2020-09-22 06:19:00 +08:00
|
|
|
ops::Deref,
|
2020-09-21 06:42:07 +08:00
|
|
|
rc::{Rc, Weak},
|
2019-09-23 09:14:26 -04:00
|
|
|
};
|
2019-06-25 03:15:34 +02:00
|
|
|
|
2019-12-31 14:39:33 -08:00
|
|
|
pub struct Shared<T: 'static>(Rc<Execution<T>>);
|
2019-06-25 03:15:34 +02:00
|
|
|
|
|
|
|
|
impl<T> Clone for Shared<T> {
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
Shared(self.0.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-12-31 14:39:33 -08:00
|
|
|
pub struct Execution<T: 'static> {
|
2020-09-21 06:42:07 +08:00
|
|
|
runner: RefCell<RunnerEnum<T>>,
|
2019-12-31 14:39:33 -08:00
|
|
|
events: RefCell<VecDeque<Event<'static, T>>>,
|
2019-09-19 18:40:18 -04:00
|
|
|
id: RefCell<u32>,
|
2020-09-21 06:42:07 +08:00
|
|
|
all_canvases: RefCell<Vec<(WindowId, Weak<RefCell<backend::Canvas>>)>>,
|
2019-09-23 09:14:26 -04:00
|
|
|
redraw_pending: RefCell<HashSet<WindowId>>,
|
2020-09-21 06:42:07 +08:00
|
|
|
destroy_pending: RefCell<VecDeque<WindowId>>,
|
2020-08-30 21:15:44 +08:00
|
|
|
scale_change_detector: RefCell<Option<backend::ScaleChangeDetector>>,
|
2020-09-21 06:42:07 +08:00
|
|
|
unload_event_handle: RefCell<Option<backend::UnloadEventHandle>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum RunnerEnum<T: 'static> {
|
|
|
|
|
/// The `EventLoop` is created but not being run.
|
|
|
|
|
Pending,
|
|
|
|
|
/// The `EventLoop` is being run.
|
|
|
|
|
Running(Runner<T>),
|
|
|
|
|
/// The `EventLoop` is exited after being started with `EventLoop::run`. Since
|
|
|
|
|
/// `EventLoop::run` takes ownership of the `EventLoop`, we can be certain
|
|
|
|
|
/// that this event loop will never be run again.
|
|
|
|
|
Destroyed,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: 'static> RunnerEnum<T> {
|
|
|
|
|
fn maybe_runner(&self) -> Option<&Runner<T>> {
|
|
|
|
|
match self {
|
|
|
|
|
RunnerEnum::Running(runner) => Some(runner),
|
|
|
|
|
_ => None,
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-31 14:39:33 -08:00
|
|
|
struct Runner<T: 'static> {
|
2019-06-25 03:15:34 +02:00
|
|
|
state: State,
|
2022-03-18 14:09:39 +01:00
|
|
|
event_handler: Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>,
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: 'static> Runner<T> {
|
2022-03-18 14:09:39 +01:00
|
|
|
pub fn new(event_handler: Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>) -> Self {
|
2019-06-25 03:15:34 +02:00
|
|
|
Runner {
|
|
|
|
|
state: State::Init,
|
|
|
|
|
event_handler,
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-08-30 21:15:44 +08:00
|
|
|
|
|
|
|
|
/// Returns the cooresponding `StartCause` for the current `state`, or `None`
|
|
|
|
|
/// when in `Exit` state.
|
|
|
|
|
fn maybe_start_cause(&self) -> Option<StartCause> {
|
|
|
|
|
Some(match self.state {
|
|
|
|
|
State::Init => StartCause::Init,
|
|
|
|
|
State::Poll { .. } => StartCause::Poll,
|
|
|
|
|
State::Wait { start } => StartCause::WaitCancelled {
|
|
|
|
|
start,
|
|
|
|
|
requested_resume: None,
|
|
|
|
|
},
|
|
|
|
|
State::WaitUntil { start, end, .. } => StartCause::WaitCancelled {
|
|
|
|
|
start,
|
|
|
|
|
requested_resume: Some(end),
|
|
|
|
|
},
|
|
|
|
|
State::Exit => return None,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-18 14:09:39 +01:00
|
|
|
fn handle_single_event(&mut self, event: Event<'_, T>, control: &mut ControlFlow) {
|
|
|
|
|
let is_closed = matches!(*control, ControlFlow::ExitWithCode(_));
|
2020-08-30 21:15:44 +08:00
|
|
|
|
|
|
|
|
(self.event_handler)(event, control);
|
|
|
|
|
|
|
|
|
|
// Maintain closed state, even if the callback changes it
|
|
|
|
|
if is_closed {
|
2022-03-18 14:09:39 +01:00
|
|
|
*control = ControlFlow::Exit;
|
2020-08-30 21:15:44 +08:00
|
|
|
}
|
|
|
|
|
}
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: 'static> Shared<T> {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
Shared(Rc::new(Execution {
|
2020-09-21 06:42:07 +08:00
|
|
|
runner: RefCell::new(RunnerEnum::Pending),
|
2019-06-25 03:15:34 +02:00
|
|
|
events: RefCell::new(VecDeque::new()),
|
2019-09-19 18:40:18 -04:00
|
|
|
id: RefCell::new(0),
|
2020-08-30 21:15:44 +08:00
|
|
|
all_canvases: RefCell::new(Vec::new()),
|
2019-09-23 09:14:26 -04:00
|
|
|
redraw_pending: RefCell::new(HashSet::new()),
|
2020-09-21 06:42:07 +08:00
|
|
|
destroy_pending: RefCell::new(VecDeque::new()),
|
2020-08-30 21:15:44 +08:00
|
|
|
scale_change_detector: RefCell::new(None),
|
2020-09-21 06:42:07 +08:00
|
|
|
unload_event_handle: RefCell::new(None),
|
2019-06-25 03:15:34 +02:00
|
|
|
}))
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 06:42:07 +08:00
|
|
|
pub fn add_canvas(&self, id: WindowId, canvas: &Rc<RefCell<backend::Canvas>>) {
|
|
|
|
|
self.0
|
|
|
|
|
.all_canvases
|
|
|
|
|
.borrow_mut()
|
|
|
|
|
.push((id, Rc::downgrade(canvas)));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn notify_destroy_window(&self, id: WindowId) {
|
|
|
|
|
self.0.destroy_pending.borrow_mut().push_back(id);
|
2020-08-30 21:15:44 +08:00
|
|
|
}
|
|
|
|
|
|
2019-06-25 03:15:34 +02:00
|
|
|
// 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
|
|
|
|
|
// over a RootEventLoopWindowTarget reference
|
2022-03-18 14:09:39 +01:00
|
|
|
pub fn set_listener(&self, event_handler: Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>) {
|
2020-09-21 06:42:07 +08:00
|
|
|
{
|
|
|
|
|
let mut runner = self.0.runner.borrow_mut();
|
|
|
|
|
assert!(matches!(*runner, RunnerEnum::Pending));
|
|
|
|
|
*runner = RunnerEnum::Running(Runner::new(event_handler));
|
|
|
|
|
}
|
2020-01-25 19:04:03 -05:00
|
|
|
self.init();
|
2019-09-11 11:47:03 -04:00
|
|
|
|
|
|
|
|
let close_instance = self.clone();
|
2020-09-21 06:42:07 +08:00
|
|
|
*self.0.unload_event_handle.borrow_mut() =
|
|
|
|
|
Some(backend::on_unload(move || close_instance.handle_unload()));
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2020-08-30 21:15:44 +08:00
|
|
|
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));
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-19 18:40:18 -04:00
|
|
|
// Generate a strictly increasing ID
|
|
|
|
|
// This is used to differentiate windows when handling events
|
|
|
|
|
pub fn generate_id(&self) -> u32 {
|
|
|
|
|
let mut id = self.0.id.borrow_mut();
|
|
|
|
|
*id += 1;
|
|
|
|
|
|
|
|
|
|
*id
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-23 09:14:26 -04:00
|
|
|
pub fn request_redraw(&self, id: WindowId) {
|
|
|
|
|
self.0.redraw_pending.borrow_mut().insert(id);
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-25 19:04:03 -05:00
|
|
|
pub fn init(&self) {
|
|
|
|
|
let start_cause = Event::NewEvents(StartCause::Init);
|
|
|
|
|
self.run_until_cleared(iter::once(start_cause));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Run the polling logic for the Poll ControlFlow, which involves clearing the queue
|
|
|
|
|
pub fn poll(&self) {
|
|
|
|
|
let start_cause = Event::NewEvents(StartCause::Poll);
|
|
|
|
|
self.run_until_cleared(iter::once(start_cause));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Run the logic for waking from a WaitUntil, which involves clearing the queue
|
|
|
|
|
// Generally there shouldn't be events built up when this is called
|
|
|
|
|
pub fn resume_time_reached(&self, start: Instant, requested_resume: Instant) {
|
|
|
|
|
let start_cause = Event::NewEvents(StartCause::ResumeTimeReached {
|
|
|
|
|
start,
|
|
|
|
|
requested_resume,
|
|
|
|
|
});
|
|
|
|
|
self.run_until_cleared(iter::once(start_cause));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add an event to the event loop runner, from the user or an event handler
|
2019-06-25 03:15:34 +02:00
|
|
|
//
|
|
|
|
|
// It will determine if the event should be immediately sent to the user or buffered for later
|
2019-12-31 14:39:33 -08:00
|
|
|
pub fn send_event(&self, event: Event<'static, T>) {
|
2020-01-25 19:04:03 -05:00
|
|
|
self.send_events(iter::once(event));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
pub fn send_events(&self, events: impl Iterator<Item = Event<'static, T>>) {
|
2019-06-25 03:15:34 +02:00
|
|
|
// If the event loop is closed, it should discard any new events
|
2019-06-25 18:07:47 +02:00
|
|
|
if self.is_closed() {
|
2019-06-25 03:15:34 +02:00
|
|
|
return;
|
|
|
|
|
}
|
2020-01-25 19:04:03 -05:00
|
|
|
// If we can run the event processing right now, or need to queue this and wait for later
|
|
|
|
|
let mut process_immediately = true;
|
2020-09-22 06:19:00 +08:00
|
|
|
match self.0.runner.try_borrow().as_ref().map(Deref::deref) {
|
|
|
|
|
Ok(RunnerEnum::Running(ref runner)) => {
|
2020-09-21 06:42:07 +08:00
|
|
|
// If we're currently polling, queue this and wait for the poll() method to be called
|
|
|
|
|
if let State::Poll { .. } = runner.state {
|
|
|
|
|
process_immediately = false;
|
|
|
|
|
}
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
2020-09-22 06:19:00 +08:00
|
|
|
Ok(RunnerEnum::Pending) => {
|
2020-09-21 06:42:07 +08:00
|
|
|
// The runner still hasn't been attached: queue this event and wait for it to be
|
2020-01-25 19:04:03 -05:00
|
|
|
process_immediately = false;
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
2020-09-22 06:19:00 +08:00
|
|
|
// Some other code is mutating the runner, which most likely means
|
|
|
|
|
// the event loop is running and busy. So we queue this event for
|
|
|
|
|
// it to be processed later.
|
|
|
|
|
Err(_) => {
|
|
|
|
|
process_immediately = false;
|
|
|
|
|
}
|
2020-09-21 06:42:07 +08:00
|
|
|
// This is unreachable since `self.is_closed() == true`.
|
2020-09-22 06:19:00 +08:00
|
|
|
Ok(RunnerEnum::Destroyed) => unreachable!(),
|
2020-01-25 19:04:03 -05:00
|
|
|
}
|
|
|
|
|
if !process_immediately {
|
|
|
|
|
// Queue these events to look at later
|
|
|
|
|
self.0.events.borrow_mut().extend(events);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
// At this point, we know this is a fresh set of events
|
|
|
|
|
// Now we determine why new events are incoming, and handle the events
|
2020-09-21 06:42:07 +08:00
|
|
|
let start_cause = match (self.0.runner.borrow().maybe_runner())
|
2020-08-30 21:15:44 +08:00
|
|
|
.unwrap_or_else(|| {
|
|
|
|
|
unreachable!("The runner cannot process events when it is not attached")
|
|
|
|
|
})
|
|
|
|
|
.maybe_start_cause()
|
|
|
|
|
{
|
|
|
|
|
Some(c) => c,
|
|
|
|
|
// If we're in the exit state, don't do event processing
|
|
|
|
|
None => return,
|
2019-06-25 03:15:34 +02:00
|
|
|
};
|
2020-01-25 19:04:03 -05:00
|
|
|
// Take the start event, then the events provided to this function, and run an iteration of
|
|
|
|
|
// the event loop
|
|
|
|
|
let start_event = Event::NewEvents(start_cause);
|
|
|
|
|
let events = iter::once(start_event).chain(events);
|
|
|
|
|
self.run_until_cleared(events);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 06:42:07 +08:00
|
|
|
// Process the destroy-pending windows. This should only be called from
|
|
|
|
|
// `run_until_cleared` and `handle_scale_changed`, somewhere between emitting
|
|
|
|
|
// `NewEvents` and `MainEventsCleared`.
|
2022-03-18 14:09:39 +01:00
|
|
|
fn process_destroy_pending_windows(&self, control: &mut ControlFlow) {
|
2020-09-21 06:42:07 +08:00
|
|
|
while let Some(id) = self.0.destroy_pending.borrow_mut().pop_front() {
|
|
|
|
|
self.0
|
|
|
|
|
.all_canvases
|
|
|
|
|
.borrow_mut()
|
|
|
|
|
.retain(|&(item_id, _)| item_id != id);
|
|
|
|
|
self.handle_event(
|
|
|
|
|
Event::WindowEvent {
|
|
|
|
|
window_id: id,
|
|
|
|
|
event: crate::event::WindowEvent::Destroyed,
|
|
|
|
|
},
|
|
|
|
|
control,
|
|
|
|
|
);
|
|
|
|
|
self.0.redraw_pending.borrow_mut().remove(&id);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-01-25 19:04:03 -05:00
|
|
|
// Given the set of new events, run the event loop until the main events and redraw events are
|
|
|
|
|
// cleared
|
|
|
|
|
//
|
|
|
|
|
// This will also process any events that have been queued or that are queued during processing
|
|
|
|
|
fn run_until_cleared(&self, events: impl Iterator<Item = Event<'static, T>>) {
|
2019-06-25 03:15:34 +02:00
|
|
|
let mut control = self.current_control_flow();
|
2020-01-25 19:04:03 -05:00
|
|
|
for event in events {
|
2019-06-25 03:15:34 +02:00
|
|
|
self.handle_event(event, &mut control);
|
|
|
|
|
}
|
2020-09-21 06:42:07 +08:00
|
|
|
self.process_destroy_pending_windows(&mut control);
|
2019-12-03 18:16:06 +01:00
|
|
|
self.handle_event(Event::MainEventsCleared, &mut control);
|
|
|
|
|
|
2019-09-23 09:14:26 -04:00
|
|
|
// Collect all of the redraw events to avoid double-locking the RefCell
|
|
|
|
|
let redraw_events: Vec<WindowId> = self.0.redraw_pending.borrow_mut().drain().collect();
|
|
|
|
|
for window_id in redraw_events {
|
2019-12-03 18:16:06 +01:00
|
|
|
self.handle_event(Event::RedrawRequested(window_id), &mut control);
|
2019-09-23 09:14:26 -04:00
|
|
|
}
|
2019-12-03 18:16:06 +01:00
|
|
|
self.handle_event(Event::RedrawEventsCleared, &mut control);
|
|
|
|
|
|
2019-06-25 03:15:34 +02:00
|
|
|
self.apply_control_flow(control);
|
|
|
|
|
// If the event loop is closed, it has been closed this iteration and now the closing
|
|
|
|
|
// event should be emitted
|
2019-06-25 18:07:47 +02:00
|
|
|
if self.is_closed() {
|
2020-09-21 06:42:07 +08:00
|
|
|
self.handle_loop_destroyed(&mut control);
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-30 21:15:44 +08:00
|
|
|
pub fn handle_scale_changed(&self, old_scale: f64, new_scale: f64) {
|
2020-09-21 06:42:07 +08:00
|
|
|
// If there aren't any windows, then there is nothing to do here.
|
|
|
|
|
if self.0.all_canvases.borrow().is_empty() {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
let start_cause = match (self.0.runner.borrow().maybe_runner())
|
2020-08-30 21:15:44 +08:00
|
|
|
.unwrap_or_else(|| unreachable!("`scale_changed` should not happen without a runner"))
|
|
|
|
|
.maybe_start_cause()
|
|
|
|
|
{
|
|
|
|
|
Some(c) => c,
|
|
|
|
|
// If we're in the exit state, don't do event processing
|
|
|
|
|
None => return,
|
|
|
|
|
};
|
|
|
|
|
let mut control = self.current_control_flow();
|
|
|
|
|
|
|
|
|
|
// Handle the start event and all other events in the queue.
|
|
|
|
|
self.handle_event(Event::NewEvents(start_cause), &mut control);
|
|
|
|
|
|
2020-09-21 06:42:07 +08:00
|
|
|
// It is possible for windows to be dropped before this point. We don't
|
|
|
|
|
// want to send `ScaleFactorChanged` for destroyed windows, so we process
|
|
|
|
|
// the destroy-pending windows here.
|
|
|
|
|
self.process_destroy_pending_windows(&mut control);
|
|
|
|
|
|
2020-08-30 21:15:44 +08:00
|
|
|
// Now handle the `ScaleFactorChanged` events.
|
|
|
|
|
for &(id, ref canvas) in &*self.0.all_canvases.borrow() {
|
2020-09-21 06:42:07 +08:00
|
|
|
let canvas = match canvas.upgrade() {
|
|
|
|
|
Some(rc) => rc.borrow().raw().clone(),
|
|
|
|
|
// This shouldn't happen, but just in case...
|
|
|
|
|
None => continue,
|
|
|
|
|
};
|
2020-08-30 21:15:44 +08:00
|
|
|
// First, we send the `ScaleFactorChanged` event:
|
|
|
|
|
let current_size = crate::dpi::PhysicalSize {
|
|
|
|
|
width: canvas.width() as u32,
|
|
|
|
|
height: canvas.height() as u32,
|
|
|
|
|
};
|
|
|
|
|
let logical_size = current_size.to_logical::<f64>(old_scale);
|
|
|
|
|
let mut new_size = logical_size.to_physical(new_scale);
|
|
|
|
|
self.handle_single_event_sync(
|
|
|
|
|
Event::WindowEvent {
|
|
|
|
|
window_id: id,
|
|
|
|
|
event: crate::event::WindowEvent::ScaleFactorChanged {
|
|
|
|
|
scale_factor: new_scale,
|
|
|
|
|
new_inner_size: &mut new_size,
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
&mut control,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Then we resize the canvas to the new size and send a `Resized` event:
|
2020-09-21 06:42:07 +08:00
|
|
|
backend::set_canvas_size(&canvas, crate::dpi::Size::Physical(new_size));
|
2020-08-30 21:15:44 +08:00
|
|
|
self.handle_single_event_sync(
|
|
|
|
|
Event::WindowEvent {
|
|
|
|
|
window_id: id,
|
|
|
|
|
event: crate::event::WindowEvent::Resized(new_size),
|
|
|
|
|
},
|
|
|
|
|
&mut control,
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-21 06:42:07 +08:00
|
|
|
// Process the destroy-pending windows again.
|
|
|
|
|
self.process_destroy_pending_windows(&mut control);
|
2020-08-30 21:15:44 +08:00
|
|
|
self.handle_event(Event::MainEventsCleared, &mut control);
|
|
|
|
|
|
|
|
|
|
// Discard all the pending redraw as we shall just redraw all windows.
|
|
|
|
|
self.0.redraw_pending.borrow_mut().clear();
|
|
|
|
|
for &(window_id, _) in &*self.0.all_canvases.borrow() {
|
|
|
|
|
self.handle_event(Event::RedrawRequested(window_id), &mut control);
|
|
|
|
|
}
|
|
|
|
|
self.handle_event(Event::RedrawEventsCleared, &mut control);
|
|
|
|
|
|
|
|
|
|
self.apply_control_flow(control);
|
|
|
|
|
// If the event loop is closed, it has been closed this iteration and now the closing
|
|
|
|
|
// event should be emitted
|
|
|
|
|
if self.is_closed() {
|
2020-09-21 06:42:07 +08:00
|
|
|
self.handle_loop_destroyed(&mut control);
|
2020-08-30 21:15:44 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-11 11:47:03 -04:00
|
|
|
fn handle_unload(&self) {
|
2022-03-18 14:09:39 +01:00
|
|
|
self.apply_control_flow(ControlFlow::Exit);
|
2019-09-11 11:47:03 -04:00
|
|
|
let mut control = self.current_control_flow();
|
2020-09-21 06:42:07 +08:00
|
|
|
// We don't call `handle_loop_destroyed` here because we don't need to
|
|
|
|
|
// perform cleanup when the web browser is going to destroy the page.
|
2019-09-11 11:47:03 -04:00
|
|
|
self.handle_event(Event::LoopDestroyed, &mut control);
|
|
|
|
|
}
|
|
|
|
|
|
2020-08-30 21:15:44 +08:00
|
|
|
// handle_single_event_sync takes in an event and handles it synchronously.
|
|
|
|
|
//
|
|
|
|
|
// It should only ever be called from `scale_changed`.
|
2022-03-18 14:09:39 +01:00
|
|
|
fn handle_single_event_sync(&self, event: Event<'_, T>, control: &mut ControlFlow) {
|
2020-08-30 21:15:44 +08:00
|
|
|
if self.is_closed() {
|
2022-03-18 14:09:39 +01:00
|
|
|
*control = ControlFlow::Exit;
|
2020-08-30 21:15:44 +08:00
|
|
|
}
|
|
|
|
|
match *self.0.runner.borrow_mut() {
|
2020-09-21 06:42:07 +08:00
|
|
|
RunnerEnum::Running(ref mut runner) => {
|
2020-08-30 21:15:44 +08:00
|
|
|
runner.handle_single_event(event, control);
|
|
|
|
|
}
|
|
|
|
|
_ => panic!("Cannot handle event synchronously without a runner"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-25 03:15:34 +02:00
|
|
|
// handle_event takes in events and either queues them or applies a callback
|
|
|
|
|
//
|
2020-08-30 21:15:44 +08:00
|
|
|
// It should only ever be called from `run_until_cleared` and `scale_changed`.
|
2022-03-18 14:09:39 +01:00
|
|
|
fn handle_event(&self, event: Event<'static, T>, control: &mut ControlFlow) {
|
2020-08-30 21:15:44 +08:00
|
|
|
if self.is_closed() {
|
2022-03-18 14:09:39 +01:00
|
|
|
*control = ControlFlow::Exit;
|
2020-08-30 21:15:44 +08:00
|
|
|
}
|
2019-06-25 03:15:34 +02:00
|
|
|
match *self.0.runner.borrow_mut() {
|
2020-09-21 06:42:07 +08:00
|
|
|
RunnerEnum::Running(ref mut runner) => {
|
2020-08-30 21:15:44 +08:00
|
|
|
runner.handle_single_event(event, control);
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
// If an event is being handled without a runner somehow, add it to the event queue so
|
|
|
|
|
// it will eventually be processed
|
2020-09-21 06:42:07 +08:00
|
|
|
RunnerEnum::Pending => self.0.events.borrow_mut().push_back(event),
|
|
|
|
|
// If the Runner has been destroyed, there is nothing to do.
|
|
|
|
|
RunnerEnum::Destroyed => return,
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2022-03-18 14:09:39 +01:00
|
|
|
let is_closed = matches!(*control, ControlFlow::ExitWithCode(_));
|
2020-08-30 21:15:44 +08:00
|
|
|
|
2019-06-25 03:15:34 +02:00
|
|
|
// Don't take events out of the queue if the loop is closed or the runner doesn't exist
|
|
|
|
|
// If the runner doesn't exist and this method recurses, it will recurse infinitely
|
2020-09-21 06:42:07 +08:00
|
|
|
if !is_closed && self.0.runner.borrow().maybe_runner().is_some() {
|
2019-06-25 03:15:34 +02:00
|
|
|
// Take an event out of the queue and handle it
|
2020-04-11 15:20:38 -04:00
|
|
|
// Make sure not to let the borrow_mut live during the next handle_event
|
|
|
|
|
let event = { self.0.events.borrow_mut().pop_front() };
|
|
|
|
|
if let Some(event) = event {
|
2019-06-25 03:15:34 +02:00
|
|
|
self.handle_event(event, control);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply the new ControlFlow that has been selected by the user
|
|
|
|
|
// Start any necessary timeouts etc
|
2022-03-18 14:09:39 +01:00
|
|
|
fn apply_control_flow(&self, control_flow: ControlFlow) {
|
2019-06-25 18:07:47 +02:00
|
|
|
let new_state = match control_flow {
|
2022-03-18 14:09:39 +01:00
|
|
|
ControlFlow::Poll => {
|
2019-06-25 03:15:34 +02:00
|
|
|
let cloned = self.clone();
|
|
|
|
|
State::Poll {
|
2020-04-11 22:49:07 +03:00
|
|
|
request: backend::AnimationFrameRequest::new(move || cloned.poll()),
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
2022-03-18 14:09:39 +01:00
|
|
|
ControlFlow::Wait => State::Wait {
|
2019-06-25 03:15:34 +02:00
|
|
|
start: Instant::now(),
|
|
|
|
|
},
|
2022-03-18 14:09:39 +01:00
|
|
|
ControlFlow::WaitUntil(end) => {
|
2019-06-25 03:15:34 +02:00
|
|
|
let start = Instant::now();
|
2019-06-25 18:07:47 +02:00
|
|
|
|
2019-06-25 03:15:34 +02:00
|
|
|
let delay = if end <= start {
|
|
|
|
|
Duration::from_millis(0)
|
|
|
|
|
} else {
|
|
|
|
|
end - start
|
|
|
|
|
};
|
2019-06-25 18:07:47 +02:00
|
|
|
|
|
|
|
|
let cloned = self.clone();
|
|
|
|
|
|
2019-06-25 03:15:34 +02:00
|
|
|
State::WaitUntil {
|
|
|
|
|
start,
|
|
|
|
|
end,
|
|
|
|
|
timeout: backend::Timeout::new(
|
2020-01-25 19:04:03 -05:00
|
|
|
move || cloned.resume_time_reached(start, end),
|
2019-06-25 03:15:34 +02:00
|
|
|
delay,
|
|
|
|
|
),
|
|
|
|
|
}
|
|
|
|
|
}
|
2022-03-18 14:09:39 +01:00
|
|
|
ControlFlow::ExitWithCode(_) => State::Exit,
|
2019-06-25 03:15:34 +02:00
|
|
|
};
|
|
|
|
|
|
2022-06-10 13:43:33 +03:00
|
|
|
if let RunnerEnum::Running(ref mut runner) = *self.0.runner.borrow_mut() {
|
|
|
|
|
runner.state = new_state;
|
2020-09-21 06:42:07 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-18 14:09:39 +01:00
|
|
|
fn handle_loop_destroyed(&self, control: &mut ControlFlow) {
|
2020-09-21 06:42:07 +08:00
|
|
|
self.handle_event(Event::LoopDestroyed, control);
|
|
|
|
|
let all_canvases = std::mem::take(&mut *self.0.all_canvases.borrow_mut());
|
|
|
|
|
*self.0.scale_change_detector.borrow_mut() = None;
|
|
|
|
|
*self.0.unload_event_handle.borrow_mut() = None;
|
|
|
|
|
// Dropping the `Runner` drops the event handler closure, which will in
|
|
|
|
|
// turn drop all `Window`s moved into the closure.
|
|
|
|
|
*self.0.runner.borrow_mut() = RunnerEnum::Destroyed;
|
|
|
|
|
for (_, canvas) in all_canvases {
|
|
|
|
|
// In case any remaining `Window`s are still not dropped, we will need
|
|
|
|
|
// to explicitly remove the event handlers associated with their canvases.
|
|
|
|
|
if let Some(canvas) = canvas.upgrade() {
|
|
|
|
|
let mut canvas = canvas.borrow_mut();
|
|
|
|
|
canvas.remove_listeners();
|
|
|
|
|
}
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
2020-09-21 06:42:07 +08:00
|
|
|
// At this point, the `self.0` `Rc` should only be strongly referenced
|
|
|
|
|
// by the following:
|
|
|
|
|
// * `self`, i.e. the item which triggered this event loop wakeup, which
|
|
|
|
|
// is usually a `wasm-bindgen` `Closure`, which will be dropped after
|
|
|
|
|
// returning to the JS glue code.
|
|
|
|
|
// * The `EventLoopWindowTarget` leaked inside `EventLoop::run` due to the
|
|
|
|
|
// JS exception thrown at the end.
|
|
|
|
|
// * For each undropped `Window`:
|
|
|
|
|
// * The `register_redraw_request` closure.
|
|
|
|
|
// * The `destroy_fn` closure.
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
2019-06-25 18:07:47 +02:00
|
|
|
// Check if the event loop is currently closed
|
|
|
|
|
fn is_closed(&self) -> bool {
|
2020-09-22 06:19:00 +08:00
|
|
|
match self.0.runner.try_borrow().as_ref().map(Deref::deref) {
|
|
|
|
|
Ok(RunnerEnum::Running(runner)) => runner.state.is_exit(),
|
2020-09-21 06:42:07 +08:00
|
|
|
// The event loop is not closed since it is not initialized.
|
2020-09-22 06:19:00 +08:00
|
|
|
Ok(RunnerEnum::Pending) => false,
|
2020-09-21 06:42:07 +08:00
|
|
|
// The event loop is closed since it has been destroyed.
|
2020-09-22 06:19:00 +08:00
|
|
|
Ok(RunnerEnum::Destroyed) => true,
|
|
|
|
|
// Some other code is mutating the runner, which most likely means
|
|
|
|
|
// the event loop is running and busy.
|
|
|
|
|
Err(_) => false,
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the current control flow state
|
2022-03-18 14:09:39 +01:00
|
|
|
fn current_control_flow(&self) -> ControlFlow {
|
2019-06-25 03:15:34 +02:00
|
|
|
match *self.0.runner.borrow() {
|
2020-09-21 06:42:07 +08:00
|
|
|
RunnerEnum::Running(ref runner) => runner.state.control_flow(),
|
2022-03-18 14:09:39 +01:00
|
|
|
RunnerEnum::Pending => ControlFlow::Poll,
|
|
|
|
|
RunnerEnum::Destroyed => ControlFlow::Exit,
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|