Skip to content

Commit 6f2cee8

Browse files
committed
feat: Consumer support for scrolling and clipping children
1 parent 29584d4 commit 6f2cee8

File tree

2 files changed

+74
-5
lines changed

2 files changed

+74
-5
lines changed

consumer/src/filters.rs

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// the LICENSE-APACHE file) or the MIT license (found in
44
// the LICENSE-MIT file), at your option.
55

6-
use accesskit::Role;
6+
use accesskit::{Rect, Role};
77

88
use crate::node::Node;
99

@@ -14,6 +14,29 @@ pub enum FilterResult {
1414
ExcludeSubtree,
1515
}
1616

17+
fn filter_for_sibling_clip_check(node: &Node) -> FilterResult {
18+
if node.is_focused() {
19+
return FilterResult::Include;
20+
}
21+
22+
if node.is_hidden() {
23+
return FilterResult::ExcludeSubtree;
24+
}
25+
26+
FilterResult::Include
27+
}
28+
29+
fn is_first_sibling_in_parent_bbox<'a>(
30+
mut siblings: impl Iterator<Item = Node<'a>>,
31+
parent_bbox: Rect,
32+
) -> bool {
33+
siblings.next().is_some_and(|sibling| {
34+
sibling
35+
.bounding_box()
36+
.is_some_and(|bbox| !bbox.intersect(parent_bbox).is_empty())
37+
})
38+
}
39+
1740
pub fn common_filter(node: &Node) -> FilterResult {
1841
if node.is_focused() {
1942
return FilterResult::Include;
@@ -23,15 +46,33 @@ pub fn common_filter(node: &Node) -> FilterResult {
2346
return FilterResult::ExcludeSubtree;
2447
}
2548

49+
let role = node.role();
50+
if role == Role::GenericContainer || role == Role::TextRun {
51+
return FilterResult::ExcludeNode;
52+
}
53+
2654
if let Some(parent) = node.parent() {
2755
if common_filter(&parent) == FilterResult::ExcludeSubtree {
2856
return FilterResult::ExcludeSubtree;
2957
}
30-
}
3158

32-
let role = node.role();
33-
if role == Role::GenericContainer || role == Role::TextRun {
34-
return FilterResult::ExcludeNode;
59+
if parent.clips_children() {
60+
if let Some(bbox) = node.bounding_box() {
61+
if let Some(parent_bbox) = parent.bounding_box() {
62+
if bbox.intersect(parent_bbox).is_empty()
63+
&& !(is_first_sibling_in_parent_bbox(
64+
node.following_filtered_siblings(&filter_for_sibling_clip_check),
65+
parent_bbox,
66+
) || is_first_sibling_in_parent_bbox(
67+
node.preceding_filtered_siblings(&filter_for_sibling_clip_check),
68+
parent_bbox,
69+
))
70+
{
71+
return FilterResult::ExcludeSubtree;
72+
}
73+
}
74+
}
75+
}
3576
}
3677

3778
FilterResult::Include

consumer/src/node.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,34 @@ impl<'a> Node<'a> {
378378
self.data().numeric_value_jump()
379379
}
380380

381+
pub fn clips_children(&self) -> bool {
382+
self.data().clips_children()
383+
}
384+
385+
pub fn scroll_x(&self) -> Option<f64> {
386+
self.data().scroll_x()
387+
}
388+
389+
pub fn scroll_x_min(&self) -> Option<f64> {
390+
self.data().scroll_x_min()
391+
}
392+
393+
pub fn scroll_x_max(&self) -> Option<f64> {
394+
self.data().scroll_x_max()
395+
}
396+
397+
pub fn scroll_y(&self) -> Option<f64> {
398+
self.data().scroll_y()
399+
}
400+
401+
pub fn scroll_y_min(&self) -> Option<f64> {
402+
self.data().scroll_y_min()
403+
}
404+
405+
pub fn scroll_y_max(&self) -> Option<f64> {
406+
self.data().scroll_y_max()
407+
}
408+
381409
pub fn is_text_input(&self) -> bool {
382410
matches!(
383411
self.role(),

0 commit comments

Comments
 (0)