From 2e0657418c0d31f87fd63da9c848a9f133264038 Mon Sep 17 00:00:00 2001 From: Ashley Wulber Date: Wed, 28 Aug 2024 19:06:02 -0400 Subject: [PATCH] update winit --- Cargo.toml | 15 +- accessibility/Cargo.toml | 17 +- examples/integration/src/main.rs | 6 +- examples/sctk_session_lock/Cargo.toml | 9 +- examples/todos/Cargo.toml | 2 +- winit/src/application.rs | 21 +- winit/src/application/drag_resize.rs | 16 +- winit/src/clipboard.rs | 4 +- winit/src/conversion.rs | 26 +- winit/src/program.rs | 733 +++++++++++--------------- winit/src/program/state.rs | 6 +- winit/src/program/window_manager.rs | 10 +- winit/src/proxy.rs | 21 +- 13 files changed, 411 insertions(+), 475 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4986139956..4b7e17c2f8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -223,12 +223,17 @@ web-time = "0.2" winapi = "0.3" # window_clipboard = "0.4.1" -window_clipboard = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-dnd-8" } -dnd = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-dnd-8" } -mime = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-dnd-8" } +window_clipboard = { path = "../../../window_clipboard" } +dnd = { path = "../../../window_clipboard/dnd" } +mime = { path = "../../../window_clipboard/mime" } + +# window_clipboard = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-dnd-8" } +# dnd = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-dnd-8" } +# mime = { git = "https://github.com/pop-os/window_clipboard.git", tag = "pop-dnd-8" } # winit = { git = "https://github.com/pop-os/winit.git", branch = "winit-0.29" } # winit = { path = "../../winit" } -winit = { git = "https://github.com/iced-rs/winit.git", rev = "254d6b3420ce4e674f516f7a2bd440665e05484d" } +# winit = { git = "https://github.com/iced-rs/winit.git", rev = "254d6b3420ce4e674f516f7a2bd440665e05484d" } +winit = { git = "https://github.com/rust-windowing/winit.git", rev = "241b7a80bba96c91fa3901729cd5dec66abb9be4" } [workspace.lints.rust] @@ -258,4 +263,4 @@ useless_conversion = "deny" broken_intra_doc_links = "forbid" [patch.crates-io] -winit = { git = "https://github.com/iced-rs/winit.git", rev = "254d6b3420ce4e674f516f7a2bd440665e05484d" } +winit = { git = "https://github.com/rust-windowing/winit.git", rev = "241b7a80bba96c91fa3901729cd5dec66abb9be4" } diff --git a/accessibility/Cargo.toml b/accessibility/Cargo.toml index b0faea17aa..7ca0e2e5bf 100644 --- a/accessibility/Cargo.toml +++ b/accessibility/Cargo.toml @@ -10,10 +10,17 @@ async-io = ["accesskit_unix?/async-io", "accesskit_winit?/async-io"] tokio = ["accesskit_unix?/tokio", "accesskit_winit?/tokio"] [dependencies] -accesskit = { git = "https://github.com/accesskit/accesskit" } -accesskit_unix = { git = "https://github.com/accesskit/accesskit", optional = true } -accesskit_windows = { git = "https://github.com/accesskit/accesskit", optional = true } -accesskit_macos = { git = "https://github.com/accesskit/accesskit", optional = true } -accesskit_winit = { git = "https://github.com/accesskit/accesskit", optional = true, default-features = false, features = [ +# accesskit = { git = "https://github.com/accesskit/accesskit" } +# accesskit_unix = { git = "https://github.com/accesskit/accesskit", optional = true } +# accesskit_windows = { git = "https://github.com/accesskit/accesskit", optional = true } +# accesskit_macos = { git = "https://github.com/accesskit/accesskit", optional = true } +# accesskit_winit = { git = "https://github.com/accesskit/accesskit", optional = true, default-features = false, features = [ +# "rwh_06", +# ] } +accesskit = { path = "../../../../accesskit/common" } +accesskit_unix = { path = "../../../../accesskit/platforms/unix", optional = true } +accesskit_windows = { path = "../../../../accesskit/platforms/windows", optional = true } +accesskit_macos = { path = "../../../../accesskit/platforms/macos", optional = true } +accesskit_winit = { path = "../../../../accesskit/platforms/winit", optional = true, default-features = false, features = [ "rwh_06", ] } diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index 3855946903..ebe6c2917a 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -35,7 +35,7 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { enum Runner { Loading, Ready { - window: Arc, + window: Arc, device: wgpu::Device, queue: wgpu::Queue, surface: wgpu::Surface<'static>, @@ -54,7 +54,7 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { } impl winit::application::ApplicationHandler for Runner { - fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + fn resumed(&mut self, event_loop: &dyn winit::event_loop::ActiveEventLoop) { if let Self::Loading = self { let window = Arc::new( event_loop @@ -186,7 +186,7 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { fn window_event( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, _window_id: winit::window::WindowId, event: WindowEvent, ) { diff --git a/examples/sctk_session_lock/Cargo.toml b/examples/sctk_session_lock/Cargo.toml index 0ceb5bff98..6a26dce306 100644 --- a/examples/sctk_session_lock/Cargo.toml +++ b/examples/sctk_session_lock/Cargo.toml @@ -5,7 +5,12 @@ edition = "2021" [dependencies] sctk = { package = "smithay-client-toolkit", git = "https://github.com/smithay/client-toolkit", rev = "828b1eb" } -iced = { path = "../..", default-features = false, features = ["async-std", "wayland", "debug", "a11y"] } +iced = { path = "../..", default-features = false, features = [ + "async-std", + "wayland", + "debug", + "a11y", +] } iced_runtime = { path = "../../runtime" } env_logger = "0.10" -async-std = "1.0" +async-std = "1" diff --git a/examples/todos/Cargo.toml b/examples/todos/Cargo.toml index c014c6bb36..9404d879c5 100644 --- a/examples/todos/Cargo.toml +++ b/examples/todos/Cargo.toml @@ -10,7 +10,7 @@ iced.workspace = true iced_core.workspace = true # iced.features = ["async-std", "debug", "winit", "a11y", "tiny-skia"] # TODO(POP): Fix a11y not working with new winit -iced.features = ["a11y", "async-std", "debug", "winit", "tiny-skia"] +iced.features = ["tokio", "debug", "winit", "tiny-skia"] once_cell.workspace = true serde = { version = "1.0", features = ["derive"] } diff --git a/winit/src/application.rs b/winit/src/application.rs index 85f24474ea..fcffd47f6e 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -339,7 +339,10 @@ where F: Future, C: Compositor + 'static, { - fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + fn resumed( + &mut self, + event_loop: &dyn winit::event_loop::ActiveEventLoop, + ) { let Some(BootConfig { sender, id, @@ -448,7 +451,7 @@ where fn new_events( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, cause: winit::event::StartCause, ) { if self.boot.is_some() { @@ -463,7 +466,7 @@ where fn window_event( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, window_id: winit::window::WindowId, event: winit::event::WindowEvent, ) { @@ -496,7 +499,7 @@ where fn user_event( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, action: UserEventWrapper>, ) { self.process_event( @@ -507,7 +510,7 @@ where fn about_to_wait( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, ) { self.process_event(event_loop, winit::event::Event::AboutToWait); } @@ -519,7 +522,7 @@ where { fn process_event( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, + event_loop: &dyn winit::event_loop::ActiveEventLoop, event: winit::event::Event>>, ) { // On Wasm, events may start being processed before the compositor @@ -576,7 +579,7 @@ where } struct Boot { - window: Arc, + window: Arc, compositor: C, should_be_visible: bool, exit_on_close_request: bool, @@ -1318,7 +1321,7 @@ pub fn update( >, debug: &mut Debug, messages: &mut Vec, - window: &winit::window::Window, + window: &dyn winit::window::Window, ) where A::Theme: DefaultStyle, { @@ -1354,7 +1357,7 @@ pub fn run_action( clipboard: &mut Clipboard>, should_exit: &mut bool, debug: &mut Debug, - window: &winit::window::Window, + window: &dyn winit::window::Window, ) where A: Application, C: Compositor + 'static, diff --git a/winit/src/application/drag_resize.rs b/winit/src/application/drag_resize.rs index 0584fe263a..220169e7ba 100644 --- a/winit/src/application/drag_resize.rs +++ b/winit/src/application/drag_resize.rs @@ -2,17 +2,22 @@ use winit::window::{CursorIcon, ResizeDirection}; /// If supported by winit, returns a closure that implements cursor resize support. pub fn event_func( - window: &winit::window::Window, + window: &dyn winit::window::Window, border_size: f64, ) -> Option< - Box bool>, + Box< + dyn FnMut( + &dyn winit::window::Window, + &winit::event::WindowEvent, + ) -> bool, + >, > { if window.drag_resize_window(ResizeDirection::East).is_ok() { // Keep track of cursor when it is within a resizeable border. let mut cursor_prev_resize_direction = None; Some(Box::new( - move |window: &winit::window::Window, + move |window: &dyn winit::window::Window, window_event: &winit::event::WindowEvent| -> bool { // Keep track of border resize state and set cursor icon when in range @@ -27,8 +32,9 @@ pub fn event_func( border_size, ); if location != cursor_prev_resize_direction { - window.set_cursor_icon( - resize_direction_cursor_icon(location), + window.set_cursor( + resize_direction_cursor_icon(location) + .into(), ); cursor_prev_resize_direction = location; return true; diff --git a/winit/src/clipboard.rs b/winit/src/clipboard.rs index e1cecc1fdf..b7fa3db8c5 100644 --- a/winit/src/clipboard.rs +++ b/winit/src/clipboard.rs @@ -32,7 +32,7 @@ enum State { // // Note that the field ordering is load-bearing. #[allow(dead_code)] - window: Arc, + window: Arc, }, Unavailable, } @@ -62,7 +62,7 @@ impl dnd::Sender for ControlSender { impl Clipboard { /// Creates a new [`Clipboard`] for the given window. - pub fn connect(window: Arc, proxy: ControlSender) -> Clipboard { + pub fn connect(window: Arc, proxy: ControlSender) -> Clipboard { #[allow(unsafe_code)] let state = unsafe { window_clipboard::Clipboard::connect(window.as_ref()) } diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index 6b91bdfc55..e526a17cac 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -2,6 +2,10 @@ //! //! [`winit`]: https://github.com/rust-windowing/winit //! [`iced_runtime`]: https://github.com/iced-rs/iced/tree/0.12/runtime +use std::hash::DefaultHasher; +use std::hash::Hash; +use std::hash::Hasher; + use crate::core::keyboard; use crate::core::mouse; use crate::core::touch; @@ -322,10 +326,12 @@ pub fn position( } window::Position::SpecificWith(to_position) => { if let Some(monitor) = monitor { - let start = monitor.position(); + let start = monitor.position().unwrap_or_default(); - let resolution: winit::dpi::LogicalSize = - monitor.size().to_logical(monitor.scale_factor()); + let resolution: winit::dpi::LogicalSize = monitor + .current_video_mode() + .map(|m| m.size().to_logical(monitor.scale_factor())) + .unwrap_or_default(); let position = to_position( size, @@ -351,10 +357,12 @@ pub fn position( } window::Position::Centered => { if let Some(monitor) = monitor { - let start = monitor.position(); + let start = monitor.position().unwrap_or_default(); - let resolution: winit::dpi::LogicalSize = - monitor.size().to_logical(monitor.scale_factor()); + let resolution: winit::dpi::LogicalSize = monitor + .current_video_mode() + .map(|m| m.size().to_logical(monitor.scale_factor())) + .unwrap_or_default(); let centered: winit::dpi::PhysicalPosition = winit::dpi::LogicalPosition { @@ -487,7 +495,11 @@ pub fn touch_event( touch: winit::event::Touch, scale_factor: f64, ) -> touch::Event { - let id = touch::Finger(touch.id); + // TODO we probably should get the actual internal id in some way instead + let mut s = DefaultHasher::new(); + touch.finger_id.hash(&mut s); + + let id = touch::Finger(s.finish()); let position = { let location = touch.location.to_logical::(scale_factor); diff --git a/winit/src/program.rs b/winit/src/program.rs index 9cb35c6a73..24765265f7 100644 --- a/winit/src/program.rs +++ b/winit/src/program.rs @@ -171,11 +171,11 @@ where let mut debug = Debug::new(); debug.startup_started(); - let event_loop = EventLoop::with_user_event() - .build() - .expect("Create event loop"); + let event_loop = EventLoop::new().expect("Create event loop"); - let (proxy, worker) = Proxy::new(event_loop.create_proxy()); + let (event_sender, event_receiver) = mpsc::unbounded(); + let (proxy, worker): (Proxy<

