From 9ac3259a79f996da63d91d5ee4b7233d14687b85 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Mon, 31 Jul 2023 00:39:01 +0400 Subject: [PATCH] Remove `lifetime` from the `Event` Lifetimes don't work nicely when dealing with multithreaded environments in the current design of the existing winit's event handling model, so remove it in favor of `InnerSizeWriter` fences passed to client, so they could try to update the size. Fixes #1387. --- CHANGELOG.md | 2 + examples/child_window.rs | 2 +- examples/multithreaded.rs | 4 +- src/error.rs | 3 + src/event.rs | 302 +++--------------- src/event_loop.rs | 2 +- src/platform/pump_events.rs | 12 +- src/platform/run_ondemand.rs | 12 +- src/platform/web.rs | 12 +- src/platform_impl/android/mod.rs | 30 +- src/platform_impl/ios/app_state.rs | 13 +- src/platform_impl/ios/event_loop.rs | 10 +- src/platform_impl/ios/mod.rs | 2 +- src/platform_impl/linux/mod.rs | 12 +- .../linux/wayland/event_loop/mod.rs | 20 +- .../linux/wayland/event_loop/sink.rs | 6 +- .../linux/x11/event_processor.rs | 34 +- src/platform_impl/linux/x11/mod.rs | 10 +- src/platform_impl/macos/app_state.rs | 25 +- src/platform_impl/macos/event.rs | 2 +- src/platform_impl/macos/event_loop.rs | 14 +- src/platform_impl/macos/view.rs | 2 +- src/platform_impl/macos/window_delegate.rs | 2 +- src/platform_impl/orbital/event_loop.rs | 6 +- src/platform_impl/web/event_loop/mod.rs | 6 +- src/platform_impl/web/event_loop/runner.rs | 8 +- src/platform_impl/web/mod.rs | 2 +- src/platform_impl/web/web_sys/canvas.rs | 52 +-- src/platform_impl/windows/drop_handler.rs | 6 +- src/platform_impl/windows/event_loop.rs | 23 +- .../windows/event_loop/runner.rs | 45 ++- 31 files changed, 252 insertions(+), 429 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3099b6d..576d63a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ And please only add new entries to the top of this list, right below the `# Unre # Unreleased - On Windows, added `WindowBuilderExtWindows::with_class_name` to customize the internal class name. +- **Breaking:** Remove lifetime parameter from `Event` and `WindowEvent`. +- **Breaking:** `ScaleFactorChanged` now contains a writer instead of a reference to update inner size. - On iOS, always wake the event loop when transitioning from `ControlFlow::Poll` to `ControlFlow::Poll`. - **Breaking:** `ActivationTokenDone` event which could be requested with the new `startup_notify` module, see its docs for more. - On Wayland, make double clicking and moving the CSD frame more reliable. diff --git a/examples/child_window.rs b/examples/child_window.rs index 65135b79..9d3bc053 100644 --- a/examples/child_window.rs +++ b/examples/child_window.rs @@ -46,7 +46,7 @@ fn main() -> Result<(), impl std::error::Error> { println!("parent window: {parent_window:?})"); - event_loop.run(move |event: Event<'_, ()>, event_loop, control_flow| { + event_loop.run(move |event: Event<()>, event_loop, control_flow| { *control_flow = ControlFlow::Wait; if let Event::WindowEvent { event, window_id } = event { diff --git a/examples/multithreaded.rs b/examples/multithreaded.rs index bd9f9004..c1557821 100644 --- a/examples/multithreaded.rs +++ b/examples/multithreaded.rs @@ -195,9 +195,7 @@ fn main() -> Result<(), impl std::error::Error> { } _ => { if let Some(tx) = window_senders.get(&window_id) { - if let Some(event) = event.to_static() { - tx.send(event).unwrap(); - } + tx.send(event).unwrap(); } } }, diff --git a/src/error.rs b/src/error.rs index 0a1cda9e..7324742d 100644 --- a/src/error.rs +++ b/src/error.rs @@ -8,6 +8,8 @@ use crate::platform_impl; pub enum ExternalError { /// The operation is not supported by the backend. NotSupported(NotSupportedError), + /// The operation was ignored. + Ignored, /// The OS cannot perform the operation. Os(OsError), } @@ -74,6 +76,7 @@ impl fmt::Display for ExternalError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { match self { ExternalError::NotSupported(e) => e.fmt(f), + ExternalError::Ignored => write!(f, "Operation was ignored"), ExternalError::Os(e) => e.fmt(f), } } diff --git a/src/event.rs b/src/event.rs index 06bf3a0b..e0afca44 100644 --- a/src/event.rs +++ b/src/event.rs @@ -33,13 +33,16 @@ //! //! [`EventLoop::run(...)`]: crate::event_loop::EventLoop::run //! [`ControlFlow::WaitUntil`]: crate::event_loop::ControlFlow::WaitUntil -use smol_str::SmolStr; use std::path::PathBuf; +use std::sync::{Mutex, Weak}; #[cfg(not(wasm_platform))] use std::time::Instant; + +use smol_str::SmolStr; #[cfg(wasm_platform)] use web_time::Instant; +use crate::error::ExternalError; #[cfg(doc)] use crate::window::Window; use crate::{ @@ -53,8 +56,8 @@ use crate::{ /// Describes a generic event. /// /// See the module-level docs for more information on the event loop manages each event. -#[derive(Debug, PartialEq)] -pub enum Event<'a, T: 'static> { +#[derive(Debug, Clone, PartialEq)] +pub enum Event { /// Emitted when new events arrive from the OS to be processed. /// /// This event type is useful as a place to put code that should be done before you start @@ -66,7 +69,7 @@ pub enum Event<'a, T: 'static> { /// Emitted when the OS sends an event to a winit window. WindowEvent { window_id: WindowId, - event: WindowEvent<'a>, + event: WindowEvent, }, /// Emitted when the OS sends an event to a device. @@ -237,32 +240,9 @@ pub enum Event<'a, T: 'static> { LoopExiting, } -impl Clone for Event<'static, T> { - fn clone(&self) -> Self { - use self::Event::*; - match self { - WindowEvent { window_id, event } => WindowEvent { - window_id: *window_id, - event: event.clone(), - }, - UserEvent(event) => UserEvent(event.clone()), - DeviceEvent { device_id, event } => DeviceEvent { - device_id: *device_id, - event: event.clone(), - }, - NewEvents(cause) => NewEvents(*cause), - AboutToWait => AboutToWait, - RedrawRequested(wid) => RedrawRequested(*wid), - LoopExiting => LoopExiting, - Suspended => Suspended, - Resumed => Resumed, - } - } -} - -impl<'a, T> Event<'a, T> { +impl Event { #[allow(clippy::result_large_err)] - pub fn map_nonuser_event(self) -> Result, Event<'a, T>> { + pub fn map_nonuser_event(self) -> Result, Event> { use self::Event::*; match self { UserEvent(_) => Err(self), @@ -276,25 +256,6 @@ impl<'a, T> Event<'a, T> { Resumed => Ok(Resumed), } } - - /// If the event doesn't contain a reference, turn it into an event with a `'static` lifetime. - /// Otherwise, return `None`. - pub fn to_static(self) -> Option> { - use self::Event::*; - match self { - WindowEvent { window_id, event } => event - .to_static() - .map(|event| WindowEvent { window_id, event }), - UserEvent(event) => Some(UserEvent(event)), - DeviceEvent { device_id, event } => Some(DeviceEvent { device_id, event }), - NewEvents(cause) => Some(NewEvents(cause)), - AboutToWait => Some(AboutToWait), - RedrawRequested(wid) => Some(RedrawRequested(wid)), - LoopExiting => Some(LoopExiting), - Suspended => Some(Suspended), - Resumed => Some(Resumed), - } - } } /// Describes the reason the event loop is resuming. @@ -328,8 +289,8 @@ pub enum StartCause { } /// Describes an event from a [`Window`]. -#[derive(Debug, PartialEq)] -pub enum WindowEvent<'a> { +#[derive(Debug, Clone, PartialEq)] +pub enum WindowEvent { /// The activation token was delivered back and now could be used. /// #[cfg_attr( @@ -563,7 +524,10 @@ pub enum WindowEvent<'a> { /// For more information about DPI in general, see the [`dpi`](crate::dpi) module. ScaleFactorChanged { scale_factor: f64, - new_inner_size: &'a mut PhysicalSize, + /// Handle to update inner size during scale changes. + /// + /// See [`InnerSizeWriter`] docs for more details. + inner_size_writer: InnerSizeWriter, }, /// The system window theme has changed. @@ -592,209 +556,6 @@ pub enum WindowEvent<'a> { Occluded(bool), } -impl Clone for WindowEvent<'static> { - fn clone(&self) -> Self { - use self::WindowEvent::*; - return match self { - ActivationTokenDone { serial, token } => ActivationTokenDone { - serial: *serial, - token: token.clone(), - }, - Resized(size) => Resized(*size), - Moved(pos) => Moved(*pos), - CloseRequested => CloseRequested, - Destroyed => Destroyed, - DroppedFile(file) => DroppedFile(file.clone()), - HoveredFile(file) => HoveredFile(file.clone()), - HoveredFileCancelled => HoveredFileCancelled, - Focused(f) => Focused(*f), - KeyboardInput { - device_id, - event, - is_synthetic, - } => KeyboardInput { - device_id: *device_id, - event: event.clone(), - is_synthetic: *is_synthetic, - }, - Ime(preedit_state) => Ime(preedit_state.clone()), - ModifiersChanged(modifiers) => ModifiersChanged(*modifiers), - CursorMoved { - device_id, - position, - } => CursorMoved { - device_id: *device_id, - position: *position, - }, - CursorEntered { device_id } => CursorEntered { - device_id: *device_id, - }, - CursorLeft { device_id } => CursorLeft { - device_id: *device_id, - }, - MouseWheel { - device_id, - delta, - phase, - } => MouseWheel { - device_id: *device_id, - delta: *delta, - phase: *phase, - }, - MouseInput { - device_id, - state, - button, - } => MouseInput { - device_id: *device_id, - state: *state, - button: *button, - }, - TouchpadMagnify { - device_id, - delta, - phase, - } => TouchpadMagnify { - device_id: *device_id, - delta: *delta, - phase: *phase, - }, - SmartMagnify { device_id } => SmartMagnify { - device_id: *device_id, - }, - TouchpadRotate { - device_id, - delta, - phase, - } => TouchpadRotate { - device_id: *device_id, - delta: *delta, - phase: *phase, - }, - TouchpadPressure { - device_id, - pressure, - stage, - } => TouchpadPressure { - device_id: *device_id, - pressure: *pressure, - stage: *stage, - }, - AxisMotion { - device_id, - axis, - value, - } => AxisMotion { - device_id: *device_id, - axis: *axis, - value: *value, - }, - Touch(touch) => Touch(*touch), - ThemeChanged(theme) => ThemeChanged(*theme), - ScaleFactorChanged { .. } => { - unreachable!("Static event can't be about scale factor changing") - } - Occluded(occluded) => Occluded(*occluded), - }; - } -} - -impl<'a> WindowEvent<'a> { - pub fn to_static(self) -> Option> { - use self::WindowEvent::*; - match self { - ActivationTokenDone { serial, token } => Some(ActivationTokenDone { serial, token }), - Resized(size) => Some(Resized(size)), - Moved(position) => Some(Moved(position)), - CloseRequested => Some(CloseRequested), - Destroyed => Some(Destroyed), - DroppedFile(file) => Some(DroppedFile(file)), - HoveredFile(file) => Some(HoveredFile(file)), - HoveredFileCancelled => Some(HoveredFileCancelled), - Focused(focused) => Some(Focused(focused)), - KeyboardInput { - device_id, - event, - is_synthetic, - } => Some(KeyboardInput { - device_id, - event, - is_synthetic, - }), - ModifiersChanged(modifers) => Some(ModifiersChanged(modifers)), - Ime(event) => Some(Ime(event)), - CursorMoved { - device_id, - position, - } => Some(CursorMoved { - device_id, - position, - }), - CursorEntered { device_id } => Some(CursorEntered { device_id }), - CursorLeft { device_id } => Some(CursorLeft { device_id }), - MouseWheel { - device_id, - delta, - phase, - } => Some(MouseWheel { - device_id, - delta, - phase, - }), - MouseInput { - device_id, - state, - button, - } => Some(MouseInput { - device_id, - state, - button, - }), - TouchpadMagnify { - device_id, - delta, - phase, - } => Some(TouchpadMagnify { - device_id, - delta, - phase, - }), - SmartMagnify { device_id } => Some(SmartMagnify { device_id }), - TouchpadRotate { - device_id, - delta, - phase, - } => Some(TouchpadRotate { - device_id, - delta, - phase, - }), - TouchpadPressure { - device_id, - pressure, - stage, - } => Some(TouchpadPressure { - device_id, - pressure, - stage, - }), - AxisMotion { - device_id, - axis, - value, - } => Some(AxisMotion { - device_id, - axis, - value, - }), - Touch(touch) => Some(Touch(touch)), - ThemeChanged(theme) => Some(ThemeChanged(theme)), - ScaleFactorChanged { .. } => None, - Occluded(occluded) => Some(Occluded(occluded)), - } - } -} - /// Identifier of an input device. /// /// Whenever you receive an event arising from a particular input device, this event contains a `DeviceId` which @@ -1301,3 +1062,36 @@ pub enum MouseScrollDelta { /// and move the content right and down (to reveal more things left and up). PixelDelta(PhysicalPosition), } + +/// Handle to synchroniously change the size of the window from the +/// [`WindowEvent`]. +#[derive(Debug, Clone)] +pub struct InnerSizeWriter { + pub(crate) new_inner_size: Weak>>, +} + +impl InnerSizeWriter { + #[cfg(not(orbital_platform))] + pub(crate) fn new(new_inner_size: Weak>>) -> Self { + Self { new_inner_size } + } + + /// Try to request inner size which will be set synchroniously on the window. + pub fn request_inner_size( + &mut self, + new_inner_size: PhysicalSize, + ) -> Result<(), ExternalError> { + if let Some(inner) = self.new_inner_size.upgrade() { + *inner.lock().unwrap() = new_inner_size; + Ok(()) + } else { + Err(ExternalError::Ignored) + } + } +} + +impl PartialEq for InnerSizeWriter { + fn eq(&self, other: &Self) -> bool { + self.new_inner_size.as_ptr() == other.new_inner_size.as_ptr() + } +} diff --git a/src/event_loop.rs b/src/event_loop.rs index f497c933..881a0845 100644 --- a/src/event_loop.rs +++ b/src/event_loop.rs @@ -314,7 +314,7 @@ impl EventLoop { #[inline] pub fn run(self, event_handler: F) -> Result<(), RunLoopError> where - F: 'static + FnMut(Event<'_, T>, &EventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow), { self.event_loop.run(event_handler) } diff --git a/src/platform/pump_events.rs b/src/platform/pump_events.rs index 3851b2cd..d9bdf8f4 100644 --- a/src/platform/pump_events.rs +++ b/src/platform/pump_events.rs @@ -174,11 +174,7 @@ pub trait EventLoopExtPumpEvents { /// callback. fn pump_events(&mut self, timeout: Option, event_handler: F) -> PumpStatus where - F: FnMut( - Event<'_, Self::UserEvent>, - &EventLoopWindowTarget, - &mut ControlFlow, - ); + F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow); } impl EventLoopExtPumpEvents for EventLoop { @@ -186,11 +182,7 @@ impl EventLoopExtPumpEvents for EventLoop { fn pump_events(&mut self, timeout: Option, event_handler: F) -> PumpStatus where - F: FnMut( - Event<'_, Self::UserEvent>, - &EventLoopWindowTarget, - &mut ControlFlow, - ), + F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow), { self.event_loop.pump_events(timeout, event_handler) } diff --git a/src/platform/run_ondemand.rs b/src/platform/run_ondemand.rs index 9f4871db..c1e36326 100644 --- a/src/platform/run_ondemand.rs +++ b/src/platform/run_ondemand.rs @@ -59,11 +59,7 @@ pub trait EventLoopExtRunOnDemand { /// - **iOS:** It's not possible to stop and start an `NSApplication` repeatedly on iOS. fn run_ondemand(&mut self, event_handler: F) -> Result<(), RunLoopError> where - F: FnMut( - Event<'_, Self::UserEvent>, - &EventLoopWindowTarget, - &mut ControlFlow, - ); + F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow); } impl EventLoopExtRunOnDemand for EventLoop { @@ -71,11 +67,7 @@ impl EventLoopExtRunOnDemand for EventLoop { fn run_ondemand(&mut self, event_handler: F) -> Result<(), RunLoopError> where - F: FnMut( - Event<'_, Self::UserEvent>, - &EventLoopWindowTarget, - &mut ControlFlow, - ), + F: FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow), { self.event_loop.run_ondemand(event_handler) } diff --git a/src/platform/web.rs b/src/platform/web.rs index 9aef7df6..7a1bb66f 100644 --- a/src/platform/web.rs +++ b/src/platform/web.rs @@ -116,11 +116,7 @@ pub trait EventLoopExtWebSys { fn spawn(self, event_handler: F) where F: 'static - + FnMut( - Event<'_, Self::UserEvent>, - &EventLoopWindowTarget, - &mut ControlFlow, - ); + + FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow); } impl EventLoopExtWebSys for EventLoop { @@ -129,11 +125,7 @@ impl EventLoopExtWebSys for EventLoop { fn spawn(self, event_handler: F) where F: 'static - + FnMut( - Event<'_, Self::UserEvent>, - &EventLoopWindowTarget, - &mut ControlFlow, - ), + + FnMut(Event, &EventLoopWindowTarget, &mut ControlFlow), { self.event_loop.spawn(event_handler) } diff --git a/src/platform_impl/android/mod.rs b/src/platform_impl/android/mod.rs index e610dd26..6d8f1e18 100644 --- a/src/platform_impl/android/mod.rs +++ b/src/platform_impl/android/mod.rs @@ -5,7 +5,7 @@ use std::{ hash::Hash, sync::{ atomic::{AtomicBool, Ordering}, - mpsc, Arc, RwLock, + mpsc, Arc, Mutex, RwLock, }, time::{Duration, Instant}, }; @@ -22,7 +22,7 @@ use raw_window_handle::{ use crate::{ dpi::{PhysicalPosition, PhysicalSize, Position, Size}, error, - event::{self, StartCause}, + event::{self, InnerSizeWriter, StartCause}, event_loop::{self, ControlFlow, EventLoopWindowTarget as RootELW}, keyboard::NativeKey, platform::pump_events::PumpStatus, @@ -169,12 +169,12 @@ impl Default for PlatformSpecificEventLoopAttributes { } fn sticky_exit_callback( - evt: event::Event<'_, T>, + evt: event::Event, target: &RootELW, control_flow: &mut ControlFlow, callback: &mut F, ) where - F: FnMut(event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(event::Event, &RootELW, &mut ControlFlow), { // make ControlFlow::ExitWithCode sticky by providing a dummy // control flow reference if it is already ExitWithCode. @@ -219,7 +219,7 @@ impl EventLoop { fn single_iteration(&mut self, main_event: Option>, callback: &mut F) where - F: FnMut(event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(event::Event, &RootELW, &mut ControlFlow), { trace!("Mainloop iteration"); @@ -289,11 +289,15 @@ impl EventLoop { let old_scale_factor = monitor.scale_factor(); let scale_factor = monitor.scale_factor(); if (scale_factor - old_scale_factor).abs() < f64::EPSILON { - let mut size = MonitorHandle::new(self.android_app.clone()).size(); + let new_inner_size = Arc::new(Mutex::new( + MonitorHandle::new(self.android_app.clone()).size(), + )); let event = event::Event::WindowEvent { window_id: window::WindowId(WindowId), event: event::WindowEvent::ScaleFactorChanged { - new_inner_size: &mut size, + inner_size_writer: InnerSizeWriter::new(Arc::downgrade( + &new_inner_size, + )), scale_factor, }, }; @@ -523,14 +527,14 @@ impl EventLoop { pub fn run(mut self, event_handler: F) -> Result<(), RunLoopError> where F: 'static - + FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget, &mut ControlFlow), + + FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), { self.run_ondemand(event_handler) } pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), RunLoopError> where - F: FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget, &mut ControlFlow), + F: FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), { if self.loop_running { return Err(RunLoopError::AlreadyRunning); @@ -553,7 +557,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut callback: F) -> PumpStatus where - F: FnMut(event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(event::Event, &RootELW, &mut ControlFlow), { if !self.loop_running { self.loop_running = true; @@ -593,7 +597,7 @@ impl EventLoop { fn poll_events_with_timeout(&mut self, mut timeout: Option, mut callback: F) where - F: FnMut(event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(event::Event, &RootELW, &mut ControlFlow), { let start = Instant::now(); @@ -996,8 +1000,8 @@ pub struct MonitorHandle { app: AndroidApp, } impl PartialOrd for MonitorHandle { - fn partial_cmp(&self, _other: &Self) -> Option { - Some(std::cmp::Ordering::Equal) + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) } } impl Ord for MonitorHandle { diff --git a/src/platform_impl/ios/app_state.rs b/src/platform_impl/ios/app_state.rs index 7b22e7ef..822ce60b 100644 --- a/src/platform_impl/ios/app_state.rs +++ b/src/platform_impl/ios/app_state.rs @@ -6,6 +6,7 @@ use std::{ mem, os::raw::c_void, ptr, + sync::{Arc, Mutex}, time::Instant, }; @@ -25,7 +26,7 @@ use super::uikit::UIView; use super::view::WinitUIWindow; use crate::{ dpi::LogicalSize, - event::{Event, StartCause, WindowEvent}, + event::{Event, InnerSizeWriter, StartCause, WindowEvent}, event_loop::ControlFlow, platform_impl::platform::{ event_loop::{EventHandler, EventProxy, EventWrapper, Never}, @@ -57,7 +58,7 @@ enum UserCallbackTransitionResult<'a> { }, } -impl Event<'static, Never> { +impl Event { fn is_redraw(&self) -> bool { matches!(self, Event::RedrawRequested(_)) } @@ -807,18 +808,18 @@ fn handle_hidpi_proxy( scale_factor: f64, window: Id, ) { - let mut size = suggested_size.to_physical(scale_factor); - let new_inner_size = &mut size; + let new_inner_size = Arc::new(Mutex::new(suggested_size.to_physical(scale_factor))); let event = Event::WindowEvent { window_id: RootWindowId(window.id()), event: WindowEvent::ScaleFactorChanged { scale_factor, - new_inner_size, + inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), }, }; event_handler.handle_nonuser_event(event, &mut control_flow); let (view, screen_frame) = get_view_and_screen_frame(&window); - let physical_size = *new_inner_size; + let physical_size = *new_inner_size.lock().unwrap(); + drop(new_inner_size); let logical_size = physical_size.to_logical(scale_factor); let size = CGSize::new(logical_size.width, logical_size.height); let new_frame: CGRect = CGRect::new(screen_frame.origin, size); diff --git a/src/platform_impl/ios/event_loop.rs b/src/platform_impl/ios/event_loop.rs index f2e77e1a..cde6430e 100644 --- a/src/platform_impl/ios/event_loop.rs +++ b/src/platform_impl/ios/event_loop.rs @@ -33,7 +33,7 @@ use crate::{ #[derive(Debug)] pub(crate) enum EventWrapper { - StaticEvent(Event<'static, Never>), + StaticEvent(Event), EventProxy(EventProxy), } @@ -106,7 +106,7 @@ impl EventLoop { pub fn run(self, event_handler: F) -> ! where - F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { unsafe { let application = UIApplication::shared(MainThreadMarker::new().unwrap()); @@ -315,7 +315,7 @@ fn setup_control_flow_observers() { pub enum Never {} pub trait EventHandler: Debug { - fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow); + fn handle_nonuser_event(&mut self, event: Event, control_flow: &mut ControlFlow); fn handle_user_events(&mut self, control_flow: &mut ControlFlow); } @@ -334,10 +334,10 @@ impl Debug for EventLoopHandler { impl EventHandler for EventLoopHandler where - F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), T: 'static, { - fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow) { + fn handle_nonuser_event(&mut self, event: Event, control_flow: &mut ControlFlow) { (self.f)( event.map_nonuser_event().unwrap(), &self.event_loop, diff --git a/src/platform_impl/ios/mod.rs b/src/platform_impl/ios/mod.rs index d70bce56..c7b788c0 100644 --- a/src/platform_impl/ios/mod.rs +++ b/src/platform_impl/ios/mod.rs @@ -89,7 +89,7 @@ pub(crate) use self::{ use self::uikit::UIScreen; pub(crate) use crate::icon::NoIcon as PlatformIcon; -pub(self) use crate::platform_impl::Fullscreen; +pub(crate) use crate::platform_impl::Fullscreen; #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct DeviceId { diff --git a/src/platform_impl/linux/mod.rs b/src/platform_impl/linux/mod.rs index 4c2a43c7..ae6d762f 100644 --- a/src/platform_impl/linux/mod.rs +++ b/src/platform_impl/linux/mod.rs @@ -48,7 +48,7 @@ use crate::{ }; pub(crate) use crate::icon::RgbaIcon as PlatformIcon; -pub(self) use crate::platform_impl::Fullscreen; +pub(crate) use crate::platform_impl::Fullscreen; pub mod common; #[cfg(wayland_platform)] @@ -832,21 +832,21 @@ impl EventLoop { pub fn run(mut self, callback: F) -> Result<(), RunLoopError> where - F: FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(crate::event::Event, &RootELW, &mut ControlFlow), { self.run_ondemand(callback) } pub fn run_ondemand(&mut self, callback: F) -> Result<(), RunLoopError> where - F: FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(crate::event::Event, &RootELW, &mut ControlFlow), { x11_or_wayland!(match self; EventLoop(evlp) => evlp.run_ondemand(callback)) } pub fn pump_events(&mut self, timeout: Option, callback: F) -> PumpStatus where - F: FnMut(crate::event::Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(crate::event::Event, &RootELW, &mut ControlFlow), { x11_or_wayland!(match self; EventLoop(evlp) => evlp.pump_events(timeout, callback)) } @@ -928,12 +928,12 @@ impl EventLoopWindowTarget { } fn sticky_exit_callback( - evt: Event<'_, T>, + evt: Event, target: &RootELW, control_flow: &mut ControlFlow, callback: &mut F, ) where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event, &RootELW, &mut ControlFlow), { // make ControlFlow::ExitWithCode sticky by providing a dummy // control flow reference if it is already ExitWithCode. diff --git a/src/platform_impl/linux/wayland/event_loop/mod.rs b/src/platform_impl/linux/wayland/event_loop/mod.rs index a3111333..f33cde0f 100644 --- a/src/platform_impl/linux/wayland/event_loop/mod.rs +++ b/src/platform_impl/linux/wayland/event_loop/mod.rs @@ -7,6 +7,7 @@ use std::marker::PhantomData; use std::mem; use std::rc::Rc; use std::sync::atomic::Ordering; +use std::sync::{Arc, Mutex}; use std::time::{Duration, Instant}; use raw_window_handle::{RawDisplayHandle, WaylandDisplayHandle}; @@ -17,7 +18,7 @@ use sctk::reexports::client::{Connection, Proxy, QueueHandle, WaylandSource}; use crate::dpi::{LogicalSize, PhysicalSize}; use crate::error::{OsError as RootOsError, RunLoopError}; -use crate::event::{Event, StartCause, WindowEvent}; +use crate::event::{Event, InnerSizeWriter, StartCause, WindowEvent}; use crate::event_loop::{ControlFlow, EventLoopWindowTarget as RootEventLoopWindowTarget}; use crate::platform::pump_events::PumpStatus; use crate::platform_impl::platform::min_timeout; @@ -147,7 +148,7 @@ impl EventLoop { pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), RunLoopError> where - F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { if self.loop_running { return Err(RunLoopError::AlreadyRunning); @@ -178,7 +179,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut callback: F) -> PumpStatus where - F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { if !self.loop_running { self.loop_running = true; @@ -216,7 +217,7 @@ impl EventLoop { pub fn poll_events_with_timeout(&mut self, mut timeout: Option, mut callback: F) where - F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { let start = Instant::now(); @@ -321,7 +322,7 @@ impl EventLoop { fn single_iteration(&mut self, mut callback: &mut F, cause: StartCause) where - F: FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { // NOTE currently just indented to simplify the diff @@ -370,7 +371,7 @@ impl EventLoop { for mut compositor_update in compositor_updates.drain(..) { let window_id = compositor_update.window_id; if let Some(scale_factor) = compositor_update.scale_factor { - let mut physical_size = self.with_state(|state| { + let physical_size = self.with_state(|state| { let windows = state.windows.get_mut(); let mut window = windows.get(&window_id).unwrap().lock().unwrap(); @@ -383,12 +384,15 @@ impl EventLoop { // Stash the old window size. let old_physical_size = physical_size; + let new_inner_size = Arc::new(Mutex::new(physical_size)); sticky_exit_callback( Event::WindowEvent { window_id: crate::window::WindowId(window_id), event: WindowEvent::ScaleFactorChanged { scale_factor, - new_inner_size: &mut physical_size, + inner_size_writer: InnerSizeWriter::new(Arc::downgrade( + &new_inner_size, + )), }, }, &self.window_target, @@ -396,6 +400,8 @@ impl EventLoop { &mut callback, ); + let physical_size = *new_inner_size.lock().unwrap(); + drop(new_inner_size); let new_logical_size = physical_size.to_logical(scale_factor); // Resize the window when user altered the size. diff --git a/src/platform_impl/linux/wayland/event_loop/sink.rs b/src/platform_impl/linux/wayland/event_loop/sink.rs index 0bf2ae58..5b356be4 100644 --- a/src/platform_impl/linux/wayland/event_loop/sink.rs +++ b/src/platform_impl/linux/wayland/event_loop/sink.rs @@ -12,7 +12,7 @@ use super::{DeviceId, WindowId}; /// to the winit's user. #[derive(Default)] pub struct EventSink { - pub window_events: Vec>, + pub window_events: Vec>, } impl EventSink { @@ -31,7 +31,7 @@ impl EventSink { /// Add new window event to a queue. #[inline] - pub fn push_window_event(&mut self, event: WindowEvent<'static>, window_id: WindowId) { + pub fn push_window_event(&mut self, event: WindowEvent, window_id: WindowId) { self.window_events.push(Event::WindowEvent { event, window_id: RootWindowId(window_id), @@ -44,7 +44,7 @@ impl EventSink { } #[inline] - pub fn drain(&mut self) -> Drain<'_, Event<'static, ()>> { + pub fn drain(&mut self) -> Drain<'_, Event<()>> { self.window_events.drain(..) } } diff --git a/src/platform_impl/linux/x11/event_processor.rs b/src/platform_impl/linux/x11/event_processor.rs index e2cee68f..5d030f89 100644 --- a/src/platform_impl/linux/x11/event_processor.rs +++ b/src/platform_impl/linux/x11/event_processor.rs @@ -4,7 +4,7 @@ use std::{ os::raw::{c_char, c_int, c_long, c_ulong}, rc::Rc, slice, - sync::Arc, + sync::{Arc, Mutex}, }; use x11rb::protocol::xproto::{self, ConnectionExt as _}; @@ -16,7 +16,6 @@ use super::{ WindowId, XExtension, }; -use crate::platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest}; use crate::{ dpi::{PhysicalPosition, PhysicalSize}, event::{DeviceEvent, ElementState, Event, Ime, RawKeyEvent, TouchPhase, WindowEvent}, @@ -24,6 +23,10 @@ use crate::{ keyboard::ModifiersState, platform_impl::platform::common::{keymap, xkb_state::KbdState}, }; +use crate::{ + event::InnerSizeWriter, + platform_impl::platform::x11::ime::{ImeEvent, ImeEventReceiver, ImeRequest}, +}; /// The X11 documentation states: "Keycodes lie in the inclusive range `[8, 255]`". const KEYCODE_OFFSET: u8 = 8; @@ -126,7 +129,7 @@ impl EventProcessor { pub(super) fn process_event(&mut self, xev: &mut ffi::XEvent, mut callback: F) where - F: FnMut(Event<'_, T>), + F: FnMut(Event), { let wt = get_xtarget(&self.target); let atoms = wt.x_connection().atoms(); @@ -437,19 +440,25 @@ impl EventProcessor { ); let old_inner_size = PhysicalSize::new(width, height); - let mut new_inner_size = PhysicalSize::new(new_width, new_height); + let new_inner_size = PhysicalSize::new(new_width, new_height); // Unlock shared state to prevent deadlock in callback below drop(shared_state_lock); + let inner_size = Arc::new(Mutex::new(new_inner_size)); callback(Event::WindowEvent { window_id, event: WindowEvent::ScaleFactorChanged { scale_factor: new_scale_factor, - new_inner_size: &mut new_inner_size, + inner_size_writer: InnerSizeWriter::new(Arc::downgrade( + &inner_size, + )), }, }); + let new_inner_size = *inner_size.lock().unwrap(); + drop(inner_size); + if new_inner_size != old_inner_size { window.request_inner_size_physical( new_inner_size.width, @@ -1308,17 +1317,22 @@ impl EventProcessor { let window_id = crate::window::WindowId(*window_id); let old_inner_size = PhysicalSize::new(width, height); - let mut new_inner_size = - PhysicalSize::new(new_width, new_height); - + let inner_size = Arc::new(Mutex::new( + PhysicalSize::new(new_width, new_height), + )); callback(Event::WindowEvent { window_id, event: WindowEvent::ScaleFactorChanged { scale_factor: new_monitor.scale_factor, - new_inner_size: &mut new_inner_size, + inner_size_writer: InnerSizeWriter::new( + Arc::downgrade(&inner_size), + ), }, }); + let new_inner_size = *inner_size.lock().unwrap(); + drop(inner_size); + if new_inner_size != old_inner_size { let (new_width, new_height) = new_inner_size.into(); window.request_inner_size_physical( @@ -1400,7 +1414,7 @@ impl EventProcessor { kb_state: &mut KbdState, callback: &mut F, ) where - F: FnMut(Event<'_, T>), + F: FnMut(Event), { let device_id = mkdid(util::VIRTUAL_CORE_KEYBOARD.into()); diff --git a/src/platform_impl/linux/x11/mod.rs b/src/platform_impl/linux/x11/mod.rs index 9259f1ae..718a5c32 100644 --- a/src/platform_impl/linux/x11/mod.rs +++ b/src/platform_impl/linux/x11/mod.rs @@ -434,7 +434,7 @@ impl EventLoop { pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), RunLoopError> where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event, &RootELW, &mut ControlFlow), { if self.loop_running { return Err(RunLoopError::AlreadyRunning); @@ -468,7 +468,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut callback: F) -> PumpStatus where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event, &RootELW, &mut ControlFlow), { if !self.loop_running { self.loop_running = true; @@ -512,7 +512,7 @@ impl EventLoop { pub fn poll_events_with_timeout(&mut self, mut timeout: Option, mut callback: F) where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event, &RootELW, &mut ControlFlow), { let start = Instant::now(); @@ -595,7 +595,7 @@ impl EventLoop { fn single_iteration(&mut self, callback: &mut F, cause: StartCause) where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event, &RootELW, &mut ControlFlow), { let mut control_flow = self.control_flow; @@ -694,7 +694,7 @@ impl EventLoop { fn drain_events(&mut self, callback: &mut F, control_flow: &mut ControlFlow) where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event, &RootELW, &mut ControlFlow), { let target = &self.target; let mut xev = MaybeUninit::uninit(); diff --git a/src/platform_impl/macos/app_state.rs b/src/platform_impl/macos/app_state.rs index 1d49d22f..172a56f0 100644 --- a/src/platform_impl/macos/app_state.rs +++ b/src/platform_impl/macos/app_state.rs @@ -6,7 +6,7 @@ use std::{ rc::{Rc, Weak}, sync::{ atomic::{AtomicBool, Ordering}, - Mutex, MutexGuard, + Arc, Mutex, MutexGuard, }, time::Instant, }; @@ -19,7 +19,7 @@ use once_cell::sync::Lazy; use super::appkit::{NSApp, NSApplication, NSApplicationActivationPolicy, NSEvent}; use crate::{ dpi::LogicalSize, - event::{Event, StartCause, WindowEvent}, + event::{Event, InnerSizeWriter, StartCause, WindowEvent}, event_loop::{ControlFlow, EventLoopWindowTarget as RootWindowTarget}, platform_impl::platform::{ event::{EventProxy, EventWrapper}, @@ -34,8 +34,8 @@ use crate::{ static HANDLER: Lazy = Lazy::new(Default::default); -impl<'a, Never> Event<'a, Never> { - fn userify(self) -> Event<'a, T> { +impl Event { + fn userify(self) -> Event { self.map_nonuser_event() // `Never` can't be constructed, so the `UserEvent` variant can't // be present here. @@ -45,12 +45,11 @@ impl<'a, Never> Event<'a, Never> { pub trait EventHandler: Debug { // Not sure probably it should accept Event<'static, Never> - fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow); + fn handle_nonuser_event(&mut self, event: Event, control_flow: &mut ControlFlow); fn handle_user_events(&mut self, control_flow: &mut ControlFlow); } -pub(crate) type Callback = - RefCell, &RootWindowTarget, &mut ControlFlow)>; +pub(crate) type Callback = RefCell, &RootWindowTarget, &mut ControlFlow)>; struct EventLoopHandler { callback: Weak>, @@ -62,7 +61,7 @@ impl EventLoopHandler { where F: FnOnce( &mut EventLoopHandler, - RefMut<'_, dyn FnMut(Event<'_, T>, &RootWindowTarget, &mut ControlFlow)>, + RefMut<'_, dyn FnMut(Event, &RootWindowTarget, &mut ControlFlow)>, ), { // The `NSApp` and our `HANDLER` are global state and so it's possible that @@ -90,7 +89,7 @@ impl Debug for EventLoopHandler { } impl EventHandler for EventLoopHandler { - fn handle_nonuser_event(&mut self, event: Event<'_, Never>, control_flow: &mut ControlFlow) { + fn handle_nonuser_event(&mut self, event: Event, control_flow: &mut ControlFlow) { self.with_callback(|this, mut callback| { if let ControlFlow::ExitWithCode(code) = *control_flow { // XXX: why isn't event dispatching simply skipped after control_flow = ExitWithCode? @@ -338,19 +337,19 @@ impl Handler { suggested_size: LogicalSize, scale_factor: f64, ) { - let mut size = suggested_size.to_physical(scale_factor); - let new_inner_size = &mut size; + let new_inner_size = Arc::new(Mutex::new(suggested_size.to_physical(scale_factor))); let event = Event::WindowEvent { window_id: WindowId(window.id()), event: WindowEvent::ScaleFactorChanged { scale_factor, - new_inner_size, + inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), }, }; callback.handle_nonuser_event(event, &mut self.control_flow.lock().unwrap()); - let physical_size = *new_inner_size; + let physical_size = *new_inner_size.lock().unwrap(); + drop(new_inner_size); let logical_size = physical_size.to_logical(scale_factor); let size = NSSize::new(logical_size.width, logical_size.height); window.setContentSize(size); diff --git a/src/platform_impl/macos/event.rs b/src/platform_impl/macos/event.rs index 867b9482..5dc61e66 100644 --- a/src/platform_impl/macos/event.rs +++ b/src/platform_impl/macos/event.rs @@ -24,7 +24,7 @@ use crate::{ #[derive(Debug)] pub(crate) enum EventWrapper { - StaticEvent(Event<'static, Never>), + StaticEvent(Event), EventProxy(EventProxy), } diff --git a/src/platform_impl/macos/event_loop.rs b/src/platform_impl/macos/event_loop.rs index 8726cf76..0adaa448 100644 --- a/src/platform_impl/macos/event_loop.rs +++ b/src/platform_impl/macos/event_loop.rs @@ -195,7 +195,7 @@ impl EventLoop { pub fn run(mut self, callback: F) -> Result<(), RunLoopError> where - F: 'static + FnMut(Event<'_, T>, &RootWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event, &RootWindowTarget, &mut ControlFlow), { self.run_ondemand(callback) } @@ -206,7 +206,7 @@ impl EventLoop { // redundant wake ups. pub fn run_ondemand(&mut self, callback: F) -> Result<(), RunLoopError> where - F: FnMut(Event<'_, T>, &RootWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootWindowTarget, &mut ControlFlow), { if AppState::is_running() { return Err(RunLoopError::AlreadyRunning); @@ -223,8 +223,8 @@ impl EventLoop { let callback = unsafe { mem::transmute::< - Rc, &RootWindowTarget, &mut ControlFlow)>>, - Rc, &RootWindowTarget, &mut ControlFlow)>>, + Rc, &RootWindowTarget, &mut ControlFlow)>>, + Rc, &RootWindowTarget, &mut ControlFlow)>>, >(Rc::new(RefCell::new(callback))) }; @@ -293,7 +293,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, callback: F) -> PumpStatus where - F: FnMut(Event<'_, T>, &RootWindowTarget, &mut ControlFlow), + F: FnMut(Event, &RootWindowTarget, &mut ControlFlow), { // # Safety // We are erasing the lifetime of the application callback here so that we @@ -306,8 +306,8 @@ impl EventLoop { let callback = unsafe { mem::transmute::< - Rc, &RootWindowTarget, &mut ControlFlow)>>, - Rc, &RootWindowTarget, &mut ControlFlow)>>, + Rc, &RootWindowTarget, &mut ControlFlow)>>, + Rc, &RootWindowTarget, &mut ControlFlow)>>, >(Rc::new(RefCell::new(callback))) }; diff --git a/src/platform_impl/macos/view.rs b/src/platform_impl/macos/view.rs index 391089ea..eba06c19 100644 --- a/src/platform_impl/macos/view.rs +++ b/src/platform_impl/macos/view.rs @@ -821,7 +821,7 @@ impl WinitView { WindowId(self.window().id()) } - fn queue_event(&self, event: WindowEvent<'static>) { + fn queue_event(&self, event: WindowEvent) { let event = Event::WindowEvent { window_id: self.window_id(), event, diff --git a/src/platform_impl/macos/window_delegate.rs b/src/platform_impl/macos/window_delegate.rs index 16f0d91d..67eb8fe8 100644 --- a/src/platform_impl/macos/window_delegate.rs +++ b/src/platform_impl/macos/window_delegate.rs @@ -442,7 +442,7 @@ impl WinitWindowDelegate { } } - pub(crate) fn queue_event(&self, event: WindowEvent<'static>) { + pub(crate) fn queue_event(&self, event: WindowEvent) { let event = Event::WindowEvent { window_id: WindowId(self.window.id()), event, diff --git a/src/platform_impl/orbital/event_loop.rs b/src/platform_impl/orbital/event_loop.rs index 3adda04f..3cfc2b86 100644 --- a/src/platform_impl/orbital/event_loop.rs +++ b/src/platform_impl/orbital/event_loop.rs @@ -308,7 +308,7 @@ impl EventLoop { event_state: &mut EventState, mut event_handler: F, ) where - F: FnMut(event::Event<'_, T>), + F: FnMut(event::Event), { match event_option { EventOption::Key(KeyEvent { @@ -446,11 +446,11 @@ impl EventLoop { pub fn run(mut self, mut event_handler_inner: F) -> Result<(), RunLoopError> where F: 'static - + FnMut(event::Event<'_, T>, &event_loop::EventLoopWindowTarget, &mut ControlFlow), + + FnMut(event::Event, &event_loop::EventLoopWindowTarget, &mut ControlFlow), { // Wrapper for event handler function that prevents ExitWithCode from being unset. let mut event_handler = - move |event: event::Event<'_, T>, + move |event: event::Event, window_target: &event_loop::EventLoopWindowTarget, control_flow: &mut ControlFlow| { if let ControlFlow::ExitWithCode(code) = control_flow { diff --git a/src/platform_impl/web/event_loop/mod.rs b/src/platform_impl/web/event_loop/mod.rs index 1dcee878..4ed00367 100644 --- a/src/platform_impl/web/event_loop/mod.rs +++ b/src/platform_impl/web/event_loop/mod.rs @@ -31,7 +31,7 @@ impl EventLoop { pub fn run(self, event_handler: F) -> ! where - F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { self.spawn_inner(event_handler, false); @@ -46,14 +46,14 @@ impl EventLoop { pub fn spawn(self, event_handler: F) where - F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { self.spawn_inner(event_handler, true); } fn spawn_inner(self, mut event_handler: F, event_loop_recreation: bool) where - F: 'static + FnMut(Event<'_, T>, &RootEventLoopWindowTarget, &mut ControlFlow), + F: 'static + FnMut(Event, &RootEventLoopWindowTarget, &mut ControlFlow), { let target = RootEventLoopWindowTarget { p: self.elw.p.clone(), diff --git a/src/platform_impl/web/event_loop/runner.rs b/src/platform_impl/web/event_loop/runner.rs index 726596ff..ebc035d4 100644 --- a/src/platform_impl/web/event_loop/runner.rs +++ b/src/platform_impl/web/event_loop/runner.rs @@ -24,7 +24,7 @@ use web_time::{Duration, Instant}; pub struct Shared(Rc>); -pub(super) type EventHandler = dyn FnMut(Event<'_, T>, &mut ControlFlow); +pub(super) type EventHandler = dyn FnMut(Event, &mut ControlFlow); impl Clone for Shared { fn clone(&self) -> Self { @@ -748,7 +748,7 @@ impl Shared { } pub(crate) enum EventWrapper { - Event(Event<'static, T>), + Event(Event), ScaleChange { canvas: Weak>, size: PhysicalSize, @@ -756,8 +756,8 @@ pub(crate) enum EventWrapper { }, } -impl From> for EventWrapper { - fn from(value: Event<'static, T>) -> Self { +impl From> for EventWrapper { + fn from(value: Event) -> Self { Self::Event(value) } } diff --git a/src/platform_impl/web/mod.rs b/src/platform_impl/web/mod.rs index dc178179..3abd2684 100644 --- a/src/platform_impl/web/mod.rs +++ b/src/platform_impl/web/mod.rs @@ -38,4 +38,4 @@ pub use self::window::{PlatformSpecificWindowBuilderAttributes, Window, WindowId pub(crate) use self::keyboard::KeyEventExtra; pub(crate) use crate::icon::NoIcon as PlatformIcon; -pub(self) use crate::platform_impl::Fullscreen; +pub(crate) use crate::platform_impl::Fullscreen; diff --git a/src/platform_impl/web/web_sys/canvas.rs b/src/platform_impl/web/web_sys/canvas.rs index 0c42c59b..89ad8211 100644 --- a/src/platform_impl/web/web_sys/canvas.rs +++ b/src/platform_impl/web/web_sys/canvas.rs @@ -1,20 +1,7 @@ -use super::super::WindowId; -use super::event_handle::EventListenerHandle; -use super::intersection_handle::IntersectionObserverHandle; -use super::media_query_handle::MediaQueryListHandle; -use super::pointer::PointerHandler; -use super::{event, fullscreen, ButtonsState, ResizeScaleHandle}; -use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; -use crate::error::OsError as RootOE; -use crate::event::{Force, MouseButton, MouseScrollDelta}; -use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState}; -use crate::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes}; -use crate::window::{WindowAttributes, WindowId as RootWindowId}; - use std::cell::{Cell, RefCell}; use std::rc::Rc; use std::sync::atomic::AtomicBool; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use js_sys::Promise; use smol_str::SmolStr; @@ -24,6 +11,20 @@ use web_sys::{ CssStyleDeclaration, Document, Event, FocusEvent, HtmlCanvasElement, KeyboardEvent, WheelEvent, }; +use crate::dpi::{LogicalPosition, PhysicalPosition, PhysicalSize}; +use crate::error::OsError as RootOE; +use crate::event::{Force, InnerSizeWriter, MouseButton, MouseScrollDelta}; +use crate::keyboard::{Key, KeyCode, KeyLocation, ModifiersState}; +use crate::platform_impl::{OsError, PlatformSpecificWindowBuilderAttributes}; +use crate::window::{WindowAttributes, WindowId as RootWindowId}; + +use super::super::WindowId; +use super::event_handle::EventListenerHandle; +use super::intersection_handle::IntersectionObserverHandle; +use super::media_query_handle::MediaQueryListHandle; +use super::pointer::PointerHandler; +use super::{event, fullscreen, ButtonsState, ResizeScaleHandle}; + #[allow(dead_code)] pub struct Canvas { common: Common, @@ -451,20 +452,25 @@ impl Canvas { pub(crate) fn handle_scale_change( &self, runner: &super::super::event_loop::runner::Shared, - event_handler: impl FnOnce(crate::event::Event<'_, T>), + event_handler: impl FnOnce(crate::event::Event), current_size: PhysicalSize, scale: f64, ) { // First, we send the `ScaleFactorChanged` event: self.set_current_size(current_size); - let mut new_size = current_size; - event_handler(crate::event::Event::WindowEvent { - window_id: RootWindowId(self.id), - event: crate::event::WindowEvent::ScaleFactorChanged { - scale_factor: scale, - new_inner_size: &mut new_size, - }, - }); + let new_size = { + let new_size = Arc::new(Mutex::new(current_size)); + event_handler(crate::event::Event::WindowEvent { + window_id: RootWindowId(self.id), + event: crate::event::WindowEvent::ScaleFactorChanged { + scale_factor: scale, + inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_size)), + }, + }); + + let new_size = *new_size.lock().unwrap(); + new_size + }; if current_size != new_size { // Then we resize the canvas to the new size, a new diff --git a/src/platform_impl/windows/drop_handler.rs b/src/platform_impl/windows/drop_handler.rs index 5de7cd0c..84bebbd1 100644 --- a/src/platform_impl/windows/drop_handler.rs +++ b/src/platform_impl/windows/drop_handler.rs @@ -30,7 +30,7 @@ pub struct FileDropHandlerData { pub interface: IDropTarget, refcount: AtomicUsize, window: HWND, - send_event: Box)>, + send_event: Box)>, cursor_effect: u32, hovered_is_valid: bool, /* If the currently hovered item is not valid there must not be any `HoveredFileCancelled` emitted */ } @@ -41,7 +41,7 @@ pub struct FileDropHandler { #[allow(non_snake_case)] impl FileDropHandler { - pub fn new(window: HWND, send_event: Box)>) -> FileDropHandler { + pub fn new(window: HWND, send_event: Box)>) -> FileDropHandler { let data = Box::new(FileDropHandlerData { interface: IDropTarget { lpVtbl: &DROP_TARGET_VTBL as *const IDropTargetVtbl, @@ -211,7 +211,7 @@ impl FileDropHandler { } impl FileDropHandlerData { - fn send_event(&self, event: Event<'static, ()>) { + fn send_event(&self, event: Event<()>) { (self.send_event)(event); } } diff --git a/src/platform_impl/windows/event_loop.rs b/src/platform_impl/windows/event_loop.rs index f2224502..9856fca3 100644 --- a/src/platform_impl/windows/event_loop.rs +++ b/src/platform_impl/windows/event_loop.rs @@ -76,7 +76,10 @@ use windows_sys::Win32::{ use crate::{ dpi::{PhysicalPosition, PhysicalSize}, error::RunLoopError, - event::{DeviceEvent, Event, Force, Ime, RawKeyEvent, Touch, TouchPhase, WindowEvent}, + event::{ + DeviceEvent, Event, Force, Ime, InnerSizeWriter, RawKeyEvent, Touch, TouchPhase, + WindowEvent, + }, event_loop::{ControlFlow, DeviceEvents, EventLoopClosed, EventLoopWindowTarget as RootELW}, keyboard::{KeyCode, ModifiersState}, platform::{pump_events::PumpStatus, scancode::KeyCodeExtScancode}, @@ -142,7 +145,7 @@ pub(crate) struct WindowData { } impl WindowData { - unsafe fn send_event(&self, event: Event<'_, T>) { + unsafe fn send_event(&self, event: Event) { self.event_loop_runner.send_event(event); } @@ -157,7 +160,7 @@ struct ThreadMsgTargetData { } impl ThreadMsgTargetData { - unsafe fn send_event(&self, event: Event<'_, T>) { + unsafe fn send_event(&self, event: Event) { self.event_loop_runner.send_event(event); } } @@ -245,14 +248,14 @@ impl EventLoop { pub fn run(mut self, event_handler: F) -> Result<(), RunLoopError> where - F: 'static + FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: 'static + FnMut(Event, &RootELW, &mut ControlFlow), { self.run_ondemand(event_handler) } pub fn run_ondemand(&mut self, mut event_handler: F) -> Result<(), RunLoopError> where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event, &RootELW, &mut ControlFlow), { { let runner = &self.window_target.p.runner_shared; @@ -298,7 +301,7 @@ impl EventLoop { pub fn pump_events(&mut self, timeout: Option, mut event_handler: F) -> PumpStatus where - F: FnMut(Event<'_, T>, &RootELW, &mut ControlFlow), + F: FnMut(Event, &RootELW, &mut ControlFlow), { { let runner = &self.window_target.p.runner_shared; @@ -2051,7 +2054,7 @@ unsafe fn public_window_callback_inner( // `allow_resize` prevents us from re-applying DPI adjustment to the restored size after // exiting fullscreen (the restored size is already DPI adjusted). - let mut new_physical_inner_size = match allow_resize { + let new_physical_inner_size = match allow_resize { // We calculate our own size because the default suggested rect doesn't do a great job // of preserving the window's logical size. true => old_physical_inner_size @@ -2060,14 +2063,18 @@ unsafe fn public_window_callback_inner( false => old_physical_inner_size, }; + let new_inner_size = Arc::new(Mutex::new(new_physical_inner_size)); userdata.send_event(Event::WindowEvent { window_id: RootWindowId(WindowId(window)), event: ScaleFactorChanged { scale_factor: new_scale_factor, - new_inner_size: &mut new_physical_inner_size, + inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), }, }); + let new_physical_inner_size = *new_inner_size.lock().unwrap(); + drop(new_inner_size); + let dragging_window: bool; { diff --git a/src/platform_impl/windows/event_loop/runner.rs b/src/platform_impl/windows/event_loop/runner.rs index c85450f9..f81055db 100644 --- a/src/platform_impl/windows/event_loop/runner.rs +++ b/src/platform_impl/windows/event_loop/runner.rs @@ -4,6 +4,7 @@ use std::{ collections::VecDeque, mem, panic, rc::Rc, + sync::{Arc, Mutex}, time::Instant, }; @@ -11,7 +12,7 @@ use windows_sys::Win32::Foundation::HWND; use crate::{ dpi::PhysicalSize, - event::{Event, StartCause, WindowEvent}, + event::{Event, InnerSizeWriter, StartCause, WindowEvent}, event_loop::ControlFlow, platform_impl::platform::{ event_loop::{WindowData, GWL_USERDATA}, @@ -22,7 +23,7 @@ use crate::{ pub(crate) type EventLoopRunnerShared = Rc>; -type EventHandler = Cell, &mut ControlFlow)>>>; +type EventHandler = Cell, &mut ControlFlow)>>>; pub(crate) struct EventLoopRunner { // The event loop's win32 handles @@ -59,7 +60,7 @@ pub(crate) enum RunnerState { } enum BufferedEvent { - Event(Event<'static, T>), + Event(Event), ScaleFactorChanged(WindowId, f64, PhysicalSize), } @@ -90,11 +91,11 @@ impl EventLoopRunner { /// undefined behaviour. pub(crate) unsafe fn set_event_handler(&self, f: F) where - F: FnMut(Event<'_, T>, &mut ControlFlow), + F: FnMut(Event, &mut ControlFlow), { let old_event_handler = self.event_handler.replace(mem::transmute::< - Option, &mut ControlFlow)>>, - Option, &mut ControlFlow)>>, + Option, &mut ControlFlow)>>, + Option, &mut ControlFlow)>>, >(Some(Box::new(f)))); assert!(old_event_handler.is_none()); } @@ -196,7 +197,7 @@ impl EventLoopRunner { self.move_state_to(RunnerState::HandlingMainEvents); } - pub(crate) fn send_event(&self, event: Event<'_, T>) { + pub(crate) fn send_event(&self, event: Event) { if let Event::RedrawRequested(_) = event { self.call_event_handler(event); // As a rule, to ensure that `pump_events` can't block an external event loop @@ -219,7 +220,7 @@ impl EventLoopRunner { self.move_state_to(RunnerState::Destroyed); } - fn call_event_handler(&self, event: Event<'_, T>) { + fn call_event_handler(&self, event: Event) { self.catch_unwind(|| { let mut control_flow = self.control_flow.take(); let mut event_handler = self.event_handler.take() @@ -361,38 +362,50 @@ impl EventLoopRunner { } impl BufferedEvent { - pub fn from_event(event: Event<'_, T>) -> BufferedEvent { + pub fn from_event(event: Event) -> BufferedEvent { match event { Event::WindowEvent { event: WindowEvent::ScaleFactorChanged { scale_factor, - new_inner_size, + inner_size_writer, }, window_id, - } => BufferedEvent::ScaleFactorChanged(window_id, scale_factor, *new_inner_size), - event => BufferedEvent::Event(event.to_static().unwrap()), + } => BufferedEvent::ScaleFactorChanged( + window_id, + scale_factor, + *inner_size_writer + .new_inner_size + .upgrade() + .unwrap() + .lock() + .unwrap(), + ), + event => BufferedEvent::Event(event), } } - pub fn dispatch_event(self, dispatch: impl FnOnce(Event<'_, T>)) { + pub fn dispatch_event(self, dispatch: impl FnOnce(Event)) { match self { Self::Event(event) => dispatch(event), - Self::ScaleFactorChanged(window_id, scale_factor, mut new_inner_size) => { + Self::ScaleFactorChanged(window_id, scale_factor, new_inner_size) => { + let new_inner_size = Arc::new(Mutex::new(new_inner_size)); dispatch(Event::WindowEvent { window_id, event: WindowEvent::ScaleFactorChanged { scale_factor, - new_inner_size: &mut new_inner_size, + inner_size_writer: InnerSizeWriter::new(Arc::downgrade(&new_inner_size)), }, }); + let inner_size = *new_inner_size.lock().unwrap(); + drop(new_inner_size); let window_flags = unsafe { let userdata = get_window_long(window_id.0.into(), GWL_USERDATA) as *mut WindowData; (*userdata).window_state_lock().window_flags }; - window_flags.set_size((window_id.0).0, new_inner_size); + window_flags.set_size((window_id.0).0, inner_size); } } }