use crate::shell::{CosmicMappedRenderElement, WorkspaceRenderElement}; use smithay::{ backend::renderer::{ element::{ surface::WaylandSurfaceRenderElement, texture::TextureRenderElement, utils::{CropRenderElement, Relocate, RelocateRenderElement, RescaleRenderElement}, Element, Id, Kind, RenderElement, UnderlyingStorage, }, gles::{GlesError, GlesTexture}, glow::{GlowFrame, GlowRenderer}, utils::{CommitCounter, DamageSet, OpaqueRegions}, ImportAll, ImportMem, Renderer, }, utils::{Buffer as BufferCoords, Logical, Physical, Point, Rectangle, Scale}, }; use super::{cursor::CursorRenderElement, GlMultiRenderer}; pub enum CosmicElement where R: AsGlowRenderer + Renderer + ImportAll + ImportMem, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { Workspace(RelocateRenderElement>), Cursor(RelocateRenderElement>), Dnd(WaylandSurfaceRenderElement), MoveGrab(CosmicMappedRenderElement), AdditionalDamage(DamageElement), Mirror( CropRenderElement< RelocateRenderElement>>, >, ), #[cfg(feature = "debug")] Egui(TextureRenderElement), } impl Element for CosmicElement where R: AsGlowRenderer + Renderer + ImportAll + ImportMem, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn id(&self) -> &Id { match self { CosmicElement::Workspace(elem) => elem.id(), CosmicElement::Cursor(elem) => elem.id(), CosmicElement::Dnd(elem) => elem.id(), CosmicElement::MoveGrab(elem) => elem.id(), CosmicElement::AdditionalDamage(elem) => elem.id(), CosmicElement::Mirror(elem) => elem.id(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.id(), } } fn current_commit(&self) -> CommitCounter { match self { CosmicElement::Workspace(elem) => elem.current_commit(), CosmicElement::Cursor(elem) => elem.current_commit(), CosmicElement::Dnd(elem) => elem.current_commit(), CosmicElement::MoveGrab(elem) => elem.current_commit(), CosmicElement::AdditionalDamage(elem) => elem.current_commit(), CosmicElement::Mirror(elem) => elem.current_commit(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.current_commit(), } } fn src(&self) -> Rectangle { match self { CosmicElement::Workspace(elem) => elem.src(), CosmicElement::Cursor(elem) => elem.src(), CosmicElement::Dnd(elem) => elem.src(), CosmicElement::MoveGrab(elem) => elem.src(), CosmicElement::AdditionalDamage(elem) => elem.src(), CosmicElement::Mirror(elem) => elem.src(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.src(), } } fn geometry(&self, scale: Scale) -> Rectangle { match self { CosmicElement::Workspace(elem) => elem.geometry(scale), CosmicElement::Cursor(elem) => elem.geometry(scale), CosmicElement::Dnd(elem) => elem.geometry(scale), CosmicElement::MoveGrab(elem) => elem.geometry(scale), CosmicElement::AdditionalDamage(elem) => elem.geometry(scale), CosmicElement::Mirror(elem) => elem.geometry(scale), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.geometry(scale), } } fn location(&self, scale: Scale) -> Point { match self { CosmicElement::Workspace(elem) => elem.location(scale), CosmicElement::Cursor(elem) => elem.location(scale), CosmicElement::Dnd(elem) => elem.location(scale), CosmicElement::MoveGrab(elem) => elem.location(scale), CosmicElement::AdditionalDamage(elem) => elem.location(scale), CosmicElement::Mirror(elem) => elem.location(scale), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.location(scale), } } fn transform(&self) -> smithay::utils::Transform { match self { CosmicElement::Workspace(elem) => elem.transform(), CosmicElement::Cursor(elem) => elem.transform(), CosmicElement::Dnd(elem) => elem.transform(), CosmicElement::MoveGrab(elem) => elem.transform(), CosmicElement::AdditionalDamage(elem) => elem.transform(), CosmicElement::Mirror(elem) => elem.transform(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.transform(), } } fn damage_since( &self, scale: Scale, commit: Option, ) -> DamageSet { match self { CosmicElement::Workspace(elem) => elem.damage_since(scale, commit), CosmicElement::Cursor(elem) => elem.damage_since(scale, commit), CosmicElement::Dnd(elem) => elem.damage_since(scale, commit), CosmicElement::MoveGrab(elem) => elem.damage_since(scale, commit), CosmicElement::AdditionalDamage(elem) => elem.damage_since(scale, commit), CosmicElement::Mirror(elem) => elem.damage_since(scale, commit), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.damage_since(scale, commit), } } fn opaque_regions(&self, scale: Scale) -> OpaqueRegions { match self { CosmicElement::Workspace(elem) => elem.opaque_regions(scale), CosmicElement::Cursor(elem) => elem.opaque_regions(scale), CosmicElement::Dnd(elem) => elem.opaque_regions(scale), CosmicElement::MoveGrab(elem) => elem.opaque_regions(scale), CosmicElement::AdditionalDamage(elem) => elem.opaque_regions(scale), CosmicElement::Mirror(elem) => elem.opaque_regions(scale), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.opaque_regions(scale), } } fn alpha(&self) -> f32 { match self { CosmicElement::Workspace(elem) => elem.alpha(), CosmicElement::Cursor(elem) => elem.alpha(), CosmicElement::Dnd(elem) => elem.alpha(), CosmicElement::MoveGrab(elem) => elem.alpha(), CosmicElement::AdditionalDamage(elem) => elem.alpha(), CosmicElement::Mirror(elem) => elem.alpha(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.alpha(), } } fn kind(&self) -> Kind { match self { CosmicElement::Workspace(elem) => elem.kind(), CosmicElement::Cursor(elem) => elem.kind(), CosmicElement::Dnd(elem) => elem.kind(), CosmicElement::MoveGrab(elem) => elem.kind(), CosmicElement::AdditionalDamage(elem) => elem.kind(), CosmicElement::Mirror(elem) => elem.kind(), #[cfg(feature = "debug")] CosmicElement::Egui(elem) => elem.kind(), } } } impl RenderElement for CosmicElement where R: AsGlowRenderer + Renderer + ImportAll + ImportMem, ::TextureId: 'static, ::Error: FromGlesError, CosmicMappedRenderElement: RenderElement, { fn draw( &self, frame: &mut R::Frame<'_>, src: Rectangle, dst: Rectangle, damage: &[Rectangle], opaque_regions: &[Rectangle], ) -> Result<(), R::Error> { match self { CosmicElement::Workspace(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::Cursor(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::Dnd(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::MoveGrab(elem) => elem.draw(frame, src, dst, damage, opaque_regions), CosmicElement::AdditionalDamage(elem) => { RenderElement::::draw(elem, frame, src, dst, damage, opaque_regions) } CosmicElement::Mirror(elem) => { let elem = { let glow_frame = R::glow_frame_mut(frame); RenderElement::::draw( elem, glow_frame, src, dst, damage, opaque_regions, ) .map_err(FromGlesError::from_gles_error) }; elem } #[cfg(feature = "debug")] CosmicElement::Egui(elem) => { let elem = { let glow_frame = R::glow_frame_mut(frame); RenderElement::::draw( elem, glow_frame, src, dst, damage, opaque_regions, ) .map_err(FromGlesError::from_gles_error) }; elem } } } fn underlying_storage(&self, renderer: &mut R) -> Option { match self { CosmicElement::Workspace(elem) => elem.underlying_storage(renderer), CosmicElement::Cursor(elem) => elem.underlying_storage(renderer), CosmicElement::Dnd(elem) => elem.underlying_storage(renderer), CosmicElement::MoveGrab(elem) => elem.underlying_storage(renderer), CosmicElement::AdditionalDamage(elem) => elem.underlying_storage(renderer), CosmicElement::Mirror(elem) => { let glow_renderer = renderer.glow_renderer_mut(); match elem.underlying_storage(glow_renderer) { Some(UnderlyingStorage::Wayland(buffer)) => { Some(UnderlyingStorage::Wayland(buffer)) } _ => None, } } #[cfg(feature = "debug")] CosmicElement::Egui(elem) => { let glow_renderer = renderer.glow_renderer_mut(); match elem.underlying_storage(glow_renderer) { Some(UnderlyingStorage::Wayland(buffer)) => { Some(UnderlyingStorage::Wayland(buffer)) } _ => None, } } } } } impl From> for CosmicElement where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn from(elem: WorkspaceRenderElement) -> Self { Self::Workspace(RelocateRenderElement::from_element( elem, (0, 0), Relocate::Relative, )) } } impl From> for CosmicElement where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn from(elem: CosmicMappedRenderElement) -> Self { Self::MoveGrab(elem) } } impl From for CosmicElement where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn from(elem: DamageElement) -> Self { Self::AdditionalDamage(elem) } } #[cfg(feature = "debug")] impl From> for CosmicElement where R: Renderer + ImportAll + ImportMem + AsGlowRenderer, ::TextureId: 'static, CosmicMappedRenderElement: RenderElement, { fn from(elem: TextureRenderElement) -> Self { Self::Egui(elem) } } pub trait AsGlowRenderer where Self: Renderer, { fn glow_renderer(&self) -> &GlowRenderer; fn glow_renderer_mut(&mut self) -> &mut GlowRenderer; fn glow_frame<'a, 'frame>(frame: &'a Self::Frame<'frame>) -> &'a GlowFrame<'frame>; fn glow_frame_mut<'a, 'frame>(frame: &'a mut Self::Frame<'frame>) -> &'a mut GlowFrame<'frame>; } impl AsGlowRenderer for GlowRenderer { fn glow_renderer(&self) -> &GlowRenderer { self } fn glow_renderer_mut(&mut self) -> &mut GlowRenderer { self } fn glow_frame<'a, 'frame>(frame: &'a Self::Frame<'frame>) -> &'a GlowFrame<'frame> { frame } fn glow_frame_mut<'a, 'frame>(frame: &'a mut Self::Frame<'frame>) -> &'a mut GlowFrame<'frame> { frame } } impl<'a> AsGlowRenderer for GlMultiRenderer<'a> { fn glow_renderer(&self) -> &GlowRenderer { self.as_ref() } fn glow_renderer_mut(&mut self) -> &mut GlowRenderer { self.as_mut() } fn glow_frame<'b, 'frame>(frame: &'b Self::Frame<'frame>) -> &'b GlowFrame<'frame> { frame.as_ref() } fn glow_frame_mut<'b, 'frame>(frame: &'b mut Self::Frame<'frame>) -> &'b mut GlowFrame<'frame> { frame.as_mut() } } pub struct DamageElement { id: Id, geometry: Rectangle, } impl DamageElement { pub fn new(geometry: Rectangle) -> DamageElement { DamageElement { id: Id::new(), geometry, } } } impl Element for DamageElement { fn id(&self) -> &Id { &self.id } fn current_commit(&self) -> CommitCounter { CommitCounter::default() } fn src(&self) -> Rectangle { Rectangle::from_loc_and_size((0.0, 0.0), (1.0, 1.0)) } fn geometry(&self, scale: Scale) -> Rectangle { self.geometry.to_f64().to_physical(scale).to_i32_round() } fn damage_since( &self, scale: Scale, _commit: Option, ) -> DamageSet { DamageSet::from_slice(&[Rectangle::from_loc_and_size( (0, 0), self.geometry(scale).size, )]) } } impl RenderElement for DamageElement { fn draw( &self, _frame: &mut ::Frame<'_>, _src: Rectangle, _dst: Rectangle, _damage: &[Rectangle], _opaque_regions: &[Rectangle], ) -> Result<(), ::Error> { Ok(()) } } pub trait FromGlesError { fn from_gles_error(err: GlesError) -> Self; } impl FromGlesError for GlesError { fn from_gles_error(err: GlesError) -> Self { err } }