Skip to main content

kozan_core/compositor/
layer_tree.rs

1//! Layer tree — arena of compositor layers.
2//!
3//! Chrome: `cc::LayerTreeImpl` — the compositor's view of the page.
4//! Rebuilt from the fragment tree after each paint on the view thread,
5//! then committed to the compositor on the main thread.
6
7use kozan_primitives::arena::Storage;
8
9use super::layer::{Layer, LayerId};
10
11/// Arena of layers indexed by LayerId.
12///
13/// Chrome: `LayerTreeImpl` owns all layers. The compositor reads/mutates
14/// layer properties (transform, opacity, scroll offset) without touching
15/// the view thread.
16pub struct LayerTree {
17    layers: Storage<Layer>,
18    next_id: u32,
19    root: Option<LayerId>,
20}
21
22impl LayerTree {
23    pub fn new() -> Self {
24        Self {
25            layers: Storage::new(),
26            next_id: 0,
27            root: None,
28        }
29    }
30
31    pub fn push(&mut self, layer: Layer) -> LayerId {
32        let id = LayerId(self.next_id);
33        self.layers.set(self.next_id, layer);
34        self.next_id += 1;
35        id
36    }
37
38    pub fn root(&self) -> Option<LayerId> {
39        self.root
40    }
41
42    pub fn set_root(&mut self, id: LayerId) {
43        self.root = Some(id);
44    }
45
46    pub fn layer(&self, id: LayerId) -> &Layer {
47        self.layers
48            .get(id.0)
49            .expect("LayerId points to valid layer")
50    }
51
52    pub fn layer_mut(&mut self, id: LayerId) -> &mut Layer {
53        self.layers
54            .get_mut(id.0)
55            .expect("LayerId points to valid layer")
56    }
57
58    pub fn len(&self) -> u32 {
59        self.next_id
60    }
61
62    pub fn layer_for_dom_node(&self, dom_id: u32) -> Option<LayerId> {
63        self.layers
64            .iter()
65            .find(|(_, l)| l.dom_node == Some(dom_id))
66            .map(|(i, _)| LayerId(i))
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73    use kozan_primitives::geometry::Rect;
74
75    #[test]
76    fn push_and_retrieve() {
77        let mut tree = LayerTree::new();
78        let id = tree.push(Layer::new(Some(1), Rect::new(0.0, 0.0, 800.0, 600.0)));
79        tree.set_root(id);
80
81        assert_eq!(tree.root(), Some(id));
82        assert_eq!(tree.layer(id).dom_node, Some(1));
83        assert_eq!(tree.len(), 1);
84    }
85
86    #[test]
87    fn parent_child() {
88        let mut tree = LayerTree::new();
89        let parent = tree.push(Layer::new(Some(1), Rect::new(0.0, 0.0, 800.0, 600.0)));
90        let child = tree.push(Layer::new(Some(5), Rect::new(10.0, 10.0, 200.0, 300.0)));
91        tree.layer_mut(parent).children.push(child);
92        tree.set_root(parent);
93
94        assert_eq!(tree.layer(parent).children.len(), 1);
95        assert_eq!(tree.layer(parent).children[0], child);
96    }
97
98    #[test]
99    fn find_by_dom_node() {
100        let mut tree = LayerTree::new();
101        tree.push(Layer::new(Some(1), Rect::new(0.0, 0.0, 800.0, 600.0)));
102        let id = tree.push(Layer::new(Some(42), Rect::new(0.0, 0.0, 100.0, 100.0)));
103
104        assert_eq!(tree.layer_for_dom_node(42), Some(id));
105        assert_eq!(tree.layer_for_dom_node(99), None);
106    }
107}