2020-05-04 15:14:13 -04:00
|
|
|
use std::{
|
|
|
|
|
any::Any,
|
|
|
|
|
cell::{Cell, RefCell},
|
|
|
|
|
collections::{HashSet, VecDeque},
|
|
|
|
|
mem, panic, ptr,
|
|
|
|
|
rc::Rc,
|
|
|
|
|
time::Instant,
|
|
|
|
|
};
|
2019-08-26 22:05:42 -04:00
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
use windows_sys::Win32::{
|
|
|
|
|
Foundation::HWND,
|
|
|
|
|
Graphics::Gdi::{RedrawWindow, RDW_INTERNALPAINT},
|
2020-05-04 15:14:13 -04:00
|
|
|
};
|
2019-08-26 22:05:42 -04:00
|
|
|
|
|
|
|
|
use crate::{
|
2020-01-06 15:28:58 -05:00
|
|
|
dpi::PhysicalSize,
|
|
|
|
|
event::{Event, StartCause, WindowEvent},
|
2019-08-26 22:05:42 -04:00
|
|
|
event_loop::ControlFlow,
|
2020-05-04 15:14:13 -04:00
|
|
|
platform_impl::platform::util,
|
2019-08-26 22:05:42 -04:00
|
|
|
window::WindowId,
|
|
|
|
|
};
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub(crate) type EventLoopRunnerShared<T> = Rc<EventLoopRunner<T>>;
|
2022-03-24 05:08:04 +11:00
|
|
|
|
|
|
|
|
type EventHandler<T> = Cell<Option<Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>>>;
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub(crate) struct EventLoopRunner<T: 'static> {
|
|
|
|
|
// The event loop's win32 handles
|
2021-07-16 12:40:48 +02:00
|
|
|
pub(super) thread_msg_target: HWND,
|
2022-03-07 22:58:12 +01:00
|
|
|
wait_thread_id: u32,
|
2020-05-04 15:14:13 -04:00
|
|
|
|
|
|
|
|
control_flow: Cell<ControlFlow>,
|
|
|
|
|
runner_state: Cell<RunnerState>,
|
|
|
|
|
last_events_cleared: Cell<Instant>,
|
2022-03-24 05:08:04 +11:00
|
|
|
event_handler: EventHandler<T>,
|
2020-05-04 15:14:13 -04:00
|
|
|
event_buffer: RefCell<VecDeque<BufferedEvent<T>>>,
|
|
|
|
|
|
|
|
|
|
owned_windows: Cell<HashSet<HWND>>,
|
2020-03-07 20:04:24 +01:00
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
panic_error: Cell<Option<PanicError>>,
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-03-07 20:04:24 +01:00
|
|
|
|
2019-08-26 22:05:42 -04:00
|
|
|
pub type PanicError = Box<dyn Any + Send + 'static>;
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
/// See `move_state_to` function for details on how the state loop works.
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
|
|
|
|
enum RunnerState {
|
|
|
|
|
/// The event loop has just been created, and an `Init` event must be sent.
|
|
|
|
|
Uninitialized,
|
|
|
|
|
/// The event loop is idling.
|
|
|
|
|
Idle,
|
|
|
|
|
/// The event loop is handling the OS's events and sending them to the user's callback.
|
|
|
|
|
/// `NewEvents` has been sent, and `MainEventsCleared` hasn't.
|
|
|
|
|
HandlingMainEvents,
|
|
|
|
|
/// The event loop is handling the redraw events and sending them to the user's callback.
|
|
|
|
|
/// `MainEventsCleared` has been sent, and `RedrawEventsCleared` hasn't.
|
|
|
|
|
HandlingRedrawEvents,
|
2020-07-02 16:53:47 -04:00
|
|
|
/// The event loop has been destroyed. No other events will be emitted.
|
|
|
|
|
Destroyed,
|
2020-05-04 15:14:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
enum BufferedEvent<T: 'static> {
|
2020-01-06 15:28:58 -05:00
|
|
|
Event(Event<'static, T>),
|
|
|
|
|
ScaleFactorChanged(WindowId, f64, PhysicalSize<u32>),
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
impl<T> EventLoopRunner<T> {
|
2022-03-07 22:58:12 +01:00
|
|
|
pub(crate) fn new(thread_msg_target: HWND, wait_thread_id: u32) -> EventLoopRunner<T> {
|
2020-05-04 15:14:13 -04:00
|
|
|
EventLoopRunner {
|
|
|
|
|
thread_msg_target,
|
|
|
|
|
wait_thread_id,
|
|
|
|
|
runner_state: Cell::new(RunnerState::Uninitialized),
|
|
|
|
|
control_flow: Cell::new(ControlFlow::Poll),
|
|
|
|
|
panic_error: Cell::new(None),
|
|
|
|
|
last_events_cleared: Cell::new(Instant::now()),
|
|
|
|
|
event_handler: Cell::new(None),
|
|
|
|
|
event_buffer: RefCell::new(VecDeque::new()),
|
|
|
|
|
owned_windows: Cell::new(HashSet::new()),
|
2020-01-06 15:28:58 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub(crate) unsafe fn set_event_handler<F>(&self, f: F)
|
|
|
|
|
where
|
|
|
|
|
F: FnMut(Event<'_, T>, &mut ControlFlow),
|
|
|
|
|
{
|
|
|
|
|
let old_event_handler = self.event_handler.replace(mem::transmute::<
|
|
|
|
|
Option<Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>>,
|
|
|
|
|
Option<Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>>,
|
|
|
|
|
>(Some(Box::new(f))));
|
|
|
|
|
assert!(old_event_handler.is_none());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub(crate) fn reset_runner(&self) {
|
|
|
|
|
let EventLoopRunner {
|
|
|
|
|
thread_msg_target: _,
|
|
|
|
|
wait_thread_id: _,
|
|
|
|
|
runner_state,
|
|
|
|
|
panic_error,
|
|
|
|
|
control_flow,
|
|
|
|
|
last_events_cleared: _,
|
|
|
|
|
event_handler,
|
|
|
|
|
event_buffer: _,
|
|
|
|
|
owned_windows: _,
|
|
|
|
|
} = self;
|
|
|
|
|
runner_state.set(RunnerState::Uninitialized);
|
|
|
|
|
panic_error.set(None);
|
|
|
|
|
control_flow.set(ControlFlow::Poll);
|
|
|
|
|
event_handler.set(None);
|
2020-01-06 15:28:58 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
/// State retrieval functions.
|
|
|
|
|
impl<T> EventLoopRunner<T> {
|
|
|
|
|
pub fn thread_msg_target(&self) -> HWND {
|
|
|
|
|
self.thread_msg_target
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
|
2022-03-07 22:58:12 +01:00
|
|
|
pub fn wait_thread_id(&self) -> u32 {
|
2020-05-04 15:14:13 -04:00
|
|
|
self.wait_thread_id
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub fn redrawing(&self) -> bool {
|
|
|
|
|
self.runner_state.get() == RunnerState::HandlingRedrawEvents
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub fn take_panic_error(&self) -> Result<(), PanicError> {
|
|
|
|
|
match self.panic_error.take() {
|
|
|
|
|
Some(err) => Err(err),
|
|
|
|
|
None => Ok(()),
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub fn control_flow(&self) -> ControlFlow {
|
|
|
|
|
self.control_flow.get()
|
2019-06-19 16:49:43 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub fn handling_events(&self) -> bool {
|
|
|
|
|
self.runner_state.get() != RunnerState::Idle
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub fn should_buffer(&self) -> bool {
|
|
|
|
|
let handler = self.event_handler.take();
|
|
|
|
|
let should_buffer = handler.is_none();
|
|
|
|
|
self.event_handler.set(handler);
|
|
|
|
|
should_buffer
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
}
|
2019-08-26 22:05:42 -04:00
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
/// Misc. functions
|
|
|
|
|
impl<T> EventLoopRunner<T> {
|
|
|
|
|
pub fn catch_unwind<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
|
|
|
|
|
let panic_error = self.panic_error.take();
|
|
|
|
|
if panic_error.is_none() {
|
|
|
|
|
let result = panic::catch_unwind(panic::AssertUnwindSafe(f));
|
|
|
|
|
|
|
|
|
|
// Check to see if the panic error was set in a re-entrant call to catch_unwind inside
|
|
|
|
|
// of `f`. If it was, that error takes priority. If it wasn't, check if our call to
|
|
|
|
|
// catch_unwind caught any panics and set panic_error appropriately.
|
|
|
|
|
match self.panic_error.take() {
|
|
|
|
|
None => match result {
|
|
|
|
|
Ok(r) => Some(r),
|
|
|
|
|
Err(e) => {
|
|
|
|
|
self.panic_error.set(Some(e));
|
|
|
|
|
None
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
Some(e) => {
|
|
|
|
|
self.panic_error.set(Some(e));
|
|
|
|
|
None
|
|
|
|
|
}
|
2020-03-07 20:04:24 +01:00
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
} else {
|
|
|
|
|
self.panic_error.set(panic_error);
|
|
|
|
|
None
|
2020-01-06 15:28:58 -05:00
|
|
|
}
|
|
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
pub fn register_window(&self, window: HWND) {
|
|
|
|
|
let mut owned_windows = self.owned_windows.take();
|
|
|
|
|
owned_windows.insert(window);
|
|
|
|
|
self.owned_windows.set(owned_windows);
|
|
|
|
|
}
|
2020-01-06 15:28:58 -05:00
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub fn remove_window(&self, window: HWND) {
|
|
|
|
|
let mut owned_windows = self.owned_windows.take();
|
|
|
|
|
owned_windows.remove(&window);
|
|
|
|
|
self.owned_windows.set(owned_windows);
|
2020-03-07 20:04:24 +01:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub fn owned_windows(&self, mut f: impl FnMut(HWND)) {
|
|
|
|
|
let mut owned_windows = self.owned_windows.take();
|
|
|
|
|
for hwnd in &owned_windows {
|
|
|
|
|
f(*hwnd);
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
let new_owned_windows = self.owned_windows.take();
|
|
|
|
|
owned_windows.extend(&new_owned_windows);
|
|
|
|
|
self.owned_windows.set(owned_windows);
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
}
|
2019-08-26 22:05:42 -04:00
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
/// Event dispatch functions.
|
|
|
|
|
impl<T> EventLoopRunner<T> {
|
|
|
|
|
pub(crate) unsafe fn poll(&self) {
|
|
|
|
|
self.move_state_to(RunnerState::HandlingMainEvents);
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub(crate) unsafe fn send_event(&self, event: Event<'_, T>) {
|
|
|
|
|
if let Event::RedrawRequested(_) = event {
|
|
|
|
|
if self.runner_state.get() != RunnerState::HandlingRedrawEvents {
|
|
|
|
|
warn!("RedrawRequested dispatched without explicit MainEventsCleared");
|
|
|
|
|
self.move_state_to(RunnerState::HandlingRedrawEvents);
|
|
|
|
|
}
|
|
|
|
|
self.call_event_handler(event);
|
2022-03-07 22:58:12 +01:00
|
|
|
} else if self.should_buffer() {
|
|
|
|
|
// If the runner is already borrowed, we're in the middle of an event loop invocation. Add
|
|
|
|
|
// the event to a buffer to be processed later.
|
|
|
|
|
self.event_buffer
|
|
|
|
|
.borrow_mut()
|
|
|
|
|
.push_back(BufferedEvent::from_event(event))
|
2020-05-04 15:14:13 -04:00
|
|
|
} else {
|
2022-03-07 22:58:12 +01:00
|
|
|
self.move_state_to(RunnerState::HandlingMainEvents);
|
|
|
|
|
self.call_event_handler(event);
|
|
|
|
|
self.dispatch_buffered_events();
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub(crate) unsafe fn main_events_cleared(&self) {
|
|
|
|
|
self.move_state_to(RunnerState::HandlingRedrawEvents);
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub(crate) unsafe fn redraw_events_cleared(&self) {
|
|
|
|
|
self.move_state_to(RunnerState::Idle);
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
|
2020-07-02 16:53:47 -04:00
|
|
|
pub(crate) unsafe fn loop_destroyed(&self) {
|
|
|
|
|
self.move_state_to(RunnerState::Destroyed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsafe fn call_event_handler(&self, event: Event<'_, T>) {
|
2020-05-04 15:14:13 -04:00
|
|
|
self.catch_unwind(|| {
|
|
|
|
|
let mut control_flow = self.control_flow.take();
|
|
|
|
|
let mut event_handler = self.event_handler.take()
|
|
|
|
|
.expect("either event handler is re-entrant (likely), or no event handler is registered (very unlikely)");
|
2019-08-26 22:05:42 -04:00
|
|
|
|
2022-01-11 01:23:20 +01:00
|
|
|
if let ControlFlow::ExitWithCode(code) = control_flow {
|
|
|
|
|
event_handler(event, &mut ControlFlow::ExitWithCode(code));
|
2020-05-04 15:14:13 -04:00
|
|
|
} else {
|
2022-01-11 01:23:20 +01:00
|
|
|
event_handler(event, &mut control_flow);
|
2020-05-04 15:14:13 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
assert!(self.event_handler.replace(Some(event_handler)).is_none());
|
|
|
|
|
self.control_flow.set(control_flow);
|
|
|
|
|
});
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
unsafe fn dispatch_buffered_events(&self) {
|
|
|
|
|
loop {
|
|
|
|
|
// We do this instead of using a `while let` loop because if we use a `while let`
|
|
|
|
|
// loop the reference returned `borrow_mut()` doesn't get dropped until the end
|
|
|
|
|
// of the loop's body and attempts to add events to the event buffer while in
|
|
|
|
|
// `process_event` will fail.
|
|
|
|
|
let buffered_event_opt = self.event_buffer.borrow_mut().pop_front();
|
|
|
|
|
match buffered_event_opt {
|
|
|
|
|
Some(e) => e.dispatch_event(|e| self.call_event_handler(e)),
|
|
|
|
|
None => break,
|
|
|
|
|
}
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-07-02 16:53:47 -04:00
|
|
|
/// Dispatch control flow events (`NewEvents`, `MainEventsCleared`, `RedrawEventsCleared`, and
|
|
|
|
|
/// `LoopDestroyed`) as necessary to bring the internal `RunnerState` to the new runner state.
|
2020-05-04 15:14:13 -04:00
|
|
|
///
|
|
|
|
|
/// The state transitions are defined as follows:
|
|
|
|
|
///
|
|
|
|
|
/// ```text
|
|
|
|
|
/// Uninitialized
|
|
|
|
|
/// |
|
|
|
|
|
/// V
|
|
|
|
|
/// HandlingMainEvents
|
|
|
|
|
/// ^ |
|
|
|
|
|
/// | V
|
|
|
|
|
/// Idle <--- HandlingRedrawEvents
|
2020-07-02 16:53:47 -04:00
|
|
|
/// |
|
|
|
|
|
/// V
|
|
|
|
|
/// Destroyed
|
2020-05-04 15:14:13 -04:00
|
|
|
/// ```
|
|
|
|
|
///
|
2020-07-02 16:53:47 -04:00
|
|
|
/// Attempting to transition back to `Uninitialized` will result in a panic. Attempting to
|
|
|
|
|
/// transition *from* `Destroyed` will also reuslt in a panic. Transitioning to the current
|
|
|
|
|
/// state is a no-op. Even if the `new_runner_state` isn't the immediate next state in the
|
|
|
|
|
/// runner state machine (e.g. `self.runner_state == HandlingMainEvents` and
|
2020-05-04 15:14:13 -04:00
|
|
|
/// `new_runner_state == Idle`), the intermediate state transitions will still be executed.
|
|
|
|
|
unsafe fn move_state_to(&self, new_runner_state: RunnerState) {
|
2020-07-02 16:53:47 -04:00
|
|
|
use RunnerState::{
|
|
|
|
|
Destroyed, HandlingMainEvents, HandlingRedrawEvents, Idle, Uninitialized,
|
|
|
|
|
};
|
2020-05-04 15:14:13 -04:00
|
|
|
|
|
|
|
|
match (
|
|
|
|
|
self.runner_state.replace(new_runner_state),
|
|
|
|
|
new_runner_state,
|
|
|
|
|
) {
|
|
|
|
|
(Uninitialized, Uninitialized)
|
|
|
|
|
| (Idle, Idle)
|
|
|
|
|
| (HandlingMainEvents, HandlingMainEvents)
|
2020-07-02 16:53:47 -04:00
|
|
|
| (HandlingRedrawEvents, HandlingRedrawEvents)
|
|
|
|
|
| (Destroyed, Destroyed) => (),
|
2020-05-04 15:14:13 -04:00
|
|
|
|
|
|
|
|
// State transitions that initialize the event loop.
|
|
|
|
|
(Uninitialized, HandlingMainEvents) => {
|
|
|
|
|
self.call_new_events(true);
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
(Uninitialized, HandlingRedrawEvents) => {
|
|
|
|
|
self.call_new_events(true);
|
|
|
|
|
self.call_event_handler(Event::MainEventsCleared);
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
(Uninitialized, Idle) => {
|
|
|
|
|
self.call_new_events(true);
|
|
|
|
|
self.call_event_handler(Event::MainEventsCleared);
|
|
|
|
|
self.call_redraw_events_cleared();
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-07-02 16:53:47 -04:00
|
|
|
(Uninitialized, Destroyed) => {
|
|
|
|
|
self.call_new_events(true);
|
|
|
|
|
self.call_event_handler(Event::MainEventsCleared);
|
|
|
|
|
self.call_redraw_events_cleared();
|
|
|
|
|
self.call_event_handler(Event::LoopDestroyed);
|
|
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
(_, Uninitialized) => panic!("cannot move state to Uninitialized"),
|
2019-08-26 22:05:42 -04:00
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
// State transitions that start the event handling process.
|
|
|
|
|
(Idle, HandlingMainEvents) => {
|
|
|
|
|
self.call_new_events(false);
|
|
|
|
|
}
|
|
|
|
|
(Idle, HandlingRedrawEvents) => {
|
|
|
|
|
self.call_new_events(false);
|
|
|
|
|
self.call_event_handler(Event::MainEventsCleared);
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-07-02 16:53:47 -04:00
|
|
|
(Idle, Destroyed) => {
|
|
|
|
|
self.call_event_handler(Event::LoopDestroyed);
|
|
|
|
|
}
|
2019-08-26 22:05:42 -04:00
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
(HandlingMainEvents, HandlingRedrawEvents) => {
|
2020-03-07 20:04:24 +01:00
|
|
|
self.call_event_handler(Event::MainEventsCleared);
|
2019-10-24 14:33:50 -04:00
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
(HandlingMainEvents, Idle) => {
|
|
|
|
|
warn!("RedrawEventsCleared emitted without explicit MainEventsCleared");
|
|
|
|
|
self.call_event_handler(Event::MainEventsCleared);
|
|
|
|
|
self.call_redraw_events_cleared();
|
2020-01-06 15:28:58 -05:00
|
|
|
}
|
2020-07-02 16:53:47 -04:00
|
|
|
(HandlingMainEvents, Destroyed) => {
|
|
|
|
|
self.call_event_handler(Event::MainEventsCleared);
|
|
|
|
|
self.call_redraw_events_cleared();
|
|
|
|
|
self.call_event_handler(Event::LoopDestroyed);
|
|
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
|
|
|
|
|
(HandlingRedrawEvents, Idle) => {
|
|
|
|
|
self.call_redraw_events_cleared();
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
(HandlingRedrawEvents, HandlingMainEvents) => {
|
|
|
|
|
warn!("NewEvents emitted without explicit RedrawEventsCleared");
|
|
|
|
|
self.call_redraw_events_cleared();
|
|
|
|
|
self.call_new_events(false);
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
2020-07-02 16:53:47 -04:00
|
|
|
(HandlingRedrawEvents, Destroyed) => {
|
|
|
|
|
self.call_redraw_events_cleared();
|
|
|
|
|
self.call_event_handler(Event::LoopDestroyed);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(Destroyed, _) => panic!("cannot move state from Destroyed"),
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
unsafe fn call_new_events(&self, init: bool) {
|
|
|
|
|
let start_cause = match (init, self.control_flow()) {
|
|
|
|
|
(true, _) => StartCause::Init,
|
|
|
|
|
(false, ControlFlow::Poll) => StartCause::Poll,
|
2022-01-11 01:23:20 +01:00
|
|
|
(false, ControlFlow::ExitWithCode(_)) | (false, ControlFlow::Wait) => {
|
|
|
|
|
StartCause::WaitCancelled {
|
|
|
|
|
requested_resume: None,
|
|
|
|
|
start: self.last_events_cleared.get(),
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
(false, ControlFlow::WaitUntil(requested_resume)) => {
|
|
|
|
|
if Instant::now() < requested_resume {
|
|
|
|
|
StartCause::WaitCancelled {
|
|
|
|
|
requested_resume: Some(requested_resume),
|
|
|
|
|
start: self.last_events_cleared.get(),
|
2020-01-06 15:28:58 -05:00
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
} else {
|
|
|
|
|
StartCause::ResumeTimeReached {
|
|
|
|
|
requested_resume,
|
|
|
|
|
start: self.last_events_cleared.get(),
|
2020-01-06 15:28:58 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
};
|
|
|
|
|
self.call_event_handler(Event::NewEvents(start_cause));
|
2022-07-26 14:03:12 +01:00
|
|
|
// NB: For consistency all platforms must emit a 'resumed' event even though Windows
|
|
|
|
|
// applications don't themselves have a formal suspend/resume lifecycle.
|
|
|
|
|
if init {
|
|
|
|
|
self.call_event_handler(Event::Resumed);
|
|
|
|
|
}
|
2020-05-04 15:14:13 -04:00
|
|
|
self.dispatch_buffered_events();
|
2022-03-07 22:58:12 +01:00
|
|
|
RedrawWindow(self.thread_msg_target, ptr::null(), 0, RDW_INTERNALPAINT);
|
2020-01-06 15:28:58 -05:00
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
unsafe fn call_redraw_events_cleared(&self) {
|
|
|
|
|
self.call_event_handler(Event::RedrawEventsCleared);
|
|
|
|
|
self.last_events_cleared.set(Instant::now());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> BufferedEvent<T> {
|
|
|
|
|
pub fn from_event(event: Event<'_, T>) -> BufferedEvent<T> {
|
|
|
|
|
match event {
|
|
|
|
|
Event::WindowEvent {
|
|
|
|
|
event:
|
|
|
|
|
WindowEvent::ScaleFactorChanged {
|
|
|
|
|
scale_factor,
|
|
|
|
|
new_inner_size,
|
|
|
|
|
},
|
|
|
|
|
window_id,
|
|
|
|
|
} => BufferedEvent::ScaleFactorChanged(window_id, scale_factor, *new_inner_size),
|
|
|
|
|
event => BufferedEvent::Event(event.to_static().unwrap()),
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-05-04 15:14:13 -04:00
|
|
|
pub fn dispatch_event(self, dispatch: impl FnOnce(Event<'_, T>)) {
|
|
|
|
|
match self {
|
|
|
|
|
Self::Event(event) => dispatch(event),
|
|
|
|
|
Self::ScaleFactorChanged(window_id, scale_factor, mut new_inner_size) => {
|
|
|
|
|
dispatch(Event::WindowEvent {
|
|
|
|
|
window_id,
|
|
|
|
|
event: WindowEvent::ScaleFactorChanged {
|
|
|
|
|
scale_factor,
|
|
|
|
|
new_inner_size: &mut new_inner_size,
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
util::set_inner_size_physical(
|
|
|
|
|
(window_id.0).0,
|
|
|
|
|
new_inner_size.width as _,
|
|
|
|
|
new_inner_size.height as _,
|
|
|
|
|
);
|
|
|
|
|
}
|
2019-08-26 22:05:42 -04:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|