2019-02-06 02:30:33 +11:00
|
|
|
//! The `EventLoop` struct and assorted supporting types, including `ControlFlow`.
|
|
|
|
//!
|
|
|
|
//! If you want to send custom events to the event loop, use [`EventLoop::create_proxy()`][create_proxy]
|
|
|
|
//! to acquire an [`EventLoopProxy`][event_loop_proxy] and call its [`send_event`][send_event] method.
|
|
|
|
//!
|
|
|
|
//! See the root-level documentation for information on how to create and use an event loop to
|
|
|
|
//! handle events.
|
|
|
|
//!
|
2019-11-12 10:05:59 +11:00
|
|
|
//! [create_proxy]: crate::event_loop::EventLoop::create_proxy
|
|
|
|
//! [event_loop_proxy]: crate::event_loop::EventLoopProxy
|
|
|
|
//! [send_event]: crate::event_loop::EventLoopProxy::send_event
|
2019-06-17 14:30:05 +10:00
|
|
|
use instant::Instant;
|
2022-02-17 08:09:03 +11:00
|
|
|
use std::marker::PhantomData;
|
2019-02-06 02:30:33 +11:00
|
|
|
use std::ops::Deref;
|
2019-06-25 11:15:34 +10:00
|
|
|
use std::{error, fmt};
|
2019-02-06 02:30:33 +11:00
|
|
|
|
2019-10-06 00:49:24 +10:00
|
|
|
use crate::{event::Event, monitor::MonitorHandle, platform_impl};
|
2019-02-06 02:30:33 +11:00
|
|
|
|
|
|
|
/// Provides a way to retrieve events from the system and from the windows that were registered to
|
|
|
|
/// the events loop.
|
|
|
|
///
|
|
|
|
/// An `EventLoop` can be seen more or less as a "context". Calling `EventLoop::new()`
|
|
|
|
/// initializes everything that will be required to create windows. For example on Linux creating
|
2019-06-22 10:34:55 +10:00
|
|
|
/// an event loop opens a connection to the X or Wayland server.
|
2019-02-06 02:30:33 +11:00
|
|
|
///
|
|
|
|
/// To wake up an `EventLoop` from a another thread, see the `EventLoopProxy` docs.
|
|
|
|
///
|
|
|
|
/// Note that the `EventLoop` 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 `EventLoop` _can_ be sent to an other thread, and the
|
2019-06-22 10:34:55 +10:00
|
|
|
/// `EventLoopProxy` allows you to wake up an `EventLoop` from another thread.
|
2019-10-19 02:51:06 +11:00
|
|
|
///
|
2019-02-06 02:30:33 +11:00
|
|
|
pub struct EventLoop<T: 'static> {
|
|
|
|
pub(crate) event_loop: platform_impl::EventLoop<T>,
|
2022-02-17 08:09:03 +11:00
|
|
|
pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Target that associates windows with an `EventLoop`.
|
|
|
|
///
|
2019-07-13 09:05:07 +10:00
|
|
|
/// This type exists to allow you to create new windows while Winit executes
|
|
|
|
/// your callback. `EventLoop` will coerce into this type (`impl<T> Deref for
|
|
|
|
/// EventLoop<T>`), so functions that take this as a parameter can also take
|
|
|
|
/// `&EventLoop`.
|
2019-02-06 02:30:33 +11:00
|
|
|
pub struct EventLoopWindowTarget<T: 'static> {
|
|
|
|
pub(crate) p: platform_impl::EventLoopWindowTarget<T>,
|
2022-02-17 08:09:03 +11:00
|
|
|
pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync
|
|
|
|
}
|
|
|
|
|
|
|
|
/// 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.
|
2022-03-30 19:30:45 +11:00
|
|
|
#[derive(Default)]
|
2022-02-17 08:09:03 +11:00
|
|
|
pub struct EventLoopBuilder<T: 'static> {
|
|
|
|
pub(crate) platform_specific: platform_impl::PlatformSpecificEventLoopAttributes,
|
|
|
|
_p: PhantomData<T>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EventLoopBuilder<()> {
|
|
|
|
/// Start building a new event loop.
|
|
|
|
#[inline]
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self::with_user_event()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> EventLoopBuilder<T> {
|
|
|
|
/// Start building a new event loop, with the given type as the user event
|
|
|
|
/// type.
|
|
|
|
#[inline]
|
|
|
|
pub fn with_user_event() -> Self {
|
|
|
|
Self {
|
|
|
|
platform_specific: Default::default(),
|
|
|
|
_p: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Builds a new event loop.
|
|
|
|
///
|
|
|
|
/// ***For cross-platform compatibility, the `EventLoop` must be created on the main thread.***
|
|
|
|
/// Attempting to create the event loop on a different 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.
|
|
|
|
///
|
|
|
|
/// Usage will result in display backend initialisation, this can be controlled on linux
|
|
|
|
/// using an environment variable `WINIT_UNIX_BACKEND`. Legal values are `x11` and `wayland`.
|
|
|
|
/// If it is not set, winit will try to connect to a wayland connection, and if it fails will
|
|
|
|
/// fallback on x11. If this variable is set with any other value, winit will panic.
|
|
|
|
///
|
|
|
|
/// ## Platform-specific
|
|
|
|
///
|
|
|
|
/// - **iOS:** Can only be called on the main thread.
|
|
|
|
#[inline]
|
|
|
|
pub fn build(&mut self) -> EventLoop<T> {
|
|
|
|
EventLoop {
|
2022-03-30 19:30:45 +11:00
|
|
|
event_loop: platform_impl::EventLoop::new(&mut self.platform_specific),
|
2022-02-17 08:09:03 +11:00
|
|
|
_marker: PhantomData,
|
|
|
|
}
|
|
|
|
}
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> fmt::Debug for EventLoop<T> {
|
2019-07-10 07:49:07 +10:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.pad("EventLoop { .. }")
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> fmt::Debug for EventLoopWindowTarget<T> {
|
2019-07-10 07:49:07 +10:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.pad("EventLoopWindowTarget { .. }")
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Set by the user callback given to the `EventLoop::run` method.
|
|
|
|
///
|
2019-12-22 16:47:39 +11:00
|
|
|
/// Indicates the desired behavior of the event loop after [`Event::RedrawEventsCleared`][events_cleared]
|
2019-02-06 02:30:33 +11:00
|
|
|
/// is emitted. Defaults to `Poll`.
|
|
|
|
///
|
|
|
|
/// ## Persistency
|
|
|
|
/// Almost every change is persistent between multiple calls to the event loop closure within a
|
2022-01-11 11:23:20 +11:00
|
|
|
/// given run loop. The only exception to this is `ExitWithCode` which, once set, cannot be unset.
|
|
|
|
/// Changes are **not** persistent between multiple calls to `run_return` - issuing a new call will
|
|
|
|
/// reset the control flow to `Poll`.
|
2019-02-06 02:30:33 +11:00
|
|
|
///
|
2019-12-22 16:47:39 +11:00
|
|
|
/// [events_cleared]: crate::event::Event::RedrawEventsCleared
|
2019-06-17 14:30:05 +10:00
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
2019-02-06 02:30:33 +11:00
|
|
|
pub enum ControlFlow {
|
|
|
|
/// When the current loop iteration finishes, immediately begin a new iteration regardless of
|
2020-08-30 23:15:44 +10:00
|
|
|
/// whether or not new events are available to process.
|
|
|
|
///
|
2020-09-25 00:30:26 +10:00
|
|
|
/// ## Platform-specific
|
|
|
|
/// - **Web:** Events are queued and usually sent when `requestAnimationFrame` fires but sometimes
|
|
|
|
/// the events in the queue may be sent before the next `requestAnimationFrame` callback, for
|
|
|
|
/// example when the scaling of the page has changed. This should be treated as an implementation
|
|
|
|
/// detail which should not be relied on.
|
2019-02-06 02:30:33 +11:00
|
|
|
Poll,
|
|
|
|
/// When the current loop iteration finishes, suspend the thread until another event arrives.
|
|
|
|
Wait,
|
|
|
|
/// When the current loop iteration finishes, suspend the thread until either another event
|
|
|
|
/// arrives or the given time is reached.
|
|
|
|
WaitUntil(Instant),
|
|
|
|
/// Send a `LoopDestroyed` event and stop the event loop. This variant is *sticky* - once set,
|
2022-01-11 11:23:20 +11:00
|
|
|
/// `control_flow` cannot be changed from `ExitWithCode`, and any future attempts to do so will
|
|
|
|
/// result in the `control_flow` parameter being reset to `ExitWithCode`.
|
|
|
|
///
|
|
|
|
/// The contained number will be used as exit code. The [`Exit`] constant is a shortcut for this
|
|
|
|
/// with exit code 0.
|
|
|
|
///
|
|
|
|
/// ## Platform-specific
|
|
|
|
///
|
|
|
|
/// - **Android / iOS / WASM**: The supplied exit code is unused.
|
|
|
|
/// - **Unix**: On most Unix-like platforms, only the 8 least significant bits will be used,
|
|
|
|
/// which can cause surprises with negative exit values (`-42` would end up as `214`). See
|
|
|
|
/// [`std::process::exit`].
|
|
|
|
///
|
|
|
|
/// [`Exit`]: ControlFlow::Exit
|
|
|
|
ExitWithCode(i32),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ControlFlow {
|
|
|
|
/// Alias for [`ExitWithCode`]`(0)`.
|
|
|
|
///
|
|
|
|
/// [`ExitWithCode`]: ControlFlow::ExitWithCode
|
|
|
|
#[allow(non_upper_case_globals)]
|
|
|
|
pub const Exit: Self = Self::ExitWithCode(0);
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for ControlFlow {
|
|
|
|
#[inline(always)]
|
|
|
|
fn default() -> ControlFlow {
|
|
|
|
ControlFlow::Poll
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl EventLoop<()> {
|
2022-02-17 08:09:03 +11:00
|
|
|
/// Alias for `EventLoopBuilder::new().build()`.
|
|
|
|
#[inline]
|
2019-02-06 02:30:33 +11:00
|
|
|
pub fn new() -> EventLoop<()> {
|
2022-02-17 08:09:03 +11:00
|
|
|
EventLoopBuilder::new().build()
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> EventLoop<T> {
|
2022-02-20 02:21:37 +11:00
|
|
|
#[deprecated = "Use `EventLoopBuilder::<T>::with_user_event().build()` instead."]
|
2019-07-30 00:58:16 +10:00
|
|
|
pub fn with_user_event() -> EventLoop<T> {
|
2022-02-17 08:09:03 +11:00
|
|
|
EventLoopBuilder::<T>::with_user_event().build()
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
|
2019-06-22 10:34:55 +10:00
|
|
|
/// Hijacks the calling thread and initializes the winit event loop with the provided
|
2019-02-06 02:30:33 +11:00
|
|
|
/// closure. Since the closure is `'static`, it must be a `move` closure if it needs to
|
|
|
|
/// access any data from the calling context.
|
|
|
|
///
|
|
|
|
/// See the [`ControlFlow`] docs for information on how changes to `&mut ControlFlow` impact the
|
|
|
|
/// event loop's behavior.
|
|
|
|
///
|
|
|
|
/// Any values not passed to this function will *not* be dropped.
|
|
|
|
///
|
2022-01-11 11:23:20 +11:00
|
|
|
/// ## Platform-specific
|
|
|
|
///
|
|
|
|
/// - **X11 / Wayland**: The program terminates with exit code 1 if the display server
|
|
|
|
/// disconnects.
|
|
|
|
///
|
2019-11-12 10:05:59 +11:00
|
|
|
/// [`ControlFlow`]: crate::event_loop::ControlFlow
|
2019-02-06 02:30:33 +11:00
|
|
|
#[inline]
|
|
|
|
pub fn run<F>(self, event_handler: F) -> !
|
2019-06-25 11:15:34 +10:00
|
|
|
where
|
2019-06-20 06:49:43 +10:00
|
|
|
F: 'static + FnMut(Event<'_, T>, &EventLoopWindowTarget<T>, &mut ControlFlow),
|
2019-02-06 02:30:33 +11:00
|
|
|
{
|
|
|
|
self.event_loop.run(event_handler)
|
|
|
|
}
|
|
|
|
|
2019-05-30 11:29:54 +10:00
|
|
|
/// Creates an `EventLoopProxy` that can be used to dispatch user events to the main event loop.
|
2019-02-06 02:30:33 +11:00
|
|
|
pub fn create_proxy(&self) -> EventLoopProxy<T> {
|
|
|
|
EventLoopProxy {
|
|
|
|
event_loop_proxy: self.event_loop.create_proxy(),
|
|
|
|
}
|
|
|
|
}
|
2020-07-05 05:46:41 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Deref for EventLoop<T> {
|
|
|
|
type Target = EventLoopWindowTarget<T>;
|
|
|
|
fn deref(&self) -> &EventLoopWindowTarget<T> {
|
|
|
|
self.event_loop.window_target()
|
|
|
|
}
|
|
|
|
}
|
2019-05-30 11:29:54 +10:00
|
|
|
|
2020-07-05 05:46:41 +10:00
|
|
|
impl<T> EventLoopWindowTarget<T> {
|
2019-05-30 11:29:54 +10:00
|
|
|
/// Returns the list of all the monitors available on the system.
|
|
|
|
#[inline]
|
2019-06-18 04:27:00 +10:00
|
|
|
pub fn available_monitors(&self) -> impl Iterator<Item = MonitorHandle> {
|
2020-07-05 05:46:41 +10:00
|
|
|
self.p
|
2019-10-06 00:49:24 +10:00
|
|
|
.available_monitors()
|
|
|
|
.into_iter()
|
|
|
|
.map(|inner| MonitorHandle { inner })
|
2019-05-30 11:29:54 +10:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns the primary monitor of the system.
|
2020-09-08 03:20:47 +10:00
|
|
|
///
|
|
|
|
/// Returns `None` if it can't identify any monitor as a primary one.
|
|
|
|
///
|
|
|
|
/// ## Platform-specific
|
|
|
|
///
|
|
|
|
/// **Wayland:** Always returns `None`.
|
2019-05-30 11:29:54 +10:00
|
|
|
#[inline]
|
2020-09-08 03:20:47 +10:00
|
|
|
pub fn primary_monitor(&self) -> Option<MonitorHandle> {
|
|
|
|
self.p.primary_monitor()
|
2019-05-30 11:29:54 +10:00
|
|
|
}
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Used to send custom events to `EventLoop`.
|
2019-02-21 20:51:43 +11:00
|
|
|
pub struct EventLoopProxy<T: 'static> {
|
2019-02-06 02:30:33 +11:00
|
|
|
event_loop_proxy: platform_impl::EventLoopProxy<T>,
|
|
|
|
}
|
|
|
|
|
2019-08-06 06:51:42 +10:00
|
|
|
impl<T: 'static> Clone for EventLoopProxy<T> {
|
|
|
|
fn clone(&self) -> Self {
|
|
|
|
Self {
|
|
|
|
event_loop_proxy: self.event_loop_proxy.clone(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-21 20:51:43 +11:00
|
|
|
impl<T: 'static> EventLoopProxy<T> {
|
2019-02-06 02:30:33 +11:00
|
|
|
/// Send an event to the `EventLoop` from which this proxy was created. This emits a
|
|
|
|
/// `UserEvent(event)` event in the event loop, where `event` is the value passed to this
|
|
|
|
/// function.
|
|
|
|
///
|
|
|
|
/// Returns an `Err` if the associated `EventLoop` no longer exists.
|
2019-12-08 04:22:03 +11:00
|
|
|
pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed<T>> {
|
2019-02-06 02:30:33 +11:00
|
|
|
self.event_loop_proxy.send_event(event)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-21 20:51:43 +11:00
|
|
|
impl<T: 'static> fmt::Debug for EventLoopProxy<T> {
|
2019-07-10 07:49:07 +10:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
|
|
f.pad("EventLoopProxy { .. }")
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The error that is returned when an `EventLoopProxy` attempts to wake up an `EventLoop` that
|
2019-12-08 04:22:03 +11:00
|
|
|
/// no longer exists. Contains the original event given to `send_event`.
|
|
|
|
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
|
|
|
|
pub struct EventLoopClosed<T>(pub T);
|
2019-02-06 02:30:33 +11:00
|
|
|
|
2020-01-10 16:29:31 +11:00
|
|
|
impl<T> fmt::Display for EventLoopClosed<T> {
|
2019-06-18 04:27:00 +10:00
|
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
2020-01-10 16:29:31 +11:00
|
|
|
f.write_str("Tried to wake up a closed `EventLoop`")
|
2019-02-06 02:30:33 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-10 16:29:31 +11:00
|
|
|
impl<T: fmt::Debug> error::Error for EventLoopClosed<T> {}
|