1use crate::{
12 context::{ActionHandlerNoMut, ActionHandlerWrapper, AppContext, Context},
13 filters::filter,
14 node::{NodeIdOrRoot, NodeWrapper, PlatformNode, PlatformRoot},
15 util::WindowBounds,
16 AdapterCallback, Event, ObjectEvent, WindowEvent,
17};
18use accesskit::{ActionHandler, NodeId, Role, TreeUpdate};
19use accesskit_consumer::{FilterResult, Node, Tree, TreeChangeHandler, TreeState};
20use atspi_common::{InterfaceSet, Politeness, State};
21use std::fmt::{Debug, Formatter};
22use std::{
23 collections::HashSet,
24 sync::{
25 atomic::{AtomicUsize, Ordering},
26 Arc, RwLock,
27 },
28};
29
30struct AdapterChangeHandler<'a> {
31 adapter: &'a Adapter,
32 added_nodes: HashSet<NodeId>,
33 removed_nodes: HashSet<NodeId>,
34 checked_text_change: HashSet<NodeId>,
35 selection_changed: HashSet<NodeId>,
36}
37
38impl<'a> AdapterChangeHandler<'a> {
39 fn new(adapter: &'a Adapter) -> Self {
40 Self {
41 adapter,
42 added_nodes: HashSet::new(),
43 removed_nodes: HashSet::new(),
44 checked_text_change: HashSet::new(),
45 selection_changed: HashSet::new(),
46 }
47 }
48
49 fn add_node(&mut self, node: &Node) {
50 let id = node.id();
51 if self.added_nodes.contains(&id) {
52 return;
53 }
54 self.added_nodes.insert(id);
55
56 let role = node.role();
57 let is_root = node.is_root();
58 let wrapper = NodeWrapper(node);
59 let interfaces = wrapper.interfaces();
60 self.adapter.register_interfaces(node.id(), interfaces);
61 if is_root && role == Role::Window {
62 let adapter_index = self
63 .adapter
64 .context
65 .read_app_context()
66 .adapter_index(self.adapter.id)
67 .unwrap();
68 self.adapter.window_created(adapter_index, node.id());
69 }
70
71 let live = wrapper.live();
72 if live != Politeness::None {
73 if let Some(name) = wrapper.name() {
74 self.adapter
75 .emit_object_event(node.id(), ObjectEvent::Announcement(name, live));
76 }
77 }
78 if let Some(true) = node.is_selected() {
79 self.enqueue_selection_changed_if_needed(node);
80 }
81 }
82
83 fn add_subtree(&mut self, node: &Node) {
84 self.add_node(node);
85 for child in node.filtered_children(&filter) {
86 self.add_subtree(&child);
87 }
88 }
89
90 fn remove_node(&mut self, node: &Node) {
91 let id = node.id();
92 if self.removed_nodes.contains(&id) {
93 return;
94 }
95 self.removed_nodes.insert(id);
96
97 let role = node.role();
98 let is_root = node.is_root();
99 let wrapper = NodeWrapper(node);
100 if is_root && role == Role::Window {
101 self.adapter.window_destroyed(node.id());
102 }
103 self.adapter
104 .emit_object_event(node.id(), ObjectEvent::StateChanged(State::Defunct, true));
105 self.adapter
106 .unregister_interfaces(node.id(), wrapper.interfaces());
107 if let Some(true) = node.is_selected() {
108 self.enqueue_selection_changed_if_needed(node);
109 }
110 }
111
112 fn remove_subtree(&mut self, node: &Node) {
113 for child in node.filtered_children(&filter) {
114 self.remove_subtree(&child);
115 }
116 self.remove_node(node);
117 }
118
119 fn emit_text_change_if_needed_parent(&mut self, old_node: &Node, new_node: &Node) {
120 if !new_node.supports_text_ranges() || !old_node.supports_text_ranges() {
121 return;
122 }
123 let id = new_node.id();
124 if self.checked_text_change.contains(&id) {
125 return;
126 }
127 self.checked_text_change.insert(id);
128 let old_text = old_node.document_range().text();
129 let new_text = new_node.document_range().text();
130
131 let mut old_chars = old_text.chars();
132 let mut new_chars = new_text.chars();
133 let mut prefix_usv_count = 0;
134 let mut prefix_byte_count = 0;
135 loop {
136 match (old_chars.next(), new_chars.next()) {
137 (Some(old_char), Some(new_char)) if old_char == new_char => {
138 prefix_usv_count += 1;
139 prefix_byte_count += new_char.len_utf8();
140 }
141 (None, None) => return,
142 _ => break,
143 }
144 }
145
146 let suffix_byte_count = old_text[prefix_byte_count..]
147 .chars()
148 .rev()
149 .zip(new_text[prefix_byte_count..].chars().rev())
150 .take_while(|(old_char, new_char)| old_char == new_char)
151 .fold(0, |count, (c, _)| count + c.len_utf8());
152
153 let old_content = &old_text[prefix_byte_count..old_text.len() - suffix_byte_count];
154 if let Ok(length) = old_content.chars().count().try_into() {
155 if length > 0 {
156 self.adapter.emit_object_event(
157 id,
158 ObjectEvent::TextRemoved {
159 start_index: prefix_usv_count,
160 length,
161 content: old_content.to_string(),
162 },
163 );
164 }
165 }
166
167 let new_content = &new_text[prefix_byte_count..new_text.len() - suffix_byte_count];
168 if let Ok(length) = new_content.chars().count().try_into() {
169 if length > 0 {
170 self.adapter.emit_object_event(
171 id,
172 ObjectEvent::TextInserted {
173 start_index: prefix_usv_count,
174 length,
175 content: new_content.to_string(),
176 },
177 );
178 }
179 }
180 }
181
182 fn emit_text_change_if_needed(&mut self, old_node: &Node, new_node: &Node) {
183 if let Role::TextRun | Role::GenericContainer = new_node.role() {
184 if let (Some(old_parent), Some(new_parent)) = (
185 old_node.filtered_parent(&filter),
186 new_node.filtered_parent(&filter),
187 ) {
188 self.emit_text_change_if_needed_parent(&old_parent, &new_parent);
189 }
190 } else {
191 self.emit_text_change_if_needed_parent(old_node, new_node);
192 }
193 }
194
195 fn emit_text_selection_change(&self, old_node: Option<&Node>, new_node: &Node) {
196 if !new_node.supports_text_ranges() {
197 return;
198 }
199 let Some(old_node) = old_node else {
200 if let Some(selection) = new_node.text_selection() {
201 if !selection.is_degenerate() {
202 self.adapter
203 .emit_object_event(new_node.id(), ObjectEvent::TextSelectionChanged);
204 }
205 }
206 if let Some(selection_focus) = new_node.text_selection_focus() {
207 if let Ok(offset) = selection_focus.to_global_usv_index().try_into() {
208 self.adapter
209 .emit_object_event(new_node.id(), ObjectEvent::CaretMoved(offset));
210 }
211 }
212 return;
213 };
214 if !old_node.is_focused() || new_node.raw_text_selection() == old_node.raw_text_selection()
215 {
216 return;
217 }
218
219 if let Some(selection) = new_node.text_selection() {
220 if !selection.is_degenerate()
221 || old_node
222 .text_selection()
223 .map(|selection| !selection.is_degenerate())
224 .unwrap_or(false)
225 {
226 self.adapter
227 .emit_object_event(new_node.id(), ObjectEvent::TextSelectionChanged);
228 }
229 }
230
231 let old_caret_position = old_node
232 .raw_text_selection()
233 .map(|selection| selection.focus);
234 let new_caret_position = new_node
235 .raw_text_selection()
236 .map(|selection| selection.focus);
237 if old_caret_position != new_caret_position {
238 if let Some(selection_focus) = new_node.text_selection_focus() {
239 if let Ok(offset) = selection_focus.to_global_usv_index().try_into() {
240 self.adapter
241 .emit_object_event(new_node.id(), ObjectEvent::CaretMoved(offset));
242 }
243 }
244 }
245 }
246
247 fn enqueue_selection_changed_if_needed_parent(&mut self, node: Node) {
248 if !node.is_container_with_selectable_children() {
249 return;
250 }
251 let id = node.id();
252 if self.selection_changed.contains(&id) {
253 return;
254 }
255 self.selection_changed.insert(id);
256 }
257
258 fn enqueue_selection_changed_if_needed(&mut self, node: &Node) {
259 if !node.is_item_like() {
260 return;
261 }
262 if let Some(node) = node.selection_container(&filter) {
263 self.enqueue_selection_changed_if_needed_parent(node);
264 }
265 }
266
267 fn emit_selection_changed(&mut self) {
268 for id in self.selection_changed.iter() {
269 if self.removed_nodes.contains(id) {
270 continue;
271 }
272 self.adapter
273 .emit_object_event(*id, ObjectEvent::SelectionChanged);
274 }
275 }
276}
277
278impl TreeChangeHandler for AdapterChangeHandler<'_> {
279 fn node_added(&mut self, node: &Node) {
280 if filter(node) == FilterResult::Include {
281 self.add_node(node);
282 }
283 }
284
285 fn node_updated(&mut self, old_node: &Node, new_node: &Node) {
286 self.emit_text_change_if_needed(old_node, new_node);
287 let filter_old = filter(old_node);
288 let filter_new = filter(new_node);
289 if filter_new != filter_old {
290 if filter_new == FilterResult::Include {
291 if filter_old == FilterResult::ExcludeSubtree {
292 self.add_subtree(new_node);
293 } else {
294 self.add_node(new_node);
295 }
296 } else if filter_old == FilterResult::Include {
297 if filter_new == FilterResult::ExcludeSubtree {
298 self.remove_subtree(old_node);
299 } else {
300 self.remove_node(old_node);
301 }
302 }
303 } else if filter_new == FilterResult::Include {
304 let old_wrapper = NodeWrapper(old_node);
305 let new_wrapper = NodeWrapper(new_node);
306 let old_interfaces = old_wrapper.interfaces();
307 let new_interfaces = new_wrapper.interfaces();
308 let kept_interfaces = old_interfaces & new_interfaces;
309 self.adapter
310 .unregister_interfaces(new_wrapper.id(), old_interfaces ^ kept_interfaces);
311 self.adapter
312 .register_interfaces(new_node.id(), new_interfaces ^ kept_interfaces);
313 let bounds = *self.adapter.context.read_root_window_bounds();
314 new_wrapper.notify_changes(&bounds, self.adapter, &old_wrapper);
315 self.emit_text_selection_change(Some(old_node), new_node);
316 if new_node.is_selected() != old_node.is_selected() {
317 self.enqueue_selection_changed_if_needed(new_node);
318 }
319 }
320 }
321
322 fn focus_moved(&mut self, old_node: Option<&Node>, new_node: Option<&Node>) {
323 if let (None, Some(new_node)) = (old_node, new_node) {
324 if let Some(root_window) = root_window(new_node.tree_state) {
325 self.adapter.window_activated(&NodeWrapper(&root_window));
326 }
327 } else if let (Some(old_node), None) = (old_node, new_node) {
328 if let Some(root_window) = root_window(old_node.tree_state) {
329 self.adapter.window_deactivated(&NodeWrapper(&root_window));
330 }
331 }
332 if let Some(node) = new_node {
333 self.adapter
334 .emit_object_event(node.id(), ObjectEvent::StateChanged(State::Focused, true));
335 self.emit_text_selection_change(None, node);
336 }
337 if let Some(node) = old_node {
338 self.adapter
339 .emit_object_event(node.id(), ObjectEvent::StateChanged(State::Focused, false));
340 }
341 }
342
343 fn node_removed(&mut self, node: &Node) {
344 if filter(node) == FilterResult::Include {
345 self.remove_node(node);
346 }
347 }
348}
349
350static NEXT_ADAPTER_ID: AtomicUsize = AtomicUsize::new(0);
351
352pub fn next_adapter_id() -> usize {
355 NEXT_ADAPTER_ID.fetch_add(1, Ordering::Relaxed)
356}
357
358pub struct Adapter {
359 id: usize,
360 callback: Box<dyn AdapterCallback + Send + Sync>,
361 context: Arc<Context>,
362}
363
364impl Debug for Adapter {
365 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
366 f.debug_struct("Adapter")
367 .field("id", &self.id)
368 .field("callback", &"AdapterCallback")
369 .field("context", &self.context)
370 .finish()
371 }
372}
373
374impl Adapter {
375 pub fn new(
376 app_context: &Arc<RwLock<AppContext>>,
377 callback: impl 'static + AdapterCallback + Send + Sync,
378 initial_state: TreeUpdate,
379 is_window_focused: bool,
380 root_window_bounds: WindowBounds,
381 action_handler: impl 'static + ActionHandler + Send,
382 ) -> Self {
383 let id = next_adapter_id();
384 Self::with_id(
385 id,
386 app_context,
387 callback,
388 initial_state,
389 is_window_focused,
390 root_window_bounds,
391 action_handler,
392 )
393 }
394
395 pub fn with_id(
396 id: usize,
397 app_context: &Arc<RwLock<AppContext>>,
398 callback: impl 'static + AdapterCallback + Send + Sync,
399 initial_state: TreeUpdate,
400 is_window_focused: bool,
401 root_window_bounds: WindowBounds,
402 action_handler: impl 'static + ActionHandler + Send,
403 ) -> Self {
404 Self::with_wrapped_action_handler(
405 id,
406 app_context,
407 callback,
408 initial_state,
409 is_window_focused,
410 root_window_bounds,
411 Arc::new(ActionHandlerWrapper::new(action_handler)),
412 )
413 }
414
415 pub fn with_wrapped_action_handler(
418 id: usize,
419 app_context: &Arc<RwLock<AppContext>>,
420 callback: impl 'static + AdapterCallback + Send + Sync,
421 initial_state: TreeUpdate,
422 is_window_focused: bool,
423 root_window_bounds: WindowBounds,
424 action_handler: Arc<dyn ActionHandlerNoMut + Send + Sync>,
425 ) -> Self {
426 let tree = Tree::new(initial_state, is_window_focused);
427 let focus_id = tree.state().focus_id();
428 let context = Context::new(app_context, tree, action_handler, root_window_bounds);
429 context.write_app_context().push_adapter(id, &context);
430 let adapter = Self {
431 id,
432 callback: Box::new(callback),
433 context,
434 };
435 adapter.register_tree();
436 if let Some(id) = focus_id {
437 adapter.emit_object_event(id, ObjectEvent::StateChanged(State::Focused, true));
438 }
439 adapter
440 }
441
442 fn register_tree(&self) {
443 fn add_children(node: Node<'_>, to_add: &mut Vec<(NodeId, InterfaceSet)>) {
444 for child in node.filtered_children(&filter) {
445 let child_id = child.id();
446 let wrapper = NodeWrapper(&child);
447 let interfaces = wrapper.interfaces();
448 to_add.push((child_id, interfaces));
449 add_children(child, to_add);
450 }
451 }
452
453 let mut objects_to_add = Vec::new();
454
455 let (adapter_index, root_id) = {
456 let tree = self.context.read_tree();
457 let tree_state = tree.state();
458 let mut app_context = self.context.write_app_context();
459 app_context.toolkit_name = tree_state.toolkit_name().map(|s| s.to_string());
460 app_context.toolkit_version = tree_state.toolkit_version().map(|s| s.to_string());
461 let adapter_index = app_context.adapter_index(self.id).unwrap();
462 let root = tree_state.root();
463 let root_id = root.id();
464 let wrapper = NodeWrapper(&root);
465 objects_to_add.push((root_id, wrapper.interfaces()));
466 add_children(root, &mut objects_to_add);
467 (adapter_index, root_id)
468 };
469
470 for (id, interfaces) in objects_to_add {
471 self.register_interfaces(id, interfaces);
472 if id == root_id {
473 self.window_created(adapter_index, id);
474 }
475 }
476 }
477
478 pub fn platform_node(&self, id: NodeId) -> PlatformNode {
479 PlatformNode::new(&self.context, self.id, id)
480 }
481
482 pub fn root_id(&self) -> NodeId {
483 self.context.read_tree().state().root_id()
484 }
485
486 pub fn platform_root(&self) -> PlatformRoot {
487 PlatformRoot::new(&self.context.app_context)
488 }
489
490 fn register_interfaces(&self, id: NodeId, new_interfaces: InterfaceSet) {
491 self.callback.register_interfaces(self, id, new_interfaces);
492 }
493
494 fn unregister_interfaces(&self, id: NodeId, old_interfaces: InterfaceSet) {
495 self.callback
496 .unregister_interfaces(self, id, old_interfaces);
497 }
498
499 pub(crate) fn emit_object_event(&self, target: NodeId, event: ObjectEvent) {
500 let target = NodeIdOrRoot::Node(target);
501 self.callback
502 .emit_event(self, Event::Object { target, event });
503 }
504
505 fn emit_root_object_event(&self, event: ObjectEvent) {
506 let target = NodeIdOrRoot::Root;
507 self.callback
508 .emit_event(self, Event::Object { target, event });
509 }
510
511 pub fn set_root_window_bounds(&mut self, new_bounds: WindowBounds) {
512 let mut bounds = self.context.root_window_bounds.write().unwrap();
513 *bounds = new_bounds;
514 }
515
516 pub fn update(&mut self, update: TreeUpdate) {
517 let mut handler = AdapterChangeHandler::new(self);
518 let mut tree = self.context.tree.write().unwrap();
519 tree.update_and_process_changes(update, &mut handler);
520 drop(tree);
521 handler.emit_selection_changed();
522 }
523
524 pub fn update_window_focus_state(&mut self, is_focused: bool) {
525 let mut handler = AdapterChangeHandler::new(self);
526 let mut tree = self.context.tree.write().unwrap();
527 tree.update_host_focus_state_and_process_changes(is_focused, &mut handler);
528 }
529
530 fn window_created(&self, adapter_index: usize, window: NodeId) {
531 self.emit_root_object_event(ObjectEvent::ChildAdded(adapter_index, window));
532 }
533
534 fn window_activated(&self, window: &NodeWrapper<'_>) {
535 self.callback.emit_event(
536 self,
537 Event::Window {
538 target: window.id(),
539 name: window.name().unwrap_or_default(),
540 event: WindowEvent::Activated,
541 },
542 );
543 self.emit_object_event(window.id(), ObjectEvent::StateChanged(State::Active, true));
544 self.emit_root_object_event(ObjectEvent::ActiveDescendantChanged(window.id()));
545 }
546
547 fn window_deactivated(&self, window: &NodeWrapper<'_>) {
548 self.callback.emit_event(
549 self,
550 Event::Window {
551 target: window.id(),
552 name: window.name().unwrap_or_default(),
553 event: WindowEvent::Deactivated,
554 },
555 );
556 self.emit_object_event(window.id(), ObjectEvent::StateChanged(State::Active, false));
557 }
558
559 fn window_destroyed(&self, window: NodeId) {
560 self.emit_root_object_event(ObjectEvent::ChildRemoved(window));
561 }
562
563 pub fn id(&self) -> usize {
564 self.id
565 }
566
567 pub fn is_window_focused(&self) -> bool {
568 self.context.read_tree().state().is_host_focused()
569 }
570
571 pub fn root_window_bounds(&self) -> WindowBounds {
572 *self.context.read_root_window_bounds()
573 }
574
575 pub fn wrapped_action_handler(&self) -> Arc<dyn ActionHandlerNoMut + Send + Sync> {
578 Arc::clone(&self.context.action_handler)
579 }
580}
581
582fn root_window(current_state: &TreeState) -> Option<Node<'_>> {
583 const WINDOW_ROLES: &[Role] = &[Role::AlertDialog, Role::Dialog, Role::Window];
584 let root = current_state.root();
585 if WINDOW_ROLES.contains(&root.role()) {
586 Some(root)
587 } else {
588 None
589 }
590}
591
592impl Drop for Adapter {
593 fn drop(&mut self) {
594 let root_id = self.context.read_tree().state().root_id();
595 self.window_destroyed(root_id);
596 self.context.write_app_context().remove_adapter(self.id);
600 }
601}