<NME> mod.rs
<BEF> //! This module contains the [`Space`] helper class as well has related
//! rendering helpers to add custom elements or different clients to a space.

use crate::{
    backend::renderer::{
        damage::{
            DamageTrackedRenderer, DamageTrackedRendererError, DamageTrackedRendererMode, OutputNoMode,
        },
        element::{AsRenderElements, RenderElement, RenderElementStates, Wrap},
        Renderer, Texture,
    },
    output::Output,
    utils::{IsAlive, Logical, Physical, Point, Rectangle, Scale, Transform},
};
#[cfg(feature = "wayland_frontend")]
use crate::{
    backend::renderer::{element::surface::WaylandSurfaceRenderElement, ImportAll},
    desktop::{layer_map_for_output, LayerSurface, WindowSurfaceType},
    wayland::shell::wlr_layer::Layer,
};
use std::{collections::HashMap, fmt};
#[cfg(feature = "wayland_frontend")]
use wayland_server::protocol::wl_surface::WlSurface;

mod element;
mod output;

#[cfg(feature = "wayland_frontend")]
mod wayland {
    mod layer;
    mod window;
}

pub use self::element::*;
use self::output::*;

crate::utils::ids::id_gen!(next_space_id, SPACE_ID, SPACE_IDS);

#[derive(Debug)]
struct InnerElement<E> {
    element: E,
    location: Point<i32, Logical>,
    outputs: HashMap<Output, Rectangle<i32, Logical>>,
}

/// Represents two dimensional plane to map windows and outputs upon.
///
/// Space is generic over the types of elements mapped onto it.
/// The simplest usecase is a `Space<Window>`, but other types can be used
/// by implementing [`SpaceElement`]. Multiple types might be quickly aggregated into
/// an enum by using the [`space_elements!`]-macro.
#[derive(Debug)]
pub struct Space<E: SpaceElement> {
    pub(super) id: usize,
    // in z-order, back to front
    elements: Vec<InnerElement<E>>,
    outputs: Vec<Output>,
    _logger: ::slog::Logger,
}

impl<E: SpaceElement> PartialEq for Space<E> {
    fn eq(&self, other: &Self) -> bool {
        self.id == other.id
    }
}

impl<E: SpaceElement> Drop for Space<E> {
    fn drop(&mut self) {
        SPACE_IDS.lock().unwrap().remove(&self.id);
    }
}

impl<E: SpaceElement + PartialEq> Space<E> {
    /// Create a new [`Space`]
    pub fn new<L>(log: L) -> Self
    where
        L: Into<Option<slog::Logger>>,
    {
        Space {
            id: next_space_id(),
            elements: Vec::new(),
            outputs: Vec::new(),
            _logger: crate::slog_or_fallback(log),
        }
    }

    /// Gets the id of this space
    pub fn id(&self) -> usize {
        self.id
    }

    /// Map a [`SpaceElement`] and move it to top of the stack
    ///
    /// If a z_index is provided it will override the default
    /// z_index of [`RenderZindex::Shell`] for the mapped window.
    ///
    /// This can safely be called on an already mapped window
    /// to update its location or z_index inside the space.
    ///
    /// If activate is true it will set the new windows state
    /// to be activate and removes that state from every
    /// other mapped window.
    pub fn map_element<P>(&mut self, element: E, location: P, activate: bool)
    where
        P: Into<Point<i32, Logical>>,
    {
        let outputs = if let Some(pos) = self.elements.iter().position(|inner| inner.element == element) {
            self.elements.remove(pos).outputs
        } else {
            HashMap::new()
        };

        let inner = InnerElement {
            element,
            location: location.into(),
            outputs,
        };
        self.insert_elem(inner, activate);
    }

    /// Moves an already mapped [`SpaceElement`] to top of the stack
    ///
    /// This function does nothing for unmapped windows.
    ///
    /// If activate is true it will set the new windows state
    /// to be activate and removes that state from every
    /// other mapped window.
    pub fn raise_element(&mut self, element: &E, activate: bool) {
        if let Some(pos) = self.elements.iter().position(|inner| &inner.element == element) {
            let inner = self.elements.remove(pos);
            self.insert_elem(inner, activate);
        }
    }

    fn insert_elem(&mut self, elem: InnerElement<E>, activate: bool) {
        if activate {
            elem.element.set_activate(true);
            for e in self.elements.iter() {
                e.element.set_activate(false);
            }
        }

        self.elements.push(elem);
        self.elements
            .sort_by(|e1, e2| e1.element.z_index().cmp(&e2.element.z_index()));
    }

    /// Unmap a [`SpaceElement`] from this space.
    ///
    /// This function does nothing for already unmapped windows
    pub fn unmap_elem(&mut self, element: &E) {
        if let Some(pos) = self.elements.iter().position(|inner| &inner.element == element) {
            let elem = self.elements.remove(pos);
            for output in elem.outputs.keys() {
                elem.element.output_leave(output);
            }
        }
    }

    /// Iterate window in z-order back to front
    pub fn elements(&self) -> impl DoubleEndedIterator<Item = &E> {
        self.elements.iter().map(|e| &e.element)
    }

    /// Finds the topmost element under this point if any and returns it
    /// together with the location of this element relative to this space.
    ///
    /// This is equivalent to iterating the elements in the space from
    /// top to bottom and testing if the point is within the elements
    /// input region and returning the first matching one.
    ///
    /// Note that [`SpaceElement::is_in_input_region`] expects the point
    /// to be relative to the elements origin.
    pub fn element_under<P: Into<Point<f64, Logical>>>(&self, point: P) -> Option<(&E, Point<i32, Logical>)> {
        let point = point.into();
        self.elements
            .iter()
            .rev()
            .filter(|e| e.bbox().to_f64().contains(point))
            .find_map(|e| {
                // we need to offset the point to the location where the surface is actually drawn
                let render_location = e.render_location();
                if e.element.is_in_input_region(&(point - render_location.to_f64())) {
                    Some((&e.element, render_location))
                } else {
                    None
                }
            })
    }

    /// Get a reference to the outputs under a given point
    pub fn output_under<P: Into<Point<f64, Logical>>>(&self, point: P) -> impl Iterator<Item = &Output> {
        let point = point.into();
        self.outputs.iter().rev().filter(move |o| {
            let bbox = self.output_geometry(o);
            bbox.map(|bbox| bbox.to_f64().contains(point)).unwrap_or(false)
        })
    }

    /// Returns the layer surface matching a given surface, if any
    ///
    /// `surface_type` can be used to limit the types of surfaces queried for equality.
    #[cfg(feature = "wayland_frontend")]
    pub fn layer_for_surface(
        &self,
        surface: &WlSurface,
        surface_type: WindowSurfaceType,
    ) -> Option<LayerSurface> {
        self.outputs.iter().find_map(|o| {
            let map = layer_map_for_output(o);
            map.layer_for_surface(surface, surface_type).cloned()
        })
    }

    /// Returns the location of a [`SpaceElement`] inside the Space.
    pub fn element_location(&self, elem: &E) -> Option<Point<i32, Logical>> {
        self.elements
            .iter()
            .find(|e| &e.element == elem)
            .map(|e| e.location)
    }

    /// Returns the bounding box of a [`SpaceElement`] including its relative position inside the Space.
    pub fn element_bbox(&self, elem: &E) -> Option<Rectangle<i32, Logical>> {
        self.elements
            .iter()
            .find(|e| &e.element == elem)
            .map(|e| e.bbox())
    }

    /// Returns the geometry of a [`SpaceElement`] including its relative position inside the Space.
    ///
    /// This area is usually defined as the contents of the window, excluding decorations.
    pub fn element_geometry(&self, elem: &E) -> Option<Rectangle<i32, Logical>> {
        self.elements
            .iter()
            .find(|e| &e.element == elem)
            .map(|e| e.geometry())
    }

