Skip to content

Commit 4b8239f

Browse files
committed
fix: Populate range info on Android
1 parent 6759028 commit 4b8239f

4 files changed

Lines changed: 128 additions & 4 deletions

File tree

platforms/android/src/adapter.rs

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,20 @@ fn enqueue_focus_event_if_applicable(
5252
struct AdapterChangeHandler<'a> {
5353
events: &'a mut Vec<QueuedEvent>,
5454
node_id_map: &'a mut NodeIdMap,
55+
accessibility_focus: Option<jint>,
5556
enqueued_window_content_changed: bool,
5657
}
5758

5859
impl<'a> AdapterChangeHandler<'a> {
59-
fn new(events: &'a mut Vec<QueuedEvent>, node_id_map: &'a mut NodeIdMap) -> Self {
60+
fn new(
61+
events: &'a mut Vec<QueuedEvent>,
62+
node_id_map: &'a mut NodeIdMap,
63+
accessibility_focus: Option<jint>,
64+
) -> Self {
6065
Self {
6166
events,
6267
node_id_map,
68+
accessibility_focus,
6369
enqueued_window_content_changed: false,
6470
}
6571
}
@@ -142,6 +148,28 @@ impl TreeChangeHandler for AdapterChangeHandler<'_> {
142148
y: scroll_y,
143149
});
144150
}
151+
if old_node.numeric_value() != new_node.numeric_value() && new_node.data().value().is_none()
152+
{
153+
if let (Some(current), Some(min), Some(max)) = (
154+
new_node.numeric_value(),
155+
new_node.min_numeric_value(),
156+
new_node.max_numeric_value(),
157+
) {
158+
let id = self.node_id_map.get_or_create_java_id(new_node);
159+
let event_type = if self.accessibility_focus == Some(id) {
160+
EVENT_VIEW_SELECTED
161+
} else {
162+
EVENT_VIEW_SCROLLED
163+
};
164+
self.events.push(QueuedEvent::RangeValueChanged {
165+
virtual_view_id: id,
166+
event_type,
167+
current,
168+
min,
169+
max,
170+
});
171+
}
172+
}
145173
// TODO: other events
146174
}
147175

@@ -205,10 +233,11 @@ impl State {
205233
fn update_tree(
206234
events: &mut Vec<QueuedEvent>,
207235
node_id_map: &mut NodeIdMap,
236+
accessibility_focus: Option<jint>,
208237
tree: &mut Tree,
209238
update: TreeUpdate,
210239
) {
211-
let mut handler = AdapterChangeHandler::new(events, node_id_map);
240+
let mut handler = AdapterChangeHandler::new(events, node_id_map, accessibility_focus);
212241
tree.update_and_process_changes(update, &mut handler);
213242
}
214243

@@ -261,7 +290,13 @@ impl Adapter {
261290
}
262291
State::Active(tree) => {
263292
let mut events = Vec::new();
264-
update_tree(&mut events, &mut self.node_id_map, tree, update_factory());
293+
update_tree(
294+
&mut events,
295+
&mut self.node_id_map,
296+
self.accessibility_focus,
297+
tree,
298+
update_factory(),
299+
);
265300
Some(QueuedEvents(events))
266301
}
267302
}
@@ -518,7 +553,13 @@ impl Adapter {
518553
tree_id,
519554
focus: focus_id,
520555
};
521-
update_tree(events, &mut self.node_id_map, tree, update);
556+
update_tree(
557+
events,
558+
&mut self.node_id_map,
559+
self.accessibility_focus,
560+
tree,
561+
update,
562+
);
522563
let request = ActionRequest {
523564
action: Action::SetTextSelection,
524565
target_tree: tree_id,

platforms/android/src/event.rs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,28 @@ pub(crate) struct ScrollDimension {
233233
pub(crate) max: Option<jint>,
234234
}
235235

236+
fn send_range_value_changed(
237+
env: &mut JNIEnv,
238+
host: &JObject,
239+
virtual_view_id: jint,
240+
event_type: jint,
241+
current: f64,
242+
min: f64,
243+
max: f64,
244+
) {
245+
let event = new_event(env, host, virtual_view_id, event_type);
246+
let item_index = if max > min && current >= min && current <= max {
247+
((current - min) * 100.0 / (max - min)) as jint
248+
} else {
249+
0
250+
};
251+
env.call_method(&event, "setItemCount", "(I)V", &[100i32.into()])
252+
.unwrap();
253+
env.call_method(&event, "setCurrentItemIndex", "(I)V", &[item_index.into()])
254+
.unwrap();
255+
send_completed_event(env, host, event);
256+
}
257+
236258
fn send_scrolled(
237259
env: &mut JNIEnv,
238260
host: &JObject,
@@ -297,6 +319,13 @@ pub(crate) enum QueuedEvent {
297319
x: Option<ScrollDimension>,
298320
y: Option<ScrollDimension>,
299321
},
322+
RangeValueChanged {
323+
virtual_view_id: jint,
324+
event_type: jint,
325+
current: f64,
326+
min: f64,
327+
max: f64,
328+
},
300329
InvalidateHost,
301330
}
302331

@@ -365,6 +394,23 @@ impl QueuedEvents {
365394
} => {
366395
send_scrolled(env, host, virtual_view_id, x, y);
367396
}
397+
QueuedEvent::RangeValueChanged {
398+
virtual_view_id,
399+
event_type,
400+
current,
401+
min,
402+
max,
403+
} => {
404+
send_range_value_changed(
405+
env,
406+
host,
407+
virtual_view_id,
408+
event_type,
409+
current,
410+
min,
411+
max,
412+
);
413+
}
368414
QueuedEvent::InvalidateHost => {
369415
env.call_method(host, "invalidate", "()V", &[]).unwrap();
370416
}

platforms/android/src/node.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,40 @@ impl NodeWrapper<'_> {
389389
add_action(env, node_info, ACTION_SCROLL_FORWARD);
390390
}
391391

