diff --git a/examples/child_window.rs b/examples/child_window.rs index d77ca34e..7b591413 100644 --- a/examples/child_window.rs +++ b/examples/child_window.rs @@ -20,7 +20,7 @@ fn main() -> Result<(), impl std::error::Error> { } impl ApplicationHandler for Application { - fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { let attributes = Window::default_attributes() .with_title("parent window") .with_position(Position::Logical(LogicalPosition::new(0.0, 0.0))) @@ -35,7 +35,7 @@ fn main() -> Result<(), impl std::error::Error> { fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: winit::window::WindowId, event: WindowEvent, ) { @@ -72,7 +72,7 @@ fn main() -> Result<(), impl std::error::Error> { } } - fn spawn_child_window(parent: &Window, event_loop: &ActiveEventLoop) -> Window { + fn spawn_child_window(parent: &Window, event_loop: &dyn ActiveEventLoop) -> Window { let parent = parent.raw_window_handle().unwrap(); let mut window_attributes = Window::default_attributes() .with_title("child window") diff --git a/examples/control_flow.rs b/examples/control_flow.rs index 1f57dcc2..7b35d1c2 100644 --- a/examples/control_flow.rs +++ b/examples/control_flow.rs @@ -56,7 +56,7 @@ struct ControlFlowDemo { } impl ApplicationHandler for ControlFlowDemo { - fn new_events(&mut self, _event_loop: &ActiveEventLoop, cause: StartCause) { + fn new_events(&mut self, _event_loop: &dyn ActiveEventLoop, cause: StartCause) { info!("new_events: {cause:?}"); self.wait_cancelled = match cause { @@ -65,7 +65,7 @@ impl ApplicationHandler for ControlFlowDemo { } } - fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { let window_attributes = Window::default_attributes().with_title( "Press 1, 2, 3 to change control flow mode. Press R to toggle redraw requests.", ); @@ -74,7 +74,7 @@ impl ApplicationHandler for ControlFlowDemo { fn window_event( &mut self, - _event_loop: &ActiveEventLoop, + _event_loop: &dyn ActiveEventLoop, _window_id: WindowId, event: WindowEvent, ) { @@ -120,7 +120,7 @@ impl ApplicationHandler for ControlFlowDemo { } } - fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) { if self.request_redraw && !self.wait_cancelled && !self.close_requested { self.window.as_ref().unwrap().request_redraw(); } diff --git a/examples/pump_events.rs b/examples/pump_events.rs index b9f6e782..1c307b63 100644 --- a/examples/pump_events.rs +++ b/examples/pump_events.rs @@ -22,14 +22,14 @@ fn main() -> std::process::ExitCode { } impl ApplicationHandler for PumpDemo { - fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { let window_attributes = Window::default_attributes().with_title("A fantastic window!"); self.window = Some(event_loop.create_window(window_attributes).unwrap()); } fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, _window_id: WindowId, event: WindowEvent, ) { diff --git a/examples/run_on_demand.rs b/examples/run_on_demand.rs index 6347b0bb..10f220a3 100644 --- a/examples/run_on_demand.rs +++ b/examples/run_on_demand.rs @@ -22,13 +22,13 @@ fn main() -> Result<(), Box> { } impl ApplicationHandler for App { - fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) { + fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) { if let Some(window) = self.window.as_ref() { window.request_redraw(); } } - fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { let window_attributes = Window::default_attributes() .with_title("Fantastic window number one!") .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)); @@ -39,7 +39,7 @@ fn main() -> Result<(), Box> { fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { diff --git a/examples/window.rs b/examples/window.rs index f51fc4b1..b1862da4 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -129,7 +129,7 @@ impl Application { fn create_window( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, _tab_id: Option, ) -> Result> { // TODO read-out activation token. @@ -175,7 +175,7 @@ impl Application { Ok(window_id) } - fn handle_action_from_proxy(&mut self, _event_loop: &ActiveEventLoop, action: Action) { + fn handle_action_from_proxy(&mut self, _event_loop: &dyn ActiveEventLoop, action: Action) { match action { #[cfg(web_platform)] Action::DumpMonitors => self.dump_monitors(_event_loop), @@ -188,7 +188,7 @@ impl Application { fn handle_action_with_window( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, action: Action, ) { @@ -286,7 +286,7 @@ impl Application { } } - fn dump_monitors(&self, event_loop: &ActiveEventLoop) { + fn dump_monitors(&self, event_loop: &dyn ActiveEventLoop) { info!("Monitors information"); let primary_monitor = event_loop.primary_monitor(); for monitor in event_loop.available_monitors() { @@ -366,7 +366,7 @@ impl Application { } impl ApplicationHandler for Application { - fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) { + fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { while let Ok(action) = self.receiver.try_recv() { self.handle_action_from_proxy(event_loop, action) } @@ -374,7 +374,7 @@ impl ApplicationHandler for Application { fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { @@ -516,14 +516,14 @@ impl ApplicationHandler for Application { fn device_event( &mut self, - _event_loop: &ActiveEventLoop, + _event_loop: &dyn ActiveEventLoop, device_id: DeviceId, event: DeviceEvent, ) { info!("Device {device_id:?} event: {event:?}"); } - fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { info!("Ready to create surfaces"); self.dump_monitors(event_loop); @@ -533,7 +533,7 @@ impl ApplicationHandler for Application { self.print_help(); } - fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) { if self.windows.is_empty() { info!("No windows left, exiting..."); event_loop.exit(); @@ -541,7 +541,7 @@ impl ApplicationHandler for Application { } #[cfg(not(any(android_platform, ios_platform)))] - fn exiting(&mut self, _event_loop: &ActiveEventLoop) { + fn exiting(&mut self, _event_loop: &dyn ActiveEventLoop) { // We must drop the context here. self.context = None; } @@ -755,7 +755,10 @@ impl WindowState { /// Custom cursor from an URL. #[cfg(web_platform)] - fn url_custom_cursor(&mut self, event_loop: &ActiveEventLoop) -> Result<(), Box> { + fn url_custom_cursor( + &mut self, + event_loop: &dyn ActiveEventLoop, + ) -> Result<(), Box> { let cursor = event_loop.create_custom_cursor(url_custom_cursor())?; self.window.set_cursor(cursor); @@ -767,7 +770,7 @@ impl WindowState { #[cfg(web_platform)] fn animation_custom_cursor( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, custom_cursors: &[CustomCursor], ) -> Result<(), Box> { use std::time::Duration; diff --git a/examples/x11_embed.rs b/examples/x11_embed.rs index 7b728d4b..c13075a6 100644 --- a/examples/x11_embed.rs +++ b/examples/x11_embed.rs @@ -18,7 +18,7 @@ fn main() -> Result<(), Box> { } impl ApplicationHandler for XEmbedDemo { - fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { let window_attributes = Window::default_attributes() .with_title("An embedded window!") .with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0)) @@ -29,7 +29,7 @@ fn main() -> Result<(), Box> { fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, _window_id: WindowId, event: WindowEvent, ) { @@ -44,7 +44,7 @@ fn main() -> Result<(), Box> { } } - fn about_to_wait(&mut self, _event_loop: &ActiveEventLoop) { + fn about_to_wait(&mut self, _event_loop: &dyn ActiveEventLoop) { self.window.as_ref().unwrap().request_redraw(); } } diff --git a/src/application.rs b/src/application.rs index d63a777a..8b268b05 100644 --- a/src/application.rs +++ b/src/application.rs @@ -12,7 +12,7 @@ pub trait ApplicationHandler { /// events, such as updating frame timing information for benchmarking or checking the /// [`StartCause`] to see if a timer set by /// [`ControlFlow::WaitUntil`][crate::event_loop::ControlFlow::WaitUntil] has elapsed. - fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { + fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) { let _ = (event_loop, cause); } @@ -46,7 +46,7 @@ pub trait ApplicationHandler { /// **Android / macOS / Orbital / Wayland / Windows / X11:** Unsupported. /// /// [`resumed()`]: Self::resumed - fn resumed(&mut self, event_loop: &ActiveEventLoop) { + fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) { let _ = event_loop; } @@ -91,7 +91,7 @@ pub trait ApplicationHandler { /// /// [`can_create_surfaces()`]: Self::can_create_surfaces /// [`destroy_surfaces()`]: Self::destroy_surfaces - fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop); + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop); /// Called after a wake up is requested using [`EventLoopProxy::wake_up()`]. /// @@ -126,15 +126,15 @@ pub trait ApplicationHandler { /// impl ApplicationHandler for MyApp { /// # fn window_event( /// # &mut self, - /// # _event_loop: &ActiveEventLoop, + /// # _event_loop: &dyn ActiveEventLoop, /// # _window_id: winit::window::WindowId, /// # _event: winit::event::WindowEvent, /// # ) { /// # } /// # - /// # fn can_create_surfaces(&mut self, _event_loop: &ActiveEventLoop) {} + /// # fn can_create_surfaces(&mut self, _event_loop: &dyn ActiveEventLoop) {} /// # - /// fn proxy_wake_up(&mut self, _event_loop: &ActiveEventLoop) { + /// fn proxy_wake_up(&mut self, _event_loop: &dyn ActiveEventLoop) { /// // Iterate current events, since wake-ups may have been merged. /// // /// // Note: We take care not to use `recv` or `iter` here, as those are blocking, @@ -180,14 +180,14 @@ pub trait ApplicationHandler { /// Ok(()) /// } /// ``` - fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) { + fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { let _ = event_loop; } /// Emitted when the OS sends an event to a winit window. fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, event: WindowEvent, ); @@ -195,7 +195,7 @@ pub trait ApplicationHandler { /// Emitted when the OS sends an event to a device. fn device_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, device_id: DeviceId, event: DeviceEvent, ) { @@ -213,7 +213,7 @@ pub trait ApplicationHandler { /// /// This is not an ideal event to drive application rendering from and instead applications /// should render in response to [`WindowEvent::RedrawRequested`] events. - fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) { let _ = event_loop; } @@ -247,7 +247,7 @@ pub trait ApplicationHandler { /// **Android / macOS / Orbital / Wayland / Windows / X11:** Unsupported. /// /// [`suspended()`]: Self::suspended - fn suspended(&mut self, event_loop: &ActiveEventLoop) { + fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) { let _ = event_loop; } @@ -286,7 +286,7 @@ pub trait ApplicationHandler { /// /// [`can_create_surfaces()`]: Self::can_create_surfaces /// [`destroy_surfaces()`]: Self::destroy_surfaces - fn destroy_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn destroy_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { let _ = event_loop; } @@ -294,7 +294,7 @@ pub trait ApplicationHandler { /// /// This is irreversible - if this method is called, it is guaranteed that the event loop /// will exit right after. - fn exiting(&mut self, event_loop: &ActiveEventLoop) { + fn exiting(&mut self, event_loop: &dyn ActiveEventLoop) { let _ = event_loop; } @@ -322,7 +322,7 @@ pub trait ApplicationHandler { /// ### Others /// /// - **macOS / Orbital / Wayland / Web / Windows:** Unsupported. - fn memory_warning(&mut self, event_loop: &ActiveEventLoop) { + fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) { let _ = event_loop; } } @@ -330,29 +330,29 @@ pub trait ApplicationHandler { #[deny(clippy::missing_trait_methods)] impl ApplicationHandler for &mut A { #[inline] - fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { + fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) { (**self).new_events(event_loop, cause); } #[inline] - fn resumed(&mut self, event_loop: &ActiveEventLoop) { + fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).resumed(event_loop); } #[inline] - fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).can_create_surfaces(event_loop); } #[inline] - fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) { + fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).proxy_wake_up(event_loop); } #[inline] fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { @@ -362,7 +362,7 @@ impl ApplicationHandler for &mut A { #[inline] fn device_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, device_id: DeviceId, event: DeviceEvent, ) { @@ -370,27 +370,27 @@ impl ApplicationHandler for &mut A { } #[inline] - fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).about_to_wait(event_loop); } #[inline] - fn suspended(&mut self, event_loop: &ActiveEventLoop) { + fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).suspended(event_loop); } #[inline] - fn destroy_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn destroy_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).destroy_surfaces(event_loop); } #[inline] - fn exiting(&mut self, event_loop: &ActiveEventLoop) { + fn exiting(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).exiting(event_loop); } #[inline] - fn memory_warning(&mut self, event_loop: &ActiveEventLoop) { + fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).memory_warning(event_loop); } } @@ -398,29 +398,29 @@ impl ApplicationHandler for &mut A { #[deny(clippy::missing_trait_methods)] impl ApplicationHandler for Box { #[inline] - fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { + fn new_events(&mut self, event_loop: &dyn ActiveEventLoop, cause: StartCause) { (**self).new_events(event_loop, cause); } #[inline] - fn resumed(&mut self, event_loop: &ActiveEventLoop) { + fn resumed(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).resumed(event_loop); } #[inline] - fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).can_create_surfaces(event_loop); } #[inline] - fn proxy_wake_up(&mut self, event_loop: &ActiveEventLoop) { + fn proxy_wake_up(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).proxy_wake_up(event_loop); } #[inline] fn window_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, window_id: WindowId, event: WindowEvent, ) { @@ -430,7 +430,7 @@ impl ApplicationHandler for Box { #[inline] fn device_event( &mut self, - event_loop: &ActiveEventLoop, + event_loop: &dyn ActiveEventLoop, device_id: DeviceId, event: DeviceEvent, ) { @@ -438,27 +438,27 @@ impl ApplicationHandler for Box { } #[inline] - fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + fn about_to_wait(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).about_to_wait(event_loop); } #[inline] - fn suspended(&mut self, event_loop: &ActiveEventLoop) { + fn suspended(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).suspended(event_loop); } #[inline] - fn destroy_surfaces(&mut self, event_loop: &ActiveEventLoop) { + fn destroy_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).destroy_surfaces(event_loop); } #[inline] - fn exiting(&mut self, event_loop: &ActiveEventLoop) { + fn exiting(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).exiting(event_loop); } #[inline] - fn memory_warning(&mut self, event_loop: &ActiveEventLoop) { + fn memory_warning(&mut self, event_loop: &dyn ActiveEventLoop) { (**self).memory_warning(event_loop); } } diff --git a/src/changelog/unreleased.md b/src/changelog/unreleased.md index 18aa542c..5c408300 100644 --- a/src/changelog/unreleased.md +++ b/src/changelog/unreleased.md @@ -59,6 +59,8 @@ changelog entry. ### Changed +- Change `ActiveEventLoop` to be a trait. +- `ApplicationHandler` now uses `dyn ActiveEventLoop`. - On Web, let events wake up event loop immediately when using `ControlFlow::Poll`. - Bump MSRV from `1.70` to `1.73`. - Changed `ApplicationHandler::user_event` to `user_wake_up`, removing the diff --git a/src/cursor.rs b/src/cursor.rs index cae0e80d..b54e082d 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -50,7 +50,7 @@ impl From for Cursor { /// ```no_run /// # use winit::event_loop::ActiveEventLoop; /// # use winit::window::Window; -/// # fn scope(event_loop: &ActiveEventLoop, window: &Window) { +/// # fn scope(event_loop: &dyn ActiveEventLoop, window: &Window) { /// use winit::window::CustomCursor; /// /// let w = 10; diff --git a/src/event_loop.rs b/src/event_loop.rs index 0595001f..d769d11e 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -8,6 +8,7 @@ //! //! See the root-level documentation for information on how to create and use an event loop to //! handle events. +use std::any::Any; use std::fmt; use std::marker::PhantomData; #[cfg(any(x11_platform, wayland_platform))] @@ -45,15 +46,6 @@ pub struct EventLoop { pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync } -/// Target that associates windows with an [`EventLoop`]. -/// -/// This type exists to allow you to create new windows while Winit executes -/// your callback. -pub struct ActiveEventLoop { - pub(crate) p: platform_impl::ActiveEventLoop, - pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync -} - /// Object that allows building the event loop. /// /// This is used to make specifying options that affect the whole application @@ -129,12 +121,6 @@ impl fmt::Debug for EventLoop { } } -impl fmt::Debug for ActiveEventLoop { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("ActiveEventLoop { .. }") - } -} - /// Set through [`ActiveEventLoop::set_control_flow()`]. /// /// Indicates the desired behavior of the event loop after [`about_to_wait`] is called. @@ -239,14 +225,14 @@ impl EventLoop { /// Creates an [`EventLoopProxy`] that can be used to dispatch user events /// to the main event loop, possibly from another thread. pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy { event_loop_proxy: self.event_loop.window_target().p.create_proxy() } + self.event_loop.window_target().create_proxy() } /// Gets a persistent reference to the underlying platform display. /// /// See the [`OwnedDisplayHandle`] type for more information. pub fn owned_display_handle(&self) -> OwnedDisplayHandle { - OwnedDisplayHandle { platform: self.event_loop.window_target().p.owned_display_handle() } + self.event_loop.window_target().owned_display_handle() } /// Change if or when [`DeviceEvent`]s are captured. @@ -260,13 +246,12 @@ impl EventLoop { allowed = ?allowed ) .entered(); - - self.event_loop.window_target().p.listen_device_events(allowed); + self.event_loop.window_target().listen_device_events(allowed) } /// Sets the [`ControlFlow`]. pub fn set_control_flow(&self, control_flow: ControlFlow) { - self.event_loop.window_target().p.set_control_flow(control_flow) + self.event_loop.window_target().set_control_flow(control_flow); } /// Create custom cursor. @@ -278,14 +263,14 @@ impl EventLoop { &self, custom_cursor: CustomCursorSource, ) -> Result { - self.event_loop.window_target().p.create_custom_cursor(custom_cursor) + self.event_loop.window_target().create_custom_cursor(custom_cursor) } } #[cfg(feature = "rwh_06")] impl rwh_06::HasDisplayHandle for EventLoop { fn display_handle(&self) -> Result, rwh_06::HandleError> { - rwh_06::HasDisplayHandle::display_handle(self.event_loop.window_target()) + rwh_06::HasDisplayHandle::display_handle(self.event_loop.window_target().rwh_06_handle()) } } @@ -317,12 +302,10 @@ impl AsRawFd for EventLoop { } } -impl ActiveEventLoop { +pub trait ActiveEventLoop { /// Creates an [`EventLoopProxy`] that can be used to dispatch user events /// to the main event loop, possibly from another thread. - pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy { event_loop_proxy: self.p.create_proxy() } - } + fn create_proxy(&self) -> EventLoopProxy; /// Create the window. /// @@ -332,31 +315,17 @@ impl ActiveEventLoop { /// /// - **Web:** The window is created but not inserted into the Web page automatically. Please /// see the Web platform module for more information. - #[inline] - pub fn create_window(&self, window_attributes: WindowAttributes) -> Result { - let _span = tracing::debug_span!( - "winit::ActiveEventLoop::create_window", - window_attributes = ?window_attributes - ) - .entered(); - - let window = platform_impl::Window::new(&self.p, window_attributes)?; - Ok(Window { window }) - } + fn create_window(&self, window_attributes: WindowAttributes) -> Result; /// Create custom cursor. /// /// ## Platform-specific /// /// **iOS / Android / Orbital:** Unsupported. - pub fn create_custom_cursor( + fn create_custom_cursor( &self, custom_cursor: CustomCursorSource, - ) -> Result { - let _span = tracing::debug_span!("winit::ActiveEventLoop::create_custom_cursor",).entered(); - - self.p.create_custom_cursor(custom_cursor) - } + ) -> Result; /// Returns the list of all the monitors available on the system. /// @@ -368,13 +337,7 @@ impl ActiveEventLoop { doc = "[detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]." )] #[cfg_attr(not(any(web_platform, docsrs)), doc = "detailed monitor permissions.")] - #[inline] - pub fn available_monitors(&self) -> impl Iterator { - let _span = tracing::debug_span!("winit::ActiveEventLoop::available_monitors",).entered(); - - #[allow(clippy::useless_conversion)] // false positive on some platforms - self.p.available_monitors().into_iter().map(|inner| MonitorHandle { inner }) - } + fn available_monitors(&self) -> Box>; /// Returns the primary monitor of the system. /// @@ -389,12 +352,7 @@ impl ActiveEventLoop { doc = " [detailed monitor permissions][crate::platform::web::ActiveEventLoopExtWeb::request_detailed_monitor_permission]." )] #[cfg_attr(not(any(web_platform, docsrs)), doc = " detailed monitor permissions.")] - #[inline] - pub fn primary_monitor(&self) -> Option { - let _span = tracing::debug_span!("winit::ActiveEventLoop::primary_monitor",).entered(); - - self.p.primary_monitor().map(|inner| MonitorHandle { inner }) - } + fn primary_monitor(&self) -> Option; /// Change if or when [`DeviceEvent`]s are captured. /// @@ -407,15 +365,7 @@ impl ActiveEventLoop { /// - **Wayland / macOS / iOS / Android / Orbital:** Unsupported. /// /// [`DeviceEvent`]: crate::event::DeviceEvent - pub fn listen_device_events(&self, allowed: DeviceEvents) { - let _span = tracing::debug_span!( - "winit::ActiveEventLoop::listen_device_events", - allowed = ?allowed - ) - .entered(); - - self.p.listen_device_events(allowed); - } + fn listen_device_events(&self, allowed: DeviceEvents); /// Returns the current system theme. /// @@ -424,51 +374,37 @@ impl ActiveEventLoop { /// ## Platform-specific /// /// - **iOS / Android / Wayland / x11 / Orbital:** Unsupported. - pub fn system_theme(&self) -> Option { - self.p.system_theme() - } + fn system_theme(&self) -> Option; /// Sets the [`ControlFlow`]. - pub fn set_control_flow(&self, control_flow: ControlFlow) { - self.p.set_control_flow(control_flow) - } + fn set_control_flow(&self, control_flow: ControlFlow); /// Gets the current [`ControlFlow`]. - pub fn control_flow(&self) -> ControlFlow { - self.p.control_flow() - } + fn control_flow(&self) -> ControlFlow; /// This exits the event loop. /// /// See [`exiting`][crate::application::ApplicationHandler::exiting]. - pub fn exit(&self) { - let _span = tracing::debug_span!("winit::ActiveEventLoop::exit",).entered(); - - self.p.exit() - } + fn exit(&self); /// Returns if the [`EventLoop`] is about to stop. /// /// See [`exit()`][Self::exit]. - pub fn exiting(&self) -> bool { - self.p.exiting() - } + fn exiting(&self) -> bool; /// Gets a persistent reference to the underlying platform display. /// /// See the [`OwnedDisplayHandle`] type for more information. - pub fn owned_display_handle(&self) -> OwnedDisplayHandle { - OwnedDisplayHandle { platform: self.p.owned_display_handle() } - } -} + fn owned_display_handle(&self) -> OwnedDisplayHandle; -#[cfg(feature = "rwh_06")] -impl rwh_06::HasDisplayHandle for ActiveEventLoop { - fn display_handle(&self) -> Result, rwh_06::HandleError> { - let raw = self.p.raw_display_handle_rwh_06()?; - // SAFETY: The display will never be deallocated while the event loop is alive. - Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw) }) - } + /// Get the [`ActiveEventLoop`] as [`Any`]. + /// + /// This is useful for downcasting to a concrete event loop type. + fn as_any(&self) -> &dyn Any; + + /// Get the raw-window-handle handle. + #[cfg(feature = "rwh_06")] + fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle; } /// A proxy for the underlying display handle. @@ -486,7 +422,7 @@ impl rwh_06::HasDisplayHandle for ActiveEventLoop { #[derive(Clone)] pub struct OwnedDisplayHandle { #[cfg_attr(not(feature = "rwh_06"), allow(dead_code))] - platform: platform_impl::OwnedDisplayHandle, + pub(crate) platform: platform_impl::OwnedDisplayHandle, } impl fmt::Debug for OwnedDisplayHandle { @@ -512,7 +448,7 @@ impl rwh_06::HasDisplayHandle for OwnedDisplayHandle { /// Control the [`EventLoop`], possibly from a different thread, without referencing it directly. #[derive(Clone)] pub struct EventLoopProxy { - event_loop_proxy: platform_impl::EventLoopProxy, + pub(crate) event_loop_proxy: platform_impl::EventLoopProxy, } impl EventLoopProxy { diff --git a/src/lib.rs b/src/lib.rs index 5e5036ba..6d8f084b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -52,11 +52,11 @@ //! } //! //! impl ApplicationHandler for App { -//! fn can_create_surfaces(&mut self, event_loop: &ActiveEventLoop) { +//! fn can_create_surfaces(&mut self, event_loop: &dyn ActiveEventLoop) { //! self.window = Some(event_loop.create_window(Window::default_attributes()).unwrap()); //! } //! -//! fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) { +//! fn window_event(&mut self, event_loop: &dyn ActiveEventLoop, id: WindowId, event: WindowEvent) { //! match event { //! WindowEvent::CloseRequested => { //! println!("The close button was pressed; stopping"); diff --git a/src/platform/android.rs b/src/platform/android.rs index fe435be2..27171fd2 100644 --- a/src/platform/android.rs +++ b/src/platform/android.rs @@ -109,9 +109,11 @@ impl WindowExtAndroid for Window { } } -impl ActiveEventLoopExtAndroid for ActiveEventLoop { +impl ActiveEventLoopExtAndroid for &dyn ActiveEventLoop { fn android_app(&self) -> &AndroidApp { - &self.p.app + let event_loop = + self.as_any().downcast_ref::().unwrap(); + &event_loop.app } } diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 8938a5ca..af2d1846 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -395,21 +395,37 @@ pub trait ActiveEventLoopExtMacOS { fn allows_automatic_window_tabbing(&self) -> bool; } -impl ActiveEventLoopExtMacOS for ActiveEventLoop { +impl ActiveEventLoopExtMacOS for &dyn ActiveEventLoop { fn hide_application(&self) { - self.p.hide_application() + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non macOS event loop on macOS"); + event_loop.hide_application() } fn hide_other_applications(&self) { - self.p.hide_other_applications() + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non macOS event loop on macOS"); + event_loop.hide_other_applications() } fn set_allows_automatic_window_tabbing(&self, enabled: bool) { - self.p.set_allows_automatic_window_tabbing(enabled); + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non macOS event loop on macOS"); + event_loop.set_allows_automatic_window_tabbing(enabled); } fn allows_automatic_window_tabbing(&self) -> bool { - self.p.allows_automatic_window_tabbing() + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non macOS event loop on macOS"); + event_loop.allows_automatic_window_tabbing() } } diff --git a/src/platform/startup_notify.rs b/src/platform/startup_notify.rs index c9047a03..3927384c 100644 --- a/src/platform/startup_notify.rs +++ b/src/platform/startup_notify.rs @@ -25,6 +25,8 @@ use std::env; use crate::error::NotSupportedError; use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial}; +#[cfg(wayland_platform)] +use crate::platform::wayland::ActiveEventLoopExtWayland; use crate::window::{ActivationToken, Window, WindowAttributes}; /// The variable which is used mostly on X11. @@ -55,16 +57,18 @@ pub trait WindowAttributesExtStartupNotify { fn with_activation_token(self, token: ActivationToken) -> Self; } -impl EventLoopExtStartupNotify for ActiveEventLoop { +impl EventLoopExtStartupNotify for &dyn ActiveEventLoop { fn read_token_from_env(&self) -> Option { - match self.p { - #[cfg(wayland_platform)] - crate::platform_impl::ActiveEventLoop::Wayland(_) => env::var(WAYLAND_VAR), - #[cfg(x11_platform)] - crate::platform_impl::ActiveEventLoop::X(_) => env::var(X11_VAR), + #[cfg(x11_platform)] + let _is_wayland = false; + #[cfg(wayland_platform)] + let _is_wayland = self.is_wayland(); + + if _is_wayland { + env::var(WAYLAND_VAR).ok().map(ActivationToken::_new) + } else { + env::var(X11_VAR).ok().map(ActivationToken::_new) } - .ok() - .map(ActivationToken::_new) } } diff --git a/src/platform/wayland.rs b/src/platform/wayland.rs index f9b339f9..7b489abe 100644 --- a/src/platform/wayland.rs +++ b/src/platform/wayland.rs @@ -24,10 +24,10 @@ pub trait ActiveEventLoopExtWayland { fn is_wayland(&self) -> bool; } -impl ActiveEventLoopExtWayland for ActiveEventLoop { +impl ActiveEventLoopExtWayland for &dyn ActiveEventLoop { #[inline] fn is_wayland(&self) -> bool { - self.p.is_wayland() + self.as_any().downcast_ref::().is_some() } } diff --git a/src/platform/web.rs b/src/platform/web.rs index 4e968201..f86140fb 100644 --- a/src/platform/web.rs +++ b/src/platform/web.rs @@ -94,7 +94,7 @@ pub trait WindowExtWeb { /// Returns whether using [`CursorGrabMode::Locked`] returns raw, un-accelerated mouse input. /// - /// This is the same as [`ActiveEventLoop::is_cursor_lock_raw()`], and is provided for + /// This is the same as [`ActiveEventLoopExtWeb::is_cursor_lock_raw()`], and is provided for /// convenience. /// /// [`CursorGrabMode::Locked`]: crate::window::CursorGrabMode::Locked @@ -344,50 +344,86 @@ pub trait ActiveEventLoopExtWeb { fn has_detailed_monitor_permission(&self) -> bool; } -impl ActiveEventLoopExtWeb for ActiveEventLoop { +impl ActiveEventLoopExtWeb for &dyn ActiveEventLoop { #[inline] fn create_custom_cursor_async(&self, source: CustomCursorSource) -> CustomCursorFuture { - self.p.create_custom_cursor_async(source) + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non Web event loop on Web"); + event_loop.create_custom_cursor_async(source) } #[inline] fn set_poll_strategy(&self, strategy: PollStrategy) { - self.p.set_poll_strategy(strategy); + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non Web event loop on Web"); + event_loop.set_poll_strategy(strategy); } #[inline] fn poll_strategy(&self) -> PollStrategy { - self.p.poll_strategy() + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non Web event loop on Web"); + event_loop.poll_strategy() } #[inline] fn set_wait_until_strategy(&self, strategy: WaitUntilStrategy) { - self.p.set_wait_until_strategy(strategy); + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non Web event loop on Web"); + event_loop.set_wait_until_strategy(strategy); } #[inline] fn wait_until_strategy(&self) -> WaitUntilStrategy { - self.p.wait_until_strategy() + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non Web event loop on Web"); + event_loop.wait_until_strategy() } #[inline] fn is_cursor_lock_raw(&self) -> bool { - self.p.is_cursor_lock_raw() + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non Web event loop on Web"); + event_loop.is_cursor_lock_raw() } #[inline] fn has_multiple_screens(&self) -> Result { - self.p.has_multiple_screens() + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non Web event loop on Web"); + event_loop.has_multiple_screens() } #[inline] fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture { - MonitorPermissionFuture(self.p.request_detailed_monitor_permission()) + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non Web event loop on Web"); + MonitorPermissionFuture(event_loop.request_detailed_monitor_permission()) } #[inline] fn has_detailed_monitor_permission(&self) -> bool { - self.p.has_detailed_monitor_permission() + let event_loop = self + .as_any() + .downcast_ref::() + .expect("non Web event loop on Web"); + event_loop.has_detailed_monitor_permission() } } @@ -623,7 +659,7 @@ pub trait MonitorHandleExtWeb { /// [`false`] will always represent the current monitor the browser window is in instead of a /// specific monitor. /// - /// See [`ActiveEventLoop::request_detailed_monitor_permission()`]. + /// See [`ActiveEventLoopExtWeb::request_detailed_monitor_permission()`]. fn is_detailed(&self) -> bool; } diff --git a/src/platform/x11.rs b/src/platform/x11.rs index 7f1e2454..612d22c9 100644 --- a/src/platform/x11.rs +++ b/src/platform/x11.rs @@ -91,10 +91,10 @@ pub trait ActiveEventLoopExtX11 { fn is_x11(&self) -> bool; } -impl ActiveEventLoopExtX11 for ActiveEventLoop { +impl ActiveEventLoopExtX11 for &dyn ActiveEventLoop { #[inline] fn is_x11(&self) -> bool { - !self.p.is_wayland() + self.as_any().downcast_ref::().is_some() } } @@ -187,7 +187,7 @@ pub trait WindowAttributesExtX11 { /// use winit::window::Window; /// use winit::event_loop::ActiveEventLoop; /// use winit::platform::x11::{XWindow, WindowAttributesExtX11}; - /// # fn create_window(event_loop: &ActiveEventLoop) -> Result<(), Box> { + /// # fn create_window(event_loop: &dyn ActiveEventLoop) -> Result<(), Box> { /// let parent_window_id = std::env::args().nth(1).unwrap().parse::()?; /// let window_attributes = Window::default_attributes().with_embed_parent_window(parent_window_id); /// let window = event_loop.create_window(window_attributes)?; diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 1a9cabfe..df0f91f5 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -1,7 +1,7 @@ +use std::any::Any; use std::cell::Cell; use std::collections::VecDeque; use std::hash::Hash; -use std::marker::PhantomData; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; @@ -17,12 +17,16 @@ use crate::cursor::Cursor; use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size}; use crate::error::{self, EventLoopError, ExternalError, NotSupportedError}; use crate::event::{self, Force, InnerSizeWriter, StartCause}; -use crate::event_loop::{self, ControlFlow, DeviceEvents}; +use crate::event_loop::{ + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, +}; +use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::platform::pump_events::PumpStatus; use crate::platform_impl::Fullscreen; use crate::window::{ self, CursorGrabMode, CustomCursor, CustomCursorSource, ImePurpose, ResizeDirection, Theme, - WindowButtons, WindowLevel, + Window as RootWindow, WindowAttributes, WindowButtons, WindowLevel, }; mod keycodes; @@ -98,7 +102,7 @@ pub struct KeyEventExtra {} pub struct EventLoop { pub(crate) android_app: AndroidApp, - window_target: event_loop::ActiveEventLoop, + window_target: ActiveEventLoop, redraw_flag: SharedFlag, loop_running: bool, // Dispatched `NewEvents` running: bool, @@ -134,18 +138,12 @@ impl EventLoop { Ok(Self { android_app: android_app.clone(), - window_target: event_loop::ActiveEventLoop { - p: ActiveEventLoop { - app: android_app.clone(), - control_flow: Cell::new(ControlFlow::default()), - exit: Cell::new(false), - redraw_requester: RedrawRequester::new( - &redraw_flag, - android_app.create_waker(), - ), - proxy_wake_up, - }, - _marker: PhantomData, + window_target: ActiveEventLoop { + app: android_app.clone(), + control_flow: Cell::new(ControlFlow::default()), + exit: Cell::new(false), + redraw_requester: RedrawRequester::new(&redraw_flag, android_app.create_waker()), + proxy_wake_up, }, redraw_flag, loop_running: false, @@ -157,6 +155,10 @@ impl EventLoop { }) } + pub(crate) fn window_target(&self) -> &dyn RootActiveEventLoop { + &self.window_target + } + fn single_iteration( &mut self, main_event: Option>, @@ -168,17 +170,17 @@ impl EventLoop { let mut pending_redraw = self.pending_redraw; let mut resized = false; - app.new_events(self.window_target(), cause); + app.new_events(&self.window_target, cause); if let Some(event) = main_event { trace!("Handling main event {:?}", event); match event { MainEvent::InitWindow { .. } => { - app.can_create_surfaces(self.window_target()); + app.can_create_surfaces(&self.window_target); }, MainEvent::TerminateWindow { .. } => { - app.destroy_surfaces(self.window_target()); + app.destroy_surfaces(&self.window_target); }, MainEvent::WindowResized { .. } => resized = true, MainEvent::RedrawNeeded { .. } => pending_redraw = true, @@ -189,13 +191,13 @@ impl EventLoop { HAS_FOCUS.store(true, Ordering::Relaxed); let window_id = window::WindowId(WindowId); let event = event::WindowEvent::Focused(true); - app.window_event(self.window_target(), window_id, event); + app.window_event(&self.window_target, window_id, event); }, MainEvent::LostFocus => { HAS_FOCUS.store(false, Ordering::Relaxed); let window_id = window::WindowId(WindowId); let event = event::WindowEvent::Focused(false); - app.window_event(self.window_target(), window_id, event); + app.window_event(&self.window_target, window_id, event); }, MainEvent::ConfigChanged { .. } => { let monitor = MonitorHandle::new(self.android_app.clone()); @@ -213,11 +215,11 @@ impl EventLoop { scale_factor, }; - app.window_event(self.window_target(), window_id, event); + app.window_event(&self.window_target, window_id, event); } }, MainEvent::LowMemory => { - app.memory_warning(self.window_target()); + app.memory_warning(&self.window_target); }, MainEvent::Start => { // XXX: how to forward this state to applications? @@ -276,8 +278,8 @@ impl EventLoop { }, } - if self.window_target.p.proxy_wake_up.swap(false, Ordering::Relaxed) { - app.proxy_wake_up(self.window_target()); + if self.window_target.proxy_wake_up.swap(false, Ordering::Relaxed) { + app.proxy_wake_up(&self.window_target); } if self.running { @@ -291,7 +293,7 @@ impl EventLoop { }; let window_id = window::WindowId(WindowId); let event = event::WindowEvent::Resized(size); - app.window_event(self.window_target(), window_id, event); + app.window_event(&self.window_target, window_id, event); } pending_redraw |= self.redraw_flag.get_and_reset(); @@ -299,12 +301,12 @@ impl EventLoop { pending_redraw = false; let window_id = window::WindowId(WindowId); let event = event::WindowEvent::RedrawRequested; - app.window_event(self.window_target(), window_id, event); + app.window_event(&self.window_target, window_id, event); } } // This is always the last event we dispatch before poll again - app.about_to_wait(self.window_target()); + app.about_to_wait(&self.window_target); self.pending_redraw = pending_redraw; } @@ -361,7 +363,7 @@ impl EventLoop { force: Some(Force::Normalized(pointer.pressure() as f64)), }); - app.window_event(self.window_target(), window_id, event); + app.window_event(&self.window_target, window_id, event); } } }, @@ -404,7 +406,7 @@ impl EventLoop { is_synthetic: false, }; - app.window_event(self.window_target(), window_id, event); + app.window_event(&self.window_target, window_id, event); }, } }, @@ -424,7 +426,7 @@ impl EventLoop { &mut self, mut app: A, ) -> Result<(), EventLoopError> { - self.window_target.p.clear_exit(); + self.window_target.clear_exit(); loop { match self.pump_app_events(None, &mut app) { PumpStatus::Exit(0) => { @@ -466,7 +468,7 @@ impl EventLoop { if self.exiting() { self.loop_running = false; - app.exiting(self.window_target()); + app.exiting(&self.window_target); PumpStatus::Exit(0) } else { @@ -484,7 +486,7 @@ impl EventLoop { self.pending_redraw |= self.redraw_flag.get_and_reset(); timeout = if self.running - && (self.pending_redraw || self.window_target.p.proxy_wake_up.load(Ordering::Relaxed)) + && (self.pending_redraw || self.window_target.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) @@ -517,7 +519,7 @@ impl EventLoop { self.pending_redraw |= self.redraw_flag.get_and_reset(); if !self.running || (!self.pending_redraw - && !self.window_target.p.proxy_wake_up.load(Ordering::Relaxed)) + && !self.window_target.proxy_wake_up.load(Ordering::Relaxed)) { return; } @@ -547,16 +549,12 @@ impl EventLoop { }); } - pub fn window_target(&self) -> &event_loop::ActiveEventLoop { - &self.window_target - } - fn control_flow(&self) -> ControlFlow { - self.window_target.p.control_flow() + self.window_target.control_flow() } fn exiting(&self) -> bool { - self.window_target.p.exiting() + self.window_target.exiting() } } @@ -582,65 +580,85 @@ pub struct ActiveEventLoop { } impl ActiveEventLoop { - pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy { proxy_wake_up: self.proxy_wake_up.clone(), waker: self.app.create_waker() } + fn clear_exit(&self) { + self.exit.set(false); + } +} + +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 } } - pub fn primary_monitor(&self) -> Option { - Some(MonitorHandle::new(self.app.clone())) + fn create_window( + &self, + window_attributes: WindowAttributes, + ) -> Result { + let window = Window::new(self, window_attributes)?; + Ok(RootWindow { window }) } - pub fn create_custom_cursor( + fn create_custom_cursor( &self, _source: CustomCursorSource, ) -> Result { Err(ExternalError::NotSupported(NotSupportedError::new())) } - pub fn available_monitors(&self) -> VecDeque { - let mut v = VecDeque::with_capacity(1); - v.push_back(MonitorHandle::new(self.app.clone())); - v + fn available_monitors(&self) -> Box> { + let handle = RootMonitorHandle { inner: MonitorHandle::new(self.app.clone()) }; + Box::new(vec![handle].into_iter()) } - #[inline] - pub fn listen_device_events(&self, _allowed: DeviceEvents) {} + fn primary_monitor(&self) -> Option { + Some(RootMonitorHandle { inner: MonitorHandle::new(self.app.clone()) }) + } - #[inline] - pub fn system_theme(&self) -> Option { + fn system_theme(&self) -> Option { None } - #[cfg(feature = "rwh_06")] - #[inline] - pub fn raw_display_handle_rwh_06( - &self, - ) -> Result { - Ok(rwh_06::RawDisplayHandle::Android(rwh_06::AndroidDisplayHandle::new())) - } + fn listen_device_events(&self, _allowed: DeviceEvents) {} - pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { + fn set_control_flow(&self, control_flow: ControlFlow) { self.control_flow.set(control_flow) } - pub(crate) fn control_flow(&self) -> ControlFlow { + fn control_flow(&self) -> ControlFlow { self.control_flow.get() } - pub(crate) fn exit(&self) { + fn exit(&self) { self.exit.set(true) } - pub(crate) fn clear_exit(&self) { - self.exit.set(false) - } - - pub(crate) fn exiting(&self) -> bool { + fn exiting(&self) -> bool { self.exit.get() } - pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle { - OwnedDisplayHandle + fn owned_display_handle(&self) -> RootOwnedDisplayHandle { + RootOwnedDisplayHandle { platform: OwnedDisplayHandle } + } + + fn as_any(&self) -> &dyn Any { + self + } + + #[cfg(feature = "rwh_06")] + fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle { + self + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for ActiveEventLoop { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + let raw = rwh_06::AndroidDisplayHandle::new(); + Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw.into()) }) } } diff --git a/src/platform_impl/apple/appkit/app_state.rs b/src/platform_impl/apple/appkit/app_state.rs index b90a85c7..0a82daf0 100644 --- a/src/platform_impl/apple/appkit/app_state.rs +++ b/src/platform_impl/apple/appkit/app_state.rs @@ -16,7 +16,7 @@ use super::observer::{EventLoopWaker, RunLoop}; use super::{menu, WindowId}; use crate::application::ApplicationHandler; use crate::event::{StartCause, WindowEvent}; -use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow}; +use crate::event_loop::ControlFlow; use crate::window::WindowId as RootWindowId; #[derive(Debug)] @@ -282,7 +282,7 @@ impl ApplicationDelegate { #[track_caller] pub fn maybe_queue_with_handler( &self, - callback: impl FnOnce(&mut dyn ApplicationHandler, &RootActiveEventLoop) + 'static, + callback: impl FnOnce(&mut dyn ApplicationHandler, &ActiveEventLoop) + 'static, ) { // Most programmer actions in AppKit (e.g. change window fullscreen, set focused, etc.) // result in an event being queued, and applied at a later point. @@ -302,11 +302,9 @@ impl ApplicationDelegate { } #[track_caller] - fn with_handler( - &self, - callback: impl FnOnce(&mut dyn ApplicationHandler, &RootActiveEventLoop), - ) { - let event_loop = ActiveEventLoop::new_root(self.retain()); + fn with_handler(&self, callback: impl FnOnce(&mut dyn ApplicationHandler, &ActiveEventLoop)) { + let event_loop = + ActiveEventLoop { delegate: self.retain(), mtm: MainThreadMarker::from(self) }; self.ivars().event_handler.handle(callback, &event_loop); } diff --git a/src/platform_impl/apple/appkit/event_handler.rs b/src/platform_impl/apple/appkit/event_handler.rs index c8a33ad9..8cc75554 100644 --- a/src/platform_impl/apple/appkit/event_handler.rs +++ b/src/platform_impl/apple/appkit/event_handler.rs @@ -2,7 +2,7 @@ use std::cell::RefCell; use std::{fmt, mem}; use crate::application::ApplicationHandler; -use crate::event_loop::ActiveEventLoop as RootActiveEventLoop; +use crate::platform_impl::ActiveEventLoop; #[derive(Default)] pub(crate) struct EventHandler { @@ -110,8 +110,8 @@ impl EventHandler { pub(crate) fn handle( &self, - callback: impl FnOnce(&mut dyn ApplicationHandler, &RootActiveEventLoop), - event_loop: &RootActiveEventLoop, + callback: impl FnOnce(&mut dyn ApplicationHandler, &ActiveEventLoop), + event_loop: &ActiveEventLoop, ) { match self.inner.try_borrow_mut().as_deref_mut() { Ok(Some(user_app)) => { diff --git a/src/platform_impl/apple/appkit/event_loop.rs b/src/platform_impl/apple/appkit/event_loop.rs index 849e0435..5590b658 100644 --- a/src/platform_impl/apple/appkit/event_loop.rs +++ b/src/platform_impl/apple/appkit/event_loop.rs @@ -1,7 +1,5 @@ use std::any::Any; use std::cell::Cell; -use std::collections::VecDeque; -use std::marker::PhantomData; use std::os::raw::c_void; use std::panic::{catch_unwind, resume_unwind, RefUnwindSafe, UnwindSafe}; use std::ptr; @@ -25,14 +23,21 @@ use super::app::WinitApplication; use super::app_state::ApplicationDelegate; use super::cursor::CustomCursor; use super::event::dummy_event; -use super::monitor::{self, MonitorHandle}; +use super::monitor; use super::observer::setup_control_flow_observers; use crate::application::ApplicationHandler; use crate::error::{EventLoopError, ExternalError}; -use crate::event_loop::{ActiveEventLoop as RootWindowTarget, ControlFlow, DeviceEvents}; +use crate::event_loop::{ + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, +}; +use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::platform::macos::ActivationPolicy; use crate::platform::pump_events::PumpStatus; -use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme}; +use crate::platform_impl::Window; +use crate::window::{ + CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow, +}; #[derive(Default)] pub struct PanicInfo { @@ -66,85 +71,15 @@ impl PanicInfo { #[derive(Debug)] pub struct ActiveEventLoop { - delegate: Retained, + pub(super) delegate: Retained, pub(super) mtm: MainThreadMarker, } impl ActiveEventLoop { - pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy::new(self.delegate.proxy_wake_up()) - } - - pub(super) fn new_root(delegate: Retained) -> RootWindowTarget { - let mtm = MainThreadMarker::from(&*delegate); - let p = Self { delegate, mtm }; - RootWindowTarget { p, _marker: PhantomData } - } - pub(super) fn app_delegate(&self) -> &ApplicationDelegate { &self.delegate } - pub fn create_custom_cursor( - &self, - source: CustomCursorSource, - ) -> Result { - Ok(RootCustomCursor { inner: CustomCursor::new(source.inner)? }) - } - - #[inline] - pub fn available_monitors(&self) -> VecDeque { - monitor::available_monitors() - } - - #[inline] - pub fn primary_monitor(&self) -> Option { - let monitor = monitor::primary_monitor(); - Some(monitor) - } - - #[inline] - pub fn listen_device_events(&self, _allowed: DeviceEvents) {} - - #[inline] - pub fn system_theme(&self) -> Option { - let app = NSApplication::sharedApplication(self.mtm); - - if app.respondsToSelector(sel!(effectiveAppearance)) { - Some(super::window_delegate::appearance_to_theme(&app.effectiveAppearance())) - } else { - Some(Theme::Light) - } - } - - #[cfg(feature = "rwh_06")] - #[inline] - pub fn raw_display_handle_rwh_06( - &self, - ) -> Result { - Ok(rwh_06::RawDisplayHandle::AppKit(rwh_06::AppKitDisplayHandle::new())) - } - - pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { - self.delegate.set_control_flow(control_flow) - } - - pub(crate) fn control_flow(&self) -> ControlFlow { - self.delegate.control_flow() - } - - pub(crate) fn exit(&self) { - self.delegate.exit() - } - - pub(crate) fn exiting(&self) -> bool { - self.delegate.exiting() - } - - pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle { - OwnedDisplayHandle - } - pub(crate) fn hide_application(&self) { NSApplication::sharedApplication(self.mtm).hide(None) } @@ -162,6 +97,86 @@ impl ActiveEventLoop { } } +impl RootActiveEventLoop for ActiveEventLoop { + fn create_proxy(&self) -> RootEventLoopProxy { + let event_loop_proxy = EventLoopProxy::new(self.delegate.proxy_wake_up()); + RootEventLoopProxy { event_loop_proxy } + } + + fn create_window( + &self, + window_attributes: crate::window::WindowAttributes, + ) -> Result { + let window = Window::new(self, window_attributes)?; + Ok(RootWindow { window }) + } + + fn create_custom_cursor( + &self, + source: CustomCursorSource, + ) -> Result { + Ok(RootCustomCursor { inner: CustomCursor::new(source.inner)? }) + } + + fn available_monitors(&self) -> Box> { + Box::new(monitor::available_monitors().into_iter().map(|inner| RootMonitorHandle { inner })) + } + + fn primary_monitor(&self) -> Option { + let monitor = monitor::primary_monitor(); + Some(RootMonitorHandle { inner: monitor }) + } + + fn listen_device_events(&self, _allowed: DeviceEvents) {} + + fn system_theme(&self) -> Option { + let app = NSApplication::sharedApplication(self.mtm); + + if app.respondsToSelector(sel!(effectiveAppearance)) { + Some(super::window_delegate::appearance_to_theme(&app.effectiveAppearance())) + } else { + Some(Theme::Light) + } + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.delegate.set_control_flow(control_flow) + } + + fn control_flow(&self) -> ControlFlow { + self.delegate.control_flow() + } + + fn exit(&self) { + self.delegate.exit() + } + + fn exiting(&self) -> bool { + self.delegate.exiting() + } + + fn owned_display_handle(&self) -> RootOwnedDisplayHandle { + RootOwnedDisplayHandle { platform: OwnedDisplayHandle } + } + + fn as_any(&self) -> &dyn Any { + self + } + + #[cfg(feature = "rwh_06")] + fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle { + self + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for ActiveEventLoop { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + let raw = rwh_06::RawDisplayHandle::AppKit(rwh_06::AppKitDisplayHandle::new()); + unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) } + } +} + pub struct EventLoop { /// Store a reference to the application for convenience. /// @@ -174,7 +189,7 @@ pub struct EventLoop { /// keep it around here as well. delegate: Retained, - window_target: RootWindowTarget, + window_target: ActiveEventLoop, panic_info: Rc, } @@ -235,15 +250,12 @@ impl EventLoop { Ok(EventLoop { app, delegate: delegate.clone(), - window_target: RootWindowTarget { - p: ActiveEventLoop { delegate, mtm }, - _marker: PhantomData, - }, + window_target: ActiveEventLoop { delegate, mtm }, panic_info, }) } - pub fn window_target(&self) -> &RootWindowTarget { + pub fn window_target(&self) -> &dyn RootActiveEventLoop { &self.window_target } diff --git a/src/platform_impl/apple/uikit/app_state.rs b/src/platform_impl/apple/uikit/app_state.rs index 0f79962f..83db6efb 100644 --- a/src/platform_impl/apple/uikit/app_state.rs +++ b/src/platform_impl/apple/uikit/app_state.rs @@ -24,6 +24,7 @@ use objc2_foundation::{ use objc2_ui_kit::{UIApplication, UICoordinateSpace, UIView, UIWindow}; use super::window::WinitUIWindow; +use super::ActiveEventLoop; use crate::dpi::PhysicalSize; use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent}; use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow}; @@ -43,8 +44,8 @@ macro_rules! bug_assert { pub(crate) struct EventLoopHandler { #[allow(clippy::type_complexity)] - pub(crate) handler: Box, - pub(crate) event_loop: RootActiveEventLoop, + pub(crate) handler: Box, + pub(crate) event_loop: ActiveEventLoop, } impl fmt::Debug for EventLoopHandler { diff --git a/src/platform_impl/apple/uikit/event_loop.rs b/src/platform_impl/apple/uikit/event_loop.rs index 55f65abb..eafae5dc 100644 --- a/src/platform_impl/apple/uikit/event_loop.rs +++ b/src/platform_impl/apple/uikit/event_loop.rs @@ -1,6 +1,5 @@ -use std::collections::VecDeque; +use std::any::Any; use std::ffi::{c_char, c_int, c_void}; -use std::marker::PhantomData; use std::ptr::{self, NonNull}; use std::sync::atomic::{AtomicBool, Ordering as AtomicOrdering}; use std::sync::Arc; @@ -21,73 +20,95 @@ use super::app_delegate::AppDelegate; use super::app_state::{AppState, EventLoopHandler}; use super::{app_state, monitor, MonitorHandle}; use crate::application::ApplicationHandler; -use crate::error::{EventLoopError, ExternalError, NotSupportedError}; +use crate::error::{EventLoopError, ExternalError, NotSupportedError, OsError}; use crate::event::Event; -use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents}; -use crate::window::{CustomCursor, CustomCursorSource, Theme}; +use crate::event_loop::{ + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, +}; +use crate::monitor::MonitorHandle as RootMonitorHandle; +use crate::platform_impl::Window; +use crate::window::{CustomCursor, CustomCursorSource, Theme, Window as RootWindow}; #[derive(Debug)] -pub struct ActiveEventLoop { +pub(crate) struct ActiveEventLoop { pub(super) mtm: MainThreadMarker, } -impl ActiveEventLoop { - pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy::new(AppState::get_mut(self.mtm).proxy_wake_up()) +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 } } - pub fn create_custom_cursor( + fn create_window( + &self, + window_attributes: crate::window::WindowAttributes, + ) -> Result { + let window = Window::new(self, window_attributes)?; + Ok(RootWindow { window }) + } + + fn create_custom_cursor( &self, _source: CustomCursorSource, ) -> Result { Err(ExternalError::NotSupported(NotSupportedError::new())) } - pub fn available_monitors(&self) -> VecDeque { - monitor::uiscreens(self.mtm) + fn available_monitors(&self) -> Box> { + Box::new(monitor::uiscreens(self.mtm).into_iter().map(|inner| RootMonitorHandle { inner })) } - pub fn primary_monitor(&self) -> Option { + fn primary_monitor(&self) -> Option { #[allow(deprecated)] - Some(MonitorHandle::new(UIScreen::mainScreen(self.mtm))) + let monitor = MonitorHandle::new(UIScreen::mainScreen(self.mtm)); + Some(RootMonitorHandle { inner: monitor }) } - #[inline] - pub fn listen_device_events(&self, _allowed: DeviceEvents) {} + fn listen_device_events(&self, _allowed: DeviceEvents) {} - #[inline] - pub fn system_theme(&self) -> Option { - None - } - - #[cfg(feature = "rwh_06")] - #[inline] - pub fn raw_display_handle_rwh_06( - &self, - ) -> Result { - Ok(rwh_06::RawDisplayHandle::UiKit(rwh_06::UiKitDisplayHandle::new())) - } - - pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { + fn set_control_flow(&self, control_flow: ControlFlow) { AppState::get_mut(self.mtm).set_control_flow(control_flow) } - pub(crate) fn control_flow(&self) -> ControlFlow { + fn system_theme(&self) -> Option { + None + } + + fn control_flow(&self) -> ControlFlow { AppState::get_mut(self.mtm).control_flow() } - pub(crate) fn exit(&self) { + fn exit(&self) { // https://developer.apple.com/library/archive/qa/qa1561/_index.html // it is not possible to quit an iOS app gracefully and programmatically tracing::warn!("`ControlFlow::Exit` ignored on iOS"); } - pub(crate) fn exiting(&self) -> bool { + fn exiting(&self) -> bool { false } - pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle { - OwnedDisplayHandle + fn owned_display_handle(&self) -> RootOwnedDisplayHandle { + RootOwnedDisplayHandle { platform: OwnedDisplayHandle } + } + + fn as_any(&self) -> &dyn Any { + self + } + + #[cfg(feature = "rwh_06")] + fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle { + self + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for ActiveEventLoop { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + let raw = rwh_06::RawDisplayHandle::UiKit(rwh_06::UiKitDisplayHandle::new()); + unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) } } } @@ -107,7 +128,7 @@ impl OwnedDisplayHandle { fn map_user_event<'a, A: ApplicationHandler + 'a>( mut app: A, proxy_wake_up: Arc, -) -> impl FnMut(Event, &RootActiveEventLoop) + 'a { +) -> impl FnMut(Event, &dyn RootActiveEventLoop) + 'a { move |event, window_target| match event { Event::NewEvents(cause) => app.new_events(window_target, cause), Event::WindowEvent { window_id, event } => { @@ -132,7 +153,7 @@ fn map_user_event<'a, A: ApplicationHandler + 'a>( pub struct EventLoop { mtm: MainThreadMarker, - window_target: RootActiveEventLoop, + window_target: ActiveEventLoop, } #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -157,10 +178,7 @@ impl EventLoop { // this line sets up the main run loop before `UIApplicationMain` setup_control_flow_observers(); - Ok(EventLoop { - mtm, - window_target: RootActiveEventLoop { p: ActiveEventLoop { mtm }, _marker: PhantomData }, - }) + Ok(EventLoop { mtm, window_target: ActiveEventLoop { mtm } }) } pub fn run_app(self, app: A) -> ! { @@ -177,8 +195,8 @@ impl EventLoop { let handler = unsafe { std::mem::transmute::< - Box, - Box, + Box, + Box, >(Box::new(handler)) }; @@ -206,7 +224,7 @@ impl EventLoop { unreachable!() } - pub fn window_target(&self) -> &RootActiveEventLoop { + pub fn window_target(&self) -> &dyn RootActiveEventLoop { &self.window_target } } diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 9d1f14a4..3d51c77f 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -19,8 +19,8 @@ use self::x11::{X11Error, XConnection, XError, XNotSupported}; use crate::application::ApplicationHandler; pub(crate) use crate::cursor::OnlyCursorImageSource as PlatformCustomCursorSource; use crate::dpi::{PhysicalPosition, PhysicalSize, Position, Size}; -use crate::error::{EventLoopError, ExternalError, NotSupportedError, OsError as RootOsError}; -use crate::event_loop::{AsyncRequestSerial, ControlFlow, DeviceEvents}; +use crate::error::{EventLoopError, ExternalError, NotSupportedError}; +use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial}; use crate::icon::Icon; pub(crate) use crate::icon::RgbaIcon as PlatformIcon; use crate::keyboard::Key; @@ -31,8 +31,8 @@ pub(crate) use crate::platform_impl::Fullscreen; #[cfg(x11_platform)] use crate::utils::Lazy; use crate::window::{ - ActivationToken, Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, ImePurpose, - ResizeDirection, Theme, UserAttentionType, WindowAttributes, WindowButtons, WindowLevel, + ActivationToken, Cursor, CursorGrabMode, ImePurpose, ResizeDirection, Theme, UserAttentionType, + WindowButtons, WindowLevel, }; pub(crate) mod common; @@ -281,23 +281,6 @@ impl VideoModeHandle { } impl Window { - #[inline] - pub(crate) fn new( - window_target: &ActiveEventLoop, - attribs: WindowAttributes, - ) -> Result { - match *window_target { - #[cfg(wayland_platform)] - ActiveEventLoop::Wayland(ref window_target) => { - wayland::Window::new(window_target, attribs).map(Window::Wayland) - }, - #[cfg(x11_platform)] - ActiveEventLoop::X(ref window_target) => { - x11::Window::new(window_target, attribs).map(Window::X) - }, - } - } - pub(crate) fn maybe_queue_on_main(&self, f: impl FnOnce(&Self) + Send + 'static) { f(self) } @@ -789,7 +772,7 @@ impl EventLoop { x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_app_events(timeout, app)) } - pub fn window_target(&self) -> &crate::event_loop::ActiveEventLoop { + pub fn window_target(&self) -> &dyn ActiveEventLoop { x11_or_wayland!(match self; EventLoop(evlp) => evlp.window_target()) } } @@ -812,112 +795,6 @@ impl EventLoopProxy { } } -pub enum ActiveEventLoop { - #[cfg(wayland_platform)] - Wayland(wayland::ActiveEventLoop), - #[cfg(x11_platform)] - X(x11::ActiveEventLoop), -} - -impl ActiveEventLoop { - pub fn create_proxy(&self) -> EventLoopProxy { - x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.create_proxy(); as EventLoopProxy) - } - - #[inline] - pub fn is_wayland(&self) -> bool { - match *self { - #[cfg(wayland_platform)] - ActiveEventLoop::Wayland(_) => true, - #[cfg(x11_platform)] - _ => false, - } - } - - pub fn create_custom_cursor( - &self, - cursor: CustomCursorSource, - ) -> Result { - x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.create_custom_cursor(cursor)) - } - - #[inline] - pub fn available_monitors(&self) -> VecDeque { - match *self { - #[cfg(wayland_platform)] - ActiveEventLoop::Wayland(ref evlp) => { - evlp.available_monitors().map(MonitorHandle::Wayland).collect() - }, - #[cfg(x11_platform)] - ActiveEventLoop::X(ref evlp) => { - evlp.available_monitors().map(MonitorHandle::X).collect() - }, - } - } - - #[inline] - pub fn primary_monitor(&self) -> Option { - Some( - x11_or_wayland!(match self; ActiveEventLoop(evlp) => evlp.primary_monitor()?; as MonitorHandle), - ) - } - - #[inline] - pub fn listen_device_events(&self, allowed: DeviceEvents) { - x11_or_wayland!(match self; Self(evlp) => evlp.listen_device_events(allowed)) - } - - #[inline] - pub fn system_theme(&self) -> Option { - None - } - - #[cfg(feature = "rwh_06")] - #[inline] - pub fn raw_display_handle_rwh_06( - &self, - ) -> Result { - x11_or_wayland!(match self; Self(evlp) => evlp.raw_display_handle_rwh_06()) - } - - pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { - x11_or_wayland!(match self; Self(evlp) => evlp.set_control_flow(control_flow)) - } - - pub(crate) fn control_flow(&self) -> ControlFlow { - x11_or_wayland!(match self; Self(evlp) => evlp.control_flow()) - } - - fn clear_exit(&self) { - x11_or_wayland!(match self; Self(evlp) => evlp.clear_exit()) - } - - pub(crate) fn exit(&self) { - x11_or_wayland!(match self; Self(evlp) => evlp.exit()) - } - - pub(crate) fn exiting(&self) -> bool { - x11_or_wayland!(match self; Self(evlp) => evlp.exiting()) - } - - pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle { - match self { - #[cfg(x11_platform)] - Self::X(conn) => OwnedDisplayHandle::X(conn.x_connection().clone()), - #[cfg(wayland_platform)] - Self::Wayland(conn) => OwnedDisplayHandle::Wayland(conn.connection.clone()), - } - } - - fn set_exit_code(&self, code: i32) { - x11_or_wayland!(match self; Self(evlp) => evlp.set_exit_code(code)) - } - - fn exit_code(&self) -> Option { - x11_or_wayland!(match self; Self(evlp) => evlp.exit_code()) - } -} - #[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 8e4c2cbf..39a546e7 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -1,8 +1,8 @@ //! The event-loop routines. +use std::any::Any; use std::cell::{Cell, RefCell}; use std::io::Result as IOResult; -use std::marker::PhantomData; use std::mem; use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::sync::atomic::Ordering; @@ -21,10 +21,8 @@ use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent}; use crate::event_loop::{ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents}; use crate::platform::pump_events::PumpStatus; use crate::platform_impl::platform::min_timeout; -use crate::platform_impl::{ - ActiveEventLoop as PlatformActiveEventLoop, OsError, PlatformCustomCursor, -}; -use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource}; +use crate::platform_impl::{OsError, PlatformCustomCursor}; +use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, Theme}; mod proxy; pub mod sink; @@ -55,7 +53,7 @@ pub struct EventLoop { connection: Connection, /// Event loop window target. - window_target: RootActiveEventLoop, + active_event_loop: ActiveEventLoop, // XXX drop after everything else, just to be safe. /// Calloop's event loop. @@ -132,7 +130,7 @@ impl EventLoop { .map_err(|error| error.error); map_err!(result, WaylandError::Calloop)?; - let window_target = ActiveEventLoop { + let active_event_loop = ActiveEventLoop { connection: connection.clone(), wayland_dispatcher: wayland_dispatcher.clone(), event_loop_awakener, @@ -151,10 +149,7 @@ impl EventLoop { connection, wayland_dispatcher, event_loop, - window_target: RootActiveEventLoop { - p: PlatformActiveEventLoop::Wayland(window_target), - _marker: PhantomData, - }, + active_event_loop, }; Ok(event_loop) @@ -168,7 +163,7 @@ impl EventLoop { &mut self, mut app: A, ) -> Result<(), EventLoopError> { - self.window_target.p.clear_exit(); + self.active_event_loop.clear_exit(); let exit = loop { match self.pump_app_events(None, &mut app) { PumpStatus::Exit(0) => { @@ -212,7 +207,7 @@ impl EventLoop { if let Some(code) = self.exit_code() { self.loop_running = false; - app.exiting(&self.window_target); + app.exiting(&self.active_event_loop); PumpStatus::Exit(code) } else { @@ -300,17 +295,17 @@ impl EventLoop { let mut buffer_sink = std::mem::take(&mut self.buffer_sink); let mut window_ids = std::mem::take(&mut self.window_ids); - app.new_events(&self.window_target, cause); + app.new_events(&self.active_event_loop, cause); // NB: For consistency all platforms must call `can_create_surfaces` even though Wayland // applications don't themselves have a formal surface destroy/create lifecycle. if cause == StartCause::Init { - app.can_create_surfaces(&self.window_target); + app.can_create_surfaces(&self.active_event_loop); } // Indicate user wake up. if self.with_state(|state| mem::take(&mut state.proxy_wake_up)) { - app.proxy_wake_up(&self.window_target); + app.proxy_wake_up(&self.active_event_loop); } // Drain the pending compositor updates. @@ -337,7 +332,7 @@ impl EventLoop { inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), }; - app.window_event(&self.window_target, root_window_id, event); + app.window_event(&self.active_event_loop, root_window_id, event); let physical_size = *new_inner_size.lock().unwrap(); drop(new_inner_size); @@ -382,12 +377,12 @@ impl EventLoop { let window_id = crate::window::WindowId(window_id); let event = WindowEvent::Resized(physical_size); - app.window_event(&self.window_target, window_id, event); + app.window_event(&self.active_event_loop, window_id, event); } if compositor_update.close_window { let window_id = crate::window::WindowId(window_id); - app.window_event(&self.window_target, window_id, WindowEvent::CloseRequested); + app.window_event(&self.active_event_loop, window_id, WindowEvent::CloseRequested); } } @@ -398,10 +393,10 @@ impl EventLoop { for event in buffer_sink.drain() { match event { Event::WindowEvent { window_id, event } => { - app.window_event(&self.window_target, window_id, event) + app.window_event(&self.active_event_loop, window_id, event) }, Event::DeviceEvent { device_id, event } => { - app.device_event(&self.window_target, device_id, event) + app.device_event(&self.active_event_loop, device_id, event) }, _ => unreachable!("event which is neither device nor window event."), } @@ -414,10 +409,10 @@ impl EventLoop { for event in buffer_sink.drain() { match event { Event::WindowEvent { window_id, event } => { - app.window_event(&self.window_target, window_id, event) + app.window_event(&self.active_event_loop, window_id, event) }, Event::DeviceEvent { device_id, event } => { - app.device_event(&self.window_target, device_id, event) + app.device_event(&self.active_event_loop, device_id, event) }, _ => unreachable!("event which is neither device nor window event."), } @@ -457,7 +452,7 @@ impl EventLoop { if let Some(event) = event { let window_id = crate::window::WindowId(*window_id); - app.window_event(&self.window_target, window_id, event); + app.window_event(&self.active_event_loop, window_id, event); } } @@ -467,7 +462,7 @@ impl EventLoop { }); // This is always the last event we dispatch before poll again - app.about_to_wait(&self.window_target); + app.about_to_wait(&self.active_event_loop); // Update the window frames and schedule redraws. let mut wake_up = false; @@ -496,13 +491,7 @@ impl EventLoop { // If the user draws from the `AboutToWait` this is likely not required, however // we can't do much about it. if wake_up { - match &self.window_target.p { - PlatformActiveEventLoop::Wayland(window_target) => { - window_target.event_loop_awakener.ping(); - }, - #[cfg(x11_platform)] - PlatformActiveEventLoop::X(_) => unreachable!(), - } + self.active_event_loop.event_loop_awakener.ping(); } std::mem::swap(&mut self.compositor_updates, &mut compositor_updates); @@ -511,26 +500,17 @@ impl EventLoop { } #[inline] - pub fn window_target(&self) -> &RootActiveEventLoop { - &self.window_target + pub fn window_target(&self) -> &dyn RootActiveEventLoop { + &self.active_event_loop } fn with_state<'a, U: 'a, F: FnOnce(&'a mut WinitState) -> U>(&'a mut self, callback: F) -> U { - let state = match &mut self.window_target.p { - PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(), - #[cfg(x11_platform)] - _ => unreachable!(), - }; - + let state = self.active_event_loop.state.get_mut(); callback(state) } fn loop_dispatch>>(&mut self, timeout: D) -> IOResult<()> { - let state = match &mut self.window_target.p { - PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(), - #[cfg(feature = "x11")] - _ => unreachable!(), - }; + let state = &mut self.active_event_loop.state.get_mut(); self.event_loop.dispatch(timeout, state).map_err(|error| { tracing::error!("Error dispatching event loop: {}", error); @@ -539,11 +519,7 @@ impl EventLoop { } fn roundtrip(&mut self) -> Result { - let state = match &mut self.window_target.p { - PlatformActiveEventLoop::Wayland(window_target) => window_target.state.get_mut(), - #[cfg(feature = "x11")] - _ => unreachable!(), - }; + let state = &mut self.active_event_loop.state.get_mut(); let mut wayland_source = self.wayland_dispatcher.as_source_mut(); let event_queue = wayland_source.queue(); @@ -553,19 +529,19 @@ impl EventLoop { } fn control_flow(&self) -> ControlFlow { - self.window_target.p.control_flow() + self.active_event_loop.control_flow() } fn exiting(&self) -> bool { - self.window_target.p.exiting() + self.active_event_loop.exiting() } fn set_exit_code(&self, code: i32) { - self.window_target.p.set_exit_code(code) + self.active_event_loop.set_exit_code(code) } fn exit_code(&self) -> Option { - self.window_target.p.exit_code() + self.active_event_loop.exit_code() } } @@ -608,43 +584,35 @@ pub struct ActiveEventLoop { pub connection: Connection, } -impl ActiveEventLoop { - pub(crate) fn create_proxy(&self) -> EventLoopProxy { - self.event_loop_proxy.clone() +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(), + ), + } } - pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { + fn set_control_flow(&self, control_flow: ControlFlow) { self.control_flow.set(control_flow) } - pub(crate) fn control_flow(&self) -> ControlFlow { + fn control_flow(&self) -> ControlFlow { self.control_flow.get() } - pub(crate) fn exit(&self) { + fn exit(&self) { self.exit.set(Some(0)) } - pub(crate) fn clear_exit(&self) { - self.exit.set(None) - } - - pub(crate) fn exiting(&self) -> bool { + fn exiting(&self) -> bool { self.exit.get().is_some() } - pub(crate) fn set_exit_code(&self, code: i32) { - self.exit.set(Some(code)) - } - - pub(crate) fn exit_code(&self) -> Option { - self.exit.get() - } - #[inline] - pub fn listen_device_events(&self, _allowed: DeviceEvents) {} + fn listen_device_events(&self, _allowed: DeviceEvents) {} - pub(crate) fn create_custom_cursor( + fn create_custom_cursor( &self, cursor: CustomCursorSource, ) -> Result { @@ -653,17 +621,78 @@ impl ActiveEventLoop { }) } - #[cfg(feature = "rwh_06")] #[inline] - pub fn raw_display_handle_rwh_06( - &self, - ) -> Result { - use sctk::reexports::client::Proxy; + fn system_theme(&self) -> Option { + None + } - Ok(rwh_06::WaylandDisplayHandle::new({ - let ptr = self.connection.display().id().as_ptr(); - std::ptr::NonNull::new(ptr as *mut _).expect("wl_display should never be null") - }) - .into()) + fn create_window( + &self, + window_attributes: crate::window::WindowAttributes, + ) -> Result { + let window = crate::platform_impl::wayland::Window::new(self, window_attributes)?; + let window = crate::platform_impl::Window::Wayland(window); + Ok(crate::window::Window { window }) + } + + fn available_monitors(&self) -> Box> { + Box::new( + self.state + .borrow() + .output_state + .outputs() + .map(crate::platform_impl::wayland::output::MonitorHandle::new) + .map(crate::platform_impl::MonitorHandle::Wayland) + .map(|inner| crate::monitor::MonitorHandle { inner }), + ) + } + + fn primary_monitor(&self) -> Option { + // There's no primary monitor on Wayland. + None + } + + fn owned_display_handle(&self) -> crate::event_loop::OwnedDisplayHandle { + crate::event_loop::OwnedDisplayHandle { + platform: crate::platform_impl::OwnedDisplayHandle::Wayland(self.connection.clone()), + } + } + + #[inline(always)] + fn as_any(&self) -> &dyn Any { + self + } + + #[cfg(feature = "rwh_06")] + fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle { + self + } +} + +impl ActiveEventLoop { + fn clear_exit(&self) { + self.exit.set(None) + } + + fn set_exit_code(&self, code: i32) { + self.exit.set(Some(code)) + } + + fn exit_code(&self) -> Option { + self.exit.get() + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for ActiveEventLoop { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + use sctk::reexports::client::Proxy; + + let raw = rwh_06::WaylandDisplayHandle::new({ + let ptr = self.connection.display().id().as_ptr(); + std::ptr::NonNull::new(ptr as *mut _).expect("wl_display should never be null") + }); + + Ok(unsafe { rwh_06::DisplayHandle::borrow_raw(raw.into()) }) } } diff --git a/src/platform_impl/linux/wayland/output.rs b/src/platform_impl/linux/wayland/output.rs index 2095afdc..42537ced 100644 --- a/src/platform_impl/linux/wayland/output.rs +++ b/src/platform_impl/linux/wayland/output.rs @@ -2,23 +2,9 @@ use sctk::output::OutputData; use sctk::reexports::client::protocol::wl_output::WlOutput; use sctk::reexports::client::Proxy; -use super::event_loop::ActiveEventLoop; use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; use crate::platform_impl::platform::VideoModeHandle as PlatformVideoModeHandle; -impl ActiveEventLoop { - #[inline] - pub fn available_monitors(&self) -> impl Iterator { - self.state.borrow().output_state.outputs().map(MonitorHandle::new) - } - - #[inline] - pub fn primary_monitor(&self) -> Option { - // There's no primary monitor on Wayland. - None - } -} - #[derive(Clone, Debug)] pub struct MonitorHandle { pub(crate) proxy: WlOutput, diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 63f54db6..a80e540a 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -25,13 +25,11 @@ use crate::event::{ DeviceEvent, ElementState, Event, Ime, InnerSizeWriter, MouseButton, MouseScrollDelta, RawKeyEvent, Touch, TouchPhase, WindowEvent, }; -use crate::event_loop::ActiveEventLoop as RootAEL; use crate::keyboard::ModifiersState; use crate::platform_impl::common::xkb::{self, XkbState}; use crate::platform_impl::platform::common::xkb::Context; use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest}; use crate::platform_impl::platform::x11::ActiveEventLoop; -use crate::platform_impl::platform::ActiveEventLoop as PlatformActiveEventLoop; use crate::platform_impl::x11::atoms::*; use crate::platform_impl::x11::util::cookie::GenericEventCookie; use crate::platform_impl::x11::{ @@ -53,7 +51,7 @@ pub struct EventProcessor { pub devices: RefCell>, pub xi2ext: ExtensionInformation, pub xkbext: ExtensionInformation, - pub target: RootAEL, + pub target: ActiveEventLoop, pub xkb_context: Context, // Number of touch events currently in progress pub num_touch: u32, @@ -75,18 +73,17 @@ pub struct EventProcessor { impl EventProcessor { pub(crate) fn process_event(&mut self, xev: &mut XEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { self.process_xevent(xev, &mut callback); - let window_target = Self::window_target_mut(&mut self.target); - // Handle IME requests. while let Ok(request) = self.ime_receiver.try_recv() { - let ime = match window_target.ime.as_mut() { + let ime = match self.target.ime.as_mut() { Some(ime) => ime, None => continue, }; + let ime = ime.get_mut(); match request { ImeRequest::Position(window_id, x, y) => { @@ -131,9 +128,8 @@ impl EventProcessor { /// along with an extra copy of the KeyRelease events. This also prevents backspace and /// arrow keys from being detected twice. fn filter_event(&mut self, xev: &mut XEvent) -> bool { - let wt = Self::window_target(&self.target); unsafe { - (wt.xconn.xlib.XFilterEvent)(xev, { + (self.target.xconn.xlib.XFilterEvent)(xev, { let xev: &XAnyEvent = xev.as_ref(); xev.window }) == xlib::True @@ -142,7 +138,7 @@ impl EventProcessor { fn process_xevent(&mut self, xev: &mut XEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { let event_type = xev.get_type(); @@ -184,9 +180,8 @@ impl EventProcessor { self.xinput_key_input(xev.as_mut(), state, &mut callback); }, xlib::GenericEvent => { - let wt = Self::window_target(&self.target); let xev: GenericEventCookie = - match GenericEventCookie::from_event(wt.xconn.clone(), *xev) { + match GenericEventCookie::from_event(self.target.xconn.clone(), *xev) { Some(xev) if xev.extension() == self.xi2ext.major_opcode => xev, _ => return, }; @@ -298,14 +293,10 @@ impl EventProcessor { } pub fn poll(&self) -> bool { - let window_target = Self::window_target(&self.target); - let result = unsafe { (window_target.xconn.xlib.XPending)(window_target.xconn.display) }; - - result != 0 + unsafe { (self.target.xconn.xlib.XPending)(self.target.xconn.display) != 0 } } pub unsafe fn poll_one_event(&mut self, event_ptr: *mut XEvent) -> bool { - let window_target = Self::window_target(&self.target); // This function is used to poll and remove a single event // from the Xlib event queue in a non-blocking, atomic way. // XCheckIfEvent is non-blocking and removes events from queue. @@ -321,22 +312,19 @@ impl EventProcessor { 1 } - let result = unsafe { - (window_target.xconn.xlib.XCheckIfEvent)( - window_target.xconn.display, + unsafe { + (self.target.xconn.xlib.XCheckIfEvent)( + self.target.xconn.display, event_ptr, Some(predicate), std::ptr::null_mut(), - ) - }; - - result != 0 + ) != 0 + } } pub fn init_device(&self, device: xinput::DeviceId) { - let window_target = Self::window_target(&self.target); let mut devices = self.devices.borrow_mut(); - if let Some(info) = DeviceInfo::get(&window_target.xconn, device as _) { + if let Some(info) = DeviceInfo::get(&self.target.xconn, device as _) { for info in info.iter() { devices.insert(DeviceId(info.deviceid as _), Device::new(info)); } @@ -349,8 +337,8 @@ impl EventProcessor { { let mut deleted = false; let window_id = WindowId(window_id as _); - let window_target = Self::window_target(&self.target); - let result = window_target + let result = self + .target .windows .borrow() .get(&window_id) @@ -363,53 +351,33 @@ impl EventProcessor { if deleted { // Garbage collection - window_target.windows.borrow_mut().remove(&window_id); + self.target.windows.borrow_mut().remove(&window_id); } result } - // NOTE: we avoid `self` to not borrow the entire `self` as not mut. - /// Get the platform window target. - pub fn window_target(window_target: &RootAEL) -> &ActiveEventLoop { - match &window_target.p { - PlatformActiveEventLoop::X(target) => target, - #[cfg(wayland_platform)] - _ => unreachable!(), - } - } - - /// Get the platform window target. - pub fn window_target_mut(window_target: &mut RootAEL) -> &mut ActiveEventLoop { - match &mut window_target.p { - PlatformActiveEventLoop::X(target) => target, - #[cfg(wayland_platform)] - _ => unreachable!(), - } - } - fn client_message(&mut self, xev: &XClientMessageEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - let atoms = wt.xconn.atoms(); + let atoms = self.target.xconn.atoms(); let window = xev.window as xproto::Window; let window_id = mkwid(window); - if xev.data.get_long(0) as xproto::Atom == wt.wm_delete_window { + if xev.data.get_long(0) as xproto::Atom == self.target.wm_delete_window { let event = Event::WindowEvent { window_id, event: WindowEvent::CloseRequested }; callback(&self.target, event); return; } - if xev.data.get_long(0) as xproto::Atom == wt.net_wm_ping { + if xev.data.get_long(0) as xproto::Atom == self.target.net_wm_ping { let client_msg = xproto::ClientMessageEvent { response_type: xproto::CLIENT_MESSAGE_EVENT, format: xev.format as _, sequence: xev.serial as _, - window: wt.root, + window: self.target.root, type_: xev.message_type as _, data: xproto::ClientMessageData::from({ let [a, b, c, d, e]: [c_long; 5] = xev.data.as_longs().try_into().unwrap(); @@ -417,11 +385,12 @@ impl EventProcessor { }), }; - wt.xconn + self.target + .xconn .xcb_connection() .send_event( false, - wt.root, + self.target.root, xproto::EventMask::SUBSTRUCTURE_NOTIFY | xproto::EventMask::SUBSTRUCTURE_REDIRECT, client_msg.serialize(), @@ -430,7 +399,7 @@ impl EventProcessor { return; } - if xev.data.get_long(0) as xproto::Atom == wt.net_wm_sync_request { + if xev.data.get_long(0) as xproto::Atom == self.target.net_wm_sync_request { let sync_counter_id = match self .with_window(xev.window as xproto::Window, |window| window.sync_counter_id()) { @@ -448,10 +417,12 @@ impl EventProcessor { bytemuck::cast::((xev.data.get_long(3) & 0xffffffff) as u32), ); - wt.xconn + self.target + .xconn .xcb_connection() .sync_set_counter(sync_counter_id, Int64 { lo, hi }) .expect_then_ignore_error("Failed to set XSync counter."); + return; } @@ -526,7 +497,7 @@ impl EventProcessor { }; // Log this timestamp. - wt.xconn.set_timestamp(time); + self.target.xconn.set_timestamp(time); // This results in the `SelectionNotify` event below unsafe { @@ -580,16 +551,15 @@ impl EventProcessor { fn selection_notify(&mut self, xev: &XSelectionEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - let atoms = wt.xconn.atoms(); + let atoms = self.target.xconn.atoms(); let window = xev.requestor as xproto::Window; let window_id = mkwid(window); // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); if xev.property != atoms[XdndSelection] as c_ulong { return; @@ -614,10 +584,8 @@ impl EventProcessor { fn configure_notify(&self, xev: &XConfigureEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - let xwindow = xev.window as xproto::Window; let window_id = mkwid(xwindow); @@ -672,7 +640,8 @@ impl EventProcessor { // We need to convert client area position to window position. let frame_extents = shared_state_lock.frame_extents.as_ref().cloned().unwrap_or_else(|| { - let frame_extents = wt.xconn.get_frame_extents_heuristic(xwindow, wt.root); + let frame_extents = + self.target.xconn.get_frame_extents_heuristic(xwindow, self.target.root); shared_state_lock.frame_extents = Some(frame_extents.clone()); frame_extents }); @@ -703,7 +672,8 @@ impl EventProcessor { let last_scale_factor = shared_state_lock.last_monitor.scale_factor; let new_scale_factor = { let window_rect = util::AaRect::new(new_outer_position, new_inner_size); - let monitor = wt + let monitor = self + .target .xconn .get_monitor_for_window(Some(window_rect)) .expect("Failed to find monitor for window"); @@ -798,9 +768,7 @@ impl EventProcessor { /// really have much impact, since on the WMs affected (xmonad, dwm, etc.) the only /// effect is that we waste some time trying to query unsupported properties. fn reparent_notify(&self, xev: &XReparentEvent) { - let wt = Self::window_target(&self.target); - - wt.xconn.update_cached_wm_info(wt.root); + self.target.xconn.update_cached_wm_info(self.target.root); self.with_window(xev.window as xproto::Window, |window| { window.invalidate_cached_frame_extents(); @@ -809,7 +777,7 @@ impl EventProcessor { fn map_notify(&self, xev: &XMapEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { let window = xev.window as xproto::Window; let window_id = mkwid(window); @@ -827,20 +795,18 @@ impl EventProcessor { fn destroy_notify(&self, xev: &XDestroyWindowEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - let window = xev.window as xproto::Window; let window_id = mkwid(window); // In the event that the window's been destroyed without being dropped first, we // cleanup again here. - wt.windows.borrow_mut().remove(&WindowId(window as _)); + self.target.windows.borrow_mut().remove(&WindowId(window as _)); // Since all XIM stuff needs to happen from the same thread, we destroy the input // context here instead of when dropping the window. - if let Some(ime) = wt.ime.as_ref() { + if let Some(ime) = self.target.ime.as_ref() { ime.borrow_mut() .remove_context(window as XWindow) .expect("Failed to destroy input context"); @@ -851,10 +817,9 @@ impl EventProcessor { fn property_notify(&mut self, xev: &XPropertyEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - let atoms = wt.x_connection().atoms(); + let atoms = self.target.x_connection().atoms(); let atom = xev.atom as xproto::Atom; if atom == xproto::Atom::from(xproto::AtomEnum::RESOURCE_MANAGER) @@ -866,7 +831,7 @@ impl EventProcessor { fn visibility_notify(&self, xev: &XVisibilityEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { let xwindow = xev.window as xproto::Window; @@ -883,7 +848,7 @@ impl EventProcessor { fn expose(&self, xev: &XExposeEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { // Multiple Expose events may be received for subareas of a window. // We issue `RedrawRequested` only for the last event of such a series. @@ -899,12 +864,10 @@ impl EventProcessor { fn xinput_key_input(&mut self, xev: &mut XKeyEvent, state: ElementState, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); let window = match self.active_window { Some(window) => window, @@ -989,12 +952,10 @@ impl EventProcessor { return; } - let wt = Self::window_target(&self.target); - if let Some(ic) = - wt.ime.as_ref().and_then(|ime| ime.borrow().get_context(window as XWindow)) + self.target.ime.as_ref().and_then(|ime| ime.borrow().get_context(window as XWindow)) { - let written = wt.xconn.lookup_utf8(ic, xev); + let written = self.target.xconn.lookup_utf8(ic, xev); if !written.is_empty() { let event = Event::WindowEvent { window_id, @@ -1017,15 +978,14 @@ impl EventProcessor { state: u16, mut callback: F, ) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { let keymap = match self.xkb_context.keymap_mut() { Some(keymap) => keymap, None => return, }; - let wt = Self::window_target(&self.target); - let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection(); + let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection(); // Use synthetic state since we're replaying the modifier. The user modifier state // will be restored later. @@ -1046,14 +1006,13 @@ impl EventProcessor { fn xinput2_button_input(&self, event: &XIDeviceEvent, state: ElementState, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); let window_id = mkwid(event.event as xproto::Window); let device_id = mkdid(event.deviceid as xinput::DeviceId); // Set the timestamp. - wt.xconn.set_timestamp(event.time as xproto::Timestamp); + self.target.xconn.set_timestamp(event.time as xproto::Timestamp); // Deliver multi-touch events instead of emulated mouse events. if (event.flags & xinput2::XIPointerEmulated) != 0 { @@ -1099,12 +1058,10 @@ impl EventProcessor { fn xinput2_mouse_motion(&self, event: &XIDeviceEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - // Set the timestamp. - wt.xconn.set_timestamp(event.time as xproto::Timestamp); + self.target.xconn.set_timestamp(event.time as xproto::Timestamp); let device_id = mkdid(event.deviceid as xinput::DeviceId); let window = event.event as xproto::Window; @@ -1174,18 +1131,16 @@ impl EventProcessor { fn xinput2_mouse_enter(&self, event: &XIEnterEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - // Set the timestamp. - wt.xconn.set_timestamp(event.time as xproto::Timestamp); + self.target.xconn.set_timestamp(event.time as xproto::Timestamp); let window = event.event as xproto::Window; let window_id = mkwid(window); let device_id = mkdid(event.deviceid as xinput::DeviceId); - if let Some(all_info) = DeviceInfo::get(&wt.xconn, super::ALL_DEVICES.into()) { + if let Some(all_info) = DeviceInfo::get(&self.target.xconn, super::ALL_DEVICES.into()) { let mut devices = self.devices.borrow_mut(); for device_info in all_info.iter() { // The second expression is need for resetting to work correctly on i3, and @@ -1219,13 +1174,12 @@ impl EventProcessor { fn xinput2_mouse_left(&self, event: &XILeaveEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); let window = event.event as xproto::Window; // Set the timestamp. - wt.xconn.set_timestamp(event.time as xproto::Timestamp); + self.target.xconn.set_timestamp(event.time as xproto::Timestamp); // Leave, FocusIn, and FocusOut can be received by a window that's already // been destroyed, which the user presumably doesn't want to deal with. @@ -1242,15 +1196,14 @@ impl EventProcessor { fn xinput2_focused(&mut self, xev: &XIFocusInEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); let window = xev.event as xproto::Window; // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); - if let Some(ime) = wt.ime.as_ref() { + if let Some(ime) = self.target.ime.as_ref() { ime.borrow_mut().focus(xev.event).expect("Failed to focus input context"); } @@ -1260,7 +1213,7 @@ impl EventProcessor { self.active_window = Some(window); - wt.update_listen_device_events(true); + self.target.update_listen_device_events(true); let window_id = mkwid(window); let position = PhysicalPosition::new(xev.event_x, xev.event_y); @@ -1301,26 +1254,25 @@ impl EventProcessor { fn xinput2_unfocused(&mut self, xev: &XIFocusOutEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); let window = xev.event as xproto::Window; // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); if !self.window_exists(window) { return; } - if let Some(ime) = wt.ime.as_ref() { + if let Some(ime) = self.target.ime.as_ref() { ime.borrow_mut().unfocus(xev.event).expect("Failed to unfocus input context"); } if self.active_window.take() == Some(window) { let window_id = mkwid(window); - wt.update_listen_device_events(false); + self.target.update_listen_device_events(false); // Clear the modifiers when unfocusing the window. if let Some(xkb_state) = self.xkb_context.state_mut() { @@ -1353,12 +1305,10 @@ impl EventProcessor { fn xinput2_touch(&mut self, xev: &XIDeviceEvent, phase: TouchPhase, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); let window = xev.event as xproto::Window; if self.window_exists(window) { @@ -1395,12 +1345,10 @@ impl EventProcessor { fn xinput2_raw_button_input(&self, xev: &XIRawEvent, state: ElementState, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); if xev.flags & xinput2::XIPointerEmulated == 0 { let event = Event::DeviceEvent { @@ -1413,12 +1361,10 @@ impl EventProcessor { fn xinput2_raw_mouse_motion(&self, xev: &XIRawEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); let did = mkdid(xev.deviceid as xinput::DeviceId); @@ -1467,12 +1413,10 @@ impl EventProcessor { fn xinput2_raw_key_input(&mut self, xev: &XIRawEvent, state: ElementState, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); let device_id = mkdid(xev.sourceid as xinput::DeviceId); let keycode = xev.detail as u32; @@ -1488,10 +1432,8 @@ impl EventProcessor { } fn xinput2_hierarchy_changed(&mut self, xev: &XIHierarchyEvent) { - let wt = Self::window_target(&self.target); - // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); let infos = unsafe { slice::from_raw_parts(xev.info, xev.num_info as usize) }; for info in infos { if 0 != info.flags & (xinput2::XISlaveAdded | xinput2::XIMasterAdded) { @@ -1505,15 +1447,14 @@ impl EventProcessor { fn xkb_event(&mut self, xev: &XkbAnyEvent, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); match xev.xkb_type { xlib::XkbNewKeyboardNotify => { let xev = unsafe { &*(xev as *const _ as *const xlib::XkbNewKeyboardNotifyEvent) }; // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); let keycodes_changed_flag = 0x1; let geometry_changed_flag = 0x1 << 1; @@ -1524,9 +1465,9 @@ impl EventProcessor { if xev.device == self.xkb_context.core_keyboard_id && (keycodes_changed || geometry_changed) { - let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection(); + let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection(); self.xkb_context.set_keymap_from_x11(xcb); - self.xmodmap.reload_from_x_connection(&wt.xconn); + self.xmodmap.reload_from_x_connection(&self.target.xconn); let window_id = match self.active_window.map(super::mkwid) { Some(window_id) => window_id, @@ -1540,9 +1481,9 @@ impl EventProcessor { } }, xlib::XkbMapNotify => { - let xcb = wt.xconn.xcb_connection().get_raw_xcb_connection(); + let xcb = self.target.xconn.xcb_connection().get_raw_xcb_connection(); self.xkb_context.set_keymap_from_x11(xcb); - self.xmodmap.reload_from_x_connection(&wt.xconn); + self.xmodmap.reload_from_x_connection(&self.target.xconn); let window_id = match self.active_window.map(super::mkwid) { Some(window_id) => window_id, None => return, @@ -1557,7 +1498,7 @@ impl EventProcessor { let xev = unsafe { &*(xev as *const _ as *const xlib::XkbStateNotifyEvent) }; // Set the timestamp. - wt.xconn.set_timestamp(xev.time as xproto::Timestamp); + self.target.xconn.set_timestamp(xev.time as xproto::Timestamp); if let Some(state) = self.xkb_context.state_mut() { state.update_modifiers( @@ -1589,7 +1530,7 @@ impl EventProcessor { force: bool, mut callback: F, ) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { if let Some(state) = self.xkb_context.state_mut() { state.update_modifiers( @@ -1615,10 +1556,8 @@ impl EventProcessor { fn update_mods_from_query(&mut self, window_id: crate::window::WindowId, mut callback: F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - let xkb_state = match self.xkb_context.state_mut() { Some(xkb_state) => xkb_state, None => return, @@ -1626,8 +1565,11 @@ impl EventProcessor { unsafe { let mut state: XkbStateRec = std::mem::zeroed(); - if (wt.xconn.xlib.XkbGetState)(wt.xconn.display, XkbId::USE_CORE_KBD.into(), &mut state) - == xlib::True + if (self.target.xconn.xlib.XkbGetState)( + self.target.xconn.display, + XkbId::USE_CORE_KBD.into(), + &mut state, + ) == xlib::True { xkb_state.update_modifiers( state.base_mods as u32, @@ -1650,7 +1592,7 @@ impl EventProcessor { state: u16, mut callback: F, ) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { let xkb_mask = self.xkb_mod_mask_from_core(state); let xkb_state = match self.xkb_context.state_mut() { @@ -1723,7 +1665,7 @@ impl EventProcessor { /// /// The event won't be sent when the `modifiers` match the previously `sent` modifiers value, /// unless `force` is passed. The `force` should be passed when the active window changes. - fn send_modifiers( + fn send_modifiers( &self, window_id: crate::window::WindowId, modifiers: ModifiersState, @@ -1742,19 +1684,18 @@ impl EventProcessor { } fn handle_pressed_keys( - target: &RootAEL, + target: &ActiveEventLoop, window_id: crate::window::WindowId, state: ElementState, xkb_context: &mut Context, callback: &mut F, ) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD); // Update modifiers state and emit key events based on which keys are currently pressed. - let window_target = Self::window_target(target); - let xcb = window_target.xconn.xcb_connection().get_raw_xcb_connection(); + let xcb = target.xconn.xcb_connection().get_raw_xcb_connection(); let keymap = match xkb_context.keymap_mut() { Some(keymap) => keymap, @@ -1771,9 +1712,7 @@ impl EventProcessor { None => return, }; - for keycode in - window_target.xconn.query_keymap().into_iter().filter(|k| *k >= KEYCODE_OFFSET) - { + for keycode in target.xconn.query_keymap().into_iter().filter(|k| *k >= KEYCODE_OFFSET) { let event = key_processor.process_key_event(keycode as u32, state, false); let event = Event::WindowEvent { window_id, @@ -1785,21 +1724,20 @@ impl EventProcessor { fn process_dpi_change(&self, callback: &mut F) where - F: FnMut(&RootAEL, Event), + F: FnMut(&ActiveEventLoop, Event), { - let wt = Self::window_target(&self.target); - wt.xconn.reload_database().expect("failed to reload Xft database"); + self.target.xconn.reload_database().expect("failed to reload Xft database"); // In the future, it would be quite easy to emit monitor hotplug events. let prev_list = { - let prev_list = wt.xconn.invalidate_cached_monitor_list(); + let prev_list = self.target.xconn.invalidate_cached_monitor_list(); match prev_list { Some(prev_list) => prev_list, None => return, } }; - let new_list = wt.xconn.available_monitors().expect("Failed to get monitor list"); + let new_list = self.target.xconn.available_monitors().expect("Failed to get monitor list"); for new_monitor in new_list { // Previous list may be empty, in case of disconnecting and // reconnecting the only one monitor. We still need to emit events in @@ -1809,7 +1747,7 @@ impl EventProcessor { .find(|prev_monitor| prev_monitor.name == new_monitor.name) .map(|prev_monitor| prev_monitor.scale_factor); if Some(new_monitor.scale_factor) != maybe_prev_scale_factor { - for window in wt.windows.borrow().iter().filter_map(|(_, w)| w.upgrade()) { + for window in self.target.windows.borrow().iter().filter_map(|(_, w)| w.upgrade()) { window.refresh_dpi_for_monitor(&new_monitor, maybe_prev_scale_factor, |event| { callback(&self.target, event); }) diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index efbf4fa1..e669d155 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -1,7 +1,7 @@ +use std::any::Any; use std::cell::{Cell, RefCell}; use std::collections::{HashMap, HashSet, VecDeque}; use std::ffi::CStr; -use std::marker::PhantomData; use std::mem::MaybeUninit; use std::ops::Deref; use std::os::raw::*; @@ -27,14 +27,17 @@ use x11rb::xcb_ffi::ReplyOrIdError; use crate::application::ApplicationHandler; use crate::error::{EventLoopError, ExternalError, OsError as RootOsError}; use crate::event::{Event, StartCause, WindowEvent}; -use crate::event_loop::{ActiveEventLoop as RootAEL, ControlFlow, DeviceEvents}; +use crate::event_loop::{ + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + OwnedDisplayHandle as RootOwnedDisplayHandle, +}; use crate::platform::pump_events::PumpStatus; use crate::platform_impl::common::xkb::Context; use crate::platform_impl::platform::{min_timeout, WindowId}; -use crate::platform_impl::{ - ActiveEventLoop as PlatformActiveEventLoop, OsError, PlatformCustomCursor, +use crate::platform_impl::{OsError, OwnedDisplayHandle, PlatformCustomCursor}; +use crate::window::{ + CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowAttributes, }; -use crate::window::{CustomCursor as RootCustomCursor, CustomCursorSource, WindowAttributes}; mod activation; mod atoms; @@ -310,11 +313,8 @@ impl EventLoop { // Set initial device event filter. window_target.update_listen_device_events(true); - let root_window_target = - RootAEL { p: PlatformActiveEventLoop::X(window_target), _marker: PhantomData }; - let event_processor = EventProcessor { - target: root_window_target, + target: window_target, dnd, devices: Default::default(), randr_event_offset, @@ -335,9 +335,9 @@ impl EventLoop { // Register for device hotplug events // (The request buffer is flushed during `init_device`) - let xconn = &EventProcessor::window_target(&event_processor.target).xconn; - - xconn + event_processor + .target + .xconn .select_xinput_events( root, ALL_DEVICES, @@ -345,7 +345,9 @@ impl EventLoop { ) .expect_then_ignore_error("Failed to register for XInput2 device hotplug events"); - xconn + event_processor + .target + .xconn .select_xkb_events( 0x100, // Use the "core keyboard device" xkb::EventType::NEW_KEYBOARD_NOTIFY @@ -366,7 +368,7 @@ impl EventLoop { } } - pub(crate) fn window_target(&self) -> &RootAEL { + pub(crate) fn window_target(&self) -> &dyn RootActiveEventLoop { &self.event_processor.target } @@ -378,7 +380,7 @@ impl EventLoop { &mut self, mut app: A, ) -> Result<(), EventLoopError> { - self.event_processor.target.p.clear_exit(); + self.event_processor.target.clear_exit(); let exit = loop { match self.pump_app_events(None, &mut app) { PumpStatus::Exit(0) => { @@ -397,8 +399,7 @@ impl EventLoop { // `run_on_demand` calls but if they have only just dropped their // windows we need to make sure those last requests are sent to the // X Server. - let wt = EventProcessor::window_target(&self.event_processor.target); - wt.x_connection().sync_with_server().map_err(|x_err| { + self.event_processor.target.x_connection().sync_with_server().map_err(|x_err| { EventLoopError::Os(os_error!(OsError::XError(Arc::new(X11Error::Xlib(x_err))))) })?; @@ -576,7 +577,6 @@ impl EventLoop { event: WindowEvent::RedrawRequested, } = event { - let window_target = EventProcessor::window_target(window_target); window_target.redraw_sender.send(wid); } else { match event { @@ -594,21 +594,19 @@ impl EventLoop { } fn control_flow(&self) -> ControlFlow { - let window_target = EventProcessor::window_target(&self.event_processor.target); - window_target.control_flow() + self.event_processor.target.control_flow() } fn exiting(&self) -> bool { - let window_target = EventProcessor::window_target(&self.event_processor.target); - window_target.exiting() + self.event_processor.target.exiting() } fn set_exit_code(&self, code: i32) { - self.window_target().p.set_exit_code(code); + self.event_processor.target.set_exit_code(code); } fn exit_code(&self) -> Option { - self.window_target().p.exit_code() + self.event_processor.target.exit_code() } } @@ -625,37 +623,12 @@ impl AsRawFd for EventLoop { } impl ActiveEventLoop { - pub fn create_proxy(&self) -> EventLoopProxy { - self.event_loop_proxy.clone() - } - /// Returns the `XConnection` of this events loop. #[inline] pub(crate) fn x_connection(&self) -> &Arc { &self.xconn } - pub fn available_monitors(&self) -> impl Iterator { - self.xconn.available_monitors().into_iter().flatten() - } - - pub fn primary_monitor(&self) -> Option { - self.xconn.primary_monitor().ok() - } - - pub(crate) fn create_custom_cursor( - &self, - cursor: CustomCursorSource, - ) -> Result { - Ok(RootCustomCursor { - inner: PlatformCustomCursor::X(CustomCursor::new(self, cursor.inner)?), - }) - } - - pub fn listen_device_events(&self, allowed: DeviceEvents) { - self.device_events.set(allowed); - } - /// Update the device event based on window focus. pub fn update_listen_device_events(&self, focus: bool) { let device_events = self.device_events.get() == DeviceEvents::Always @@ -690,26 +663,10 @@ impl ActiveEventLoop { Ok(display_handle.into()) } - pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { - self.control_flow.set(control_flow) - } - - pub(crate) fn control_flow(&self) -> ControlFlow { - self.control_flow.get() - } - - pub(crate) fn exit(&self) { - self.exit.set(Some(0)) - } - pub(crate) fn clear_exit(&self) { self.exit.set(None) } - pub(crate) fn exiting(&self) -> bool { - self.exit.get().is_some() - } - pub(crate) fn set_exit_code(&self, code: i32) { self.exit.set(Some(code)) } @@ -719,6 +676,99 @@ 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_window( + &self, + window_attributes: WindowAttributes, + ) -> Result { + let window = crate::platform_impl::x11::Window::new(self, window_attributes)?; + let window = crate::platform_impl::Window::X(window); + Ok(crate::window::Window { window }) + } + + fn create_custom_cursor( + &self, + custom_cursor: CustomCursorSource, + ) -> Result { + Ok(RootCustomCursor { + inner: PlatformCustomCursor::X(CustomCursor::new(self, custom_cursor.inner)?), + }) + } + + fn available_monitors(&self) -> Box> { + Box::new( + self.xconn + .available_monitors() + .into_iter() + .flatten() + .map(crate::platform_impl::MonitorHandle::X) + .map(|inner| crate::monitor::MonitorHandle { inner }), + ) + } + + fn primary_monitor(&self) -> Option { + self.xconn + .primary_monitor() + .ok() + .map(crate::platform_impl::MonitorHandle::X) + .map(|inner| crate::monitor::MonitorHandle { inner }) + } + + fn system_theme(&self) -> Option { + None + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.device_events.set(allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.control_flow.set(control_flow) + } + + fn control_flow(&self) -> ControlFlow { + self.control_flow.get() + } + + fn exit(&self) { + self.exit.set(Some(0)) + } + + fn exiting(&self) -> bool { + self.exit.get().is_some() + } + + fn owned_display_handle(&self) -> RootOwnedDisplayHandle { + let handle = OwnedDisplayHandle::X(self.x_connection().clone()); + RootOwnedDisplayHandle { platform: handle } + } + + fn as_any(&self) -> &dyn Any { + self + } + + #[cfg(feature = "rwh_06")] + fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle { + self + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for ActiveEventLoop { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + let raw = self.raw_display_handle_rwh_06()?; + unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) } + } +} + impl EventLoopProxy { pub fn wake_up(&self) { self.ping.ping(); diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index 67ab7444..f75f5687 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -1,6 +1,6 @@ +use std::any::Any; use std::cell::Cell; use std::collections::VecDeque; -use std::marker::PhantomData; use std::sync::{mpsc, Arc, Mutex}; use std::time::Instant; use std::{mem, slice}; @@ -19,7 +19,7 @@ use super::{ use crate::application::ApplicationHandler; use crate::error::{EventLoopError, ExternalError, NotSupportedError}; use crate::event::{self, Ime, Modifiers, StartCause}; -use crate::event_loop::{self, ControlFlow, DeviceEvents}; +use crate::event_loop::{self, ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents}; use crate::keyboard::{ Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NamedKey, NativeKey, NativeKeyCode, PhysicalKey, @@ -273,7 +273,7 @@ impl EventState { pub struct EventLoop { windows: Vec<(Arc, EventState)>, - window_target: event_loop::ActiveEventLoop, + window_target: ActiveEventLoop, user_events_receiver: mpsc::Receiver<()>, } @@ -306,18 +306,15 @@ impl EventLoop { Ok(Self { windows: Vec::new(), - window_target: event_loop::ActiveEventLoop { - p: ActiveEventLoop { - control_flow: Cell::new(ControlFlow::default()), - exit: Cell::new(false), - creates: Mutex::new(VecDeque::new()), - redraws: Arc::new(Mutex::new(VecDeque::new())), - destroys: Arc::new(Mutex::new(VecDeque::new())), - event_socket, - wake_socket, - user_events_sender, - }, - _marker: PhantomData, + window_target: ActiveEventLoop { + control_flow: Cell::new(ControlFlow::default()), + exit: Cell::new(false), + creates: Mutex::new(VecDeque::new()), + redraws: Arc::new(Mutex::new(VecDeque::new())), + destroys: Arc::new(Mutex::new(VecDeque::new())), + event_socket, + wake_socket, + user_events_sender, }, user_events_receiver, }) @@ -327,7 +324,7 @@ impl EventLoop { window_id: WindowId, event_option: EventOption, event_state: &mut EventState, - window_target: &event_loop::ActiveEventLoop, + window_target: &ActiveEventLoop, app: &mut A, ) { match event_option { @@ -511,7 +508,7 @@ impl EventLoop { // Handle window creates. while let Some(window) = { - let mut creates = self.window_target.p.creates.lock().unwrap(); + let mut creates = self.window_target.creates.lock().unwrap(); creates.pop_front() } { let window_id = WindowId { fd: window.fd as u64 }; @@ -535,7 +532,7 @@ impl EventLoop { // Handle window destroys. while let Some(destroy_id) = { - let mut destroys = self.window_target.p.destroys.lock().unwrap(); + let mut destroys = self.window_target.destroys.lock().unwrap(); destroys.pop_front() } { let window_id = RootWindowId(destroy_id); @@ -584,7 +581,7 @@ impl EventLoop { .expect("failed to acknowledge resize"); // Require redraw after resize. - let mut redraws = self.window_target.p.redraws.lock().unwrap(); + let mut redraws = self.window_target.redraws.lock().unwrap(); if !redraws.contains(&window_id) { redraws.push_back(window_id); } @@ -600,7 +597,7 @@ impl EventLoop { // To avoid deadlocks the redraws lock is not held during event processing. while let Some(window_id) = { - let mut redraws = self.window_target.p.redraws.lock().unwrap(); + let mut redraws = self.window_target.redraws.lock().unwrap(); redraws.pop_front() } { app.window_event( @@ -612,11 +609,11 @@ impl EventLoop { app.about_to_wait(&self.window_target); - if self.window_target.p.exiting() { + if self.window_target.exiting() { break; } - let requested_resume = match self.window_target.p.control_flow() { + let requested_resume = match self.window_target.control_flow() { ControlFlow::Poll => { start_cause = StartCause::Poll; continue; @@ -630,7 +627,6 @@ impl EventLoop { let timeout_socket = TimeSocket::open().unwrap(); self.window_target - .p .event_socket .write(&syscall::Event { id: timeout_socket.0.fd, @@ -658,7 +654,7 @@ impl EventLoop { // Wait for event if needed. let mut event = syscall::Event::default(); - self.window_target.p.event_socket.read(&mut event).unwrap(); + self.window_target.event_socket.read(&mut event).unwrap(); // TODO: handle spurious wakeups (redraw caused wakeup but redraw already handled) match requested_resume { @@ -679,7 +675,7 @@ impl EventLoop { Ok(()) } - pub fn window_target(&self) -> &event_loop::ActiveEventLoop { + pub fn window_target(&self) -> &dyn RootActiveEventLoop { &self.window_target } } @@ -721,65 +717,82 @@ pub struct ActiveEventLoop { user_events_sender: mpsc::SyncSender<()>, } -impl ActiveEventLoop { - pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy { - user_events_sender: self.user_events_sender.clone(), - wake_socket: self.wake_socket.clone(), +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(), + }, } } - pub fn create_custom_cursor( + fn create_window( &self, - _source: CustomCursorSource, + window_attributes: crate::window::WindowAttributes, + ) -> Result { + let window = crate::platform_impl::Window::new(self, window_attributes)?; + Ok(crate::window::Window { window }) + } + + fn create_custom_cursor( + &self, + _: CustomCursorSource, ) -> Result { Err(ExternalError::NotSupported(NotSupportedError::new())) } - pub fn primary_monitor(&self) -> Option { - Some(MonitorHandle) - } - - pub fn available_monitors(&self) -> VecDeque { + fn available_monitors(&self) -> Box> { let mut v = VecDeque::with_capacity(1); - v.push_back(MonitorHandle); - v + v.push_back(crate::monitor::MonitorHandle { inner: MonitorHandle }); + Box::new(v.into_iter()) } - #[inline] - pub fn listen_device_events(&self, _allowed: DeviceEvents) {} - - #[inline] - pub fn system_theme(&self) -> Option { + fn system_theme(&self) -> Option { None } - #[cfg(feature = "rwh_06")] - #[inline] - pub fn raw_display_handle_rwh_06( - &self, - ) -> Result { - Ok(rwh_06::RawDisplayHandle::Orbital(rwh_06::OrbitalDisplayHandle::new())) + fn primary_monitor(&self) -> Option { + Some(crate::monitor::MonitorHandle { inner: MonitorHandle }) } - pub fn set_control_flow(&self, control_flow: ControlFlow) { + fn listen_device_events(&self, _allowed: DeviceEvents) {} + + fn set_control_flow(&self, control_flow: ControlFlow) { self.control_flow.set(control_flow) } - pub fn control_flow(&self) -> ControlFlow { + fn control_flow(&self) -> ControlFlow { self.control_flow.get() } - pub(crate) fn exit(&self) { + fn exit(&self) { self.exit.set(true); } - pub(crate) fn exiting(&self) -> bool { + fn exiting(&self) -> bool { self.exit.get() } - pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle { - OwnedDisplayHandle + fn owned_display_handle(&self) -> event_loop::OwnedDisplayHandle { + event_loop::OwnedDisplayHandle { platform: OwnedDisplayHandle } + } + + fn as_any(&self) -> &dyn Any { + self + } + + #[cfg(feature = "rwh_06")] + fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle { + self + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for ActiveEventLoop { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + let raw = rwh_06::RawDisplayHandle::Orbital(rwh_06::OrbitalDisplayHandle::new()); + unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) } } } diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index 53050f65..b9c47a4b 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -1,11 +1,9 @@ -use std::marker::PhantomData; - use super::{backend, device, window, HasMonitorPermissionFuture, MonitorPermissionFuture}; use crate::application::ApplicationHandler; use crate::error::{EventLoopError, NotSupportedError}; use crate::event::Event; use crate::event_loop::ActiveEventLoop as RootActiveEventLoop; -use crate::platform::web::{ActiveEventLoopExtWeb, PollStrategy, WaitUntilStrategy}; +use crate::platform::web::{PollStrategy, WaitUntilStrategy}; mod proxy; pub(crate) mod runner; @@ -16,7 +14,7 @@ pub(crate) use proxy::EventLoopProxy; pub(crate) use window_target::{ActiveEventLoop, OwnedDisplayHandle}; pub struct EventLoop { - elw: RootActiveEventLoop, + elw: ActiveEventLoop, } #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -24,16 +22,15 @@ pub(crate) struct PlatformSpecificEventLoopAttributes {} impl EventLoop { pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result { - let elw = RootActiveEventLoop { p: ActiveEventLoop::new(), _marker: PhantomData }; - Ok(EventLoop { elw }) + Ok(EventLoop { elw: ActiveEventLoop::new() }) } pub fn run_app(self, mut app: A) -> ! { - let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData }; + let event_loop = self.elw.clone(); // SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`. let handler: Box = - Box::new(|event| handle_event(&mut app, &target, event)); + Box::new(|event| handle_event(&mut app, &event_loop, event)); // SAFETY: The `transmute` is necessary because `run()` requires `'static`. This is safe // because this function will never return and all resources not cleaned up by the point we @@ -41,7 +38,7 @@ impl EventLoop { let handler = unsafe { std::mem::transmute::, Box>(handler) }; - self.elw.p.run(handler, false); + self.elw.run(handler, false); // Throw an exception to break out of Rust execution and use unreachable to tell the // compiler this function won't return, giving it a return type of '!' @@ -53,12 +50,11 @@ impl EventLoop { } pub fn spawn_app(self, mut app: A) { - let target = RootActiveEventLoop { p: self.elw.p.clone(), _marker: PhantomData }; - - self.elw.p.run(Box::new(move |event| handle_event(&mut app, &target, event)), true); + let event_loop = self.elw.clone(); + self.elw.run(Box::new(move |event| handle_event(&mut app, &event_loop, event)), true); } - pub fn window_target(&self) -> &RootActiveEventLoop { + pub fn window_target(&self) -> &dyn RootActiveEventLoop { &self.elw } @@ -83,15 +79,15 @@ impl EventLoop { } pub(crate) fn request_detailed_monitor_permission(&self) -> MonitorPermissionFuture { - self.elw.request_detailed_monitor_permission().0 + self.elw.request_detailed_monitor_permission() } pub fn has_detailed_monitor_permission(&self) -> HasMonitorPermissionFuture { - self.elw.p.runner.monitor().has_detailed_monitor_permission_async() + self.elw.runner.monitor().has_detailed_monitor_permission_async() } } -fn handle_event(app: &mut A, target: &RootActiveEventLoop, event: Event) { +fn handle_event(app: &mut A, target: &ActiveEventLoop, event: Event) { match event { Event::NewEvents(cause) => app.new_events(target, cause), Event::WindowEvent { window_id, event } => app.window_event(target, window_id, event), diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index 5e90d5a2..86e94cce 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -1,3 +1,4 @@ +use std::any::Any; use std::cell::Cell; use std::clone::Clone; use std::iter; @@ -5,7 +6,7 @@ use std::rc::Rc; use web_sys::Element; -use super::super::monitor::{MonitorHandle, MonitorPermissionFuture}; +use super::super::monitor::MonitorPermissionFuture; use super::super::{lock, KeyEventExtra}; use super::device::DeviceId; use super::runner::{EventWrapper, WeakShared}; @@ -15,13 +16,19 @@ use crate::error::{ExternalError, NotSupportedError}; use crate::event::{ DeviceId as RootDeviceId, ElementState, Event, KeyEvent, Touch, TouchPhase, WindowEvent, }; -use crate::event_loop::{ControlFlow, DeviceEvents}; +use crate::event_loop::{ + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, +}; 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::Window; use crate::window::{ - CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId, + CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow, + WindowId as RootWindowId, }; #[derive(Default)] @@ -67,17 +74,6 @@ impl ActiveEventLoop { WindowId(self.runner.generate_id()) } - pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy::new(self.waker()) - } - - pub fn create_custom_cursor( - &self, - source: CustomCursorSource, - ) -> Result { - Ok(RootCustomCursor { inner: CustomCursor::new(self, source.inner) }) - } - pub fn create_custom_cursor_async(&self, source: CustomCursorSource) -> CustomCursorFuture { CustomCursorFuture(CustomCursor::new_async(self, source.inner)) } @@ -594,52 +590,6 @@ impl ActiveEventLoop { canvas.on_context_menu(); } - pub fn available_monitors(&self) -> Vec { - self.runner.monitor().available_monitors() - } - - pub fn primary_monitor(&self) -> Option { - self.runner.monitor().primary_monitor() - } - - #[cfg(feature = "rwh_06")] - #[inline] - pub fn raw_display_handle_rwh_06( - &self, - ) -> Result { - Ok(rwh_06::RawDisplayHandle::Web(rwh_06::WebDisplayHandle::new())) - } - - pub fn listen_device_events(&self, allowed: DeviceEvents) { - self.runner.listen_device_events(allowed) - } - - pub fn system_theme(&self) -> Option { - backend::is_dark_mode(self.runner.window()).map(|is_dark_mode| { - if is_dark_mode { - Theme::Dark - } else { - Theme::Light - } - }) - } - - pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { - self.runner.set_control_flow(control_flow) - } - - pub(crate) fn control_flow(&self) -> ControlFlow { - self.runner.control_flow() - } - - pub(crate) fn exit(&self) { - self.runner.exit() - } - - pub(crate) fn exiting(&self) -> bool { - self.runner.exiting() - } - pub(crate) fn set_poll_strategy(&self, strategy: PollStrategy) { self.runner.set_poll_strategy(strategy) } @@ -675,9 +625,92 @@ impl ActiveEventLoop { pub(crate) fn waker(&self) -> Waker { self.runner.waker() } +} - pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle { - OwnedDisplayHandle +impl RootActiveEventLoop for ActiveEventLoop { + fn create_proxy(&self) -> RootEventLoopProxy { + let event_loop_proxy = EventLoopProxy::new(self.waker()); + RootEventLoopProxy { event_loop_proxy } + } + + fn create_window( + &self, + window_attributes: crate::window::WindowAttributes, + ) -> Result { + let window = Window::new(self, window_attributes)?; + Ok(RootWindow { window }) + } + + fn create_custom_cursor( + &self, + source: CustomCursorSource, + ) -> Result { + Ok(RootCustomCursor { inner: CustomCursor::new(self, source.inner) }) + } + + fn available_monitors(&self) -> Box> { + Box::new( + self.runner + .monitor() + .available_monitors() + .into_iter() + .map(|inner| RootMonitorHandle { inner }), + ) + } + + fn primary_monitor(&self) -> Option { + self.runner.monitor().primary_monitor().map(|inner| RootMonitorHandle { inner }) + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + self.runner.listen_device_events(allowed) + } + + fn system_theme(&self) -> Option { + backend::is_dark_mode(self.runner.window()).map(|is_dark_mode| { + if is_dark_mode { + Theme::Dark + } else { + Theme::Light + } + }) + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.runner.set_control_flow(control_flow) + } + + fn control_flow(&self) -> ControlFlow { + self.runner.control_flow() + } + + fn exit(&self) { + self.runner.exit() + } + + fn exiting(&self) -> bool { + self.runner.exiting() + } + + fn owned_display_handle(&self) -> RootOwnedDisplayHandle { + RootOwnedDisplayHandle { platform: OwnedDisplayHandle } + } + + fn as_any(&self) -> &dyn Any { + self + } + + #[cfg(feature = "rwh_06")] + fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle { + self + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for ActiveEventLoop { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + let raw = rwh_06::RawDisplayHandle::Web(rwh_06::WebDisplayHandle::new()); + unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) } } } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index 873c385f..eb2fef2d 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -3,9 +3,7 @@ mod runner; use std::cell::Cell; -use std::collections::VecDeque; use std::ffi::c_void; -use std::marker::PhantomData; use std::rc::Rc; use std::sync::atomic::{AtomicU32, Ordering}; use std::sync::{Arc, Mutex, MutexGuard}; @@ -58,12 +56,16 @@ use super::window::set_skip_taskbar; use super::SelectedCursor; use crate::application::ApplicationHandler; use crate::dpi::{PhysicalPosition, PhysicalSize}; -use crate::error::{EventLoopError, ExternalError}; +use crate::error::{EventLoopError, ExternalError, OsError}; use crate::event::{ Event, Force, Ime, InnerSizeWriter, RawKeyEvent, Touch, TouchPhase, WindowEvent, }; -use crate::event_loop::{ActiveEventLoop as RootAEL, ControlFlow, DeviceEvents}; +use crate::event_loop::{ + ActiveEventLoop as RootActiveEventLoop, ControlFlow, DeviceEvents, + EventLoopProxy as RootEventLoopProxy, OwnedDisplayHandle as RootOwnedDisplayHandle, +}; use crate::keyboard::ModifiersState; +use crate::monitor::MonitorHandle as RootMonitorHandle; use crate::platform::pump_events::PumpStatus; use crate::platform_impl::platform::dark_mode::try_theme; use crate::platform_impl::platform::dpi::{become_dpi_aware, dpi_to_scale_factor}; @@ -80,9 +82,11 @@ use crate::platform_impl::platform::window_state::{ use crate::platform_impl::platform::{ raw_input, util, wrap_device_id, Fullscreen, WindowId, DEVICE_ID, }; +use crate::platform_impl::Window; use crate::utils::Lazy; use crate::window::{ - CustomCursor as RootCustomCursor, CustomCursorSource, Theme, WindowId as RootWindowId, + CustomCursor as RootCustomCursor, CustomCursorSource, Theme, Window as RootWindow, + WindowAttributes, WindowId as RootWindowId, }; pub(crate) struct WindowData { @@ -122,7 +126,7 @@ pub(crate) enum ProcResult { } pub struct EventLoop { - window_target: RootAEL, + window_target: ActiveEventLoop, msg_hook: Option bool + 'static>>, } @@ -174,15 +178,12 @@ impl EventLoop { ); Ok(EventLoop { - window_target: RootAEL { - p: ActiveEventLoop { thread_id, thread_msg_target, runner_shared }, - _marker: PhantomData, - }, + window_target: ActiveEventLoop { thread_id, thread_msg_target, runner_shared }, msg_hook: attributes.msg_hook.take(), }) } - pub fn window_target(&self) -> &RootAEL { + pub fn window_target(&self) -> &dyn RootActiveEventLoop { &self.window_target } @@ -194,9 +195,9 @@ impl EventLoop { &mut self, mut app: A, ) -> Result<(), EventLoopError> { - self.window_target.p.clear_exit(); + self.window_target.clear_exit(); { - let runner = &self.window_target.p.runner_shared; + let runner = &self.window_target.runner_shared; let event_loop_windows_ref = &self.window_target; // # Safety @@ -236,7 +237,7 @@ impl EventLoop { } }; - let runner = &self.window_target.p.runner_shared; + let runner = &self.window_target.runner_shared; runner.loop_destroyed(); // # Safety @@ -257,7 +258,7 @@ impl EventLoop { mut app: A, ) -> PumpStatus { { - let runner = &self.window_target.p.runner_shared; + let runner = &self.window_target.runner_shared; let event_loop_windows_ref = &self.window_target; // let user_event_receiver = &self.user_event_receiver; @@ -296,7 +297,7 @@ impl EventLoop { self.dispatch_peeked_messages(); } - let runner = &self.window_target.p.runner_shared; + let runner = &self.window_target.runner_shared; let status = if let Some(code) = runner.exit_code() { runner.loop_destroyed(); @@ -358,7 +359,7 @@ impl EventLoop { } } - let runner = &self.window_target.p.runner_shared; + let runner = &self.window_target.runner_shared; // We aim to be consistent with the MacOS backend which has a RunLoop // observer that will dispatch AboutToWait when about to wait for @@ -420,7 +421,7 @@ impl EventLoop { /// Dispatch all queued messages via `PeekMessageW` fn dispatch_peeked_messages(&mut self) { - let runner = &self.window_target.p.runner_shared; + let runner = &self.window_target.runner_shared; // We generally want to continue dispatching all pending messages // but we also allow dispatching to be interrupted as a means to @@ -469,81 +470,100 @@ impl EventLoop { } fn exit_code(&self) -> Option { - self.window_target.p.exit_code() + self.window_target.exit_code() } } impl ActiveEventLoop { - pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy { target_window: self.thread_msg_target } - } - #[inline(always)] pub(crate) fn create_thread_executor(&self) -> EventLoopThreadExecutor { EventLoopThreadExecutor { thread_id: self.thread_id, target_window: self.thread_msg_target } } - pub fn create_custom_cursor( - &self, - source: CustomCursorSource, - ) -> Result { - Ok(RootCustomCursor { inner: WinCursor::new(&source.inner.0)? }) - } - - // TODO: Investigate opportunities for caching - pub fn available_monitors(&self) -> VecDeque { - monitor::available_monitors() - } - - pub fn primary_monitor(&self) -> Option { - let monitor = monitor::primary_monitor(); - Some(monitor) - } - - #[cfg(feature = "rwh_06")] - pub fn raw_display_handle_rwh_06( - &self, - ) -> Result { - Ok(rwh_06::RawDisplayHandle::Windows(rwh_06::WindowsDisplayHandle::new())) - } - - pub fn listen_device_events(&self, allowed: DeviceEvents) { - raw_input::register_all_mice_and_keyboards_for_raw_input(self.thread_msg_target, allowed); - } - - pub fn system_theme(&self) -> Option { - Some(if super::dark_mode::should_use_dark_mode() { Theme::Dark } else { Theme::Light }) - } - - pub(crate) fn set_control_flow(&self, control_flow: ControlFlow) { - self.runner_shared.set_control_flow(control_flow) - } - - pub(crate) fn control_flow(&self) -> ControlFlow { - self.runner_shared.control_flow() - } - - pub(crate) fn exit(&self) { - self.runner_shared.set_exit_code(0) - } - - pub(crate) fn exiting(&self) -> bool { - self.runner_shared.exit_code().is_some() - } - pub(crate) fn clear_exit(&self) { self.runner_shared.clear_exit(); } - pub(crate) fn owned_display_handle(&self) -> OwnedDisplayHandle { - OwnedDisplayHandle - } - fn exit_code(&self) -> Option { self.runner_shared.exit_code() } } +impl RootActiveEventLoop for ActiveEventLoop { + fn create_proxy(&self) -> RootEventLoopProxy { + let event_loop_proxy = EventLoopProxy { target_window: self.thread_msg_target }; + RootEventLoopProxy { event_loop_proxy } + } + + fn create_window(&self, window_attributes: WindowAttributes) -> Result { + let window = Window::new(self, window_attributes)?; + Ok(RootWindow { window }) + } + + fn create_custom_cursor( + &self, + source: CustomCursorSource, + ) -> Result { + Ok(RootCustomCursor { inner: WinCursor::new(&source.inner.0)? }) + } + + fn available_monitors(&self) -> Box> { + Box::new( + monitor::available_monitors() + .into_iter() + .map(|inner| crate::monitor::MonitorHandle { inner }), + ) + } + + fn primary_monitor(&self) -> Option { + Some(RootMonitorHandle { inner: monitor::primary_monitor() }) + } + + fn exiting(&self) -> bool { + self.runner_shared.exit_code().is_some() + } + + fn system_theme(&self) -> Option { + Some(if super::dark_mode::should_use_dark_mode() { Theme::Dark } else { Theme::Light }) + } + + fn listen_device_events(&self, allowed: DeviceEvents) { + raw_input::register_all_mice_and_keyboards_for_raw_input(self.thread_msg_target, allowed); + } + + fn set_control_flow(&self, control_flow: ControlFlow) { + self.runner_shared.set_control_flow(control_flow) + } + + fn control_flow(&self) -> ControlFlow { + self.runner_shared.control_flow() + } + + fn exit(&self) { + self.runner_shared.set_exit_code(0) + } + + fn owned_display_handle(&self) -> RootOwnedDisplayHandle { + RootOwnedDisplayHandle { platform: OwnedDisplayHandle } + } + + fn as_any(&self) -> &dyn std::any::Any { + self + } + + fn rwh_06_handle(&self) -> &dyn rwh_06::HasDisplayHandle { + self + } +} + +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for ActiveEventLoop { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + let raw = rwh_06::RawDisplayHandle::Windows(rwh_06::WindowsDisplayHandle::new()); + unsafe { Ok(rwh_06::DisplayHandle::borrow_raw(raw)) } + } +} + #[derive(Clone)] pub(crate) struct OwnedDisplayHandle; @@ -632,7 +652,7 @@ fn dur2timeout(dur: Duration) -> u32 { impl Drop for EventLoop { fn drop(&mut self) { unsafe { - DestroyWindow(self.window_target.p.thread_msg_target); + DestroyWindow(self.window_target.thread_msg_target); } } } diff --git a/src/platform_impl/windows/mod.rs b/src/platform_impl/windows/mod.rs index 4b3255c4..abd9ed16 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -3,8 +3,7 @@ use windows_sys::Win32::Foundation::{HANDLE, HWND}; use windows_sys::Win32::UI::WindowsAndMessaging::{HMENU, WINDOW_LONG_PTR_INDEX}; pub(crate) use self::event_loop::{ - ActiveEventLoop, EventLoop, EventLoopProxy, OwnedDisplayHandle, - PlatformSpecificEventLoopAttributes, + EventLoop, EventLoopProxy, OwnedDisplayHandle, PlatformSpecificEventLoopAttributes, }; pub use self::icon::WinIcon as PlatformIcon; pub(crate) use self::icon::{SelectedCursor, WinCursor as PlatformCustomCursor, WinIcon};