    /// Maps an [`Output`] inside the space.
    ///
    /// Can be safely called on an already mapped
    /// [`Output`] to update its location.
    ///
    /// *Note:* Remapping an output does reset it's damage memory.
    pub fn map_output<P: Into<Point<i32, Logical>>>(&mut self, output: &Output, location: P) {
        let mut state = output_state(self.id, output);
        *state = OutputState {
            location: location.into(),
        };
        if !self.outputs.contains(output) {
            self.outputs.push(output.clone());
        }
    }

    /// Iterate over all mapped [`Output`]s of this space.
    pub fn outputs(&self) -> impl Iterator<Item = &Output> {
        self.outputs.iter()
    }

    /// Unmap an [`Output`] from this space.
    ///
    /// Does nothing if the output was not previously mapped.
    pub fn unmap_output(&mut self, output: &Output) {
        if !self.outputs.contains(output) {
            return;
        }
        if let Some(map) = output.user_data().get::<OutputUserdata>() {
            map.borrow_mut().remove(&self.id);
        }
        self.outputs.retain(|o| o != output);
    }

    /// Returns the geometry of the output including it's relative position inside the space.
    ///
    /// The size is matching the amount of logical pixels of the space visible on the output
    /// given is current mode and scale.
    pub fn output_geometry(&self, o: &Output) -> Option<Rectangle<i32, Logical>> {
        if !self.outputs.contains(o) {
            return None;
        }

        let transform: Transform = o.current_transform();
        let state = output_state(self.id, o);
        o.current_mode().map(|mode| {
            Rectangle::from_loc_and_size(
                state.location,
                transform
                    .transform_size(mode.size)
                    .to_f64()
                    .to_logical(o.current_scale().fractional_scale())
                    .to_i32_ceil(),
            )
        })
    }

    /// Returns all [`Output`]s a [`SpaceElement`] overlaps with.
    pub fn outputs_for_element(&self, elem: &E) -> Vec<Output> {
        if !self.elements.iter().any(|e| &e.element == elem) {
            return Vec::new();
        }

        self.elements
            .iter()
            .find(|e| &e.element == elem)
            .into_iter()
            .flat_map(|e| &e.outputs)
            .map(|(o, _)| o)
            .cloned()
            .collect()
    }

    /// Refresh some internal values and update client state,
    /// meaning this will handle output enter and leave events
    /// for mapped outputs and windows based on their position.
    ///
    /// Needs to be called periodically, at best before every
    /// wayland socket flush.
    pub fn refresh(&mut self) {
        self.elements.retain(|e| e.alive());

        let outputs = self
            .outputs
            .iter()
            .cloned()
            .map(|o| {
                let geo = self
                    .output_geometry(&o)
                    .unwrap_or_else(|| Rectangle::from_loc_and_size((0, 0), (0, 0)));
                (o, geo)
            })
            .collect::<Vec<_>>();
        for e in &mut self.elements {
            let bbox = e.bbox();

            for (output, output_geometry) in &outputs {
                // Check if the bounding box of the toplevel intersects with the output
                if let Some(mut overlap) = output_geometry.intersection(bbox) {
                    // output_enter expects the overlap to be relative to the element
                    overlap.loc -= bbox.loc;
                    let old = e.outputs.insert(output.clone(), overlap);
                    if old.is_none() || matches!(old, Some(old_overlap) if old_overlap != overlap) {
                        e.element.output_enter(output, overlap);
                    }
                } else if e.outputs.remove(output).is_some() {
                    e.element.output_leave(output);
                }
            }
            e.outputs.retain(|output, _| {
                if !outputs.iter().any(|(o, _)| o == output) {
                    e.element.output_leave(output);
                    false
                } else {
                    true
                }
            });
        }

        self.elements.iter().for_each(|e| e.element.refresh());
    }

    /// Retrieve the render elements for a given region of the space.
    ///
    /// *Note:* Because this is not rendering a specific output,
    /// this will not contain layer surfaces.
    /// Use [`Space::render_elements_for_output`], if you care about this.
    pub fn render_elements_for_region<'a, R: Renderer, S: Into<Scale<f64>>>(
        &'a self,
        region: &Rectangle<i32, Logical>,
        scale: S,
    ) -> Vec<<E as AsRenderElements<R>>::RenderElement>
    where
        <R as Renderer>::TextureId: Texture + 'static,
        E: AsRenderElements<R>,
        <E as AsRenderElements<R>>::RenderElement: 'a,
    {
        let scale = scale.into();

        self.elements
            .iter()
            .rev()
            .filter(|e| {
                let geometry = e.bbox();
                region.overlaps(geometry)
            })
            .flat_map(|e| {
                let location = e.render_location() - region.loc;
                e.element
                    .render_elements::<<E as AsRenderElements<R>>::RenderElement>(
                        location.to_physical_precise_round(scale),
                        scale,
                    )
            })
            .collect::<Vec<_>>()
    }

    /// Retrieve the render elements for an output
    pub fn render_elements_for_output<
        'a,
        #[cfg(feature = "wayland_frontend")] R: Renderer + ImportAll,
        #[cfg(not(feature = "wayland_frontend"))] R: Renderer,
    >(
        &'a self,
        output: &Output,
    ) -> Result<Vec<SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>>, OutputError>
    where
        <R as Renderer>::TextureId: Texture + 'static,
        E: AsRenderElements<R>,
        <E as AsRenderElements<R>>::RenderElement: 'a,
        SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>:
            From<Wrap<<E as AsRenderElements<R>>::RenderElement>>,
    {
        if !self.outputs.contains(output) {
            return Err(OutputError::Unmapped);
        }

        let output_scale = output.current_scale().fractional_scale();
        // The unwrap is safe or we would have returned OutputError::Unmapped already
        let output_geo = self.output_geometry(output).unwrap();

        let mut space_elements: Vec<SpaceElements<'a, E>> =
            self.elements.iter().rev().map(SpaceElements::Element).collect();

        #[cfg(feature = "wayland_frontend")]
        {
            let layer_map = layer_map_for_output(output);
            space_elements.extend(layer_map.layers().rev().cloned().map(|l| SpaceElements::Layer {
                surface: l,
                output_location: output_geo.loc,
            }));
        }

        space_elements.sort_by_key(|e| std::cmp::Reverse(e.z_index()));

        Ok(space_elements
            .into_iter()
            .filter(|e| {
                let geometry = e.bbox();
                output_geo.overlaps(geometry)
            })
            .flat_map(|e| {
                let location = e.render_location() - output_geo.loc;
                e.render_elements::<SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>>(
                    location.to_physical_precise_round(output_scale),
                    Scale::from(output_scale),
                )
            })
            .collect::<Vec<_>>())
    }
}

/// Errors thrown by [`Space::elements_for_output`]
#[derive(thiserror::Error, Debug)]
pub enum OutputError {
    /// The given [`Output`] has no set mode
    #[error(transparent)]
    NoMode(#[from] OutputNoMode),
    /// The given [`Output`] is not mapped to this [`Space`].
    #[error("Output was not mapped to this space")]
    Unmapped,
}

impl<E: IsAlive> IsAlive for InnerElement<E> {
    fn alive(&self) -> bool {
        self.element.alive()
    }
}

impl<E: SpaceElement> InnerElement<E> {
    // the inner geometry of the element in space coordinates
    fn geometry(&self) -> Rectangle<i32, Logical> {
        let mut geo = self.element.geometry();
        geo.loc = self.location;
        geo
    }

    // the bounding box of the element in space coordinates
    fn bbox(&self) -> Rectangle<i32, Logical> {
        let mut bbox = self.element.bbox();
        bbox.loc += self.location - self.element.geometry().loc;
        bbox
    }

