1use geometry_core::Rect;
2use platform_core::Event;
3use ui_tree::EventResult;
4
5pub(crate) fn pointer_coords(event: &Event) -> Option<(f64, f64)> {
6 match event {
7 Event::PointerMoved { x, y, .. } => Some((*x, *y)),
8 Event::PointerPressed { x, y, .. } => Some((*x, *y)),
9 Event::PointerReleased { x, y, .. } => Some((*x, *y)),
10 _ => None,
11 }
12}
13
14pub fn transform_pointer(event: &Event, matrix: [f32; 6]) -> Option<Event> {
21 let inv = geometry_core::Transform::from_array(matrix).invert()?;
22 let apply = |world_x: f64, world_y: f64| -> (f64, f64) {
24 let local_x = inv.a as f64 * world_x + inv.c as f64 * world_y + inv.e as f64;
25 let local_y = inv.b as f64 * world_x + inv.d as f64 * world_y + inv.f as f64;
26 (local_x, local_y)
27 };
28 match event {
29 Event::PointerMoved { x, y, source } => {
30 let (local_x, local_y) = apply(*x, *y);
31 Some(Event::PointerMoved {
32 x: local_x,
33 y: local_y,
34 source: source.clone(),
35 })
36 }
37 Event::PointerPressed {
38 x,
39 y,
40 button,
41 source,
42 } => {
43 let (local_x, local_y) = apply(*x, *y);
44 Some(Event::PointerPressed {
45 x: local_x,
46 y: local_y,
47 button: button.clone(),
48 source: source.clone(),
49 })
50 }
51 Event::PointerReleased {
52 x,
53 y,
54 button,
55 source,
56 } => {
57 let (local_x, local_y) = apply(*x, *y);
58 Some(Event::PointerReleased {
59 x: local_x,
60 y: local_y,
61 button: button.clone(),
62 source: source.clone(),
63 })
64 }
65 _ => None,
66 }
67}
68
69pub(crate) fn offset_pointer(event: &Event, dx: f64, dy: f64) -> Option<Event> {
70 transform_pointer(event, [1.0, 0.0, 0.0, 1.0, dx as f32, dy as f32])
71}
72
73pub(crate) fn clip_pointer_event<'a>(event: &'a Event, rect: Rect) -> Option<&'a Event> {
75 match pointer_coords(event) {
76 Some((x, y)) if !rect.contains(x as f32, y as f32) => None,
77 _ => Some(event),
78 }
79}
80
81pub(crate) fn dispatch_to_children_filtered<T, P, D>(
83 children: &mut [T],
84 mut should_dispatch: P,
85 mut get_result: D,
86) -> EventResult
87where
88 P: FnMut(&T) -> bool,
89 D: FnMut(&mut T) -> EventResult,
90{
91 for entry in children.iter_mut() {
92 if !should_dispatch(entry) {
93 continue;
94 }
95 if get_result(entry) == EventResult::Handled {
96 return EventResult::Handled;
97 }
98 }
99 EventResult::Ignored
100}
101
102pub(crate) fn dispatch_container_event(
103 children: &mut crate::layout_item::TrackedChildren,
104 event: &Event,
105) -> EventResult {
106 if matches!(
112 event,
113 Event::PointerMoved { .. } | Event::PointerReleased { .. }
114 ) {
115 let mut any_handled = false;
116 for child in children.iter() {
117 if child.item.borrow_mut().on_event(event) == EventResult::Handled {
118 any_handled = true;
119 }
120 }
121 return if any_handled {
122 EventResult::Handled
123 } else {
124 EventResult::Ignored
125 };
126 }
127 let pointer_pos = pointer_coords(event).map(|(x, y)| (x as f32, y as f32));
128 dispatch_to_children_filtered(
129 children,
130 |child| match pointer_pos {
131 Some((pointer_x, pointer_y)) => child
132 .rect
133 .as_ref()
134 .map_or(true, |sig| sig.get().contains(pointer_x, pointer_y)),
135 None => true,
136 },
137 |child| child.item.borrow_mut().on_event(event),
138 )
139}