::Message>, _) = + Proxy::new(event_loop.create_proxy(), event_sender.clone()); let mut runtime = { let executor = @@ -207,7 +207,6 @@ where )); let (boot_sender, boot_receiver) = oneshot::channel(); - let (event_sender, event_receiver) = mpsc::unbounded(); let (control_sender, control_receiver) = mpsc::unbounded(); let instance = Box::pin(run_instance::( @@ -228,7 +227,7 @@ where context: task::Context<'static>, id: Option, boot: Option>, - sender: mpsc::UnboundedSender>>, + sender: mpsc::UnboundedSender>, receiver: mpsc::UnboundedReceiver, error: Option, @@ -265,14 +264,78 @@ where queued_events: Vec::new(), }; - impl winit::application::ApplicationHandler> + impl winit::application::ApplicationHandler for Runner where Message: std::fmt::Debug, F: Future, C: Compositor + 'static, { - fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { + fn proxy_wake_up( + &mut self, + event_loop: &dyn winit::event_loop::ActiveEventLoop, + ) { + self.process_event(event_loop, None); + } + + fn new_events( + &mut self, + event_loop: &dyn winit::event_loop::ActiveEventLoop, + cause: winit::event::StartCause, + ) { + if self.boot.is_some() { + return; + } + self.process_event(event_loop, Some(Event::NewEvents(cause))); + } + + fn window_event( + &mut self, + event_loop: &dyn winit::event_loop::ActiveEventLoop, + window_id: winit::window::WindowId, + event: winit::event::WindowEvent, + ) { + #[cfg(target_os = "windows")] + let is_move_or_resize = matches!( + event, + winit::event::WindowEvent::Resized(_) + | winit::event::WindowEvent::Moved(_) + ); + + self.process_event( + event_loop, + Some(Event::Winit(window_id, event)), + ); + + // TODO: Remove when unnecessary + // On Windows, we emulate an `AboutToWait` event after every `Resized` event + // since the event loop does not resume during resize interaction. + // More details: https://github.com/rust-windowing/winit/issues/3272 + #[cfg(target_os = "windows")] + { + if is_move_or_resize { + self.process_event( + event_loop, + Event::EventLoopAwakened( + winit::event::Event::AboutToWait, + ), + ); + } + } + } + + fn about_to_wait( + &mut self, + event_loop: &dyn winit::event_loop::ActiveEventLoop, + ) { + self.process_event(event_loop, Some(Event::AboutToWait)); + } + + fn can_create_surfaces( + &mut self, + event_loop: &dyn winit::event_loop::ActiveEventLoop, + ) { + // create initial window let Some(BootConfig { sender, fonts, @@ -283,10 +346,12 @@ where return; }; - let window = match event_loop.create_window( - winit::window::WindowAttributes::default().with_visible(false), - ) { - Ok(window) => Arc::new(window), + let window: Arc = match event_loop + .create_window( + winit::window::WindowAttributes::default() + .with_visible(false), + ) { + Ok(window) => Arc::from(window), Err(error) => { self.error = Some(Error::WindowCreationFailed(error)); event_loop.exit(); @@ -337,98 +402,6 @@ where }); } } - - fn new_events( - &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, - cause: winit::event::StartCause, - ) { - if self.boot.is_some() { - return; - } - self.process_event( - event_loop, - Event::EventLoopAwakened(winit::event::Event::NewEvents(cause)), - ); - } - - fn window_event( - &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, - window_id: winit::window::WindowId, - event: winit::event::WindowEvent, - ) { - #[cfg(target_os = "windows")] - let is_move_or_resize = matches!( - event, - winit::event::WindowEvent::Resized(_) - | winit::event::WindowEvent::Moved(_) - ); - - self.process_event( - event_loop, - Event::EventLoopAwakened(winit::event::Event::WindowEvent { - window_id, - event, - }), - ); - - // TODO: Remove when unnecessary - // On Windows, we emulate an `AboutToWait` event after every `Resized` event - // since the event loop does not resume during resize interaction. - // More details: https://github.com/rust-windowing/winit/issues/3272 - #[cfg(target_os = "windows")] - { - if is_move_or_resize { - self.process_event( - event_loop, - Event::EventLoopAwakened( - winit::event::Event::AboutToWait, - ), - ); - } - } - } - - fn user_event( - &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, - action: Action, - ) { - self.process_event( - event_loop, - Event::EventLoopAwakened(winit::event::Event::UserEvent( - action, - )), - ); - } - - fn received_url( - &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, - url: String, - ) { - self.process_event( - event_loop, - Event::EventLoopAwakened( - winit::event::Event::PlatformSpecific( - winit::event::PlatformSpecific::MacOS( - winit::event::MacOS::ReceivedUrl(url), - ), - ), - ), - ); - } - - fn about_to_wait( - &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, - ) { - self.process_event( - event_loop, - Event::EventLoopAwakened(winit::event::Event::AboutToWait), - ); - } } impl Runner @@ -438,8 +411,8 @@ where { fn process_event( &mut self, - event_loop: &winit::event_loop::ActiveEventLoop, - event: Event>, + event_loop: &dyn winit::event_loop::ActiveEventLoop, + event: Option>, ) { #[cfg(target_arch = "wasm32")] if !*self.is_booted.borrow() { @@ -458,7 +431,9 @@ where return; } - self.sender.start_send(event).expect("Send event"); + if let Some(event) = event { + self.sender.start_send(event).expect("Send event"); + } loop { let poll = self.instance.as_mut().poll(&mut self.context); @@ -500,19 +475,20 @@ where let target = settings.platform_specific.target.clone(); - let window = event_loop - .create_window( - conversion::window_attributes( - settings, - &title, - monitor - .or(event_loop + let window = Arc::from( + event_loop + .create_window( + conversion::window_attributes( + settings, + &title, + monitor.or(event_loop .primary_monitor()), - self.id.clone(), + self.id.clone(), + ) + .with_visible(false), ) - .with_visible(false), - ) - .expect("Create window"); + .expect("Create window"), + ); #[cfg(target_arch = "wasm32")] { @@ -562,34 +538,37 @@ where self.process_event( event_loop, - Event::WindowCreated { + Some(Event::WindowCreated { id, window, exit_on_close_request, make_visible: visible, on_open, resize_border, - }, + }), ); } Control::Exit => { event_loop.exit(); } Control::Dnd(e) => { - self.process_event(event_loop, Event::Dnd(e)); + self.process_event( + event_loop, + Some(Event::Dnd(e)), + ); } #[cfg(feature = "a11y")] Control::Accessibility(event) => { self.process_event( event_loop, - Event::Accessibility(event), + Some(Event::Accessibility(event)), ); } #[cfg(feature = "a11y")] Control::AccessibilityEnabled(event) => { self.process_event( event_loop, - Event::AccessibilityEnabled(event), + Some(Event::AccessibilityEnabled(event)), ); } }, @@ -628,11 +607,10 @@ struct Boot { clipboard: Clipboard, } -#[derive(Debug)] -enum Event { +pub(crate) enum Event { WindowCreated { id: window::Id, - window: winit::window::Window, + window: Arc, exit_on_close_request: bool, make_visible: bool, on_open: oneshot::Sender, @@ -643,7 +621,10 @@ enum Event { Accessibility(iced_accessibility::accesskit::ActionRequest), #[cfg(feature = "a11y")] AccessibilityEnabled(bool), - EventLoopAwakened(winit::event::Event), + Winit(winit::window::WindowId, winit::event::WindowEvent), + AboutToWait, + UserEvent(Action), + NewEvents(winit::event::StartCause), } #[derive(Debug)] @@ -670,7 +651,7 @@ async fn run_instance( mut proxy: Proxy, mut debug: Debug, boot: oneshot::Receiver>, - mut event_receiver: mpsc::UnboundedReceiver>>, + mut event_receiver: mpsc::UnboundedReceiver>, mut control_sender: mpsc::UnboundedSender, is_daemon: bool, ) where @@ -779,7 +760,7 @@ async fn run_instance( ( node_id, Some(Adapter::with_direct_handlers( - &raw, + raw.as_ref(), activation_handler, action_handler, deactivation_handler, @@ -796,7 +777,6 @@ async fn run_instance( let mut cur_dnd_surface: Option = None; debug.startup_finished(); - loop { // Empty the queue if possible let event = if let Ok(event) = event_receiver.try_next() { @@ -821,7 +801,7 @@ async fn run_instance( } => { let window = window_manager.insert( id, - Arc::new(window), + window, &program, &mut compositor, exit_on_close_request, @@ -858,53 +838,36 @@ async fn run_instance( let _ = on_open.send(id); is_window_opening = false; } - Event::EventLoopAwakened(event) => { + Event::UserEvent(action) => { + run_action( + action, + &program, + &mut compositor, + &mut events, + &mut messages, + &mut clipboard, + &mut control_sender, + &mut debug, + &mut user_interfaces, + &mut window_manager, + &mut ui_caches, + &mut is_window_opening, + ); + actions += 1; + } + Event::NewEvents( + event::StartCause::Init + | event::StartCause::ResumeTimeReached { .. }, + ) => { + for (_id, window) in window_manager.iter_mut() { + window.raw.request_redraw(); + } + } + Event::Winit(window_id, event) => { match event { - event::Event::NewEvents( - event::StartCause::Init - | event::StartCause::ResumeTimeReached { .. }, - ) => { - for (_id, window) in window_manager.iter_mut() { - window.raw.request_redraw(); - } - } - event::Event::PlatformSpecific( - event::PlatformSpecific::MacOS( - event::MacOS::ReceivedUrl(url), - ), - ) => { - runtime.broadcast( - subscription::Event::PlatformSpecific( - subscription::PlatformSpecific::MacOS( - subscription::MacOS::ReceivedUrl(url), - ), - ), - ); - } - event::Event::UserEvent(action) => { - run_action( - action, - &program, - &mut compositor, - &mut events, - &mut messages, - &mut clipboard, - &mut control_sender, - &mut debug, - &mut user_interfaces, - &mut window_manager, - &mut ui_caches, - &mut is_window_opening, - ); - actions += 1; - } - event::Event::WindowEvent { - window_id: id, - event: event::WindowEvent::RedrawRequested, - .. - } => { + event::WindowEvent::RedrawRequested => { let Some((id, window)) = - window_manager.get_mut_alias(id) + window_manager.get_mut_alias(window_id) else { continue; }; @@ -949,7 +912,8 @@ async fn run_instance( window.raw.set_cursor( conversion::mouse_interaction( new_mouse_interaction, - ), + ) + .into(), ); window.mouse_interaction = new_mouse_interaction; @@ -1026,7 +990,8 @@ async fn run_instance( window.raw.set_cursor( conversion::mouse_interaction( new_mouse_interaction, - ), + ) + .into(), ); window.mouse_interaction = @@ -1076,10 +1041,7 @@ async fn run_instance( }, } } - event::Event::WindowEvent { - event: window_event, - window_id, - } => { + window_event => { if !is_daemon && matches!( window_event, @@ -1105,7 +1067,7 @@ async fn run_instance( if let Some(func) = window.drag_resize_window_func.as_mut() { - if func(&window.raw, &window_event) { + if func(window.raw.as_ref(), &window_event) { continue; } } @@ -1133,7 +1095,7 @@ async fn run_instance( )); } else { window.state.update( - &window.raw, + window.raw.as_ref(), &window_event, &mut debug, ); @@ -1147,273 +1109,196 @@ async fn run_instance( } } } - event::Event::AboutToWait => { - if events.is_empty() && messages.is_empty() { - continue; - } - debug.event_processing_started(); - let mut uis_stale = false; - - for (id, window) in window_manager.iter_mut() { - let mut window_events = vec![]; + _ => {} + } + } + Event::AboutToWait => { + if events.is_empty() && messages.is_empty() { + continue; + } - events.retain(|(window_id, event)| { - if *window_id == Some(id) { - window_events.push(event.clone()); - false - } else { - true - } - }); + debug.event_processing_started(); + let mut uis_stale = false; - if window_events.is_empty() && messages.is_empty() { - continue; - } + for (id, window) in window_manager.iter_mut() { + let mut window_events = vec![]; - let (ui_state, statuses) = user_interfaces - .get_mut(&id) - .expect("Get user interface") - .update( - &window_events, - window.state.cursor(), - &mut window.renderer, - &mut clipboard, - &mut messages, - ); + events.retain(|(window_id, event)| { + if *window_id == Some(id) { + window_events.push(event.clone()); + false + } else { + true + } + }); - window.raw.request_redraw(); + if window_events.is_empty() && messages.is_empty() { + continue; + } - if !uis_stale { - uis_stale = matches!( - ui_state, - user_interface::State::Outdated - ); - } + let (ui_state, statuses) = user_interfaces + .get_mut(&id) + .expect("Get user interface") + .update( + &window_events, + window.state.cursor(), + &mut window.renderer, + &mut clipboard, + &mut messages, + ); - for (event, status) in window_events - .into_iter() - .zip(statuses.into_iter()) - { - runtime.broadcast( - subscription::Event::Interaction { - window: id, - event, - status, - }, - ); - } - } + window.raw.request_redraw(); - for (id, event) in events.drain(..) { - runtime.broadcast( - subscription::Event::Interaction { - window: id.unwrap_or(window::Id::NONE), - event, - status: core::event::Status::Ignored, - }, - ); - } + if !uis_stale { + uis_stale = + matches!(ui_state, user_interface::State::Outdated); + } - debug.event_processing_finished(); + for (event, status) in + window_events.into_iter().zip(statuses.into_iter()) + { + runtime.broadcast(subscription::Event::Interaction { + window: id, + event, + status, + }); + } + } - if !messages.is_empty() || uis_stale { - let cached_interfaces: FxHashMap< - window::Id, - user_interface::Cache, - > = ManuallyDrop::into_inner(user_interfaces) - .drain() - .map(|(id, ui)| (id, ui.into_cache())) - .collect(); + for (id, event) in events.drain(..) { + runtime.broadcast(subscription::Event::Interaction { + window: id.unwrap_or(window::Id::NONE), + event, + status: core::event::Status::Ignored, + }); + } - update( - &mut program, - &mut runtime, - &mut debug, - &mut messages, - ); + debug.event_processing_finished(); - for (id, window) in window_manager.iter_mut() { - window.state.synchronize( - &program, - id, - &window.raw, - ); + if !messages.is_empty() || uis_stale { + let cached_interfaces: FxHashMap< + window::Id, + user_interface::Cache, + > = ManuallyDrop::into_inner(user_interfaces) + .drain() + .map(|(id, ui)| (id, ui.into_cache())) + .collect(); - window.raw.request_redraw(); - } + update( + &mut program, + &mut runtime, + &mut debug, + &mut messages, + ); - user_interfaces = - ManuallyDrop::new(build_user_interfaces( - &program, - &mut debug, - &mut window_manager, - cached_interfaces, - &mut clipboard, - )); - - if actions > 0 { - proxy.free_slots(actions); - actions = 0; - } - } + for (id, window) in window_manager.iter_mut() { + window.state.synchronize( + &program, + id, + window.raw.as_ref(), + ); - debug.draw_started(); + window.raw.request_redraw(); + } - for (id, window) in window_manager.iter_mut() { - // TODO: Avoid redrawing all the time by forcing widgets to - // request redraws on state changes - // - // Then, we can use the `interface_state` here to decide if a redraw - // is needed right away, or simply wait until a specific time. - let redraw_event = core::Event::Window( - window::Event::RedrawRequested(Instant::now()), - ); + user_interfaces = ManuallyDrop::new(build_user_interfaces( + &program, + &mut debug, + &mut window_manager, + cached_interfaces, + &mut clipboard, + )); - let cursor = window.state.cursor(); + if actions > 0 { + proxy.free_slots(actions); + actions = 0; + } + } - let ui = user_interfaces - .get_mut(&id) - .expect("Get user interface"); - - let (ui_state, _) = ui.update( - &[redraw_event.clone()], - cursor, - &mut window.renderer, - &mut clipboard, - &mut messages, - ); + debug.draw_started(); - let new_mouse_interaction = { - let state = &window.state; + for (id, window) in window_manager.iter_mut() { + // TODO: Avoid redrawing all the time by forcing widgets to + // request redraws on state changes + // + // Then, we can use the `interface_state` here to decide if a redraw + // is needed right away, or simply wait until a specific time. + let redraw_event = core::Event::Window( + window::Event::RedrawRequested(Instant::now()), + ); - ui.draw( - &mut window.renderer, - state.theme(), - &renderer::Style { - icon_color: state.icon_color(), - text_color: state.text_color(), - scale_factor: state.scale_factor(), - }, - cursor, - ) - }; + let cursor = window.state.cursor(); - if new_mouse_interaction != window.mouse_interaction - { - window.raw.set_cursor_icon( - conversion::mouse_interaction( - new_mouse_interaction, - ), - ); + let ui = user_interfaces + .get_mut(&id) + .expect("Get user interface"); - window.mouse_interaction = - new_mouse_interaction; - } + let (ui_state, _) = ui.update( + &[redraw_event.clone()], + cursor, + &mut window.renderer, + &mut clipboard, + &mut messages, + ); - // TODO once widgets can request to be redrawn, we can avoid always requesting a - // redraw - window.raw.request_redraw(); - runtime.broadcast( - subscription::Event::Interaction { - window: id, - event: redraw_event, - status: core::event::Status::Ignored, - }, - ); + let new_mouse_interaction = { + let state = &window.state; - let _ = control_sender.start_send( - Control::ChangeFlow(match ui_state { - user_interface::State::Updated { - redraw_request: Some(redraw_request), - } => match redraw_request { - window::RedrawRequest::NextFrame => { - window.raw.request_redraw(); + ui.draw( + &mut window.renderer, + state.theme(), + &renderer::Style { + icon_color: state.icon_color(), + text_color: state.text_color(), + scale_factor: state.scale_factor(), + }, + cursor, + ) + }; - ControlFlow::Wait - } - window::RedrawRequest::At(at) => { - ControlFlow::WaitUntil(at) - } - }, - _ => ControlFlow::Wait, - }), - ); - } + if new_mouse_interaction != window.mouse_interaction { + window.raw.set_cursor( + conversion::mouse_interaction( + new_mouse_interaction, + ) + .into(), + ); - debug.draw_finished(); + window.mouse_interaction = new_mouse_interaction; } - event::Event::PlatformSpecific( - event::PlatformSpecific::MacOS( - event::MacOS::ReceivedUrl(url), - ), - ) => { - use crate::core::event; - - // events.push(( - // None, - // event::Event::PlatformSpecific( - // event::PlatformSpecific::MacOS( - // event::MacOS::ReceivedUrl(url), - // ), - // ), - // )); - } - event::Event::WindowEvent { - event: window_event, - window_id, - } => { - let Some((id, window)) = - window_manager.get_mut_alias(window_id) - else { - continue; - }; - - if matches!( - window_event, - winit::event::WindowEvent::CloseRequested - ) { - let w = window_manager.remove(id); - let _ = user_interfaces.remove(&id); - let _ = ui_caches.remove(&id); - if let Some(w) = w.as_ref() { - clipboard.register_dnd_destination( - DndSurface(Arc::new(Box::new( - w.raw.clone(), - ))), - Vec::new(), - ); - } - events.push(( - Some(id), - core::Event::Window(window::Event::Closed), - )); + // TODO once widgets can request to be redrawn, we can avoid always requesting a + // redraw + window.raw.request_redraw(); + runtime.broadcast(subscription::Event::Interaction { + window: id, + event: redraw_event, + status: core::event::Status::Ignored, + }); - if window_manager.is_empty() - && w.is_some_and(|w| w.exit_on_close_request) - { - break; - } - } else { - window.state.update( - &window.raw, - &window_event, - &mut debug, - ); + let _ = control_sender.start_send(Control::ChangeFlow( + match ui_state { + user_interface::State::Updated { + redraw_request: Some(redraw_request), + } => match redraw_request { + window::RedrawRequest::NextFrame => { + window.raw.request_redraw(); - if let Some(event) = conversion::window_event( - window_event, - window.state.scale_factor(), - window.state.modifiers(), - ) { - events.push((Some(id), event)); - } - } - } - _ => {} + ControlFlow::Wait + } + window::RedrawRequest::At(at) => { + ControlFlow::WaitUntil(at) + } + }, + _ => ControlFlow::Wait, + }, + )); } + + debug.draw_finished(); } + Event::Dnd(e) => { match &e { dnd::DndEvent::Offer(_, dnd::OfferEvent::Leave) => { @@ -1468,6 +1353,7 @@ async fn run_instance( Event::AccessibilityEnabled(enabled) => { a11y_enabled = enabled; } + _ => {} } } @@ -1615,7 +1501,8 @@ fn run_action( winit::dpi::LogicalSize { width: size.width, height: size.height, - }, + } + .into(), ); } } @@ -1671,7 +1558,8 @@ fn run_action( winit::dpi::LogicalPosition { x: position.x, y: position.y, - }, + } + .into(), ); } } @@ -1738,7 +1626,8 @@ fn run_action( winit::dpi::LogicalPosition { x: point.x, y: point.y, - }, + } + .into(), ); } } diff --git a/winit/src/program/state.rs b/winit/src/program/state.rs index 4a63ab50e8..8e7997ebb6 100644 --- a/winit/src/program/state.rs +++ b/winit/src/program/state.rs @@ -47,7 +47,7 @@ where pub fn new( application: &P, window_id: window::Id, - window: &Window, + window: &dyn Window, ) -> Self { let title = application.title(window_id); let scale_factor = application.scale_factor(window_id); @@ -143,7 +143,7 @@ where /// Processes the provided window event and updates the [`State`] accordingly. pub fn update( &mut self, - window: &Window, + window: &dyn Window, event: &WindowEvent, _debug: &mut crate::runtime::Debug, ) { @@ -209,7 +209,7 @@ where &mut self, application: &P, window_id: window::Id, - window: &Window, + window: &dyn Window, ) { // Update window title let new_title = application.title(window_id); diff --git a/winit/src/program/window_manager.rs b/winit/src/program/window_manager.rs index d23f6a8fc3..316c10651d 100644 --- a/winit/src/program/window_manager.rs +++ b/winit/src/program/window_manager.rs @@ -35,13 +35,13 @@ where pub fn insert( &mut self, id: Id, - window: Arc, + window: Arc, application: &P, compositor: &mut C, exit_on_close_request: bool, resize_border: u32, ) -> &mut Window { - let state = State::new(application, id, &window); + let state = State::new(application, id, window.as_ref()); let viewport_version = state.viewport_version(); let physical_size = state.physical_size(); let surface = compositor.create_surface( @@ -54,7 +54,7 @@ where let _ = self.aliases.insert(window.id(), id); let drag_resize_window_func = super::drag_resize::event_func( - &window, + window.as_ref(), resize_border as f64 * window.scale_factor(), ); @@ -139,14 +139,14 @@ where C: Compositor, P::Theme: DefaultStyle, { - pub raw: Arc, + pub raw: Arc, pub(crate) state: State

, pub viewport_version: u64, pub exit_on_close_request: bool, pub drag_resize_window_func: Option< Box< dyn FnMut( - &winit::window::Window, + &dyn winit::window::Window, &winit::event::WindowEvent, ) -> bool, >, diff --git a/winit/src/proxy.rs b/winit/src/proxy.rs index 99cb84df91..dd81c5fb49 100644 --- a/winit/src/proxy.rs +++ b/winit/src/proxy.rs @@ -6,14 +6,16 @@ use crate::futures::futures::{ task::{Context, Poll}, Future, Sink, StreamExt, }; +use crate::program::Event; use crate::runtime::Action; use std::pin::Pin; /// An event loop proxy with backpressure that implements `Sink`. #[derive(Debug)] pub struct Proxy { - raw: winit::event_loop::EventLoopProxy>, + raw: winit::event_loop::EventLoopProxy, sender: mpsc::Sender>, + event_sender: mpsc::UnboundedSender>, notifier: mpsc::Sender, } @@ -23,6 +25,7 @@ impl Clone for Proxy { raw: self.raw.clone(), sender: self.sender.clone(), notifier: self.notifier.clone(), + event_sender: self.event_sender.clone(), } } } @@ -32,11 +35,14 @@ impl Proxy { /// Creates a new [`Proxy`] from an `EventLoopProxy`. pub fn new( - raw: winit::event_loop::EventLoopProxy>, + raw: winit::event_loop::EventLoopProxy, + event_sender: mpsc::UnboundedSender>, ) -> (Self, impl Future) { let (notifier, mut processed) = mpsc::channel(Self::MAX_SIZE); - let (sender, mut receiver) = mpsc::channel(Self::MAX_SIZE); + let (sender, mut receiver): (mpsc::Sender>, _) = + mpsc::channel(Self::MAX_SIZE); let proxy = raw.clone(); + let event_sender_clone = event_sender.clone(); let worker = async move { let mut count = 0; @@ -45,7 +51,9 @@ impl Proxy { if count < Self::MAX_SIZE { select! { message = receiver.select_next_some() => { - let _ = proxy.send_event(message); + let + _ = event_sender_clone.unbounded_send(Event::UserEvent(message)); + let _ = proxy.wake_up(); count += 1; } @@ -70,6 +78,7 @@ impl Proxy { raw, sender, notifier, + event_sender, }, worker, ) @@ -94,8 +103,8 @@ impl Proxy { where T: std::fmt::Debug, { - self.raw - .send_event(action) + self.event_sender + .unbounded_send(Event::UserEvent(action)) .expect("Send message to event loop"); }