pub mod never_return; pub mod pump_events; pub mod register; pub mod run_on_demand; use std::fmt::{self, Debug}; use std::sync::Arc; use std::sync::atomic::{AtomicUsize, Ordering}; use std::time::Duration; use rwh_06::{DisplayHandle, HandleError, HasDisplayHandle}; use crate::Instant; use crate::as_any::AsAny; use crate::cursor::{CustomCursor, CustomCursorSource}; use crate::error::RequestError; use crate::monitor::MonitorHandle; use crate::window::{Theme, Window, WindowAttributes}; pub trait ActiveEventLoop: AsAny + fmt::Debug { /// Creates an [`EventLoopProxy`] that can be used to dispatch user events /// to the main event loop, possibly from another thread. fn create_proxy(&self) -> EventLoopProxy; /// Create the window. /// /// Possible causes of error include denied permission, incompatible system, and lack of memory. /// /// ## Platform-specific /// /// - **Web:** The window is created but not inserted into the Web page automatically. Please /// see the Web platform module for more information. fn create_window( &self, window_attributes: WindowAttributes, ) -> Result, RequestError>; /// Create custom cursor. /// /// ## Platform-specific /// /// **iOS / Android / Orbital:** Unsupported. fn create_custom_cursor( &self, custom_cursor: CustomCursorSource, ) -> Result; /// Returns the list of all the monitors available on the system. /// /// ## Platform-specific /// /// **Web:** Only returns the current monitor without `detailed monitor permissions`. fn available_monitors(&self) -> Box>; /// Returns the primary monitor of the system. /// /// Returns `None` if it can't identify any monitor as a primary one. /// /// ## Platform-specific /// /// - **Wayland:** Always returns `None`. /// - **Web:** Always returns `None` without `detailed monitor permissions`. fn primary_monitor(&self) -> Option; /// Change if or when [`DeviceEvent`]s are captured. /// /// Since the [`DeviceEvent`] capture can lead to high CPU usage for unfocused windows, winit /// will ignore them by default for unfocused windows on Linux/BSD. This method allows changing /// this at runtime to explicitly capture them again. /// /// ## Platform-specific /// /// - **Wayland / macOS / iOS / Android / Orbital:** Unsupported. /// /// [`DeviceEvent`]: crate::event::DeviceEvent fn listen_device_events(&self, allowed: DeviceEvents); /// Returns the current system theme. /// /// Returns `None` if it cannot be determined on the current platform. /// /// ## Platform-specific /// /// - **iOS / Android / Wayland / x11 / Orbital:** Unsupported. fn system_theme(&self) -> Option; /// Sets the [`ControlFlow`]. fn set_control_flow(&self, control_flow: ControlFlow); /// Gets the current [`ControlFlow`]. fn control_flow(&self) -> ControlFlow; /// Stop the event loop. /// /// ## Platform-specific /// /// ### iOS /// /// It is not possible to programmatically exit/quit an application on iOS, so this function is /// a no-op there. See also [this technical Q&A][qa1561]. /// /// [qa1561]: https://developer.apple.com/library/archive/qa/qa1561/_index.html fn exit(&self); /// Returns whether the [`ActiveEventLoop`] is about to stop. /// /// Set by [`exit()`][Self::exit]. fn exiting(&self) -> bool; /// Gets a persistent reference to the underlying platform display. /// /// See the [`OwnedDisplayHandle`] type for more information. fn owned_display_handle(&self) -> OwnedDisplayHandle; /// Get the raw-window-handle handle. fn rwh_06_handle(&self) -> &dyn HasDisplayHandle; } impl HasDisplayHandle for dyn ActiveEventLoop + '_ { fn display_handle(&self) -> Result, HandleError> { self.rwh_06_handle().display_handle() } } impl_dyn_casting!(ActiveEventLoop); /// Control the [`ActiveEventLoop`], possibly from a different thread, without referencing it /// directly. #[derive(Clone, Debug)] pub struct EventLoopProxy { pub(crate) proxy: Arc, } impl EventLoopProxy { /// Wake up the [`ActiveEventLoop`], resulting in [`ApplicationHandler::proxy_wake_up()`] being /// called. /// /// Calls to this method are coalesced into a single call to [`proxy_wake_up`], see the /// documentation on that for details. /// /// If the event loop is no longer running, this is a no-op. /// /// [`proxy_wake_up`]: crate::application::ApplicationHandler::proxy_wake_up /// [`ApplicationHandler::proxy_wake_up()`]: crate::application::ApplicationHandler::proxy_wake_up /// /// # Platform-specific /// /// - **Windows**: The wake-up may be ignored under high contention, see [#3687]. /// /// [#3687]: https://github.com/rust-windowing/winit/pull/3687 pub fn wake_up(&self) { self.proxy.wake_up(); } pub fn new(proxy: Arc) -> Self { Self { proxy } } } pub trait EventLoopProxyProvider: Send + Sync + Debug { /// See [`EventLoopProxy::wake_up`] for details. fn wake_up(&self); } /// A proxy for the underlying display handle. /// /// The purpose of this type is to provide a cheaply cloneable handle to the underlying /// display handle. This is often used by graphics APIs to connect to the underlying APIs. /// It is difficult to keep a handle to the underlying event loop type or the [`ActiveEventLoop`] /// type. In contrast, this type involves no lifetimes and can be persisted for as long as /// needed. /// /// For all platforms, this is one of the following: /// /// - A zero-sized type that is likely optimized out. /// - A reference-counted pointer to the underlying type. #[derive(Clone)] pub struct OwnedDisplayHandle { pub(crate) handle: Arc, } impl OwnedDisplayHandle { pub fn new(handle: Arc) -> Self { Self { handle } } } impl HasDisplayHandle for OwnedDisplayHandle { fn display_handle(&self) -> Result, HandleError> { self.handle.display_handle() } } impl fmt::Debug for OwnedDisplayHandle { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("OwnedDisplayHandle").finish_non_exhaustive() } } impl PartialEq for OwnedDisplayHandle { fn eq(&self, other: &Self) -> bool { match (self.display_handle(), other.display_handle()) { (Ok(lhs), Ok(rhs)) => lhs == rhs, _ => false, } } } impl Eq for OwnedDisplayHandle {} /// Set through [`ActiveEventLoop::set_control_flow()`]. /// /// Indicates the desired behavior of the event loop after [`about_to_wait`] is called. /// /// Defaults to [`Wait`]. /// /// [`Wait`]: Self::Wait /// [`about_to_wait`]: crate::application::ApplicationHandler::about_to_wait #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)] pub enum ControlFlow { /// When the current loop iteration finishes, immediately begin a new iteration regardless of /// whether or not new events are available to process. Poll, /// When the current loop iteration finishes, suspend the thread until another event arrives. #[default] Wait, /// When the current loop iteration finishes, suspend the thread until either another event /// arrives or the given time is reached. /// /// Useful for implementing efficient timers. Applications which want to render at the /// display's native refresh rate should instead use [`Poll`] and the VSync functionality /// of a graphics API to reduce odds of missed frames. /// /// [`Poll`]: Self::Poll WaitUntil(Instant), } impl ControlFlow { /// Creates a [`ControlFlow`] that waits until a timeout has expired. /// /// In most cases, this is set to [`WaitUntil`]. However, if the timeout overflows, it is /// instead set to [`Wait`]. /// /// [`WaitUntil`]: Self::WaitUntil /// [`Wait`]: Self::Wait pub fn wait_duration(timeout: Duration) -> Self { match Instant::now().checked_add(timeout) { Some(instant) => Self::WaitUntil(instant), None => Self::Wait, } } } /// Control when device events are captured. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)] #[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum DeviceEvents { /// Report device events regardless of window focus. Always, /// Only capture device events while the window is focused. #[default] WhenFocused, /// Never capture device events. Never, } /// A unique identifier of the winit's async request. /// /// This could be used to identify the async request once it's done /// and a specific action must be taken. /// /// One of the handling scenarios could be to maintain a working list /// containing [`AsyncRequestSerial`] and some closure associated with it. /// Then once event is arriving the working list is being traversed and a job /// executed and removed from the list. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct AsyncRequestSerial { serial: usize, } impl AsyncRequestSerial { pub fn get() -> Self { static CURRENT_SERIAL: AtomicUsize = AtomicUsize::new(0); // NOTE: We rely on wrap around here, while the user may just request // in the loop usize::MAX times that's issue is considered on them. let serial = CURRENT_SERIAL.fetch_add(1, Ordering::Relaxed); Self { serial } } }