use crate::{ backend::renderer::{ element::{ surface::{render_elements_from_surface_tree, WaylandSurfaceRenderElement}, AsRenderElements, Kind, }, ImportAll, Renderer, }, desktop::{space::SpaceElement, PopupManager, Window, WindowSurface, WindowSurfaceType}, output::Output, utils::{Logical, Physical, Point, Rectangle, Scale}, wayland::seat::WaylandFocus, }; use super::{output_update, WindowOutputUserData}; impl SpaceElement for Window { fn geometry(&self) -> Rectangle { self.geometry() } fn bbox(&self) -> Rectangle { self.bbox_with_popups() } fn is_in_input_region(&self, point: &Point) -> bool { self.surface_under(*point, WindowSurfaceType::ALL).is_some() } fn z_index(&self) -> u8 { self.0.z_index.load(std::sync::atomic::Ordering::SeqCst) } fn set_activate(&self, activated: bool) { self.set_activated(activated); } #[profiling::function] fn output_enter(&self, output: &Output, overlap: Rectangle) { self.user_data().insert_if_missing(WindowOutputUserData::default); { let mut state = self .user_data() .get::() .unwrap() .borrow_mut(); state.output_overlap.insert(output.downgrade(), overlap); state.output_overlap.retain(|weak, _| weak.is_alive()); } self.refresh() } #[profiling::function] fn output_leave(&self, output: &Output) { if let Some(state) = self.user_data().get::() { state.borrow_mut().output_overlap.retain(|weak, _| weak != output); } if let Some(surface) = self.wl_surface() { output_update(output, None, &surface); for (popup, _) in PopupManager::popups_for_surface(&surface) { output_update(output, None, popup.wl_surface()); } } } #[profiling::function] fn refresh(&self) { self.user_data().insert_if_missing(WindowOutputUserData::default); let state = self.user_data().get::().unwrap().borrow(); if let Some(surface) = self.wl_surface() { for (weak, overlap) in state.output_overlap.iter() { if let Some(output) = weak.upgrade() { output_update(&output, Some(*overlap), &surface); for (popup, location) in PopupManager::popups_for_surface(&surface) { let mut overlap = *overlap; overlap.loc -= location; output_update(&output, Some(overlap), popup.wl_surface()); } } } } } } impl AsRenderElements for Window where R: Renderer + ImportAll, R::TextureId: Clone + 'static, { type RenderElement = WaylandSurfaceRenderElement; #[profiling::function] fn render_elements>>( &self, renderer: &mut R, location: Point, scale: Scale, alpha: f32, ) -> Vec { match self.underlying_surface() { WindowSurface::Wayland(s) => { let mut render_elements: Vec = Vec::new(); let surface = s.wl_surface(); let popup_render_elements = PopupManager::popups_for_surface(surface).flat_map(|(popup, popup_offset)| { let offset = (self.geometry().loc + popup_offset - popup.geometry().loc) .to_physical_precise_round(scale); render_elements_from_surface_tree( renderer, popup.wl_surface(), location + offset, scale, alpha, Kind::Unspecified, ) }); render_elements.extend(popup_render_elements); render_elements.extend(render_elements_from_surface_tree( renderer, surface, location, scale, alpha, Kind::Unspecified, )); render_elements } #[cfg(feature = "xwayland")] WindowSurface::X11(s) => AsRenderElements::render_elements(s, renderer, location, scale, alpha), } } }