desktop: streamline custom elements logic
This commit is contained in:
parent
bb1e68c916
commit
8536fa90a1
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::renderer::{utils::draw_surface_tree, Frame, ImportAll, Renderer, Texture},
|
backend::renderer::{utils::draw_surface_tree, Frame, ImportAll, Renderer, Texture},
|
||||||
desktop::{utils::*, PopupManager, Space},
|
desktop::{space::RenderElement, utils::*, PopupManager, Space},
|
||||||
utils::{user_data::UserDataMap, Logical, Point, Rectangle},
|
utils::{user_data::UserDataMap, Logical, Point, Rectangle},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::with_states,
|
compositor::with_states,
|
||||||
|
@ -267,12 +267,12 @@ impl LayerMap {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub(super) struct LayerState {
|
pub struct LayerState {
|
||||||
location: Point<i32, Logical>,
|
pub location: Point<i32, Logical>,
|
||||||
}
|
}
|
||||||
|
|
||||||
type LayerUserdata = RefCell<Option<LayerState>>;
|
type LayerUserdata = RefCell<Option<LayerState>>;
|
||||||
fn layer_state(layer: &LayerSurface) -> RefMut<'_, LayerState> {
|
pub fn layer_state(layer: &LayerSurface) -> RefMut<'_, LayerState> {
|
||||||
let userdata = layer.user_data();
|
let userdata = layer.user_data();
|
||||||
userdata.insert_if_missing(LayerUserdata::default);
|
userdata.insert_if_missing(LayerUserdata::default);
|
||||||
RefMut::map(userdata.get::<LayerUserdata>().unwrap().borrow_mut(), |opt| {
|
RefMut::map(userdata.get::<LayerUserdata>().unwrap().borrow_mut(), |opt| {
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
// TODO: Remove - but for now, this makes sure these files are not completely highlighted with warnings
|
// TODO: Remove - but for now, this makes sure these files are not completely highlighted with warnings
|
||||||
#![allow(missing_docs, clippy::all)]
|
#![allow(missing_docs, clippy::all)]
|
||||||
mod layer;
|
pub(crate) mod layer;
|
||||||
mod output;
|
|
||||||
mod popup;
|
mod popup;
|
||||||
mod space;
|
pub mod space;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
mod window;
|
mod window;
|
||||||
|
|
||||||
pub use self::layer::*;
|
pub use self::layer::{draw_layer, layer_map_for_output, LayerMap, LayerSurface};
|
||||||
pub use self::popup::*;
|
pub use self::popup::*;
|
||||||
pub use self::space::*;
|
pub use self::space::Space;
|
||||||
pub use self::window::*;
|
pub use self::window::*;
|
||||||
|
|
|
@ -0,0 +1,141 @@
|
||||||
|
use crate::{
|
||||||
|
backend::renderer::{Frame, ImportAll, Renderer, Texture},
|
||||||
|
desktop::{space::*, utils::*},
|
||||||
|
utils::{Logical, Point, Rectangle},
|
||||||
|
wayland::output::Output,
|
||||||
|
};
|
||||||
|
use std::any::{Any, TypeId};
|
||||||
|
use wayland_server::protocol::wl_surface::WlSurface;
|
||||||
|
|
||||||
|
pub trait RenderElement<R, F, E, T>
|
||||||
|
where
|
||||||
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||||
|
F: Frame<Error = E, TextureId = T>,
|
||||||
|
E: std::error::Error,
|
||||||
|
T: Texture + 'static,
|
||||||
|
Self: Any + 'static,
|
||||||
|
{
|
||||||
|
fn id(&self) -> usize;
|
||||||
|
#[doc(hidden)]
|
||||||
|
fn type_of(&self) -> TypeId {
|
||||||
|
std::any::Any::type_id(self)
|
||||||
|
}
|
||||||
|
fn geometry(&self) -> Rectangle<i32, Logical>;
|
||||||
|
fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>>;
|
||||||
|
fn draw(
|
||||||
|
&self,
|
||||||
|
renderer: &mut R,
|
||||||
|
frame: &mut F,
|
||||||
|
scale: f64,
|
||||||
|
location: Point<i32, Logical>,
|
||||||
|
damage: &[Rectangle<i32, Logical>],
|
||||||
|
log: &slog::Logger,
|
||||||
|
) -> Result<(), R::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) trait SpaceElement<R, F, E, T>
|
||||||
|
where
|
||||||
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||||
|
F: Frame<Error = E, TextureId = T>,
|
||||||
|
E: std::error::Error,
|
||||||
|
T: Texture,
|
||||||
|
{
|
||||||
|
fn id(&self) -> usize;
|
||||||
|
fn type_of(&self) -> TypeId;
|
||||||
|
fn location(&self, space_id: usize) -> Point<i32, Logical> {
|
||||||
|
self.geometry(space_id).loc
|
||||||
|
}
|
||||||
|
fn geometry(&self, space_id: usize) -> Rectangle<i32, Logical>;
|
||||||
|
fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>>;
|
||||||
|
fn draw(
|
||||||
|
&self,
|
||||||
|
space_id: usize,
|
||||||
|
renderer: &mut R,
|
||||||
|
frame: &mut F,
|
||||||
|
scale: f64,
|
||||||
|
location: Point<i32, Logical>,
|
||||||
|
damage: &[Rectangle<i32, Logical>],
|
||||||
|
log: &slog::Logger,
|
||||||
|
) -> Result<(), R::Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, F, E, T> SpaceElement<R, F, E, T> for Box<dyn RenderElement<R, F, E, T>>
|
||||||
|
where
|
||||||
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll + 'static,
|
||||||
|
F: Frame<Error = E, TextureId = T> + 'static,
|
||||||
|
E: std::error::Error + 'static,
|
||||||
|
T: Texture + 'static,
|
||||||
|
{
|
||||||
|
fn id(&self) -> usize {
|
||||||
|
(&**self as &dyn RenderElement<R, F, E, T>).id()
|
||||||
|
}
|
||||||
|
fn type_of(&self) -> TypeId {
|
||||||
|
(&**self as &dyn RenderElement<R, F, E, T>).type_of()
|
||||||
|
}
|
||||||
|
fn geometry(&self, _space_id: usize) -> Rectangle<i32, Logical> {
|
||||||
|
(&**self as &dyn RenderElement<R, F, E, T>).geometry()
|
||||||
|
}
|
||||||
|
fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>> {
|
||||||
|
(&**self as &dyn RenderElement<R, F, E, T>).accumulated_damage(for_values)
|
||||||
|
}
|
||||||
|
fn draw(
|
||||||
|
&self,
|
||||||
|
_space_id: usize,
|
||||||
|
renderer: &mut R,
|
||||||
|
frame: &mut F,
|
||||||
|
scale: f64,
|
||||||
|
location: Point<i32, Logical>,
|
||||||
|
damage: &[Rectangle<i32, Logical>],
|
||||||
|
log: &slog::Logger,
|
||||||
|
) -> Result<(), R::Error> {
|
||||||
|
(&**self as &dyn RenderElement<R, F, E, T>).draw(renderer, frame, scale, location, damage, log)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct SurfaceTree {
|
||||||
|
pub surface: WlSurface,
|
||||||
|
pub position: Point<i32, Logical>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, F, E, T> RenderElement<R, F, E, T> for SurfaceTree
|
||||||
|
where
|
||||||
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||||
|
F: Frame<Error = E, TextureId = T>,
|
||||||
|
E: std::error::Error,
|
||||||
|
T: Texture + 'static,
|
||||||
|
{
|
||||||
|
fn id(&self) -> usize {
|
||||||
|
self.surface.as_ref().id() as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
fn geometry(&self) -> Rectangle<i32, Logical> {
|
||||||
|
let mut bbox = bbox_from_surface_tree(&self.surface, (0, 0));
|
||||||
|
bbox.loc += self.position;
|
||||||
|
bbox
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>> {
|
||||||
|
damage_from_surface_tree(&self.surface, (0, 0), for_values)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(
|
||||||
|
&self,
|
||||||
|
renderer: &mut R,
|
||||||
|
frame: &mut F,
|
||||||
|
scale: f64,
|
||||||
|
location: Point<i32, Logical>,
|
||||||
|
damage: &[Rectangle<i32, Logical>],
|
||||||
|
log: &slog::Logger,
|
||||||
|
) -> Result<(), R::Error> {
|
||||||
|
crate::backend::renderer::utils::draw_surface_tree(
|
||||||
|
renderer,
|
||||||
|
frame,
|
||||||
|
&self.surface,
|
||||||
|
scale,
|
||||||
|
location,
|
||||||
|
damage,
|
||||||
|
log,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,72 @@
|
||||||
|
use crate::{
|
||||||
|
backend::renderer::{Frame, ImportAll, Renderer, Texture},
|
||||||
|
desktop::{
|
||||||
|
layer::{layer_state as output_layer_state, *},
|
||||||
|
space::{Space, SpaceElement},
|
||||||
|
},
|
||||||
|
utils::{Logical, Point, Rectangle},
|
||||||
|
wayland::output::Output,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
any::TypeId,
|
||||||
|
cell::{RefCell, RefMut},
|
||||||
|
collections::HashMap,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct LayerState {
|
||||||
|
pub drawn: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
type LayerUserdata = RefCell<HashMap<usize, LayerState>>;
|
||||||
|
pub fn layer_state(space: usize, l: &LayerSurface) -> RefMut<'_, LayerState> {
|
||||||
|
let userdata = l.user_data();
|
||||||
|
userdata.insert_if_missing(LayerUserdata::default);
|
||||||
|
RefMut::map(userdata.get::<LayerUserdata>().unwrap().borrow_mut(), |m| {
|
||||||
|
m.entry(space).or_default()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, F, E, T> SpaceElement<R, F, E, T> for LayerSurface
|
||||||
|
where
|
||||||
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||||
|
F: Frame<Error = E, TextureId = T>,
|
||||||
|
E: std::error::Error,
|
||||||
|
T: Texture + 'static,
|
||||||
|
{
|
||||||
|
fn id(&self) -> usize {
|
||||||
|
self.0.id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_of(&self) -> TypeId {
|
||||||
|
TypeId::of::<LayerSurface>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn geometry(&self, space_id: usize) -> Rectangle<i32, Logical> {
|
||||||
|
let mut bbox = self.bbox_with_popups();
|
||||||
|
let state = output_layer_state(self);
|
||||||
|
bbox.loc += state.location;
|
||||||
|
bbox
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>> {
|
||||||
|
self.accumulated_damage(for_values)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(
|
||||||
|
&self,
|
||||||
|
space_id: usize,
|
||||||
|
renderer: &mut R,
|
||||||
|
frame: &mut F,
|
||||||
|
scale: f64,
|
||||||
|
location: Point<i32, Logical>,
|
||||||
|
damage: &[Rectangle<i32, Logical>],
|
||||||
|
log: &slog::Logger,
|
||||||
|
) -> Result<(), R::Error> {
|
||||||
|
let res = draw_layer(renderer, frame, self, scale, location, damage, log);
|
||||||
|
if res.is_ok() {
|
||||||
|
layer_state(space_id, self).drawn = true;
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,7 +1,9 @@
|
||||||
use super::{draw_window, Window};
|
|
||||||
use crate::{
|
use crate::{
|
||||||
backend::renderer::{utils::SurfaceState, Frame, ImportAll, Renderer, Texture, Transform},
|
backend::renderer::{utils::SurfaceState, Frame, ImportAll, Renderer, Transform},
|
||||||
desktop::{layer::*, output::*},
|
desktop::{
|
||||||
|
layer::{layer_map_for_output, LayerSurface},
|
||||||
|
window::Window,
|
||||||
|
},
|
||||||
utils::{Logical, Point, Rectangle},
|
utils::{Logical, Point, Rectangle},
|
||||||
wayland::{
|
wayland::{
|
||||||
compositor::{
|
compositor::{
|
||||||
|
@ -14,9 +16,8 @@ use crate::{
|
||||||
};
|
};
|
||||||
use indexmap::{IndexMap, IndexSet};
|
use indexmap::{IndexMap, IndexSet};
|
||||||
use std::{
|
use std::{
|
||||||
any::{Any, TypeId},
|
cell::RefCell,
|
||||||
cell::{RefCell, RefMut},
|
collections::{HashSet, VecDeque},
|
||||||
collections::{HashMap, HashSet, VecDeque},
|
|
||||||
sync::{
|
sync::{
|
||||||
atomic::{AtomicUsize, Ordering},
|
atomic::{AtomicUsize, Ordering},
|
||||||
Mutex,
|
Mutex,
|
||||||
|
@ -24,6 +25,16 @@ use std::{
|
||||||
};
|
};
|
||||||
use wayland_server::protocol::wl_surface::WlSurface;
|
use wayland_server::protocol::wl_surface::WlSurface;
|
||||||
|
|
||||||
|
mod element;
|
||||||
|
mod layer;
|
||||||
|
mod output;
|
||||||
|
mod window;
|
||||||
|
|
||||||
|
pub use self::element::*;
|
||||||
|
use self::layer::*;
|
||||||
|
use self::output::*;
|
||||||
|
use self::window::*;
|
||||||
|
|
||||||
static SPACE_ID: AtomicUsize = AtomicUsize::new(0);
|
static SPACE_ID: AtomicUsize = AtomicUsize::new(0);
|
||||||
lazy_static::lazy_static! {
|
lazy_static::lazy_static! {
|
||||||
static ref SPACE_IDS: Mutex<HashSet<usize>> = Mutex::new(HashSet::new());
|
static ref SPACE_IDS: Mutex<HashSet<usize>> = Mutex::new(HashSet::new());
|
||||||
|
@ -46,35 +57,6 @@ fn next_space_id() -> usize {
|
||||||
id
|
id
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct WindowState {
|
|
||||||
location: Point<i32, Logical>,
|
|
||||||
drawn: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
type WindowUserdata = RefCell<HashMap<usize, WindowState>>;
|
|
||||||
fn window_state(space: usize, w: &Window) -> RefMut<'_, WindowState> {
|
|
||||||
let userdata = w.user_data();
|
|
||||||
userdata.insert_if_missing(WindowUserdata::default);
|
|
||||||
RefMut::map(userdata.get::<WindowUserdata>().unwrap().borrow_mut(), |m| {
|
|
||||||
m.entry(space).or_default()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
struct LayerState {
|
|
||||||
drawn: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
type LayerUserdata = RefCell<HashMap<usize, LayerState>>;
|
|
||||||
fn layer_state(space: usize, l: &LayerSurface) -> RefMut<'_, LayerState> {
|
|
||||||
let userdata = l.user_data();
|
|
||||||
userdata.insert_if_missing(LayerUserdata::default);
|
|
||||||
RefMut::map(userdata.get::<LayerUserdata>().unwrap().borrow_mut(), |m| {
|
|
||||||
m.entry(space).or_default()
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Maybe replace UnmanagedResource if nothing else comes up?
|
// TODO: Maybe replace UnmanagedResource if nothing else comes up?
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum SpaceError {
|
pub enum SpaceError {
|
||||||
|
@ -421,12 +403,9 @@ impl Space {
|
||||||
output: &Output,
|
output: &Output,
|
||||||
age: usize,
|
age: usize,
|
||||||
clear_color: [f32; 4],
|
clear_color: [f32; 4],
|
||||||
custom_elements: &[&(dyn RenderElement<
|
custom_elements: &[Box<
|
||||||
R,
|
dyn RenderElement<R, <R as Renderer>::Frame, <R as Renderer>::Error, <R as Renderer>::TextureId>,
|
||||||
<R as Renderer>::Frame,
|
>],
|
||||||
<R as Renderer>::Error,
|
|
||||||
<R as Renderer>::TextureId,
|
|
||||||
>)],
|
|
||||||
) -> Result<bool, RenderError<R>>
|
) -> Result<bool, RenderError<R>>
|
||||||
where
|
where
|
||||||
R: Renderer + ImportAll + 'static,
|
R: Renderer + ImportAll + 'static,
|
||||||
|
@ -434,6 +413,9 @@ impl Space {
|
||||||
R::Error: 'static,
|
R::Error: 'static,
|
||||||
R::Frame: 'static,
|
R::Frame: 'static,
|
||||||
{
|
{
|
||||||
|
type SpaceElem<R> =
|
||||||
|
dyn SpaceElement<R, <R as Renderer>::Frame, <R as Renderer>::Error, <R as Renderer>::TextureId>;
|
||||||
|
|
||||||
let mut state = output_state(self.id, output);
|
let mut state = output_state(self.id, output);
|
||||||
let output_size = output
|
let output_size = output
|
||||||
.current_mode()
|
.current_mode()
|
||||||
|
@ -451,14 +433,16 @@ impl Space {
|
||||||
for old_toplevel in state
|
for old_toplevel in state
|
||||||
.last_state
|
.last_state
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(id, w)| {
|
.filter_map(|(id, geo)| {
|
||||||
if !self.windows.iter().any(|w| ToplevelId::Xdg(w.0.id) == *id)
|
if !self
|
||||||
&& !layer_map.layers().any(|l| ToplevelId::Layer(l.0.id) == *id)
|
.windows
|
||||||
&& !custom_elements
|
|
||||||
.iter()
|
.iter()
|
||||||
.any(|c| ToplevelId::Custom(c.type_of(), c.id()) == *id)
|
.map(|w| w as &SpaceElem<R>)
|
||||||
|
.chain(layer_map.layers().map(|l| l as &SpaceElem<R>))
|
||||||
|
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||||
|
.any(|e| ToplevelId::from(e) == *id)
|
||||||
{
|
{
|
||||||
Some(*w)
|
Some(*geo)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
@ -470,9 +454,15 @@ impl Space {
|
||||||
}
|
}
|
||||||
|
|
||||||
// lets iterate front to back and figure out, what new windows or unmoved windows we have
|
// lets iterate front to back and figure out, what new windows or unmoved windows we have
|
||||||
for window in self.windows.iter() {
|
for element in self
|
||||||
let geo = window_rect_with_popups(window, &self.id);
|
.windows
|
||||||
let old_geo = state.last_state.get(&ToplevelId::Xdg(window.0.id)).cloned();
|
.iter()
|
||||||
|
.map(|w| w as &SpaceElem<R>)
|
||||||
|
.chain(layer_map.layers().map(|l| l as &SpaceElem<R>))
|
||||||
|
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||||
|
{
|
||||||
|
let geo = element.geometry(self.id);
|
||||||
|
let old_geo = state.last_state.get(&ToplevelId::from(element)).cloned();
|
||||||
|
|
||||||
// window was moved or resized
|
// window was moved or resized
|
||||||
if old_geo.map(|old_geo| old_geo != geo).unwrap_or(false) {
|
if old_geo.map(|old_geo| old_geo != geo).unwrap_or(false) {
|
||||||
|
@ -481,62 +471,13 @@ impl Space {
|
||||||
damage.push(geo);
|
damage.push(geo);
|
||||||
} else {
|
} else {
|
||||||
// window stayed at its place
|
// window stayed at its place
|
||||||
let loc = window_loc(window, &self.id);
|
let loc = element.location(self.id);
|
||||||
damage.extend(
|
damage.extend(element.accumulated_damage(Some((self, output))).into_iter().map(
|
||||||
window
|
|mut rect| {
|
||||||
.accumulated_damage(Some((self, output)))
|
|
||||||
.into_iter()
|
|
||||||
.map(|mut rect| {
|
|
||||||
rect.loc += loc;
|
rect.loc += loc;
|
||||||
rect
|
rect
|
||||||
}),
|
},
|
||||||
);
|
));
|
||||||
}
|
|
||||||
}
|
|
||||||
for layer in layer_map.layers() {
|
|
||||||
let geo = layer_map.layer_geometry(layer);
|
|
||||||
let old_geo = state.last_state.get(&ToplevelId::Layer(layer.0.id)).cloned();
|
|
||||||
|
|
||||||
// layer moved or resized
|
|
||||||
if old_geo.map(|old_geo| old_geo != geo).unwrap_or(false) {
|
|
||||||
// Add damage for the old position of the layer
|
|
||||||
damage.push(old_geo.unwrap());
|
|
||||||
damage.push(geo);
|
|
||||||
} else {
|
|
||||||
let location = geo.loc;
|
|
||||||
damage.extend(
|
|
||||||
layer
|
|
||||||
.accumulated_damage(Some((self, output)))
|
|
||||||
.into_iter()
|
|
||||||
.map(|mut rect| {
|
|
||||||
rect.loc += location;
|
|
||||||
rect
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for elem in custom_elements {
|
|
||||||
let geo = elem.geometry();
|
|
||||||
let old_geo = state
|
|
||||||
.last_state
|
|
||||||
.get(&ToplevelId::Custom(elem.type_of(), elem.id()))
|
|
||||||
.cloned();
|
|
||||||
|
|
||||||
// moved of resized
|
|
||||||
if old_geo.map(|old_geo| old_geo != geo).unwrap_or(false) {
|
|
||||||
// Add damage for the old position of the layer
|
|
||||||
damage.push(old_geo.unwrap());
|
|
||||||
damage.push(geo);
|
|
||||||
} else {
|
|
||||||
let location = geo.loc;
|
|
||||||
damage.extend(
|
|
||||||
elem.accumulated_damage(Some((self, output)))
|
|
||||||
.into_iter()
|
|
||||||
.map(|mut rect| {
|
|
||||||
rect.loc += location;
|
|
||||||
rect
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -598,115 +539,40 @@ impl Space {
|
||||||
|
|
||||||
// Then re-draw all windows & layers overlapping with a damage rect.
|
// Then re-draw all windows & layers overlapping with a damage rect.
|
||||||
|
|
||||||
for layer in layer_map
|
for element in layer_map
|
||||||
.layers_on(WlrLayer::Background)
|
.layers_on(WlrLayer::Background)
|
||||||
.chain(layer_map.layers_on(WlrLayer::Bottom))
|
.chain(layer_map.layers_on(WlrLayer::Bottom))
|
||||||
|
.map(|l| l as &SpaceElem<R>)
|
||||||
|
.chain(self.windows.iter().map(|w| w as &SpaceElem<R>))
|
||||||
|
.chain(
|
||||||
|
layer_map
|
||||||
|
.layers_on(WlrLayer::Top)
|
||||||
|
.chain(layer_map.layers_on(WlrLayer::Overlay))
|
||||||
|
.map(|l| l as &SpaceElem<R>),
|
||||||
|
)
|
||||||
|
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||||
{
|
{
|
||||||
let lgeo = layer_map.layer_geometry(layer);
|
let geo = element.geometry(self.id);
|
||||||
if damage.iter().any(|geo| lgeo.overlaps(*geo)) {
|
if damage.iter().any(|d| d.overlaps(geo)) {
|
||||||
let layer_damage = damage
|
let loc = element.location(self.id) - output_geo.loc;
|
||||||
|
let damage = damage
|
||||||
.iter()
|
.iter()
|
||||||
.flat_map(|geo| geo.intersection(lgeo))
|
.flat_map(|d| d.intersection(geo))
|
||||||
.map(|geo| Rectangle::from_loc_and_size(geo.loc - lgeo.loc, geo.size))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
slog::trace!(
|
|
||||||
self.logger,
|
|
||||||
"Rendering layer at {:?} with damage {:#?}",
|
|
||||||
lgeo,
|
|
||||||
layer_damage
|
|
||||||
);
|
|
||||||
draw_layer(
|
|
||||||
renderer,
|
|
||||||
frame,
|
|
||||||
layer,
|
|
||||||
state.render_scale,
|
|
||||||
lgeo.loc,
|
|
||||||
&layer_damage,
|
|
||||||
&self.logger,
|
|
||||||
)?;
|
|
||||||
layer_state(self.id, layer).drawn = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for window in self.windows.iter() {
|
|
||||||
let wgeo = window_rect_with_popups(window, &self.id);
|
|
||||||
let mut loc = window_loc(window, &self.id);
|
|
||||||
if damage.iter().any(|geo| wgeo.overlaps(*geo)) {
|
|
||||||
loc -= output_geo.loc;
|
|
||||||
let win_damage = damage
|
|
||||||
.iter()
|
|
||||||
.flat_map(|geo| geo.intersection(wgeo))
|
|
||||||
.map(|geo| Rectangle::from_loc_and_size(geo.loc - loc, geo.size))
|
.map(|geo| Rectangle::from_loc_and_size(geo.loc - loc, geo.size))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
slog::trace!(
|
slog::trace!(
|
||||||
self.logger,
|
self.logger,
|
||||||
"Rendering window at {:?} with damage {:#?}",
|
"Rendering toplevel at {:?} with damage {:#?}",
|
||||||
wgeo,
|
geo,
|
||||||
win_damage
|
damage
|
||||||
);
|
);
|
||||||
draw_window(
|
element.draw(
|
||||||
|
self.id,
|
||||||
renderer,
|
renderer,
|
||||||
frame,
|
frame,
|
||||||
window,
|
|
||||||
state.render_scale,
|
state.render_scale,
|
||||||
loc,
|
loc,
|
||||||
&win_damage,
|
&damage,
|
||||||
&self.logger,
|
|
||||||
)?;
|
|
||||||
window_state(self.id, window).drawn = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for layer in layer_map
|
|
||||||
.layers_on(WlrLayer::Top)
|
|
||||||
.chain(layer_map.layers_on(WlrLayer::Overlay))
|
|
||||||
{
|
|
||||||
let lgeo = layer_map.layer_geometry(layer);
|
|
||||||
if damage.iter().any(|geo| lgeo.overlaps(*geo)) {
|
|
||||||
let layer_damage = damage
|
|
||||||
.iter()
|
|
||||||
.flat_map(|geo| geo.intersection(lgeo))
|
|
||||||
.map(|geo| Rectangle::from_loc_and_size(geo.loc - lgeo.loc, geo.size))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
slog::trace!(
|
|
||||||
self.logger,
|
|
||||||
"Rendering layer at {:?} with damage {:#?}",
|
|
||||||
lgeo,
|
|
||||||
layer_damage
|
|
||||||
);
|
|
||||||
draw_layer(
|
|
||||||
renderer,
|
|
||||||
frame,
|
|
||||||
layer,
|
|
||||||
state.render_scale,
|
|
||||||
lgeo.loc,
|
|
||||||
&layer_damage,
|
|
||||||
&self.logger,
|
|
||||||
)?;
|
|
||||||
layer_state(self.id, layer).drawn = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for elem in custom_elements {
|
|
||||||
let egeo = elem.geometry();
|
|
||||||
if damage.iter().any(|geo| egeo.overlaps(*geo)) {
|
|
||||||
let elem_damage = damage
|
|
||||||
.iter()
|
|
||||||
.flat_map(|geo| geo.intersection(egeo))
|
|
||||||
.map(|geo| Rectangle::from_loc_and_size(geo.loc - egeo.loc, geo.size))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
slog::trace!(
|
|
||||||
self.logger,
|
|
||||||
"Rendering custom element at {:?} with damage {:#?}",
|
|
||||||
egeo,
|
|
||||||
elem_damage
|
|
||||||
);
|
|
||||||
elem.draw(
|
|
||||||
renderer,
|
|
||||||
frame,
|
|
||||||
state.render_scale,
|
|
||||||
egeo.loc,
|
|
||||||
&elem_damage,
|
|
||||||
&self.logger,
|
&self.logger,
|
||||||
)?;
|
)?;
|
||||||
}
|
}
|
||||||
|
@ -726,18 +592,13 @@ impl Space {
|
||||||
state.last_state = self
|
state.last_state = self
|
||||||
.windows
|
.windows
|
||||||
.iter()
|
.iter()
|
||||||
.map(|window| {
|
.map(|w| w as &SpaceElem<R>)
|
||||||
let wgeo = window_rect_with_popups(window, &self.id);
|
.chain(layer_map.layers().map(|l| l as &SpaceElem<R>))
|
||||||
(ToplevelId::Xdg(window.0.id), wgeo)
|
.chain(custom_elements.iter().map(|c| c as &SpaceElem<R>))
|
||||||
|
.map(|elem| {
|
||||||
|
let geo = elem.geometry(self.id);
|
||||||
|
(ToplevelId::from(elem), geo)
|
||||||
})
|
})
|
||||||
.chain(layer_map.layers().map(|layer| {
|
|
||||||
let lgeo = layer_map.layer_geometry(layer);
|
|
||||||
(ToplevelId::Layer(layer.0.id), lgeo)
|
|
||||||
}))
|
|
||||||
.chain(custom_elements.iter().map(|custom| {
|
|
||||||
let egeo = custom.geometry();
|
|
||||||
(ToplevelId::Custom(custom.type_of(), custom.id()), egeo)
|
|
||||||
}))
|
|
||||||
.collect();
|
.collect();
|
||||||
state.old_damage.push_front(new_damage);
|
state.old_damage.push_front(new_damage);
|
||||||
|
|
||||||
|
@ -768,78 +629,6 @@ impl Space {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RenderElement<R, F, E, T>
|
|
||||||
where
|
|
||||||
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
|
||||||
F: Frame<Error = E, TextureId = T>,
|
|
||||||
E: std::error::Error,
|
|
||||||
T: Texture + 'static,
|
|
||||||
Self: Any + 'static,
|
|
||||||
{
|
|
||||||
fn id(&self) -> usize;
|
|
||||||
fn type_of(&self) -> TypeId {
|
|
||||||
std::any::Any::type_id(self)
|
|
||||||
}
|
|
||||||
fn geometry(&self) -> Rectangle<i32, Logical>;
|
|
||||||
fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>>;
|
|
||||||
fn draw(
|
|
||||||
&self,
|
|
||||||
renderer: &mut R,
|
|
||||||
frame: &mut F,
|
|
||||||
scale: f64,
|
|
||||||
location: Point<i32, Logical>,
|
|
||||||
damage: &[Rectangle<i32, Logical>],
|
|
||||||
log: &slog::Logger,
|
|
||||||
) -> Result<(), R::Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct SurfaceTree {
|
|
||||||
pub surface: WlSurface,
|
|
||||||
pub position: Point<i32, Logical>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<R, F, E, T> RenderElement<R, F, E, T> for SurfaceTree
|
|
||||||
where
|
|
||||||
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
|
||||||
F: Frame<Error = E, TextureId = T>,
|
|
||||||
E: std::error::Error,
|
|
||||||
T: Texture + 'static,
|
|
||||||
{
|
|
||||||
fn id(&self) -> usize {
|
|
||||||
self.surface.as_ref().id() as usize
|
|
||||||
}
|
|
||||||
fn geometry(&self) -> Rectangle<i32, Logical> {
|
|
||||||
let mut bbox = super::utils::bbox_from_surface_tree(&self.surface, (0, 0));
|
|
||||||
bbox.loc += self.position;
|
|
||||||
bbox
|
|
||||||
}
|
|
||||||
|
|
||||||
fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>> {
|
|
||||||
super::utils::damage_from_surface_tree(&self.surface, (0, 0), for_values)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw(
|
|
||||||
&self,
|
|
||||||
renderer: &mut R,
|
|
||||||
frame: &mut F,
|
|
||||||
scale: f64,
|
|
||||||
location: Point<i32, Logical>,
|
|
||||||
damage: &[Rectangle<i32, Logical>],
|
|
||||||
log: &slog::Logger,
|
|
||||||
) -> Result<(), R::Error> {
|
|
||||||
crate::backend::renderer::utils::draw_surface_tree(
|
|
||||||
renderer,
|
|
||||||
frame,
|
|
||||||
&self.surface,
|
|
||||||
scale,
|
|
||||||
location,
|
|
||||||
damage,
|
|
||||||
log,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, thiserror::Error)]
|
#[derive(Debug, thiserror::Error)]
|
||||||
pub enum RenderError<R: Renderer> {
|
pub enum RenderError<R: Renderer> {
|
||||||
#[error(transparent)]
|
#[error(transparent)]
|
||||||
|
@ -847,35 +636,3 @@ pub enum RenderError<R: Renderer> {
|
||||||
#[error("Output has no active mode")]
|
#[error("Output has no active mode")]
|
||||||
OutputNoMode,
|
OutputNoMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn window_geo(window: &Window, space_id: &usize) -> Rectangle<i32, Logical> {
|
|
||||||
let loc = window_loc(window, space_id);
|
|
||||||
let mut wgeo = window.geometry();
|
|
||||||
wgeo.loc = loc;
|
|
||||||
wgeo
|
|
||||||
}
|
|
||||||
|
|
||||||
fn window_rect(window: &Window, space_id: &usize) -> Rectangle<i32, Logical> {
|
|
||||||
let loc = window_loc(window, space_id);
|
|
||||||
let mut wgeo = window.bbox();
|
|
||||||
wgeo.loc += loc;
|
|
||||||
wgeo
|
|
||||||
}
|
|
||||||
|
|
||||||
fn window_rect_with_popups(window: &Window, space_id: &usize) -> Rectangle<i32, Logical> {
|
|
||||||
let loc = window_loc(window, space_id);
|
|
||||||
let mut wgeo = window.bbox_with_popups();
|
|
||||||
wgeo.loc += loc;
|
|
||||||
wgeo
|
|
||||||
}
|
|
||||||
|
|
||||||
fn window_loc(window: &Window, space_id: &usize) -> Point<i32, Logical> {
|
|
||||||
window
|
|
||||||
.user_data()
|
|
||||||
.get::<RefCell<HashMap<usize, WindowState>>>()
|
|
||||||
.unwrap()
|
|
||||||
.borrow()
|
|
||||||
.get(space_id)
|
|
||||||
.unwrap()
|
|
||||||
.location
|
|
||||||
}
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
|
backend::renderer::{Frame, ImportAll, Renderer, Texture},
|
||||||
|
desktop::{space::SpaceElement, LayerSurface, Window},
|
||||||
utils::{Logical, Point, Rectangle},
|
utils::{Logical, Point, Rectangle},
|
||||||
wayland::output::Output,
|
wayland::output::Output,
|
||||||
};
|
};
|
||||||
|
@ -6,43 +8,34 @@ use indexmap::IndexMap;
|
||||||
use wayland_server::protocol::wl_surface::WlSurface;
|
use wayland_server::protocol::wl_surface::WlSurface;
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
any::TypeId,
|
any::{Any, TypeId},
|
||||||
cell::{RefCell, RefMut},
|
cell::{RefCell, RefMut},
|
||||||
collections::{HashMap, VecDeque},
|
collections::{HashMap, VecDeque},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, Hash, PartialEq, Eq)]
|
||||||
pub(super) enum ToplevelId {
|
pub struct ToplevelId {
|
||||||
Xdg(usize),
|
t_id: TypeId,
|
||||||
Layer(usize),
|
id: usize,
|
||||||
Custom(TypeId, usize),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToplevelId {
|
impl<R, F, E, T> From<&dyn SpaceElement<R, F, E, T>> for ToplevelId
|
||||||
pub fn is_xdg(&self) -> bool {
|
where
|
||||||
match self {
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll + 'static,
|
||||||
ToplevelId::Xdg(_) => true,
|
F: Frame<Error = E, TextureId = T> + 'static,
|
||||||
_ => false,
|
E: std::error::Error + 'static,
|
||||||
}
|
T: Texture + 'static,
|
||||||
}
|
{
|
||||||
|
fn from(elem: &dyn SpaceElement<R, F, E, T>) -> ToplevelId {
|
||||||
pub fn is_layer(&self) -> bool {
|
ToplevelId {
|
||||||
match self {
|
t_id: elem.type_of(),
|
||||||
ToplevelId::Layer(_) => true,
|
id: elem.id(),
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn is_custom(&self) -> bool {
|
|
||||||
match self {
|
|
||||||
ToplevelId::Custom(_, _) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Default)]
|
#[derive(Clone, Default)]
|
||||||
pub(super) struct OutputState {
|
pub struct OutputState {
|
||||||
pub location: Point<i32, Logical>,
|
pub location: Point<i32, Logical>,
|
||||||
pub render_scale: f64,
|
pub render_scale: f64,
|
||||||
|
|
||||||
|
@ -54,8 +47,8 @@ pub(super) struct OutputState {
|
||||||
pub surfaces: Vec<WlSurface>,
|
pub surfaces: Vec<WlSurface>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) type OutputUserdata = RefCell<HashMap<usize, OutputState>>;
|
pub type OutputUserdata = RefCell<HashMap<usize, OutputState>>;
|
||||||
pub(super) fn output_state(space: usize, o: &Output) -> RefMut<'_, OutputState> {
|
pub fn output_state(space: usize, o: &Output) -> RefMut<'_, OutputState> {
|
||||||
let userdata = o.user_data();
|
let userdata = o.user_data();
|
||||||
userdata.insert_if_missing(OutputUserdata::default);
|
userdata.insert_if_missing(OutputUserdata::default);
|
||||||
RefMut::map(userdata.get::<OutputUserdata>().unwrap().borrow_mut(), |m| {
|
RefMut::map(userdata.get::<OutputUserdata>().unwrap().borrow_mut(), |m| {
|
|
@ -0,0 +1,106 @@
|
||||||
|
use crate::{
|
||||||
|
backend::renderer::{Frame, ImportAll, Renderer, Texture},
|
||||||
|
desktop::{
|
||||||
|
space::{Space, SpaceElement},
|
||||||
|
window::{draw_window, Window},
|
||||||
|
},
|
||||||
|
utils::{Logical, Point, Rectangle},
|
||||||
|
wayland::output::Output,
|
||||||
|
};
|
||||||
|
use std::{
|
||||||
|
any::TypeId,
|
||||||
|
cell::{RefCell, RefMut},
|
||||||
|
collections::HashMap,
|
||||||
|
};
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct WindowState {
|
||||||
|
pub location: Point<i32, Logical>,
|
||||||
|
pub drawn: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub type WindowUserdata = RefCell<HashMap<usize, WindowState>>;
|
||||||
|
pub fn window_state(space: usize, w: &Window) -> RefMut<'_, WindowState> {
|
||||||
|
let userdata = w.user_data();
|
||||||
|
userdata.insert_if_missing(WindowUserdata::default);
|
||||||
|
RefMut::map(userdata.get::<WindowUserdata>().unwrap().borrow_mut(), |m| {
|
||||||
|
m.entry(space).or_default()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn window_geo(window: &Window, space_id: &usize) -> Rectangle<i32, Logical> {
|
||||||
|
let loc = window_loc(window, space_id);
|
||||||
|
let mut wgeo = window.geometry();
|
||||||
|
wgeo.loc = loc;
|
||||||
|
wgeo
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn window_rect(window: &Window, space_id: &usize) -> Rectangle<i32, Logical> {
|
||||||
|
let loc = window_loc(window, space_id);
|
||||||
|
let mut wgeo = window.bbox();
|
||||||
|
wgeo.loc += loc;
|
||||||
|
wgeo
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn window_rect_with_popups(window: &Window, space_id: &usize) -> Rectangle<i32, Logical> {
|
||||||
|
let loc = window_loc(window, space_id);
|
||||||
|
let mut wgeo = window.bbox_with_popups();
|
||||||
|
wgeo.loc += loc;
|
||||||
|
wgeo
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn window_loc(window: &Window, space_id: &usize) -> Point<i32, Logical> {
|
||||||
|
window
|
||||||
|
.user_data()
|
||||||
|
.get::<RefCell<HashMap<usize, WindowState>>>()
|
||||||
|
.unwrap()
|
||||||
|
.borrow()
|
||||||
|
.get(space_id)
|
||||||
|
.unwrap()
|
||||||
|
.location
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<R, F, E, T> SpaceElement<R, F, E, T> for Window
|
||||||
|
where
|
||||||
|
R: Renderer<Error = E, TextureId = T, Frame = F> + ImportAll,
|
||||||
|
F: Frame<Error = E, TextureId = T>,
|
||||||
|
E: std::error::Error,
|
||||||
|
T: Texture + 'static,
|
||||||
|
{
|
||||||
|
fn id(&self) -> usize {
|
||||||
|
self.0.id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_of(&self) -> TypeId {
|
||||||
|
TypeId::of::<Window>()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn location(&self, space_id: usize) -> Point<i32, Logical> {
|
||||||
|
window_loc(self, &space_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn geometry(&self, space_id: usize) -> Rectangle<i32, Logical> {
|
||||||
|
window_rect_with_popups(self, &space_id)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn accumulated_damage(&self, for_values: Option<(&Space, &Output)>) -> Vec<Rectangle<i32, Logical>> {
|
||||||
|
self.accumulated_damage(for_values)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(
|
||||||
|
&self,
|
||||||
|
space_id: usize,
|
||||||
|
renderer: &mut R,
|
||||||
|
frame: &mut F,
|
||||||
|
scale: f64,
|
||||||
|
location: Point<i32, Logical>,
|
||||||
|
damage: &[Rectangle<i32, Logical>],
|
||||||
|
log: &slog::Logger,
|
||||||
|
) -> Result<(), R::Error> {
|
||||||
|
let res = draw_window(renderer, frame, &self, scale, location, damage, log);
|
||||||
|
if res.is_ok() {
|
||||||
|
window_state(space_id, self).drawn = true;
|
||||||
|
}
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue