orinium_browser/engine/input/
mod.rs1use super::layouter::types::{InfoNode, NodeKind};
4use ui_layout::LayoutNode;
5
6pub struct HitItem<'a> {
8 pub layout: &'a LayoutNode,
9 pub info: &'a InfoNode,
10}
11
12pub type HitPath<'a> = Vec<HitItem<'a>>;
14
15pub fn hit_test<'a>(layout: &'a LayoutNode, info: &'a InfoNode, x: f32, y: f32) -> HitPath<'a> {
17 if layout.layout_boxes.is_empty() {
19 return Vec::new();
20 }
21
22 for box_model in layout
23 .layout_boxes
24 .iter()
25 .collect::<Vec<_>>()
26 .into_iter()
27 .rev()
28 {
29 let rect = box_model.padding_box;
31
32 if x < rect.x || y < rect.y || x > rect.x + rect.width || y > rect.y + rect.height {
34 continue;
35 }
36
37 let mut local_x = x - box_model.content_box.x;
39 let mut local_y = y - box_model.content_box.y;
40
41 if let NodeKind::Container {
42 scroll_offset_x,
43 scroll_offset_y,
44 ..
45 } = &info.kind
46 {
47 local_x += *scroll_offset_x;
48 local_y += *scroll_offset_y;
49 }
50
51 for (child_layout, child_info) in layout.children.iter().zip(&info.children).rev() {
53 let mut path = hit_test(child_layout, child_info, local_x, local_y);
54 if !path.is_empty() {
55 path.push(HitItem { layout, info });
57 return path;
58 }
59 }
60
61 return vec![HitItem { layout, info }];
63 }
64
65 Vec::new()
67}