use smithay::{ backend::renderer::{ damage::OutputDamageTracker, element::{ memory::MemoryRenderBufferRenderElement, solid::SolidColorRenderElement, surface::WaylandSurfaceRenderElement, AsRenderElements, Id, Kind, }, gles::{GlesRenderer, GlesTarget}, utils::CommitCounter, Color32F, ImportAll, ImportDmaWl, ImportMem, ImportMemWl, Renderer, RendererSuper, }, desktop::{space::SpaceElement, Window}, output::Output, render_elements, utils::{IsAlive, Physical, Point, Scale}, }; use wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1::Mode; use crate::State; render_elements! { pub OutputElement where R: ImportMem + ImportDmaWl + ImportMemWl; Window=WaylandSurfaceRenderElement, Background=SolidColorRenderElement, } #[derive(PartialEq, Eq, Clone)] pub struct DecoratedWindow { pub window: Window, } impl DecoratedWindow { pub fn new(window: Window) -> Self { Self { window } } fn decorated(&self) -> bool { let mut b = false; if let Some(toplevel) = self.window.toplevel() { toplevel.with_pending_state(|f| { if let Some(decor) = f.decoration_mode { b = decor == Mode::ServerSide; } }); } b } } impl SpaceElement for DecoratedWindow { fn bbox(&self) -> smithay::utils::Rectangle { let mut bbox = self.window.bbox(); if self.decorated() { bbox.loc.x -= 5; bbox.loc.y -= 22; } bbox } fn is_in_input_region( &self, point: &smithay::utils::Point, ) -> bool { self.window.is_in_input_region(point) } fn set_activate(&self, activated: bool) { self.window.set_activate(activated) } fn output_enter( &self, output: &Output, overlap: smithay::utils::Rectangle, ) { self.window.output_enter(output, overlap) } fn output_leave(&self, output: &Output) { self.window.output_leave(output) } } impl IsAlive for DecoratedWindow { fn alive(&self) -> bool { self.window.alive() } } impl AsRenderElements for DecoratedWindow where R: Renderer + ImportDmaWl + ImportMemWl + ImportMem + ImportAll, ::TextureId: Clone + Send + 'static, { type RenderElement = OutputElement; // one enum, both variants fn render_elements>( &self, renderer: &mut R, location: Point, scale: Scale, alpha: f32, ) -> Vec { let mut elements: Vec = Vec::new(); /* Start with actual window elements */ elements.extend( self.window .render_elements::>(renderer, location, scale, alpha) .into_iter() .map(C::from), ); /* If the window is decorated, push a solid color */ let decorated = self.decorated(); if decorated { let mut bg_rect = self.window.geometry().to_physical_precise_round(scale); bg_rect.size.w += 10; bg_rect.size.h += 27; let background = SolidColorRenderElement::new( Id::new(), bg_rect, CommitCounter::default(), Color32F::new(1.0, 0.75, 0.26, 1.0), Kind::Unspecified, ); elements.push(C::from(OutputElement::Background(background))); } elements } } impl State { pub fn render( &self, output: &Output, renderer: &mut GlesRenderer, framebuffer: &mut GlesTarget, damage_tracker: &mut OutputDamageTracker, ) -> Result<(), Box> { // let elem = DecorationElement:: smithay::desktop::space::render_output::<_, OutputElement, _, _>( output, renderer, framebuffer, 1.0, 0, [&self.space], &[], damage_tracker, [0.07, 0.16, 0.286, 1.0], )?; Ok(()) } }