1use crate::{OutputHandle, OutputInfo};
2use layer_shika_domain::value_objects::surface_instance_id::SurfaceInstanceId;
3use std::fmt::{Debug, Formatter, Result as FmtResult};
4use std::sync::Arc;
5
6#[derive(Debug, Clone)]
8pub struct SurfaceInfo {
9 pub name: String,
11 pub output: OutputHandle,
13 pub instance_id: SurfaceInstanceId,
15}
16
17#[derive(Clone)]
42pub enum Surface {
43 All,
45 Named(String),
47 Any(Vec<String>),
49 Filter(Arc<dyn Fn(&SurfaceInfo) -> bool + Send + Sync>),
51 Not(Box<Surface>),
53 Or(Vec<Surface>),
55}
56
57impl Surface {
58 pub fn all() -> Self {
60 Self::All
61 }
62
63 pub fn named(name: impl Into<String>) -> Self {
65 Self::Named(name.into())
66 }
67
68 pub fn any(names: impl IntoIterator<Item = impl Into<String>>) -> Self {
70 Self::Any(names.into_iter().map(Into::into).collect())
71 }
72
73 pub fn matching<F>(predicate: F) -> Self
79 where
80 F: Fn(&SurfaceInfo) -> bool + Send + Sync + 'static,
81 {
82 Self::Filter(Arc::new(predicate))
83 }
84
85 pub fn on(self, output: Output) -> Selector {
92 Selector {
93 surface: self,
94 output,
95 }
96 }
97
98 #[must_use]
104 pub fn except(self, other: impl Into<Surface>) -> Self {
105 Self::Not(Box::new(other.into()))
106 }
107
108 #[must_use]
114 pub fn or(self, other: impl Into<Surface>) -> Self {
115 match self {
116 Self::Or(mut selectors) => {
117 selectors.push(other.into());
118 Self::Or(selectors)
119 }
120 _ => Self::Or(vec![self, other.into()]),
121 }
122 }
123
124 pub(crate) fn matches(&self, info: &SurfaceInfo) -> bool {
125 match self {
126 Self::All => true,
127 Self::Named(name) => &info.name == name,
128 Self::Any(names) => names.iter().any(|name| name == &info.name),
129 Self::Filter(predicate) => predicate(info),
130 Self::Not(selector) => !selector.matches(info),
131 Self::Or(selectors) => selectors.iter().any(|s| s.matches(info)),
132 }
133 }
134}
135
136impl Debug for Surface {
137 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
138 match self {
139 Self::All => write!(f, "Surface::All"),
140 Self::Named(name) => write!(f, "Surface::Named({:?})", name),
141 Self::Any(names) => write!(f, "Surface::Any({:?})", names),
142 Self::Filter(_) => write!(f, "Surface::Filter(<fn>)"),
143 Self::Not(selector) => write!(f, "Surface::Not({:?})", selector),
144 Self::Or(selectors) => write!(f, "Surface::Or({:?})", selectors),
145 }
146 }
147}
148
149#[derive(Clone)]
167pub enum Output {
168 All,
170 Primary,
172 Active,
174 Handle(OutputHandle),
176 Named(String),
178 Filter(Arc<dyn Fn(&OutputInfo) -> bool + Send + Sync>),
180 Not(Box<Output>),
182 Or(Vec<Output>),
184}
185
186impl Output {
187 pub fn all() -> Self {
189 Self::All
190 }
191
192 pub fn primary() -> Self {
194 Self::Primary
195 }
196
197 pub fn active() -> Self {
199 Self::Active
200 }
201
202 pub fn handle(handle: OutputHandle) -> Self {
204 Self::Handle(handle)
205 }
206
207 pub fn named(name: impl Into<String>) -> Self {
209 Self::Named(name.into())
210 }
211
212 pub fn matching<F>(predicate: F) -> Self
218 where
219 F: Fn(&OutputInfo) -> bool + Send + Sync + 'static,
220 {
221 Self::Filter(Arc::new(predicate))
222 }
223
224 #[must_use]
230 pub fn except(self, other: impl Into<Output>) -> Self {
231 Self::Not(Box::new(other.into()))
232 }
233
234 #[must_use]
240 pub fn or(self, other: impl Into<Output>) -> Self {
241 match self {
242 Self::Or(mut selectors) => {
243 selectors.push(other.into());
244 Self::Or(selectors)
245 }
246 _ => Self::Or(vec![self, other.into()]),
247 }
248 }
249
250 pub(crate) fn matches(
251 &self,
252 handle: OutputHandle,
253 info: Option<&OutputInfo>,
254 primary: Option<OutputHandle>,
255 active: Option<OutputHandle>,
256 ) -> bool {
257 match self {
258 Self::All => true,
259 Self::Primary => primary == Some(handle),
260 Self::Active => active == Some(handle),
261 Self::Handle(h) => *h == handle,
262 Self::Named(name) => info.is_some_and(|i| i.name() == Some(name.as_str())),
263 Self::Filter(predicate) => info.is_some_and(|i| predicate(i)),
264 Self::Not(selector) => !selector.matches(handle, info, primary, active),
265 Self::Or(selectors) => selectors
266 .iter()
267 .any(|s| s.matches(handle, info, primary, active)),
268 }
269 }
270}
271
272impl Debug for Output {
273 fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult {
274 match self {
275 Self::All => write!(f, "Output::All"),
276 Self::Primary => write!(f, "Output::Primary"),
277 Self::Active => write!(f, "Output::Active"),
278 Self::Handle(h) => write!(f, "Output::Handle({:?})", h),
279 Self::Named(name) => write!(f, "Output::Named({:?})", name),
280 Self::Filter(_) => write!(f, "Output::Filter(<fn>)"),
281 Self::Not(selector) => write!(f, "Output::Not({:?})", selector),
282 Self::Or(selectors) => write!(f, "Output::Or({:?})", selectors),
283 }
284 }
285}
286
287#[derive(Clone, Debug)]
302pub struct Selector {
303 pub surface: Surface,
304 pub output: Output,
305}
306
307impl Selector {
308 pub fn all() -> Self {
310 Self {
311 surface: Surface::All,
312 output: Output::All,
313 }
314 }
315
316 pub(crate) fn matches(
317 &self,
318 surface_info: &SurfaceInfo,
319 output_info: Option<&OutputInfo>,
320 primary: Option<OutputHandle>,
321 active: Option<OutputHandle>,
322 ) -> bool {
323 self.surface.matches(surface_info)
324 && self
325 .output
326 .matches(surface_info.output, output_info, primary, active)
327 }
328}
329
330impl From<Surface> for Selector {
331 fn from(surface: Surface) -> Self {
332 Self {
333 surface,
334 output: Output::All,
335 }
336 }
337}
338
339impl From<Output> for Selector {
340 fn from(output: Output) -> Self {
341 Self {
342 surface: Surface::All,
343 output,
344 }
345 }
346}