From 3a60cbaba5fd96d9244a1f316ae562d7032b2b98 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 12 Nov 2024 10:56:20 +0300 Subject: [PATCH] api: make EventLoopProxy wrap an opaque type The proxy is intended to be Clone, thus use `Arc` for it internally and don't require backends for it to be `Clone`. Use `EventLoopProxyProvider` to hide the backend's proxy implementation details. Co-authored-by: daxpedda --- src/event_loop.rs | 22 +++- src/platform_impl/android/mod.rs | 40 +++--- src/platform_impl/apple/appkit/app_state.rs | 14 +-- src/platform_impl/apple/appkit/event_loop.rs | 30 ++--- src/platform_impl/apple/appkit/mod.rs | 3 +- src/platform_impl/apple/uikit/app_state.rs | 18 +-- src/platform_impl/apple/uikit/event_loop.rs | 27 ++-- src/platform_impl/linux/mod.rs | 14 --- .../linux/wayland/event_loop/mod.rs | 15 +-- .../linux/wayland/event_loop/proxy.rs | 17 ++- src/platform_impl/linux/wayland/mod.rs | 2 +- src/platform_impl/linux/x11/mod.rs | 31 ++--- src/platform_impl/orbital/event_loop.rs | 38 ++---- src/platform_impl/orbital/mod.rs | 2 +- src/platform_impl/orbital/window.rs | 13 +- src/platform_impl/web/async/mod.rs | 6 +- src/platform_impl/web/async/waker.rs | 117 ------------------ src/platform_impl/web/event_loop/mod.rs | 1 - src/platform_impl/web/event_loop/proxy.rs | 102 +++++++++++++-- src/platform_impl/web/event_loop/runner.rs | 21 ++-- .../web/event_loop/window_target.rs | 15 +-- src/platform_impl/web/mod.rs | 3 +- src/platform_impl/windows/event_loop.rs | 10 +- src/platform_impl/windows/mod.rs | 2 +- 24 files changed, 256 insertions(+), 307 deletions(-) delete mode 100644 src/platform_impl/web/async/waker.rs diff --git a/src/event_loop.rs b/src/event_loop.rs index 2b3c57e4..42411143 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -13,6 +13,7 @@ use std::marker::PhantomData; #[cfg(any(x11_platform, wayland_platform))] use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; +use std::sync::Arc; #[cfg(not(web_platform))] use std::time::{Duration, Instant}; @@ -452,10 +453,21 @@ impl rwh_06::HasDisplayHandle for OwnedDisplayHandle { } } +pub(crate) trait EventLoopProxyProvider: Send + Sync { + /// See [`EventLoopProxy::wake_up`] for details. + fn wake_up(&self); +} + /// Control the [`EventLoop`], possibly from a different thread, without referencing it directly. #[derive(Clone)] pub struct EventLoopProxy { - pub(crate) event_loop_proxy: platform_impl::EventLoopProxy, + pub(crate) proxy: Arc, +} + +impl fmt::Debug for EventLoopProxy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("EventLoopProxy").finish_non_exhaustive() + } } impl EventLoopProxy { @@ -475,13 +487,11 @@ impl EventLoopProxy { /// /// [#3687]: https://github.com/rust-windowing/winit/pull/3687 pub fn wake_up(&self) { - self.event_loop_proxy.wake_up(); + self.proxy.wake_up(); } -} -impl fmt::Debug for EventLoopProxy { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.debug_struct("ActiveEventLoop").finish_non_exhaustive() + pub(crate) fn new(proxy: Arc) -> Self { + Self { proxy } } } diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 533316e6..1b024bde 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -18,7 +18,8 @@ use crate::error::{EventLoopError, NotSupportedError, RequestError}; use crate::event::{self, DeviceId, FingerId, Force, StartCause, SurfaceSizeWriter}; use crate::event_loop::{ ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, - EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, + EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, + OwnedDisplayHandle as RootOwnedDisplayHandle, }; use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::platform::pump_events::PumpStatus; @@ -131,12 +132,13 @@ impl EventLoop { pub(crate) fn new( attributes: &PlatformSpecificEventLoopAttributes, ) -> Result { - let proxy_wake_up = Arc::new(AtomicBool::new(false)); - let android_app = attributes.android_app.as_ref().expect( "An `AndroidApp` as passed to android_main() is required to create an `EventLoop` on \ Android", ); + + let event_loop_proxy = Arc::new(EventLoopProxy::new(android_app.create_waker())); + let redraw_flag = SharedFlag::new(); Ok(Self { @@ -147,7 +149,7 @@ impl EventLoop { control_flow: Cell::new(ControlFlow::default()), exit: Cell::new(false), redraw_requester: RedrawRequester::new(&redraw_flag, android_app.create_waker()), - proxy_wake_up, + event_loop_proxy, }, redraw_flag, loop_running: false, @@ -276,7 +278,7 @@ impl EventLoop { }, } - if self.window_target.proxy_wake_up.swap(false, Ordering::Relaxed) { + if self.window_target.event_loop_proxy.wake_up.swap(false, Ordering::Relaxed) { app.proxy_wake_up(&self.window_target); } @@ -562,7 +564,8 @@ impl EventLoop { self.pending_redraw |= self.redraw_flag.get_and_reset(); timeout = if self.running - && (self.pending_redraw || self.window_target.proxy_wake_up.load(Ordering::Relaxed)) + && (self.pending_redraw + || self.window_target.event_loop_proxy.wake_up.load(Ordering::Relaxed)) { // If we already have work to do then we don't want to block on the next poll Some(Duration::ZERO) @@ -595,7 +598,7 @@ impl EventLoop { self.pending_redraw |= self.redraw_flag.get_and_reset(); if !self.running || (!self.pending_redraw - && !self.window_target.proxy_wake_up.load(Ordering::Relaxed)) + && !self.window_target.event_loop_proxy.wake_up.load(Ordering::Relaxed)) { return; } @@ -634,15 +637,20 @@ impl EventLoop { } } -#[derive(Clone)] pub struct EventLoopProxy { - proxy_wake_up: Arc, + wake_up: AtomicBool, waker: AndroidAppWaker, } impl EventLoopProxy { - pub fn wake_up(&self) { - self.proxy_wake_up.store(true, Ordering::Relaxed); + fn new(waker: AndroidAppWaker) -> Self { + Self { wake_up: AtomicBool::new(false), waker } + } +} + +impl EventLoopProxyProvider for EventLoopProxy { + fn wake_up(&self) { + self.wake_up.store(true, Ordering::Relaxed); self.waker.wake(); } } @@ -652,7 +660,7 @@ pub struct ActiveEventLoop { control_flow: Cell, exit: Cell, redraw_requester: RedrawRequester, - proxy_wake_up: Arc, + event_loop_proxy: Arc, } impl ActiveEventLoop { @@ -662,12 +670,8 @@ impl ActiveEventLoop { } impl RootActiveEventLoop for ActiveEventLoop { - fn create_proxy(&self) -> RootEventLoopProxy { - let event_loop_proxy = EventLoopProxy { - proxy_wake_up: self.proxy_wake_up.clone(), - waker: self.app.create_waker(), - }; - RootEventLoopProxy { event_loop_proxy } + fn create_proxy(&self) -> CoreEventLoopProxy { + CoreEventLoopProxy::new(self.event_loop_proxy.clone()) } fn create_window( diff --git a/src/platform_impl/apple/appkit/app_state.rs b/src/platform_impl/apple/appkit/app_state.rs index 6c1769ff..c2f107ee 100644 --- a/src/platform_impl/apple/appkit/app_state.rs +++ b/src/platform_impl/apple/appkit/app_state.rs @@ -1,7 +1,7 @@ use std::cell::{Cell, OnceCell, RefCell}; use std::mem; use std::rc::{Rc, Weak}; -use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; +use std::sync::atomic::Ordering as AtomicOrdering; use std::sync::Arc; use std::time::Instant; @@ -9,7 +9,7 @@ use objc2_app_kit::{NSApplication, NSApplicationActivationPolicy}; use objc2_foundation::{MainThreadMarker, NSNotification}; use super::super::event_handler::EventHandler; -use super::event_loop::{stop_app_immediately, ActiveEventLoop, PanicInfo}; +use super::event_loop::{stop_app_immediately, ActiveEventLoop, EventLoopProxy, PanicInfo}; use super::menu; use super::observer::{EventLoopWaker, RunLoop}; use crate::application::ApplicationHandler; @@ -24,7 +24,7 @@ pub(super) struct AppState { default_menu: bool, activate_ignoring_other_apps: bool, run_loop: RunLoop, - proxy_wake_up: Arc, + event_loop_proxy: Arc, event_handler: EventHandler, stop_on_launch: Cell, stop_before_wait: Cell, @@ -72,7 +72,7 @@ impl AppState { let this = Rc::new(AppState { mtm, activation_policy, - proxy_wake_up: Arc::new(AtomicBool::new(false)), + event_loop_proxy: Arc::new(EventLoopProxy::new()), default_menu, activate_ignoring_other_apps, run_loop: RunLoop::main(mtm), @@ -165,8 +165,8 @@ impl AppState { self.event_handler.set(handler, closure) } - pub fn proxy_wake_up(&self) -> Arc { - self.proxy_wake_up.clone() + pub fn event_loop_proxy(&self) -> &Arc { + &self.event_loop_proxy } /// If `pump_events` is called to progress the event loop then we @@ -350,7 +350,7 @@ impl AppState { return; } - if self.proxy_wake_up.swap(false, AtomicOrdering::Relaxed) { + if self.event_loop_proxy.wake_up.swap(false, AtomicOrdering::Relaxed) { self.with_handler(|app, event_loop| app.proxy_wake_up(event_loop)); } diff --git a/src/platform_impl/apple/appkit/event_loop.rs b/src/platform_impl/apple/appkit/event_loop.rs index 17b68328..d14fbb86 100644 --- a/src/platform_impl/apple/appkit/event_loop.rs +++ b/src/platform_impl/apple/appkit/event_loop.rs @@ -5,7 +5,6 @@ use std::panic::{catch_unwind, resume_unwind, RefUnwindSafe, UnwindSafe}; use std::ptr; use std::rc::{Rc, Weak}; use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; -use std::sync::Arc; use std::time::{Duration, Instant}; use core_foundation::base::{CFIndex, CFRelease}; @@ -32,7 +31,8 @@ use crate::application::ApplicationHandler; use crate::error::{EventLoopError, RequestError}; use crate::event_loop::{ ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, - EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, + EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, + OwnedDisplayHandle as RootOwnedDisplayHandle, }; use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::platform::macos::ActivationPolicy; @@ -95,9 +95,8 @@ impl ActiveEventLoop { } impl RootActiveEventLoop for ActiveEventLoop { - fn create_proxy(&self) -> RootEventLoopProxy { - let event_loop_proxy = EventLoopProxy::new(self.app_state.proxy_wake_up()); - RootEventLoopProxy { event_loop_proxy } + fn create_proxy(&self) -> CoreEventLoopProxy { + CoreEventLoopProxy::new(self.app_state.event_loop_proxy().clone()) } fn create_window( @@ -436,8 +435,9 @@ pub fn stop_app_on_panic R + UnwindSafe, R>( } } +#[derive(Debug)] pub struct EventLoopProxy { - proxy_wake_up: Arc, + pub(crate) wake_up: AtomicBool, source: CFRunLoopSourceRef, } @@ -452,14 +452,8 @@ impl Drop for EventLoopProxy { } } -impl Clone for EventLoopProxy { - fn clone(&self) -> Self { - EventLoopProxy::new(self.proxy_wake_up.clone()) - } -} - impl EventLoopProxy { - fn new(proxy_wake_up: Arc) -> Self { + pub(crate) fn new() -> Self { unsafe { // just wake up the eventloop extern "C" fn event_loop_proxy_handler(_: *const c_void) {} @@ -483,14 +477,16 @@ impl EventLoopProxy { CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes); CFRunLoopWakeUp(rl); - EventLoopProxy { proxy_wake_up, source } + EventLoopProxy { wake_up: AtomicBool::new(false), source } } } +} - pub fn wake_up(&self) { - self.proxy_wake_up.store(true, AtomicOrdering::Relaxed); +impl EventLoopProxyProvider for EventLoopProxy { + fn wake_up(&self) { + self.wake_up.store(true, AtomicOrdering::Relaxed); unsafe { - // let the main thread know there's a new event + // Let the main thread know there's a new event. CFRunLoopSourceSignal(self.source); let rl = CFRunLoopGetMain(); CFRunLoopWakeUp(rl); diff --git a/src/platform_impl/apple/appkit/mod.rs b/src/platform_impl/apple/appkit/mod.rs index 17a593a1..3f7e2b92 100644 --- a/src/platform_impl/apple/appkit/mod.rs +++ b/src/platform_impl/apple/appkit/mod.rs @@ -17,8 +17,7 @@ mod window_delegate; pub(crate) use self::cursor::CustomCursor as PlatformCustomCursor; pub(crate) use self::event::{physicalkey_to_scancode, scancode_to_physicalkey, KeyEventExtra}; pub(crate) use self::event_loop::{ - ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, - PlatformSpecificEventLoopAttributes, + ActiveEventLoop, EventLoop, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, }; pub(crate) use self::monitor::{MonitorHandle, VideoModeHandle}; pub(crate) use self::window::Window; diff --git a/src/platform_impl/apple/uikit/app_state.rs b/src/platform_impl/apple/uikit/app_state.rs index 4b5880d1..c90629e2 100644 --- a/src/platform_impl/apple/uikit/app_state.rs +++ b/src/platform_impl/apple/uikit/app_state.rs @@ -3,7 +3,7 @@ use std::cell::{OnceCell, RefCell, RefMut}; use std::collections::HashSet; use std::os::raw::c_void; -use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::atomic::Ordering; use std::sync::{Arc, Mutex, OnceLock}; use std::time::Instant; use std::{mem, ptr}; @@ -24,7 +24,7 @@ use objc2_ui_kit::{UIApplication, UICoordinateSpace, UIView, UIWindow}; use super::super::event_handler::EventHandler; use super::window::WinitUIWindow; -use super::ActiveEventLoop; +use super::{ActiveEventLoop, EventLoopProxy}; use crate::application::ApplicationHandler; use crate::dpi::PhysicalSize; use crate::event::{Event, StartCause, SurfaceSizeWriter, WindowEvent}; @@ -139,7 +139,7 @@ pub(crate) struct AppState { app_state: Option, control_flow: ControlFlow, waker: EventLoopWaker, - proxy_wake_up: Arc, + event_loop_proxy: Arc, } impl AppState { @@ -164,7 +164,7 @@ impl AppState { }), control_flow: ControlFlow::default(), waker, - proxy_wake_up: Arc::new(AtomicBool::new(false)), + event_loop_proxy: Arc::new(EventLoopProxy::new()), }); } init_guard(&mut guard); @@ -376,8 +376,8 @@ impl AppState { } } - pub(crate) fn proxy_wake_up(&self) -> Arc { - self.proxy_wake_up.clone() + pub fn event_loop_proxy(&self) -> &Arc { + &self.event_loop_proxy } pub(crate) fn set_control_flow(&mut self, control_flow: ControlFlow) { @@ -543,10 +543,10 @@ fn handle_user_events(mtm: MainThreadMarker) { if processing_redraws { bug!("user events attempted to be sent out while `ProcessingRedraws`"); } - let proxy_wake_up = this.proxy_wake_up.clone(); + let event_loop_proxy = this.event_loop_proxy().clone(); drop(this); - if proxy_wake_up.swap(false, Ordering::Relaxed) { + if event_loop_proxy.wake_up.swap(false, Ordering::Relaxed) { handle_event(mtm, Event::UserWakeUp); } @@ -578,7 +578,7 @@ fn handle_user_events(mtm: MainThreadMarker) { } } - if proxy_wake_up.swap(false, Ordering::Relaxed) { + if event_loop_proxy.wake_up.swap(false, Ordering::Relaxed) { handle_event(mtm, Event::UserWakeUp); } } diff --git a/src/platform_impl/apple/uikit/event_loop.rs b/src/platform_impl/apple/uikit/event_loop.rs index 31eee8c0..22a89800 100644 --- a/src/platform_impl/apple/uikit/event_loop.rs +++ b/src/platform_impl/apple/uikit/event_loop.rs @@ -1,7 +1,6 @@ use std::ffi::{c_char, c_int, c_void}; use std::ptr::{self, NonNull}; use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; -use std::sync::Arc; use core_foundation::base::{CFIndex, CFRelease}; use core_foundation::runloop::{ @@ -29,7 +28,8 @@ use crate::error::{EventLoopError, NotSupportedError, RequestError}; use crate::event::Event; use crate::event_loop::{ ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, - EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, + EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, + OwnedDisplayHandle as RootOwnedDisplayHandle, }; use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::platform_impl::Window; @@ -41,9 +41,8 @@ pub(crate) struct ActiveEventLoop { } impl RootActiveEventLoop for ActiveEventLoop { - fn create_proxy(&self) -> crate::event_loop::EventLoopProxy { - let event_loop_proxy = EventLoopProxy::new(AppState::get_mut(self.mtm).proxy_wake_up()); - RootEventLoopProxy { event_loop_proxy } + fn create_proxy(&self) -> CoreEventLoopProxy { + CoreEventLoopProxy::new(AppState::get_mut(self.mtm).event_loop_proxy().clone()) } fn create_window( @@ -289,19 +288,13 @@ impl EventLoop { } pub struct EventLoopProxy { - proxy_wake_up: Arc, + pub(crate) wake_up: AtomicBool, source: CFRunLoopSourceRef, } unsafe impl Send for EventLoopProxy {} unsafe impl Sync for EventLoopProxy {} -impl Clone for EventLoopProxy { - fn clone(&self) -> EventLoopProxy { - EventLoopProxy::new(self.proxy_wake_up.clone()) - } -} - impl Drop for EventLoopProxy { fn drop(&mut self) { unsafe { @@ -312,7 +305,7 @@ impl Drop for EventLoopProxy { } impl EventLoopProxy { - fn new(proxy_wake_up: Arc) -> EventLoopProxy { + pub(crate) fn new() -> EventLoopProxy { unsafe { // just wake up the eventloop extern "C" fn event_loop_proxy_handler(_: *const c_void) {} @@ -336,12 +329,14 @@ impl EventLoopProxy { CFRunLoopAddSource(rl, source, kCFRunLoopCommonModes); CFRunLoopWakeUp(rl); - EventLoopProxy { proxy_wake_up, source } + EventLoopProxy { wake_up: AtomicBool::new(false), source } } } +} - pub fn wake_up(&self) { - self.proxy_wake_up.store(true, AtomicOrdering::Relaxed); +impl EventLoopProxyProvider for EventLoopProxy { + fn wake_up(&self) { + self.wake_up.store(true, AtomicOrdering::Relaxed); unsafe { // let the main thread know there's a new event CFRunLoopSourceSignal(self.source); diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 53de1b71..ba8d96d3 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -277,14 +277,6 @@ pub enum EventLoop { X(x11::EventLoop), } -#[derive(Clone)] -pub enum EventLoopProxy { - #[cfg(x11_platform)] - X(x11::EventLoopProxy), - #[cfg(wayland_platform)] - Wayland(wayland::EventLoopProxy), -} - impl EventLoop { pub(crate) fn new( attributes: &PlatformSpecificEventLoopAttributes, @@ -404,12 +396,6 @@ impl AsRawFd for EventLoop { } } -impl EventLoopProxy { - pub fn wake_up(&self) { - x11_or_wayland!(match self; EventLoopProxy(proxy) => proxy.wake_up()) - } -} - #[derive(Clone)] #[allow(dead_code)] pub(crate) enum OwnedDisplayHandle { diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index 6fb9e0da..98618366 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -25,12 +25,13 @@ use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme} mod proxy; pub mod sink; -pub use proxy::EventLoopProxy; +use proxy::EventLoopProxy; use sink::EventSink; use super::state::{WindowCompositorUpdate, WinitState}; use super::window::state::FrameCallbackState; use super::{logical_to_physical_rounded, WindowId}; +pub use crate::event_loop::EventLoopProxy as CoreEventLoopProxy; type WaylandDispatcher = calloop::Dispatcher<'static, WaylandSource, WinitState>; @@ -120,7 +121,7 @@ impl EventLoop { connection: connection.clone(), wayland_dispatcher: wayland_dispatcher.clone(), event_loop_awakener, - event_loop_proxy: EventLoopProxy::new(ping), + event_loop_proxy: EventLoopProxy::new(ping).into(), queue_handle, control_flow: Cell::new(ControlFlow::default()), exit: Cell::new(None), @@ -539,7 +540,7 @@ impl AsRawFd for EventLoop { pub struct ActiveEventLoop { /// Event loop proxy - event_loop_proxy: EventLoopProxy, + event_loop_proxy: CoreEventLoopProxy, /// The event loop wakeup source. pub event_loop_awakener: calloop::ping::Ping, @@ -565,12 +566,8 @@ pub struct ActiveEventLoop { } impl RootActiveEventLoop for ActiveEventLoop { - fn create_proxy(&self) -> crate::event_loop::EventLoopProxy { - crate::event_loop::EventLoopProxy { - event_loop_proxy: crate::platform_impl::EventLoopProxy::Wayland( - self.event_loop_proxy.clone(), - ), - } + fn create_proxy(&self) -> CoreEventLoopProxy { + self.event_loop_proxy.clone() } fn set_control_flow(&self, control_flow: ControlFlow) { diff --git a/src/platform_impl/linux/wayland/event_loop/proxy.rs b/src/platform_impl/linux/wayland/event_loop/proxy.rs index 9fc2c58e..7eaec873 100644 --- a/src/platform_impl/linux/wayland/event_loop/proxy.rs +++ b/src/platform_impl/linux/wayland/event_loop/proxy.rs @@ -1,19 +1,30 @@ //! An event loop proxy. +use std::sync::Arc; + use sctk::reexports::calloop::ping::Ping; +use crate::event_loop::{EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider}; + /// A handle that can be sent across the threads and used to wake up the `EventLoop`. -#[derive(Clone)] pub struct EventLoopProxy { ping: Ping, } +impl EventLoopProxyProvider for EventLoopProxy { + fn wake_up(&self) { + self.ping.ping(); + } +} + impl EventLoopProxy { pub fn new(ping: Ping) -> Self { Self { ping } } +} - pub fn wake_up(&self) { - self.ping.ping(); +impl From for CoreEventLoopProxy { + fn from(value: EventLoopProxy) -> Self { + CoreEventLoopProxy::new(Arc::new(value)) } } diff --git a/src/platform_impl/linux/wayland/mod.rs b/src/platform_impl/linux/wayland/mod.rs index 6cf0c3cf..91aad463 100644 --- a/src/platform_impl/linux/wayland/mod.rs +++ b/src/platform_impl/linux/wayland/mod.rs @@ -1,6 +1,6 @@ //! Winit's Wayland backend. -pub use event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy}; +pub use event_loop::{ActiveEventLoop, EventLoop}; pub use output::{MonitorHandle, VideoModeHandle}; use sctk::reexports::client::protocol::wl_surface::WlSurface; use sctk::reexports::client::Proxy; diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 458d4fe1..3ed61353 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -27,6 +27,7 @@ use crate::error::{EventLoopError, RequestError}; use crate::event::{DeviceId, Event, StartCause, WindowEvent}; use crate::event_loop::{ ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, OwnedDisplayHandle as RootOwnedDisplayHandle, }; use crate::platform::pump_events::PumpStatus; @@ -139,7 +140,7 @@ pub struct ActiveEventLoop { windows: RefCell>>, redraw_sender: WakeSender, activation_sender: WakeSender, - event_loop_proxy: EventLoopProxy, + event_loop_proxy: CoreEventLoopProxy, device_events: Cell, } @@ -306,7 +307,7 @@ impl EventLoop { sender: activation_token_sender, // not used again so no clone waker: waker.clone(), }, - event_loop_proxy, + event_loop_proxy: event_loop_proxy.into(), device_events: Default::default(), }; @@ -675,12 +676,8 @@ impl ActiveEventLoop { } impl RootActiveEventLoop for ActiveEventLoop { - fn create_proxy(&self) -> crate::event_loop::EventLoopProxy { - crate::event_loop::EventLoopProxy { - event_loop_proxy: crate::platform_impl::EventLoopProxy::X( - self.event_loop_proxy.clone(), - ), - } + fn create_proxy(&self) -> CoreEventLoopProxy { + self.event_loop_proxy.clone() } fn create_window( @@ -759,12 +756,6 @@ impl rwh_06::HasDisplayHandle for ActiveEventLoop { } } -impl EventLoopProxy { - pub fn wake_up(&self) { - self.ping.ping(); - } -} - struct DeviceInfo<'a> { xconn: &'a XConnection, info: *const ffi::XIDeviceInfo, @@ -807,12 +798,24 @@ pub struct EventLoopProxy { ping: Ping, } +impl EventLoopProxyProvider for EventLoopProxy { + fn wake_up(&self) { + self.ping.ping(); + } +} + impl EventLoopProxy { fn new(ping: Ping) -> Self { Self { ping } } } +impl From for CoreEventLoopProxy { + fn from(value: EventLoopProxy) -> Self { + CoreEventLoopProxy::new(Arc::new(value)) + } +} + /// Generic sum error type for X11 errors. #[derive(Debug)] pub enum X11Error { diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index e71ba407..d7fe7c8e 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -18,7 +18,10 @@ use super::{ use crate::application::ApplicationHandler; use crate::error::{EventLoopError, NotSupportedError, RequestError}; use crate::event::{self, Ime, Modifiers, StartCause}; -use crate::event_loop::{self, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents}; +use crate::event_loop::{ + self, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + EventLoopProxy as CoreEventLoopProxy, EventLoopProxyProvider, +}; use crate::keyboard::{ Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, NativeKeyCode, PhysicalKey, @@ -286,8 +289,7 @@ impl EventLoop { let event_socket = Arc::new(RedoxSocket::event().map_err(|error| os_error!(format!("{error}")))?); - let wake_socket = - Arc::new(TimeSocket::open().map_err(|error| os_error!(format!("{error}")))?); + let wake_socket = TimeSocket::open().map_err(|error| os_error!(format!("{error}")))?; event_socket .write(&syscall::Event { @@ -306,8 +308,7 @@ impl EventLoop { redraws: Arc::new(Mutex::new(VecDeque::new())), destroys: Arc::new(Mutex::new(VecDeque::new())), event_socket, - wake_socket, - user_events_sender, + event_loop_proxy: Arc::new(EventLoopProxy { wake_socket, user_events_sender }), }, user_events_receiver, }) @@ -664,11 +665,11 @@ impl EventLoop { pub struct EventLoopProxy { user_events_sender: mpsc::SyncSender<()>, - wake_socket: Arc, + pub(super) wake_socket: TimeSocket, } -impl EventLoopProxy { - pub fn wake_up(&self) { +impl EventLoopProxyProvider for EventLoopProxy { + fn wake_up(&self) { // When we fail to send the event it means that we haven't woken up to read the previous // event. if self.user_events_sender.try_send(()).is_ok() { @@ -677,15 +678,6 @@ impl EventLoopProxy { } } -impl Clone for EventLoopProxy { - fn clone(&self) -> Self { - Self { - user_events_sender: self.user_events_sender.clone(), - wake_socket: self.wake_socket.clone(), - } - } -} - impl Unpin for EventLoopProxy {} pub struct ActiveEventLoop { @@ -695,18 +687,12 @@ pub struct ActiveEventLoop { pub(super) redraws: Arc>>, pub(super) destroys: Arc>>, pub(super) event_socket: Arc, - pub(super) wake_socket: Arc, - user_events_sender: mpsc::SyncSender<()>, + pub(super) event_loop_proxy: Arc, } impl RootActiveEventLoop for ActiveEventLoop { - fn create_proxy(&self) -> event_loop::EventLoopProxy { - event_loop::EventLoopProxy { - event_loop_proxy: EventLoopProxy { - user_events_sender: self.user_events_sender.clone(), - wake_socket: self.wake_socket.clone(), - }, - } + fn create_proxy(&self) -> CoreEventLoopProxy { + CoreEventLoopProxy::new(self.event_loop_proxy.clone()) } fn create_window( diff --git a/src/platform_impl/orbital/mod.rs b/src/platform_impl/orbital/mod.rs index b0f05a12..de729875 100644 --- a/src/platform_impl/orbital/mod.rs +++ b/src/platform_impl/orbital/mod.rs @@ -5,7 +5,7 @@ use std::{fmt, str}; use smol_str::SmolStr; -pub(crate) use self::event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle}; +pub(crate) use self::event_loop::{ActiveEventLoop, EventLoop, OwnedDisplayHandle}; use crate::dpi::{PhysicalPosition, PhysicalSize}; use crate::keyboard::Key; mod event_loop; diff --git a/src/platform_impl/orbital/window.rs b/src/platform_impl/orbital/window.rs index fc500728..76c69836 100644 --- a/src/platform_impl/orbital/window.rs +++ b/src/platform_impl/orbital/window.rs @@ -1,7 +1,8 @@ use std::collections::VecDeque; use std::sync::{Arc, Mutex}; -use super::{ActiveEventLoop, MonitorHandle, RedoxSocket, TimeSocket, WindowProperties}; +use super::event_loop::EventLoopProxy; +use super::{ActiveEventLoop, MonitorHandle, RedoxSocket, WindowProperties}; use crate::cursor::Cursor; use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size}; use crate::error::{NotSupportedError, RequestError}; @@ -23,7 +24,7 @@ pub struct Window { window_socket: Arc, redraws: Arc>>, destroys: Arc>>, - wake_socket: Arc, + event_loop_proxy: Arc, } impl Window { @@ -113,13 +114,13 @@ impl Window { creates.push_back(window_socket.clone()); } - el.wake_socket.wake().unwrap(); + el.event_loop_proxy.wake_socket.wake().unwrap(); Ok(Self { window_socket, redraws: el.redraws.clone(), destroys: el.destroys.clone(), - wake_socket: el.wake_socket.clone(), + event_loop_proxy: el.event_loop_proxy.clone(), }) } @@ -184,7 +185,7 @@ impl CoreWindow for Window { if !redraws.contains(&window_id) { redraws.push_back(window_id); - self.wake_socket.wake().unwrap(); + self.event_loop_proxy.wake_socket.wake().unwrap(); } } @@ -475,6 +476,6 @@ impl Drop for Window { destroys.push_back(self.id()); } - self.wake_socket.wake().unwrap(); + self.event_loop_proxy.wake_socket.wake().unwrap(); } } diff --git a/src/platform_impl/web/async/mod.rs b/src/platform_impl/web/async/mod.rs index d372c7f6..d4a09089 100644 --- a/src/platform_impl/web/async/mod.rs +++ b/src/platform_impl/web/async/mod.rs @@ -6,15 +6,13 @@ mod channel; mod concurrent_queue; mod dispatcher; mod notifier; -mod waker; mod wrapper; -use atomic_waker::AtomicWaker; +pub(crate) use atomic_waker::AtomicWaker; use concurrent_queue::{ConcurrentQueue, PushError}; pub use self::abortable::{AbortHandle, Abortable, DropAbortHandle}; pub use self::channel::{channel, Receiver, Sender}; pub use self::dispatcher::{DispatchRunner, Dispatcher}; pub use self::notifier::{Notified, Notifier}; -pub use self::waker::{Waker, WakerSpawner}; -use self::wrapper::Wrapper; +pub(crate) use self::wrapper::Wrapper; diff --git a/src/platform_impl/web/async/waker.rs b/src/platform_impl/web/async/waker.rs deleted file mode 100644 index 33387363..00000000 --- a/src/platform_impl/web/async/waker.rs +++ /dev/null @@ -1,117 +0,0 @@ -use std::future; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::Arc; -use std::task::Poll; - -use super::super::main_thread::MainThreadMarker; -use super::{AtomicWaker, Wrapper}; - -pub struct WakerSpawner(Wrapper, Sender, ()>); - -pub struct Waker(Wrapper, Sender, ()>); - -struct Handler { - value: T, - handler: fn(&T, bool), -} - -#[derive(Clone)] -struct Sender(Arc); - -impl WakerSpawner { - pub fn new(main_thread: MainThreadMarker, value: T, handler: fn(&T, bool)) -> Self { - let inner = Arc::new(Inner { - awoken: AtomicBool::new(false), - waker: AtomicWaker::new(), - closed: AtomicBool::new(false), - }); - - let handler = Handler { value, handler }; - - let sender = Sender(Arc::clone(&inner)); - - Self(Wrapper::new( - main_thread, - handler, - |handler, _| { - let handler = handler.borrow(); - let handler = handler.as_ref().unwrap(); - (handler.handler)(&handler.value, true); - }, - { - let inner = Arc::clone(&inner); - - move |handler| async move { - while future::poll_fn(|cx| { - if inner.awoken.swap(false, Ordering::Relaxed) { - Poll::Ready(true) - } else { - inner.waker.register(cx.waker()); - - if inner.awoken.swap(false, Ordering::Relaxed) { - Poll::Ready(true) - } else { - if inner.closed.load(Ordering::Relaxed) { - return Poll::Ready(false); - } - - Poll::Pending - } - } - }) - .await - { - let handler = handler.borrow(); - let handler = handler.as_ref().unwrap(); - (handler.handler)(&handler.value, false); - } - } - }, - sender, - |inner, _| { - inner.0.awoken.store(true, Ordering::Relaxed); - inner.0.waker.wake(); - }, - )) - } - - pub fn waker(&self) -> Waker { - Waker(self.0.clone()) - } - - pub fn take(&self) -> bool { - debug_assert!( - MainThreadMarker::new().is_some(), - "this should only be called from the main thread" - ); - - self.0.with_sender_data(|inner| inner.0.awoken.swap(false, Ordering::Relaxed)) - } -} - -impl Drop for WakerSpawner { - fn drop(&mut self) { - self.0.with_sender_data(|inner| { - inner.0.closed.store(true, Ordering::Relaxed); - inner.0.waker.wake(); - }); - } -} - -impl Waker { - pub fn wake(&self) { - self.0.send(()) - } -} - -impl Clone for Waker { - fn clone(&self) -> Self { - Self(self.0.clone()) - } -} - -struct Inner { - awoken: AtomicBool, - waker: AtomicWaker, - closed: AtomicBool, -} diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index 9c132668..560200b2 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -10,7 +10,6 @@ pub(crate) mod runner; mod state; mod window_target; -pub(crate) use proxy::EventLoopProxy; pub(crate) use window_target::{ActiveEventLoop, OwnedDisplayHandle}; pub struct EventLoop { diff --git a/src/platform_impl/web/event_loop/proxy.rs b/src/platform_impl/web/event_loop/proxy.rs index 0973b6c8..c148deaf 100644 --- a/src/platform_impl/web/event_loop/proxy.rs +++ b/src/platform_impl/web/event_loop/proxy.rs @@ -1,17 +1,101 @@ -use super::runner::WeakShared; -use crate::platform_impl::platform::r#async::Waker; +use std::future; +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; +use std::task::Poll; -#[derive(Clone)] -pub struct EventLoopProxy { - runner: Waker, +use super::super::main_thread::MainThreadMarker; +use crate::event_loop::EventLoopProxyProvider; +use crate::platform_impl::web::event_loop::runner::WeakShared; +use crate::platform_impl::web::r#async::{AtomicWaker, Wrapper}; + +pub struct EventLoopProxy(Wrapper, ()>); + +struct State { + awoken: AtomicBool, + waker: AtomicWaker, + closed: AtomicBool, } impl EventLoopProxy { - pub fn new(runner: Waker) -> Self { - Self { runner } + pub fn new(main_thread: MainThreadMarker, runner: WeakShared) -> Self { + let state = Arc::new(State { + awoken: AtomicBool::new(false), + waker: AtomicWaker::new(), + closed: AtomicBool::new(false), + }); + + Self(Wrapper::new( + main_thread, + runner, + |runner, _| { + let runner = runner.borrow(); + let runner = runner.as_ref().unwrap(); + + if let Some(runner) = runner.upgrade() { + runner.send_proxy_wake_up(true); + } + }, + { + let state = Arc::clone(&state); + + move |runner| async move { + while future::poll_fn(|cx| { + if state.awoken.swap(false, Ordering::Relaxed) { + Poll::Ready(true) + } else { + state.waker.register(cx.waker()); + + if state.awoken.swap(false, Ordering::Relaxed) { + Poll::Ready(true) + } else { + if state.closed.load(Ordering::Relaxed) { + return Poll::Ready(false); + } + + Poll::Pending + } + } + }) + .await + { + let runner = runner.borrow(); + let runner = runner.as_ref().unwrap(); + + if let Some(runner) = runner.upgrade() { + runner.send_proxy_wake_up(false); + } + } + } + }, + state, + |state, _| { + state.awoken.store(true, Ordering::Relaxed); + state.waker.wake(); + }, + )) } - pub fn wake_up(&self) { - self.runner.wake(); + pub fn take(&self) -> bool { + debug_assert!( + MainThreadMarker::new().is_some(), + "this should only be called from the main thread" + ); + + self.0.with_sender_data(|state| state.awoken.swap(false, Ordering::Relaxed)) + } +} + +impl Drop for EventLoopProxy { + fn drop(&mut self) { + self.0.with_sender_data(|state| { + state.closed.store(true, Ordering::Relaxed); + state.waker.wake(); + }); + } +} + +impl EventLoopProxyProvider for EventLoopProxy { + fn wake_up(&self) { + self.0.send(()) } } diff --git a/src/platform_impl/web/event_loop/runner.rs b/src/platform_impl/web/event_loop/runner.rs index b46968e8..39523e18 100644 --- a/src/platform_impl/web/event_loop/runner.rs +++ b/src/platform_impl/web/event_loop/runner.rs @@ -3,6 +3,7 @@ use std::collections::{HashSet, VecDeque}; use std::iter; use std::ops::Deref; use std::rc::{Rc, Weak}; +use std::sync::Arc; use wasm_bindgen::prelude::Closure; use wasm_bindgen::JsCast; @@ -13,13 +14,14 @@ use super::super::event; use super::super::main_thread::MainThreadMarker; use super::super::monitor::MonitorHandler; use super::backend; +use super::proxy::EventLoopProxy; use super::state::State; use crate::dpi::PhysicalSize; use crate::event::{DeviceEvent, ElementState, Event, RawKeyEvent, StartCause, WindowEvent}; use crate::event_loop::{ControlFlow, DeviceEvents}; use crate::platform::web::{PollStrategy, WaitUntilStrategy}; use crate::platform_impl::platform::backend::EventListenerHandle; -use crate::platform_impl::platform::r#async::{DispatchRunner, Waker, WakerSpawner}; +use crate::platform_impl::platform::r#async::DispatchRunner; use crate::platform_impl::platform::window::Inner; use crate::window::WindowId; @@ -37,7 +39,7 @@ type OnEventHandle = RefCell>>; struct Execution { main_thread: MainThreadMarker, - proxy_spawner: WakerSpawner, + event_loop_proxy: Arc, control_flow: Cell, poll_strategy: Cell, wait_until_strategy: Cell, @@ -140,12 +142,7 @@ impl Shared { let document = window.document().expect("Failed to obtain document"); Shared(Rc::::new_cyclic(|weak| { - let proxy_spawner = - WakerSpawner::new(main_thread, WeakShared(weak.clone()), |runner, local| { - if let Some(runner) = runner.upgrade() { - runner.send_proxy_wake_up(local); - } - }); + let proxy_spawner = EventLoopProxy::new(main_thread, WeakShared(weak.clone())); let monitor = MonitorHandler::new( main_thread, @@ -156,7 +153,7 @@ impl Shared { Execution { main_thread, - proxy_spawner, + event_loop_proxy: Arc::new(proxy_spawner), control_flow: Cell::new(ControlFlow::default()), poll_strategy: Cell::new(PollStrategy::default()), wait_until_strategy: Cell::new(WaitUntilStrategy::default()), @@ -653,7 +650,7 @@ impl Shared { // Pre-fetch `UserEvent`s to avoid having to wait until the next event loop cycle. events.extend( self.0 - .proxy_spawner + .event_loop_proxy .take() .then_some(Event::UserWakeUp) .map(EventWrapper::from), @@ -818,8 +815,8 @@ impl Shared { self.0.wait_until_strategy.get() } - pub(crate) fn waker(&self) -> Waker { - self.0.proxy_spawner.waker() + pub(crate) fn event_loop_proxy(&self) -> &Arc { + &self.0.event_loop_proxy } pub(crate) fn weak(&self) -> WeakShared { diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index 0afd8d50..d4e4059f 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -2,13 +2,14 @@ use std::cell::Cell; use std::clone::Clone; use std::iter; use std::rc::Rc; +use std::sync::Arc; use web_sys::Element; use super::super::monitor::MonitorPermissionFuture; use super::super::{lock, KeyEventExtra}; -use super::runner::{EventWrapper, WeakShared}; -use super::{backend, runner, EventLoopProxy}; +use super::runner::EventWrapper; +use super::{backend, runner}; use crate::error::{NotSupportedError, RequestError}; use crate::event::{ElementState, Event, KeyEvent, TouchPhase, WindowEvent}; use crate::event_loop::{ @@ -19,7 +20,7 @@ use crate::keyboard::ModifiersState; use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::platform::web::{CustomCursorFuture, PollStrategy, WaitUntilStrategy}; use crate::platform_impl::platform::cursor::CustomCursor; -use crate::platform_impl::platform::r#async::Waker; +use crate::platform_impl::web::event_loop::proxy::EventLoopProxy; use crate::platform_impl::Window; use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId}; @@ -476,15 +477,15 @@ impl ActiveEventLoop { self.runner.monitor().has_detailed_monitor_permission() } - pub(crate) fn waker(&self) -> Waker { - self.runner.waker() + pub(crate) fn event_loop_proxy(&self) -> Arc { + self.runner.event_loop_proxy().clone() } } impl RootActiveEventLoop for ActiveEventLoop { fn create_proxy(&self) -> RootEventLoopProxy { - let event_loop_proxy = EventLoopProxy::new(self.waker()); - RootEventLoopProxy { event_loop_proxy } + let event_loop_proxy = self.event_loop_proxy(); + RootEventLoopProxy::new(event_loop_proxy) } fn create_window( diff --git a/src/platform_impl/web/mod.rs b/src/platform_impl/web/mod.rs index 3ea7c07b..158445ff 100644 --- a/src/platform_impl/web/mod.rs +++ b/src/platform_impl/web/mod.rs @@ -38,8 +38,7 @@ pub(crate) use cursor::{ }; pub(crate) use self::event_loop::{ - ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, - PlatformSpecificEventLoopAttributes, + ActiveEventLoop, EventLoop, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, }; pub(crate) use self::keyboard::KeyEventExtra; pub(crate) use self::monitor::{ diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 10b33392..1d1531ae 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -69,7 +69,8 @@ use crate::event::{ }; use crate::event_loop::{ ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, - EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, + EventLoopProxy as RootEventLoopProxy, EventLoopProxyProvider, + OwnedDisplayHandle as RootOwnedDisplayHandle, }; use crate::keyboard::ModifiersState; use crate::monitor::MonitorHandle as RootMonitorHandle; @@ -462,7 +463,7 @@ impl ActiveEventLoop { impl RootActiveEventLoop for ActiveEventLoop { fn create_proxy(&self) -> RootEventLoopProxy { let event_loop_proxy = EventLoopProxy { target_window: self.thread_msg_target }; - RootEventLoopProxy { event_loop_proxy } + RootEventLoopProxy::new(Arc::new(event_loop_proxy)) } fn create_window( @@ -802,15 +803,14 @@ impl EventLoopThreadExecutor { type ThreadExecFn = Box>; -#[derive(Clone)] pub struct EventLoopProxy { target_window: HWND, } unsafe impl Send for EventLoopProxy {} -impl EventLoopProxy { - pub fn wake_up(&self) { +impl EventLoopProxyProvider for EventLoopProxy { + fn wake_up(&self) { unsafe { PostMessageW(self.target_window, USER_EVENT_MSG_ID.get(), 0, 0) }; } } diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 977599d8..ebc5fecc 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -3,7 +3,7 @@ use windows_sys::Win32::Foundation::HWND; use windows_sys::Win32::UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX}; pub(crate) use self::event_loop::{ - EventLoop, EventLoopProxy, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, + EventLoop, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, }; pub use self::icon::WinIcon as PlatformIcon; pub(crate) use self::icon::{SelectedCursor, WinCursor as PlatformCustomCursor, WinIcon};