From 42366231b0d92480a933339bd5eaa7fba8106f42 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Mon, 27 Jul 2026 21:50:29 +0900 Subject: [PATCH] chore: implement `EventLoopProvider` in each winit-* crate --- winit-android/src/event_loop.rs | 37 +++++++++++++++++++++++- winit-appkit/src/event_loop.rs | 37 +++++++++++++++++++++++- winit-orbital/src/event_loop.rs | 37 +++++++++++++++++++++++- winit-uikit/src/event_loop.rs | 31 +++++++++++++++++++- winit-wayland/src/event_loop/mod.rs | 37 +++++++++++++++++++++++- winit-web/src/event_loop/mod.rs | 38 ++++++++++++++++++++++-- winit-win32/src/event_loop.rs | 39 +++++++++++++++++++++++-- winit-x11/src/event_loop.rs | 37 +++++++++++++++++++++++- winit/src/event_loop.rs | 30 ++----------------- winit/src/platform_impl/linux/mod.rs | 43 ++++++++++++++++++++++++++-- 10 files changed, 326 insertions(+), 40 deletions(-) diff --git a/winit-android/src/event_loop.rs b/winit-android/src/event_loop.rs index 8ffb1a3a9..ec8abe4d9 100644 --- a/winit-android/src/event_loop.rs +++ b/winit-android/src/event_loop.rs @@ -17,7 +17,7 @@ use winit_core::error::{EventLoopError, NotSupportedError, RequestError}; use winit_core::event::{self, DeviceId, FingerId, Force, StartCause, SurfaceSizeWriter}; use winit_core::event_loop::pump_events::PumpStatus; use winit_core::event_loop::{ - ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, EventLoopProvider, EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, OwnedDisplayHandle as CoreOwnedDisplayHandle, }; @@ -644,6 +644,41 @@ impl EventLoop { } } +impl EventLoopProvider for EventLoop { + fn run_app( + mut self, + mut app: A, + ) -> Result<(), EventLoopError> { + let result = self.run_app_on_demand(&mut app); + // SAFETY: unsure that the state is dropped before the exit from the event loop. + drop(app); + result + } + + fn create_proxy(&self) -> CoreEventLoopProxy { + self.window_target().create_proxy() + } + + fn owned_display_handle(&self) -> CoreOwnedDisplayHandle { + self.window_target().owned_display_handle() + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.window_target().listen_device_events(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.window_target().set_control_flow(control_flow); + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + self.window_target().create_custom_cursor(custom_cursor) + } +} + pub struct EventLoopProxy { wake_up: AtomicBool, waker: AndroidAppWaker, diff --git a/winit-appkit/src/event_loop.rs b/winit-appkit/src/event_loop.rs index 674aa3db7..2682a3097 100644 --- a/winit-appkit/src/event_loop.rs +++ b/winit-appkit/src/event_loop.rs @@ -28,7 +28,7 @@ use winit_core::event::WindowEvent; use winit_core::event_loop::pump_events::PumpStatus; use winit_core::event_loop::{ ActiveEventLoop as RootActiveEventLoop, AsyncRequestSerial, ControlFlow, DeviceEvents, - DndAction, DragIcon, EventLoopProxy as CoreEventLoopProxy, + DndAction, DragIcon, EventLoopProvider, EventLoopProxy as CoreEventLoopProxy, OwnedDisplayHandle as CoreOwnedDisplayHandle, }; use winit_core::monitor::MonitorHandle as CoreMonitorHandle; @@ -552,6 +552,41 @@ impl EventLoop { } } +impl EventLoopProvider for EventLoop { + fn run_app( + mut self, + mut app: A, + ) -> Result<(), EventLoopError> { + let result = self.run_app_on_demand(&mut app); + // SAFETY: unsure that the state is dropped before the exit from the event loop. + drop(app); + result + } + + fn create_proxy(&self) -> CoreEventLoopProxy { + self.window_target().create_proxy() + } + + fn owned_display_handle(&self) -> CoreOwnedDisplayHandle { + self.window_target().owned_display_handle() + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.window_target().listen_device_events(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.window_target().set_control_flow(control_flow); + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + self.window_target().create_custom_cursor(custom_cursor) + } +} + pub(crate) struct OwnedDisplayHandle; impl HasDisplayHandle for OwnedDisplayHandle { diff --git a/winit-orbital/src/event_loop.rs b/winit-orbital/src/event_loop.rs index f94ad1d16..012b9ed3c 100644 --- a/winit-orbital/src/event_loop.rs +++ b/winit-orbital/src/event_loop.rs @@ -20,7 +20,7 @@ use winit_core::error::{EventLoopError, NotSupportedError, RequestError}; use winit_core::event::{self, Ime, Modifiers, StartCause}; use winit_core::event_loop::pump_events::PumpStatus; use winit_core::event_loop::{ - ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, EventLoopProvider, EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, OwnedDisplayHandle as CoreOwnedDisplayHandle, }; @@ -734,6 +734,41 @@ impl EventLoop { } } +impl EventLoopProvider for EventLoop { + fn run_app( + mut self, + mut app: A, + ) -> Result<(), EventLoopError> { + let result = self.run_app_on_demand(&mut app); + // SAFETY: unsure that the state is dropped before the exit from the event loop. + drop(app); + result + } + + fn create_proxy(&self) -> CoreEventLoopProxy { + self.window_target().create_proxy() + } + + fn owned_display_handle(&self) -> CoreOwnedDisplayHandle { + self.window_target().owned_display_handle() + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.window_target().listen_device_events(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.window_target().set_control_flow(control_flow); + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + self.window_target().create_custom_cursor(custom_cursor) + } +} + #[derive(Debug)] pub struct EventLoopProxy { user_events_sender: mpsc::SyncSender<()>, diff --git a/winit-uikit/src/event_loop.rs b/winit-uikit/src/event_loop.rs index 2d8843c9c..4ad7e7809 100644 --- a/winit-uikit/src/event_loop.rs +++ b/winit-uikit/src/event_loop.rs @@ -19,7 +19,7 @@ use winit_core::application::ApplicationHandler; use winit_core::cursor::{CustomCursor, CustomCursorSource}; use winit_core::error::{EventLoopError, NotSupportedError, RequestError}; use winit_core::event_loop::{ - ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, EventLoopProvider, EventLoopProxy as CoreEventLoopProxy, OwnedDisplayHandle as CoreOwnedDisplayHandle, }; use winit_core::monitor::MonitorHandle as CoreMonitorHandle; @@ -333,3 +333,32 @@ impl EventLoop { &self.window_target } } + +impl EventLoopProvider for EventLoop { + fn run_app(self, app: A) -> Result<(), EventLoopError> { + self.run_app_never_return(app) + } + + fn create_proxy(&self) -> CoreEventLoopProxy { + self.window_target().create_proxy() + } + + fn owned_display_handle(&self) -> CoreOwnedDisplayHandle { + self.window_target().owned_display_handle() + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.window_target().listen_device_events(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.window_target().set_control_flow(control_flow); + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + self.window_target().create_custom_cursor(custom_cursor) + } +} diff --git a/winit-wayland/src/event_loop/mod.rs b/winit-wayland/src/event_loop/mod.rs index 66bd717fd..9dd09eb7c 100644 --- a/winit-wayland/src/event_loop/mod.rs +++ b/winit-wayland/src/event_loop/mod.rs @@ -32,7 +32,7 @@ use winit_core::event::{DeviceEvent, StartCause, SurfaceSizeWriter, WindowEvent} use winit_core::event_loop::pump_events::PumpStatus; use winit_core::event_loop::{ ActiveEventLoop as RootActiveEventLoop, AsyncRequestSerial, ControlFlow, DeviceEvents, - DndAction, DragIcon, OwnedDisplayHandle as CoreOwnedDisplayHandle, + DndAction, DragIcon, EventLoopProvider, OwnedDisplayHandle as CoreOwnedDisplayHandle, }; use winit_core::icon::RgbaIcon; use winit_core::monitor::MonitorHandle as CoreMonitorHandle; @@ -624,6 +624,41 @@ impl EventLoop { } } +impl EventLoopProvider for EventLoop { + fn run_app( + mut self, + mut app: A, + ) -> Result<(), EventLoopError> { + let result = self.run_app_on_demand(&mut app); + // SAFETY: unsure that the state is dropped before the exit from the event loop. + drop(app); + result + } + + fn create_proxy(&self) -> CoreEventLoopProxy { + self.active_event_loop.create_proxy() + } + + fn owned_display_handle(&self) -> CoreOwnedDisplayHandle { + self.active_event_loop.owned_display_handle() + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.active_event_loop.listen_device_events(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.active_event_loop.set_control_flow(control_flow); + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + self.active_event_loop.create_custom_cursor(custom_cursor) + } +} + impl AsFd for EventLoop { fn as_fd(&self) -> BorrowedFd<'_> { self.event_loop.as_fd() diff --git a/winit-web/src/event_loop/mod.rs b/winit-web/src/event_loop/mod.rs index 8b722729f..fb42a423c 100644 --- a/winit-web/src/event_loop/mod.rs +++ b/winit-web/src/event_loop/mod.rs @@ -1,8 +1,12 @@ use std::sync::atomic::{AtomicBool, Ordering}; use winit_core::application::ApplicationHandler; -use winit_core::error::{EventLoopError, NotSupportedError}; -use winit_core::event_loop::ActiveEventLoop as RootActiveEventLoop; +use winit_core::cursor::{CustomCursor as CoreCustomCursor, CustomCursorSource}; +use winit_core::error::{EventLoopError, NotSupportedError, RequestError}; +use winit_core::event_loop::{ + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, EventLoopProvider, + EventLoopProxy, OwnedDisplayHandle, +}; use crate::{ HasMonitorPermissionFuture, MonitorPermissionFuture, PollStrategy, WaitUntilStrategy, backend, @@ -77,3 +81,33 @@ impl EventLoop { ) } } + +impl EventLoopProvider for EventLoop { + fn run_app(self, app: A) -> Result<(), EventLoopError> { + self.register_app(app); + Ok(()) + } + + fn create_proxy(&self) -> EventLoopProxy { + self.window_target().create_proxy() + } + + fn owned_display_handle(&self) -> OwnedDisplayHandle { + self.window_target().owned_display_handle() + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.window_target().listen_device_events(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.window_target().set_control_flow(control_flow); + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + self.window_target().create_custom_cursor(custom_cursor) + } +} diff --git a/winit-win32/src/event_loop.rs b/winit-win32/src/event_loop.rs index e52bf3114..2408a04de 100644 --- a/winit-win32/src/event_loop.rs +++ b/winit-win32/src/event_loop.rs @@ -74,8 +74,8 @@ use winit_core::event::{ use winit_core::event_loop::pump_events::PumpStatus; use winit_core::event_loop::{ ActiveEventLoop as RootActiveEventLoop, AsyncRequestSerial, ControlFlow, DeviceEvents, - DndAction, DragIcon, EventLoopProxy as RootEventLoopProxy, EventLoopProxyProvider, - OwnedDisplayHandle as CoreOwnedDisplayHandle, + DndAction, DragIcon, EventLoopProvider, EventLoopProxy as RootEventLoopProxy, + EventLoopProxyProvider, OwnedDisplayHandle as CoreOwnedDisplayHandle, }; use winit_core::keyboard::ModifiersState; use winit_core::monitor::{Fullscreen, MonitorHandle as CoreMonitorHandle}; @@ -392,6 +392,41 @@ impl EventLoop { } } +impl EventLoopProvider for EventLoop { + fn run_app( + mut self, + mut app: A, + ) -> Result<(), EventLoopError> { + let result = self.run_app_on_demand(&mut app); + // SAFETY: unsure that the state is dropped before the exit from the event loop. + drop(app); + result + } + + fn create_proxy(&self) -> RootEventLoopProxy { + self.window_target().create_proxy() + } + + fn owned_display_handle(&self) -> CoreOwnedDisplayHandle { + self.window_target().owned_display_handle() + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.window_target().listen_device_events(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.window_target().set_control_flow(control_flow); + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + self.window_target().create_custom_cursor(custom_cursor) + } +} + impl Drop for EventLoop { fn drop(&mut self) { unsafe { diff --git a/winit-x11/src/event_loop.rs b/winit-x11/src/event_loop.rs index 990be32be..fa129d52d 100644 --- a/winit-x11/src/event_loop.rs +++ b/winit-x11/src/event_loop.rs @@ -25,7 +25,7 @@ use winit_core::event::{DeviceId, StartCause, WindowEvent}; use winit_core::event_loop::pump_events::PumpStatus; use winit_core::event_loop::{ ActiveEventLoop as RootActiveEventLoop, AsyncRequestSerial, ControlFlow, DeviceEvents, - DndAction, EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, + DndAction, EventLoopProvider, EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, OwnedDisplayHandle as CoreOwnedDisplayHandle, }; use winit_core::monitor::MonitorHandle as CoreMonitorHandle; @@ -647,6 +647,41 @@ impl EventLoop { } } +impl EventLoopProvider for EventLoop { + fn run_app( + mut self, + mut app: A, + ) -> Result<(), EventLoopError> { + let result = self.run_app_on_demand(&mut app); + // SAFETY: unsure that the state is dropped before the exit from the event loop. + drop(app); + result + } + + fn create_proxy(&self) -> CoreEventLoopProxy { + self.window_target().create_proxy() + } + + fn owned_display_handle(&self) -> CoreOwnedDisplayHandle { + self.window_target().owned_display_handle() + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.window_target().listen_device_events(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.window_target().set_control_flow(control_flow); + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + self.window_target().create_custom_cursor(custom_cursor) + } +} + impl AsFd for EventLoop { fn as_fd(&self) -> BorrowedFd<'_> { self.event_loop.as_fd() diff --git a/winit/src/event_loop.rs b/winit/src/event_loop.rs index 681de2b1f..ff9ee6cc6 100644 --- a/winit/src/event_loop.rs +++ b/winit/src/event_loop.rs @@ -163,34 +163,8 @@ impl EventLoop { /// If this requirement is prohibitive for you, consider using [`run_app_on_demand`] instead /// (though note that this is not available on iOS and web). #[inline] - #[allow(unused_mut)] - pub fn run_app( - mut self, - mut app: A, - ) -> Result<(), EventLoopError> { - #[cfg(any( - windows_platform, - macos_platform, - android_platform, - orbital_platform, - x11_platform, - wayland_platform, - ))] - { - let result = self.event_loop.run_app_on_demand(&mut app); - // SAFETY: unsure that the state is dropped before the exit from the event loop. - drop(app); - result - } - #[cfg(web_platform)] - { - self.event_loop.register_app(app); - Ok(()) - } - #[cfg(ios_platform)] - { - self.event_loop.run_app_never_return(app) - } + pub fn run_app(self, app: A) -> Result<(), EventLoopError> { + self.event_loop.run_app(app) } /// Creates an [`EventLoopProxy`] that can be used to dispatch user events diff --git a/winit/src/platform_impl/linux/mod.rs b/winit/src/platform_impl/linux/mod.rs index 877e0dc62..79a8a86d7 100644 --- a/winit/src/platform_impl/linux/mod.rs +++ b/winit/src/platform_impl/linux/mod.rs @@ -9,9 +9,13 @@ use std::time::Duration; pub(crate) use winit_common::xkb::{physicalkey_to_scancode, scancode_to_physicalkey}; use winit_core::application::ApplicationHandler; -use winit_core::error::{EventLoopError, NotSupportedError}; -use winit_core::event_loop::ActiveEventLoop; +use winit_core::cursor::{CustomCursor, CustomCursorSource}; +use winit_core::error::{EventLoopError, NotSupportedError, RequestError}; use winit_core::event_loop::pump_events::PumpStatus; +use winit_core::event_loop::{ + ActiveEventLoop, ControlFlow, DeviceEvents, EventLoopProvider, EventLoopProxy, + OwnedDisplayHandle, +}; #[cfg(wayland_platform)] pub(crate) use winit_wayland as wayland; #[cfg(x11_platform)] @@ -167,6 +171,41 @@ impl EventLoop { } } +impl EventLoopProvider for EventLoop { + fn run_app( + mut self, + mut app: A, + ) -> Result<(), EventLoopError> { + let result = self.run_app_on_demand(&mut app); + // SAFETY: unsure that the state is dropped before the exit from the event loop. + drop(app); + result + } + + fn create_proxy(&self) -> EventLoopProxy { + self.window_target().create_proxy() + } + + fn owned_display_handle(&self) -> OwnedDisplayHandle { + self.window_target().owned_display_handle() + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.window_target().listen_device_events(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.window_target().set_control_flow(control_flow); + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + self.window_target().create_custom_cursor(custom_cursor) + } +} + impl AsFd for EventLoop { fn as_fd(&self) -> BorrowedFd<'_> { x11_or_wayland!(match self; EventLoop(evlp) => evlp.as_fd())