1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
//! Input hit testing: extension methods of [`InputElement`].
use super::InputElement;
use crate::media::{Geometry, GeometryHitTestResult};
use crate::{Point, Ref, Visual};
fn is_hit_test_visible(visual: &Visual) -> bool {
visual.is_visible()
&& visual.is_attached_to_visual_tree()
&& visual.downcast_ref::<InputElement>().is_some_and(InputElement::is_hit_test_visible)
}
fn is_hit_test_visible_enabled_only(visual: &Visual) -> bool {
is_hit_test_visible(visual)
&& visual.downcast_ref::<InputElement>().is_some_and(InputElement::is_effectively_enabled)
}
fn hit_test_filter(enabled_elements_only: bool) -> fn(&Visual) -> bool {
if enabled_elements_only {
is_hit_test_visible_enabled_only
} else {
is_hit_test_visible
}
}
impl InputElement {
/// Returns the active input elements at a point on the element, in the
/// element's coordinates, topmost first. Only enabled elements are
/// considered.
pub fn get_input_elements_at(&self, p: Point) -> Vec<Ref<InputElement>> {
self.get_input_elements_at_with(p, true)
}
/// Returns the active input elements at a point on the element, in the
/// element's coordinates, topmost first.
///
/// `enabled_elements_only` tells whether only enabled elements should
/// be considered.
pub fn get_input_elements_at_with(&self, p: Point, enabled_elements_only: bool) -> Vec<Ref<InputElement>> {
self.get_visuals_at_filtered(p, &hit_test_filter(enabled_elements_only))
.into_iter()
.filter_map(|visual| visual.downcast::<InputElement>().ok())
.collect()
}
/// Returns the active input elements intersecting a geometry on the
/// element, in the element's coordinates, topmost first, with the
/// details of the intersections.
///
/// `enabled_elements_only` tells whether only enabled elements should
/// be considered.
pub fn get_input_elements_at_geometry(
&self,
geometry: &Geometry,
enabled_elements_only: bool,
) -> Vec<GeometryHitTestResult> {
self.get_visuals_at_geometry_filtered(geometry, &hit_test_filter(enabled_elements_only))
.into_iter()
.filter(|x| x.visual_hit.is::<InputElement>())
.collect()
}
/// Returns the topmost active input element at a point on the element,
/// in the element's coordinates. Only enabled elements are considered.
pub fn input_hit_test(&self, p: Point) -> Option<Ref<InputElement>> {
self.input_hit_test_with(p, true)
}
/// Returns the topmost active input element at a point on the element,
/// in the element's coordinates.
///
/// `enabled_elements_only` tells whether only enabled elements should
/// be considered.
pub fn input_hit_test_with(&self, p: Point, enabled_elements_only: bool) -> Option<Ref<InputElement>> {
self.get_visual_at_filtered(p, &hit_test_filter(enabled_elements_only))
.and_then(|visual| visual.downcast::<InputElement>().ok())
}
/// Returns the topmost active input element intersecting a geometry on
/// the element, in the element's coordinates, with the details of the
/// intersection.
///
/// `enabled_elements_only` tells whether only enabled elements should
/// be considered.
pub fn input_hit_test_geometry(
&self,
geometry: &Geometry,
enabled_elements_only: bool,
) -> Option<GeometryHitTestResult> {
self.get_visual_at_geometry_filtered(geometry, &hit_test_filter(enabled_elements_only))
.filter(|hit_test| hit_test.visual_hit.is::<InputElement>())
}
/// Returns the topmost active input element at a point on the element
/// that also passes a filter, in the element's coordinates.
///
/// If `filter` returns false for a visual then the visual and all its
/// descendants are excluded from the results. `enabled_elements_only`
/// tells whether only enabled elements should be considered.
pub fn input_hit_test_filtered(
&self,
p: Point,
filter: &dyn Fn(&Visual) -> bool,
enabled_elements_only: bool,
) -> Option<Ref<InputElement>> {
let hit_test_delegate = hit_test_filter(enabled_elements_only);
self.get_visual_at_filtered(p, &|x: &Visual| hit_test_delegate(x) && filter(x))
.and_then(|visual| visual.downcast::<InputElement>().ok())
}
/// Returns the topmost active input element intersecting a geometry on
/// the element that also passes a filter, in the element's coordinates.
///
/// If `filter` returns false for a visual then the visual and all its
/// descendants are excluded from the results. `enabled_elements_only`
/// tells whether only enabled elements should be considered.
pub fn input_hit_test_geometry_filtered(
&self,
geometry: &Geometry,
filter: &dyn Fn(&Visual) -> bool,
enabled_elements_only: bool,
) -> Option<Ref<InputElement>> {
let hit_test_delegate = hit_test_filter(enabled_elements_only);
self.get_visual_at_geometry_filtered(geometry, &|x: &Visual| hit_test_delegate(x) && filter(x))
.and_then(|hit_test| hit_test.visual_hit.downcast::<InputElement>().ok())
}
}