392+
if self.0.data().value().is_none() {
393+
if let (Some(current), Some(min), Some(max)) = (
394+
self.0.numeric_value(),
395+
self.0.min_numeric_value(),
396+
self.0.max_numeric_value(),
397+
) {
398+
let range_info_class = env
399+
.find_class("android/view/accessibility/AccessibilityNodeInfo$RangeInfo")
400+
.unwrap();
401+
let range_info = env
402+
.call_static_method(
403+
&range_info_class,
404+
"obtain",
405+
"(IFFF)Landroid/view/accessibility/AccessibilityNodeInfo$RangeInfo;",
406+
&[
407+
RANGE_TYPE_FLOAT.into(),
408+
(min as f32).into(),
409+
(max as f32).into(),
410+
(current as f32).into(),
411+
],
412+
)
413+
.unwrap()
414+
.l()
415+
.unwrap();
416+
env.call_method(
417+
node_info,
418+
"setRangeInfo",
419+
"(Landroid/view/accessibility/AccessibilityNodeInfo$RangeInfo;)V",
420+
&[(&range_info).into()],
421+
)
422+
.unwrap();
423+
}
424+
}
425+
392426
let live = match self.0.live() {
393427
Live::Off => LIVE_REGION_NONE,
394428
Live::Polite => LIVE_REGION_POLITE,

platforms/android/src/util.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub(crate) const ACTION_ARGUMENT_SELECTION_END_INT: &str = "ACTION_ARGUMENT_SELE
2727
pub(crate) const CONTENT_CHANGE_TYPE_SUBTREE: jint = 1 << 0;
2828

2929
pub(crate) const EVENT_VIEW_CLICKED: jint = 1;
30+
pub(crate) const EVENT_VIEW_SELECTED: jint = 1 << 2;
3031
pub(crate) const EVENT_VIEW_FOCUSED: jint = 1 << 3;
3132
pub(crate) const EVENT_VIEW_TEXT_CHANGED: jint = 1 << 4;
3233
pub(crate) const EVENT_VIEW_HOVER_ENTER: jint = 1 << 7;
@@ -56,6 +57,8 @@ pub(crate) const MOVEMENT_GRANULARITY_WORD: jint = 1 << 1;
5657
pub(crate) const MOVEMENT_GRANULARITY_LINE: jint = 1 << 2;
5758
pub(crate) const MOVEMENT_GRANULARITY_PARAGRAPH: jint = 1 << 3;
5859

60+
pub(crate) const RANGE_TYPE_FLOAT: jint = 1;
61+
5962
#[derive(Debug, Default)]
6063
pub(crate) struct NodeIdMap {
6164
java_to_accesskit: HashMap<jint, NodeId>,

0 commit comments

Comments
 (0)