winit/platform_impl/windows/event_loop/
runner.rs

1use std::{
2    any::Any,
3    cell::{Cell, RefCell},
4    collections::{HashSet, VecDeque},
5    mem, panic, ptr,
6    rc::Rc,
7    time::Instant,
8};
9
10use winapi::{
11    shared::{minwindef::DWORD, windef::HWND},
12    um::winuser,
13};
14
15use crate::{
16    dpi::PhysicalSize,
17    event::{Event, StartCause, WindowEvent},
18    event_loop::ControlFlow,
19    platform_impl::platform::util,
20    window::WindowId,
21};
22
23pub(crate) type EventLoopRunnerShared<T> = Rc<EventLoopRunner<T>>;
24pub(crate) struct EventLoopRunner<T: 'static> {
25    // The event loop's win32 handles
26    thread_msg_target: HWND,
27    wait_thread_id: DWORD,
28
29    control_flow: Cell<ControlFlow>,
30    runner_state: Cell<RunnerState>,
31    last_events_cleared: Cell<Instant>,
32
33    event_handler: Cell<Option<Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>>>,
34    event_buffer: RefCell<VecDeque<BufferedEvent<T>>>,
35
36    owned_windows: Cell<HashSet<HWND>>,
37
38    panic_error: Cell<Option<PanicError>>,
39}
40
41pub type PanicError = Box<dyn Any + Send + 'static>;
42
43/// See `move_state_to` function for details on how the state loop works.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45enum RunnerState {
46    /// The event loop has just been created, and an `Init` event must be sent.
47    Uninitialized,
48    /// The event loop is idling.
49    Idle,
50    /// The event loop is handling the OS's events and sending them to the user's callback.
51    /// `NewEvents` has been sent, and `MainEventsCleared` hasn't.
52    HandlingMainEvents,
53    /// The event loop is handling the redraw events and sending them to the user's callback.
54    /// `MainEventsCleared` has been sent, and `RedrawEventsCleared` hasn't.
55    HandlingRedrawEvents,
56    /// The event loop has been destroyed. No other events will be emitted.
57    Destroyed,
58}
59
60enum BufferedEvent<T: 'static> {
61    Event(Event<'static, T>),
62    ScaleFactorChanged(WindowId, f64, PhysicalSize<u32>),
63}
64
65impl<T> EventLoopRunner<T> {
66    pub(crate) fn new(thread_msg_target: HWND, wait_thread_id: DWORD) -> EventLoopRunner<T> {
67        EventLoopRunner {
68            thread_msg_target,
69            wait_thread_id,
70            runner_state: Cell::new(RunnerState::Uninitialized),
71            control_flow: Cell::new(ControlFlow::Poll),
72            panic_error: Cell::new(None),
73            last_events_cleared: Cell::new(Instant::now()),
74            event_handler: Cell::new(None),
75            event_buffer: RefCell::new(VecDeque::new()),
76            owned_windows: Cell::new(HashSet::new()),
77        }
78    }
79
80    pub(crate) unsafe fn set_event_handler<F>(&self, f: F)
81    where
82        F: FnMut(Event<'_, T>, &mut ControlFlow),
83    {
84        let old_event_handler = self.event_handler.replace(mem::transmute::<
85            Option<Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>>,
86            Option<Box<dyn FnMut(Event<'_, T>, &mut ControlFlow)>>,
87        >(Some(Box::new(f))));
88        assert!(old_event_handler.is_none());
89    }
90
91    pub(crate) fn reset_runner(&self) {
92        let EventLoopRunner {
93            thread_msg_target: _,
94            wait_thread_id: _,
95            runner_state,
96            panic_error,
97            control_flow,
98            last_events_cleared: _,
99            event_handler,
100            event_buffer: _,
101            owned_windows: _,
102        } = self;
103        runner_state.set(RunnerState::Uninitialized);
104        panic_error.set(None);
105        control_flow.set(ControlFlow::Poll);
106        event_handler.set(None);
107    }
108}
109
110/// State retrieval functions.
111impl<T> EventLoopRunner<T> {
112    pub fn thread_msg_target(&self) -> HWND {
113        self.thread_msg_target
114    }
115
116    pub fn wait_thread_id(&self) -> DWORD {
117        self.wait_thread_id
118    }
119
120    pub fn redrawing(&self) -> bool {
121        self.runner_state.get() == RunnerState::HandlingRedrawEvents
122    }
123
124    pub fn take_panic_error(&self) -> Result<(), PanicError> {
125        match self.panic_error.take() {
126            Some(err) => Err(err),
127            None => Ok(()),
128        }
129    }
130
131    pub fn control_flow(&self) -> ControlFlow {
132        self.control_flow.get()
133    }
134
135    pub fn handling_events(&self) -> bool {
136        self.runner_state.get() != RunnerState::Idle
137    }
138
139    pub fn should_buffer(&self) -> bool {
140        let handler = self.event_handler.take();
141        let should_buffer = handler.is_none();
142        self.event_handler.set(handler);
143        should_buffer
144    }
145}
146
147/// Misc. functions
148impl<T> EventLoopRunner<T> {
149    pub fn catch_unwind<R>(&self, f: impl FnOnce() -> R) -> Option<R> {
150        let panic_error = self.panic_error.take();
151        if panic_error.is_none() {
152            let result = panic::catch_unwind(panic::AssertUnwindSafe(f));
153
154            // Check to see if the panic error was set in a re-entrant call to catch_unwind inside
155            // of `f`. If it was, that error takes priority. If it wasn't, check if our call to
156            // catch_unwind caught any panics and set panic_error appropriately.
157            match self.panic_error.take() {
158                None => match result {
159                    Ok(r) => Some(r),
160                    Err(e) => {
161                        self.panic_error.set(Some(e));
162                        None
163                    }
164                },
165                Some(e) => {
166                    self.panic_error.set(Some(e));
167                    None
168                }
169            }
170        } else {
171            self.panic_error.set(panic_error);
172            None
173        }
174    }
175    pub fn register_window(&self, window: HWND) {
176        let mut owned_windows = self.owned_windows.take();
177        owned_windows.insert(window);
178        self.owned_windows.set(owned_windows);
179    }
180
181    pub fn remove_window(&self, window: HWND) {
182        let mut owned_windows = self.owned_windows.take();
183        owned_windows.remove(&window);
184        self.owned_windows.set(owned_windows);
185    }
186
187    pub fn owned_windows(&self, mut f: impl FnMut(HWND)) {
188        let mut owned_windows = self.owned_windows.take();
189        for hwnd in &owned_windows {
190            f(*hwnd);
191        }
192        let new_owned_windows = self.owned_windows.take();
193        owned_windows.extend(&new_owned_windows);
194        self.owned_windows.set(owned_windows);
195    }
196}
197
198/// Event dispatch functions.
199impl<T> EventLoopRunner<T> {
200    pub(crate) unsafe fn poll(&self) {
201        self.move_state_to(RunnerState::HandlingMainEvents);
202    }
203
204    pub(crate) unsafe fn send_event(&self, event: Event<'_, T>) {
205        if let Event::RedrawRequested(_) = event {
206            if self.runner_state.get() != RunnerState::HandlingRedrawEvents {
207                warn!("RedrawRequested dispatched without explicit MainEventsCleared");
208                self.move_state_to(RunnerState::HandlingRedrawEvents);
209            }
210            self.call_event_handler(event);
211        } else {
212            if self.should_buffer() {
213                // If the runner is already borrowed, we're in the middle of an event loop invocation. Add
214                // the event to a buffer to be processed later.
215                self.event_buffer
216                    .borrow_mut()
217                    .push_back(BufferedEvent::from_event(event))
218            } else {
219                self.move_state_to(RunnerState::HandlingMainEvents);
220                self.call_event_handler(event);
221                self.dispatch_buffered_events();
222            }
223        }
224    }
225
226    pub(crate) unsafe fn main_events_cleared(&self) {
227        self.move_state_to(RunnerState::HandlingRedrawEvents);
228    }
229
230    pub(crate) unsafe fn redraw_events_cleared(&self) {
231        self.move_state_to(RunnerState::Idle);
232    }
233
234    pub(crate) unsafe fn loop_destroyed(&self) {
235        self.move_state_to(RunnerState::Destroyed);
236    }
237
238    unsafe fn call_event_handler(&self, event: Event<'_, T>) {
239        self.catch_unwind(|| {
240            let mut control_flow = self.control_flow.take();
241            let mut event_handler = self.event_handler.take()
242                .expect("either event handler is re-entrant (likely), or no event handler is registered (very unlikely)");
243
244            if control_flow != ControlFlow::Exit {
245                event_handler(event, &mut control_flow);
246            } else {
247                event_handler(event, &mut ControlFlow::Exit);
248            }
249
250            assert!(self.event_handler.replace(Some(event_handler)).is_none());
251            self.control_flow.set(control_flow);
252        });
253    }
254
255    unsafe fn dispatch_buffered_events(&self) {
256        loop {
257            // We do this instead of using a `while let` loop because if we use a `while let`
258            // loop the reference returned `borrow_mut()` doesn't get dropped until the end
259            // of the loop's body and attempts to add events to the event buffer while in
260            // `process_event` will fail.
261            let buffered_event_opt = self.event_buffer.borrow_mut().pop_front();
262            match buffered_event_opt {
263                Some(e) => e.dispatch_event(|e| self.call_event_handler(e)),
264                None => break,
265            }
266        }
267    }
268
269    /// Dispatch control flow events (`NewEvents`, `MainEventsCleared`, `RedrawEventsCleared`, and
270    /// `LoopDestroyed`) as necessary to bring the internal `RunnerState` to the new runner state.
271    ///
272    /// The state transitions are defined as follows:
273    ///
274    /// ```text
275    ///    Uninitialized
276    ///          |
277    ///          V
278    ///  HandlingMainEvents
279    ///   ^            |
280    ///   |            V
281    /// Idle <--- HandlingRedrawEvents
282    ///   |
283    ///   V
284    /// Destroyed
285    /// ```
286    ///
287    /// Attempting to transition back to `Uninitialized` will result in a panic. Attempting to
288    /// transition *from* `Destroyed` will also reuslt in a panic. Transitioning to the current
289    /// state is a no-op. Even if the `new_runner_state` isn't the immediate next state in the
290    /// runner state machine (e.g. `self.runner_state == HandlingMainEvents` and
291    /// `new_runner_state == Idle`), the intermediate state transitions will still be executed.
292    unsafe fn move_state_to(&self, new_runner_state: RunnerState) {
293        use RunnerState::{
294            Destroyed, HandlingMainEvents, HandlingRedrawEvents, Idle, Uninitialized,
295        };
296
297        match (
298            self.runner_state.replace(new_runner_state),
299            new_runner_state,
300        ) {
301            (Uninitialized, Uninitialized)
302            | (Idle, Idle)
303            | (HandlingMainEvents, HandlingMainEvents)
304            | (HandlingRedrawEvents, HandlingRedrawEvents)
305            | (Destroyed, Destroyed) => (),
306
307            // State transitions that initialize the event loop.
308            (Uninitialized, HandlingMainEvents) => {
309                self.call_new_events(true);
310            }
311            (Uninitialized, HandlingRedrawEvents) => {
312                self.call_new_events(true);
313                self.call_event_handler(Event::MainEventsCleared);
314            }
315            (Uninitialized, Idle) => {
316                self.call_new_events(true);
317                self.call_event_handler(Event::MainEventsCleared);
318                self.call_redraw_events_cleared();
319            }
320            (Uninitialized, Destroyed) => {
321                self.call_new_events(true);
322                self.call_event_handler(Event::MainEventsCleared);
323                self.call_redraw_events_cleared();
324                self.call_event_handler(Event::LoopDestroyed);
325            }
326            (_, Uninitialized) => panic!("cannot move state to Uninitialized"),
327
328            // State transitions that start the event handling process.
329            (Idle, HandlingMainEvents) => {
330                self.call_new_events(false);
331            }
332            (Idle, HandlingRedrawEvents) => {
333                self.call_new_events(false);
334                self.call_event_handler(Event::MainEventsCleared);
335            }
336            (Idle, Destroyed) => {
337                self.call_event_handler(Event::LoopDestroyed);
338            }
339
340            (HandlingMainEvents, HandlingRedrawEvents) => {
341                self.call_event_handler(Event::MainEventsCleared);
342            }
343            (HandlingMainEvents, Idle) => {
344                warn!("RedrawEventsCleared emitted without explicit MainEventsCleared");
345                self.call_event_handler(Event::MainEventsCleared);
346                self.call_redraw_events_cleared();
347            }
348            (HandlingMainEvents, Destroyed) => {
349                self.call_event_handler(Event::MainEventsCleared);
350                self.call_redraw_events_cleared();
351                self.call_event_handler(Event::LoopDestroyed);
352            }
353
354            (HandlingRedrawEvents, Idle) => {
355                self.call_redraw_events_cleared();
356            }
357            (HandlingRedrawEvents, HandlingMainEvents) => {
358                warn!("NewEvents emitted without explicit RedrawEventsCleared");
359                self.call_redraw_events_cleared();
360                self.call_new_events(false);
361            }
362            (HandlingRedrawEvents, Destroyed) => {
363                self.call_redraw_events_cleared();
364                self.call_event_handler(Event::LoopDestroyed);
365            }
366
367            (Destroyed, _) => panic!("cannot move state from Destroyed"),
368        }
369    }
370
371    unsafe fn call_new_events(&self, init: bool) {
372        let start_cause = match (init, self.control_flow()) {
373            (true, _) => StartCause::Init,
374            (false, ControlFlow::Poll) => StartCause::Poll,
375            (false, ControlFlow::Exit) | (false, ControlFlow::Wait) => StartCause::WaitCancelled {
376                requested_resume: None,
377                start: self.last_events_cleared.get(),
378            },
379            (false, ControlFlow::WaitUntil(requested_resume)) => {
380                if Instant::now() < requested_resume {
381                    StartCause::WaitCancelled {
382                        requested_resume: Some(requested_resume),
383                        start: self.last_events_cleared.get(),
384                    }
385                } else {
386                    StartCause::ResumeTimeReached {
387                        requested_resume,
388                        start: self.last_events_cleared.get(),
389                    }
390                }
391            }
392        };
393        self.call_event_handler(Event::NewEvents(start_cause));
394        self.dispatch_buffered_events();
395        winuser::RedrawWindow(
396            self.thread_msg_target,
397            ptr::null(),
398            ptr::null_mut(),
399            winuser::RDW_INTERNALPAINT,
400        );
401    }
402
403    unsafe fn call_redraw_events_cleared(&self) {
404        self.call_event_handler(Event::RedrawEventsCleared);
405        self.last_events_cleared.set(Instant::now());
406    }
407}
408
409impl<T> BufferedEvent<T> {
410    pub fn from_event(event: Event<'_, T>) -> BufferedEvent<T> {
411        match event {
412            Event::WindowEvent {
413                event:
414                    WindowEvent::ScaleFactorChanged {
415                        scale_factor,
416                        new_inner_size,
417                    },
418                window_id,
419            } => BufferedEvent::ScaleFactorChanged(window_id, scale_factor, *new_inner_size),
420            event => BufferedEvent::Event(event.to_static().unwrap()),
421        }
422    }
423
424    pub fn dispatch_event(self, dispatch: impl FnOnce(Event<'_, T>)) {
425        match self {
426            Self::Event(event) => dispatch(event),
427            Self::ScaleFactorChanged(window_id, scale_factor, mut new_inner_size) => {
428                dispatch(Event::WindowEvent {
429                    window_id,
430                    event: WindowEvent::ScaleFactorChanged {
431                        scale_factor,
432                        new_inner_size: &mut new_inner_size,
433                    },
434                });
435                util::set_inner_size_physical(
436                    (window_id.0).0,
437                    new_inner_size.width as _,
438                    new_inner_size.height as _,
439                );
440            }
441        }
442    }
443}