diff --git a/CHANGELOG.md b/CHANGELOG.md index 66530a6cf5..31112bed8c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,9 @@ Unreleased` header. # Unreleased -- **Breaking:** Removed unnecessary generic parameter `T` from `EventLoopWindowTarget`. +- **Breaking:** Removed `EventLoopWindowTarget`, and replaced it with `ActiveEventLoop<'app>`, which allows Winit to clearly define a boundary between what is possible when the application is not running, and when it is. +- Added `MaybeActiveEventLoop<'app>` trait to help be generic over `EventLoop` and `ActiveEventLoop<'app>`. +- Added `ActiveEventLoopExtWayland` and `ActiveEventLoopExtX11` to mimic the similar traits on the `EventLoop`. - On Windows, macOS, X11, Wayland and Web, implement setting images as cursors. See the `custom_cursors.rs` example. - **Breaking:** Remove `Window::set_cursor_icon` - Add `WindowBuilder::with_cursor` and `Window::set_cursor` which takes a `CursorIcon` or `CustomCursor` diff --git a/examples/child_window.rs b/examples/child_window.rs index 2693dbdc08..61f6539a68 100644 --- a/examples/child_window.rs +++ b/examples/child_window.rs @@ -16,14 +16,14 @@ fn main() -> Result<(), impl std::error::Error> { use winit::{ dpi::{LogicalPosition, LogicalSize, Position}, event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::{EventLoop, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoop}, raw_window_handle::HasRawWindowHandle, window::{Window, WindowBuilder, WindowId}, }; fn spawn_child_window( parent: &Window, - event_loop: &EventLoopWindowTarget, + event_loop: ActiveEventLoop<'_>, windows: &mut HashMap, ) { let parent = parent.raw_window_handle().unwrap(); diff --git a/examples/custom_cursors.rs b/examples/custom_cursors.rs index 11f16f7724..34562ac729 100644 --- a/examples/custom_cursors.rs +++ b/examples/custom_cursors.rs @@ -4,7 +4,7 @@ use simple_logger::SimpleLogger; use winit::{ event::{ElementState, Event, KeyEvent, WindowEvent}, - event_loop::{EventLoop, EventLoopWindowTarget}, + event_loop::EventLoop, keyboard::Key, window::{CursorIcon, CustomCursor, WindowBuilder}, }; @@ -18,14 +18,13 @@ use { #[cfg(web_platform)] static COUNTER: AtomicU64 = AtomicU64::new(0); -fn decode_cursor(bytes: &[u8], window_target: &EventLoopWindowTarget) -> CustomCursor { +fn decode_cursor(bytes: &[u8], event_loop: &EventLoop<()>) -> CustomCursor { let img = image::load_from_memory(bytes).unwrap().to_rgba8(); let samples = img.into_flat_samples(); let (_, w, h) = samples.extents(); let (w, h) = (w as u16, h as u16); let builder = CustomCursor::from_rgba(samples.samples, w, h, w / 2, h / 2).unwrap(); - - builder.build(window_target) + builder.build(event_loop) } #[cfg(not(web_platform))] diff --git a/src/cursor.rs b/src/cursor.rs index 5090af5d68..6b4d850139 100644 --- a/src/cursor.rs +++ b/src/cursor.rs @@ -5,7 +5,7 @@ use std::{error::Error, hash::Hash}; use cursor_icon::CursorIcon; -use crate::event_loop::EventLoopWindowTarget; +use crate::event_loop::MaybeActiveEventLoop; use crate::platform_impl::{self, PlatformCustomCursor, PlatformCustomCursorBuilder}; /// The maximum width and height for a cursor when using [`CustomCursor::from_rgba`]. @@ -111,9 +111,9 @@ pub struct CustomCursorBuilder { } impl CustomCursorBuilder { - pub fn build(self, window_target: &EventLoopWindowTarget) -> CustomCursor { + pub fn build<'a>(self, mut event_loop: impl MaybeActiveEventLoop<'a>) -> CustomCursor { CustomCursor { - inner: PlatformCustomCursor::build(self.inner, &window_target.p), + inner: PlatformCustomCursor::build(self.inner, event_loop.__inner()), } } } @@ -213,7 +213,7 @@ impl Eq for OnlyCursorImage {} #[allow(dead_code)] impl OnlyCursorImage { - fn build(builder: OnlyCursorImageBuilder, _: &platform_impl::EventLoopWindowTarget) -> Self { + fn build(builder: OnlyCursorImageBuilder, _: platform_impl::ActiveEventLoop<'_>) -> Self { Self(Arc::new(builder.0)) } } @@ -293,7 +293,7 @@ impl NoCustomCursor { Ok(Self) } - fn build(self, _: &platform_impl::EventLoopWindowTarget) -> NoCustomCursor { + fn build(self, _: platform_impl::ActiveEventLoop<'_>) -> NoCustomCursor { self } } diff --git a/src/event_loop.rs b/src/event_loop.rs index 1cade1f07c..2da6cbaf10 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -8,7 +8,6 @@ //! See the root-level documentation for information on how to create and use an event loop to //! handle events. use std::marker::PhantomData; -use std::ops::Deref; #[cfg(any(x11_platform, wayland_platform))] use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, RawFd}; use std::sync::atomic::{AtomicBool, AtomicU64, Ordering}; @@ -37,20 +36,98 @@ use crate::{event::Event, monitor::MonitorHandle, platform_impl}; /// [`EventLoopProxy`] allows you to wake up an `EventLoop` from another thread. /// /// [`Window`]: crate::window::Window +// TODO: Don't allow window creation from this, since that is broken on macOS/iOS. pub struct EventLoop { pub(crate) event_loop: platform_impl::EventLoop, pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync } -/// Target that associates windows with an [`EventLoop`]. +/// An active event loop. /// -/// This type exists to allow you to create new windows while Winit executes -/// your callback. [`EventLoop`] will coerce into this type (`impl Deref for -/// EventLoop`), so functions that take this as a parameter can also take -/// `&EventLoop`. -pub struct EventLoopWindowTarget { - pub(crate) p: platform_impl::EventLoopWindowTarget, - pub(crate) _marker: PhantomData<*mut ()>, // Not Send nor Sync +/// This type exists to differentiate between functionality available when Winit +/// is executing your callback, and outside of it. +#[derive(Copy, Clone)] +pub struct ActiveEventLoop<'a> { + pub(crate) inner: platform_impl::ActiveEventLoop<'a>, + _marker: PhantomData<*mut ()>, // Not Send nor Sync +} + +impl fmt::Debug for ActiveEventLoop<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.pad("ActiveEventLoop { .. }") + } +} + +impl<'a> ActiveEventLoop<'a> { + pub(crate) fn new(inner: platform_impl::ActiveEventLoop<'a>) -> Self { + Self { + inner, + _marker: PhantomData, + } + } + + /// Sets the [`ControlFlow`]. + pub fn set_control_flow(&self, control_flow: ControlFlow) { + self.inner.set_control_flow(control_flow) + } + + /// Gets the current [`ControlFlow`]. + pub fn control_flow(&self) -> ControlFlow { + self.inner.control_flow() + } + + /// This exits the event loop. + /// + /// See [`LoopExiting`](Event::LoopExiting). + pub fn exit(&self) { + self.inner.exit() + } + + /// Returns if the [`EventLoop`] is about to stop. + /// + /// See [`exit()`](Self::exit). + pub fn exiting(&self) -> bool { + self.inner.exiting() + } + + /// Returns the primary monitor of the system. + /// + /// Returns `None` if it can't identify any monitor as a primary one. + /// + /// ## Platform-specific + /// + /// **Wayland / Web:** Always returns `None`. + #[inline] + pub fn primary_monitor(&self) -> Option { + self.inner + .primary_monitor() + .map(|inner| MonitorHandle { inner }) + } + + /// Returns the list of all the monitors available on the system. + #[inline] + pub fn available_monitors(&self) -> impl Iterator { + #[allow(clippy::useless_conversion)] // false positive on some platforms + self.inner + .available_monitors() + .into_iter() + .map(|inner| MonitorHandle { inner }) + } + + /// Change if or when [`DeviceEvent`]s are captured. + /// + /// Since the [`DeviceEvent`] capture can lead to high CPU usage for unfocused windows, winit + /// will ignore them by default for unfocused windows on Linux/BSD. This method allows changing + /// this at runtime to explicitly capture them again. + /// + /// ## Platform-specific + /// + /// - **Wayland / macOS / iOS / Android / Orbital:** Unsupported. + /// + /// [`DeviceEvent`]: crate::event::DeviceEvent + pub fn listen_device_events(&self, allowed: DeviceEvents) { + self.inner.listen_device_events(allowed); + } } /// Object that allows building the event loop. @@ -142,13 +219,7 @@ impl fmt::Debug for EventLoop { } } -impl fmt::Debug for EventLoopWindowTarget { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.pad("EventLoopWindowTarget { .. }") - } -} - -/// Set through [`EventLoopWindowTarget::set_control_flow()`]. +/// Set through [`ActiveEventLoop::set_control_flow()`]. /// /// Indicates the desired behavior of the event loop after [`Event::AboutToWait`] is emitted. /// @@ -234,16 +305,67 @@ impl EventLoop { /// /// This function won't be available with `target_feature = "exception-handling"`. /// - /// [`set_control_flow()`]: EventLoopWindowTarget::set_control_flow() + /// [`set_control_flow()`]: ActiveEventLoop::set_control_flow() /// [`run()`]: Self::run() /// [^1]: `EventLoopExtWebSys::spawn()` is only available on Web. #[inline] #[cfg(not(all(web_platform, target_feature = "exception-handling")))] - pub fn run(self, event_handler: F) -> Result<(), EventLoopError> + pub fn run(self, mut handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &EventLoopWindowTarget), + F: FnMut(Event, ActiveEventLoop<'_>), { - self.event_loop.run(event_handler) + self.event_loop + .run(move |event, inner| handler(event, ActiveEventLoop::new(inner))) + } + + /// Set the initial [`ControlFlow`]. + pub fn set_control_flow(&self, control_flow: ControlFlow) { + self.event_loop + .window_target() + .set_control_flow(control_flow) + } + + /// Returns the primary monitor of the system. + /// + /// Returns `None` if it can't identify any monitor as a primary one. + /// + /// ## Platform-specific + /// + /// **Wayland / Web:** Always returns `None`. + #[inline] + pub fn primary_monitor(&self) -> Option { + self.event_loop + .window_target() + .primary_monitor() + .map(|inner| MonitorHandle { inner }) + } + + /// Returns the list of all the monitors available on the system. + #[inline] + pub fn available_monitors(&self) -> impl Iterator { + #[allow(clippy::useless_conversion)] // false positive on some platforms + self.event_loop + .window_target() + .available_monitors() + .into_iter() + .map(|inner| MonitorHandle { inner }) + } + + /// Change if or when [`DeviceEvent`]s are captured. + /// + /// Since the [`DeviceEvent`] capture can lead to high CPU usage for unfocused windows, winit + /// will ignore them by default for unfocused windows on Linux/BSD. This method allows changing + /// this at runtime to explicitly capture them again. + /// + /// ## Platform-specific + /// + /// - **Wayland / macOS / iOS / Android / Orbital:** Unsupported. + /// + /// [`DeviceEvent`]: crate::event::DeviceEvent + pub fn listen_device_events(&self, allowed: DeviceEvents) { + self.event_loop + .window_target() + .listen_device_events(allowed); } /// Creates an [`EventLoopProxy`] that can be used to dispatch user events to the main event loop. @@ -257,7 +379,12 @@ impl EventLoop { #[cfg(feature = "rwh_06")] impl rwh_06::HasDisplayHandle for EventLoop { fn display_handle(&self) -> Result, rwh_06::HandleError> { - rwh_06::HasDisplayHandle::display_handle(&**self) + let raw = self + .event_loop + .window_target() + .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) }) } } @@ -265,7 +392,7 @@ impl rwh_06::HasDisplayHandle for EventLoop { unsafe impl rwh_05::HasRawDisplayHandle for EventLoop { /// Returns a [`rwh_05::RawDisplayHandle`] for the event loop. fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle { - rwh_05::HasRawDisplayHandle::raw_display_handle(&**self) + self.event_loop.window_target().raw_display_handle_rwh_05() } } @@ -297,92 +424,51 @@ impl AsRawFd for EventLoop { } } -impl Deref for EventLoop { - type Target = EventLoopWindowTarget; - fn deref(&self) -> &EventLoopWindowTarget { - self.event_loop.window_target() +#[cfg(feature = "rwh_06")] +impl rwh_06::HasDisplayHandle for ActiveEventLoop<'_> { + fn display_handle(&self) -> Result, rwh_06::HandleError> { + let raw = self.inner.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) }) } } -impl EventLoopWindowTarget { - /// Returns the list of all the monitors available on the system. - #[inline] - pub fn available_monitors(&self) -> impl Iterator { - #[allow(clippy::useless_conversion)] // false positive on some platforms - self.p - .available_monitors() - .into_iter() - .map(|inner| MonitorHandle { inner }) - } - - /// Returns the primary monitor of the system. - /// - /// Returns `None` if it can't identify any monitor as a primary one. - /// - /// ## Platform-specific - /// - /// **Wayland / Web:** Always returns `None`. - #[inline] - pub fn primary_monitor(&self) -> Option { - self.p - .primary_monitor() - .map(|inner| MonitorHandle { inner }) - } - - /// Change if or when [`DeviceEvent`]s are captured. - /// - /// Since the [`DeviceEvent`] capture can lead to high CPU usage for unfocused windows, winit - /// will ignore them by default for unfocused windows on Linux/BSD. This method allows changing - /// this at runtime to explicitly capture them again. - /// - /// ## Platform-specific - /// - /// - **Wayland / macOS / iOS / Android / Orbital:** Unsupported. - /// - /// [`DeviceEvent`]: crate::event::DeviceEvent - pub fn listen_device_events(&self, allowed: DeviceEvents) { - self.p.listen_device_events(allowed); - } - - /// Sets the [`ControlFlow`]. - pub fn set_control_flow(&self, control_flow: ControlFlow) { - self.p.set_control_flow(control_flow) +#[cfg(feature = "rwh_05")] +unsafe impl rwh_05::HasRawDisplayHandle for ActiveEventLoop<'_> { + /// Returns a [`rwh_05::RawDisplayHandle`] for the event loop. + fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle { + self.inner.raw_display_handle_rwh_05() } +} - /// Gets the current [`ControlFlow`]. - pub fn control_flow(&self) -> ControlFlow { - self.p.control_flow() - } +mod private { + pub trait Sealed {} +} - /// This exits the event loop. - /// - /// See [`LoopExiting`](Event::LoopExiting). - pub fn exit(&self) { - self.p.exit() - } +/// Trait to allow functions to be generic over [`EventLoop`] and [`ActiveEventLoop`]. +pub trait MaybeActiveEventLoop<'a>: private::Sealed { + #[doc(hidden)] + fn __inner(&mut self) -> platform_impl::ActiveEventLoop<'a>; +} - /// Returns if the [`EventLoop`] is about to stop. - /// - /// See [`exit()`](Self::exit). - pub fn exiting(&self) -> bool { - self.p.exiting() +impl private::Sealed for &EventLoop {} +impl<'a, T: 'static> MaybeActiveEventLoop<'a> for &'a EventLoop { + fn __inner(&mut self) -> platform_impl::ActiveEventLoop<'a> { + self.event_loop.window_target() } } -#[cfg(feature = "rwh_06")] -impl rwh_06::HasDisplayHandle for EventLoopWindowTarget { - 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) }) +impl private::Sealed for ActiveEventLoop<'_> {} +impl<'a> MaybeActiveEventLoop<'a> for ActiveEventLoop<'a> { + fn __inner(&mut self) -> platform_impl::ActiveEventLoop<'a> { + self.inner } } -#[cfg(feature = "rwh_05")] -unsafe impl rwh_05::HasRawDisplayHandle for EventLoopWindowTarget { - /// Returns a [`rwh_05::RawDisplayHandle`] for the event loop. - fn raw_display_handle(&self) -> rwh_05::RawDisplayHandle { - self.p.raw_display_handle_rwh_05() +impl<'a, T: MaybeActiveEventLoop<'a>> private::Sealed for &mut T {} +impl<'a, T: MaybeActiveEventLoop<'a>> MaybeActiveEventLoop<'a> for &mut T { + fn __inner(&mut self) -> platform_impl::ActiveEventLoop<'a> { + T::__inner(self) } } @@ -470,3 +556,15 @@ impl AsyncRequestSerial { Self { serial } } } + +#[cfg(test)] +mod tests { + use super::*; + + #[allow(unused)] + fn assert_active_event_loop_covariance<'b>( + event_loop: ActiveEventLoop<'static>, + ) -> ActiveEventLoop<'b> { + event_loop + } +} diff --git a/src/lib.rs b/src/lib.rs index 99aa888a55..ecd965f875 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -132,7 +132,7 @@ //! [`EventLoop`]: event_loop::EventLoop //! [`EventLoop::new()`]: event_loop::EventLoop::new //! [`EventLoop::run()`]: event_loop::EventLoop::run -//! [`exit()`]: event_loop::EventLoopWindowTarget::exit +//! [`exit()`]: event_loop::ActiveEventLoop::exit //! [`Window`]: window::Window //! [`WindowId`]: window::WindowId //! [`WindowBuilder`]: window::WindowBuilder diff --git a/src/monitor.rs b/src/monitor.rs index 7fe7e23494..e8c8478f75 100644 --- a/src/monitor.rs +++ b/src/monitor.rs @@ -3,7 +3,8 @@ //! If you want to get basic information about a monitor, you can use the //! [`MonitorHandle`] type. This is retrieved from one of the following //! methods, which return an iterator of [`MonitorHandle`]: -//! - [`EventLoopWindowTarget::available_monitors`](crate::event_loop::EventLoopWindowTarget::available_monitors). +//! - [`EventLoop::available_monitors`](crate::event_loop::EventLoop::available_monitors). +//! - [`ActiveEventLoop::available_monitors`](crate::event_loop::ActiveEventLoop::available_monitors). //! - [`Window::available_monitors`](crate::window::Window::available_monitors). use crate::{ dpi::{PhysicalPosition, PhysicalSize}, diff --git a/src/platform/android.rs b/src/platform/android.rs index 9bdcb03528..3dc125a4a4 100644 --- a/src/platform/android.rs +++ b/src/platform/android.rs @@ -1,5 +1,5 @@ use crate::{ - event_loop::{EventLoop, EventLoopBuilder, EventLoopWindowTarget}, + event_loop::{EventLoop, EventLoopBuilder}, window::{Window, WindowBuilder}, }; @@ -10,9 +10,6 @@ pub trait EventLoopExtAndroid {} impl EventLoopExtAndroid for EventLoop {} -/// Additional methods on [`EventLoopWindowTarget`] that are specific to Android. -pub trait EventLoopWindowTargetExtAndroid {} - /// Additional methods on [`Window`] that are specific to Android. pub trait WindowExtAndroid { fn content_rect(&self) -> Rect; @@ -30,8 +27,6 @@ impl WindowExtAndroid for Window { } } -impl EventLoopWindowTargetExtAndroid for EventLoopWindowTarget {} - /// Additional methods on [`WindowBuilder`] that are specific to Android. pub trait WindowBuilderExtAndroid {} diff --git a/src/platform/macos.rs b/src/platform/macos.rs index 869c9bf3fb..e0189bfc00 100644 --- a/src/platform/macos.rs +++ b/src/platform/macos.rs @@ -4,7 +4,7 @@ use std::os::raw::c_void; use serde::{Deserialize, Serialize}; use crate::{ - event_loop::{EventLoopBuilder, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoopBuilder}, monitor::MonitorHandle, window::{Window, WindowBuilder}, }; @@ -374,8 +374,8 @@ impl MonitorHandleExtMacOS for MonitorHandle { } } -/// Additional methods on [`EventLoopWindowTarget`] that are specific to macOS. -pub trait EventLoopWindowTargetExtMacOS { +/// Additional methods on [`ActiveEventLoop`] that are specific to macOS. +pub trait ActiveEventLoopExtMacOS { /// Hide the entire application. In most applications this is typically triggered with Command-H. fn hide_application(&self); /// Hide the other applications. In most applications this is typically triggered with Command+Option-H. @@ -388,21 +388,21 @@ pub trait EventLoopWindowTargetExtMacOS { fn allows_automatic_window_tabbing(&self) -> bool; } -impl EventLoopWindowTargetExtMacOS for EventLoopWindowTarget { +impl ActiveEventLoopExtMacOS for ActiveEventLoop<'_> { fn hide_application(&self) { - self.p.hide_application() + self.inner.hide_application() } fn hide_other_applications(&self) { - self.p.hide_other_applications() + self.inner.hide_other_applications() } fn set_allows_automatic_window_tabbing(&self, enabled: bool) { - self.p.set_allows_automatic_window_tabbing(enabled); + self.inner.set_allows_automatic_window_tabbing(enabled); } fn allows_automatic_window_tabbing(&self) -> bool { - self.p.allows_automatic_window_tabbing() + self.inner.allows_automatic_window_tabbing() } } diff --git a/src/platform/pump_events.rs b/src/platform/pump_events.rs index 403c52d978..994c70750d 100644 --- a/src/platform/pump_events.rs +++ b/src/platform/pump_events.rs @@ -2,7 +2,7 @@ use std::time::Duration; use crate::{ event::Event, - event_loop::{EventLoop, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoop}, }; /// The return status for `pump_events` @@ -174,16 +174,18 @@ pub trait EventLoopExtPumpEvents { /// callback. fn pump_events(&mut self, timeout: Option, event_handler: F) -> PumpStatus where - F: FnMut(Event, &EventLoopWindowTarget); + F: FnMut(Event, ActiveEventLoop<'_>); } impl EventLoopExtPumpEvents for EventLoop { type UserEvent = T; - fn pump_events(&mut self, timeout: Option, event_handler: F) -> PumpStatus + fn pump_events(&mut self, timeout: Option, mut event_handler: F) -> PumpStatus where - F: FnMut(Event, &EventLoopWindowTarget), + F: FnMut(Event, ActiveEventLoop<'_>), { - self.event_loop.pump_events(timeout, event_handler) + self.event_loop.pump_events(timeout, move |event, inner| { + event_handler(event, ActiveEventLoop::new(inner)) + }) } } diff --git a/src/platform/run_on_demand.rs b/src/platform/run_on_demand.rs index 603efab1aa..98114dafbf 100644 --- a/src/platform/run_on_demand.rs +++ b/src/platform/run_on_demand.rs @@ -1,7 +1,7 @@ use crate::{ error::EventLoopError, event::Event, - event_loop::{EventLoop, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoop}, }; #[cfg(doc)] @@ -62,28 +62,22 @@ pub trait EventLoopExtRunOnDemand { doc = "[^1]: `spawn()` is only available on `wasm` platforms." )] /// - /// [`exit()`]: EventLoopWindowTarget::exit() - /// [`set_control_flow()`]: EventLoopWindowTarget::set_control_flow() + /// [`exit()`]: ActiveEventLoop::exit() + /// [`set_control_flow()`]: ActiveEventLoop::set_control_flow() fn run_on_demand(&mut self, event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &EventLoopWindowTarget); + F: FnMut(Event, ActiveEventLoop<'_>); } impl EventLoopExtRunOnDemand for EventLoop { type UserEvent = T; - fn run_on_demand(&mut self, event_handler: F) -> Result<(), EventLoopError> + fn run_on_demand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &EventLoopWindowTarget), + F: FnMut(Event, ActiveEventLoop<'_>), { self.event_loop.window_target().clear_exit(); - self.event_loop.run_on_demand(event_handler) - } -} - -impl EventLoopWindowTarget { - /// Clear exit status. - pub(crate) fn clear_exit(&self) { - self.p.clear_exit() + self.event_loop + .run_on_demand(move |event, inner| event_handler(event, ActiveEventLoop::new(inner))) } } diff --git a/src/platform/startup_notify.rs b/src/platform/startup_notify.rs index 207aff86cb..df6aa3317f 100644 --- a/src/platform/startup_notify.rs +++ b/src/platform/startup_notify.rs @@ -24,7 +24,7 @@ use std::env; use crate::error::NotSupportedError; -use crate::event_loop::{AsyncRequestSerial, EventLoopWindowTarget}; +use crate::event_loop::{ActiveEventLoop, AsyncRequestSerial, EventLoop}; use crate::window::{ActivationToken, Window, WindowBuilder}; /// The variable which is used mostly on X11. @@ -55,13 +55,24 @@ pub trait WindowBuilderExtStartupNotify { fn with_activation_token(self, token: ActivationToken) -> Self; } -impl EventLoopExtStartupNotify for EventLoopWindowTarget { +impl EventLoopExtStartupNotify for EventLoop { fn read_token_from_env(&self) -> Option { - match self.p { - #[cfg(wayland_platform)] - crate::platform_impl::EventLoopWindowTarget::Wayland(_) => env::var(WAYLAND_VAR), - #[cfg(x11_platform)] - crate::platform_impl::EventLoopWindowTarget::X(_) => env::var(X11_VAR), + if self.event_loop.window_target().is_wayland() { + env::var(WAYLAND_VAR) + } else { + env::var(X11_VAR) + } + .ok() + .map(ActivationToken::_new) + } +} + +impl EventLoopExtStartupNotify for ActiveEventLoop<'_> { + fn read_token_from_env(&self) -> Option { + if self.inner.is_wayland() { + env::var(WAYLAND_VAR) + } else { + env::var(X11_VAR) } .ok() .map(ActivationToken::_new) diff --git a/src/platform/wayland.rs b/src/platform/wayland.rs index 587c3805e1..e4495c280b 100644 --- a/src/platform/wayland.rs +++ b/src/platform/wayland.rs @@ -1,21 +1,34 @@ use crate::{ - event_loop::{EventLoopBuilder, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder}, monitor::MonitorHandle, window::{Window, WindowBuilder}, }; pub use crate::window::Theme; -/// Additional methods on [`EventLoopWindowTarget`] that are specific to Wayland. -pub trait EventLoopWindowTargetExtWayland { - /// True if the [`EventLoopWindowTarget`] uses Wayland. +/// Additional methods on [`EventLoop`] that are specific to Wayland. +pub trait EventLoopExtWayland { + /// True if the [`EventLoop`] uses Wayland. fn is_wayland(&self) -> bool; } -impl EventLoopWindowTargetExtWayland for EventLoopWindowTarget { +impl EventLoopExtWayland for EventLoop { #[inline] fn is_wayland(&self) -> bool { - self.p.is_wayland() + self.event_loop.window_target().is_wayland() + } +} + +/// Additional methods on [`ActiveEventLoop`] that are specific to Wayland. +pub trait ActiveEventLoopExtWayland { + /// True if the [`ActiveEventLoop`] uses Wayland. + fn is_wayland(&self) -> bool; +} + +impl ActiveEventLoopExtWayland for ActiveEventLoop<'_> { + #[inline] + fn is_wayland(&self) -> bool { + self.inner.is_wayland() } } diff --git a/src/platform/web.rs b/src/platform/web.rs index 2f30160534..5ad06ff815 100644 --- a/src/platform/web.rs +++ b/src/platform/web.rs @@ -39,7 +39,7 @@ use web_sys::HtmlCanvasElement; use crate::cursor::CustomCursorBuilder; use crate::event::Event; -use crate::event_loop::{EventLoop, EventLoopWindowTarget}; +use crate::event_loop::{ActiveEventLoop, EventLoop, MaybeActiveEventLoop}; #[cfg(web_platform)] use crate::platform_impl::CustomCursorFuture as PlatformCustomCursorFuture; use crate::platform_impl::{PlatformCustomCursor, PlatformCustomCursorBuilder}; @@ -172,21 +172,22 @@ pub trait EventLoopExtWebSys { /// [^1]: `run()` is _not_ available on WASM when the target supports `exception-handling`. fn spawn(self, event_handler: F) where - F: 'static + FnMut(Event, &EventLoopWindowTarget); + F: 'static + FnMut(Event, ActiveEventLoop<'_>); } impl EventLoopExtWebSys for EventLoop { type UserEvent = T; - fn spawn(self, event_handler: F) + fn spawn(self, mut event_handler: F) where - F: 'static + FnMut(Event, &EventLoopWindowTarget), + F: 'static + FnMut(Event, ActiveEventLoop<'_>), { - self.event_loop.spawn(event_handler) + self.event_loop + .spawn(move |event, inner| event_handler(event, ActiveEventLoop::new(inner))) } } -pub trait EventLoopWindowTargetExtWebSys { +pub trait ActiveEventLoopExtWebSys { /// Sets the strategy for [`ControlFlow::Poll`]. /// /// See [`PollStrategy`]. @@ -202,15 +203,15 @@ pub trait EventLoopWindowTargetExtWebSys { fn poll_strategy(&self) -> PollStrategy; } -impl EventLoopWindowTargetExtWebSys for EventLoopWindowTarget { +impl ActiveEventLoopExtWebSys for ActiveEventLoop<'_> { #[inline] fn set_poll_strategy(&self, strategy: PollStrategy) { - self.p.set_poll_strategy(strategy); + self.inner.set_poll_strategy(strategy); } #[inline] fn poll_strategy(&self) -> PollStrategy { - self.p.poll_strategy() + self.inner.poll_strategy() } } @@ -315,14 +316,17 @@ impl Error for BadAnimation {} pub trait CustomCursorBuilderExtWebSys { /// Async version of [`CustomCursorBuilder::build()`] which waits until the /// cursor has completely finished loading. - fn build_async(self, window_target: &EventLoopWindowTarget) -> CustomCursorFuture; + fn build_async<'a>(self, window_target: impl MaybeActiveEventLoop<'a>) -> CustomCursorFuture; } impl CustomCursorBuilderExtWebSys for CustomCursorBuilder { - fn build_async(self, window_target: &EventLoopWindowTarget) -> CustomCursorFuture { + fn build_async<'a>( + self, + mut window_target: impl MaybeActiveEventLoop<'a>, + ) -> CustomCursorFuture { CustomCursorFuture(PlatformCustomCursor::build_async( self.inner, - &window_target.p, + window_target.__inner(), )) } } diff --git a/src/platform/x11.rs b/src/platform/x11.rs index 608cb2f392..9de48b9354 100644 --- a/src/platform/x11.rs +++ b/src/platform/x11.rs @@ -2,7 +2,7 @@ use serde::{Deserialize, Serialize}; use crate::{ - event_loop::{EventLoopBuilder, EventLoopWindowTarget}, + event_loop::{ActiveEventLoop, EventLoop, EventLoopBuilder}, monitor::MonitorHandle, window::{Window, WindowBuilder}, }; @@ -89,16 +89,29 @@ pub fn register_xlib_error_hook(hook: XlibErrorHook) { } } -/// Additional methods on [`EventLoopWindowTarget`] that are specific to X11. -pub trait EventLoopWindowTargetExtX11 { - /// True if the [`EventLoopWindowTarget`] uses X11. +/// Additional methods on [`EventLoop`] that are specific to X11. +pub trait EventLoopExtX11 { + /// True if the [`EventLoop`] uses X11. fn is_x11(&self) -> bool; } -impl EventLoopWindowTargetExtX11 for EventLoopWindowTarget { +impl EventLoopExtX11 for EventLoop { #[inline] fn is_x11(&self) -> bool { - !self.p.is_wayland() + !self.event_loop.window_target().is_wayland() + } +} + +/// Additional methods on [`ActiveEventLoop`] that are specific to X11. +pub trait ActiveEventLoopExtX11 { + /// True if the [`ActiveEventLoop`] uses X11. + fn is_x11(&self) -> bool; +} + +impl ActiveEventLoopExtX11 for ActiveEventLoop<'_> { + #[inline] + fn is_x11(&self) -> bool { + !self.inner.is_wayland() } } diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index 426fd9bdbf..3d0d90df3f 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -4,7 +4,6 @@ use std::{ cell::Cell, collections::VecDeque, hash::Hash, - marker::PhantomData, sync::{ atomic::{AtomicBool, Ordering}, mpsc, Arc, Mutex, RwLock, @@ -24,7 +23,7 @@ use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error, event::{self, Force, InnerSizeWriter, StartCause}, - event_loop::{self, ControlFlow, DeviceEvents, EventLoopWindowTarget as RootELW}, + event_loop::{self, ControlFlow, DeviceEvents}, platform::pump_events::PumpStatus, window::{ self, CursorGrabMode, ImePurpose, ResizeDirection, Theme, WindowButtons, WindowLevel, @@ -141,7 +140,7 @@ pub struct KeyEventExtra {} pub struct EventLoop { android_app: AndroidApp, - window_target: event_loop::EventLoopWindowTarget, + window_target: EventLoopWindowTarget, redraw_flag: SharedFlag, user_events_sender: mpsc::Sender, user_events_receiver: PeekableReceiver, //must wake looper whenever something gets sent @@ -179,17 +178,11 @@ impl EventLoop { Ok(Self { android_app: android_app.clone(), - window_target: event_loop::EventLoopWindowTarget { - p: EventLoopWindowTarget { - app: android_app.clone(), - control_flow: Cell::new(ControlFlow::default()), - exit: Cell::new(false), - redraw_requester: RedrawRequester::new( - &redraw_flag, - android_app.create_waker(), - ), - }, - _marker: PhantomData, + window_target: EventLoopWindowTarget { + app: android_app.clone(), + control_flow: Cell::new(ControlFlow::default()), + exit: Cell::new(false), + redraw_requester: RedrawRequester::new(&redraw_flag, android_app.create_waker()), }, redraw_flag, user_events_sender, @@ -205,7 +198,7 @@ impl EventLoop { fn single_iteration(&mut self, main_event: Option>, callback: &mut F) where - F: FnMut(event::Event, &RootELW), + F: FnMut(event::Event, &EventLoopWindowTarget), { trace!("Mainloop iteration"); @@ -377,7 +370,7 @@ impl EventLoop { callback: &mut F, ) -> InputStatus where - F: FnMut(event::Event, &RootELW), + F: FnMut(event::Event, &EventLoopWindowTarget), { let mut input_status = InputStatus::Handled; match event { @@ -482,14 +475,14 @@ impl EventLoop { pub fn run(mut self, event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(event::Event, &event_loop::EventLoopWindowTarget), + F: FnMut(event::Event, &EventLoopWindowTarget), { self.run_on_demand(event_handler) } pub fn run_on_demand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(event::Event, &event_loop::EventLoopWindowTarget), + F: FnMut(event::Event, &EventLoopWindowTarget), { if self.loop_running { return Err(EventLoopError::AlreadyRunning); @@ -512,7 +505,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut callback: F) -> PumpStatus where - F: FnMut(event::Event, &RootELW), + F: FnMut(event::Event, &EventLoopWindowTarget), { if !self.loop_running { self.loop_running = true; @@ -545,7 +538,7 @@ impl EventLoop { fn poll_events_with_timeout(&mut self, mut timeout: Option, mut callback: F) where - F: FnMut(event::Event, &RootELW), + F: FnMut(event::Event, &EventLoopWindowTarget), { let start = Instant::now(); @@ -621,7 +614,7 @@ impl EventLoop { }); } - pub fn window_target(&self) -> &event_loop::EventLoopWindowTarget { + pub fn window_target(&self) -> &EventLoopWindowTarget { &self.window_target } @@ -633,11 +626,11 @@ impl EventLoop { } 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() } } @@ -665,6 +658,8 @@ impl EventLoopProxy { } } +pub type ActiveEventLoop<'a> = &'a EventLoopWindowTarget; + pub struct EventLoopWindowTarget { app: AndroidApp, control_flow: Cell, diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index e08776dc21..6daec5406b 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -2,7 +2,6 @@ use std::{ collections::VecDeque, ffi::c_void, fmt::{self, Debug}, - marker::PhantomData, ptr, sync::mpsc::{self, Receiver, Sender}, }; @@ -20,10 +19,7 @@ use objc2::ClassType; use crate::{ error::EventLoopError, event::Event, - event_loop::{ - ControlFlow, DeviceEvents, EventLoopClosed, - EventLoopWindowTarget as RootEventLoopWindowTarget, - }, + event_loop::{ControlFlow, DeviceEvents, EventLoopClosed}, platform::ios::Idiom, }; @@ -33,6 +29,8 @@ use super::{ uikit::{UIApplication, UIApplicationMain, UIDevice, UIScreen}, }; +pub type ActiveEventLoop<'a> = &'a EventLoopWindowTarget; + #[derive(Debug)] pub struct EventLoopWindowTarget { pub(super) mtm: MainThreadMarker, @@ -89,7 +87,7 @@ pub struct EventLoop { mtm: MainThreadMarker, sender: Sender, receiver: Receiver, - window_target: RootEventLoopWindowTarget, + window_target: EventLoopWindowTarget, } #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, Hash)] @@ -121,16 +119,13 @@ impl EventLoop { mtm, sender, receiver, - window_target: RootEventLoopWindowTarget { - p: EventLoopWindowTarget { mtm }, - _marker: PhantomData, - }, + window_target: EventLoopWindowTarget { mtm }, }) } pub fn run(self, event_handler: F) -> ! where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &EventLoopWindowTarget), { unsafe { let application = UIApplication::shared(self.mtm); @@ -142,7 +137,7 @@ impl EventLoop { ); let event_handler = std::mem::transmute::< - Box, &RootEventLoopWindowTarget)>, + Box, &EventLoopWindowTarget)>, Box>, >(Box::new(event_handler)); @@ -171,7 +166,7 @@ impl EventLoop { EventLoopProxy::new(self.sender.clone()) } - pub fn window_target(&self) -> &RootEventLoopWindowTarget { + pub fn window_target(&self) -> &EventLoopWindowTarget { &self.window_target } } @@ -342,7 +337,7 @@ fn setup_control_flow_observers() { #[derive(Debug)] pub enum Never {} -type EventHandlerCallback = dyn FnMut(Event, &RootEventLoopWindowTarget) + 'static; +type EventHandlerCallback = dyn FnMut(Event, &EventLoopWindowTarget) + 'static; pub trait EventHandler: Debug { fn handle_nonuser_event(&mut self, event: Event); @@ -352,7 +347,7 @@ pub trait EventHandler: Debug { struct EventLoopHandler { f: Box>, receiver: Receiver, - event_loop: RootEventLoopWindowTarget, + event_loop: EventLoopWindowTarget, } impl Debug for EventLoopHandler { diff --git a/src/platform_impl/ios/mod.rs b/src/platform_impl/ios/mod.rs index 54ca1342f6..1b27a12fbd 100644 --- a/src/platform_impl/ios/mod.rs +++ b/src/platform_impl/ios/mod.rs @@ -70,7 +70,8 @@ use std::fmt; pub(crate) use self::{ event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, + ActiveEventLoop, EventLoop, EventLoopProxy, EventLoopWindowTarget, + PlatformSpecificEventLoopAttributes, }, monitor::{MonitorHandle, VideoModeHandle}, window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId}, diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 28197a1f78..87788b00ea 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -21,10 +21,7 @@ use crate::platform::x11::{WindowType as XWindowType, XlibErrorHook}; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{EventLoopError, ExternalError, NotSupportedError, OsError as RootOsError}, - event_loop::{ - AsyncRequestSerial, ControlFlow, DeviceEvents, EventLoopClosed, - EventLoopWindowTarget as RootELW, - }, + event_loop::{AsyncRequestSerial, ControlFlow, DeviceEvents, EventLoopClosed}, icon::Icon, keyboard::Key, platform::pump_events::PumpStatus, @@ -781,26 +778,26 @@ impl EventLoop { pub fn run(mut self, callback: F) -> Result<(), EventLoopError> where - F: FnMut(crate::event::Event, &RootELW), + F: FnMut(crate::event::Event, &EventLoopWindowTarget), { self.run_on_demand(callback) } pub fn run_on_demand(&mut self, callback: F) -> Result<(), EventLoopError> where - F: FnMut(crate::event::Event, &RootELW), + F: FnMut(crate::event::Event, &EventLoopWindowTarget), { x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_on_demand(callback)) } pub fn pump_events(&mut self, timeout: Option, callback: F) -> PumpStatus where - F: FnMut(crate::event::Event, &RootELW), + F: FnMut(crate::event::Event, &EventLoopWindowTarget), { x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_events(timeout, callback)) } - pub fn window_target(&self) -> &crate::event_loop::EventLoopWindowTarget { + pub fn window_target(&self) -> &EventLoopWindowTarget { x11_or_wayland!(match self; EventLoop(evlp) => evlp.window_target()) } } @@ -823,6 +820,8 @@ impl EventLoopProxy { } } +pub type ActiveEventLoop<'a> = &'a EventLoopWindowTarget; + pub enum EventLoopWindowTarget { #[cfg(wayland_platform)] Wayland(wayland::EventLoopWindowTarget), diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index f881cba3a9..e984f42361 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -2,7 +2,6 @@ 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::rc::Rc; @@ -19,9 +18,7 @@ use sctk::reexports::client::{Connection, QueueHandle}; use crate::dpi::LogicalSize; use crate::error::{EventLoopError, OsError as RootOsError}; use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent}; -use crate::event_loop::{ - ControlFlow, DeviceEvents, EventLoopWindowTarget as RootEventLoopWindowTarget, -}; +use crate::event_loop::{ControlFlow, DeviceEvents}; use crate::platform::pump_events::PumpStatus; use crate::platform_impl::platform::min_timeout; use crate::platform_impl::{EventLoopWindowTarget as PlatformEventLoopWindowTarget, OsError}; @@ -63,7 +60,7 @@ pub struct EventLoop { connection: Connection, /// Event loop window target. - window_target: RootEventLoopWindowTarget, + window_target: PlatformEventLoopWindowTarget, // XXX drop after everything else, just to be safe. /// Calloop's event loop. @@ -179,10 +176,7 @@ impl EventLoop { user_events_sender, pending_user_events, event_loop, - window_target: RootEventLoopWindowTarget { - p: PlatformEventLoopWindowTarget::Wayland(window_target), - _marker: PhantomData, - }, + window_target: PlatformEventLoopWindowTarget::Wayland(window_target), }; Ok(event_loop) @@ -190,7 +184,7 @@ impl EventLoop { pub fn run_on_demand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &PlatformEventLoopWindowTarget), { if self.loop_running { return Err(EventLoopError::AlreadyRunning); @@ -221,7 +215,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut callback: F) -> PumpStatus where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &PlatformEventLoopWindowTarget), { if !self.loop_running { self.loop_running = true; @@ -248,7 +242,7 @@ impl EventLoop { pub fn poll_events_with_timeout(&mut self, mut timeout: Option, mut callback: F) where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &PlatformEventLoopWindowTarget), { let cause = loop { let start = Instant::now(); @@ -324,7 +318,7 @@ impl EventLoop { fn single_iteration(&mut self, callback: &mut F, cause: StartCause) where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &PlatformEventLoopWindowTarget), { // NOTE currently just indented to simplify the diff @@ -529,12 +523,12 @@ impl EventLoop { } #[inline] - pub fn window_target(&self) -> &RootEventLoopWindowTarget { + pub fn window_target(&self) -> &PlatformEventLoopWindowTarget { &self.window_target } 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 { + let state = match &mut self.window_target { PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), #[cfg(x11_platform)] _ => unreachable!(), @@ -544,7 +538,7 @@ impl EventLoop { } fn loop_dispatch>>(&mut self, timeout: D) -> IOResult<()> { - let state = match &mut self.window_target.p { + let state = match &mut self.window_target { PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), #[cfg(feature = "x11")] _ => unreachable!(), @@ -557,7 +551,7 @@ impl EventLoop { } fn roundtrip(&mut self) -> Result { - let state = match &mut self.window_target.p { + let state = match &mut self.window_target { PlatformEventLoopWindowTarget::Wayland(window_target) => window_target.state.get_mut(), #[cfg(feature = "x11")] _ => unreachable!(), @@ -573,19 +567,19 @@ impl EventLoop { } 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() } fn set_exit_code(&self, code: i32) { - self.window_target.p.set_exit_code(code) + self.window_target.set_exit_code(code) } fn exit_code(&self) -> Option { - self.window_target.p.exit_code() + self.window_target.exit_code() } } diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index 08bc4e2d9e..ade65cec91 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -21,10 +21,10 @@ use super::{ Dnd, DndState, GenericEventCookie, ImeReceiver, ScrollOrientation, UnownedWindow, WindowId, }; +use crate::platform_impl::EventLoopWindowTarget as PlatformEventLoopWindowTarget; use crate::{ dpi::{PhysicalPosition, PhysicalSize}, event::{DeviceEvent, ElementState, Event, Ime, RawKeyEvent, TouchPhase, WindowEvent}, - event_loop::EventLoopWindowTarget as RootELW, keyboard::ModifiersState, platform_impl::platform::common::{keymap, xkb_state::KbdState}, }; @@ -44,7 +44,7 @@ pub(super) struct EventProcessor { pub(super) devices: RefCell>, pub(super) xi2ext: ExtensionInformation, pub(super) xkbext: ExtensionInformation, - pub(super) target: Rc, + pub(super) target: Rc, pub(super) kb_state: KbdState, // Number of touch events currently in progress pub(super) num_touch: u32, diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 81ebd0924e..32a0fead59 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -27,7 +27,6 @@ use std::{ collections::{HashMap, HashSet}, ffi::CStr, fmt, - marker::PhantomData, mem::MaybeUninit, ops::Deref, os::{ @@ -69,10 +68,11 @@ use super::{common::xkb_state::KbdState, ControlFlow, OsError}; use crate::{ error::{EventLoopError, OsError as RootOsError}, event::{Event, StartCause, WindowEvent}, - event_loop::{DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW}, + event_loop::{DeviceEvents, EventLoopClosed}, platform::pump_events::PumpStatus, platform_impl::{ platform::{min_timeout, WindowId}, + EventLoopWindowTarget as PlatformEventLoopWindowTarget, PlatformSpecificWindowBuilderAttributes, }, window::WindowAttributes, @@ -167,7 +167,7 @@ pub struct EventLoop { user_receiver: PeekableReceiver, activation_receiver: PeekableReceiver, user_sender: Sender, - target: Rc, + target: Rc, /// The current state of the event loop. state: EventLoopState, @@ -325,10 +325,7 @@ impl EventLoop { // Set initial device event filter. window_target.update_listen_device_events(true); - let target = Rc::new(RootELW { - p: super::EventLoopWindowTarget::X(window_target), - _marker: PhantomData, - }); + let target = Rc::new(PlatformEventLoopWindowTarget::X(window_target)); let event_processor = EventProcessor { target: target.clone(), @@ -396,13 +393,13 @@ impl EventLoop { } } - pub(crate) fn window_target(&self) -> &RootELW { + pub(crate) fn window_target(&self) -> &PlatformEventLoopWindowTarget { &self.target } pub fn run_on_demand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &PlatformEventLoopWindowTarget), { if self.loop_running { return Err(EventLoopError::AlreadyRunning); @@ -436,7 +433,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut callback: F) -> PumpStatus where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &PlatformEventLoopWindowTarget), { if !self.loop_running { self.loop_running = true; @@ -469,7 +466,7 @@ impl EventLoop { pub fn poll_events_with_timeout(&mut self, mut timeout: Option, mut callback: F) where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &PlatformEventLoopWindowTarget), { let start = Instant::now(); @@ -547,7 +544,7 @@ impl EventLoop { fn single_iteration(&mut self, callback: &mut F, cause: StartCause) where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &PlatformEventLoopWindowTarget), { callback(crate::event::Event::NewEvents(cause), &self.target); @@ -621,7 +618,7 @@ impl EventLoop { fn drain_events(&mut self, callback: &mut F) where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &PlatformEventLoopWindowTarget), { let target = &self.target; let mut xev = MaybeUninit::uninit(); @@ -644,19 +641,19 @@ impl EventLoop { } fn control_flow(&self) -> ControlFlow { - self.target.p.control_flow() + self.target.control_flow() } fn exiting(&self) -> bool { - self.target.p.exiting() + self.target.exiting() } fn set_exit_code(&self, code: i32) { - self.target.p.set_exit_code(code) + self.target.set_exit_code(code) } fn exit_code(&self) -> Option { - self.target.p.exit_code() + self.target.exit_code() } } @@ -672,8 +669,8 @@ impl AsRawFd for EventLoop { } } -pub(crate) fn get_xtarget(target: &RootELW) -> &EventLoopWindowTarget { - match target.p { +pub(crate) fn get_xtarget(target: &PlatformEventLoopWindowTarget) -> &EventLoopWindowTarget { + match target { super::EventLoopWindowTarget::X(ref target) => target, #[cfg(wayland_platform)] _ => unreachable!(), diff --git a/src/platform_impl/macos/app_delegate.rs b/src/platform_impl/macos/app_delegate.rs index c6d239e02f..75ad3a1393 100644 --- a/src/platform_impl/macos/app_delegate.rs +++ b/src/platform_impl/macos/app_delegate.rs @@ -16,10 +16,10 @@ use super::event_loop::{stop_app_immediately, PanicInfo}; use super::observer::{EventLoopWaker, RunLoop}; use super::util::Never; use super::window::WinitWindow; -use super::{menu, WindowId, DEVICE_ID}; +use super::{menu, EventLoopWindowTarget, WindowId, DEVICE_ID}; use crate::dpi::PhysicalSize; use crate::event::{DeviceEvent, Event, InnerSizeWriter, StartCause, WindowEvent}; -use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootWindowTarget}; +use crate::event_loop::ControlFlow; use crate::window::WindowId as RootWindowId; #[derive(Debug, Default)] @@ -161,7 +161,7 @@ impl ApplicationDelegate { pub unsafe fn set_callback( &self, callback: Weak>, - window_target: Rc, + window_target: Rc, receiver: Rc>, ) { *self.ivars().callback.borrow_mut() = Some(Box::new(EventLoopHandler { @@ -501,11 +501,11 @@ trait EventHandler: fmt::Debug { fn handle_user_events(&mut self); } -pub(super) type Callback = RefCell, &RootWindowTarget)>; +pub(super) type Callback = RefCell, &EventLoopWindowTarget)>; struct EventLoopHandler { callback: Weak>, - window_target: Rc, + window_target: Rc, receiver: Rc>, } @@ -521,7 +521,10 @@ impl fmt::Debug for EventLoopHandler { impl EventLoopHandler { fn with_callback(&mut self, f: F) where - F: FnOnce(&mut EventLoopHandler, RefMut<'_, dyn FnMut(Event, &RootWindowTarget)>), + F: FnOnce( + &mut EventLoopHandler, + RefMut<'_, dyn FnMut(Event, &EventLoopWindowTarget)>, + ), { // `NSApplication` and our app delegate are global state and so it's possible // that we could get a delegate callback after the application has exit an diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 3856123949..c39385291a 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -2,7 +2,6 @@ use std::{ any::Any, cell::{Cell, RefCell}, collections::VecDeque, - marker::PhantomData, mem, os::raw::c_void, panic::{catch_unwind, resume_unwind, AssertUnwindSafe, RefUnwindSafe, UnwindSafe}, @@ -38,9 +37,7 @@ use super::{ use crate::{ error::EventLoopError, event::Event, - event_loop::{ - ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootWindowTarget, - }, + event_loop::{ControlFlow, DeviceEvents, EventLoopClosed}, platform::{macos::ActivationPolicy, pump_events::PumpStatus}, }; @@ -78,6 +75,8 @@ pub struct EventLoopWindowTarget { pub(super) mtm: MainThreadMarker, } +pub type ActiveEventLoop<'a> = &'a EventLoopWindowTarget; + impl EventLoopWindowTarget { #[inline] pub fn available_monitors(&self) -> VecDeque { @@ -164,7 +163,7 @@ pub struct EventLoop { sender: mpsc::Sender, receiver: Rc>, - window_target: Rc, + window_target: Rc, panic_info: Rc, /// We make sure that the callback closure is dropped during a panic @@ -232,22 +231,19 @@ impl EventLoop { delegate: delegate.clone(), sender, receiver: Rc::new(receiver), - window_target: Rc::new(RootWindowTarget { - p: EventLoopWindowTarget { delegate, mtm }, - _marker: PhantomData, - }), + window_target: Rc::new(EventLoopWindowTarget { delegate, mtm }), panic_info, _callback: None, }) } - pub fn window_target(&self) -> &RootWindowTarget { + pub fn window_target(&self) -> &EventLoopWindowTarget { &self.window_target } pub fn run(mut self, callback: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootWindowTarget), + F: FnMut(Event, &EventLoopWindowTarget), { self.run_on_demand(callback) } @@ -258,7 +254,7 @@ impl EventLoop { // redundant wake ups. pub fn run_on_demand(&mut self, callback: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootWindowTarget), + F: FnMut(Event, &EventLoopWindowTarget), { if self.delegate.is_running() { return Err(EventLoopError::AlreadyRunning); @@ -275,8 +271,8 @@ impl EventLoop { let callback = unsafe { mem::transmute::< - Rc, &RootWindowTarget)>>, - Rc, &RootWindowTarget)>>, + Rc, &EventLoopWindowTarget)>>, + Rc, &EventLoopWindowTarget)>>, >(Rc::new(RefCell::new(callback))) }; @@ -342,7 +338,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, callback: F) -> PumpStatus where - F: FnMut(Event, &RootWindowTarget), + F: FnMut(Event, &EventLoopWindowTarget), { // # Safety // We are erasing the lifetime of the application callback here so that we @@ -355,8 +351,8 @@ impl EventLoop { let callback = unsafe { mem::transmute::< - Rc, &RootWindowTarget)>>, - Rc, &RootWindowTarget)>>, + Rc, &EventLoopWindowTarget)>>, + Rc, &EventLoopWindowTarget)>>, >(Rc::new(RefCell::new(callback))) }; diff --git a/src/platform_impl/macos/mod.rs b/src/platform_impl/macos/mod.rs index 65bea82f13..ed34edb556 100644 --- a/src/platform_impl/macos/mod.rs +++ b/src/platform_impl/macos/mod.rs @@ -19,7 +19,8 @@ use std::fmt; pub(crate) use self::{ event::{physicalkey_to_scancode, scancode_to_physicalkey, KeyEventExtra}, event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, + ActiveEventLoop, EventLoop, EventLoopProxy, EventLoopWindowTarget, + PlatformSpecificEventLoopAttributes, }, monitor::{MonitorHandle, VideoModeHandle}, window::WindowId, diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index 62c85d19bc..b87ee5dc23 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -1,7 +1,6 @@ use std::{ cell::Cell, collections::VecDeque, - marker::PhantomData, mem, slice, sync::{mpsc, Arc, Mutex}, time::Instant, @@ -16,7 +15,7 @@ use orbclient::{ use crate::{ error::EventLoopError, event::{self, Ime, Modifiers, StartCause}, - event_loop::{self, ControlFlow, DeviceEvents}, + event_loop::{ControlFlow, DeviceEvents, EventLoopClosed}, keyboard::{ Key, KeyCode, KeyLocation, ModifiersKeys, ModifiersState, NativeKey, NativeKeyCode, PhysicalKey, @@ -274,7 +273,7 @@ impl EventState { pub struct EventLoop { windows: Vec<(Arc, EventState)>, - window_target: event_loop::EventLoopWindowTarget, + window_target: EventLoopWindowTarget, user_events_sender: mpsc::Sender, user_events_receiver: mpsc::Receiver, } @@ -306,17 +305,14 @@ impl EventLoop { Ok(Self { windows: Vec::new(), - window_target: event_loop::EventLoopWindowTarget { - p: EventLoopWindowTarget { - 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, - }, - _marker: PhantomData, + window_target: EventLoopWindowTarget { + 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, @@ -466,10 +462,10 @@ impl EventLoop { pub fn run(mut self, mut event_handler_inner: F) -> Result<(), EventLoopError> where - F: FnMut(event::Event, &event_loop::EventLoopWindowTarget), + F: FnMut(event::Event, &EventLoopWindowTarget), { let mut event_handler = - move |event: event::Event, window_target: &event_loop::EventLoopWindowTarget| { + move |event: event::Event, window_target: &EventLoopWindowTarget| { event_handler_inner(event, window_target); }; @@ -484,7 +480,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 { @@ -518,7 +514,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() } { event_handler( @@ -573,7 +569,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); } @@ -589,7 +585,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() } { event_handler( @@ -603,11 +599,11 @@ impl EventLoop { event_handler(event::Event::AboutToWait, &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; @@ -621,7 +617,6 @@ impl EventLoop { let timeout_socket = TimeSocket::open().unwrap(); self.window_target - .p .event_socket .write(&syscall::Event { id: timeout_socket.0.fd, @@ -649,7 +644,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 { @@ -676,14 +671,14 @@ impl EventLoop { Ok(()) } - pub fn window_target(&self) -> &event_loop::EventLoopWindowTarget { + pub fn window_target(&self) -> &EventLoopWindowTarget { &self.window_target } pub fn create_proxy(&self) -> EventLoopProxy { EventLoopProxy { user_events_sender: self.user_events_sender.clone(), - wake_socket: self.window_target.p.wake_socket.clone(), + wake_socket: self.window_target.wake_socket.clone(), } } } @@ -694,10 +689,10 @@ pub struct EventLoopProxy { } impl EventLoopProxy { - pub fn send_event(&self, event: T) -> Result<(), event_loop::EventLoopClosed> { + pub fn send_event(&self, event: T) -> Result<(), EventLoopClosed> { self.user_events_sender .send(event) - .map_err(|mpsc::SendError(x)| event_loop::EventLoopClosed(x))?; + .map_err(|mpsc::SendError(x)| EventLoopClosed(x))?; self.wake_socket.wake().unwrap(); @@ -716,6 +711,8 @@ impl Clone for EventLoopProxy { impl Unpin for EventLoopProxy {} +pub type ActiveEventLoop<'a> = &'a EventLoopWindowTarget; + pub struct EventLoopWindowTarget { control_flow: Cell, exit: Cell, diff --git a/src/platform_impl/orbital/mod.rs b/src/platform_impl/orbital/mod.rs index 937e9c12b6..64f9cd471f 100644 --- a/src/platform_impl/orbital/mod.rs +++ b/src/platform_impl/orbital/mod.rs @@ -6,7 +6,7 @@ use std::sync::Arc; use crate::dpi::{PhysicalPosition, PhysicalSize}; -pub use self::event_loop::{EventLoop, EventLoopProxy, EventLoopWindowTarget}; +pub use self::event_loop::{ActiveEventLoop, EventLoop, EventLoopProxy, EventLoopWindowTarget}; mod event_loop; pub use self::window::Window; diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index 79e3abf21e..86f9e8efa5 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -1,9 +1,7 @@ -use std::marker::PhantomData; use std::sync::mpsc::{self, Receiver, Sender}; use crate::error::EventLoopError; use crate::event::Event; -use crate::event_loop::EventLoopWindowTarget as RootEventLoopWindowTarget; use super::{backend, device, window}; @@ -15,8 +13,10 @@ mod window_target; pub use proxy::EventLoopProxy; pub use window_target::EventLoopWindowTarget; +pub type ActiveEventLoop<'a> = &'a EventLoopWindowTarget; + pub struct EventLoop { - elw: RootEventLoopWindowTarget, + elw: EventLoopWindowTarget, user_event_sender: Sender, user_event_receiver: Receiver, } @@ -27,12 +27,8 @@ pub(crate) struct PlatformSpecificEventLoopAttributes {} impl EventLoop { pub(crate) fn new(_: &PlatformSpecificEventLoopAttributes) -> Result { let (user_event_sender, user_event_receiver) = mpsc::channel(); - let elw = RootEventLoopWindowTarget { - p: EventLoopWindowTarget::new(), - _marker: PhantomData, - }; Ok(EventLoop { - elw, + elw: EventLoopWindowTarget::new(), user_event_sender, user_event_receiver, }) @@ -40,12 +36,9 @@ impl EventLoop { pub fn run(self, mut event_handler: F) -> ! where - F: FnMut(Event, &RootEventLoopWindowTarget), + F: FnMut(Event, &EventLoopWindowTarget), { - let target = RootEventLoopWindowTarget { - p: self.elw.p.clone(), - _marker: PhantomData, - }; + let target = self.elw.clone(); // SAFETY: Don't use `move` to make sure we leak the `event_handler` and `target`. let handler: Box)> = Box::new(|event| { @@ -64,7 +57,7 @@ impl EventLoop { // because this function will never return and all resources not cleaned up by the point we // `throw` will leak, making this actually `'static`. let handler = unsafe { std::mem::transmute(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 '!' @@ -77,14 +70,11 @@ impl EventLoop { pub fn spawn(self, mut event_handler: F) where - F: 'static + FnMut(Event, &RootEventLoopWindowTarget), + F: 'static + FnMut(Event, &EventLoopWindowTarget), { - let target = RootEventLoopWindowTarget { - p: self.elw.p.clone(), - _marker: PhantomData, - }; + let target = self.elw.clone(); - self.elw.p.run( + self.elw.run( Box::new(move |event| { let event = match event.map_nonuser_event() { Ok(event) => event, @@ -102,10 +92,10 @@ impl EventLoop { } pub fn create_proxy(&self) -> EventLoopProxy { - EventLoopProxy::new(self.elw.p.waker(), self.user_event_sender.clone()) + EventLoopProxy::new(self.elw.waker(), self.user_event_sender.clone()) } - pub fn window_target(&self) -> &RootEventLoopWindowTarget { + pub fn window_target(&self) -> &EventLoopWindowTarget { &self.elw } } diff --git a/src/platform_impl/web/event_loop/runner.rs b/src/platform_impl/web/event_loop/runner.rs index f7932ff76e..4cda651377 100644 --- a/src/platform_impl/web/event_loop/runner.rs +++ b/src/platform_impl/web/event_loop/runner.rs @@ -215,7 +215,7 @@ impl Shared { // Set the event callback to use for the event loop runner // This the event callback is a fairly thin layer over the user-provided callback that closes - // over a RootEventLoopWindowTarget reference + // over a EventLoopWindowTarget reference pub fn set_listener(&self, event_handler: Box) { { let mut runner = self.0.runner.borrow_mut(); diff --git a/src/platform_impl/web/event_loop/window_target.rs b/src/platform_impl/web/event_loop/window_target.rs index 260b592e5c..c5a83e50c6 100644 --- a/src/platform_impl/web/event_loop/window_target.rs +++ b/src/platform_impl/web/event_loop/window_target.rs @@ -49,7 +49,7 @@ pub struct EventLoopWindowTarget { } impl EventLoopWindowTarget { - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self { runner: runner::Shared::new(), modifiers: ModifiersShared::default(), diff --git a/src/platform_impl/web/mod.rs b/src/platform_impl/web/mod.rs index 3d23351efe..9aeb9e937e 100644 --- a/src/platform_impl/web/mod.rs +++ b/src/platform_impl/web/mod.rs @@ -33,7 +33,8 @@ mod backend; pub use self::device::DeviceId; pub use self::error::OsError; pub(crate) use self::event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, + ActiveEventLoop, EventLoop, EventLoopProxy, EventLoopWindowTarget, + PlatformSpecificEventLoopAttributes, }; pub use self::monitor::{MonitorHandle, VideoModeHandle}; pub use self::window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId}; diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index ef5da8baaa..8915006a15 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -6,7 +6,6 @@ use std::{ cell::Cell, collections::VecDeque, ffi::c_void, - marker::PhantomData, mem, panic, ptr, rc::Rc, sync::{ @@ -74,7 +73,7 @@ use crate::{ DeviceEvent, Event, Force, Ime, InnerSizeWriter, RawKeyEvent, Touch, TouchPhase, WindowEvent, }, - event_loop::{ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW}, + event_loop::{ControlFlow, DeviceEvents, EventLoopClosed}, keyboard::ModifiersState, platform::pump_events::PumpStatus, platform_impl::platform::{ @@ -158,7 +157,7 @@ pub(crate) enum ProcResult { pub struct EventLoop { user_event_sender: Sender, user_event_receiver: Receiver, - window_target: RootELW, + window_target: EventLoopWindowTarget, msg_hook: Option bool + 'static>>, } @@ -178,6 +177,8 @@ impl Default for PlatformSpecificEventLoopAttributes { } } +pub type ActiveEventLoop<'a> = &'a EventLoopWindowTarget; + pub struct EventLoopWindowTarget { thread_id: u32, thread_msg_target: HWND, @@ -217,35 +218,32 @@ impl EventLoop { Ok(EventLoop { user_event_sender, user_event_receiver, - window_target: RootELW { - p: EventLoopWindowTarget { - thread_id, - thread_msg_target, - runner_shared, - }, - _marker: PhantomData, + window_target: EventLoopWindowTarget { + thread_id, + thread_msg_target, + runner_shared, }, msg_hook: attributes.msg_hook.take(), }) } - pub fn window_target(&self) -> &RootELW { + pub fn window_target(&self) -> &EventLoopWindowTarget { &self.window_target } pub fn run(mut self, event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &EventLoopWindowTarget), { self.run_on_demand(event_handler) } pub fn run_on_demand(&mut self, mut event_handler: F) -> Result<(), EventLoopError> where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &EventLoopWindowTarget), { { - let runner = &self.window_target.p.runner_shared; + let runner = &self.window_target.runner_shared; if runner.state() != RunnerState::Uninitialized { return Err(EventLoopError::AlreadyRunning); } @@ -290,7 +288,7 @@ impl EventLoop { } }; - let runner = &self.window_target.p.runner_shared; + let runner = &self.window_target.runner_shared; runner.loop_destroyed(); // # Safety @@ -307,10 +305,10 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut event_handler: F) -> PumpStatus where - F: FnMut(Event, &RootELW), + F: FnMut(Event, &EventLoopWindowTarget), { { - 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; @@ -343,7 +341,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(); @@ -405,7 +403,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 @@ -467,7 +465,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 @@ -517,13 +515,13 @@ impl EventLoop { pub fn create_proxy(&self) -> EventLoopProxy { EventLoopProxy { - target_window: self.window_target.p.thread_msg_target, + target_window: self.window_target.thread_msg_target, event_send: self.user_event_sender.clone(), } } fn exit_code(&self) -> Option { - self.window_target.p.exit_code() + self.window_target.exit_code() } } @@ -671,7 +669,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 7cce3a76c8..ccac89eb38 100644 --- a/src/platform_impl/windows/mod.rs +++ b/src/platform_impl/windows/mod.rs @@ -8,7 +8,8 @@ use windows_sys::Win32::{ pub(crate) use self::{ event_loop::{ - EventLoop, EventLoopProxy, EventLoopWindowTarget, PlatformSpecificEventLoopAttributes, + ActiveEventLoop, EventLoop, EventLoopProxy, EventLoopWindowTarget, + PlatformSpecificEventLoopAttributes, }, icon::{SelectedCursor, WinIcon}, keyboard::{physicalkey_to_scancode, scancode_to_physicalkey}, diff --git a/src/window.rs b/src/window.rs index a0d55bb01f..f4d3c1e1c3 100644 --- a/src/window.rs +++ b/src/window.rs @@ -4,7 +4,7 @@ use std::fmt; use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error::{ExternalError, NotSupportedError, OsError}, - event_loop::EventLoopWindowTarget, + event_loop::MaybeActiveEventLoop, monitor::{MonitorHandle, VideoModeHandle}, platform_impl, }; @@ -531,9 +531,12 @@ impl WindowBuilder { /// - **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 build(self, window_target: &EventLoopWindowTarget) -> Result { + pub fn build<'a>( + self, + mut event_loop: impl MaybeActiveEventLoop<'a>, + ) -> Result { let window = - platform_impl::Window::new(&window_target.p, self.window, self.platform_specific)?; + platform_impl::Window::new(event_loop.__inner(), self.window, self.platform_specific)?; window.maybe_queue_on_main(|w| w.request_redraw()); Ok(Window { window }) } @@ -555,7 +558,7 @@ impl Window { /// /// [`WindowBuilder::new().build(event_loop)`]: WindowBuilder::build #[inline] - pub fn new(event_loop: &EventLoopWindowTarget) -> Result { + pub fn new<'a>(event_loop: impl MaybeActiveEventLoop<'a>) -> Result { let builder = WindowBuilder::new(); builder.build(event_loop) } @@ -1515,9 +1518,9 @@ impl Window { /// Returns the list of all the monitors available on the system. /// - /// This is the same as [`EventLoopWindowTarget::available_monitors`], and is provided for convenience. + /// This is the same as [`ActiveEventLoop::available_monitors`], and is provided for convenience. /// - /// [`EventLoopWindowTarget::available_monitors`]: crate::event_loop::EventLoopWindowTarget::available_monitors + /// [`ActiveEventLoop::available_monitors`]: crate::event_loop::ActiveEventLoop::available_monitors #[inline] pub fn available_monitors(&self) -> impl Iterator { self.window.maybe_wait_on_main(|w| { @@ -1531,13 +1534,13 @@ impl Window { /// /// Returns `None` if it can't identify any monitor as a primary one. /// - /// This is the same as [`EventLoopWindowTarget::primary_monitor`], and is provided for convenience. + /// This is the same as [`ActiveEventLoop::primary_monitor`], and is provided for convenience. /// /// ## Platform-specific /// /// **Wayland / Web:** Always returns `None`. /// - /// [`EventLoopWindowTarget::primary_monitor`]: crate::event_loop::EventLoopWindowTarget::primary_monitor + /// [`ActiveEventLoop::primary_monitor`]: crate::event_loop::ActiveEventLoop::primary_monitor #[inline] pub fn primary_monitor(&self) -> Option { self.window