use mint::Vector2; use parking_lot::Mutex; use smithay::{ backend::renderer::utils::RendererSurfaceStateUserData, reexports::wayland_server::protocol::wl_surface::WlSurface, wayland::{ compositor, shell::xdg::{SurfaceCachedState, XdgToplevelSurfaceData}, }, }; use crate::nodes::items::panel::{ChildInfo, Geometry, ToplevelInfo}; use super::xdg_shell::surface_panel_item; pub trait WlSurfaceExt { fn insert_data(&self, data: T) -> bool; fn get_data(&self) -> Option; fn get_data_raw O>(&self, f: F) -> Option; fn get_current_surface_state(&self) -> SurfaceCachedState; fn get_pending_surface_state(&self) -> SurfaceCachedState; fn get_size(&self) -> Option>; fn get_geometry(&self) -> Option; } impl WlSurfaceExt for WlSurface { fn insert_data(&self, data: T) -> bool { compositor::with_states(self, |d| { d.data_map.insert_if_missing_threadsafe(move || data) }) } fn get_data(&self) -> Option { compositor::with_states(self, |d| d.data_map.get::().cloned()) } fn get_data_raw O>(&self, f: F) -> Option { compositor::with_states(self, |d| Some((f)(d.data_map.get::()?))) } fn get_current_surface_state(&self) -> SurfaceCachedState { compositor::with_states(self, |states| { *states.cached_state.get::().current() }) } fn get_pending_surface_state(&self) -> SurfaceCachedState { compositor::with_states(self, |states| { *states.cached_state.get::().pending() }) } fn get_size(&self) -> Option> { self.get_data_raw::(|surface_states| { surface_states.lock().unwrap().surface_size() }) .flatten() .map(|size| Vector2::from([size.w as u32, size.h as u32])) } fn get_geometry(&self) -> Option { self.get_current_surface_state().geometry.map(|r| r.into()) } } pub trait ToplevelInfoExt { fn get_toplevel_info(&self) -> Option; fn with_toplevel_info O>(&self, f: F) -> Option; fn get_parent(&self) -> Option; fn get_app_id(&self) -> Option; fn get_title(&self) -> Option; fn min_size(&self) -> Option>; fn max_size(&self) -> Option>; } impl ToplevelInfoExt for WlSurface { fn get_toplevel_info(&self) -> Option { self.get_data_raw::, _, _>(|c| c.lock().clone()) } fn with_toplevel_info O>(&self, f: F) -> Option { self.get_data_raw::, _, _>(|r| (f)(&mut r.lock())) } fn get_parent(&self) -> Option { self.get_data_raw::(|d| d.lock().unwrap().parent.clone()) .flatten() .and_then(|p| surface_panel_item(&p)) .and_then(|p| p.node.upgrade()) .map(|p| p.get_id()) } fn get_app_id(&self) -> Option { self.get_data_raw::(|d| d.lock().ok()?.app_id.clone()) .flatten() } fn get_title(&self) -> Option { self.get_data_raw::(|d| d.lock().ok()?.title.clone()) .flatten() } fn min_size(&self) -> Option> { let state = self.get_pending_surface_state(); let size = state.min_size; if size.w == 0 && size.h == 0 { None } else { Some(Vector2::from([size.w as u32, size.h as u32])) } } fn max_size(&self) -> Option> { let state = self.get_pending_surface_state(); let size = state.max_size; if size.w == 0 && size.h == 0 { None } else { Some(Vector2::from([size.w as u32, size.h as u32])) } } } pub trait ChildInfoExt { fn get_child_info(&self) -> Option; fn with_child_info O>(&self, f: F) -> Option; } impl ChildInfoExt for WlSurface { fn get_child_info(&self) -> Option { self.get_data_raw::, _, _>(|c| c.lock().clone()) } fn with_child_info O>(&self, f: F) -> Option { self.get_data_raw::, _, _>(|r| (f)(&mut r.lock())) } }