ferroui_base/rendering/composition/
container_visual.rs1use super::hit_testing::{CompositionHitTestAabbTree, ICompositionHitTester};
5use super::{CompositionTarget, CompositionVisual};
6use crate::media::IntersectionResult;
7use std::rc::Rc;
8
9pub type CompositionContainerVisual = CompositionVisual;
11
12pub(crate) const HIT_TEST_AABB_TREE_THRESHOLD: usize = 32;
15
16impl CompositionVisual {
17 pub(crate) fn add_hit_test_child(&self, child: &Rc<CompositionVisual>) {
18 let mut tree = self.hit_test_children.borrow_mut();
19 let Some(tree) = tree.as_mut() else { return };
20
21 if let Some(order) = self.children().index_of(child) {
22 tree.update(child, order as i32);
23 }
24 Self::update_hit_test_child_order(self, tree);
25 }
26
27 pub(crate) fn remove_hit_test_child(&self, child: &Rc<CompositionVisual>) {
28 let mut tree = self.hit_test_children.borrow_mut();
29 let Some(tree) = tree.as_mut() else { return };
30
31 tree.remove(child);
32 Self::update_hit_test_child_order(self, tree);
33 }
34
35 pub(crate) fn clear_hit_test_children(&self) {
36 if let Some(tree) = self.hit_test_children.borrow_mut().as_mut() {
37 tree.clear();
38 }
39 }
40
41 pub(crate) fn try_query_hit_test_children<H: ICompositionHitTester>(
45 &self,
46 input: &H::Input,
47 results: &mut Vec<Rc<CompositionVisual>>,
48 ) -> bool {
49 if self.children().count() < HIT_TEST_AABB_TREE_THRESHOLD {
50 *self.hit_test_children.borrow_mut() = None;
51 return false;
52 }
53
54 let read_revision = self.compositor().readback().read_revision();
55 let mut tree = self.hit_test_children.borrow_mut();
56 let tree = tree.get_or_insert_with(|| CompositionHitTestAabbTree::new(self.children().clone()));
57 tree.query::<H>(input, results, read_revision);
58 true
59 }
60
61 pub(crate) fn try_query_first_hit_test_child<H: ICompositionHitTester>(
65 &self,
66 target: &CompositionTarget,
67 input: &H::Input,
68 filter: Option<&dyn Fn(&Rc<CompositionVisual>) -> bool>,
69 result_filter: Option<&dyn Fn(&Rc<CompositionVisual>) -> bool>,
70 ) -> Option<(Option<Rc<CompositionVisual>>, IntersectionResult)> {
71 if self.children().count() < HIT_TEST_AABB_TREE_THRESHOLD {
72 *self.hit_test_children.borrow_mut() = None;
73 return None;
74 }
75
76 let read_revision = self.compositor().readback().read_revision();
77 let mut tree = self.hit_test_children.borrow_mut();
78 let tree = tree.get_or_insert_with(|| CompositionHitTestAabbTree::new(self.children().clone()));
79 Some(tree.query_first::<H>(target, input, filter, result_filter, read_revision))
80 }
81
82 fn update_hit_test_child_order(&self, tree: &mut CompositionHitTestAabbTree) {
83 for (i, child) in self.children().items().iter().enumerate() {
84 tree.update_order(child, i as i32);
85 }
86 }
87}