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.
|
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};
|
2025-05-02 13:28:57 +09:00
|
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
2024-07-07 18:38:50 +02:00
|
|
|
|
2024-11-13 15:29:05 +03:00
|
|
|
use rwh_06::{DisplayHandle, HandleError, HasDisplayHandle};
|
2025-05-02 13:28:57 +09:00
|
|
|
pub use winit_core::event_loop::*;
|
2022-06-22 19:43:25 +02:00
|
|
|
|
2024-02-23 14:37:21 +04:00
|
|
|
use crate::application::ApplicationHandler;
|
2025-05-03 18:24:44 +09:00
|
|
|
use crate::cursor::{CustomCursor, CustomCursorSource};
|
2024-09-06 17:20:11 +03:00
|
|
|
use crate::error::{EventLoopError, RequestError};
|
2019-10-05 16:49:24 +02:00
|
|
|
use crate::platform_impl;
|
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
|
2025-03-03 08:40:04 +01:00
|
|
|
#[derive(Debug)]
|
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`].
|
2025-03-03 08:40:04 +01:00
|
|
|
#[derive(Default, Debug, 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.
|
2024-10-14 03:34:11 +09:00
|
|
|
/// `EventLoopBuilderExt::with_any_thread` functions are exposed in the relevant
|
2023-08-13 23:20:09 +04:00
|
|
|
/// [`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-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-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
|
|
|
///
|
2025-05-03 21:25:22 +09:00
|
|
|
/// The `app` is dropped when the event loop is shut down.
|
|
|
|
|
///
|
2025-03-17 10:56:00 +01:00
|
|
|
/// ## Event loop flow
|
|
|
|
|
///
|
|
|
|
|
/// This function internally handles the different parts of a traditional event-handling loop.
|
|
|
|
|
/// You can imagine this method as being implemented like this:
|
|
|
|
|
///
|
|
|
|
|
/// ```rust,ignore
|
|
|
|
|
/// let mut start_cause = StartCause::Init;
|
|
|
|
|
///
|
|
|
|
|
/// // Run the event loop.
|
|
|
|
|
/// while !event_loop.exiting() {
|
|
|
|
|
/// // Wake up.
|
|
|
|
|
/// app.new_events(event_loop, start_cause);
|
|
|
|
|
///
|
|
|
|
|
/// // Indicate that surfaces can now safely be created.
|
|
|
|
|
/// if start_cause == StartCause::Init {
|
|
|
|
|
/// app.can_create_surfaces(event_loop);
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// // Handle proxy wake-up event.
|
|
|
|
|
/// if event_loop.proxy_wake_up_set() {
|
|
|
|
|
/// event_loop.proxy_wake_up_clear();
|
|
|
|
|
/// app.proxy_wake_up(event_loop);
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// // Handle actions done by the user / system such as moving the cursor, resizing the
|
|
|
|
|
/// // window, changing the window theme, etc.
|
|
|
|
|
/// for event in event_loop.events() {
|
|
|
|
|
/// match event {
|
|
|
|
|
/// window event => app.window_event(event_loop, window_id, event),
|
|
|
|
|
/// device event => app.device_event(event_loop, device_id, event),
|
|
|
|
|
/// }
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// // Handle redraws.
|
|
|
|
|
/// for window_id in event_loop.pending_redraws() {
|
|
|
|
|
/// app.window_event(event_loop, window_id, WindowEvent::RedrawRequested);
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// // Done handling events, wait until we're woken up again.
|
|
|
|
|
/// app.about_to_wait(event_loop);
|
|
|
|
|
/// start_cause = event_loop.wait_if_necessary();
|
|
|
|
|
/// }
|
|
|
|
|
///
|
|
|
|
|
/// // Finished running, drop application state.
|
|
|
|
|
/// drop(app);
|
|
|
|
|
/// ```
|
|
|
|
|
///
|
|
|
|
|
/// This is of course a very coarse-grained overview, and leaves out timing details like
|
|
|
|
|
/// [`ControlFlow::WaitUntil`] and life-cycle methods like [`ApplicationHandler::resumed`], but
|
|
|
|
|
/// it should give you an idea of how things fit together.
|
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(
|
2025-02-08 14:19:58 +03:00
|
|
|
web_platform,
|
2024-07-10 16:17:39 +02:00
|
|
|
doc = " [`EventLoopExtWeb::spawn_app()`][crate::platform::web::EventLoopExtWeb::spawn_app()]"
|
2023-10-25 17:42:51 +02:00
|
|
|
)]
|
2025-02-08 14:19:58 +03:00
|
|
|
#[cfg_attr(not(web_platform), doc = " `EventLoopExtWeb::spawn_app()`")]
|
2024-07-10 16:17:39 +02:00
|
|
|
/// [^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,
|
2024-09-06 17:20:11 +03:00
|
|
|
) -> Result<CustomCursor, RequestError> {
|
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
|
|
|
}
|
|
|
|
|
|
2024-11-13 15:29:05 +03:00
|
|
|
impl HasDisplayHandle for EventLoop {
|
|
|
|
|
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
|
|
|
|
|
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
|
2025-05-20 16:56:53 +02:00
|
|
|
/// [`pump_app_events`]: crate::event_loop::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
|
2025-05-20 16:56:53 +02:00
|
|
|
/// [`pump_app_events`]: crate::event_loop::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()
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-20 16:56:53 +02:00
|
|
|
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
windows_platform,
|
|
|
|
|
macos_platform,
|
|
|
|
|
android_platform,
|
|
|
|
|
x11_platform,
|
|
|
|
|
wayland_platform,
|
|
|
|
|
docsrs,
|
|
|
|
|
))]
|
|
|
|
|
impl winit_core::event_loop::pump_events::EventLoopExtPumpEvents for EventLoop {
|
|
|
|
|
fn pump_app_events<A: ApplicationHandler>(
|
|
|
|
|
&mut self,
|
|
|
|
|
timeout: Option<std::time::Duration>,
|
|
|
|
|
app: A,
|
|
|
|
|
) -> winit_core::event_loop::pump_events::PumpStatus {
|
|
|
|
|
self.event_loop.pump_app_events(timeout, app)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(unused_imports)]
|
|
|
|
|
#[cfg(any(
|
|
|
|
|
windows_platform,
|
|
|
|
|
macos_platform,
|
|
|
|
|
android_platform,
|
|
|
|
|
x11_platform,
|
|
|
|
|
wayland_platform,
|
|
|
|
|
docsrs,
|
|
|
|
|
))]
|
|
|
|
|
impl winit_core::event_loop::run_on_demand::EventLoopExtRunOnDemand for EventLoop {
|
|
|
|
|
fn run_app_on_demand<A: ApplicationHandler>(&mut self, app: A) -> Result<(), EventLoopError> {
|
|
|
|
|
self.event_loop.run_app_on_demand(app)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-24 13:29:53 +02:00
|
|
|
#[cfg(android_platform)]
|
|
|
|
|
impl winit_android::EventLoopExtAndroid for EventLoop {
|
|
|
|
|
fn android_app(&self) -> &winit_android::activity::AndroidApp {
|
|
|
|
|
&self.event_loop.android_app
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg(android_platform)]
|
|
|
|
|
impl winit_android::EventLoopBuilderExtAndroid for EventLoopBuilder {
|
|
|
|
|
fn with_android_app(&mut self, app: winit_android::activity::AndroidApp) -> &mut Self {
|
|
|
|
|
self.platform_specific.android_app = Some(app);
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn handle_volume_keys(&mut self) -> &mut Self {
|
|
|
|
|
self.platform_specific.ignore_volume_keys = false;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-25 05:13:25 +02:00
|
|
|
#[cfg(windows_platform)]
|
|
|
|
|
impl winit_win32::EventLoopBuilderExtWindows for EventLoopBuilder {
|
|
|
|
|
#[inline]
|
|
|
|
|
fn with_any_thread(&mut self, any_thread: bool) -> &mut Self {
|
|
|
|
|
self.platform_specific.any_thread = any_thread;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn with_dpi_aware(&mut self, dpi_aware: bool) -> &mut Self {
|
|
|
|
|
self.platform_specific.dpi_aware = dpi_aware;
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[inline]
|
|
|
|
|
fn with_msg_hook<F>(&mut self, callback: F) -> &mut Self
|
|
|
|
|
where
|
|
|
|
|
F: FnMut(*const core::ffi::c_void) -> bool + 'static,
|
|
|
|
|
{
|
|
|
|
|
self.platform_specific.msg_hook = Some(Box::new(callback));
|
|
|
|
|
self
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-20 16:56:53 +02:00
|
|
|
/// ```compile_error
|
|
|
|
|
/// use winit::event_loop::run_on_demand::EventLoopExtRunOnDemand;
|
|
|
|
|
/// use winit::event_loop::EventLoop;
|
|
|
|
|
///
|
|
|
|
|
/// let mut event_loop = EventLoop::new().unwrap();
|
|
|
|
|
/// event_loop.run_app_on_demand(|_, _| {
|
|
|
|
|
/// // Attempt to run the event loop re-entrantly; this must fail.
|
|
|
|
|
/// event_loop.run_app_on_demand(|_, _| {});
|
|
|
|
|
/// });
|
|
|
|
|
/// ```
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
fn test_run_on_demand_cannot_access_event_loop() {}
|