diff --git a/src/desktop/layer.rs b/src/desktop/layer.rs index 11cf832..92d94d9 100644 --- a/src/desktop/layer.rs +++ b/src/desktop/layer.rs @@ -332,6 +332,12 @@ impl LayerMap { self.layers.retain(|layer| layer.alive()); self.surfaces.retain(|s| s.as_ref().is_alive()); } + + /// Returns layers count + #[allow(clippy::len_without_is_empty)] //we don't need is_empty on that struct for now, mark as allow + pub fn len(&self) -> usize { + self.layers.len() + } } #[derive(Debug, Default)] diff --git a/src/desktop/space/element.rs b/src/desktop/space/element.rs index b2294bc..afd35f4 100644 --- a/src/desktop/space/element.rs +++ b/src/desktop/space/element.rs @@ -10,6 +10,33 @@ use std::{ }; use wayland_server::protocol::wl_surface::WlSurface; +/// Indicates default values for some zindexs inside smithay +#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(u8)] +pub enum RenderZindex { + /// WlrLayer::Background default zindex + Background = 10, + /// WlrLayer::Bottom default zindex + Bottom = 20, + /// Default zindex for Windows + Shell = 30, + /// WlrLayer::Top default zindex + Top = 40, + /// Default zindex for Windows PopUps + Popups = 50, + /// Default Layer for RenderElements + Overlay = 60, + /// Default Layer for Overlay PopUp + PopupsOverlay = 70, +} + +/// Elements rendered by [`Space::render_output`] in addition to windows, layers and popups. +pub type DynamicRenderElements = + Box::Frame, ::Error, ::TextureId>>; + +pub(super) type SpaceElem = + dyn SpaceElement::Frame, ::Error, ::TextureId>; + /// Trait for custom elements to be rendered during [`Space::render_output`]. pub trait RenderElement where @@ -58,6 +85,11 @@ where damage: &[Rectangle], log: &slog::Logger, ) -> Result<(), R::Error>; + + /// Returns z_index of RenderElement, reverf too [`RenderZindex`] for default values + fn z_index(&self) -> u8 { + RenderZindex::Overlay as u8 + } } pub(crate) trait SpaceElement @@ -85,6 +117,7 @@ where damage: &[Rectangle], log: &slog::Logger, ) -> Result<(), R::Error>; + fn z_index(&self) -> u8; } impl SpaceElement for Box> @@ -118,6 +151,10 @@ where ) -> Result<(), R::Error> { (&**self as &dyn RenderElement).draw(renderer, frame, scale, location, damage, log) } + + fn z_index(&self) -> u8 { + RenderElement::z_index(self.as_ref()) + } } /// Generic helper for drawing [`WlSurface`]s and their subsurfaces diff --git a/src/desktop/space/layer.rs b/src/desktop/space/layer.rs index 89a4799..93087dd 100644 --- a/src/desktop/space/layer.rs +++ b/src/desktop/space/layer.rs @@ -5,7 +5,7 @@ use crate::{ space::{Space, SpaceElement}, }, utils::{Logical, Point, Rectangle}, - wayland::output::Output, + wayland::{output::Output, shell::wlr_layer::Layer}, }; use std::{ any::TypeId, @@ -13,6 +13,8 @@ use std::{ collections::HashMap, }; +use super::RenderZindex; + #[derive(Default)] pub struct LayerState { pub drawn: bool, @@ -69,4 +71,18 @@ where } res } + + fn z_index(&self) -> u8 { + if let Some(layer) = self.layer() { + let z_index = match layer { + Layer::Background => RenderZindex::Background, + Layer::Bottom => RenderZindex::Bottom, + Layer::Top => RenderZindex::Top, + Layer::Overlay => RenderZindex::Overlay, + }; + z_index as u8 + } else { + 0 + } + } } diff --git a/src/desktop/space/mod.rs b/src/desktop/space/mod.rs index 2f91365..797d9d3 100644 --- a/src/desktop/space/mod.rs +++ b/src/desktop/space/mod.rs @@ -13,7 +13,6 @@ use crate::{ wayland::{ compositor::{get_parent, is_sync_subsurface}, output::Output, - shell::wlr_layer::Layer as WlrLayer, }, }; use indexmap::{IndexMap, IndexSet}; @@ -43,10 +42,6 @@ pub struct Space { logger: ::slog::Logger, } -/// Elements rendered by [`Space::render_output`] in addition to windows, layers and popups. -pub type DynamicRenderElements = - Box::Frame, ::Error, ::TextureId>>; - impl PartialEq for Space { fn eq(&self, other: &Space) -> bool { self.id == other.id @@ -415,9 +410,6 @@ impl Space { return Err(RenderError::UnmappedOutput); } - type SpaceElem = - dyn SpaceElement::Frame, ::Error, ::TextureId>; - let mut state = output_state(self.id, output); let output_size = output .current_mode() @@ -439,23 +431,31 @@ impl Space { .flat_map(|l| l.popup_elements::(self.id)) .collect::>(); + let mut render_elements: Vec<&SpaceElem> = Vec::with_capacity( + custom_elements.len() + + layer_map.len() + + self.windows.len() + + window_popups.len() + + layer_popups.len(), + ); + + render_elements.extend(custom_elements.iter().map(|l| l as &SpaceElem)); + render_elements.extend(self.windows.iter().map(|l| l as &SpaceElem)); + render_elements.extend(window_popups.iter().map(|l| l as &SpaceElem)); + render_elements.extend(layer_map.layers().map(|l| l as &SpaceElem)); + render_elements.extend(layer_popups.iter().map(|l| l as &SpaceElem)); + + render_elements.sort_by_key(|e| e.z_index()); + // This will hold all the damage we need for this rendering step let mut damage = Vec::>::new(); // First add damage for windows gone + for old_toplevel in state .last_state .iter() .filter_map(|(id, geo)| { - if !self - .windows - .iter() - .map(|w| w as &SpaceElem) - .chain(window_popups.iter().map(|p| p as &SpaceElem)) - .chain(layer_map.layers().map(|l| l as &SpaceElem)) - .chain(layer_popups.iter().map(|p| p as &SpaceElem)) - .chain(custom_elements.iter().map(|c| c as &SpaceElem)) - .any(|e| ToplevelId::from(e) == *id) - { + if !render_elements.iter().any(|e| ToplevelId::from(*e) == *id) { Some(*geo) } else { None @@ -468,17 +468,9 @@ impl Space { } // lets iterate front to back and figure out, what new windows or unmoved windows we have - for element in self - .windows - .iter() - .map(|w| w as &SpaceElem) - .chain(window_popups.iter().map(|p| p as &SpaceElem)) - .chain(layer_map.layers().map(|l| l as &SpaceElem)) - .chain(layer_popups.iter().map(|p| p as &SpaceElem)) - .chain(custom_elements.iter().map(|c| c as &SpaceElem)) - { + for element in &render_elements { let geo = element.geometry(self.id); - let old_geo = state.last_state.get(&ToplevelId::from(element)).cloned(); + let old_geo = state.last_state.get(&ToplevelId::from(*element)).cloned(); // window was moved or resized if old_geo.map(|old_geo| old_geo != geo).unwrap_or(false) { @@ -551,22 +543,9 @@ impl Space { .map(|geo| geo.to_f64().to_physical(state.render_scale).to_i32_round()) .collect::>(), )?; - // Then re-draw all windows & layers overlapping with a damage rect. - for element in layer_map - .layers_on(WlrLayer::Background) - .chain(layer_map.layers_on(WlrLayer::Bottom)) - .map(|l| l as &SpaceElem) - .chain(self.windows.iter().map(|w| w as &SpaceElem)) - .chain( - layer_map - .layers_on(WlrLayer::Top) - .chain(layer_map.layers_on(WlrLayer::Overlay)) - .map(|l| l as &SpaceElem), - ) - .chain(custom_elements.iter().map(|c| c as &SpaceElem)) - { + for element in &render_elements { let geo = element.geometry(self.id); if damage.iter().any(|d| d.overlaps(geo)) { let loc = element.location(self.id); @@ -607,17 +586,11 @@ impl Space { } // If rendering was successful capture the state and add the damage - state.last_state = self - .windows + state.last_state = render_elements .iter() - .map(|w| w as &SpaceElem) - .chain(window_popups.iter().map(|p| p as &SpaceElem)) - .chain(layer_map.layers().map(|l| l as &SpaceElem)) - .chain(layer_popups.iter().map(|p| p as &SpaceElem)) - .chain(custom_elements.iter().map(|c| c as &SpaceElem)) .map(|elem| { let geo = elem.geometry(self.id); - (ToplevelId::from(elem), geo) + (ToplevelId::from(*elem), geo) }) .collect(); state.old_damage.push_front(new_damage.clone()); diff --git a/src/desktop/space/popup.rs b/src/desktop/space/popup.rs index dbef156..dd8cc47 100644 --- a/src/desktop/space/popup.rs +++ b/src/desktop/space/popup.rs @@ -8,14 +8,17 @@ use crate::{ window::Window, }, utils::{Logical, Point, Rectangle}, - wayland::output::Output, + wayland::{output::Output, shell::wlr_layer::Layer}, }; use std::any::TypeId; +use super::RenderZindex; + #[derive(Debug)] pub struct RenderPopup { location: Point, popup: PopupKind, + z_index: u8, } impl Window { @@ -39,6 +42,7 @@ impl Window { RenderPopup { location: offset, popup, + z_index: RenderZindex::Popups as u8, } }) }) @@ -48,7 +52,7 @@ impl Window { } impl LayerSurface { - pub(super) fn popup_elements(&self, space_id: usize) -> impl Iterator + pub(super) fn popup_elements(&self, space_id: usize) -> impl Iterator + '_ where R: Renderer + ImportAll + 'static, R::TextureId: 'static, @@ -67,9 +71,20 @@ impl LayerSurface { .flatten() .map(move |(popup, location)| { let offset = loc + location - popup.geometry().loc; + let z_index = if let Some(layer) = self.layer() { + if layer == Layer::Overlay { + RenderZindex::PopupsOverlay as u8 + } else { + RenderZindex::Popups as u8 + } + } else { + 0 + }; + RenderPopup { location: offset, popup, + z_index, } }) }) @@ -126,4 +141,8 @@ where // popups are special, we track them, but they render with their parents Ok(()) } + + fn z_index(&self) -> u8 { + self.z_index + } } diff --git a/src/desktop/space/window.rs b/src/desktop/space/window.rs index f1ece6b..9b0c045 100644 --- a/src/desktop/space/window.rs +++ b/src/desktop/space/window.rs @@ -13,6 +13,8 @@ use std::{ collections::HashMap, }; +use super::RenderZindex; + #[derive(Default)] pub struct WindowState { pub location: Point, @@ -103,4 +105,8 @@ where } res } + + fn z_index(&self) -> u8 { + RenderZindex::Shell as u8 + } }