2022-06-11 18:57:19 +02:00
|
|
|
//! The [`EventLoop`] struct and assorted supporting types, including
|
|
|
|
|
//! [`ControlFlow`].
|
2019-02-05 10:30:33 -05:00
|
|
|
//!
|
2022-06-11 18:57:19 +02:00
|
|
|
//! If you want to send custom events to the event loop, use
|
|
|
|
|
//! [`EventLoop::create_proxy`] to acquire an [`EventLoopProxy`] and call its
|
2024-06-24 13:04:55 +03:00
|
|
|
//! [`wake_up`][EventLoopProxy::wake_up] method. Then during handling the wake up
|
|
|
|
|
//! you can poll your event sources.
|
2019-02-05 10:30:33 -05:00
|
|
|
//!
|
|
|
|
|
//! See the root-level documentation for information on how to create and use an event loop to
|
|
|
|
|
//! handle events.
|
2024-06-24 13:04:55 +03:00
|
|
|
use std::fmt;
|
2022-02-16 22:09:03 +01:00
|
|
|
use std::marker::PhantomData;
|
2023-10-15 20:31:29 +04:00
|
|
|
#[cfg(any(x11_platform, wayland_platform))]
|
|
|
|
|
use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd};
|
2024-02-08 00:58:43 +04:00
|
|
|
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
2024-01-14 18:54:52 +01:00
|
|
|
#[cfg(not(web_platform))]
|
2023-06-01 17:22:28 +02:00
|
|
|
use std::time::{Duration, Instant};
|
2024-07-07 18:38:50 +02:00
|
|
|
|
2024-01-14 18:54:52 +01:00
|
|
|
#[cfg(web_platform)]
|
2023-06-01 17:22:28 +02:00
|
|
|
use web_time::{Duration, Instant};
|
2022-06-22 19:43:25 +02:00
|
|
|
|
2024-02-23 14:37:21 +04:00
|
|
|
use crate::application::ApplicationHandler;
|
2024-08-06 18:57:03 +02:00
|
|
|
use crate::error::{EventLoopError, ExternalError, OsError};
|
2019-10-05 16:49:24 +02:00
|
|
|
use crate::monitor::MonitorHandle;
|
|
|
|
|
use crate::platform_impl;
|
2024-08-11 21:24:34 +03:00
|
|
|
use crate::utils::AsAny;
|
2024-08-05 20:51:38 +02:00
|
|
|
use crate::window::{CustomCursor, CustomCursorSource, Theme, Window, WindowAttributes};
|
2019-02-05 10:30:33 -05:00
|
|
|
|
|
|
|
|
/// Provides a way to retrieve events from the system and from the windows that were registered to
|
|
|
|
|
/// the events loop.
|
|
|
|
|
///
|
2022-06-11 18:57:19 +02:00
|
|
|
/// An `EventLoop` can be seen more or less as a "context". Calling [`EventLoop::new`]
|
2019-02-05 10:30:33 -05:00
|
|
|
/// initializes everything that will be required to create windows. For example on Linux creating
|
2019-06-22 02:34:55 +02:00
|
|
|
/// an event loop opens a connection to the X or Wayland server.
|
2019-02-05 10:30:33 -05:00
|
|
|
///
|
2022-06-11 18:57:19 +02:00
|
|
|
/// To wake up an `EventLoop` from a another thread, see the [`EventLoopProxy`] docs.
|
2019-02-05 10:30:33 -05:00
|
|
|
///
|
2022-06-11 18:57:19 +02:00
|
|
|
/// Note that this cannot be shared across threads (due to platform-dependant logic
|
|
|
|
|
/// forbidding it), as such it is neither [`Send`] nor [`Sync`]. If you need cross-thread access,
|
|
|
|
|
/// the [`Window`] created from this _can_ be sent to an other thread, and the
|
|
|
|
|
/// [`EventLoopProxy`] allows you to wake up an `EventLoop` from another thread.
|
2019-10-18 11:51:06 -04:00
|
|
|
///
|
2022-06-11 18:57:19 +02:00
|
|
|
/// [`Window`]: crate::window::Window
|
2024-06-24 13:04:55 +03:00
|
|
|
pub struct EventLoop {
|
|
|
|
|
pub(crate) event_loop: platform_impl::EventLoop,
|
2022-02-16 22:09:03 +01:00
|
|
|
pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync
|
2019-02-05 10:30:33 -05:00
|
|
|
}
|
|
|
|
|
|
2022-02-16 22:09:03 +01:00
|
|
|
/// Object that allows building the event loop.
|
|
|
|
|
///
|
|
|
|
|
/// This is used to make specifying options that affect the whole application
|
|
|
|
|
/// easier. But note that constructing multiple event loops is not supported.
|
2023-08-30 10:54:46 +02:00
|
|
|
///
|
2024-06-24 13:04:55 +03:00
|
|
|
/// This can be created using [`EventLoop::builder`].
|
2024-08-08 00:46:28 +02:00
|
|
|
#[derive(Default, PartialEq, Eq, Hash)]
|
2024-06-24 13:04:55 +03:00
|
|
|
pub struct EventLoopBuilder {
|
2022-02-16 22:09:03 +01:00
|
|
|
pub(crate) platform_specific: platform_impl::PlatformSpecificEventLoopAttributes,
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-30 10:54:46 +02:00
|
|
|
static EVENT_LOOP_CREATED: AtomicBool = AtomicBool::new(false);
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
impl EventLoopBuilder {
|
2022-02-16 22:09:03 +01:00
|
|
|
/// Builds a new event loop.
|
|
|
|
|
///
|
2022-06-22 19:43:25 +02:00
|
|
|
/// ***For cross-platform compatibility, the [`EventLoop`] must be created on the main thread,
|
|
|
|
|
/// and only once per application.***
|
|
|
|
|
///
|
2022-05-29 04:51:27 -07:00
|
|
|
/// Calling this function will result in display backend initialisation.
|
2022-02-16 22:09:03 +01:00
|
|
|
///
|
2023-08-13 23:20:09 +04:00
|
|
|
/// ## Panics
|
|
|
|
|
///
|
|
|
|
|
/// Attempting to create the event loop off the main thread will panic. This
|
|
|
|
|
/// restriction isn't strictly necessary on all platforms, but is imposed to
|
|
|
|
|
/// eliminate any nasty surprises when porting to platforms that require it.
|
|
|
|
|
/// `EventLoopBuilderExt::any_thread` functions are exposed in the relevant
|
|
|
|
|
/// [`platform`] module if the target platform supports creating an event
|
|
|
|
|
/// loop on any thread.
|
|
|
|
|
///
|
2022-02-16 22:09:03 +01:00
|
|
|
/// ## Platform-specific
|
|
|
|
|
///
|
2023-08-13 23:20:09 +04:00
|
|
|
/// - **Wayland/X11:** to prevent running under `Wayland` or `X11` unset `WAYLAND_DISPLAY` or
|
|
|
|
|
/// `DISPLAY` respectively when building the event loop.
|
|
|
|
|
/// - **Android:** must be configured with an `AndroidApp` from `android_main()` by calling
|
|
|
|
|
/// [`.with_android_app(app)`] before calling `.build()`, otherwise it'll panic.
|
2022-06-11 18:57:19 +02:00
|
|
|
///
|
|
|
|
|
/// [`platform`]: crate::platform
|
2022-11-10 16:55:19 +00:00
|
|
|
#[cfg_attr(
|
2024-05-06 07:11:57 +02:00
|
|
|
android_platform,
|
2022-11-10 16:55:19 +00:00
|
|
|
doc = "[`.with_android_app(app)`]: \
|
|
|
|
|
crate::platform::android::EventLoopBuilderExtAndroid::with_android_app"
|
|
|
|
|
)]
|
2024-05-06 07:11:57 +02:00
|
|
|
#[cfg_attr(
|
|
|
|
|
not(android_platform),
|
|
|
|
|
doc = "[`.with_android_app(app)`]: #only-available-on-android"
|
|
|
|
|
)]
|
2022-02-16 22:09:03 +01:00
|
|
|
#[inline]
|
2024-06-24 13:04:55 +03:00
|
|
|
pub fn build(&mut self) -> Result<EventLoop, EventLoopError> {
|
2024-02-25 19:20:39 -08:00
|
|
|
let _span = tracing::debug_span!("winit::EventLoopBuilder::build").entered();
|
|
|
|
|
|
2023-06-23 15:01:42 -02:30
|
|
|
if EVENT_LOOP_CREATED.swap(true, Ordering::Relaxed) {
|
2023-08-13 23:20:09 +04:00
|
|
|
return Err(EventLoopError::RecreationAttempt);
|
2022-06-22 19:43:25 +02:00
|
|
|
}
|
2023-06-23 15:01:42 -02:30
|
|
|
|
2022-06-10 13:43:33 +03:00
|
|
|
// Certain platforms accept a mutable reference in their API.
|
|
|
|
|
#[allow(clippy::unnecessary_mut_passed)]
|
2023-08-13 23:20:09 +04:00
|
|
|
Ok(EventLoop {
|
|
|
|
|
event_loop: platform_impl::EventLoop::new(&mut self.platform_specific)?,
|
2022-02-16 22:09:03 +01:00
|
|
|
_marker: PhantomData,
|
2023-08-13 23:20:09 +04:00
|
|
|
})
|
2022-02-16 22:09:03 +01:00
|
|
|
}
|
2023-06-23 15:01:42 -02:30
|
|
|
|
2024-01-14 18:54:52 +01:00
|
|
|
#[cfg(web_platform)]
|
2023-06-23 15:01:42 -02:30
|
|
|
pub(crate) fn allow_event_loop_recreation() {
|
|
|
|
|
EVENT_LOOP_CREATED.store(false, Ordering::Relaxed);
|
|
|
|
|
}
|
2019-02-05 10:30:33 -05:00
|
|
|
}
|
|
|
|
|
|
2024-08-08 00:46:28 +02:00
|
|
|
impl fmt::Debug for EventLoopBuilder {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
f.debug_struct("EventLoopBuilder").finish_non_exhaustive()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
impl fmt::Debug for EventLoop {
|
2019-07-09 23:49:07 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2024-08-08 00:46:28 +02:00
|
|
|
f.debug_struct("EventLoop").finish_non_exhaustive()
|
2019-02-05 10:30:33 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-31 17:29:59 +04:00
|
|
|
/// Set through [`ActiveEventLoop::set_control_flow()`].
|
2022-06-11 18:57:19 +02:00
|
|
|
///
|
2024-06-24 13:04:55 +03:00
|
|
|
/// Indicates the desired behavior of the event loop after [`about_to_wait`] is called.
|
2019-02-05 10:30:33 -05:00
|
|
|
///
|
2023-09-22 21:27:11 +02:00
|
|
|
/// Defaults to [`Wait`].
|
2019-02-05 10:30:33 -05:00
|
|
|
///
|
2023-09-22 21:27:11 +02:00
|
|
|
/// [`Wait`]: Self::Wait
|
2024-06-24 13:04:55 +03:00
|
|
|
/// [`about_to_wait`]: crate::application::ApplicationHandler::about_to_wait
|
2024-08-08 00:46:28 +02:00
|
|
|
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Hash)]
|
2019-02-05 10:30:33 -05:00
|
|
|
pub enum ControlFlow {
|
|
|
|
|
/// When the current loop iteration finishes, immediately begin a new iteration regardless of
|
2020-08-30 21:15:44 +08:00
|
|
|
/// whether or not new events are available to process.
|
2019-02-05 10:30:33 -05:00
|
|
|
Poll,
|
2023-01-16 01:14:09 +00:00
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
/// When the current loop iteration finishes, suspend the thread until another event arrives.
|
2023-09-22 21:27:11 +02:00
|
|
|
#[default]
|
2019-02-05 10:30:33 -05:00
|
|
|
Wait,
|
2023-01-16 01:14:09 +00:00
|
|
|
|
2019-02-05 10:30:33 -05:00
|
|
|
/// When the current loop iteration finishes, suspend the thread until either another event
|
|
|
|
|
/// arrives or the given time is reached.
|
2022-03-31 13:38:02 -07:00
|
|
|
///
|
|
|
|
|
/// Useful for implementing efficient timers. Applications which want to render at the
|
2022-06-11 18:57:19 +02:00
|
|
|
/// display's native refresh rate should instead use [`Poll`] and the VSync functionality
|
2022-03-31 13:38:02 -07:00
|
|
|
/// of a graphics API to reduce odds of missed frames.
|
2022-06-11 18:57:19 +02:00
|
|
|
///
|
|
|
|
|
/// [`Poll`]: Self::Poll
|
2019-02-05 10:30:33 -05:00
|
|
|
WaitUntil(Instant),
|
2022-01-11 01:23:20 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl ControlFlow {
|
2023-09-07 08:25:04 +02:00
|
|
|
/// Creates a [`ControlFlow`] that waits until a timeout has expired.
|
2023-01-16 01:14:09 +00:00
|
|
|
///
|
|
|
|
|
/// 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
|
2023-09-07 08:25:04 +02:00
|
|
|
pub fn wait_duration(timeout: Duration) -> Self {
|
2023-01-16 01:14:09 +00:00
|
|
|
match Instant::now().checked_add(timeout) {
|
2023-09-07 08:25:04 +02:00
|
|
|
Some(instant) => Self::WaitUntil(instant),
|
|
|
|
|
None => Self::Wait,
|
2023-01-16 01:14:09 +00:00
|
|
|
}
|
|
|
|
|
}
|
2019-02-05 10:30:33 -05:00
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
impl EventLoop {
|
2023-08-30 10:54:46 +02:00
|
|
|
/// Create the event loop.
|
2022-06-11 18:57:19 +02:00
|
|
|
///
|
2023-08-30 10:54:46 +02:00
|
|
|
/// This is an alias of `EventLoop::builder().build()`.
|
2022-02-16 22:09:03 +01:00
|
|
|
#[inline]
|
2024-06-24 13:04:55 +03:00
|
|
|
pub fn new() -> Result<EventLoop, EventLoopError> {
|
2023-08-30 10:54:46 +02:00
|
|
|
Self::builder().build()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Start building a new event loop.
|
|
|
|
|
///
|
|
|
|
|
/// This returns an [`EventLoopBuilder`], to allow configuring the event loop before creation.
|
|
|
|
|
///
|
|
|
|
|
/// To get the actual event loop, call [`build`][EventLoopBuilder::build] on that.
|
|
|
|
|
#[inline]
|
2024-06-24 13:04:55 +03:00
|
|
|
pub fn builder() -> EventLoopBuilder {
|
|
|
|
|
EventLoopBuilder { platform_specific: Default::default() }
|
2019-02-05 10:30:33 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
impl EventLoop {
|
2024-02-23 14:37:21 +04:00
|
|
|
/// Run the application with the event loop on the calling thread.
|
2023-04-11 12:50:52 +01:00
|
|
|
///
|
2023-09-07 08:25:04 +02:00
|
|
|
/// See the [`set_control_flow()`] docs on how to change the event loop's behavior.
|
2019-02-05 10:30:33 -05:00
|
|
|
///
|
2022-01-11 01:23:20 +01:00
|
|
|
/// ## Platform-specific
|
|
|
|
|
///
|
2023-04-11 12:50:52 +01:00
|
|
|
/// - **iOS:** Will never return to the caller and so values not passed to this function will
|
|
|
|
|
/// *not* be dropped before the process exits.
|
|
|
|
|
/// - **Web:** Will _act_ as if it never returns to the caller by throwing a Javascript
|
|
|
|
|
/// exception (that Rust doesn't see) that will also mean that the rest of the function is
|
|
|
|
|
/// never executed and any values not passed to this function will *not* be dropped.
|
|
|
|
|
///
|
2023-10-25 17:42:51 +02:00
|
|
|
/// Web applications are recommended to use
|
|
|
|
|
#[cfg_attr(
|
2024-07-10 16:17:39 +02:00
|
|
|
any(web_platform, docsrs),
|
|
|
|
|
doc = " [`EventLoopExtWeb::spawn_app()`][crate::platform::web::EventLoopExtWeb::spawn_app()]"
|
2023-10-25 17:42:51 +02:00
|
|
|
)]
|
2024-07-10 16:17:39 +02:00
|
|
|
#[cfg_attr(not(any(web_platform, docsrs)), doc = " `EventLoopExtWeb::spawn_app()`")]
|
|
|
|
|
/// [^1] instead of [`run_app()`] to avoid the need for the Javascript exception trick, and to
|
|
|
|
|
/// make it clearer that the event loop runs asynchronously (via the browser's own,
|
|
|
|
|
/// internal, event loop) and doesn't block the current thread of execution like it does
|
|
|
|
|
/// on other platforms.
|
2022-01-11 01:23:20 +01:00
|
|
|
///
|
2023-08-06 01:56:56 +04:00
|
|
|
/// This function won't be available with `target_feature = "exception-handling"`.
|
|
|
|
|
///
|
2024-07-10 16:17:39 +02:00
|
|
|
/// [^1]: `spawn_app()` is only available on the Web platform.
|
|
|
|
|
///
|
2024-01-31 17:29:59 +04:00
|
|
|
/// [`set_control_flow()`]: ActiveEventLoop::set_control_flow()
|
2024-02-23 14:37:21 +04:00
|
|
|
/// [`run_app()`]: Self::run_app()
|
2019-02-05 10:30:33 -05:00
|
|
|
#[inline]
|
2024-01-14 18:54:52 +01:00
|
|
|
#[cfg(not(all(web_platform, target_feature = "exception-handling")))]
|
2024-07-11 15:38:09 +02:00
|
|
|
pub fn run_app<A: ApplicationHandler>(self, app: A) -> Result<(), EventLoopError> {
|
2024-05-20 20:27:36 +04:00
|
|
|
self.event_loop.run_app(app)
|
2019-02-05 10:30:33 -05:00
|
|
|
}
|
|
|
|
|
|
2024-02-01 14:27:44 +01:00
|
|
|
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
|
|
|
|
|
/// to the main event loop, possibly from another thread.
|
2024-06-24 13:04:55 +03:00
|
|
|
pub fn create_proxy(&self) -> EventLoopProxy {
|
2024-08-06 21:02:53 +03:00
|
|
|
self.event_loop.window_target().create_proxy()
|
2019-02-05 10:30:33 -05:00
|
|
|
}
|
2024-01-31 17:29:59 +04:00
|
|
|
|
|
|
|
|
/// Gets a persistent reference to the underlying platform display.
|
|
|
|
|
///
|
|
|
|
|
/// See the [`OwnedDisplayHandle`] type for more information.
|
|
|
|
|
pub fn owned_display_handle(&self) -> OwnedDisplayHandle {
|
2024-08-06 21:02:53 +03:00
|
|
|
self.event_loop.window_target().owned_display_handle()
|
2024-01-31 17:29:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Change if or when [`DeviceEvent`]s are captured.
|
|
|
|
|
///
|
|
|
|
|
/// See [`ActiveEventLoop::listen_device_events`] for details.
|
|
|
|
|
///
|
|
|
|
|
/// [`DeviceEvent`]: crate::event::DeviceEvent
|
|
|
|
|
pub fn listen_device_events(&self, allowed: DeviceEvents) {
|
2024-02-25 19:20:39 -08:00
|
|
|
let _span = tracing::debug_span!(
|
|
|
|
|
"winit::EventLoop::listen_device_events",
|
|
|
|
|
allowed = ?allowed
|
|
|
|
|
)
|
|
|
|
|
.entered();
|
2024-08-06 21:02:53 +03:00
|
|
|
self.event_loop.window_target().listen_device_events(allowed)
|
2024-01-31 17:29:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Sets the [`ControlFlow`].
|
|
|
|
|
pub fn set_control_flow(&self, control_flow: ControlFlow) {
|
2024-08-06 21:02:53 +03:00
|
|
|
self.event_loop.window_target().set_control_flow(control_flow);
|
2024-01-31 17:29:59 +04:00
|
|
|
}
|
|
|
|
|
|
2024-02-03 07:27:17 +04:00
|
|
|
/// Create custom cursor.
|
2024-08-06 18:57:03 +02:00
|
|
|
///
|
|
|
|
|
/// ## Platform-specific
|
|
|
|
|
///
|
|
|
|
|
/// **iOS / Android / Orbital:** Unsupported.
|
|
|
|
|
pub fn create_custom_cursor(
|
|
|
|
|
&self,
|
|
|
|
|
custom_cursor: CustomCursorSource,
|
|
|
|
|
) -> Result<CustomCursor, ExternalError> {
|
2024-08-06 21:02:53 +03:00
|
|
|
self.event_loop.window_target().create_custom_cursor(custom_cursor)
|
2024-02-03 07:27:17 +04:00
|
|
|
}
|
2020-07-04 15:46:41 -04:00
|
|
|
}
|
|
|
|
|
|
2023-10-14 19:07:39 -07:00
|
|
|
#[cfg(feature = "rwh_06")]
|
2024-06-24 13:04:55 +03:00
|
|
|
impl rwh_06::HasDisplayHandle for EventLoop {
|
2023-10-14 19:07:39 -07:00
|
|
|
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
|
2024-08-06 21:02:53 +03:00
|
|
|
rwh_06::HasDisplayHandle::display_handle(self.event_loop.window_target().rwh_06_handle())
|
2023-10-14 19:07:39 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-10-15 20:31:29 +04:00
|
|
|
#[cfg(any(x11_platform, wayland_platform))]
|
2024-06-24 13:04:55 +03:00
|
|
|
impl AsFd for EventLoop {
|
2023-10-15 20:31:29 +04:00
|
|
|
/// Get the underlying [EventLoop]'s `fd` which you can register
|
|
|
|
|
/// into other event loop, like [`calloop`] or [`mio`]. When doing so, the
|
2024-02-23 14:37:21 +04:00
|
|
|
/// loop must be polled with the [`pump_app_events`] API.
|
2023-10-15 20:31:29 +04:00
|
|
|
///
|
|
|
|
|
/// [`calloop`]: https://crates.io/crates/calloop
|
|
|
|
|
/// [`mio`]: https://crates.io/crates/mio
|
2024-02-23 14:37:21 +04:00
|
|
|
/// [`pump_app_events`]: crate::platform::pump_events::EventLoopExtPumpEvents::pump_app_events
|
2023-10-15 20:31:29 +04:00
|
|
|
fn as_fd(&self) -> BorrowedFd<'_> {
|
|
|
|
|
self.event_loop.as_fd()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(any(x11_platform, wayland_platform))]
|
2024-06-24 13:04:55 +03:00
|
|
|
impl AsRawFd for EventLoop {
|
2023-10-15 20:31:29 +04:00
|
|
|
/// Get the underlying [EventLoop]'s raw `fd` which you can register
|
|
|
|
|
/// into other event loop, like [`calloop`] or [`mio`]. When doing so, the
|
2024-02-23 14:37:21 +04:00
|
|
|
/// loop must be polled with the [`pump_app_events`] API.
|
2023-10-15 20:31:29 +04:00
|
|
|
///
|
|
|
|
|
/// [`calloop`]: https://crates.io/crates/calloop
|
|
|
|
|
/// [`mio`]: https://crates.io/crates/mio
|
2024-02-23 14:37:21 +04:00
|
|
|
/// [`pump_app_events`]: crate::platform::pump_events::EventLoopExtPumpEvents::pump_app_events
|
2023-10-15 20:31:29 +04:00
|
|
|
fn as_raw_fd(&self) -> RawFd {
|
|
|
|
|
self.event_loop.as_raw_fd()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-08-11 21:24:34 +03:00
|
|
|
pub trait ActiveEventLoop: AsAny {
|
2024-06-29 17:19:09 +02:00
|
|
|
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
|
|
|
|
|
/// to the main event loop, possibly from another thread.
|
2024-08-06 21:02:53 +03:00
|
|
|
fn create_proxy(&self) -> EventLoopProxy;
|
2024-06-29 17:19:09 +02:00
|
|
|
|
2024-01-31 17:29:59 +04:00
|
|
|
/// Create the window.
|
|
|
|
|
///
|
|
|
|
|
/// Possible causes of error include denied permission, incompatible system, and lack of memory.
|
|
|
|
|
///
|
|
|
|
|
/// ## Platform-specific
|
|
|
|
|
///
|
2024-07-10 16:17:39 +02:00
|
|
|
/// - **Web:** The window is created but not inserted into the Web page automatically. Please
|
|
|
|
|
/// see the Web platform module for more information.
|
2024-08-06 21:02:53 +03:00
|
|
|
fn create_window(&self, window_attributes: WindowAttributes) -> Result<Window, OsError>;
|
2019-05-29 21:29:54 -04:00
|
|
|
|
2024-02-03 07:27:17 +04:00
|
|
|
/// Create custom cursor.
|
2024-08-06 18:57:03 +02:00
|
|
|
///
|
|
|
|
|
/// ## Platform-specific
|
|
|
|
|
///
|
|
|
|
|
/// **iOS / Android / Orbital:** Unsupported.
|
2024-08-06 21:02:53 +03:00
|
|
|
fn create_custom_cursor(
|
2024-08-06 18:57:03 +02:00
|
|
|
&self,
|
|
|
|
|
custom_cursor: CustomCursorSource,
|
2024-08-06 21:02:53 +03:00
|
|
|
) -> Result<CustomCursor, ExternalError>;
|
2024-02-03 07:27:17 +04:00
|
|
|
|
2019-05-29 21:29:54 -04:00
|
|
|
/// Returns the list of all the monitors available on the system.
|
2024-07-23 20:33:10 +02:00
|
|
|
///
|
|
|
|
|
/// ## Platform-specific
|
|
|
|
|
///
|
|
|
|
|
/// **Web:** Only returns the current monitor without
|
|
|
|
|
#[cfg_attr(
|
|
|
|
|
any(web_platform, docsrs),
|
|
|
|
|
doc = "[detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
|
|
|
|
|
)]
|
|
|
|
|
#[cfg_attr(not(any(web_platform, docsrs)), doc = "detailed monitor permissions.")]
|
2024-08-06 21:02:53 +03:00
|
|
|
fn available_monitors(&self) -> Box<dyn Iterator<Item = MonitorHandle>>;
|
2019-05-29 21:29:54 -04:00
|
|
|
|
|
|
|
|
/// Returns the primary monitor of the system.
|
2020-09-07 20:20:47 +03:00
|
|
|
///
|
|
|
|
|
/// Returns `None` if it can't identify any monitor as a primary one.
|
|
|
|
|
///
|
|
|
|
|
/// ## Platform-specific
|
|
|
|
|
///
|
2024-07-23 20:33:10 +02:00
|
|
|
/// - **Wayland:** Always returns `None`.
|
|
|
|
|
/// - **Web:** Always returns `None` without
|
|
|
|
|
#[cfg_attr(
|
|
|
|
|
any(web_platform, docsrs),
|
|
|
|
|
doc = " [detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]."
|
|
|
|
|
)]
|
|
|
|
|
#[cfg_attr(not(any(web_platform, docsrs)), doc = " detailed monitor permissions.")]
|
2024-08-06 21:02:53 +03:00
|
|
|
fn primary_monitor(&self) -> Option<MonitorHandle>;
|
2022-06-07 23:17:45 +02:00
|
|
|
|
2023-05-30 21:32:31 +02:00
|
|
|
/// Change if or when [`DeviceEvent`]s are captured.
|
2022-06-07 23:17:45 +02:00
|
|
|
///
|
|
|
|
|
/// 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
|
2023-05-30 21:32:31 +02:00
|
|
|
/// this at runtime to explicitly capture them again.
|
2022-06-07 23:17:45 +02:00
|
|
|
///
|
|
|
|
|
/// ## Platform-specific
|
|
|
|
|
///
|
2023-06-14 10:26:26 +02:00
|
|
|
/// - **Wayland / macOS / iOS / Android / Orbital:** Unsupported.
|
2022-06-07 23:17:45 +02:00
|
|
|
///
|
|
|
|
|
/// [`DeviceEvent`]: crate::event::DeviceEvent
|
2024-08-06 21:02:53 +03:00
|
|
|
fn listen_device_events(&self, allowed: DeviceEvents);
|
2023-09-07 08:25:04 +02:00
|
|
|
|
2024-08-05 20:51:38 +02:00
|
|
|
/// Returns the current system theme.
|
|
|
|
|
///
|
|
|
|
|
/// Returns `None` if it cannot be determined on the current platform.
|
|
|
|
|
///
|
|
|
|
|
/// ## Platform-specific
|
|
|
|
|
///
|
|
|
|
|
/// - **iOS / Android / Wayland / x11 / Orbital:** Unsupported.
|
2024-08-06 21:02:53 +03:00
|
|
|
fn system_theme(&self) -> Option<Theme>;
|
2024-08-05 20:51:38 +02:00
|
|
|
|
2023-09-07 08:25:04 +02:00
|
|
|
/// Sets the [`ControlFlow`].
|
2024-08-06 21:02:53 +03:00
|
|
|
fn set_control_flow(&self, control_flow: ControlFlow);
|
2023-09-07 08:25:04 +02:00
|
|
|
|
|
|
|
|
/// Gets the current [`ControlFlow`].
|
2024-08-06 21:02:53 +03:00
|
|
|
fn control_flow(&self) -> ControlFlow;
|
2023-09-07 08:25:04 +02:00
|
|
|
|
|
|
|
|
/// This exits the event loop.
|
|
|
|
|
///
|
2024-06-24 13:04:55 +03:00
|
|
|
/// See [`exiting`][crate::application::ApplicationHandler::exiting].
|
2024-08-06 21:02:53 +03:00
|
|
|
fn exit(&self);
|
2023-09-07 08:25:04 +02:00
|
|
|
|
|
|
|
|
/// Returns if the [`EventLoop`] is about to stop.
|
|
|
|
|
///
|
2024-03-16 10:22:29 +01:00
|
|
|
/// See [`exit()`][Self::exit].
|
2024-08-06 21:02:53 +03:00
|
|
|
fn exiting(&self) -> bool;
|
2024-01-15 11:58:11 -08:00
|
|
|
|
|
|
|
|
/// Gets a persistent reference to the underlying platform display.
|
|
|
|
|
///
|
|
|
|
|
/// See the [`OwnedDisplayHandle`] type for more information.
|
2024-08-06 21:02:53 +03:00
|
|
|
fn owned_display_handle(&self) -> OwnedDisplayHandle;
|
2019-02-05 10:30:33 -05:00
|
|
|
|
2024-08-06 21:02:53 +03:00
|
|
|
/// Get the raw-window-handle handle.
|
|
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle;
|
2023-10-14 19:07:39 -07:00
|
|
|
}
|
|
|
|
|
|
2024-08-11 21:24:34 +03:00
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
impl rwh_06::HasDisplayHandle for dyn ActiveEventLoop + '_ {
|
|
|
|
|
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
|
|
|
|
|
self.rwh_06_handle().display_handle()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-15 11:58:11 -08:00
|
|
|
/// A proxy for the underlying display handle.
|
|
|
|
|
///
|
|
|
|
|
/// The purpose of this type is to provide a cheaply clonable handle to the underlying
|
|
|
|
|
/// display handle. This is often used by graphics APIs to connect to the underlying APIs.
|
2024-01-31 17:29:59 +04:00
|
|
|
/// It is difficult to keep a handle to the [`EventLoop`] type or the [`ActiveEventLoop`]
|
2024-01-15 11:58:11 -08:00
|
|
|
/// 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.
|
2024-08-08 00:46:28 +02:00
|
|
|
#[derive(Clone, PartialEq, Eq)]
|
2024-01-15 11:58:11 -08:00
|
|
|
pub struct OwnedDisplayHandle {
|
2024-08-04 00:18:39 +02:00
|
|
|
#[cfg_attr(not(feature = "rwh_06"), allow(dead_code))]
|
2024-08-06 21:02:53 +03:00
|
|
|
pub(crate) platform: platform_impl::OwnedDisplayHandle,
|
2024-01-15 11:58:11 -08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl fmt::Debug for OwnedDisplayHandle {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
|
f.debug_struct("OwnedDisplayHandle").finish_non_exhaustive()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(feature = "rwh_06")]
|
|
|
|
|
impl rwh_06::HasDisplayHandle for OwnedDisplayHandle {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn display_handle(&self) -> Result<rwh_06::DisplayHandle<'_>, rwh_06::HandleError> {
|
|
|
|
|
let raw = self.platform.raw_display_handle_rwh_06()?;
|
|
|
|
|
|
|
|
|
|
// SAFETY: The underlying display handle should be safe.
|
|
|
|
|
let handle = unsafe { rwh_06::DisplayHandle::borrow_raw(raw) };
|
|
|
|
|
|
|
|
|
|
Ok(handle)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
/// Control the [`EventLoop`], possibly from a different thread, without referencing it directly.
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct EventLoopProxy {
|
2024-08-06 21:02:53 +03:00
|
|
|
pub(crate) event_loop_proxy: platform_impl::EventLoopProxy,
|
2019-08-06 05:51:42 +09:00
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
impl EventLoopProxy {
|
|
|
|
|
/// Wake up the [`EventLoop`], resulting in [`ApplicationHandler::proxy_wake_up()`] being
|
|
|
|
|
/// called.
|
2019-02-05 10:30:33 -05:00
|
|
|
///
|
2024-06-24 13:04:55 +03:00
|
|
|
/// Calls to this method are coalesced into a single call to [`proxy_wake_up`], see the
|
|
|
|
|
/// documentation on that for details.
|
2022-06-11 18:57:19 +02:00
|
|
|
///
|
2024-06-24 13:04:55 +03:00
|
|
|
/// If the event loop is no longer running, this is a no-op.
|
|
|
|
|
///
|
|
|
|
|
/// [`proxy_wake_up`]: 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.event_loop_proxy.wake_up();
|
2019-02-05 10:30:33 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-24 13:04:55 +03:00
|
|
|
impl fmt::Debug for EventLoopProxy {
|
2019-07-09 23:49:07 +02:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2024-08-08 00:46:28 +02:00
|
|
|
f.debug_struct("ActiveEventLoop").finish_non_exhaustive()
|
2019-02-05 10:30:33 -05:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-05-30 21:32:31 +02:00
|
|
|
/// Control when device events are captured.
|
|
|
|
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Default)]
|
2024-08-08 00:46:28 +02:00
|
|
|
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
2023-05-30 21:32:31 +02:00
|
|
|
pub enum DeviceEvents {
|
|
|
|
|
/// Report device events regardless of window focus.
|
2022-06-07 23:17:45 +02:00
|
|
|
Always,
|
2023-05-30 21:32:31 +02:00
|
|
|
/// Only capture device events while the window is focused.
|
|
|
|
|
#[default]
|
|
|
|
|
WhenFocused,
|
|
|
|
|
/// Never capture device events.
|
2022-06-07 23:17:45 +02:00
|
|
|
Never,
|
|
|
|
|
}
|
2023-07-20 13:16:51 +00:00
|
|
|
|
|
|
|
|
/// 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.
|
|
|
|
|
///
|
2024-02-19 11:58:44 +07:00
|
|
|
/// One of the handling scenarios could be to maintain a working list
|
2023-07-20 13:16:51 +00:00
|
|
|
/// 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.
|
2024-08-08 00:46:28 +02:00
|
|
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
2023-07-20 13:16:51 +00:00
|
|
|
pub struct AsyncRequestSerial {
|
2024-02-08 00:58:43 +04:00
|
|
|
serial: usize,
|
2023-07-20 13:16:51 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl AsyncRequestSerial {
|
2024-02-08 00:58:43 +04:00
|
|
|
// TODO(kchibisov): Remove `cfg` when the clipboard will be added.
|
2023-07-20 13:16:51 +00:00
|
|
|
#[allow(dead_code)]
|
|
|
|
|
pub(crate) fn get() -> Self {
|
2024-02-08 00:58:43 +04:00
|
|
|
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.
|
2023-07-20 13:16:51 +00:00
|
|
|
let serial = CURRENT_SERIAL.fetch_add(1, Ordering::Relaxed);
|
|
|
|
|
Self { serial }
|
|
|
|
|
}
|
|
|
|
|
}
|