cosmic/surface/
action.rs

1// Copyright 2025 System76 <info@system76.com>
2// SPDX-License-Identifier: MPL-2.0
3
4use super::Action;
5#[cfg(feature = "winit")]
6use crate::Application;
7
8use std::{any::Any, sync::Arc};
9
10/// Used to produce a destroy popup message from within a widget.
11#[cfg(feature = "wayland")]
12#[must_use]
13pub fn destroy_popup(id: iced_core::window::Id) -> Action {
14    Action::DestroyPopup(id)
15}
16
17#[cfg(feature = "wayland")]
18#[must_use]
19pub fn destroy_subsurface(id: iced_core::window::Id) -> Action {
20    Action::DestroySubsurface(id)
21}
22
23#[cfg(all(feature = "wayland", feature = "winit"))]
24#[must_use]
25pub fn app_popup<App: Application>(
26    settings: impl Fn(&mut App) -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
27    + Send
28    + Sync
29    + 'static,
30    view: Option<
31        Box<
32            dyn for<'a> Fn(&'a App) -> crate::Element<'a, crate::Action<App::Message>>
33                + Send
34                + Sync
35                + 'static,
36        >,
37    >,
38) -> Action {
39    let boxed: Box<
40        dyn Fn(&mut App) -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
41            + Send
42            + Sync
43            + 'static,
44    > = Box::new(settings);
45    let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
46
47    Action::AppPopup(
48        Arc::new(boxed),
49        view.map(|view| {
50            let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
51            Arc::new(boxed)
52        }),
53    )
54}
55
56/// Used to create a subsurface message from within a widget.
57#[cfg(all(feature = "wayland", feature = "winit"))]
58#[must_use]
59pub fn simple_subsurface<Message: 'static, V>(
60    settings: impl Fn() -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings
61    + Send
62    + Sync
63    + 'static,
64    view: Option<
65        Box<dyn Fn() -> crate::Element<'static, crate::Action<Message>> + Send + Sync + 'static>,
66    >,
67) -> Action {
68    let boxed: Box<
69        dyn Fn() -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings
70            + Send
71            + Sync
72            + 'static,
73    > = Box::new(settings);
74    let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
75
76    Action::Subsurface(
77        Arc::new(boxed),
78        view.map(|view| {
79            let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
80            Arc::new(boxed)
81        }),
82    )
83}
84
85/// Used to create a popup message from within a widget.
86#[cfg(all(feature = "wayland", feature = "winit"))]
87#[must_use]
88pub fn simple_popup<Message: 'static, V>(
89    settings: impl Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
90    + Send
91    + Sync
92    + 'static,
93    view: Option<
94        impl Fn() -> crate::Element<'static, crate::Action<Message>> + Send + Sync + 'static,
95    >,
96) -> Action {
97    let boxed: Box<
98        dyn Fn() -> iced_runtime::platform_specific::wayland::popup::SctkPopupSettings
99            + Send
100            + Sync
101            + 'static,
102    > = Box::new(settings);
103    let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
104
105    Action::Popup(
106        Arc::new(boxed),
107        view.map(|view| {
108            let boxed: Box<
109                dyn Fn() -> crate::Element<'static, crate::Action<Message>> + Send + Sync + 'static,
110            > = Box::new(view);
111            let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
112            Arc::new(boxed)
113        }),
114    )
115}
116
117#[cfg(all(feature = "wayland", feature = "winit"))]
118#[must_use]
119pub fn subsurface<App: Application>(
120    settings: impl Fn(
121        &mut App,
122    )
123        -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings
124    + Send
125    + Sync
126    + 'static,
127    // XXX Boxed trait object is required for less cumbersome type inference, but we box it anyways.
128    view: Option<
129        Box<
130            dyn for<'a> Fn(&'a App) -> crate::Element<'a, crate::Action<App::Message>>
131                + Send
132                + Sync
133                + 'static,
134        >,
135    >,
136) -> Action {
137    let boxed: Box<
138        dyn Fn(
139                &mut App,
140            )
141                -> iced_runtime::platform_specific::wayland::subsurface::SctkSubsurfaceSettings
142            + Send
143            + Sync
144            + 'static,
145    > = Box::new(settings);
146    let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(boxed);
147
148    Action::AppSubsurface(
149        Arc::new(boxed),
150        view.map(|view| {
151            let boxed: Box<dyn Any + Send + Sync + 'static> = Box::new(view);
152            Arc::new(boxed)
153        }),
154    )
155}