improv: allow overrides for corner radius or blur that apply on creation as well
This commit is contained in:
parent
f268bb86cf
commit
ac4a1ab259
9 changed files with 415 additions and 285 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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<
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue