From e400f972c1fe6fa4f70f8cfe559ded680e6cf740 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 4 Jun 2024 23:20:33 +0200 Subject: Introduce `window::Id` to `Event` subscriptions And remove `window::Id` from `Event` altogether. --- core/src/event.rs | 2 +- examples/events/src/main.rs | 5 ++--- examples/integration/src/main.rs | 2 -- examples/loading_spinners/src/circular.rs | 2 +- examples/loading_spinners/src/linear.rs | 2 +- examples/multi_window/src/main.rs | 12 ++++++----- examples/toast/src/main.rs | 4 +--- examples/visible_bounds/src/main.rs | 4 ++-- futures/src/event.rs | 19 ++++++++--------- futures/src/keyboard.rs | 11 +++++----- futures/src/runtime.rs | 10 +++++++-- futures/src/subscription.rs | 11 ++++++---- futures/src/subscription/tracker.rs | 16 +++++++++++--- runtime/src/window.rs | 4 ++-- widget/src/shader.rs | 2 +- widget/src/text_input.rs | 6 +++--- winit/src/application.rs | 10 +++++---- winit/src/conversion.rs | 35 +++++++++++++------------------ winit/src/multi_window.rs | 29 ++++++++++--------------- 19 files changed, 95 insertions(+), 91 deletions(-) diff --git a/core/src/event.rs b/core/src/event.rs index 870b3074..953cd73f 100644 --- a/core/src/event.rs +++ b/core/src/event.rs @@ -19,7 +19,7 @@ pub enum Event { Mouse(mouse::Event), /// A window event - Window(window::Id, window::Event), + Window(window::Event), /// A touch event Touch(touch::Event), diff --git a/examples/events/src/main.rs b/examples/events/src/main.rs index 9d1c502a..bacd8e6e 100644 --- a/examples/events/src/main.rs +++ b/examples/events/src/main.rs @@ -37,9 +37,8 @@ impl Events { Command::none() } Message::EventOccurred(event) => { - if let Event::Window(id, window::Event::CloseRequested) = event - { - window::close(id) + if let Event::Window(window::Event::CloseRequested) = event { + window::close(window::Id::MAIN) } else { Command::none() } diff --git a/examples/integration/src/main.rs b/examples/integration/src/main.rs index e1c7d62f..9818adf3 100644 --- a/examples/integration/src/main.rs +++ b/examples/integration/src/main.rs @@ -9,7 +9,6 @@ use iced_wgpu::{wgpu, Engine, Renderer}; use iced_winit::conversion; use iced_winit::core::mouse; use iced_winit::core::renderer; -use iced_winit::core::window; use iced_winit::core::{Color, Font, Pixels, Size, Theme}; use iced_winit::futures; use iced_winit::runtime::program; @@ -317,7 +316,6 @@ pub fn main() -> Result<(), winit::error::EventLoopError> { // Map window event to iced event if let Some(event) = iced_winit::conversion::window_event( - window::Id::MAIN, event, window.scale_factor(), *modifiers, diff --git a/examples/loading_spinners/src/circular.rs b/examples/loading_spinners/src/circular.rs index de728af2..bf70e190 100644 --- a/examples/loading_spinners/src/circular.rs +++ b/examples/loading_spinners/src/circular.rs @@ -275,7 +275,7 @@ where ) -> event::Status { let state = tree.state.downcast_mut::(); - if let Event::Window(_, window::Event::RedrawRequested(now)) = event { + if let Event::Window(window::Event::RedrawRequested(now)) = event { state.animation = state.animation.timed_transition( self.cycle_duration, self.rotation_duration, diff --git a/examples/loading_spinners/src/linear.rs b/examples/loading_spinners/src/linear.rs index ce375621..164993c6 100644 --- a/examples/loading_spinners/src/linear.rs +++ b/examples/loading_spinners/src/linear.rs @@ -189,7 +189,7 @@ where ) -> event::Status { let state = tree.state.downcast_mut::(); - if let Event::Window(_, window::Event::RedrawRequested(now)) = event { + if let Event::Window(window::Event::RedrawRequested(now)) = event { *state = state.timed_transition(self.cycle_duration, now); shell.request_redraw(RedrawRequest::NextFrame); diff --git a/examples/multi_window/src/main.rs b/examples/multi_window/src/main.rs index 31c2e4f6..eb74c94a 100644 --- a/examples/multi_window/src/main.rs +++ b/examples/multi_window/src/main.rs @@ -145,16 +145,18 @@ impl multi_window::Application for Example { } fn subscription(&self) -> Subscription { - event::listen_with(|event, _| { - if let iced::Event::Window(id, window_event) = event { + event::listen_with(|event, _, window| { + if let iced::Event::Window(window_event) = event { match window_event { window::Event::CloseRequested => { - Some(Message::CloseWindow(id)) + Some(Message::CloseWindow(window)) } window::Event::Opened { position, .. } => { - Some(Message::WindowOpened(id, position)) + Some(Message::WindowOpened(window, position)) + } + window::Event::Closed => { + Some(Message::WindowClosed(window)) } - window::Event::Closed => Some(Message::WindowClosed(id)), _ => None, } } else { diff --git a/examples/toast/src/main.rs b/examples/toast/src/main.rs index 355c40b8..700b6b10 100644 --- a/examples/toast/src/main.rs +++ b/examples/toast/src/main.rs @@ -499,9 +499,7 @@ mod toast { clipboard: &mut dyn Clipboard, shell: &mut Shell<'_, Message>, ) -> event::Status { - if let Event::Window(_, window::Event::RedrawRequested(now)) = - &event - { + if let Event::Window(window::Event::RedrawRequested(now)) = &event { let mut next_redraw: Option = None; self.instants.iter_mut().enumerate().for_each( diff --git a/examples/visible_bounds/src/main.rs b/examples/visible_bounds/src/main.rs index 332b6a7b..8030f5b4 100644 --- a/examples/visible_bounds/src/main.rs +++ b/examples/visible_bounds/src/main.rs @@ -145,11 +145,11 @@ impl Example { } fn subscription(&self) -> Subscription { - event::listen_with(|event, _| match event { + event::listen_with(|event, _status, _window| match event { Event::Mouse(mouse::Event::CursorMoved { position }) => { Some(Message::MouseMoved(position)) } - Event::Window(_, window::Event::Resized { .. }) => { + Event::Window(window::Event::Resized { .. }) => { Some(Message::WindowResized) } _ => None, diff --git a/futures/src/event.rs b/futures/src/event.rs index 97224506..4f3342ca 100644 --- a/futures/src/event.rs +++ b/futures/src/event.rs @@ -9,7 +9,7 @@ use crate::MaybeSend; /// This subscription will notify your application of any [`Event`] that was /// not captured by any widget. pub fn listen() -> Subscription { - listen_with(|event, status| match status { + listen_with(|event, status, _window| match status { event::Status::Ignored => Some(event), event::Status::Captured => None, }) @@ -24,7 +24,7 @@ pub fn listen() -> Subscription { /// - Returns `None`, the [`Event`] will be discarded. /// - Returns `Some` message, the `Message` will be produced. pub fn listen_with( - f: fn(Event, event::Status) -> Option, + f: fn(Event, event::Status, window::Id) -> Option, ) -> Subscription where Message: 'static + MaybeSend, @@ -32,13 +32,12 @@ where #[derive(Hash)] struct EventsWith; - subscription::filter_map( - (EventsWith, f), - move |event, status| match event { - Event::Window(_, window::Event::RedrawRequested(_)) => None, - _ => f(event, status), - }, - ) + subscription::filter_map((EventsWith, f), move |event, status, window| { + match event { + Event::Window(window::Event::RedrawRequested(_)) => None, + _ => f(event, status, window), + } + }) } /// Creates a [`Subscription`] that produces a message for every runtime event, @@ -47,7 +46,7 @@ where /// **Warning:** This [`Subscription`], if unfiltered, may produce messages in /// an infinite loop. pub fn listen_raw( - f: fn(Event, event::Status) -> Option, + f: fn(Event, event::Status, window::Id) -> Option, ) -> Subscription where Message: 'static + MaybeSend, diff --git a/futures/src/keyboard.rs b/futures/src/keyboard.rs index 8e7da38f..43ed7742 100644 --- a/futures/src/keyboard.rs +++ b/futures/src/keyboard.rs @@ -18,7 +18,7 @@ where #[derive(Hash)] struct OnKeyPress; - subscription::filter_map((OnKeyPress, f), move |event, status| { + subscription::filter_map((OnKeyPress, f), move |event, status, _window| { match (event, status) { ( core::Event::Keyboard(Event::KeyPressed { @@ -45,8 +45,9 @@ where #[derive(Hash)] struct OnKeyRelease; - subscription::filter_map((OnKeyRelease, f), move |event, status| { - match (event, status) { + subscription::filter_map( + (OnKeyRelease, f), + move |event, status, _window| match (event, status) { ( core::Event::Keyboard(Event::KeyReleased { key, @@ -56,6 +57,6 @@ where core::event::Status::Ignored, ) => f(key, modifiers), _ => None, - } - }) + }, + ) } diff --git a/futures/src/runtime.rs b/futures/src/runtime.rs index cac7b7e1..ae55f814 100644 --- a/futures/src/runtime.rs +++ b/futures/src/runtime.rs @@ -1,5 +1,6 @@ //! Run commands and keep track of subscriptions. use crate::core::event::{self, Event}; +use crate::core::window; use crate::subscription; use crate::{BoxFuture, BoxStream, Executor, MaybeSend}; @@ -127,7 +128,12 @@ where /// See [`Tracker::broadcast`] to learn more. /// /// [`Tracker::broadcast`]: subscription::Tracker::broadcast - pub fn broadcast(&mut self, event: Event, status: event::Status) { - self.subscriptions.broadcast(event, status); + pub fn broadcast( + &mut self, + event: Event, + status: event::Status, + window: window::Id, + ) { + self.subscriptions.broadcast(event, status, window); } } diff --git a/futures/src/subscription.rs b/futures/src/subscription.rs index 93e35608..79cea6ed 100644 --- a/futures/src/subscription.rs +++ b/futures/src/subscription.rs @@ -4,6 +4,7 @@ mod tracker; pub use tracker::Tracker; use crate::core::event::{self, Event}; +use crate::core::window; use crate::futures::{Future, Stream}; use crate::{BoxStream, MaybeSend}; @@ -15,7 +16,7 @@ use std::hash::Hash; /// A stream of runtime events. /// /// It is the input of a [`Subscription`]. -pub type EventStream = BoxStream<(Event, event::Status)>; +pub type EventStream = BoxStream<(Event, event::Status, window::Id)>; /// The hasher used for identifying subscriptions. pub type Hasher = rustc_hash::FxHasher; @@ -289,7 +290,9 @@ where pub(crate) fn filter_map(id: I, f: F) -> Subscription where I: Hash + 'static, - F: Fn(Event, event::Status) -> Option + MaybeSend + 'static, + F: Fn(Event, event::Status, window::Id) -> Option + + MaybeSend + + 'static, Message: 'static + MaybeSend, { Subscription::from_recipe(Runner { @@ -298,8 +301,8 @@ where use futures::future; use futures::stream::StreamExt; - events.filter_map(move |(event, status)| { - future::ready(f(event, status)) + events.filter_map(move |(event, status, window)| { + future::ready(f(event, status, window)) }) }, }) diff --git a/futures/src/subscription/tracker.rs b/futures/src/subscription/tracker.rs index 277a446b..086b0f09 100644 --- a/futures/src/subscription/tracker.rs +++ b/futures/src/subscription/tracker.rs @@ -1,4 +1,5 @@ use crate::core::event::{self, Event}; +use crate::core::window; use crate::subscription::{Hasher, Recipe}; use crate::{BoxFuture, MaybeSend}; @@ -23,7 +24,9 @@ pub struct Tracker { #[derive(Debug)] pub struct Execution { _cancel: futures::channel::oneshot::Sender<()>, - listener: Option>, + listener: Option< + futures::channel::mpsc::Sender<(Event, event::Status, window::Id)>, + >, } impl Tracker { @@ -139,12 +142,19 @@ impl Tracker { /// currently open. /// /// [`Recipe::stream`]: crate::subscription::Recipe::stream - pub fn broadcast(&mut self, event: Event, status: event::Status) { + pub fn broadcast( + &mut self, + event: Event, + status: event::Status, + window: window::Id, + ) { self.subscriptions .values_mut() .filter_map(|connection| connection.listener.as_mut()) .for_each(|listener| { - if let Err(error) = listener.try_send((event.clone(), status)) { + if let Err(error) = + listener.try_send((event.clone(), status, window)) + { log::warn!( "Error sending event to subscription: {error:?}" ); diff --git a/runtime/src/window.rs b/runtime/src/window.rs index e32465d3..b68c9a71 100644 --- a/runtime/src/window.rs +++ b/runtime/src/window.rs @@ -28,8 +28,8 @@ use raw_window_handle::WindowHandle; /// In any case, this [`Subscription`] is useful to smoothly draw application-driven /// animations without missing any frames. pub fn frames() -> Subscription { - event::listen_raw(|event, _status| match event { - crate::core::Event::Window(_, Event::RedrawRequested(at)) => Some(at), + event::listen_raw(|event, _status, _window| match event { + crate::core::Event::Window(Event::RedrawRequested(at)) => Some(at), _ => None, }) } diff --git a/widget/src/shader.rs b/widget/src/shader.rs index fad2f4eb..473cfd0d 100644 --- a/widget/src/shader.rs +++ b/widget/src/shader.rs @@ -107,7 +107,7 @@ where Some(Event::Keyboard(keyboard_event)) } core::Event::Touch(touch_event) => Some(Event::Touch(touch_event)), - core::Event::Window(_, window::Event::RedrawRequested(instant)) => { + core::Event::Window(window::Event::RedrawRequested(instant)) => { Some(Event::RedrawRequested(instant)) } _ => None, diff --git a/widget/src/text_input.rs b/widget/src/text_input.rs index 941e9bde..dc4f83e0 100644 --- a/widget/src/text_input.rs +++ b/widget/src/text_input.rs @@ -1003,14 +1003,14 @@ where state.keyboard_modifiers = modifiers; } - Event::Window(_, window::Event::Unfocused) => { + Event::Window(window::Event::Unfocused) => { let state = state::(tree); if let Some(focus) = &mut state.is_focused { focus.is_window_focused = false; } } - Event::Window(_, window::Event::Focused) => { + Event::Window(window::Event::Focused) => { let state = state::(tree); if let Some(focus) = &mut state.is_focused { @@ -1020,7 +1020,7 @@ where shell.request_redraw(window::RedrawRequest::NextFrame); } } - Event::Window(_, window::Event::RedrawRequested(now)) => { + Event::Window(window::Event::RedrawRequested(now)) => { let state = state::(tree); if let Some(focus) = &mut state.is_focused { diff --git a/winit/src/application.rs b/winit/src/application.rs index 4aed1eee..ed8715d8 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -623,7 +623,6 @@ async fn run_instance( // 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 = Event::Window( - window::Id::MAIN, window::Event::RedrawRequested(Instant::now()), ); @@ -651,7 +650,11 @@ async fn run_instance( _ => ControlFlow::Wait, }); - runtime.broadcast(redraw_event, core::event::Status::Ignored); + runtime.broadcast( + redraw_event, + core::event::Status::Ignored, + window::Id::MAIN, + ); debug.draw_started(); let new_mouse_interaction = user_interface.draw( @@ -714,7 +717,6 @@ async fn run_instance( state.update(&window, &window_event, &mut debug); if let Some(event) = conversion::window_event( - window::Id::MAIN, window_event, state.scale_factor(), state.modifiers(), @@ -742,7 +744,7 @@ async fn run_instance( for (event, status) in events.drain(..).zip(statuses.into_iter()) { - runtime.broadcast(event, status); + runtime.broadcast(event, status, window::Id::MAIN); } if !messages.is_empty() diff --git a/winit/src/conversion.rs b/winit/src/conversion.rs index ea33e610..79fcf92e 100644 --- a/winit/src/conversion.rs +++ b/winit/src/conversion.rs @@ -126,7 +126,6 @@ pub fn window_attributes( /// Converts a winit window event into an iced event. pub fn window_event( - id: window::Id, event: winit::event::WindowEvent, scale_factor: f64, modifiers: winit::keyboard::ModifiersState, @@ -137,16 +136,13 @@ pub fn window_event( WindowEvent::Resized(new_size) => { let logical_size = new_size.to_logical(scale_factor); - Some(Event::Window( - id, - window::Event::Resized { - width: logical_size.width, - height: logical_size.height, - }, - )) + Some(Event::Window(window::Event::Resized { + width: logical_size.width, + height: logical_size.height, + })) } WindowEvent::CloseRequested => { - Some(Event::Window(id, window::Event::CloseRequested)) + Some(Event::Window(window::Event::CloseRequested)) } WindowEvent::CursorMoved { position, .. } => { let position = position.to_logical::(scale_factor); @@ -264,22 +260,19 @@ pub fn window_event( self::modifiers(new_modifiers.state()), ))) } - WindowEvent::Focused(focused) => Some(Event::Window( - id, - if focused { - window::Event::Focused - } else { - window::Event::Unfocused - }, - )), + WindowEvent::Focused(focused) => Some(Event::Window(if focused { + window::Event::Focused + } else { + window::Event::Unfocused + })), WindowEvent::HoveredFile(path) => { - Some(Event::Window(id, window::Event::FileHovered(path.clone()))) + Some(Event::Window(window::Event::FileHovered(path.clone()))) } WindowEvent::DroppedFile(path) => { - Some(Event::Window(id, window::Event::FileDropped(path.clone()))) + Some(Event::Window(window::Event::FileDropped(path.clone()))) } WindowEvent::HoveredFileCancelled => { - Some(Event::Window(id, window::Event::FilesHoveredLeft)) + Some(Event::Window(window::Event::FilesHoveredLeft)) } WindowEvent::Touch(touch) => { Some(Event::Touch(touch_event(touch, scale_factor))) @@ -288,7 +281,7 @@ pub fn window_event( let winit::dpi::LogicalPosition { x, y } = position.to_logical(scale_factor); - Some(Event::Window(id, window::Event::Moved { x, y })) + Some(Event::Window(window::Event::Moved { x, y })) } _ => None, } diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 74ab64f2..3696f952 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -492,13 +492,10 @@ async fn run_instance( let mut events = { vec![( Some(window::Id::MAIN), - core::Event::Window( - window::Id::MAIN, - window::Event::Opened { - position: main_window.position(), - size: main_window.size(), - }, - ), + core::Event::Window(window::Event::Opened { + position: main_window.position(), + size: main_window.size(), + }), )] }; @@ -565,13 +562,10 @@ async fn run_instance( events.push(( Some(id), - core::Event::Window( - id, - window::Event::Opened { - position: window.position(), - size: window.size(), - }, - ), + core::Event::Window(window::Event::Opened { + position: window.position(), + size: window.size(), + }), )); } Event::EventLoopAwakened(event) => { @@ -623,7 +617,6 @@ async fn run_instance( // 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( - id, window::Event::RedrawRequested(Instant::now()), ); @@ -665,6 +658,7 @@ async fn run_instance( runtime.broadcast( redraw_event.clone(), core::event::Status::Ignored, + id, ); let _ = control_sender.start_send(Control::ChangeFlow( @@ -802,7 +796,7 @@ async fn run_instance( events.push(( None, - core::Event::Window(id, window::Event::Closed), + core::Event::Window(window::Event::Closed), )); if window_manager.is_empty() { @@ -816,7 +810,6 @@ async fn run_instance( ); if let Some(event) = conversion::window_event( - id, window_event, window.state.scale_factor(), window.state.modifiers(), @@ -874,7 +867,7 @@ async fn run_instance( .into_iter() .zip(statuses.into_iter()) { - runtime.broadcast(event, status); + runtime.broadcast(event, status, id); } } -- cgit From ae2bf8ee40d1eb8f8176eae4541550fa2365f7a4 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Thu, 6 Jun 2024 02:13:06 +0200 Subject: Broadcast orphaned events in `multi_window` runtime --- winit/src/multi_window.rs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 3696f952..b4c30a20 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -491,7 +491,7 @@ async fn run_instance( let mut clipboard = Clipboard::connect(&main_window.raw); let mut events = { vec![( - Some(window::Id::MAIN), + window::Id::MAIN, core::Event::Window(window::Event::Opened { position: main_window.position(), size: main_window.size(), @@ -561,7 +561,7 @@ async fn run_instance( let _ = ui_caches.insert(id, user_interface::Cache::default()); events.push(( - Some(id), + id, core::Event::Window(window::Event::Opened { position: window.position(), size: window.size(), @@ -588,7 +588,7 @@ async fn run_instance( use crate::core::event; events.push(( - None, + window::Id::MAIN, event::Event::PlatformSpecific( event::PlatformSpecific::MacOS( event::MacOS::ReceivedUrl(url), @@ -795,7 +795,7 @@ async fn run_instance( let _ = ui_caches.remove(&id); events.push(( - None, + id, core::Event::Window(window::Event::Closed), )); @@ -814,7 +814,7 @@ async fn run_instance( window.state.scale_factor(), window.state.modifiers(), ) { - events.push((Some(id), event)); + events.push((id, event)); } } } @@ -830,8 +830,7 @@ async fn run_instance( let mut window_events = vec![]; events.retain(|(window_id, event)| { - if *window_id == Some(id) || window_id.is_none() - { + if *window_id == id { window_events.push(event.clone()); false } else { @@ -871,6 +870,14 @@ async fn run_instance( } } + for (id, event) in events.drain(..) { + runtime.broadcast( + event, + core::event::Status::Ignored, + id, + ); + } + debug.event_processing_finished(); // TODO mw application update returns which window IDs to update -- cgit From 83296a73ebbb3c02ed63dfb4661056a8a8962267 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Fri, 7 Jun 2024 01:59:17 +0200 Subject: Fix widget operations in `multi_window` runtime --- winit/src/multi_window.rs | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index b4c30a20..13839828 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -1272,25 +1272,20 @@ fn run_command( std::mem::take(ui_caches), ); - 'operate: while let Some(mut operation) = - current_operation.take() - { + while let Some(mut operation) = current_operation.take() { for (id, ui) in uis.iter_mut() { if let Some(window) = window_manager.get_mut(*id) { ui.operate(&window.renderer, operation.as_mut()); + } + } - match operation.finish() { - operation::Outcome::None => {} - operation::Outcome::Some(message) => { - proxy.send(message); - - // operation completed, don't need to try to operate on rest of UIs - break 'operate; - } - operation::Outcome::Chain(next) => { - current_operation = Some(next); - } - } + match operation.finish() { + operation::Outcome::None => {} + operation::Outcome::Some(message) => { + proxy.send(message); + } + operation::Outcome::Chain(next) => { + current_operation = Some(next); } } } -- cgit From 5d7dcf417c694853a606b8fb0a47a580277fc9c0 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 11 Jun 2024 19:41:05 +0200 Subject: Introduce `subscription::Event` ... and remove `PlatformSpecific` from `Event` --- core/src/event.rs | 21 ---------------- core/src/program.rs | 1 + examples/url_handler/src/main.rs | 17 ++++--------- futures/src/event.rs | 43 +++++++++++++++++++++++++++---- futures/src/keyboard.rs | 42 +++++++++++++------------------ futures/src/runtime.rs | 11 ++------ futures/src/subscription.rs | 50 +++++++++++++++++++++++++++++++------ futures/src/subscription/tracker.rs | 19 +++----------- src/lib.rs | 6 +++-- widget/src/canvas.rs | 2 +- widget/src/shader.rs | 2 +- winit/src/application.rs | 29 +++++++++++---------- winit/src/multi_window.rs | 42 ++++++++++++++++++------------- 13 files changed, 156 insertions(+), 129 deletions(-) create mode 100644 core/src/program.rs diff --git a/core/src/event.rs b/core/src/event.rs index 953cd73f..b6cf321e 100644 --- a/core/src/event.rs +++ b/core/src/event.rs @@ -23,27 +23,6 @@ pub enum Event { /// A touch event Touch(touch::Event), - - /// A platform specific event - PlatformSpecific(PlatformSpecific), -} - -/// A platform specific event -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum PlatformSpecific { - /// A MacOS specific event - MacOS(MacOS), -} - -/// Describes an event specific to MacOS -#[derive(Debug, Clone, PartialEq, Eq)] -pub enum MacOS { - /// Triggered when the app receives an URL from the system - /// - /// _**Note:** For this event to be triggered, the executable needs to be properly [bundled]!_ - /// - /// [bundled]: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW19 - ReceivedUrl(String), } /// The status of an [`Event`] after being processed. diff --git a/core/src/program.rs b/core/src/program.rs new file mode 100644 index 00000000..16fd7e8f --- /dev/null +++ b/core/src/program.rs @@ -0,0 +1 @@ +use crate::window; diff --git a/examples/url_handler/src/main.rs b/examples/url_handler/src/main.rs index 800a188b..3ab19252 100644 --- a/examples/url_handler/src/main.rs +++ b/examples/url_handler/src/main.rs @@ -1,4 +1,4 @@ -use iced::event::{self, Event}; +use iced::event; use iced::widget::{center, text}; use iced::{Element, Subscription}; @@ -15,27 +15,20 @@ struct App { #[derive(Debug, Clone)] enum Message { - EventOccurred(Event), + UrlReceived(String), } impl App { fn update(&mut self, message: Message) { match message { - Message::EventOccurred(event) => { - if let Event::PlatformSpecific( - event::PlatformSpecific::MacOS(event::MacOS::ReceivedUrl( - url, - )), - ) = event - { - self.url = Some(url); - } + Message::UrlReceived(url) => { + self.url = Some(url); } } } fn subscription(&self) -> Subscription { - event::listen().map(Message::EventOccurred) + event::listen_url().map(Message::UrlReceived) } fn view(&self) -> Element { diff --git a/futures/src/event.rs b/futures/src/event.rs index 4f3342ca..72ea78ad 100644 --- a/futures/src/event.rs +++ b/futures/src/event.rs @@ -32,11 +32,17 @@ where #[derive(Hash)] struct EventsWith; - subscription::filter_map((EventsWith, f), move |event, status, window| { - match event { - Event::Window(window::Event::RedrawRequested(_)) => None, - _ => f(event, status, window), + subscription::filter_map((EventsWith, f), move |event| match event { + subscription::Event::Interaction { + event: Event::Window(window::Event::RedrawRequested(_)), + .. } + | subscription::Event::PlatformSpecific(_) => None, + subscription::Event::Interaction { + window, + event, + status, + } => f(event, status, window), }) } @@ -54,5 +60,32 @@ where #[derive(Hash)] struct RawEvents; - subscription::filter_map((RawEvents, f), f) + subscription::filter_map((RawEvents, f), move |event| match event { + subscription::Event::Interaction { + window, + event, + status, + } => f(event, status, window), + subscription::Event::PlatformSpecific(_) => None, + }) +} + +/// Creates a [`Subscription`] that notifies of custom application URL +/// received from the system. +/// +/// _**Note:** Currently, it only triggers on macOS and the executable needs to be properly [bundled]!_ +/// +/// [bundled]: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW19 +pub fn listen_url() -> Subscription { + #[derive(Hash)] + struct ListenUrl; + + subscription::filter_map(ListenUrl, move |event| match event { + subscription::Event::PlatformSpecific( + subscription::PlatformSpecific::MacOS( + subscription::MacOS::ReceivedUrl(url), + ), + ) => Some(url), + _ => None, + }) } diff --git a/futures/src/keyboard.rs b/futures/src/keyboard.rs index 43ed7742..f0d7d757 100644 --- a/futures/src/keyboard.rs +++ b/futures/src/keyboard.rs @@ -1,5 +1,6 @@ //! Listen to keyboard events. use crate::core; +use crate::core::event; use crate::core::keyboard::{Event, Key, Modifiers}; use crate::subscription::{self, Subscription}; use crate::MaybeSend; @@ -18,16 +19,14 @@ where #[derive(Hash)] struct OnKeyPress; - subscription::filter_map((OnKeyPress, f), move |event, status, _window| { - match (event, status) { - ( - core::Event::Keyboard(Event::KeyPressed { - key, modifiers, .. - }), - core::event::Status::Ignored, - ) => f(key, modifiers), - _ => None, - } + subscription::filter_map((OnKeyPress, f), move |event| match event { + subscription::Event::Interaction { + event: + core::Event::Keyboard(Event::KeyPressed { key, modifiers, .. }), + status: event::Status::Ignored, + .. + } => f(key, modifiers), + _ => None, }) } @@ -45,18 +44,13 @@ where #[derive(Hash)] struct OnKeyRelease; - subscription::filter_map( - (OnKeyRelease, f), - move |event, status, _window| match (event, status) { - ( - core::Event::Keyboard(Event::KeyReleased { - key, - modifiers, - .. - }), - core::event::Status::Ignored, - ) => f(key, modifiers), - _ => None, - }, - ) + subscription::filter_map((OnKeyRelease, f), move |event| match event { + subscription::Event::Interaction { + event: + core::Event::Keyboard(Event::KeyReleased { key, modifiers, .. }), + status: event::Status::Ignored, + .. + } => f(key, modifiers), + _ => None, + }) } diff --git a/futures/src/runtime.rs b/futures/src/runtime.rs index ae55f814..157e2c67 100644 --- a/futures/src/runtime.rs +++ b/futures/src/runtime.rs @@ -1,6 +1,4 @@ //! Run commands and keep track of subscriptions. -use crate::core::event::{self, Event}; -use crate::core::window; use crate::subscription; use crate::{BoxFuture, BoxStream, Executor, MaybeSend}; @@ -128,12 +126,7 @@ where /// See [`Tracker::broadcast`] to learn more. /// /// [`Tracker::broadcast`]: subscription::Tracker::broadcast - pub fn broadcast( - &mut self, - event: Event, - status: event::Status, - window: window::Id, - ) { - self.subscriptions.broadcast(event, status, window); + pub fn broadcast(&mut self, event: subscription::Event) { + self.subscriptions.broadcast(event); } } diff --git a/futures/src/subscription.rs b/futures/src/subscription.rs index 79cea6ed..316fc44d 100644 --- a/futures/src/subscription.rs +++ b/futures/src/subscription.rs @@ -3,7 +3,7 @@ mod tracker; pub use tracker::Tracker; -use crate::core::event::{self, Event}; +use crate::core::event; use crate::core::window; use crate::futures::{Future, Stream}; use crate::{BoxStream, MaybeSend}; @@ -13,10 +13,48 @@ use futures::never::Never; use std::any::TypeId; use std::hash::Hash; +/// A subscription event. +#[derive(Debug, Clone, PartialEq)] +pub enum Event { + /// A user interacted with a user interface in a window. + Interaction { + /// The window holding the interface of the interaction. + window: window::Id, + /// The [`Event`] describing the interaction. + /// + /// [`Event`]: event::Event + event: event::Event, + + /// The [`event::Status`] of the interaction. + status: event::Status, + }, + + /// A platform specific event. + PlatformSpecific(PlatformSpecific), +} + +/// A platform specific event +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum PlatformSpecific { + /// A MacOS specific event + MacOS(MacOS), +} + +/// Describes an event specific to MacOS +#[derive(Debug, Clone, PartialEq, Eq)] +pub enum MacOS { + /// Triggered when the app receives an URL from the system + /// + /// _**Note:** For this event to be triggered, the executable needs to be properly [bundled]!_ + /// + /// [bundled]: https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFBundles/BundleTypes/BundleTypes.html#//apple_ref/doc/uid/10000123i-CH101-SW19 + ReceivedUrl(String), +} + /// A stream of runtime events. /// /// It is the input of a [`Subscription`]. -pub type EventStream = BoxStream<(Event, event::Status, window::Id)>; +pub type EventStream = BoxStream; /// The hasher used for identifying subscriptions. pub type Hasher = rustc_hash::FxHasher; @@ -290,9 +328,7 @@ where pub(crate) fn filter_map(id: I, f: F) -> Subscription where I: Hash + 'static, - F: Fn(Event, event::Status, window::Id) -> Option - + MaybeSend - + 'static, + F: Fn(Event) -> Option + MaybeSend + 'static, Message: 'static + MaybeSend, { Subscription::from_recipe(Runner { @@ -301,9 +337,7 @@ where use futures::future; use futures::stream::StreamExt; - events.filter_map(move |(event, status, window)| { - future::ready(f(event, status, window)) - }) + events.filter_map(move |event| future::ready(f(event))) }, }) } diff --git a/futures/src/subscription/tracker.rs b/futures/src/subscription/tracker.rs index 086b0f09..f17e3ea3 100644 --- a/futures/src/subscription/tracker.rs +++ b/futures/src/subscription/tracker.rs @@ -1,6 +1,4 @@ -use crate::core::event::{self, Event}; -use crate::core::window; -use crate::subscription::{Hasher, Recipe}; +use crate::subscription::{Event, Hasher, Recipe}; use crate::{BoxFuture, MaybeSend}; use futures::channel::mpsc; @@ -24,9 +22,7 @@ pub struct Tracker { #[derive(Debug)] pub struct Execution { _cancel: futures::channel::oneshot::Sender<()>, - listener: Option< - futures::channel::mpsc::Sender<(Event, event::Status, window::Id)>, - >, + listener: Option>, } impl Tracker { @@ -142,19 +138,12 @@ impl Tracker { /// currently open. /// /// [`Recipe::stream`]: crate::subscription::Recipe::stream - pub fn broadcast( - &mut self, - event: Event, - status: event::Status, - window: window::Id, - ) { + pub fn broadcast(&mut self, event: Event) { self.subscriptions .values_mut() .filter_map(|connection| connection.listener.as_mut()) .for_each(|listener| { - if let Err(error) = - listener.try_send((event.clone(), status, window)) - { + if let Err(error) = listener.try_send(event.clone()) { log::warn!( "Error sending event to subscription: {error:?}" ); diff --git a/src/lib.rs b/src/lib.rs index 50ee7ecc..317d25a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -236,8 +236,10 @@ pub mod font { pub mod event { //! Handle events of a user interface. - pub use crate::core::event::{Event, MacOS, PlatformSpecific, Status}; - pub use iced_futures::event::{listen, listen_raw, listen_with}; + pub use crate::core::event::{Event, Status}; + pub use iced_futures::event::{ + listen, listen_raw, listen_url, listen_with, + }; } pub mod keyboard { diff --git a/widget/src/canvas.rs b/widget/src/canvas.rs index be09f163..73cef087 100644 --- a/widget/src/canvas.rs +++ b/widget/src/canvas.rs @@ -172,7 +172,7 @@ where core::Event::Keyboard(keyboard_event) => { Some(Event::Keyboard(keyboard_event)) } - _ => None, + core::Event::Window(_) => None, }; if let Some(canvas_event) = canvas_event { diff --git a/widget/src/shader.rs b/widget/src/shader.rs index 473cfd0d..3c81f8ed 100644 --- a/widget/src/shader.rs +++ b/widget/src/shader.rs @@ -110,7 +110,7 @@ where core::Event::Window(window::Event::RedrawRequested(instant)) => { Some(Event::RedrawRequested(instant)) } - _ => None, + core::Event::Window(_) => None, }; if let Some(custom_shader_event) = custom_shader_event { diff --git a/winit/src/application.rs b/winit/src/application.rs index ed8715d8..d93ea42e 100644 --- a/winit/src/application.rs +++ b/winit/src/application.rs @@ -12,7 +12,8 @@ use crate::core::widget::operation; use crate::core::window; use crate::core::{Color, Event, Point, Size, Theme}; use crate::futures::futures; -use crate::futures::{Executor, Runtime, Subscription}; +use crate::futures::subscription::{self, Subscription}; +use crate::futures::{Executor, Runtime}; use crate::graphics; use crate::graphics::compositor::{self, Compositor}; use crate::runtime::clipboard; @@ -574,12 +575,10 @@ async fn run_instance( event::Event::PlatformSpecific(event::PlatformSpecific::MacOS( event::MacOS::ReceivedUrl(url), )) => { - use crate::core::event; - - events.push(Event::PlatformSpecific( - event::PlatformSpecific::MacOS(event::MacOS::ReceivedUrl( - url, - )), + runtime.broadcast(subscription::Event::PlatformSpecific( + subscription::PlatformSpecific::MacOS( + subscription::MacOS::ReceivedUrl(url), + ), )); } event::Event::UserEvent(message) => { @@ -650,11 +649,11 @@ async fn run_instance( _ => ControlFlow::Wait, }); - runtime.broadcast( - redraw_event, - core::event::Status::Ignored, - window::Id::MAIN, - ); + runtime.broadcast(subscription::Event::Interaction { + window: window::Id::MAIN, + event: redraw_event, + status: core::event::Status::Ignored, + }); debug.draw_started(); let new_mouse_interaction = user_interface.draw( @@ -744,7 +743,11 @@ async fn run_instance( for (event, status) in events.drain(..).zip(statuses.into_iter()) { - runtime.broadcast(event, status, window::Id::MAIN); + runtime.broadcast(subscription::Event::Interaction { + window: window::Id::MAIN, + event, + status, + }); } if !messages.is_empty() diff --git a/winit/src/multi_window.rs b/winit/src/multi_window.rs index 13839828..2eaf9241 100644 --- a/winit/src/multi_window.rs +++ b/winit/src/multi_window.rs @@ -16,7 +16,8 @@ use crate::futures::futures::channel::oneshot; use crate::futures::futures::executor; use crate::futures::futures::task; use crate::futures::futures::{Future, StreamExt}; -use crate::futures::{Executor, Runtime, Subscription}; +use crate::futures::subscription::{self, Subscription}; +use crate::futures::{Executor, Runtime}; use crate::graphics; use crate::graphics::{compositor, Compositor}; use crate::multi_window::window_manager::WindowManager; @@ -585,16 +586,13 @@ async fn run_instance( event::MacOS::ReceivedUrl(url), ), ) => { - use crate::core::event; - - events.push(( - window::Id::MAIN, - 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(message) => { messages.push(message); @@ -655,11 +653,11 @@ async fn run_instance( window.mouse_interaction = new_mouse_interaction; } - runtime.broadcast( - redraw_event.clone(), - core::event::Status::Ignored, - id, - ); + runtime.broadcast(subscription::Event::Interaction { + window: id, + event: redraw_event, + status: core::event::Status::Ignored, + }); let _ = control_sender.start_send(Control::ChangeFlow( match ui_state { @@ -866,15 +864,23 @@ async fn run_instance( .into_iter() .zip(statuses.into_iter()) { - runtime.broadcast(event, status, id); + runtime.broadcast( + subscription::Event::Interaction { + window: id, + event, + status, + }, + ); } } for (id, event) in events.drain(..) { runtime.broadcast( - event, - core::event::Status::Ignored, - id, + subscription::Event::Interaction { + window: id, + event, + status: core::event::Status::Ignored, + }, ); } -- cgit From 6a03b8489b0a92535963b123b4ab91e485f6689b Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 11 Jun 2024 20:03:28 +0200 Subject: Remove `tracing` leftovers in `iced_wgpu` --- wgpu/src/quad/gradient.rs | 3 --- wgpu/src/quad/solid.rs | 3 --- 2 files changed, 6 deletions(-) diff --git a/wgpu/src/quad/gradient.rs b/wgpu/src/quad/gradient.rs index 5b32c52a..13dc10f8 100644 --- a/wgpu/src/quad/gradient.rs +++ b/wgpu/src/quad/gradient.rs @@ -188,9 +188,6 @@ impl Pipeline { layer: &'a Layer, range: Range, ) { - #[cfg(feature = "tracing")] - let _ = tracing::info_span!("Wgpu::Quad::Gradient", "DRAW").entered(); - #[cfg(not(target_arch = "wasm32"))] { render_pass.set_pipeline(&self.pipeline); diff --git a/wgpu/src/quad/solid.rs b/wgpu/src/quad/solid.rs index 1cead367..45039a2d 100644 --- a/wgpu/src/quad/solid.rs +++ b/wgpu/src/quad/solid.rs @@ -144,9 +144,6 @@ impl Pipeline { layer: &'a Layer, range: Range, ) { - #[cfg(feature = "tracing")] - let _ = tracing::info_span!("Wgpu::Quad::Solid", "DRAW").entered(); - render_pass.set_pipeline(&self.pipeline); render_pass.set_bind_group(0, constants, &[]); render_pass.set_vertex_buffer(0, layer.instances.slice(..)); -- cgit From df85d85a6fa1e50dc0e21b0b0580eb5f797a80fd Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 11 Jun 2024 20:07:06 +0200 Subject: Allow `dead_code` in `widget::lazy::cache` --- widget/src/lazy/cache.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/widget/src/lazy/cache.rs b/widget/src/lazy/cache.rs index f922fd19..b341c234 100644 --- a/widget/src/lazy/cache.rs +++ b/widget/src/lazy/cache.rs @@ -1,3 +1,4 @@ +#![allow(dead_code)] use crate::core::overlay; use crate::core::Element; -- cgit From 6ea7846d88915f8d820c5126d7757f1346234522 Mon Sep 17 00:00:00 2001 From: Héctor Ramón Jiménez Date: Tue, 11 Jun 2024 20:11:55 +0200 Subject: Remove `core::program` module leftover --- core/src/program.rs | 1 - 1 file changed, 1 deletion(-) delete mode 100644 core/src/program.rs diff --git a/core/src/program.rs b/core/src/program.rs deleted file mode 100644 index 16fd7e8f..00000000 --- a/core/src/program.rs +++ /dev/null @@ -1 +0,0 @@ -use crate::window; -- cgit