mirror of
https://github.com/rust-windowing/winit.git
synced 2026-08-29 04:40:04 -04:00
winit-core: add EventLoopProvider for common methods
Thus implementing winit main event loop API is standardized.
This commit is contained in:
@@ -125,7 +125,7 @@ pub trait ApplicationHandler {
|
|||||||
/// use std::thread;
|
/// use std::thread;
|
||||||
/// use std::time::Duration;
|
/// use std::time::Duration;
|
||||||
///
|
///
|
||||||
/// use winit::event_loop::EventLoop;
|
/// use winit::event_loop::{EventLoop, EventLoopProvider};
|
||||||
/// use winit_core::application::ApplicationHandler;
|
/// use winit_core::application::ApplicationHandler;
|
||||||
/// use winit_core::event_loop::ActiveEventLoop;
|
/// use winit_core::event_loop::ActiveEventLoop;
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -11,14 +11,104 @@ use std::time::Duration;
|
|||||||
use rwh_06::{DisplayHandle, HandleError, HasDisplayHandle};
|
use rwh_06::{DisplayHandle, HandleError, HasDisplayHandle};
|
||||||
|
|
||||||
use crate::Instant;
|
use crate::Instant;
|
||||||
|
use crate::application::ApplicationHandler;
|
||||||
use crate::as_any::AsAny;
|
use crate::as_any::AsAny;
|
||||||
use crate::cursor::{CustomCursor, CustomCursorSource};
|
use crate::cursor::{CustomCursor, CustomCursorSource};
|
||||||
use crate::data_transfer::{DataTransfer, DataTransferId, DataTransferSend, TransferType};
|
use crate::data_transfer::{DataTransfer, DataTransferId, DataTransferSend, TransferType};
|
||||||
use crate::error::{NotSupportedError, RequestError};
|
use crate::error::{EventLoopError, NotSupportedError, RequestError};
|
||||||
use crate::icon::Icon;
|
use crate::icon::Icon;
|
||||||
use crate::monitor::MonitorHandle;
|
use crate::monitor::MonitorHandle;
|
||||||
use crate::window::{Theme, Window, WindowAttributes, WindowId};
|
use crate::window::{Theme, Window, WindowAttributes, WindowId};
|
||||||
|
|
||||||
|
/// Common methods to implement for the platform event loop.
|
||||||
|
pub trait EventLoopProvider: fmt::Debug {
|
||||||
|
/// Run the event loop with the given application on the calling thread.
|
||||||
|
///
|
||||||
|
/// The `app` is dropped when the event loop is shut down.
|
||||||
|
///
|
||||||
|
/// ## 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.
|
||||||
|
///
|
||||||
|
/// ## Returns
|
||||||
|
///
|
||||||
|
/// The semantics of this function is defined by the target platform. Consult the implementor
|
||||||
|
/// docs for details.
|
||||||
|
fn run_app<A: ApplicationHandler + 'static>(self, app: A) -> Result<(), EventLoopError>;
|
||||||
|
|
||||||
|
/// 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;
|
||||||
|
|
||||||
|
/// Gets a persistent reference to the underlying platform display.
|
||||||
|
///
|
||||||
|
/// See the [`OwnedDisplayHandle`] type for more information.
|
||||||
|
fn owned_display_handle(&self) -> OwnedDisplayHandle;
|
||||||
|
|
||||||
|
/// Change if or when [`DeviceEvent`]s are captured.
|
||||||
|
///
|
||||||
|
/// See [`ActiveEventLoop::listen_device_events`] for details.
|
||||||
|
///
|
||||||
|
/// [`DeviceEvent`]: crate::event::DeviceEvent
|
||||||
|
fn listen_device_events(&self, allowed: DeviceEvents);
|
||||||
|
|
||||||
|
/// Sets the [`ControlFlow`].
|
||||||
|
fn set_control_flow(&self, control_flow: ControlFlow);
|
||||||
|
|
||||||
|
/// Create custom cursor.
|
||||||
|
fn create_custom_cursor(
|
||||||
|
&self,
|
||||||
|
custom_cursor: CustomCursorSource,
|
||||||
|
) -> Result<CustomCursor, RequestError>;
|
||||||
|
}
|
||||||
|
|
||||||
pub trait ActiveEventLoop: AsAny + fmt::Debug {
|
pub trait ActiveEventLoop: AsAny + fmt::Debug {
|
||||||
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
|
/// Creates an [`EventLoopProxy`] that can be used to dispatch user events
|
||||||
/// to the main event loop, possibly from another thread.
|
/// to the main event loop, possibly from another thread.
|
||||||
|
|||||||
@@ -6,11 +6,13 @@ use crate::{
|
|||||||
window::Window,
|
window::Window,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Additional methods on [`EventLoop`] to return control flow to the caller.
|
/// Additional methods for [`EventLoopProvider`] to return control flow to the caller.
|
||||||
|
///
|
||||||
|
/// [`EventLoopProvider`]: crate::event_loop::EventLoopProvider
|
||||||
pub trait EventLoopExtRunOnDemand {
|
pub trait EventLoopExtRunOnDemand {
|
||||||
/// Run the application with the event loop on the calling thread.
|
/// Run the application with the event loop on the calling thread.
|
||||||
///
|
///
|
||||||
/// Unlike [`EventLoop::run_app`], this function accepts non-`'static` (i.e. non-`move`)
|
/// Unlike [`EventLoopProvider::run_app`], this function accepts non-`'static` (i.e. non-`move`)
|
||||||
/// state and it is possible to return control back to the caller without consuming the
|
/// state and it is possible to return control back to the caller without consuming the
|
||||||
/// `EventLoop` (by using [`exit()`]) and so the event loop can be re-run after it has exit.
|
/// `EventLoop` (by using [`exit()`]) and so the event loop can be re-run after it has exit.
|
||||||
///
|
///
|
||||||
@@ -32,8 +34,8 @@ pub trait EventLoopExtRunOnDemand {
|
|||||||
/// to the caller (specifically this is impossible on iOS and Web).
|
/// to the caller (specifically this is impossible on iOS and Web).
|
||||||
/// - No [`Window`] state can be carried between separate runs of the event loop.
|
/// - No [`Window`] state can be carried between separate runs of the event loop.
|
||||||
///
|
///
|
||||||
/// You are strongly encouraged to use [`EventLoop::run_app()`] for portability, unless you
|
/// You are strongly encouraged to use [`EventLoopProvider::run_app`] for portability, unless
|
||||||
/// specifically need the ability to re-run a single event loop more than once
|
/// you specifically need the ability to re-run a single event loop more than once
|
||||||
///
|
///
|
||||||
/// # Supported Platforms
|
/// # Supported Platforms
|
||||||
/// - Windows
|
/// - Windows
|
||||||
@@ -50,5 +52,6 @@ pub trait EventLoopExtRunOnDemand {
|
|||||||
///
|
///
|
||||||
/// [`exit()`]: ActiveEventLoop::exit()
|
/// [`exit()`]: ActiveEventLoop::exit()
|
||||||
/// [`set_control_flow()`]: ActiveEventLoop::set_control_flow()
|
/// [`set_control_flow()`]: ActiveEventLoop::set_control_flow()
|
||||||
|
/// [`EventLoopProvider::run_app`]: crate::event_loop::EventLoopProvider::run_app
|
||||||
fn run_app_on_demand<A: ApplicationHandler>(&mut self, app: A) -> Result<(), EventLoopError>;
|
fn run_app_on_demand<A: ApplicationHandler>(&mut self, app: A) -> Result<(), EventLoopError>;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ changelog entry.
|
|||||||
matching release of a click that activated a previously inactive window are tagged, so
|
matching release of a click that activated a previously inactive window are tagged, so
|
||||||
applications can ignore activation clicks for buttons or destructive actions while accepting
|
applications can ignore activation clicks for buttons or destructive actions while accepting
|
||||||
them for low-risk actions like selection or scrolling. Always `false` on other platforms.
|
them for low-risk actions like selection or scrolling. Always `false` on other platforms.
|
||||||
|
- `winit::event_loop::EventLoopProvider` trait with common event loop methods.
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
|||||||
@@ -120,58 +120,7 @@ impl EventLoop {
|
|||||||
|
|
||||||
/// Run the event loop with the given application on the calling thread.
|
/// Run the event loop with the given application on the calling thread.
|
||||||
///
|
///
|
||||||
/// The `app` is dropped when the event loop is shut down.
|
/// For details see [`EventLoopProvider`].
|
||||||
///
|
|
||||||
/// ## 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.
|
|
||||||
///
|
///
|
||||||
/// ## Returns
|
/// ## Returns
|
||||||
///
|
///
|
||||||
@@ -200,6 +149,7 @@ impl EventLoop {
|
|||||||
/// [`run_app_on_demand`]: crate::event_loop::run_on_demand::EventLoopExtRunOnDemand::run_app_on_demand
|
/// [`run_app_on_demand`]: crate::event_loop::run_on_demand::EventLoopExtRunOnDemand::run_app_on_demand
|
||||||
/// [`run_app_never_return`]: crate::event_loop::never_return::EventLoopExtNeverReturn::run_app_never_return
|
/// [`run_app_never_return`]: crate::event_loop::never_return::EventLoopExtNeverReturn::run_app_never_return
|
||||||
/// [`register_app`]: crate::event_loop::register::EventLoopExtRegister::register_app
|
/// [`register_app`]: crate::event_loop::register::EventLoopExtRegister::register_app
|
||||||
|
/// [`EventLoopProvider`]: winit_core::event_loop::EventLoopProvider
|
||||||
///
|
///
|
||||||
/// ## Static
|
/// ## Static
|
||||||
///
|
///
|
||||||
@@ -288,6 +238,35 @@ impl EventLoop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl EventLoopProvider for EventLoop {
|
||||||
|
fn run_app<A: ApplicationHandler + 'static>(self, app: A) -> Result<(), EventLoopError> {
|
||||||
|
self.run_app(app)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_proxy(&self) -> EventLoopProxy {
|
||||||
|
self.create_proxy()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn owned_display_handle(&self) -> OwnedDisplayHandle {
|
||||||
|
self.owned_display_handle()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn listen_device_events(&self, allowed: DeviceEvents) {
|
||||||
|
self.listen_device_events(allowed);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_control_flow(&self, control_flow: ControlFlow) {
|
||||||
|
self.set_control_flow(control_flow);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_custom_cursor(
|
||||||
|
&self,
|
||||||
|
custom_cursor: CustomCursorSource,
|
||||||
|
) -> Result<CustomCursor, RequestError> {
|
||||||
|
self.create_custom_cursor(custom_cursor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl HasDisplayHandle for EventLoop {
|
impl HasDisplayHandle for EventLoop {
|
||||||
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
|
fn display_handle(&self) -> Result<DisplayHandle<'_>, HandleError> {
|
||||||
HasDisplayHandle::display_handle(self.event_loop.window_target().rwh_06_handle())
|
HasDisplayHandle::display_handle(self.event_loop.window_target().rwh_06_handle())
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
//! ```no_run
|
//! ```no_run
|
||||||
//! use winit::application::ApplicationHandler;
|
//! use winit::application::ApplicationHandler;
|
||||||
//! use winit::event::WindowEvent;
|
//! use winit::event::WindowEvent;
|
||||||
//! use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop};
|
//! use winit::event_loop::{ActiveEventLoop, ControlFlow, EventLoop, EventLoopProvider};
|
||||||
//! use winit::window::{Window, WindowId, WindowAttributes};
|
//! use winit::window::{Window, WindowId, WindowAttributes};
|
||||||
//!
|
//!
|
||||||
//! #[derive(Default)]
|
//! #[derive(Default)]
|
||||||
@@ -260,7 +260,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [`EventLoop`]: event_loop::EventLoop
|
//! [`EventLoop`]: event_loop::EventLoop
|
||||||
//! [`EventLoop::new()`]: event_loop::EventLoop::new
|
//! [`EventLoop::new()`]: event_loop::EventLoop::new
|
||||||
//! [`EventLoop::run_app()`]: event_loop::EventLoop::run_app
|
//! [`EventLoop::run_app()`]: event_loop::EventLoopProvider::run_app
|
||||||
//! [`exit()`]: event_loop::ActiveEventLoop::exit
|
//! [`exit()`]: event_loop::ActiveEventLoop::exit
|
||||||
//! [`Window`]: window::Window
|
//! [`Window`]: window::Window
|
||||||
//! [`WindowId`]: window::WindowId
|
//! [`WindowId`]: window::WindowId
|
||||||
|
|||||||
Reference in New Issue
Block a user