diff --git a/examples/applet/src/window.rs b/examples/applet/src/window.rs index f77bf512..e1163f1b 100644 --- a/examples/applet/src/window.rs +++ b/examples/applet/src/window.rs @@ -35,7 +35,7 @@ pub enum Message { PopupClosed(Id), ToggleExampleRow(bool), Selected(usize), - Surface(cosmic::surface::Action), + Surface(cosmic::surface::Action), Toggle(bool), } @@ -76,9 +76,7 @@ impl cosmic::Application for Window { self.example_row = toggled; } Message::Surface(a) => { - return cosmic::task::message(cosmic::Action::Cosmic( - cosmic::app::Action::Surface(a), - )); + return cosmic::task::message(cosmic::Action::Surface(a)); } Message::Selected(i) => { self.selected = Some(i); diff --git a/examples/application/src/main.rs b/examples/application/src/main.rs index af4200c9..18ed32a4 100644 --- a/examples/application/src/main.rs +++ b/examples/application/src/main.rs @@ -98,7 +98,7 @@ pub enum Message { Input2(String), Ignore, ToggleHide, - Surface(cosmic::surface::Action), + Surface(cosmic::surface::Action), Hi, Hi2, Hi3, @@ -255,9 +255,7 @@ impl cosmic::Application for App { self.hidden = !self.hidden; } Message::Surface(a) => { - return cosmic::task::message(cosmic::Action::Cosmic( - cosmic::app::Action::Surface(a), - )); + return cosmic::task::message(cosmic::Action::Surface(a)); } Message::Hi => { dbg!("hi"); diff --git a/examples/context-menu/src/main.rs b/examples/context-menu/src/main.rs index 50c76bfb..e10bb48c 100644 --- a/examples/context-menu/src/main.rs +++ b/examples/context-menu/src/main.rs @@ -28,7 +28,7 @@ fn main() -> Result<(), Box> { pub enum Message { Clicked, WindowClose, - Surface(cosmic::surface::Action), + Surface(cosmic::surface::Action), ToggleHideContent, ToggleSomeAction, WindowNew, @@ -89,9 +89,7 @@ impl cosmic::Application for App { self.button_label = format!("Clicked {message:?}"); } Message::Surface(action) => { - return cosmic::task::message(cosmic::Action::Cosmic( - cosmic::app::Action::Surface(action), - )); + return cosmic::task::message(cosmic::Action::Surface(action)); } Message::WindowClose | Message::ToggleHideContent diff --git a/examples/open-dialog/src/main.rs b/examples/open-dialog/src/main.rs index b4b5343f..3a12aaa5 100644 --- a/examples/open-dialog/src/main.rs +++ b/examples/open-dialog/src/main.rs @@ -34,7 +34,7 @@ pub enum Message { OpenError(Arc), OpenFile, Selected(Url), - Surface(cosmic::surface::Action), + Surface(cosmic::surface::Action), } /// The [`App`] stores application-specific state. @@ -187,9 +187,7 @@ impl cosmic::Application for App { self.error_status = None; } Message::Surface(action) => { - return cosmic::task::message(cosmic::Action::Cosmic( - cosmic::app::Action::Surface(action), - )); + return cosmic::task::message(cosmic::Action::Surface(action)); } } diff --git a/src/action.rs b/src/action.rs index b7162896..6321de28 100644 --- a/src/action.rs +++ b/src/action.rs @@ -18,6 +18,11 @@ pub const fn none() -> Action { Action::None } +/// Wrap a surface action, typically produced by a widget, to be handled by libcosmic. +pub const fn surface(action: crate::surface::Action) -> Action { + Action::Surface(action) +} + #[derive(Clone, Debug)] #[must_use] pub enum Action { @@ -29,10 +34,45 @@ pub enum Action { #[cfg(feature = "single-instance")] /// Dbus activation messages DbusActivation(dbus_activation::Message), + /// Surface (popup, subsurface, window, layer shell) requests, handled by libcosmic. + Surface(crate::surface::Action), /// Do nothing None, } +impl Action { + /// Map the application message inside, leaving libcosmic's own variants untouched. + #[must_use] + pub fn map(self, f: impl Fn(M) -> N + Clone + Send + Sync + 'static) -> Action { + match self { + Action::App(message) => Action::App(f(message)), + #[cfg(feature = "winit")] + Action::Cosmic(action) => Action::Cosmic(action), + #[cfg(feature = "single-instance")] + Action::DbusActivation(message) => Action::DbusActivation(message), + Action::Surface(action) => Action::Surface(action.map(f)), + Action::None => Action::None, + } + } +} + +impl Action> { + /// Collapse a doubly wrapped action, as produced by widgets whose message type is already + /// an [`Action`], into a single one. + #[must_use] + pub fn flatten(self) -> Action { + match self { + Action::App(action) => action, + #[cfg(feature = "winit")] + Action::Cosmic(action) => Action::Cosmic(action), + #[cfg(feature = "single-instance")] + Action::DbusActivation(message) => Action::DbusActivation(message), + Action::Surface(action) => Action::Surface(action.flatten()), + Action::None => Action::None, + } + } +} + impl From for Action { fn from(value: M) -> Self { Self::App(value) diff --git a/src/app/action.rs b/src/app/action.rs index 873622da..bf240dda 100644 --- a/src/app/action.rs +++ b/src/app/action.rs @@ -45,8 +45,6 @@ pub enum Action { /// Tracks updates to window suggested size. #[cfg(feature = "applet")] SuggestedBounds(Option), - /// Internal surface message - Surface(surface::Action), /// Notifies that a surface was closed. /// Any data relating to the surface should be cleaned up. SurfaceClosed(iced::window::Id), diff --git a/src/app/cosmic.rs b/src/app/cosmic.rs index ce8a4154..c070f3e4 100644 --- a/src/app/cosmic.rs +++ b/src/app/cosmic.rs @@ -154,7 +154,7 @@ where #[allow(clippy::too_many_lines)] pub fn surface_update( &mut self, - _surface_message: crate::surface::Action, + _surface_message: crate::surface::Action, ) -> iced::Task> { #[cfg(feature = "surface-message")] match _surface_message { @@ -195,18 +195,7 @@ where }; let settings = settings(); - if let Some(view) = view.and_then(|view| { - match std::sync::Arc::try_unwrap(view).ok()?.downcast:: Element<'static, crate::Action> + Send + Sync, - >>() { - Ok(v) => Some(v), - Err(err) => { - tracing::error!("Invalid view for subsurface view: {err:?}"); - - None - } - } - }) { + if let Some(view) = view { self.get_subsurface(settings, Some(Box::new(move |_| view()))) } else { self.get_subsurface(settings, None) @@ -302,17 +291,7 @@ where let settings = settings(); let live_settings = Box::new(move |_: &T| live_settings()); - if let Some(view) = view.and_then(|view| { - match std::sync::Arc::try_unwrap(view).ok()?.downcast:: Element<'static, crate::Action> + Send + Sync, - >>() { - Ok(v) => Some(v), - Err(err) => { - tracing::error!("Invalid view for subsurface view: {err:?}"); - None - } - } - }) { + if let Some(view) = view { self.get_popup(settings, live_settings, Some(Box::new(move |_| view()))) } else { self.get_popup(settings, live_settings, None) @@ -378,17 +357,7 @@ where return Task::none(); }; - if let Some(view) = view.and_then(|view| { - match std::sync::Arc::try_unwrap(view).ok()?.downcast:: Element<'static, crate::Action> + Send + Sync, - >>() { - Ok(v) => Some(v), - Err(err) => { - tracing::error!("Invalid view for Window: {err:?}"); - None - } - } - }) { + if let Some(view) = view { let settings = settings(); self.get_window( @@ -410,9 +379,7 @@ where } crate::surface::Action::Ignore => iced::Task::none(), - crate::surface::Action::Task(f) => { - f().map(|sm| crate::Action::Cosmic(Action::Surface(sm))) - } + crate::surface::Action::Task(f) => f().map(crate::Action::Surface), #[cfg(wayland_platform)] crate::surface::Action::AppLayerShell(settings, live_settings, view) => { let Some(settings) = std::sync::Arc::try_unwrap(settings) @@ -475,17 +442,7 @@ where let live_settings = live_settings(); let live_settings = Box::new(move |_app: &T| live_settings); - if let Some(view) = view.and_then(|view| { - match std::sync::Arc::try_unwrap(view).ok()?.downcast:: Element<'static, crate::Action> + Send + Sync, - >>() { - Ok(v) => Some(v), - Err(err) => { - tracing::error!("Invalid view for layer surface: {err:?}"); - None - } - } - }) { + if let Some(view) = view { self.get_layer_shell(settings, live_settings, Some(Box::new(move |_| view()))) } else { self.get_layer_shell(settings, live_settings, None) @@ -516,6 +473,7 @@ where let mut task = match message { crate::Action::App(message) => self.app.update(message), crate::Action::Cosmic(message) => self.cosmic_update(message), + crate::Action::Surface(action) => self.surface_update(action), crate::Action::None => iced::Task::none(), #[cfg(feature = "single-instance")] crate::Action::DbusActivation(message) => { @@ -1228,8 +1186,6 @@ impl Cosmic { } } - Action::Surface(action) => return self.surface_update(action), - Action::SurfaceClosed(id) => { if self.opened_surfaces.get_mut(&id).is_some_and(|v| { *v = v.saturating_sub(1); diff --git a/src/app/mod.rs b/src/app/mod.rs index d963b7dd..84cf57f8 100644 --- a/src/app/mod.rs +++ b/src/app/mod.rs @@ -394,7 +394,7 @@ where { nav = nav .window_id_maybe(self.core().main_window_id()) - .on_surface_action(|m| crate::Action::Cosmic(crate::app::Action::Surface(m))) + .on_surface_action(|action| crate::Action::Surface(action.flatten())) } let mut nav = nav .into_container() diff --git a/src/applet/mod.rs b/src/applet/mod.rs index 37635bf4..555ec837 100644 --- a/src/applet/mod.rs +++ b/src/applet/mod.rs @@ -295,7 +295,7 @@ impl Context { content: impl Into>, tooltip: impl Into>, has_popup: bool, - on_surface_action: impl Fn(crate::surface::Action) -> Message + 'static, + on_surface_action: impl Fn(crate::surface::Action) -> Message + 'static, parent_id: Option, ) -> crate::widget::wayland::tooltip::widget::Tooltip<'a, Message, Message> { let window_id = *TOOLTIP_WINDOW_ID; diff --git a/src/surface/action.rs b/src/surface/action.rs index 6620c34f..a4308306 100644 --- a/src/surface/action.rs +++ b/src/surface/action.rs @@ -1,7 +1,7 @@ // Copyright 2025 System76 // SPDX-License-Identifier: MPL-2.0 -use super::Action; +use super::{Action, View}; #[cfg(feature = "winit")] use crate::Application; @@ -11,30 +11,31 @@ use iced_runtime::platform_specific::wayland::CornerRadius; #[cfg(wayland_platform)] use iced_runtime::platform_specific::wayland::layer_surface::IcedMargin; use std::any::Any; + use std::sync::Arc; /// Used to produce a destroy popup message from within a widget. #[cfg(wayland_platform)] #[must_use] -pub fn destroy_popup(id: iced_core::window::Id) -> Action { +pub fn destroy_popup(id: iced_core::window::Id) -> Action { Action::DestroyPopup(id) } #[cfg(wayland_platform)] #[must_use] -pub fn destroy_subsurface(id: iced_core::window::Id) -> Action { +pub fn destroy_subsurface(id: iced_core::window::Id) -> Action { Action::DestroySubsurface(id) } #[cfg(wayland_platform)] #[must_use] -pub fn destroy_window(id: iced_core::window::Id) -> Action { +pub fn destroy_window(id: iced_core::window::Id) -> Action { Action::DestroyWindow(id) } #[cfg(wayland_platform)] #[must_use] -pub fn destroy_layer_shell(id: iced_core::window::Id) -> Action { +pub fn destroy_layer_shell(id: iced_core::window::Id) -> Action { Action::DestroyLayerShell(id) } @@ -66,7 +67,7 @@ pub fn app_window( live_settings: impl Fn(&App) -> LiveSettings + Send + Sync + 'static, settings: impl Fn(&mut App) -> window::Settings + Send + Sync + 'static, view: BoxedView, -) -> (window::Id, Action) { +) -> (window::Id, Action) { let id = window::Id::unique(); let boxed: Box window::Settings + Send + Sync + 'static> = @@ -100,7 +101,7 @@ pub fn simple_window( view: Option< impl Fn() -> crate::Element<'static, crate::Action> + Send + Sync + 'static, >, -) -> (window::Id, Action) { +) -> (window::Id, Action) { let id = window::Id::unique(); let boxed: Box window::Settings + Send + Sync + 'static> = Box::new(settings); @@ -115,16 +116,7 @@ pub fn simple_window( id, Arc::new(boxed), Arc::new(boxed_live), - view.map(|view| { - let boxed: Box< - dyn Fn() -> crate::Element<'static, crate::Action> - + Send - + Sync - + 'static, - > = Box::new(view); - let boxed: Box = Box::new(boxed); - Arc::new(boxed) - }), + view.map(|view| Arc::new(view) as View), ), ) } @@ -138,7 +130,7 @@ pub fn app_popup( + Sync + 'static, view: BoxedView, -) -> Action { +) -> Action { let boxed: Box< dyn Fn(&mut App) -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings + Send @@ -172,7 +164,7 @@ pub fn simple_subsurface( view: Option< Box crate::Element<'static, crate::Action> + Send + Sync + 'static>, >, -) -> Action { +) -> Action { let boxed: Box< dyn Fn() -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send @@ -184,10 +176,7 @@ pub fn simple_subsurface( Action::Subsurface( Arc::new(boxed), Arc::new(Box::new(LiveSettings::default)), - view.map(|view| { - let boxed: Box = Box::new(view); - Arc::new(boxed) - }), + view.map(|view| Arc::from(view) as View), ) } @@ -203,7 +192,7 @@ pub fn simple_popup( view: Option< impl Fn() -> crate::Element<'static, crate::Action> + Send + Sync + 'static, >, -) -> Action { +) -> Action { let boxed: Box< dyn Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings + Send @@ -218,13 +207,7 @@ pub fn simple_popup( Action::Popup( Arc::new(boxed), Arc::new(boxed_live), - view.map(|view| { - let boxed: Box< - dyn Fn() -> crate::Element<'static, crate::Action> + Send + Sync + 'static, - > = Box::new(view); - let boxed: Box = Box::new(boxed); - Arc::new(boxed) - }), + view.map(|view| Arc::new(view) as View), ) } @@ -240,7 +223,7 @@ pub fn subsurface( + 'static, // XXX Boxed trait object is required for less cumbersome type inference, but we box it anyways. view: BoxedView, -) -> Action { +) -> Action { let boxed: Box< dyn Fn( &mut App, @@ -274,7 +257,7 @@ pub fn simple_layer_shell( view: Option< impl Fn() -> crate::Element<'static, crate::Action> + Send + Sync + 'static, >, -) -> Action { +) -> Action { let boxed: Box< dyn Fn() -> iced_runtime::platform_specific::wayland::layer_surface::SctkLayerSurfaceSettings @@ -288,13 +271,7 @@ pub fn simple_layer_shell( Action::LayerShell( Arc::new(boxed), Arc::new(boxed_live), - view.map(|view| { - let boxed: Box< - dyn Fn() -> crate::Element<'static, crate::Action> + Send + Sync + 'static, - > = Box::new(view); - let boxed: Box = Box::new(boxed); - Arc::new(boxed) - }), + view.map(|view| Arc::new(view) as View), ) } @@ -311,7 +288,7 @@ pub fn app_layer_shell( + 'static, // XXX Boxed trait object is required for less cumbersome type inference, but we box it anyways. view: BoxedView, -) -> Action { +) -> Action { let boxed: Box< dyn Fn( &mut App, diff --git a/src/surface/mod.rs b/src/surface/mod.rs index b0a4a819..09243da3 100644 --- a/src/surface/mod.rs +++ b/src/surface/mod.rs @@ -11,19 +11,28 @@ use std::sync::Arc; type BoxedSetting = Arc>; +/// Produces the content of a surface created from within a widget. +/// +/// Typed on the message the widget publishes. +pub type View = + Arc crate::Element<'static, crate::Action> + Send + Sync + 'static>; + /// Ignore this message in your application. It will be intercepted. +/// +/// `M` is the message type of whoever created the action. The ones prefixed with `App` take the +/// application itself and are type-erased, the others carry a [`View`] typed on `M`. #[derive(Clone)] -pub enum Action { +pub enum Action { /// Create a subsurface with a view function accepting the App as a parameter AppSubsurface(BoxedSetting, BoxedSetting, Option), /// Create a subsurface with a view function - Subsurface(BoxedSetting, BoxedSetting, Option), + Subsurface(BoxedSetting, BoxedSetting, Option>), /// Destroy a subsurface with a view function DestroySubsurface(iced::window::Id), /// Create a popup with a view function accepting the App as a parameter AppPopup(BoxedSetting, BoxedSetting, Option), /// Create a popup - Popup(BoxedSetting, BoxedSetting, Option), + Popup(BoxedSetting, BoxedSetting, Option>), /// Destroy a subsurface with a view function DestroyPopup(iced::window::Id), /// Destroys the global tooltip popup subsurface @@ -41,7 +50,7 @@ pub enum Action { iced::window::Id, BoxedSetting, BoxedSetting, - Option, + Option>, ), /// Destroy a window DestroyWindow(iced::window::Id), @@ -50,7 +59,7 @@ pub enum Action { AppLayerShell(BoxedSetting, BoxedSetting, Option), /// Create a layer shell surface with a view function - LayerShell(BoxedSetting, BoxedSetting, Option), + LayerShell(BoxedSetting, BoxedSetting, Option>), /// Destroy a layer shell surface DestroyLayerShell(iced::window::Id), @@ -66,15 +75,74 @@ pub enum Action { }, Ignore, SyncLiveSettings(iced::window::Id), - Task(Arc Task + Send + Sync>), + Task(Arc Task> + Send + Sync>), +} + +impl Action { + /// Re-type the action for a component whose messages are wrapped by `f`. + /// + /// Similar to [`iced::Element::map`]. A component that maps a widget's messages must + /// map the widget's surface actions too. + #[must_use] + pub fn map(self, f: impl Fn(M) -> N + Clone + Send + Sync + 'static) -> Action { + self.map_actions(move |action| action.map(f.clone())) + } + + fn map_actions( + self, + g: impl Fn(crate::Action) -> crate::Action + Clone + Send + Sync + 'static, + ) -> Action { + let map_view = |view: Option>| -> Option> { + let view = view?; + let g = g.clone(); + Some(Arc::new(move || view().map(g.clone()))) + }; + match self { + Action::AppSubsurface(a, b, c) => Action::AppSubsurface(a, b, c), + Action::Subsurface(a, b, view) => Action::Subsurface(a, b, map_view(view)), + Action::DestroySubsurface(id) => Action::DestroySubsurface(id), + Action::AppPopup(a, b, c) => Action::AppPopup(a, b, c), + Action::Popup(a, b, view) => Action::Popup(a, b, map_view(view)), + Action::DestroyPopup(id) => Action::DestroyPopup(id), + Action::DestroyTooltipPopup => Action::DestroyTooltipPopup, + Action::AppWindow(id, a, b, c) => Action::AppWindow(id, a, b, c), + Action::Window(id, a, b, view) => Action::Window(id, a, b, map_view(view)), + Action::DestroyWindow(id) => Action::DestroyWindow(id), + Action::AppLayerShell(a, b, c) => Action::AppLayerShell(a, b, c), + Action::LayerShell(a, b, view) => Action::LayerShell(a, b, map_view(view)), + Action::DestroyLayerShell(id) => Action::DestroyLayerShell(id), + Action::ResponsiveMenuBar { + menu_bar, + limits, + size, + } => Action::ResponsiveMenuBar { + menu_bar, + limits, + size, + }, + Action::Ignore => Action::Ignore, + Action::SyncLiveSettings(id) => Action::SyncLiveSettings(id), + Action::Task(task) => Action::Task(Arc::new(move || { + let g = g.clone(); + task().map(move |action| action.map_actions(g.clone())) + })), + } + } +} + +impl Action> { + #[must_use] + pub fn flatten(self) -> Action { + self.map_actions(crate::Action::flatten) + } } #[cfg(feature = "winit")] -pub fn surface_task(action: Action) -> Task> { - crate::task::message(crate::Action::Cosmic(crate::app::Action::Surface(action))) +pub fn surface_task(action: Action) -> Task> { + crate::task::message(crate::Action::Surface(action)) } -impl std::fmt::Debug for Action { +impl std::fmt::Debug for Action { #[cold] fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { @@ -84,11 +152,11 @@ impl std::fmt::Debug for Action { .field(arg1) .field(arg2) .finish(), - Self::Subsurface(arg0, arg1, arg2) => f + Self::Subsurface(arg0, arg1, view) => f .debug_tuple("Subsurface") .field(arg0) .field(arg1) - .field(arg2) + .field(&view.as_ref().map(|_| "view")) .finish(), Self::DestroySubsurface(arg0) => { f.debug_tuple("DestroySubsurface").field(arg0).finish() @@ -99,11 +167,11 @@ impl std::fmt::Debug for Action { .field(arg1) .field(arg2) .finish(), - Self::Popup(arg0, arg1, arg2) => f + Self::Popup(arg0, arg1, view) => f .debug_tuple("Popup") .field(arg0) .field(arg1) - .field(arg2) + .field(&view.as_ref().map(|_| "view")) .finish(), Self::DestroyPopup(arg0) => f.debug_tuple("DestroyPopup").field(arg0).finish(), Self::DestroyTooltipPopup => f.debug_tuple("DestroyTooltipPopup").finish(), @@ -125,12 +193,12 @@ impl std::fmt::Debug for Action { .field(arg1) .field(arg2) .finish(), - Self::Window(id, arg0, arg1, arg2) => f + Self::Window(id, arg0, arg1, view) => f .debug_tuple("Window") .field(id) .field(arg0) .field(arg1) - .field(arg2) + .field(&view.as_ref().map(|_| "view")) .finish(), Self::DestroyWindow(arg0) => f.debug_tuple("DestroyWindow").field(arg0).finish(), Self::Task(_) => f.debug_tuple("Future").finish(), @@ -140,11 +208,11 @@ impl std::fmt::Debug for Action { .field(arg1) .field(arg2) .finish(), - Self::LayerShell(arg, arg1, arg2) => f + Self::LayerShell(arg0, arg1, view) => f .debug_tuple("LayerShell") - .field(arg) + .field(arg0) .field(arg1) - .field(arg2) + .field(&view.as_ref().map(|_| "view")) .finish(), Self::DestroyLayerShell(arg0) => { f.debug_tuple("DestroyLayerShell").field(arg0).finish() diff --git a/src/widget/context_menu.rs b/src/widget/context_menu.rs index b4665f8f..87e3ebed 100644 --- a/src/widget/context_menu.rs +++ b/src/widget/context_menu.rs @@ -66,7 +66,7 @@ pub struct ContextMenu<'a, Message> { pub on_close: Option, #[setters(skip)] pub(crate) on_surface_action: - Option Message + Send + Sync + 'static>>, + Option) -> Message + Send + Sync + 'static>>, } impl ContextMenu<'_, Message> { @@ -239,7 +239,7 @@ impl ContextMenu<'_, Message> { pub fn on_surface_action( mut self, - handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static, + handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static, ) -> Self { self.on_surface_action = Some(Arc::new(handler)); self diff --git a/src/widget/dropdown/mod.rs b/src/widget/dropdown/mod.rs index d0ec175a..a5f0162b 100644 --- a/src/widget/dropdown/mod.rs +++ b/src/widget/dropdown/mod.rs @@ -44,7 +44,7 @@ pub fn popup_dropdown< selected: Option, on_selected: impl Fn(usize) -> Message + Send + Sync + 'static, _parent_id: window::Id, - _on_surface_action: impl Fn(surface::Action) -> Message + Send + Sync + 'static, + _on_surface_action: impl Fn(surface::Action) -> Message + Send + Sync + 'static, _map_action: impl Fn(Message) -> AppMessage + Send + Sync + 'static, ) -> Dropdown<'a, S, Message, AppMessage> { let dropdown: Dropdown<'_, S, Message, AppMessage> = diff --git a/src/widget/dropdown/widget.rs b/src/widget/dropdown/widget.rs index e38be851..cbdf9b5b 100644 --- a/src/widget/dropdown/widget.rs +++ b/src/widget/dropdown/widget.rs @@ -55,7 +55,8 @@ where #[setters(strip_option)] font: Option, #[setters(skip)] - on_surface_action: Option Message + Send + Sync + 'static>>, + on_surface_action: + Option) -> Message + Send + Sync + 'static>>, #[setters(skip)] action_map: Option AppMessage + 'static + Send + Sync>>, #[setters(strip_option)] @@ -109,7 +110,7 @@ where pub fn with_popup( self, parent_id: window::Id, - on_surface_action: impl Fn(surface::Action) -> Message + Send + Sync + 'static, + on_surface_action: impl Fn(surface::Action) -> Message + Send + Sync + 'static, action_map: impl Fn(Message) -> NewAppMessage + Send + Sync + 'static, ) -> Dropdown<'a, S, Message, NewAppMessage> { let Self { @@ -552,7 +553,9 @@ pub fn update< selections: &[S], state: impl FnOnce() -> &'a mut State, _window_id: Option, - on_surface_action: Option Message + Send + Sync + 'static>>, + on_surface_action: Option< + Arc) -> Message + Send + Sync + 'static>, + >, action_map: Option AppMessage + Send + Sync + 'static>>, icons: &[icon::Handle], gap: f32, diff --git a/src/widget/menu/menu_bar.rs b/src/widget/menu/menu_bar.rs index f82a46e8..14766603 100644 --- a/src/widget/menu/menu_bar.rs +++ b/src/widget/menu/menu_bar.rs @@ -188,7 +188,7 @@ pub struct MenuBar { #[cfg(wayland_platform)] positioner: iced_runtime::platform_specific::wayland::popup::SctkPositioner, pub(crate) on_surface_action: - Option Message + Send + Sync + 'static>>, + Option) -> Message + Send + Sync + 'static>>, } impl MenuBar @@ -340,7 +340,7 @@ where #[must_use] pub fn on_surface_action( mut self, - handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static, + handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static, ) -> Self { self.on_surface_action = Some(Arc::new(handler)); self diff --git a/src/widget/menu/menu_inner.rs b/src/widget/menu/menu_inner.rs index 0ec6110b..f01682b1 100644 --- a/src/widget/menu/menu_inner.rs +++ b/src/widget/menu/menu_inner.rs @@ -455,7 +455,7 @@ pub(crate) struct Menu<'b, Message: std::clone::Clone> { pub(crate) window_id: window::Id, pub(crate) depth: usize, pub(crate) on_surface_action: - Option Message + Send + Sync + 'static>>, + Option) -> Message + Send + Sync + 'static>>, } impl<'b, Message: Clone + 'static> Menu<'b, Message> { pub(crate) fn overlay(self) -> overlay::Element<'b, Message, crate::Theme, crate::Renderer> { diff --git a/src/widget/nav_bar.rs b/src/widget/nav_bar.rs index 14790866..84dd4a08 100644 --- a/src/widget/nav_bar.rs +++ b/src/widget/nav_bar.rs @@ -159,7 +159,7 @@ impl<'a, Message: Clone + 'static> NavBar<'a, Message> { #[must_use] pub fn on_surface_action( mut self, - handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static, + handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static, ) -> Self { self.segmented_button = self.segmented_button.on_surface_action(handler); self diff --git a/src/widget/responsive_container.rs b/src/widget/responsive_container.rs index e75b7a6b..8e89d9ec 100644 --- a/src/widget/responsive_container.rs +++ b/src/widget/responsive_container.rs @@ -11,7 +11,7 @@ use iced_core::{ pub(crate) fn responsive_container<'a, Message: 'static, Theme, E>( content: E, id: Id, - on_action: impl Fn(crate::surface::Action) -> Message + 'static, + on_action: impl Fn(crate::surface::Action) -> Message + 'static, ) -> ResponsiveContainer<'a, Message, Theme, crate::Renderer> where E: Into>, @@ -32,7 +32,7 @@ where content: Element<'a, Message, Theme, Renderer>, id: Id, size: Option, - on_action: Box Message>, + on_action: Box) -> Message>, } impl<'a, Message, Theme, Renderer> ResponsiveContainer<'a, Message, Theme, Renderer> @@ -43,7 +43,7 @@ where pub(crate) fn new( content: T, id: Id, - on_action: impl Fn(crate::surface::Action) -> Message + 'static, + on_action: impl Fn(crate::surface::Action) -> Message + 'static, ) -> Self where T: Into>, diff --git a/src/widget/responsive_menu_bar.rs b/src/widget/responsive_menu_bar.rs index b7b416ef..c698f571 100644 --- a/src/widget/responsive_menu_bar.rs +++ b/src/widget/responsive_menu_bar.rs @@ -79,7 +79,11 @@ impl ResponsiveMenuBar { core: &Core, key_binds: &HashMap, id: crate::widget::Id, - action_message: impl Fn(crate::surface::Action) -> Message + Send + Sync + Clone + 'static, + action_message: impl Fn(crate::surface::Action) -> Message + + Send + + Sync + + Clone + + 'static, trees: Vec<(S, Vec>)>, ) -> Element<'a, Message> { use crate::widget::id_container; diff --git a/src/widget/segmented_button/widget.rs b/src/widget/segmented_button/widget.rs index 822d0ea5..a2f5e19c 100644 --- a/src/widget/segmented_button/widget.rs +++ b/src/widget/segmented_button/widget.rs @@ -199,7 +199,7 @@ where positioner: iced_runtime::platform_specific::wayland::popup::SctkPositioner, #[setters(skip)] pub(crate) on_surface_action: - Option Message + Send + Sync + 'static>>, + Option) -> Message + Send + Sync + 'static>>, /// Defines the implementation of this struct variant: PhantomData, @@ -899,7 +899,7 @@ where #[must_use] pub fn on_surface_action( mut self, - handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static, + handler: impl Fn(crate::surface::Action) -> Message + Send + Sync + 'static, ) -> Self { self.on_surface_action = Some(Arc::new(handler)); self @@ -1073,7 +1073,7 @@ where + Sync + 'static, view: Option crate::Element<'static, Message> + Send + Sync + 'static>, - ) -> crate::surface::Action { + ) -> crate::surface::Action { use std::any::Any; let boxed: Box< @@ -1092,11 +1092,8 @@ where Arc::new(boxed), Arc::new(boxed_live), view.map(|view| { - let boxed: Box< - dyn Fn() -> crate::Element<'static, Message> + Send + Sync + 'static, - > = Box::new(view); - let boxed: Box = Box::new(boxed); - Arc::new(boxed) + Arc::new(move || view().map(crate::Action::App)) + as crate::surface::View }), ) } diff --git a/src/widget/wayland/tooltip/widget.rs b/src/widget/wayland/tooltip/widget.rs index b0287eed..c621d966 100644 --- a/src/widget/wayland/tooltip/widget.rs +++ b/src/widget/wayland/tooltip/widget.rs @@ -40,7 +40,7 @@ pub struct Tooltip<'a, Message, TopLevelMessage> { label: Option>, content: crate::Element<'a, Message>, on_leave: Message, - on_surface_action: Box Message>, + on_surface_action: Box) -> Message>, width: Length, height: Length, padding: Padding, @@ -75,7 +75,7 @@ impl<'a, Message, TopLevelMessage> Tooltip<'a, Message, TopLevelMessage> { + Sync + 'static, on_leave: Message, - on_surface_action: impl Fn(crate::surface::Action) -> Message + 'static, + on_surface_action: impl Fn(crate::surface::Action) -> Message + 'static, ) -> Self { Self { id: Id::unique(), @@ -440,7 +440,7 @@ pub fn update<'a, Message: Clone + 'static, TopLevelMessage: Clone + 'static>( >, delay: Option, on_leave: &Message, - on_surface_action: &dyn Fn(crate::surface::Action) -> Message, + on_surface_action: &dyn Fn(crate::surface::Action) -> Message, state: impl FnOnce() -> &'a mut State, ) { match event { @@ -534,19 +534,8 @@ pub fn update<'a, Message: Clone + 'static, TopLevelMessage: Clone + 'static>( crate::surface::Action::Popup( Arc::new(boxed), Arc::new(boxed_live), - Some({ - let boxed: Box< - dyn Fn() -> crate::Element< - 'static, - crate::Action, - > + Send - + Sync - + 'static, - > = Box::new(move || view()); - let boxed: Box = - Box::new(boxed); - Arc::new(boxed) - }), + Some(Arc::new(move || view()) + as crate::surface::View), ) }) })); @@ -583,19 +572,8 @@ pub fn update<'a, Message: Clone + 'static, TopLevelMessage: Clone + 'static>( let sm = crate::surface::Action::Popup( Arc::new(boxed), Arc::new(boxed_live), - Some({ - let boxed: Box< - dyn Fn() -> crate::Element< - 'static, - crate::Action, - > + Send - + Sync - + 'static, - > = Box::new(move || view()); - let boxed: Box = - Box::new(boxed); - Arc::new(boxed) - }), + Some(Arc::new(move || view()) + as crate::surface::View), ); shell.publish((on_surface_action)(sm)); }