chore: session lock action

This commit is contained in:
Ashley Wulber 2026-09-15 18:53:27 -04:00 • committed by Ashley Wulber
parent 8cb86195ec
commit 3664828bf8
3 changed files with 100 additions and 1 deletions

View file

@ -452,6 +452,33 @@ where
crate::surface::Action::DestroyLayerShell(id) => {
iced_winit::commands::layer_surface::destroy_layer_surface(id)
}
#[cfg(wayland_platform)]
crate::surface::Action::Lock(id, output, live_settings, view) => {
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 live_settings = live_settings();
let live_settings = Box::new(move |_app: &T| live_settings);
if let Some(view) = view {
self.get_lock(id, output, live_settings, Some(Box::new(move |_| view())))
} else {
self.get_lock(id, output, live_settings, None)
}
}
#[cfg(wayland_platform)]
crate::surface::Action::DestroyLock(id) => {
iced_winit::commands::session_lock::destroy_lock_surface(id)
}
crate::surface::Action::SyncLiveSettings(id) => {
if let Some((_, id, live_settings, _)) = self.surface_views.get(&id) {
let live_settings = live_settings(&self.app);
@ -1741,6 +1768,34 @@ impl<App: Application> Cosmic<App> {
);
Task::batch([live_settings_task, get_layer_surface(settings)])
}
#[cfg(wayland_platform)]
pub fn get_lock(
&mut self,
id: window::Id,
output: cctk::wayland_client::protocol::wl_output::WlOutput,
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::session_lock::get_lock_surface;
*self.opened_surfaces.entry(id).or_insert(0) += 1;
let live_settings_task =
self.apply_live_settings(SurfaceIdWrapper::SessionLock(id), &live_settings(&self.app));
self.surface_views.insert(
id,
(
None, // TODO parent for layer shell, platform specific option maybe?
SurfaceIdWrapper::SessionLock(id),
live_settings,
view,
),
);
live_settings_task.chain(get_lock_surface(id, output))
}
}
#[cfg(wayland_platform)]

View file

@ -5,7 +5,7 @@ use super::{Action, View};
#[cfg(feature = "winit")]
use crate::Application;
use iced::{Rectangle, window};
use iced::window;
#[cfg(all(wayland_platform, feature = "winit"))]
use iced_runtime::platform_specific::wayland::CornerRadius;
#[cfg(wayland_platform)]
@ -275,6 +275,26 @@ pub fn simple_layer_shell<Message: 'static>(
)
}
#[cfg(wayland_platform)]
#[must_use]
pub fn lock<Message: 'static>(
live_settings: impl Fn() -> LiveSettings + Send + Sync + 'static,
id: window::Id,
output: cctk::wayland_client::protocol::wl_output::WlOutput,
view: Option<
impl Fn() -> crate::Element<'static, crate::Action<Message>> + Send + Sync + 'static,
>,
) -> Action<Message> {
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::Lock(
id,
output,
Arc::new(boxed_live),
view.map(|view| Arc::new(view) as View<Message>),
)
}
#[cfg(wayland_platform)]
#[must_use]
pub fn app_layer_shell<App: Application>(

View file

@ -64,6 +64,18 @@ pub enum Action<M> {
/// Destroy a layer shell surface
DestroyLayerShell(iced::window::Id),
#[cfg(wayland_platform)]
/// Create a lock shell surface with a view function
Lock(
iced::window::Id,
cctk::wayland_client::protocol::wl_output::WlOutput,
BoxedSetting,
Option<View<M>>,
),
/// Destroy a lock surface
DestroyLock(iced::window::Id),
/// Responsive menu bar update
ResponsiveMenuBar {
/// Id of the menu bar
@ -111,6 +123,9 @@ impl<M: 'static> Action<M> {
Action::AppLayerShell(a, b, c) => Action::AppLayerShell(a, b, c),
Action::LayerShell(a, b, view) => Action::LayerShell(a, b, map_view(view)),
Action::DestroyLayerShell(id) => Action::DestroyLayerShell(id),
#[cfg(wayland_platform)]
Action::Lock(id, output, a, view) => Action::Lock(id, output, a, map_view(view)),
Action::DestroyLock(id) => Action::DestroyLock(id),
Action::ResponsiveMenuBar {
menu_bar,
limits,
@ -217,6 +232,15 @@ impl<M> std::fmt::Debug for Action<M> {
Self::DestroyLayerShell(arg0) => {
f.debug_tuple("DestroyLayerShell").field(arg0).finish()
}
#[cfg(wayland_platform)]
Self::Lock(id, output, arg0, view) => f
.debug_tuple("Lock")
.field(id)
.field(output)
.field(arg0)
.field(&view.as_ref().map(|_| "view"))
.finish(),
Self::DestroyLock(arg0) => f.debug_tuple("DestroyLock").field(arg0).finish(),
Self::SyncLiveSettings(arg0) => f.debug_tuple("SyncLiveSettings").field(arg0).finish(),
}
}