2019-06-25 03:15:34 +02:00
|
|
|
use super::{backend, state::State};
|
2019-12-03 18:16:06 +01:00
|
|
|
use crate::event::{Event, StartCause};
|
2019-06-25 03:15:34 +02:00
|
|
|
use crate::event_loop as root;
|
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},
|
|
|
|
|
rc::Rc,
|
|
|
|
|
};
|
2019-06-25 03:15:34 +02:00
|
|
|
|
|
|
|
|
pub struct Shared<T>(Rc<Execution<T>>);
|
|
|
|
|
|
|
|
|
|
impl<T> Clone for Shared<T> {
|
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
|
Shared(self.0.clone())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub struct Execution<T> {
|
|
|
|
|
runner: RefCell<Option<Runner<T>>>,
|
|
|
|
|
events: RefCell<VecDeque<Event<T>>>,
|
2019-09-19 18:40:18 -04:00
|
|
|
id: RefCell<u32>,
|
2019-09-23 09:14:26 -04:00
|
|
|
redraw_pending: RefCell<HashSet<WindowId>>,
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Runner<T> {
|
|
|
|
|
state: State,
|
|
|
|
|
is_busy: bool,
|
|
|
|
|
event_handler: Box<dyn FnMut(Event<T>, &mut root::ControlFlow)>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: 'static> Runner<T> {
|
|
|
|
|
pub fn new(event_handler: Box<dyn FnMut(Event<T>, &mut root::ControlFlow)>) -> Self {
|
|
|
|
|
Runner {
|
|
|
|
|
state: State::Init,
|
|
|
|
|
is_busy: false,
|
|
|
|
|
event_handler,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T: 'static> Shared<T> {
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
Shared(Rc::new(Execution {
|
|
|
|
|
runner: RefCell::new(None),
|
|
|
|
|
events: RefCell::new(VecDeque::new()),
|
2019-09-19 18:40:18 -04:00
|
|
|
id: RefCell::new(0),
|
2019-09-23 09:14:26 -04:00
|
|
|
redraw_pending: RefCell::new(HashSet::new()),
|
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
|
|
|
|
|
pub fn set_listener(&self, event_handler: Box<dyn FnMut(Event<T>, &mut root::ControlFlow)>) {
|
|
|
|
|
self.0.runner.replace(Some(Runner::new(event_handler)));
|
|
|
|
|
self.send_event(Event::NewEvents(StartCause::Init));
|
2019-09-11 11:47:03 -04:00
|
|
|
|
|
|
|
|
let close_instance = self.clone();
|
|
|
|
|
backend::on_unload(move || close_instance.handle_unload());
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-25 03:15:34 +02:00
|
|
|
// Add an event 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_event(&self, event: Event<T>) {
|
|
|
|
|
// 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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Determine if event handling is in process, and then release the borrow on the runner
|
|
|
|
|
let (start_cause, event_is_start) = match *self.0.runner.borrow() {
|
|
|
|
|
Some(ref runner) if !runner.is_busy => {
|
|
|
|
|
if let Event::NewEvents(cause) = event {
|
|
|
|
|
(cause, true)
|
|
|
|
|
} else {
|
|
|
|
|
(
|
|
|
|
|
match runner.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;
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
false,
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
|
|
|
|
// Events are currently being handled, so queue this one and don't try to
|
|
|
|
|
// double-process the event queue
|
|
|
|
|
self.0.events.borrow_mut().push_back(event);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
let mut control = self.current_control_flow();
|
|
|
|
|
// Handle starting a new batch of events
|
|
|
|
|
//
|
|
|
|
|
// The user is informed via Event::NewEvents that there is a batch of events to process
|
|
|
|
|
// However, there is only one of these per batch of events
|
|
|
|
|
self.handle_event(Event::NewEvents(start_cause), &mut control);
|
|
|
|
|
if !event_is_start {
|
|
|
|
|
self.handle_event(event, &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() {
|
2019-06-25 03:15:34 +02:00
|
|
|
self.handle_event(Event::LoopDestroyed, &mut control);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-11 11:47:03 -04:00
|
|
|
fn handle_unload(&self) {
|
|
|
|
|
self.apply_control_flow(root::ControlFlow::Exit);
|
|
|
|
|
let mut control = self.current_control_flow();
|
|
|
|
|
self.handle_event(Event::LoopDestroyed, &mut control);
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-25 03:15:34 +02:00
|
|
|
// handle_event takes in events and either queues them or applies a callback
|
|
|
|
|
//
|
|
|
|
|
// It should only ever be called from send_event
|
|
|
|
|
fn handle_event(&self, event: Event<T>, control: &mut root::ControlFlow) {
|
2019-06-25 18:07:47 +02:00
|
|
|
let is_closed = self.is_closed();
|
2019-06-25 03:15:34 +02:00
|
|
|
|
|
|
|
|
match *self.0.runner.borrow_mut() {
|
|
|
|
|
Some(ref mut runner) => {
|
|
|
|
|
// An event is being processed, so the runner should be marked busy
|
|
|
|
|
runner.is_busy = true;
|
|
|
|
|
|
|
|
|
|
(runner.event_handler)(event, control);
|
|
|
|
|
|
|
|
|
|
// Maintain closed state, even if the callback changes it
|
2019-06-25 18:07:47 +02:00
|
|
|
if is_closed {
|
2019-06-25 03:15:34 +02:00
|
|
|
*control = root::ControlFlow::Exit;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// An event is no longer being processed
|
|
|
|
|
runner.is_busy = false;
|
|
|
|
|
}
|
|
|
|
|
// If an event is being handled without a runner somehow, add it to the event queue so
|
|
|
|
|
// it will eventually be processed
|
|
|
|
|
_ => self.0.events.borrow_mut().push_back(event),
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
2019-06-25 18:07:47 +02:00
|
|
|
if !is_closed && self.0.runner.borrow().is_some() {
|
2019-06-25 03:15:34 +02:00
|
|
|
// Take an event out of the queue and handle it
|
|
|
|
|
if let Some(event) = self.0.events.borrow_mut().pop_front() {
|
|
|
|
|
self.handle_event(event, control);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Apply the new ControlFlow that has been selected by the user
|
|
|
|
|
// Start any necessary timeouts etc
|
|
|
|
|
fn apply_control_flow(&self, control_flow: root::ControlFlow) {
|
2019-06-25 18:07:47 +02:00
|
|
|
let new_state = match control_flow {
|
2019-06-25 03:15:34 +02:00
|
|
|
root::ControlFlow::Poll => {
|
|
|
|
|
let cloned = self.clone();
|
|
|
|
|
State::Poll {
|
|
|
|
|
timeout: backend::Timeout::new(
|
|
|
|
|
move || cloned.send_event(Event::NewEvents(StartCause::Poll)),
|
2019-06-25 18:07:47 +02:00
|
|
|
Duration::from_millis(0),
|
2019-06-25 03:15:34 +02:00
|
|
|
),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
root::ControlFlow::Wait => State::Wait {
|
|
|
|
|
start: Instant::now(),
|
|
|
|
|
},
|
|
|
|
|
root::ControlFlow::WaitUntil(end) => {
|
|
|
|
|
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(
|
|
|
|
|
move || cloned.send_event(Event::NewEvents(StartCause::Poll)),
|
|
|
|
|
delay,
|
|
|
|
|
),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
root::ControlFlow::Exit => State::Exit,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
match *self.0.runner.borrow_mut() {
|
|
|
|
|
Some(ref mut runner) => {
|
2019-06-25 18:07:47 +02:00
|
|
|
runner.state = new_state;
|
2019-06-25 03:15:34 +02:00
|
|
|
}
|
|
|
|
|
None => (),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2019-06-25 18:07:47 +02:00
|
|
|
// Check if the event loop is currently closed
|
|
|
|
|
fn is_closed(&self) -> bool {
|
2019-06-25 03:15:34 +02:00
|
|
|
match *self.0.runner.borrow() {
|
|
|
|
|
Some(ref runner) => runner.state.is_exit(),
|
|
|
|
|
None => false, // If the event loop is None, it has not been intialised yet, so it cannot be closed
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get the current control flow state
|
|
|
|
|
fn current_control_flow(&self) -> root::ControlFlow {
|
|
|
|
|
match *self.0.runner.borrow() {
|
2019-06-25 18:07:47 +02:00
|
|
|
Some(ref runner) => runner.state.control_flow(),
|
2019-06-25 03:15:34 +02:00
|
|
|
None => root::ControlFlow::Poll,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|