    fn render_location(&self) -> Point<i32, Logical> {
        self.location - self.element.geometry().loc
    }
}

#[cfg(feature = "wayland_frontend")]
crate::backend::renderer::element::render_elements! {
    /// Defines the render elements used internally by a [`Space`]
    ///
    /// Use them in place of `E` in `space_render_elements` or
    /// `render_output` if you do not need custom render elements
    pub SpaceRenderElements<R, E> where
        R: ImportAll;
    /// A single wayland surface
    Surface=WaylandSurfaceRenderElement,
    /// A single texture
    Element=Wrap<E>,
}
#[cfg(not(feature = "wayland_frontend"))]
crate::backend::renderer::element::render_elements! {
    /// Defines the render elements used internally by a [`Space`]
    ///
    /// Use them in place of `E` in `space_render_elements` or
    /// `render_output` if you do not need custom render elements
    pub SpaceRenderElements<R, E>;
    /// A single texture
    Element=Wrap<E>,
}

impl<
        #[cfg(feature = "wayland_frontend")] R: Renderer + ImportAll,
        #[cfg(not(feature = "wayland_frontend"))] R: Renderer,
        E: RenderElement<R> + std::fmt::Debug,
    > std::fmt::Debug for SpaceRenderElements<R, E>
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            #[cfg(feature = "wayland_frontend")]
            Self::Surface(arg0) => f.debug_tuple("Surface").field(arg0).finish(),
            Self::Element(arg0) => f.debug_tuple("Element").field(arg0).finish(),
            Self::_GenericCatcher(_) => unreachable!(),
        }
    }
}

