use smithay::{ backend::renderer::{ ImportAll, Renderer, element::surface::{KindEvaluation, WaylandSurfaceRenderElement}, utils::RendererSurfaceStateUserData, }, reexports::wayland_server::protocol::wl_surface, render_elements, utils::{Logical, Physical, Point, Rectangle, Scale}, wayland::compositor::{self, TraversalAction}, }; use tracing::warn; use crate::backend::render::{ element::AsGlowRenderer, wayland::clipped_surface::ClippedSurfaceRenderElement, }; pub mod clipped_surface; render_elements! { pub SurfaceRenderElement where R: AsGlowRenderer + ImportAll; Clipped=ClippedSurfaceRenderElement, Wayland=WaylandSurfaceRenderElement, } pub fn render_elements_from_surface_tree( renderer: &mut R, main_surface: &wl_surface::WlSurface, location: impl Into>, geometry: impl Into>, scale: impl Into>, alpha: f32, should_clip: bool, radii: [u8; 4], kind: impl Into, ) -> Vec where R: Renderer + ImportAll + AsGlowRenderer, R::TextureId: Clone + 'static, E: From>, { let location = location.into().to_f64(); let geometry = geometry.into().to_f64(); let scale = scale.into(); let kind = kind.into(); let mut surfaces: Vec = Vec::new(); compositor::with_surface_tree_downward( main_surface, location, |_, states, location| { let mut location = *location; let data = states.data_map.get::(); if let Some(data) = data { if let Some(view) = data.lock().unwrap().view() { location += view.offset.to_f64().to_physical(scale); TraversalAction::DoChildren(location) } else { TraversalAction::SkipChildren } } else { TraversalAction::SkipChildren } }, |surface, states, location| { let mut location = *location; let kind = kind.eval(states); let data = states.data_map.get::(); if let Some(data) = data { let has_view = if let Some(view) = data.lock().unwrap().view() { location += view.offset.to_f64().to_physical(scale); true } else { false }; if has_view { match WaylandSurfaceRenderElement::from_surface( renderer, surface, states, location, alpha, kind, ) { Ok(Some(surface)) => { let elem: SurfaceRenderElement = if radii.iter().any(|r| *r != 0) && should_clip && ClippedSurfaceRenderElement::will_clip( &surface, scale, geometry, radii, ) { ClippedSurfaceRenderElement::new( renderer, surface, scale, geometry, radii, ) .into() } else { surface.into() }; surfaces.push(elem.into()); } Ok(None) => {} // surface is not mapped Err(err) => { warn!("Failed to import surface: {}", err); } }; } } }, |_, _, _| true, ); surfaces }