winit_core/event_loop/
mod.rs

1pub mod never_return;
2pub mod pump_events;
3pub mod register;
4pub mod run_on_demand;
5
6use std::fmt::{self, Debug};
7use std::sync::Arc;
8use std::sync::atomic::{AtomicUsize, Ordering};
9use std::time::Duration;
10
11use rwh_06::{DisplayHandle, HandleError, HasDisplayHandle};
12
13use crate::Instant;
14use crate::as_any::AsAny;
15use crate::cursor::{CustomCursor, CustomCursorSource};
16use crate::error::RequestError;
17use crate::monitor::MonitorHandle;
18use crate::window::{Theme, Window, WindowAttributes};
19
20pub trait ActiveEventLoop: AsAny + fmt::Debug {
21    /// Creates an [`EventLoopProxy`] that can be used to dispatch user events
22    /// to the main event loop, possibly from another thread.
23    fn create_proxy(&self) -> EventLoopProxy;
24
25    /// Create the window.
26    ///
27    /// Possible causes of error include denied permission, incompatible system, and lack of memory.
28    ///
29    /// ## Platform-specific
30    ///
31    /// - **Web:** The window is created but not inserted into the Web page automatically. Please
32    ///   see the Web platform module for more information.
33    fn create_window(
34        &self,
35        window_attributes: WindowAttributes,
36    ) -> Result<Box<dyn Window>, RequestError>;
37
38    /// Create custom cursor.
39    ///
40    /// ## Platform-specific
41    ///
42    /// **iOS / Android / Orbital:** Unsupported.
43    fn create_custom_cursor(
44        &self,
45        custom_cursor: CustomCursorSource,
46    ) -> Result<CustomCursor, RequestError>;
47
48    /// Returns the list of all the monitors available on the system.
49    ///
50    /// ## Platform-specific
51    ///
52    /// **Web:** Only returns the current monitor without `detailed monitor permissions`.
53    fn available_monitors(&self) -> Box<dyn Iterator<Item = MonitorHandle>>;
54
55    /// Returns the primary monitor of the system.
56    ///
57    /// Returns `None` if it can't identify any monitor as a primary one.
58    ///
59    /// ## Platform-specific
60    ///
61    /// - **Wayland:** Always returns `None`.
62    /// - **Web:** Always returns `None` without `detailed monitor permissions`.
63    fn primary_monitor(&self) -> Option<MonitorHandle>;
64
65    /// Change if or when [`DeviceEvent`]s are captured.
66    ///
67    /// Since the [`DeviceEvent`] capture can lead to high CPU usage for unfocused windows, winit
68    /// will ignore them by default for unfocused windows on Linux/BSD. This method allows changing
69    /// this at runtime to explicitly capture them again.
70    ///
71    /// ## Platform-specific
72    ///
73    /// - **Wayland / macOS / iOS / Android / Orbital:** Unsupported.
74    ///
75    /// [`DeviceEvent`]: crate::event::DeviceEvent
76    fn listen_device_events(&self, allowed: DeviceEvents);
77
78    /// Returns the current system theme.
79    ///
80    /// Returns `None` if it cannot be determined on the current platform.
81    ///
82    /// ## Platform-specific
83    ///
84    /// - **iOS / Android / Wayland / x11 / Orbital:** Unsupported.
85    fn system_theme(&self) -> Option<Theme>;
86
87    /// Sets the [`ControlFlow`].
88    fn set_control_flow(&self, control_flow: ControlFlow);
89
90    /// Gets the current [`ControlFlow`].
91    fn control_flow(&self) -> ControlFlow;
92
93    /// Stop the event loop.
94    ///
95    /// ## Platform-specific
96    ///
97    /// ### iOS
98    ///
99    /// It is not possible to programmatically exit/quit an application on iOS, so this function is
100    /// a no-op there. See also [this technical Q&A][qa1561].
101    ///
102    /// [qa1561]: https://developer.apple.com/library/archive/qa/qa1561/_index.html
103    fn exit(&self);
104
105    /// Returns whether the [`ActiveEventLoop`] is about to stop.
106    ///
107    /// Set by [`exit()`][Self::exit].
108    fn exiting(&self) -> bool;
109
110    /// Gets a persistent reference to the underlying platform display.
111    ///
112    /// See the [`OwnedDisplayHandle`] type for more information.
113    fn owned_display_handle(&self) -> OwnedDisplayHandle;
114
115    /// Get the raw-window-handle handle.
116    fn rwh_06_handle(&self) -> &dyn HasDisplayHandle;
117}
118
119impl HasDisplayHandle for dyn ActiveEventLoop + '_ {
120    fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
121        self.rwh_06_handle().display_handle()
122    }
123}
124
125impl_dyn_casting!(ActiveEventLoop);
126
127/// Control the [`ActiveEventLoop`], possibly from a different thread, without referencing it
128/// directly.
129#[derive(Clone, Debug)]
130pub struct EventLoopProxy {
131    pub(crate) proxy: Arc<dyn EventLoopProxyProvider>,
132}
133
134impl EventLoopProxy {
135    /// Wake up the [`ActiveEventLoop`], resulting in [`ApplicationHandler::proxy_wake_up()`] being
136    /// called.
137    ///
138    /// Calls to this method are coalesced into a single call to [`proxy_wake_up`], see the
139    /// documentation on that for details.
140    ///
141    /// If the event loop is no longer running, this is a no-op.
142    ///
143    /// [`proxy_wake_up`]: crate::application::ApplicationHandler::proxy_wake_up
144    /// [`ApplicationHandler::proxy_wake_up()`]: crate::application::ApplicationHandler::proxy_wake_up
145    ///
146    /// # Platform-specific
147    ///
148    /// - **Windows**: The wake-up may be ignored under high contention, see [#3687].
149    ///
150    /// [#3687]: https://github.com/rust-windowing/winit/pull/3687
151    pub fn wake_up(&self) {
152        self.proxy.wake_up();
153    }
154
155    pub fn new(proxy: Arc<dyn EventLoopProxyProvider>) -> Self {
156        Self { proxy }
157    }
158}
159
160pub trait EventLoopProxyProvider: Send + Sync + Debug {
161    /// See [`EventLoopProxy::wake_up`] for details.
162    fn wake_up(&self);
163}
164
165/// A proxy for the underlying display handle.
166///
167/// The purpose of this type is to provide a cheaply cloneable handle to the underlying
168/// display handle. This is often used by graphics APIs to connect to the underlying APIs.
169/// It is difficult to keep a handle to the underlying event loop type or the [`ActiveEventLoop`]
170/// type. In contrast, this type involves no lifetimes and can be persisted for as long as
171/// needed.
172///
173/// For all platforms, this is one of the following:
174///
175/// - A zero-sized type that is likely optimized out.
176/// - A reference-counted pointer to the underlying type.
177#[derive(Clone)]
178pub struct OwnedDisplayHandle {
179    pub(crate) handle: Arc<dyn HasDisplayHandle>,
180}
181
182impl OwnedDisplayHandle {
183    pub fn new(handle: Arc<dyn HasDisplayHandle>) -> Self {
184        Self { handle }
185    }
186}
187
188impl HasDisplayHandle for OwnedDisplayHandle {
189    fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
190        self.handle.display_handle()
191    }
192}
193
194impl fmt::Debug for OwnedDisplayHandle {
195    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
196        f.debug_struct("OwnedDisplayHandle").finish_non_exhaustive()
197    }
198}
199
200impl PartialEq for OwnedDisplayHandle {
201    fn eq(&self, other: &Self) -> bool {
202        match (self.display_handle(), other.display_handle()) {
203            (Ok(lhs), Ok(rhs)) => lhs == rhs,
204            _ => false,
205        }
206    }
207}
208
209impl Eq for OwnedDisplayHandle {}
210
211/// Set through [`ActiveEventLoop::set_control_flow()`].
212///
213/// Indicates the desired behavior of the event loop after [`about_to_wait`] is called.
214///
215/// Defaults to [`Wait`].
216///
217/// [`Wait`]: Self::Wait
218/// [`about_to_wait`]: crate::application::ApplicationHandler::about_to_wait
219#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
220pub enum ControlFlow {
221    /// When the current loop iteration finishes, immediately begin a new iteration regardless of
222    /// whether or not new events are available to process.
223    Poll,
224
225    /// When the current loop iteration finishes, suspend the thread until another event arrives.
226    #[default]
227    Wait,
228
229    /// When the current loop iteration finishes, suspend the thread until either another event
230    /// arrives or the given time is reached.
231    ///
232    /// Useful for implementing efficient timers. Applications which want to render at the
233    /// display's native refresh rate should instead use [`Poll`] and the VSync functionality
234    /// of a graphics API to reduce odds of missed frames.
235    ///
236    /// [`Poll`]: Self::Poll
237    WaitUntil(Instant),
238}
239
240impl ControlFlow {
241    /// Creates a [`ControlFlow`] that waits until a timeout has expired.
242    ///
243    /// In most cases, this is set to [`WaitUntil`]. However, if the timeout overflows, it is
244    /// instead set to [`Wait`].
245    ///
246    /// [`WaitUntil`]: Self::WaitUntil
247    /// [`Wait`]: Self::Wait
248    pub fn wait_duration(timeout: Duration) -> Self {
249        match Instant::now().checked_add(timeout) {
250            Some(instant) => Self::WaitUntil(instant),
251            None => Self::Wait,
252        }
253    }
254}
255
256/// Control when device events are captured.
257#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
258#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
259pub enum DeviceEvents {
260    /// Report device events regardless of window focus.
261    Always,
262    /// Only capture device events while the window is focused.
263    #[default]
264    WhenFocused,
265    /// Never capture device events.
266    Never,
267}
268
269/// A unique identifier of the winit's async request.
270///
271/// This could be used to identify the async request once it's done
272/// and a specific action must be taken.
273///
274/// One of the handling scenarios could be to maintain a working list
275/// containing [`AsyncRequestSerial`] and some closure associated with it.
276/// Then once event is arriving the working list is being traversed and a job
277/// executed and removed from the list.
278#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
279pub struct AsyncRequestSerial {
280    serial: usize,
281}
282
283impl AsyncRequestSerial {
284    pub fn get() -> Self {
285        static CURRENT_SERIAL: AtomicUsize = AtomicUsize::new(0);
286        // NOTE: We rely on wrap around here, while the user may just request
287        // in the loop usize::MAX times that's issue is considered on them.
288        let serial = CURRENT_SERIAL.fetch_add(1, Ordering::Relaxed);
289        Self { serial }
290    }
291}