improv: allow overrides for corner radius or blur that apply on creation as well

This commit is contained in:
Ashley Wulber 2026-05-15 14:27:17 -04:00 committed by Ashley Wulber
parent f268bb86cf
commit ac4a1ab259
9 changed files with 415 additions and 285 deletions

View file

@ -101,6 +101,7 @@ impl cosmic::Application for Window {
Message::Surface(destroy_popup(id))
} else {
Message::Surface(app_popup::<Window>(
|_| Default::default(),
move |state: &mut Window| {
let new_id = Id::unique();
state.popup = Some(new_id);

View file

@ -8,6 +8,8 @@ use std::sync::Arc;
use super::{Action, Application, ApplicationExt, Subscription};
#[cfg(all(feature = "wayland", target_os = "linux"))]
use crate::core::Auto;
#[cfg(all(feature = "wayland", target_os = "linux"))]
use crate::surface::action::LiveSettings;
use crate::theme::{THEME, Theme, ThemeType};
use crate::{Core, Element, keyboard_nav};
#[cfg(all(feature = "wayland", target_os = "linux"))]
@ -21,7 +23,7 @@ use iced::Application as IcedApplication;
use iced::event::wayland;
use iced::{Task, theme, window};
use iced_futures::event::listen_with;
#[cfg(all(feature = "wayland", target_os = "linux"))]
#[cfg(feature = "winit")]
use iced_winit::SurfaceIdWrapper;
use palette::color_difference::EuclideanDistance;
@ -87,16 +89,22 @@ fn init_windowing_system<M>(handle: window::raw_window_handle::WindowHandle) ->
#[derive(Default)]
pub struct Cosmic<App: Application> {
pub app: App,
#[cfg(all(feature = "wayland", target_os = "linux"))]
pub surface_views: HashMap<
window::Id,
(
Option<window::Id>,
SurfaceIdWrapper,
Box<dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>>>,
Box<dyn for<'a> Fn(&'a App) -> crate::surface::action::LiveSettings>,
Option<
Box<
dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>>
+ Send
+ Sync
+ 'static,
>,
>,
),
>,
pub tracked_surfaces: HashMap<window::Id, iced_winit::SurfaceIdWrapper>,
pub opened_surfaces: HashMap<window::Id, u32>,
blur_enabled: bool,
}
@ -144,7 +152,7 @@ where
#[cfg(feature = "surface-message")]
match _surface_message {
#[cfg(all(feature = "wayland", target_os = "linux"))]
crate::surface::Action::AppSubsurface(settings, view) => {
crate::surface::Action::AppSubsurface(settings, live_settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok()
.and_then(|s| s.downcast::<Box<dyn Fn(&mut T) -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send + Sync>>().ok()) else {
@ -152,7 +160,9 @@ where
return Task::none();
};
if let Some(view) = view.and_then(|view| {
let settings = settings(&mut self.app);
let view = view.and_then(|view| {
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
dyn for<'a> Fn(&'a T) -> Element<'a, crate::Action<T::Message>>
+ Send
@ -165,25 +175,18 @@ where
None
}
}
}) {
let settings = settings(&mut self.app);
self.get_subsurface(settings, *view)
} else {
let settings = settings(&mut self.app);
self.tracked_surfaces
.insert(settings.id, SurfaceIdWrapper::Subsurface(settings.id));
iced_winit::commands::subsurface::get_subsurface(settings)
}
});
self.get_subsurface(settings, view.map(|v| *v))
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
crate::surface::Action::Subsurface(settings, view) => {
crate::surface::Action::Subsurface(settings, live_settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok()
.and_then(|s| s.downcast::<Box<dyn Fn() -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings + Send + Sync>>().ok()) else {
tracing::error!("Invalid settings for subsurface");
return Task::none();
};
let settings = settings();
if let Some(view) = view.and_then(|view| {
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
@ -197,26 +200,32 @@ where
}
}
}) {
let settings = settings();
self.get_subsurface(settings, Box::new(move |_| view()))
self.get_subsurface(settings, Some(Box::new(move |_| view())))
} else {
let settings = settings();
self.tracked_surfaces
.insert(settings.id, SurfaceIdWrapper::Subsurface(settings.id));
iced_winit::commands::subsurface::get_subsurface(settings)
self.get_subsurface(settings, None)
}
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
crate::surface::Action::AppPopup(settings, view) => {
crate::surface::Action::AppPopup(settings, live_settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok()
.and_then(|s| s.downcast::<Box<dyn Fn(&mut T) -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings + Send + Sync>>().ok()) else {
tracing::error!("Invalid settings for popup");
return Task::none();
};
let Some(live_settings) =
std::sync::Arc::try_unwrap(live_settings)
.ok()
.and_then(|s| {
s.downcast::<Box<dyn Fn(&T) -> LiveSettings + Send + Sync>>()
.ok()
})
else {
tracing::error!("Invalid live settings for popup");
return Task::none();
};
if let Some(view) = view.and_then(|view| {
let view = view.and_then(|view| {
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
dyn for<'a> Fn(&'a T) -> Element<'a, crate::Action<T::Message>>
+ Send
@ -228,16 +237,10 @@ where
None
}
}
}) {
let settings = settings(&mut self.app);
});
let settings = settings(&mut self.app);
self.get_popup(settings, *view)
} else {
let settings = settings(&mut self.app);
self.tracked_surfaces
.insert(settings.id, SurfaceIdWrapper::Popup(settings.id));
iced_winit::commands::popup::get_popup(settings)
}
self.get_popup(settings, *live_settings, view.map(|v| *v))
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
crate::surface::Action::DestroyPopup(id) => {
@ -270,7 +273,7 @@ where
iced::Task::none()
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
crate::surface::Action::Popup(settings, view) => {
crate::surface::Action::Popup(settings, live_settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok()
.and_then(|s| s.downcast::<Box<dyn Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings + Send + Sync>>().ok()) else {
@ -278,6 +281,20 @@ where
return Task::none();
};
let Some(live_settings) =
std::sync::Arc::try_unwrap(live_settings)
.ok()
.and_then(|s| {
s.downcast::<Box<dyn Fn() -> LiveSettings + Send + Sync>>()
.ok()
})
else {
tracing::error!("Invalid live settings for popup");
return Task::none();
};
let settings = 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::<Box<
dyn Fn() -> Element<'static, crate::Action<T::Message>> + Send + Sync,
@ -289,18 +306,13 @@ where
}
}
}) {
let settings = settings();
self.get_popup(settings, Box::new(move |_| view()))
self.get_popup(settings, live_settings, Some(Box::new(move |_| view())))
} else {
let settings = settings();
self.tracked_surfaces
.insert(settings.id, SurfaceIdWrapper::Popup(settings.id));
iced_winit::commands::popup::get_popup(settings)
self.get_popup(settings, live_settings, None)
}
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
crate::surface::Action::AppWindow(id, settings, view) => {
crate::surface::Action::AppWindow(id, settings, live_settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings).ok().and_then(|s| {
s.downcast::<Box<dyn Fn(&mut T) -> iced::window::Settings + Send + Sync>>()
.ok()
@ -308,8 +320,19 @@ where
tracing::error!("Invalid settings for AppWindow");
return Task::none();
};
let Some(live_settings) =
std::sync::Arc::try_unwrap(live_settings)
.ok()
.and_then(|s| {
s.downcast::<Box<dyn Fn(&T) -> LiveSettings + Send + Sync>>()
.ok()
})
else {
tracing::error!("Invalid live settings for popup");
return Task::none();
};
if let Some(view) = view.and_then(|view| {
let view = view.and_then(|view| {
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
dyn for<'a> Fn(&'a T) -> Element<'a, crate::Action<T::Message>>
+ Send
@ -321,24 +344,13 @@ where
None
}
}
}) {
let settings = settings(&mut self.app);
});
let settings = settings(&mut self.app);
self.get_window(id, settings, *view)
} else {
let settings = settings(&mut self.app);
self.tracked_surfaces
.insert(id, SurfaceIdWrapper::Window(id));
iced_runtime::task::oneshot(|channel| {
iced_runtime::Action::Window(iced_runtime::window::Action::Open(
id, settings, channel,
))
})
.discard()
}
self.get_window(id, settings, *live_settings, view.map(|v| *v))
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
crate::surface::Action::Window(id, settings, view) => {
crate::surface::Action::Window(id, settings, live_settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings).ok().and_then(|s| {
s.downcast::<Box<dyn Fn() -> iced::window::Settings + Send + Sync>>()
.ok()
@ -347,6 +359,18 @@ where
return Task::none();
};
let Some(live_settings) =
std::sync::Arc::try_unwrap(live_settings)
.ok()
.and_then(|s| {
s.downcast::<Box<dyn Fn() -> LiveSettings + Send + Sync>>()
.ok()
})
else {
tracing::error!("Invalid live settings for popup");
return Task::none();
};
if let Some(view) = view.and_then(|view| {
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
dyn Fn() -> Element<'static, crate::Action<T::Message>> + Send + Sync,
@ -360,11 +384,14 @@ where
}) {
let settings = settings();
self.get_window(id, settings, Box::new(move |_| view()))
self.get_window(
id,
settings,
Box::new(move |_| live_settings()),
Some(Box::new(move |_| view())),
)
} else {
let settings = settings();
self.tracked_surfaces
.insert(id, SurfaceIdWrapper::Window(id));
iced_runtime::task::oneshot(|channel| {
iced_runtime::Action::Window(iced_runtime::window::Action::Open(
@ -380,15 +407,26 @@ where
f().map(|sm| crate::Action::Cosmic(Action::Surface(sm)))
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
crate::surface::Action::AppLayerShell(settings, view) => {
crate::surface::Action::AppLayerShell(settings, live_settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok()
.and_then(|s| s.downcast::<Box<dyn Fn(&mut T) -> iced_runtime::platform_specific::wayland::layer_surface::SctkLayerSurfaceSettings + Send + Sync>>().ok()) else {
tracing::error!("Invalid settings for layer surface");
return Task::none();
};
let Some(live_settings) =
std::sync::Arc::try_unwrap(live_settings)
.ok()
.and_then(|s| {
s.downcast::<Box<dyn Fn(&T) -> LiveSettings + Send + Sync>>()
.ok()
})
else {
tracing::error!("Invalid live settings for popup");
return Task::none();
};
if let Some(view) = view.and_then(|view| {
let view = view.and_then(|view| {
match std::sync::Arc::try_unwrap(view).ok()?.downcast::<Box<
dyn for<'a> Fn(&'a T) -> Element<'a, crate::Action<T::Message>>
+ Send
@ -400,19 +438,14 @@ where
None
}
}
}) {
let settings = settings(&mut self.app);
});
self.get_layer_shell(settings, *view)
} else {
let settings = settings(&mut self.app);
self.tracked_surfaces
.insert(settings.id, SurfaceIdWrapper::LayerSurface(settings.id));
iced_winit::commands::layer_surface::get_layer_surface(settings)
}
let settings = settings(&mut self.app);
self.get_layer_shell(settings, *live_settings, view.map(|v| *v))
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
crate::surface::Action::LayerShell(settings, view) => {
crate::surface::Action::LayerShell(settings, live_settings, view) => {
let Some(settings) = std::sync::Arc::try_unwrap(settings)
.ok()
.and_then(|s| s.downcast::<Box<dyn Fn() -> iced_runtime::platform_specific::wayland::layer_surface::SctkLayerSurfaceSettings + Send + Sync>>().ok()) else {
@ -420,6 +453,21 @@ where
return Task::none();
};
let Some(live_settings) =
std::sync::Arc::try_unwrap(live_settings)
.ok()
.and_then(|s| {
s.downcast::<Box<dyn Fn() -> LiveSettings + Send + Sync>>()
.ok()
})
else {
tracing::error!("Invalid live settings for popup");
return Task::none();
};
let settings = settings();
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::<Box<
dyn Fn() -> Element<'static, crate::Action<T::Message>> + Send + Sync,
@ -431,16 +479,9 @@ where
}
}
}) {
let settings = settings();
self.get_layer_shell(settings, Box::new(move |_| view()))
self.get_layer_shell(settings, live_settings, Some(Box::new(move |_| view())))
} else {
let settings = settings();
self.tracked_surfaces.insert(
settings.id,
iced_winit::SurfaceIdWrapper::LayerSurface(settings.id),
);
iced_winit::commands::layer_surface::get_layer_surface(settings)
self.get_layer_shell(settings, live_settings, None)
}
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
@ -657,8 +698,7 @@ where
#[cfg(feature = "multi-window")]
pub fn view(&self, id: window::Id) -> Element<'_, crate::Action<T::Message>> {
#[cfg(all(feature = "wayland", target_os = "linux"))]
if let Some((_, _, v)) = self.surface_views.get(&id) {
if let Some((_, _, _, Some(v))) = self.surface_views.get(&id) {
return v(&self.app);
}
if self
@ -762,20 +802,8 @@ impl<T: Application> Cosmic<T> {
use iced_winit::platform_specific::commands::corner_radius::corner_radius;
let theme = THEME.lock().unwrap();
let rounded = (!self.app.core().window.sharp_corners
&& self.app.core().sync_window_border_radii_to_theme())
|| self
.surface_views
.get(&id)
.is_some_and(|(_, surface_type, _)| {
if let SurfaceIdWrapper::Popup(_)
| SurfaceIdWrapper::LayerSurface(_) = surface_type
{
true
} else {
false
}
});
let rounded = !self.app.core().window.sharp_corners
&& self.app.core().sync_window_border_radii_to_theme();
let cur_rad = self.app.core().corners(&theme, rounded);
return Task::batch([corner_radius(id, cur_rad).discard()]);
@ -887,13 +915,12 @@ impl<T: Application> Cosmic<T> {
));
}
for (id, wrapper, ..) in &self.surface_views {
if core.blur(&theme, Some(wrapper.1)) {
cmds.push(blur(*id));
}
}
for (id, wrapper) in &self.tracked_surfaces {
if core.blur(&theme, Some(*wrapper)) {
let overriden = wrapper.2(&self.app);
if core.blur(&theme, Some(wrapper.1)) || overriden.blur.unwrap_or_default()
{
cmds.push(blur(*id));
} else if overriden.blur.is_some_and(|b| !b) {
cmds.push(iced::window::disable_blur(*id));
}
}
return Task::batch(cmds);
@ -963,25 +990,18 @@ impl<T: Application> Cosmic<T> {
.unwrap_or(window::Id::RESERVED);
let mut cmds = vec![corner_radius(main_window_id, cur_rad).discard()];
// Update radius for each tracked view with the window surface type
for (id, (_, surface_type, _)) in &self.surface_views {
let cur_rad = corners(
*surface_type,
rounded,
&cosmic_theme,
self.app.core().auto_corner_radius,
);
if cur_rad.is_none() {
continue;
}
cmds.push(corner_radius(*id, cur_rad).discard());
}
for (id, wrapper) in &self.tracked_surfaces {
let cur_rad = corners(
*wrapper,
rounded,
&cosmic_theme,
self.app.core().auto_corner_radius,
);
for (id, (_, surface_type, live_settings, _)) in &self.surface_views {
let overriden = live_settings(&self.app);
let cur_rad = if let Some(c) = overriden.corners {
Some(c)
} else {
corners(
*surface_type,
rounded,
&cosmic_theme,
self.app.core().auto_corner_radius,
)
};
if cur_rad.is_none() {
continue;
}
@ -1080,25 +1100,19 @@ impl<T: Application> Cosmic<T> {
let mut cmds =
vec![corner_radius(main_window_id, cur_rad).discard()];
// Update radius for each tracked view with the window surface type
for (id, (_, surface_type, _)) in &self.surface_views {
let cur_rad = corners(
*surface_type,
rounded,
&cosmic_theme,
self.app.core().auto_corner_radius,
);
if cur_rad.is_none() {
continue;
}
cmds.push(corner_radius(*id, cur_rad).discard());
}
for (id, wrapper) in &self.tracked_surfaces {
let cur_rad = corners(
*wrapper,
rounded,
&cosmic_theme,
self.app.core().auto_corner_radius,
);
for (id, (_, surface_type, live_settings, _)) in &self.surface_views
{
let overriden = live_settings(&self.app);
let cur_rad = if let Some(c) = overriden.corners {
Some(c)
} else {
corners(
*surface_type,
rounded,
&cosmic_theme,
self.app.core().auto_corner_radius,
)
};
if cur_rad.is_none() {
continue;
}
@ -1121,13 +1135,13 @@ impl<T: Application> Cosmic<T> {
));
}
for (id, wrapper, ..) in &self.surface_views {
if core.blur(&cosmic_theme, Some(wrapper.1)) {
cmds.push(blur(*id));
}
}
for (id, wrapper) in &self.tracked_surfaces {
if core.blur(&cosmic_theme, Some(*wrapper)) {
let overriden = wrapper.2(&self.app);
if core.blur(&cosmic_theme, Some(wrapper.1))
|| overriden.blur.unwrap_or_default()
{
cmds.push(blur(*id));
} else if overriden.blur.is_some_and(|b| !b) {
cmds.push(iced::window::disable_blur(*id));
}
}
@ -1171,12 +1185,9 @@ impl<T: Application> Cosmic<T> {
*v == 0
}) {
self.opened_surfaces.remove(&id);
#[cfg(all(feature = "wayland", target_os = "linux"))]
self.surface_views.remove(&id);
}
self.tracked_surfaces.remove(&id);
self.tracked_surfaces
.shrink_to(self.tracked_surfaces.len() * 2);
self.surface_views.shrink_to(self.surface_views.len() * 2);
let mut ret = if let Some(msg) = self.app.on_close_requested(id) {
self.app.update(msg)
@ -1247,6 +1258,7 @@ impl<T: Application> Cosmic<T> {
new_theme.transparent = new_blur;
}
core.system_theme = new_theme.clone();
let core = self.app.core();
{
let mut cosmic_theme = THEME.lock().unwrap();
@ -1266,14 +1278,15 @@ impl<T: Application> Cosmic<T> {
core.main_window_id().unwrap_or(window::Id::RESERVED),
));
}
for (id, wrapper, ..) in &self.surface_views {
if core.blur(&cosmic_theme, Some(wrapper.1)) {
cmds.push(blur(*id));
}
}
for (id, wrapper) in &self.tracked_surfaces {
if core.blur(&cosmic_theme, Some(*wrapper)) {
let overriden = wrapper.2(&self.app);
if core.blur(&cosmic_theme, Some(wrapper.1))
|| overriden.blur.unwrap_or_default()
{
cmds.push(blur(*id));
} else if overriden.blur.is_some_and(|b| !b) {
cmds.push(iced::window::disable_blur(*id));
}
}
}
@ -1339,6 +1352,7 @@ impl<T: Application> Cosmic<T> {
parent,
SurfaceIdWrapper::Subsurface(_) | SurfaceIdWrapper::Popup(_),
_,
_,
)) = self.surface_views.get(&f)
{
// If the parent is already focused, push the new focus
@ -1355,7 +1369,7 @@ impl<T: Application> Cosmic<T> {
cur = self
.surface_views
.get(&p)
.and_then(|(parent, _, _)| *parent);
.and_then(|(parent, _, _, _)| *parent);
}
parent_chain.reverse();
self.app.core_mut().focused_window = parent_chain;
@ -1387,15 +1401,14 @@ impl<T: Application> Cosmic<T> {
// TODO do we need per window sharp corners?
let rounded = (!self.app.core().window.sharp_corners
&& self.app.core().sync_window_border_radii_to_theme())
|| self
.surface_views
.get(&id)
.is_some_and(|(_, surface_type, _)| {
|| self.surface_views.get(&id).is_some_and(
|(_, surface_type, live_settings, _)| {
matches!(
surface_type,
SurfaceIdWrapper::Popup(_) | SurfaceIdWrapper::LayerSurface(_)
)
});
},
);
let new_blur = self.blur_enabled && {
let t = theme.cosmic();
match self.app.core().app_type() {
@ -1405,11 +1418,7 @@ impl<T: Application> Cosmic<T> {
}
};
let wrapper = self
.surface_views
.get(&id)
.map(|s| s.1)
.or(self.tracked_surfaces.get(&id).copied());
let wrapper = self.surface_views.get(&id).map(|s| s.1);
// this will blur untracked windows as if they were the main window
let blur_cmd = if self.app.core().blur(&theme, wrapper) {
@ -1426,15 +1435,18 @@ impl<T: Application> Cosmic<T> {
Task::none()
};
let corner_task = if let Some((_, cur_rad)) = self
.surface_views
.get(&id)
.map(|s| s.1)
.or(self.tracked_surfaces.get(&id).copied())
.and_then(|s| {
corners(s, rounded, &theme, self.app.core().auto_corner_radius)
.map(|c| (s, c))
}) {
let corner_task = if let Some((_, cur_rad)) =
self.surface_views.get(&id).map(|s| (s.1, &s.2)).and_then(
|(s, overriden)| {
let overriden = overriden(&self.app);
if let Some(c) = overriden.corners {
Some((s, c))
} else {
corners(s, rounded, &theme, self.app.core().auto_corner_radius)
.map(|c| (s, c))
}
},
) {
corner_radius(id, Some(cur_rad)).discard()
} else if id
== self
@ -1490,13 +1502,13 @@ impl<T: Application> Cosmic<T> {
));
}
for (id, wrapper, ..) in &self.surface_views {
if self.app.core().blur(&t, Some(wrapper.1)) {
cmds.push(blur(*id));
}
}
for (id, wrapper) in &self.tracked_surfaces {
if self.app.core().blur(&t, Some(*wrapper)) {
let overriden = wrapper.2(&self.app);
if self.app.core().blur(&t, Some(wrapper.1))
|| overriden.blur.unwrap_or_default()
{
cmds.push(blur(*id));
} else if overriden.blur.is_some_and(|b| !b) {
cmds.push(iced::window::disable_blur(*id));
}
}
return Task::batch(cmds);
@ -1513,35 +1525,79 @@ impl<App: Application> Cosmic<App> {
pub fn new(app: App) -> Self {
Self {
app,
#[cfg(all(feature = "wayland", target_os = "linux"))]
surface_views: HashMap::new(),
opened_surfaces: HashMap::new(),
tracked_surfaces: HashMap::new(),
blur_enabled: false,
}
}
#[cfg(all(feature = "wayland", feature = "winit", target_os = "linux"))]
/// Apply live setting overrides for a surface
pub fn apply_live_settings(
&mut self,
id_wrapper: SurfaceIdWrapper,
live_settings: &LiveSettings,
) -> Task<crate::Action<App::Message>> {
use iced_winit::commands::corner_radius;
let id = id_wrapper.inner();
let mut cmds = Vec::with_capacity(2);
let t = THEME.try_lock().unwrap();
if let Some(blur) = live_settings.blur {
let blur_cmd = if blur {
iced::window::enable_blur
} else {
iced::window::disable_blur
};
cmds.push(blur_cmd(id));
} else if self.app.core().blur(&*t, Some(id_wrapper)) {
cmds.push(iced::window::enable_blur(id));
}
if let Some(corners) = live_settings.corners {
cmds.push(corner_radius::corner_radius(id, Some(corners)).discard());
} else {
let rounded = !self.app.core().window.sharp_corners
&& self.app.core().sync_window_border_radii_to_theme();
if let Some(cur_rad) =
corners(id_wrapper, rounded, &*t, self.app.core().auto_corner_radius)
{
cmds.push(corner_radius::corner_radius(id, Some(cur_rad)).discard())
}
}
Task::batch(cmds)
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
/// Create a subsurface
pub fn get_subsurface(
&mut self,
settings: iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings,
view: Box<
dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>> + Send + Sync,
view: Option<
Box<dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>> + Send + Sync>,
>,
) -> Task<crate::Action<App::Message>> {
use iced_winit::commands::subsurface::get_subsurface;
*self.opened_surfaces.entry(settings.id).or_insert_with(|| 0) += 1;
let live_settings_task = self.apply_live_settings(
SurfaceIdWrapper::Subsurface(settings.id),
&LiveSettings {
blur: Some(self.blur_enabled),
corners: None,
},
);
self.surface_views.insert(
settings.id,
(
Some(settings.parent),
SurfaceIdWrapper::Subsurface(settings.id),
Box::new(|_| LiveSettings::default()),
view,
),
);
get_subsurface(settings)
Task::batch([get_subsurface(settings), live_settings_task])
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
@ -1549,21 +1605,27 @@ impl<App: Application> Cosmic<App> {
pub fn get_popup(
&mut self,
settings: iced_runtime::platform_specific::wayland::popup::SctkPopupSettings,
view: Box<
dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>> + Send + Sync,
live_settings: Box<dyn for<'a> Fn(&'a App) -> LiveSettings + Send + Sync>,
view: Option<
Box<dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>> + Send + Sync>,
>,
) -> Task<crate::Action<App::Message>> {
use iced_winit::commands::popup::get_popup;
*self.opened_surfaces.entry(settings.id).or_insert_with(|| 0) += 1;
let live_settings_task = self.apply_live_settings(
SurfaceIdWrapper::Popup(settings.id),
&live_settings(&self.app),
);
self.surface_views.insert(
settings.id,
(
Some(settings.parent),
SurfaceIdWrapper::Popup(settings.id),
live_settings,
view,
),
);
get_popup(settings)
Task::batch([get_popup(settings), live_settings_task])
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
@ -1572,46 +1634,62 @@ impl<App: Application> Cosmic<App> {
&mut self,
id: iced::window::Id,
settings: iced::window::Settings,
view: Box<
dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>> + Send + Sync,
live_settings: Box<dyn for<'a> Fn(&'a App) -> LiveSettings + Send + Sync>,
view: Option<
Box<dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>> + Send + Sync>,
>,
) -> Task<crate::Action<App::Message>> {
use iced_winit::SurfaceIdWrapper;
*self.opened_surfaces.entry(id).or_insert(0) += 1;
let live_settings_task =
self.apply_live_settings(SurfaceIdWrapper::Window(id), &live_settings(&self.app));
self.surface_views.insert(
id,
(
None, // TODO parent for window, platform specific option maybe?
SurfaceIdWrapper::Window(id),
live_settings,
view,
),
);
iced_runtime::task::oneshot(|channel| {
iced_runtime::Action::Window(iced_runtime::window::Action::Open(id, settings, channel))
})
.discard()
Task::batch([
iced_runtime::task::oneshot(|channel| {
iced_runtime::Action::Window(iced_runtime::window::Action::Open(
id, settings, channel,
))
})
.discard(),
live_settings_task,
])
}
#[cfg(all(feature = "wayland", target_os = "linux"))]
pub fn get_layer_shell(
&mut self,
settings: iced_runtime::platform_specific::wayland::layer_surface::SctkLayerSurfaceSettings,
view: Box<
dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>> + Send + Sync,
live_settings: Box<dyn for<'a> Fn(&'a App) -> LiveSettings + Send + Sync>,
view: Option<
Box<dyn for<'a> Fn(&'a App) -> Element<'a, crate::Action<App::Message>> + Send + Sync>,
>,
) -> Task<crate::Action<App::Message>> {
use iced_winit::SurfaceIdWrapper;
use iced_winit::platform_specific::commands::layer_surface::get_layer_surface;
*self.opened_surfaces.entry(settings.id).or_insert(0) += 1;
let live_settings_task = self.apply_live_settings(
SurfaceIdWrapper::LayerSurface(settings.id),
&live_settings(&self.app),
);
self.surface_views.insert(
settings.id,
(
None, // TODO parent for layer shell, platform specific option maybe?
SurfaceIdWrapper::LayerSurface(settings.id),
live_settings,
view,
),
);
get_layer_surface(settings)
Task::batch([get_layer_surface(settings), live_settings_task])
}
}

View file

@ -5,7 +5,9 @@ use super::Action;
#[cfg(feature = "winit")]
use crate::Application;
use iced::window;
use iced::{Rectangle, window};
#[cfg(all(feature = "wayland", target_os = "linux", feature = "winit"))]
use iced_runtime::platform_specific::wayland::CornerRadius;
use std::any::Any;
use std::sync::Arc;
@ -34,18 +36,30 @@ pub fn destroy_layer_shell(id: iced_core::window::Id) -> Action {
Action::DestroyLayerShell(id)
}
#[derive(Debug, Default, Copy, Clone)]
pub struct LiveSettings {
#[cfg(all(feature = "wayland", target_os = "linux", feature = "winit"))]
/// Override the default corner radius value for the surface type.
pub corners: Option<CornerRadius>,
/// Override the default blur setting for the surface type.
pub blur: Option<bool>,
}
type BoxedView<App> = Option<
Box<
dyn Fn(&App) -> crate::Element<'_, crate::Action<<App as Application>::Message>>
+ Send
+ Sync
+ 'static,
>,
>;
#[cfg(all(feature = "wayland", target_os = "linux", feature = "winit"))]
#[must_use]
pub fn app_window<App: Application>(
live_settings: impl Fn(&App) -> LiveSettings + Send + Sync + 'static,
settings: impl Fn(&mut App) -> window::Settings + Send + Sync + 'static,
view: Option<
Box<
dyn for<'a> Fn(&'a App) -> crate::Element<'a, crate::Action<App::Message>>
+ Send
+ Sync
+ 'static,
>,
>,
view: BoxedView<App>,
) -> (window::Id, Action) {
let id = window::Id::unique();
@ -53,11 +67,16 @@ pub fn app_window<App: Application>(
Box::new(settings);
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
let boxed_live: Box<dyn Fn(&App) -> LiveSettings + Send + Sync + 'static> =
Box::new(live_settings);
let boxed_live: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed_live);
(
id,
Action::AppWindow(
id,
Arc::new(boxed),
Arc::new(boxed_live),
view.map(|view| {
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
Arc::new(boxed)
@ -70,6 +89,7 @@ pub fn app_window<App: Application>(
#[cfg(all(feature = "wayland", target_os = "linux", feature = "winit"))]
#[must_use]
pub fn simple_window<Message: 'static>(
live_settings: impl Fn() -> LiveSettings + Send + Sync + 'static,
settings: impl Fn() -> window::Settings + Send + Sync + 'static,
view: Option<
impl Fn() -> crate::Element<'static, crate::Action<Message>> + Send + Sync + 'static,
@ -80,11 +100,15 @@ pub fn simple_window<Message: 'static>(
let boxed: Box<dyn Fn() -> window::Settings + Send + Sync + 'static> = Box::new(settings);
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
let boxed_live: Box<dyn Fn() -> LiveSettings + Send + Sync + 'static> = Box::new(live_settings);
let boxed_live: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed_live);
(
id,
Action::Window(
id,
Arc::new(boxed),
Arc::new(boxed_live),
view.map(|view| {
let boxed: Box<
dyn Fn() -> crate::Element<'static, crate::Action<Message>>
@ -102,18 +126,12 @@ pub fn simple_window<Message: 'static>(
#[cfg(all(feature = "wayland", target_os = "linux", feature = "winit"))]
#[must_use]
pub fn app_popup<App: Application>(
live_settings: impl Fn(&App) -> LiveSettings + Send + Sync + 'static,
settings: impl Fn(&mut App) -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
+ Send
+ Sync
+ 'static,
view: Option<
Box<
dyn for<'a> Fn(&'a App) -> crate::Element<'a, crate::Action<App::Message>>
+ Send
+ Sync
+ 'static,
>,
>,
view: BoxedView<App>,
) -> Action {
let boxed: Box<
dyn Fn(&mut App) -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
@ -123,8 +141,13 @@ pub fn app_popup<App: Application>(
> = Box::new(settings);
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
let boxed_live: Box<dyn Fn(&App) -> LiveSettings + Send + Sync + 'static> =
Box::new(live_settings);
let boxed_live: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed_live);
Action::AppPopup(
Arc::new(boxed),
Arc::new(boxed_live),
view.map(|view| {
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
Arc::new(boxed)
@ -154,6 +177,7 @@ pub fn simple_subsurface<Message: 'static, V>(
Action::Subsurface(
Arc::new(boxed),
Arc::new(Box::new(LiveSettings::default)),
view.map(|view| {
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
Arc::new(boxed)
@ -165,6 +189,7 @@ pub fn simple_subsurface<Message: 'static, V>(
#[cfg(all(feature = "wayland", target_os = "linux", feature = "winit"))]
#[must_use]
pub fn simple_popup<Message: 'static>(
live_settings: impl Fn() -> LiveSettings + Send + Sync + 'static,
settings: impl Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
+ Send
+ Sync
@ -181,8 +206,12 @@ pub fn simple_popup<Message: 'static>(
> = Box::new(settings);
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
let boxed_live: Box<dyn Fn() -> LiveSettings + Send + Sync + 'static> = Box::new(live_settings);
let boxed_live: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed_live);
Action::Popup(
Arc::new(boxed),
Arc::new(boxed_live),
view.map(|view| {
let boxed: Box<
dyn Fn() -> crate::Element<'static, crate::Action<Message>> + Send + Sync + 'static,
@ -204,14 +233,7 @@ pub fn subsurface<App: Application>(
+ Sync
+ 'static,
// XXX Boxed trait object is required for less cumbersome type inference, but we box it anyways.
view: Option<
Box<
dyn for<'a> Fn(&'a App) -> crate::Element<'a, crate::Action<App::Message>>
+ Send
+ Sync
+ 'static,
>,
>,
view: BoxedView<App>,
) -> Action {
let boxed: Box<
dyn Fn(
@ -226,6 +248,7 @@ pub fn subsurface<App: Application>(
Action::AppSubsurface(
Arc::new(boxed),
Arc::new(Box::new(|_: &App| LiveSettings::default())),
view.map(|view| {
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
Arc::new(boxed)
@ -236,6 +259,7 @@ pub fn subsurface<App: Application>(
#[cfg(all(feature = "wayland", target_os = "linux", feature = "winit"))]
#[must_use]
pub fn simple_layer_shell<Message: 'static>(
live_settings: impl Fn() -> LiveSettings + Send + Sync + 'static,
settings: impl Fn()
-> iced_runtime::platform_specific::wayland::layer_surface::SctkLayerSurfaceSettings
+ Send
@ -253,9 +277,11 @@ pub fn simple_layer_shell<Message: 'static>(
+ 'static,
> = Box::new(settings);
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
let boxed_live: Box<dyn Fn() -> LiveSettings + Send + Sync + 'static> = Box::new(live_settings);
let boxed_live: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed_live);
Action::LayerShell(
Arc::new(boxed),
Arc::new(boxed_live),
view.map(|view| {
let boxed: Box<
dyn Fn() -> crate::Element<'static, crate::Action<Message>> + Send + Sync + 'static,
@ -268,7 +294,8 @@ pub fn simple_layer_shell<Message: 'static>(
#[cfg(all(feature = "wayland", target_os = "linux", feature = "winit"))]
#[must_use]
pub fn layer_shell<App: Application>(
pub fn app_layer_shell<App: Application>(
live_settings: impl Fn(&App) -> LiveSettings + Send + Sync + 'static,
settings: impl Fn(
&mut App,
)
@ -277,14 +304,7 @@ pub fn layer_shell<App: Application>(
+ Sync
+ 'static,
// XXX Boxed trait object is required for less cumbersome type inference, but we box it anyways.
view: Option<
Box<
dyn for<'a> Fn(&'a App) -> crate::Element<'a, crate::Action<App::Message>>
+ Send
+ Sync
+ 'static,
>,
>,
view: BoxedView<App>,
) -> Action {
let boxed: Box<
dyn Fn(
@ -297,8 +317,13 @@ pub fn layer_shell<App: Application>(
> = Box::new(settings);
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
let boxed_live: Box<dyn Fn(&App) -> LiveSettings + Send + Sync + 'static> =
Box::new(live_settings);
let boxed_live: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed_live);
Action::AppLayerShell(
Arc::new(boxed),
Arc::new(boxed_live),
view.map(|view| {
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
Arc::new(boxed)

View file

@ -4,34 +4,24 @@
pub mod action;
use iced::{Limits, Size, Task};
use std::future::Future;
use std::any::Any;
use std::sync::Arc;
type BoxedSetting = Arc<Box<dyn Any + Send + Sync + 'static>>;
/// Ignore this message in your application. It will be intercepted.
#[derive(Clone)]
pub enum Action {
/// Create a subsurface with a view function accepting the App as a parameter
AppSubsurface(
std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>,
Option<std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>>,
),
AppSubsurface(BoxedSetting, BoxedSetting, Option<BoxedSetting>),
/// Create a subsurface with a view function
Subsurface(
std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>,
Option<std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>>,
),
Subsurface(BoxedSetting, BoxedSetting, Option<BoxedSetting>),
/// 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(
std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>,
Option<std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>>,
),
AppPopup(BoxedSetting, BoxedSetting, Option<BoxedSetting>),
/// Create a popup
Popup(
std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>,
Option<std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>>,
),
Popup(BoxedSetting, BoxedSetting, Option<BoxedSetting>),
/// Destroy a subsurface with a view function
DestroyPopup(iced::window::Id),
/// Destroys the global tooltip popup subsurface
@ -40,29 +30,25 @@ pub enum Action {
/// Create a window with a view function accepting the App as a parameter
AppWindow(
iced::window::Id,
std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>,
Option<std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>>,
BoxedSetting,
BoxedSetting,
Option<BoxedSetting>,
),
/// Create a window with a view function
Window(
iced::window::Id,
std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>,
Option<std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>>,
BoxedSetting,
BoxedSetting,
Option<BoxedSetting>,
),
/// Destroy a window
DestroyWindow(iced::window::Id),
/// Create a layer shell surface with a view function accepting the App as a parameter
AppLayerShell(
std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>,
Option<std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>>,
),
AppLayerShell(BoxedSetting, BoxedSetting, Option<BoxedSetting>),
/// Create a layer shell surface with a view function
LayerShell(
std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>,
Option<std::sync::Arc<Box<dyn std::any::Any + Send + Sync>>>,
),
LayerShell(BoxedSetting, BoxedSetting, Option<BoxedSetting>),
/// Destroy a layer shell surface
DestroyLayerShell(iced::window::Id),
@ -89,21 +75,33 @@ impl std::fmt::Debug for Action {
#[cold]
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::AppSubsurface(arg0, arg1) => f
Self::AppSubsurface(arg0, arg1, arg2) => f
.debug_tuple("AppSubsurface")
.field(arg0)
.field(arg1)
.field(arg2)
.finish(),
Self::Subsurface(arg0, arg1, arg2) => f
.debug_tuple("Subsurface")
.field(arg0)
.field(arg1)
.field(arg2)
.finish(),
Self::Subsurface(arg0, arg1) => {
f.debug_tuple("Subsurface").field(arg0).field(arg1).finish()
}
Self::DestroySubsurface(arg0) => {
f.debug_tuple("DestroySubsurface").field(arg0).finish()
}
Self::AppPopup(arg0, arg1) => {
f.debug_tuple("AppPopup").field(arg0).field(arg1).finish()
}
Self::Popup(arg0, arg1) => f.debug_tuple("Popup").field(arg0).field(arg1).finish(),
Self::AppPopup(arg0, arg1, arg2) => f
.debug_tuple("AppPopup")
.field(arg0)
.field(arg1)
.field(arg2)
.finish(),
Self::Popup(arg0, arg1, arg2) => f
.debug_tuple("Popup")
.field(arg0)
.field(arg1)
.field(arg2)
.finish(),
Self::DestroyPopup(arg0) => f.debug_tuple("DestroyPopup").field(arg0).finish(),
Self::DestroyTooltipPopup => f.debug_tuple("DestroyTooltipPopup").finish(),
Self::ResponsiveMenuBar {
@ -117,28 +115,34 @@ impl std::fmt::Debug for Action {
.field("size", size)
.finish(),
Self::Ignore => write!(f, "Ignore"),
Self::AppWindow(id, arg0, arg1) => f
Self::AppWindow(id, arg0, arg1, arg2) => f
.debug_tuple("AppWindow")
.field(id)
.field(arg0)
.field(arg1)
.field(arg2)
.finish(),
Self::Window(id, arg0, arg1) => f
Self::Window(id, arg0, arg1, arg2) => f
.debug_tuple("Window")
.field(id)
.field(arg0)
.field(arg1)
.field(arg2)
.finish(),
Self::DestroyWindow(arg0) => f.debug_tuple("DestroyWindow").field(arg0).finish(),
Self::Task(_) => f.debug_tuple("Future").finish(),
Self::AppLayerShell(any, any1) => f
Self::AppLayerShell(arg, arg1, arg2) => f
.debug_tuple("AppLayerShell")
.field(any)
.field(any1)
.field(arg)
.field(arg1)
.field(arg2)
.finish(),
Self::LayerShell(arg, arg1, arg2) => f
.debug_tuple("LayerShell")
.field(arg)
.field(arg1)
.field(arg2)
.finish(),
Self::LayerShell(any, any1) => {
f.debug_tuple("LayerShell").field(any).field(any1).finish()
}
Self::DestroyLayerShell(arg0) => {
f.debug_tuple("DestroyLayerShell").field(arg0).finish()
}

View file

@ -81,7 +81,7 @@ impl<Message: Clone + 'static> ContextMenu<'_, Message> {
my_state: &mut LocalState,
) {
if self.window_id != window::Id::NONE && self.on_surface_action.is_some() {
use crate::surface::action::destroy_popup;
use crate::surface::action::{LiveSettings, destroy_popup};
use crate::widget::menu::Menu;
use iced_runtime::platform_specific::wayland::popup::{
SctkPopupSettings, SctkPositioner,
@ -187,6 +187,7 @@ impl<Message: Clone + 'static> ContextMenu<'_, Message> {
let parent = self.window_id;
shell.publish((self.on_surface_action.as_ref().unwrap())(
crate::surface::action::simple_popup(
|| LiveSettings::default(),
move || SctkPopupSettings {
parent,
id,

View file

@ -580,6 +580,8 @@ pub fn update<
use iced_runtime::platform_specific::wayland::popup::{
SctkPopupSettings, SctkPositioner,
};
use crate::surface::action::LiveSettings;
let bounds = layout.bounds();
let anchor_rect = Rectangle {
x: bounds.x as i32,
@ -606,6 +608,7 @@ pub fn update<
let on_surface_action_clone = on_surface_action.clone();
let translation = layout.virtual_offset();
let get_popup_action = surface::action::simple_popup::<AppMessage>(
|| LiveSettings::default(),
move || {
SctkPopupSettings {
parent,

View file

@ -385,7 +385,7 @@ where
my_state: &mut MenuBarState,
) {
if self.window_id != window::Id::NONE && self.on_surface_action.is_some() {
use crate::surface::action::destroy_popup;
use crate::surface::action::{LiveSettings, destroy_popup};
use iced_runtime::platform_specific::wayland::popup::{
SctkPopupSettings, SctkPositioner,
};
@ -501,6 +501,7 @@ where
};
let parent = self.window_id;
shell.publish((surface_action)(crate::surface::action::simple_popup(
|| LiveSettings::default(),
move || SctkPopupSettings {
parent,
id,

View file

@ -988,6 +988,8 @@ impl<Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, crate::
use iced_runtime::platform_specific::wayland::popup::{
SctkPopupSettings, SctkPositioner,
};
use crate::surface::action::LiveSettings;
let overlay_offset = Point::ORIGIN - viewport.position();
let overlay_cursor = cursor.position().unwrap_or_default() - overlay_offset;
@ -1103,6 +1105,7 @@ impl<Message: std::clone::Clone + 'static> Widget<Message, crate::Theme, crate::
let parent = self.window_id;
shell.publish((self.on_surface_action.as_ref().unwrap())(
crate::surface::action::simple_popup(
|| LiveSettings::default(),
move || SctkPopupSettings {
parent,
id: popup_id,

View file

@ -21,6 +21,8 @@ use iced_core::{
Vector, Widget, layout, mouse, overlay, renderer, svg, touch,
};
use crate::surface::action::LiveSettings;
pub use super::{Catalog, Style};
/// Internally defines different button widget variants.
@ -521,8 +523,15 @@ pub fn update<'a, Message: Clone + 'static, TopLevelMessage: Clone + 'static>(
> = Box::new(move || s(bounds));
let boxed: Box<dyn Any + Send + Sync + 'static> =
Box::new(boxed);
let boxed_live: Box<
dyn Fn() -> LiveSettings + Send + Sync + 'static,
> = Box::new(move || Default::default());
let boxed_live: Box<dyn Any + Send + Sync + 'static> =
Box::new(boxed_live);
crate::surface::Action::Popup(
Arc::new(boxed),
Arc::new(boxed_live),
Some({
let boxed: Box<
dyn Fn() -> crate::Element<
@ -553,9 +562,14 @@ pub fn update<'a, Message: Clone + 'static, TopLevelMessage: Clone + 'static>(
+ 'static,
> = Box::new(move || s(bounds));
let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
let boxed_live: Box<dyn Fn() -> LiveSettings + Send + Sync + 'static> =
Box::new(move || Default::default());
let boxed_live: Box<dyn Any + Send + Sync + 'static> =
Box::new(boxed_live);
let sm = crate::surface::Action::Popup(
Arc::new(boxed),
Arc::new(boxed_live),
Some({
let boxed: Box<
dyn Fn() -> crate::Element<