#[cfg(feature = "wayland_frontend")]
crate::backend::renderer::element::render_elements! {
    OutputRenderElements<'a, R, E, C> where
        R: ImportAll;
    Space=SpaceRenderElements<R, E>,
#[error("Output has no active mode")]
pub struct OutputNoMode;

crate::backend::renderer::output::element::render_elements! {
    OutputRenderElements<'a, R, E>;
    Space=crate::backend::renderer::output::element::Custom<E>,
    Custom=&'a E,
}


    #[cfg(feature = "wayland_frontend")]
    let layer_map = layer_map_for_output(output);
    #[cfg(feature = "wayland_frontend")]
    let lower = {
        let (upper, lower): (Vec<&LayerSurface>, Vec<&LayerSurface>) = layer_map
            .layers()
            .rev()
            .partition(|s| matches!(s.layer(), Layer::Background | Layer::Bottom));

        render_elements.extend(
            upper
                .into_iter()
                .filter_map(|surface| layer_map.layer_geometry(surface).map(|geo| (geo.loc, surface)))
                .flat_map(|(loc, surface)| {
                    AsRenderElements::<R>::render_elements::<WaylandSurfaceRenderElement>(
                        surface,
                        loc.to_physical_precise_round(output_scale),
                        Scale::from(output_scale),
                    )
                    .into_iter()
                    .map(SpaceRenderElements::Surface)
                }),
        );

        lower
    };

    for space in spaces {
        if let Some(output_geo) = space.output_geometry(output) {
            render_elements.extend(
                space
                    .render_elements_for_region(&output_geo, output_scale)
                    .into_iter()
                    .map(|e| SpaceRenderElements::Element(Wrap::from(e))),
            );
        }
    }

    #[cfg(feature = "wayland_frontend")]
    render_elements.extend(
        lower
            .into_iter()
            .filter_map(|surface| layer_map.layer_geometry(surface).map(|geo| (geo.loc, surface)))
            .flat_map(|(loc, surface)| {
                AsRenderElements::<R>::render_elements::<WaylandSurfaceRenderElement>(
                    surface,
                    loc.to_physical_precise_round(output_scale),
    render_elements.extend(
        space_render_elements
            .into_iter()
            .map(|e| OutputRenderElements::Space(crate::backend::renderer::output::element::Custom::from(e))),
    );

    output_render.render_output(renderer, age, &*render_elements, log)
}

// /// Errors thrown by [`Space::render_output`]
// #[derive(thiserror::Error)]
// pub enum RenderError<R: Renderer> {
//     /// The provided [`Renderer`] did return an error during an operation
//     #[error(transparent)]
//     Rendering(R::Error),
//     /// The given [`Output`] has no set mode
//     #[error("Output has no active mode")]
//     OutputNoMode,
//     /// The given [`Output`] is not mapped to this [`Space`].
//     #[error("Output was not mapped to this space")]
//     UnmappedOutput,
// }

// impl<R: Renderer> fmt::Debug for RenderError<R> {
//     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
//         match self {
//             RenderError::Rendering(err) => fmt::Debug::fmt(err, f),
//             RenderError::OutputNoMode => f.write_str("Output has no active move"),
//             RenderError::UnmappedOutput => f.write_str("Output was not mapped to this space"),
//         }
//     }
// }

// #[macro_export]
// #[doc(hidden)]
// macro_rules! custom_elements_internal {
//     (@enum $vis:vis $name:ident; $($(#[$meta:meta])* $body:ident=$field:ty$( as <$other_renderer:ty>)?),* $(,)?) => {
//         $vis enum $name {
//             $(
//                 $(
//                     #[$meta]
//                 )*
//                 $body($field)
//             ),*,
//             #[doc(hidden)]
//             _GenericCatcher(std::convert::Infallible),
//         }
//     };
//     (@enum $vis:vis $name:ident<$renderer:ident>; $($(#[$meta:meta])* $body:ident=$field:ty$( as <$other_renderer:ty>)?),* $(,)?) => {
//         $vis enum $name<$renderer>
//         where
//             $renderer: $crate::backend::renderer::Renderer + $crate::backend::renderer::ImportAll,
//         {
//             $(
//                 $(
//                     #[$meta]
//                 )*
//                 $body($field)
//             ),*,
//             #[doc(hidden)]
//             _GenericCatcher((std::marker::PhantomData<$renderer>, std::convert::Infallible)),
//         }
//     };
//     (@call $renderer:ty; $name:ident; $($x:ident),*) => {
//         $crate::desktop::space::RenderElement::<$renderer>::$name($($x),*)
//     };
//     (@call $renderer:ty as $other:ty; draw; $x:ident, $renderer_ref:ident, $frame:ident, $($tail:ident),*) => {
//         $crate::desktop::space::RenderElement::<$other>::draw($x, $renderer_ref.as_mut(), $frame.as_mut(), $($tail),*).map_err(Into::into)
//     };
//     (@call $renderer:ty as $other:ty; $name:ident; $($x:ident),*) => {
//         $crate::desktop::space::RenderElement::<$other>::$name($($x),*)
//     };
//     (@body $renderer:ty; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
//         fn id(&self) -> usize {
//             match self {
//                 $(
//                     $(
//                         #[$meta]
//                     )*
//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; id; x)
//                 ),*,
//                 Self::_GenericCatcher(_) => unreachable!(),
//             }
//         }

//         fn type_of(&self) -> std::any::TypeId {
//             match self {
//                 $(
//                     $(
//                         #[$meta]
//                     )*
//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; type_of; x)
//                 ),*,
//                 Self::_GenericCatcher(_) => unreachable!(),
//             }
//         }

//         fn location(&self, scale: impl Into<$crate::utils::Scale<f64>>) -> $crate::utils::Point<f64, $crate::utils::Physical> {
//             match self {
//                 $(
//                     $(
//                         #[$meta]
//                     )*
//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; location; x, scale)
//                 ),*,
//                 Self::_GenericCatcher(_) => unreachable!(),
//             }
//         }

//         fn geometry(&self, scale: impl Into<$crate::utils::Scale<f64>>) -> $crate::utils::Rectangle<i32, $crate::utils::Physical> {
//             match self {
//                 $(
//                     $(
//                         #[$meta]
//                     )*
//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; geometry; x, scale)
//                 ),*,
//                 Self::_GenericCatcher(_) => unreachable!(),
//             }
//         }

//         fn accumulated_damage(&self, scale: impl Into<$crate::utils::Scale<f64>>, for_values: Option<$crate::desktop::space::SpaceOutputTuple<'_, '_>>) -> Vec<$crate::utils::Rectangle<i32, $crate::utils::Physical>> {
//             match self {
//                 $(
//                     $(
//                         #[$meta]
//                     )*
//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; accumulated_damage; x, scale, for_values)
//                 ),*,
//                 Self::_GenericCatcher(_) => unreachable!(),
//             }
//         }

//         fn opaque_regions(&self, scale: impl Into<$crate::utils::Scale<f64>>) -> Option<Vec<$crate::utils::Rectangle<i32, $crate::utils::Physical>>> {
//             match self {
//                 $(
//                     $(
//                         #[$meta]
//                     )*
//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; opaque_regions; x, scale)
//                 ),*,
//                 Self::_GenericCatcher(_) => unreachable!(),
//             }
//         }

//         fn z_index(&self) -> u8 {
//             match self {
//                 $(
//                     $(
//                         #[$meta]
//                     )*
//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; z_index; x)
//                 ),*,
//                 Self::_GenericCatcher(_) => unreachable!(),
//             }
//         }
//     };
//     (@draw <$renderer:ty>; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
//         fn draw(
//             &self,
//             renderer: &mut $renderer,
//             frame: &mut <$renderer as $crate::backend::renderer::Renderer>::Frame,
//             scale: impl Into<$crate::utils::Scale<f64>>,
//             location: $crate::utils::Point<f64, $crate::utils::Physical>,
//             damage: &[$crate::utils::Rectangle<i32, $crate::utils::Physical>],
//             log: &slog::Logger,
//         ) -> Result<(), <$renderer as $crate::backend::renderer::Renderer>::Error>
//         where
//         $(
//             $(
//                 $renderer: std::convert::AsMut<$other_renderer>,
//                 <$renderer as $crate::backend::renderer::Renderer>::Frame: std::convert::AsMut<<$other_renderer as $crate::backend::renderer::Renderer>::Frame>,
//                 <$other_renderer as $crate::backend::renderer::Renderer>::Error: Into<<$renderer as $crate::backend::renderer::Renderer>::Error>,
//             )*
//         )*
//         {
//             match self {
//                 $(
//                     $(
//                         #[$meta]
//                     )*
//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; draw; x, renderer, frame, scale, location, damage, log)
//                 ),*,
//                 Self::_GenericCatcher(_) => unreachable!(),
//             }
//         }
//     };
//     (@draw $renderer:ty; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
//         fn draw(
//             &self,
//             renderer: &mut $renderer,
//             frame: &mut <$renderer as $crate::backend::renderer::Renderer>::Frame,
//             scale: impl Into<$crate::utils::Scale<f64>>,
//             location: $crate::utils::Point<f64, $crate::utils::Physical>,
//             damage: &[$crate::utils::Rectangle<i32, $crate::utils::Physical>],
//             log: &slog::Logger,
//         ) -> Result<(), <$renderer as $crate::backend::renderer::Renderer>::Error>
//         {
//             match self {
//                 $(
//                     $(
//                         #[$meta]
//                     )*
//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; draw; x, renderer, frame, scale, location, damage, log)
//                 ),*,
//                 Self::_GenericCatcher(_) => unreachable!(),
//             }
//         }
//     };
//     (@impl $name:ident<$renderer:ident>; $($tail:tt)*) => {
//         impl<$renderer> $crate::desktop::space::RenderElement<$renderer> for $name<$renderer>
//         where
//             $renderer: $crate::backend::renderer::Renderer + $crate::backend::renderer::ImportAll + 'static,
//             <$renderer as Renderer>::TextureId: 'static,
//         {
//             $crate::custom_elements_internal!(@body $renderer; $($tail)*);
//             $crate::custom_elements_internal!(@draw <$renderer>; $($tail)*);
//         }
//     };
//     (@impl $name:ident; $renderer:ident; $($tail:tt)*) => {
//         impl<$renderer> $crate::desktop::space::RenderElement<$renderer> for $name
//         where
//             $renderer: $crate::backend::renderer::Renderer + $crate::backend::renderer::ImportAll + 'static,
//             <$renderer as Renderer>::TextureId: 'static,
//         {
//             $crate::custom_elements_internal!(@body $renderer; $($tail)*);
//             $crate::custom_elements_internal!(@draw <$renderer>; $($tail)*);
//         }
//     };
//     (@impl $name:ident<=$renderer:ty>; $($tail:tt)*) => {
//         impl $crate::desktop::space::RenderElement<$renderer> for $name
//         {
//             $crate::custom_elements_internal!(@body $renderer; $($tail)*);
//             $crate::custom_elements_internal!(@draw $renderer; $($tail)*);
//         }
//     };
//     (@from $name:ident<$renderer:ident>; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
//         $(
//             $(
//                 #[$meta]
//             )*
//             impl<$renderer> From<$field> for $name<$renderer>
//             where
//                 $renderer: $crate::backend::renderer::Renderer + $crate::backend::renderer::ImportAll,
//                 $(
//                     $($renderer: std::convert::AsMut<$other_renderer>,)?
//                 )*
//             {
//                 fn from(field: $field) -> $name<$renderer> {
//                     $name::$body(field)
//                 }
//             }
//         )*
//     };
//     (@from $name:ident; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
//         $(
//             $(
//                 #[$meta]
//             )*
//             impl From<$field> for $name {
//                 fn from(field: $field) -> $name {
//                     $name::$body(field)
//                 }
//             }
//         )*
//     };
// }

// /// Macro to collate multiple [`crate::desktop::space::RenderElement`]-implementations
// /// into one type to be used with [`Space::render_output`].
// /// ## Example
// ///
// /// ```no_run
// /// # use wayland_server::{Display, DisplayHandle};
// /// use smithay::{
// ///     backend::renderer::{Texture, Renderer, ImportAll},
// ///     desktop::space::{SurfaceTree, Space, SpaceOutputTuple, RenderElement},
// ///     utils::{Point, Size, Rectangle, Transform, Logical, Scale},
// /// };
// /// use slog::Logger;
// ///
// /// # use smithay::{
// /// #   backend::SwapBuffersError,
// /// #   backend::renderer::{TextureFilter, Frame},
// /// #   reexports::wayland_server::protocol::wl_buffer,
// /// #   wayland::compositor::SurfaceData,
// /// #   utils::{Buffer, Physical},
// /// # };
// /// # struct DummyRenderer;
// /// # struct DummyFrame;
// /// # struct DummyError;
// /// # struct DummyTexture;
// /// # impl Renderer for DummyRenderer {
// /// #    type Error = smithay::backend::SwapBuffersError;
// /// #    type TextureId = DummyTexture;
// /// #    type Frame = DummyFrame;
// /// #    fn id(&self) -> usize { 0 }
// /// #    fn downscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error> { Ok(()) }
// /// #    fn upscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error> { Ok(()) }
// /// #    fn render<F, R>(
// /// #        &mut self,
// /// #        size: Size<i32, Physical>,
// /// #        dst_transform: Transform,
// /// #        rendering: F,
// /// #    ) -> Result<R, Self::Error>
// /// #    where
// /// #        F: FnOnce(&mut Self, &mut Self::Frame) -> R
// /// #    {
// /// #       Ok(rendering(self, &mut DummyFrame))
// /// #    }
// /// # }
// /// # impl ImportAll for DummyRenderer {
// /// #    fn import_buffer(
// /// #        &mut self,
// /// #        buffer: &wl_buffer::WlBuffer,
// /// #        surface: Option<&SurfaceData>,
// /// #        damage: &[Rectangle<i32, Buffer>],
// /// #    ) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> { None }
// /// # }
// /// # impl Texture for DummyTexture {
// /// #    fn width(&self) -> u32 { 0 }
// /// #    fn height(&self) -> u32 { 0 }
// /// # }
// /// # impl Frame for DummyFrame {
// /// #   type Error = SwapBuffersError;
// /// #   type TextureId = DummyTexture;
// /// #   fn clear(&mut self, color: [f32; 4], at: &[Rectangle<i32, Physical>]) -> Result<(), Self::Error> { Ok(()) }
// /// #   #[allow(clippy::too_many_arguments)]
// /// #   fn render_texture_at(
// /// #       &mut self,
// /// #       texture: &Self::TextureId,
// /// #       pos: Point<i32, Physical>,
// /// #       texture_scale: i32,
// /// #       output_scale: impl Into<Scale<f64>>,
// /// #       src_transform: Transform,
// /// #       damage: &[Rectangle<i32, Physical>],
// /// #       alpha: f32,
// /// #   ) -> Result<(), Self::Error> {
// /// #       Ok(())
// /// #   }
// /// #   fn render_texture_from_to(
// /// #       &mut self,
// /// #       texture: &Self::TextureId,
// /// #       src: Rectangle<f64, Buffer>,
// /// #       dst: Rectangle<i32, Physical>,
// /// #       damage: &[Rectangle<i32, Physical>],
// /// #       src_transform: Transform,
// /// #       alpha: f32,
// /// #   ) -> Result<(), Self::Error> {
// /// #       Ok(())
// /// #   }
// /// #   fn transformation(&self) -> Transform { Transform::Normal }
// /// # }
// ///
// /// smithay::custom_elements! {
// ///     CustomElem; // name of the new type
// ///     SurfaceTree=SurfaceTree, // <variant name> = <type to collate>
// /// };
// ///
// /// smithay::custom_elements! {
// ///     CustomElemGeneric<R>; // You can make it generic over renderers!
// ///     SurfaceTree=SurfaceTree,
// ///     PointerElement=PointerElement<<R as Renderer>::TextureId>, // and then use R in your types
// /// };
// ///
// /// smithay::custom_elements! {
// ///     CustomElemExplicit<=DummyRenderer>; // You can make it only usable with one renderer
// ///     // that is particulary useful, if your renderer has lifetimes (e.g. MultiRenderer)
// ///     SurfaceTree=SurfaceTree,
// ///     PointerElement=PointerElement<DummyTexture>, // and then you use a concrete and matching texture type
// /// };
// /// // in case your renderer wraps another renderer and implements `std::convert::AsMut`
// /// // you can also use `RenderElement`-implementations requiring the wrapped renderer
// /// // by writing something like: `EguiFrame=EguiFrame as <Gles2Renderer>` where `as <renderer>`
// /// // denotes the type of the wrapped renderer.
// ///
// /// pub struct PointerElement<T: Texture> {
// ///    texture: T,
// ///    position: Point<i32, Logical>,
// ///    size: Size<i32, Logical>,
// /// }
// ///
// /// impl<T: Texture> PointerElement<T> {
// ///    pub fn new(texture: T, pointer_pos: Point<i32, Logical>) -> PointerElement<T> {
// ///        let size = texture.size().to_logical(1, Transform::Normal);
// ///        PointerElement {
// ///            texture,
// ///            position: pointer_pos,
// ///            size,
// ///        }
// ///    }
// /// }
// ///
// ///# impl<R> RenderElement<R> for PointerElement<<R as Renderer>::TextureId>
// ///# where
// ///#    R: Renderer + ImportAll,
// ///#    <R as Renderer>::TextureId: 'static,
// ///# {
// ///#    fn id(&self) -> usize {
// ///#        0
// ///#    }
// ///#
// ///#    fn location(&self, scale: impl Into<Scale<f64>>) -> Point<f64, Physical> {
// ///#        self.position.to_f64().to_physical(scale)
// ///#    }
// ///#
// ///#    fn geometry(&self, scale: impl Into<Scale<f64>>) -> Rectangle<i32, Physical> {
// ///#        Rectangle::from_loc_and_size(self.position, self.size).to_f64().to_physical(scale).to_i32_round()
// ///#    }
// ///#
// ///#    fn accumulated_damage(&self, _: impl Into<Scale<f64>>, _: Option<SpaceOutputTuple<'_, '_>>) -> Vec<Rectangle<i32, Physical>> {
// ///#        vec![]
// ///#    }
// ///#
// ///#    fn opaque_regions(&self, scale: impl Into<Scale<f64>>) -> Option<Vec<Rectangle<i32, Physical>>> {
// ///#        None
// ///#    }
// ///#
// ///#    fn draw(
// ///#        &self,
// ///#        _renderer: &mut R,
// ///#        frame: &mut <R as Renderer>::Frame,
// ///#        scale: impl Into<Scale<f64>>,
// ///#        location: Point<f64, Physical>,
// ///#        damage: &[Rectangle<i32, Physical>],
// ///#        _log: &Logger,
// ///#    ) -> Result<(), <R as Renderer>::Error> {
// ///#        Ok(())
// ///#    }
// ///# }
// ///# // just placeholders
// ///# let mut renderer = DummyRenderer;
// ///# let texture = DummyTexture;
// ///# let output = unsafe { std::mem::zeroed() };
// ///# let surface_tree: SurfaceTree = unsafe { std::mem::zeroed() };
// ///# let mut space = Space::new(None);
// ///# let age = 0;
// ///# let display = Display::<()>::new().unwrap();
// ///# let dh = display.handle();
// ///
// /// let elements = [CustomElem::from(surface_tree)];
// /// space.render_output(&mut renderer, &output, age, [0.0, 0.0, 0.0, 1.0], &elements);
// /// ```
// #[macro_export]
// macro_rules! custom_elements {
//     ($vis:vis $name:ident<=$renderer:ty>; $($tail:tt)*) => {
//         $crate::custom_elements_internal!(@enum $vis $name; $($tail)*);
//         $crate::custom_elements_internal!(@impl $name<=$renderer>; $($tail)*);
//         $crate::custom_elements_internal!(@from $name; $($tail)*);

//     };
//     ($vis:vis $name:ident<$renderer:ident>; $($tail:tt)*) => {
//         $crate::custom_elements_internal!(@enum $vis $name<$renderer>; $($tail)*);
//         $crate::custom_elements_internal!(@impl $name<$renderer>; $($tail)*);
//         $crate::custom_elements_internal!(@from $name<$renderer>; $($tail)*);
//     };
//     ($vis:vis $name:ident; $($tail:tt)*) => {
//         $crate::custom_elements_internal!(@enum $vis $name; $($tail)*);
//         $crate::custom_elements_internal!(@impl $name; R; $($tail)*);
//         $crate::custom_elements_internal!(@from $name; $($tail)*);
//     };
// }

/// Render a output
///
/// If multiple spaces are given their elements will be stacked
/// the same way.
#[allow(clippy::too_many_arguments)]
pub fn render_output<
    'a,
    #[cfg(feature = "wayland_frontend")] R: Renderer + ImportAll,
    #[cfg(not(feature = "wayland_frontend"))] R: Renderer,
    C: RenderElement<R>,
    E: SpaceElement + PartialEq + AsRenderElements<R> + 'a,
    L: Into<Option<slog::Logger>>,
    S: IntoIterator<Item = &'a Space<E>>,
>(
    output: &Output,
    renderer: &mut R,
    age: usize,
    spaces: S,
    custom_elements: &'a [C],
    damage_tracked_renderer: &mut DamageTrackedRenderer,
    clear_color: [f32; 4],
    log: L,
) -> Result<(Option<Vec<Rectangle<i32, Physical>>>, RenderElementStates), DamageTrackedRendererError<R>>
where
    <R as Renderer>::TextureId: Texture + 'static,
    <E as AsRenderElements<R>>::RenderElement: 'a,
    SpaceRenderElements<R, <E as AsRenderElements<R>>::RenderElement>:
        From<Wrap<<E as AsRenderElements<R>>::RenderElement>>,
{
    if let DamageTrackedRendererMode::Auto(renderer_output) = damage_tracked_renderer.mode() {
        assert!(renderer_output == output);
    }

    let space_render_elements = space_render_elements(spaces, output)?;

    let mut render_elements: Vec<OutputRenderElements<'a, R, <E as AsRenderElements<R>>::RenderElement, C>> =
        Vec::with_capacity(custom_elements.len() + space_render_elements.len());

    render_elements.extend(custom_elements.iter().map(OutputRenderElements::Custom));
    render_elements.extend(space_render_elements.into_iter().map(OutputRenderElements::Space));

    damage_tracked_renderer.render_output(renderer, age, &*render_elements, clear_color, log)
}

<MSG> add todos and silency some warnings

<DFF> @@ -535,9 +535,35 @@ pub enum OutputError {
 #[error("Output has no active mode")]
 pub struct OutputNoMode;
 
+crate::backend::renderer::output::element::render_elements! {
+    /// Defines the render elements used internally by a [`Space`]
+    ///
+    /// Use them in place of `E` in `space_render_elements` or
+    /// `render_output` if you do not need custom render elements
+    pub SpaceRenderElements<R>;
+    /// A single wayland surface
+    Surface=WaylandSurfaceRenderElement,
+    /// A single texture
+    Texture=TextureRenderElement<<R as Renderer>::TextureId>
+}
+
+impl<R> std::fmt::Debug for SpaceRenderElements<R>
+where
+    R: Renderer + ImportAll,
+    <R as Renderer>::TextureId: std::fmt::Debug,
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Surface(arg0) => f.debug_tuple("Surface").field(arg0).finish(),
+            Self::Texture(arg0) => f.debug_tuple("Texture").field(arg0).finish(),
+            Self::_GenericCatcher(_) => unreachable!(),
+        }
+    }
+}
+
 crate::backend::renderer::output::element::render_elements! {
     OutputRenderElements<'a, R, E>;
-    Space=crate::backend::renderer::output::element::Custom<E>,
+    Space=crate::backend::renderer::output::element::Wrap<E>,
     Custom=&'a E,
 }
 
@@ -592,462 +618,9 @@ where
     render_elements.extend(
         space_render_elements
             .into_iter()
-            .map(|e| OutputRenderElements::Space(crate::backend::renderer::output::element::Custom::from(e))),
+            .map(crate::backend::renderer::output::element::Wrap::from)
+            .map(OutputRenderElements::Space),
     );
 
     output_render.render_output(renderer, age, &*render_elements, log)
 }
-
-// /// Errors thrown by [`Space::render_output`]
-// #[derive(thiserror::Error)]
-// pub enum RenderError<R: Renderer> {
-//     /// The provided [`Renderer`] did return an error during an operation
-//     #[error(transparent)]
-//     Rendering(R::Error),
-//     /// The given [`Output`] has no set mode
-//     #[error("Output has no active mode")]
-//     OutputNoMode,
-//     /// The given [`Output`] is not mapped to this [`Space`].
-//     #[error("Output was not mapped to this space")]
-//     UnmappedOutput,
-// }
-
-// impl<R: Renderer> fmt::Debug for RenderError<R> {
-//     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-//         match self {
-//             RenderError::Rendering(err) => fmt::Debug::fmt(err, f),
-//             RenderError::OutputNoMode => f.write_str("Output has no active move"),
-//             RenderError::UnmappedOutput => f.write_str("Output was not mapped to this space"),
-//         }
-//     }
-// }
-
-// #[macro_export]
-// #[doc(hidden)]
-// macro_rules! custom_elements_internal {
-//     (@enum $vis:vis $name:ident; $($(#[$meta:meta])* $body:ident=$field:ty$( as <$other_renderer:ty>)?),* $(,)?) => {
-//         $vis enum $name {
-//             $(
-//                 $(
-//                     #[$meta]
-//                 )*
-//                 $body($field)
-//             ),*,
-//             #[doc(hidden)]
-//             _GenericCatcher(std::convert::Infallible),
-//         }
-//     };
-//     (@enum $vis:vis $name:ident<$renderer:ident>; $($(#[$meta:meta])* $body:ident=$field:ty$( as <$other_renderer:ty>)?),* $(,)?) => {
-//         $vis enum $name<$renderer>
-//         where
-//             $renderer: $crate::backend::renderer::Renderer + $crate::backend::renderer::ImportAll,
-//         {
-//             $(
-//                 $(
-//                     #[$meta]
-//                 )*
-//                 $body($field)
-//             ),*,
-//             #[doc(hidden)]
-//             _GenericCatcher((std::marker::PhantomData<$renderer>, std::convert::Infallible)),
-//         }
-//     };
-//     (@call $renderer:ty; $name:ident; $($x:ident),*) => {
-//         $crate::desktop::space::RenderElement::<$renderer>::$name($($x),*)
-//     };
-//     (@call $renderer:ty as $other:ty; draw; $x:ident, $renderer_ref:ident, $frame:ident, $($tail:ident),*) => {
-//         $crate::desktop::space::RenderElement::<$other>::draw($x, $renderer_ref.as_mut(), $frame.as_mut(), $($tail),*).map_err(Into::into)
-//     };
-//     (@call $renderer:ty as $other:ty; $name:ident; $($x:ident),*) => {
-//         $crate::desktop::space::RenderElement::<$other>::$name($($x),*)
-//     };
-//     (@body $renderer:ty; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
-//         fn id(&self) -> usize {
-//             match self {
-//                 $(
-//                     $(
-//                         #[$meta]
-//                     )*
-//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; id; x)
-//                 ),*,
-//                 Self::_GenericCatcher(_) => unreachable!(),
-//             }
-//         }
-
-//         fn type_of(&self) -> std::any::TypeId {
-//             match self {
-//                 $(
-//                     $(
-//                         #[$meta]
-//                     )*
-//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; type_of; x)
-//                 ),*,
-//                 Self::_GenericCatcher(_) => unreachable!(),
-//             }
-//         }
-
-//         fn location(&self, scale: impl Into<$crate::utils::Scale<f64>>) -> $crate::utils::Point<f64, $crate::utils::Physical> {
-//             match self {
-//                 $(
-//                     $(
-//                         #[$meta]
-//                     )*
-//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; location; x, scale)
-//                 ),*,
-//                 Self::_GenericCatcher(_) => unreachable!(),
-//             }
-//         }
-
-//         fn geometry(&self, scale: impl Into<$crate::utils::Scale<f64>>) -> $crate::utils::Rectangle<i32, $crate::utils::Physical> {
-//             match self {
-//                 $(
-//                     $(
-//                         #[$meta]
-//                     )*
-//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; geometry; x, scale)
-//                 ),*,
-//                 Self::_GenericCatcher(_) => unreachable!(),
-//             }
-//         }
-
-//         fn accumulated_damage(&self, scale: impl Into<$crate::utils::Scale<f64>>, for_values: Option<$crate::desktop::space::SpaceOutputTuple<'_, '_>>) -> Vec<$crate::utils::Rectangle<i32, $crate::utils::Physical>> {
-//             match self {
-//                 $(
-//                     $(
-//                         #[$meta]
-//                     )*
-//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; accumulated_damage; x, scale, for_values)
-//                 ),*,
-//                 Self::_GenericCatcher(_) => unreachable!(),
-//             }
-//         }
-
-//         fn opaque_regions(&self, scale: impl Into<$crate::utils::Scale<f64>>) -> Option<Vec<$crate::utils::Rectangle<i32, $crate::utils::Physical>>> {
-//             match self {
-//                 $(
-//                     $(
-//                         #[$meta]
-//                     )*
-//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; opaque_regions; x, scale)
-//                 ),*,
-//                 Self::_GenericCatcher(_) => unreachable!(),
-//             }
-//         }
-
-//         fn z_index(&self) -> u8 {
-//             match self {
-//                 $(
-//                     $(
-//                         #[$meta]
-//                     )*
-//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; z_index; x)
-//                 ),*,
-//                 Self::_GenericCatcher(_) => unreachable!(),
-//             }
-//         }
-//     };
-//     (@draw <$renderer:ty>; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
-//         fn draw(
-//             &self,
-//             renderer: &mut $renderer,
-//             frame: &mut <$renderer as $crate::backend::renderer::Renderer>::Frame,
-//             scale: impl Into<$crate::utils::Scale<f64>>,
-//             location: $crate::utils::Point<f64, $crate::utils::Physical>,
-//             damage: &[$crate::utils::Rectangle<i32, $crate::utils::Physical>],
-//             log: &slog::Logger,
-//         ) -> Result<(), <$renderer as $crate::backend::renderer::Renderer>::Error>
-//         where
-//         $(
-//             $(
-//                 $renderer: std::convert::AsMut<$other_renderer>,
-//                 <$renderer as $crate::backend::renderer::Renderer>::Frame: std::convert::AsMut<<$other_renderer as $crate::backend::renderer::Renderer>::Frame>,
-//                 <$other_renderer as $crate::backend::renderer::Renderer>::Error: Into<<$renderer as $crate::backend::renderer::Renderer>::Error>,
-//             )*
-//         )*
-//         {
-//             match self {
-//                 $(
-//                     $(
-//                         #[$meta]
-//                     )*
-//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; draw; x, renderer, frame, scale, location, damage, log)
-//                 ),*,
-//                 Self::_GenericCatcher(_) => unreachable!(),
-//             }
-//         }
-//     };
-//     (@draw $renderer:ty; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
-//         fn draw(
-//             &self,
-//             renderer: &mut $renderer,
-//             frame: &mut <$renderer as $crate::backend::renderer::Renderer>::Frame,
-//             scale: impl Into<$crate::utils::Scale<f64>>,
-//             location: $crate::utils::Point<f64, $crate::utils::Physical>,
-//             damage: &[$crate::utils::Rectangle<i32, $crate::utils::Physical>],
-//             log: &slog::Logger,
-//         ) -> Result<(), <$renderer as $crate::backend::renderer::Renderer>::Error>
-//         {
-//             match self {
-//                 $(
-//                     $(
-//                         #[$meta]
-//                     )*
-//                     Self::$body(x) => $crate::custom_elements_internal!(@call $renderer $(as $other_renderer)?; draw; x, renderer, frame, scale, location, damage, log)
-//                 ),*,
-//                 Self::_GenericCatcher(_) => unreachable!(),
-//             }
-//         }
-//     };
-//     (@impl $name:ident<$renderer:ident>; $($tail:tt)*) => {
-//         impl<$renderer> $crate::desktop::space::RenderElement<$renderer> for $name<$renderer>
-//         where
-//             $renderer: $crate::backend::renderer::Renderer + $crate::backend::renderer::ImportAll + 'static,
-//             <$renderer as Renderer>::TextureId: 'static,
-//         {
-//             $crate::custom_elements_internal!(@body $renderer; $($tail)*);
-//             $crate::custom_elements_internal!(@draw <$renderer>; $($tail)*);
-//         }
-//     };
-//     (@impl $name:ident; $renderer:ident; $($tail:tt)*) => {
-//         impl<$renderer> $crate::desktop::space::RenderElement<$renderer> for $name
-//         where
-//             $renderer: $crate::backend::renderer::Renderer + $crate::backend::renderer::ImportAll + 'static,
-//             <$renderer as Renderer>::TextureId: 'static,
-//         {
-//             $crate::custom_elements_internal!(@body $renderer; $($tail)*);
-//             $crate::custom_elements_internal!(@draw <$renderer>; $($tail)*);
-//         }
-//     };
-//     (@impl $name:ident<=$renderer:ty>; $($tail:tt)*) => {
-//         impl $crate::desktop::space::RenderElement<$renderer> for $name
-//         {
-//             $crate::custom_elements_internal!(@body $renderer; $($tail)*);
-//             $crate::custom_elements_internal!(@draw $renderer; $($tail)*);
-//         }
-//     };
-//     (@from $name:ident<$renderer:ident>; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
-//         $(
-//             $(
-//                 #[$meta]
-//             )*
-//             impl<$renderer> From<$field> for $name<$renderer>
-//             where
-//                 $renderer: $crate::backend::renderer::Renderer + $crate::backend::renderer::ImportAll,
-//                 $(
-//                     $($renderer: std::convert::AsMut<$other_renderer>,)?
-//                 )*
-//             {
-//                 fn from(field: $field) -> $name<$renderer> {
-//                     $name::$body(field)
-//                 }
-//             }
-//         )*
-//     };
-//     (@from $name:ident; $($(#[$meta:meta])* $body:ident=$field:ty $(as <$other_renderer:ty>)?),* $(,)?) => {
-//         $(
-//             $(
-//                 #[$meta]
-//             )*
-//             impl From<$field> for $name {
-//                 fn from(field: $field) -> $name {
-//                     $name::$body(field)
-//                 }
-//             }
-//         )*
-//     };
-// }
-
-// /// Macro to collate multiple [`crate::desktop::space::RenderElement`]-implementations
-// /// into one type to be used with [`Space::render_output`].
-// /// ## Example
-// ///
-// /// ```no_run
-// /// # use wayland_server::{Display, DisplayHandle};
-// /// use smithay::{
-// ///     backend::renderer::{Texture, Renderer, ImportAll},
-// ///     desktop::space::{SurfaceTree, Space, SpaceOutputTuple, RenderElement},
-// ///     utils::{Point, Size, Rectangle, Transform, Logical, Scale},
-// /// };
-// /// use slog::Logger;
-// ///
-// /// # use smithay::{
-// /// #   backend::SwapBuffersError,
-// /// #   backend::renderer::{TextureFilter, Frame},
-// /// #   reexports::wayland_server::protocol::wl_buffer,
-// /// #   wayland::compositor::SurfaceData,
-// /// #   utils::{Buffer, Physical},
-// /// # };
-// /// # struct DummyRenderer;
-// /// # struct DummyFrame;
-// /// # struct DummyError;
-// /// # struct DummyTexture;
-// /// # impl Renderer for DummyRenderer {
-// /// #    type Error = smithay::backend::SwapBuffersError;
-// /// #    type TextureId = DummyTexture;
-// /// #    type Frame = DummyFrame;
-// /// #    fn id(&self) -> usize { 0 }
-// /// #    fn downscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error> { Ok(()) }
-// /// #    fn upscale_filter(&mut self, filter: TextureFilter) -> Result<(), Self::Error> { Ok(()) }
-// /// #    fn render<F, R>(
-// /// #        &mut self,
-// /// #        size: Size<i32, Physical>,
-// /// #        dst_transform: Transform,
-// /// #        rendering: F,
-// /// #    ) -> Result<R, Self::Error>
-// /// #    where
-// /// #        F: FnOnce(&mut Self, &mut Self::Frame) -> R
-// /// #    {
-// /// #       Ok(rendering(self, &mut DummyFrame))
-// /// #    }
-// /// # }
-// /// # impl ImportAll for DummyRenderer {
-// /// #    fn import_buffer(
-// /// #        &mut self,
-// /// #        buffer: &wl_buffer::WlBuffer,
-// /// #        surface: Option<&SurfaceData>,
-// /// #        damage: &[Rectangle<i32, Buffer>],
-// /// #    ) -> Option<Result<<Self as Renderer>::TextureId, <Self as Renderer>::Error>> { None }
-// /// # }
-// /// # impl Texture for DummyTexture {
-// /// #    fn width(&self) -> u32 { 0 }
-// /// #    fn height(&self) -> u32 { 0 }
-// /// # }
-// /// # impl Frame for DummyFrame {
-// /// #   type Error = SwapBuffersError;
-// /// #   type TextureId = DummyTexture;
-// /// #   fn clear(&mut self, color: [f32; 4], at: &[Rectangle<i32, Physical>]) -> Result<(), Self::Error> { Ok(()) }
-// /// #   #[allow(clippy::too_many_arguments)]
-// /// #   fn render_texture_at(
-// /// #       &mut self,
-// /// #       texture: &Self::TextureId,
-// /// #       pos: Point<i32, Physical>,
-// /// #       texture_scale: i32,
-// /// #       output_scale: impl Into<Scale<f64>>,
-// /// #       src_transform: Transform,
-// /// #       damage: &[Rectangle<i32, Physical>],
-// /// #       alpha: f32,
-// /// #   ) -> Result<(), Self::Error> {
-// /// #       Ok(())
-// /// #   }
-// /// #   fn render_texture_from_to(
-// /// #       &mut self,
-// /// #       texture: &Self::TextureId,
-// /// #       src: Rectangle<f64, Buffer>,
-// /// #       dst: Rectangle<i32, Physical>,
-// /// #       damage: &[Rectangle<i32, Physical>],
-// /// #       src_transform: Transform,
-// /// #       alpha: f32,
-// /// #   ) -> Result<(), Self::Error> {
-// /// #       Ok(())
-// /// #   }
-// /// #   fn transformation(&self) -> Transform { Transform::Normal }
-// /// # }
-// ///
-// /// smithay::custom_elements! {
-// ///     CustomElem; // name of the new type
-// ///     SurfaceTree=SurfaceTree, // <variant name> = <type to collate>
-// /// };
-// ///
-// /// smithay::custom_elements! {
-// ///     CustomElemGeneric<R>; // You can make it generic over renderers!
-// ///     SurfaceTree=SurfaceTree,
-// ///     PointerElement=PointerElement<<R as Renderer>::TextureId>, // and then use R in your types
-// /// };
-// ///
-// /// smithay::custom_elements! {
-// ///     CustomElemExplicit<=DummyRenderer>; // You can make it only usable with one renderer
-// ///     // that is particulary useful, if your renderer has lifetimes (e.g. MultiRenderer)
-// ///     SurfaceTree=SurfaceTree,
-// ///     PointerElement=PointerElement<DummyTexture>, // and then you use a concrete and matching texture type
-// /// };
-// /// // in case your renderer wraps another renderer and implements `std::convert::AsMut`
-// /// // you can also use `RenderElement`-implementations requiring the wrapped renderer
-// /// // by writing something like: `EguiFrame=EguiFrame as <Gles2Renderer>` where `as <renderer>`
-// /// // denotes the type of the wrapped renderer.
-// ///
-// /// pub struct PointerElement<T: Texture> {
-// ///    texture: T,
-// ///    position: Point<i32, Logical>,
-// ///    size: Size<i32, Logical>,
-// /// }
-// ///
-// /// impl<T: Texture> PointerElement<T> {
-// ///    pub fn new(texture: T, pointer_pos: Point<i32, Logical>) -> PointerElement<T> {
-// ///        let size = texture.size().to_logical(1, Transform::Normal);
-// ///        PointerElement {
-// ///            texture,
-// ///            position: pointer_pos,
-// ///            size,
-// ///        }
-// ///    }
-// /// }
-// ///
-// ///# impl<R> RenderElement<R> for PointerElement<<R as Renderer>::TextureId>
-// ///# where
-// ///#    R: Renderer + ImportAll,
-// ///#    <R as Renderer>::TextureId: 'static,
-// ///# {
-// ///#    fn id(&self) -> usize {
-// ///#        0
-// ///#    }
-// ///#
-// ///#    fn location(&self, scale: impl Into<Scale<f64>>) -> Point<f64, Physical> {
-// ///#        self.position.to_f64().to_physical(scale)
-// ///#    }
-// ///#
-// ///#    fn geometry(&self, scale: impl Into<Scale<f64>>) -> Rectangle<i32, Physical> {
-// ///#        Rectangle::from_loc_and_size(self.position, self.size).to_f64().to_physical(scale).to_i32_round()
-// ///#    }
-// ///#
-// ///#    fn accumulated_damage(&self, _: impl Into<Scale<f64>>, _: Option<SpaceOutputTuple<'_, '_>>) -> Vec<Rectangle<i32, Physical>> {
-// ///#        vec![]
-// ///#    }
-// ///#
-// ///#    fn opaque_regions(&self, scale: impl Into<Scale<f64>>) -> Option<Vec<Rectangle<i32, Physical>>> {
-// ///#        None
-// ///#    }
-// ///#
-// ///#    fn draw(
-// ///#        &self,
-// ///#        _renderer: &mut R,
-// ///#        frame: &mut <R as Renderer>::Frame,
-// ///#        scale: impl Into<Scale<f64>>,
-// ///#        location: Point<f64, Physical>,
-// ///#        damage: &[Rectangle<i32, Physical>],
-// ///#        _log: &Logger,
-// ///#    ) -> Result<(), <R as Renderer>::Error> {
-// ///#        Ok(())
-// ///#    }
-// ///# }
-// ///# // just placeholders
-// ///# let mut renderer = DummyRenderer;
-// ///# let texture = DummyTexture;
-// ///# let output = unsafe { std::mem::zeroed() };
-// ///# let surface_tree: SurfaceTree = unsafe { std::mem::zeroed() };
-// ///# let mut space = Space::new(None);
-// ///# let age = 0;
-// ///# let display = Display::<()>::new().unwrap();
-// ///# let dh = display.handle();
-// ///
-// /// let elements = [CustomElem::from(surface_tree)];
-// /// space.render_output(&mut renderer, &output, age, [0.0, 0.0, 0.0, 1.0], &elements);
-// /// ```
-// #[macro_export]
-// macro_rules! custom_elements {
-//     ($vis:vis $name:ident<=$renderer:ty>; $($tail:tt)*) => {
-//         $crate::custom_elements_internal!(@enum $vis $name; $($tail)*);
-//         $crate::custom_elements_internal!(@impl $name<=$renderer>; $($tail)*);
-//         $crate::custom_elements_internal!(@from $name; $($tail)*);
-
-//     };
-//     ($vis:vis $name:ident<$renderer:ident>; $($tail:tt)*) => {
-//         $crate::custom_elements_internal!(@enum $vis $name<$renderer>; $($tail)*);
-//         $crate::custom_elements_internal!(@impl $name<$renderer>; $($tail)*);
-//         $crate::custom_elements_internal!(@from $name<$renderer>; $($tail)*);
-//     };
-//     ($vis:vis $name:ident; $($tail:tt)*) => {
-//         $crate::custom_elements_internal!(@enum $vis $name; $($tail)*);
-//         $crate::custom_elements_internal!(@impl $name; R; $($tail)*);
-//         $crate::custom_elements_internal!(@from $name; $($tail)*);
-//     };
-// }

add todos and silency some warnings