1 | // Copyright 2022 The AccessKit Authors. All rights reserved. |
2 | // Licensed under the Apache License, Version 2.0 (found in |
3 | // the LICENSE-APACHE file) or the MIT license (found in |
4 | // the LICENSE-MIT file), at your option. |
5 | |
6 | use accesskit::{ActionHandler, NodeId, Role, TreeUpdate}; |
7 | use accesskit_consumer::{DetachedNode, FilterResult, Node, Tree, TreeChangeHandler, TreeState}; |
8 | use atspi_common::{InterfaceSet, Live, State}; |
9 | use std::sync::{ |
10 | atomic::{AtomicUsize, Ordering}, |
11 | Arc, RwLock, |
12 | }; |
13 | |
14 | use crate::{ |
15 | context::{AppContext, Context}, |
16 | filters::{filter, filter_detached}, |
17 | node::{NodeIdOrRoot, NodeWrapper, PlatformNode, PlatformRoot}, |
18 | util::WindowBounds, |
19 | AdapterCallback, Event, ObjectEvent, WindowEvent, |
20 | }; |
21 | |
22 | struct AdapterChangeHandler<'a> { |
23 | adapter: &'a Adapter, |
24 | } |
25 | |
26 | impl AdapterChangeHandler<'_> { |
27 | fn add_node(&mut self, node: &Node) { |
28 | let role = node.role(); |
29 | let is_root = node.is_root(); |
30 | let node = NodeWrapper::Node(node); |
31 | let interfaces = node.interfaces(); |
32 | self.adapter.register_interfaces(node.id(), interfaces); |
33 | if is_root && role == Role::Window { |
34 | let adapter_index = self |
35 | .adapter |
36 | .context |
37 | .read_app_context() |
38 | .adapter_index(self.adapter.id) |
39 | .unwrap(); |
40 | self.adapter.window_created(adapter_index, node.id()); |
41 | } |
42 | |
43 | let live = node.live(); |
44 | if live != Live::None { |
45 | if let Some(name) = node.name() { |
46 | self.adapter |
47 | .emit_object_event(node.id(), ObjectEvent::Announcement(name, live)); |
48 | } |
49 | } |
50 | } |
51 | |
52 | fn remove_node(&mut self, node: &DetachedNode) { |
53 | let role = node.role(); |
54 | let is_root = node.is_root(); |
55 | let node = NodeWrapper::DetachedNode(node); |
56 | if is_root && role == Role::Window { |
57 | self.adapter.window_destroyed(node.id()); |
58 | } |
59 | self.adapter |
60 | .emit_object_event(node.id(), ObjectEvent::StateChanged(State::Defunct, true)); |
61 | self.adapter |
62 | .unregister_interfaces(node.id(), node.interfaces()); |
63 | } |
64 | } |
65 | |
66 | impl TreeChangeHandler for AdapterChangeHandler<'_> { |
67 | fn node_added(&mut self, node: &Node) { |
68 | if filter(node) == FilterResult::Include { |
69 | self.add_node(node); |
70 | } |
71 | } |
72 | |
73 | fn node_updated(&mut self, old_node: &DetachedNode, new_node: &Node) { |
74 | let filter_old = filter_detached(old_node); |
75 | let filter_new = filter(new_node); |
76 | if filter_new != filter_old { |
77 | if filter_new == FilterResult::Include { |
78 | self.add_node(new_node); |
79 | } else if filter_old == FilterResult::Include { |
80 | self.remove_node(old_node); |
81 | } |
82 | } else if filter_new == FilterResult::Include { |
83 | let old_wrapper = NodeWrapper::DetachedNode(old_node); |
84 | let new_wrapper = NodeWrapper::Node(new_node); |
85 | let old_interfaces = old_wrapper.interfaces(); |
86 | let new_interfaces = new_wrapper.interfaces(); |
87 | let kept_interfaces = old_interfaces & new_interfaces; |
88 | self.adapter |
89 | .unregister_interfaces(new_wrapper.id(), old_interfaces ^ kept_interfaces); |
90 | self.adapter |
91 | .register_interfaces(new_node.id(), new_interfaces ^ kept_interfaces); |
92 | let bounds = *self.adapter.context.read_root_window_bounds(); |
93 | new_wrapper.notify_changes(&bounds, self.adapter, &old_wrapper); |
94 | } |
95 | } |
96 | |
97 | fn focus_moved( |
98 | &mut self, |
99 | old_node: Option<&DetachedNode>, |
100 | new_node: Option<&Node>, |
101 | current_state: &TreeState, |
102 | ) { |
103 | if let Some(root_window) = root_window(current_state) { |
104 | if old_node.is_none() && new_node.is_some() { |
105 | self.adapter |
106 | .window_activated(&NodeWrapper::Node(&root_window)); |
107 | } else if old_node.is_some() && new_node.is_none() { |
108 | self.adapter |
109 | .window_deactivated(&NodeWrapper::Node(&root_window)); |
110 | } |
111 | } |
112 | } |
113 | |
114 | fn node_removed(&mut self, node: &DetachedNode, _: &TreeState) { |
115 | if filter_detached(node) == FilterResult::Include { |
116 | self.remove_node(node); |
117 | } |
118 | } |
119 | } |
120 | |
121 | static NEXT_ADAPTER_ID: AtomicUsize = AtomicUsize::new(0); |
122 | |
123 | pub struct AdapterIdToken(usize); |
124 | |
125 | impl AdapterIdToken { |
126 | pub fn next() -> Self { |
127 | let id: usize = NEXT_ADAPTER_ID.fetch_add(val:1, order:Ordering::Relaxed); |
128 | Self(id) |
129 | } |
130 | |
131 | pub fn id(&self) -> usize { |
132 | self.0 |
133 | } |
134 | } |
135 | |
136 | pub struct Adapter { |
137 | id: usize, |
138 | callback: Box<dyn AdapterCallback + Send + Sync>, |
139 | context: Arc<Context>, |
140 | } |
141 | |
142 | impl Adapter { |
143 | pub fn new( |
144 | app_context: &Arc<RwLock<AppContext>>, |
145 | callback: Box<dyn AdapterCallback + Send + Sync>, |
146 | initial_state: TreeUpdate, |
147 | is_window_focused: bool, |
148 | root_window_bounds: WindowBounds, |
149 | action_handler: Box<dyn ActionHandler + Send>, |
150 | ) -> Self { |
151 | let id_token = AdapterIdToken::next(); |
152 | Self::with_id( |
153 | id_token, |
154 | app_context, |
155 | callback, |
156 | initial_state, |
157 | is_window_focused, |
158 | root_window_bounds, |
159 | action_handler, |
160 | ) |
161 | } |
162 | |
163 | pub fn with_id( |
164 | id_token: AdapterIdToken, |
165 | app_context: &Arc<RwLock<AppContext>>, |
166 | callback: Box<dyn AdapterCallback + Send + Sync>, |
167 | initial_state: TreeUpdate, |
168 | is_window_focused: bool, |
169 | root_window_bounds: WindowBounds, |
170 | action_handler: Box<dyn ActionHandler + Send>, |
171 | ) -> Self { |
172 | let id = id_token.0; |
173 | let tree = Tree::new(initial_state, is_window_focused); |
174 | let context = Context::new(app_context, tree, action_handler, root_window_bounds); |
175 | context.write_app_context().push_adapter(id, &context); |
176 | let adapter = Self { |
177 | id, |
178 | callback, |
179 | context, |
180 | }; |
181 | adapter.register_tree(); |
182 | adapter |
183 | } |
184 | |
185 | fn register_tree(&self) { |
186 | fn add_children(node: Node<'_>, to_add: &mut Vec<(NodeId, InterfaceSet)>) { |
187 | for child in node.filtered_children(&filter) { |
188 | let child_id = child.id(); |
189 | let wrapper = NodeWrapper::Node(&child); |
190 | let interfaces = wrapper.interfaces(); |
191 | to_add.push((child_id, interfaces)); |
192 | add_children(child, to_add); |
193 | } |
194 | } |
195 | |
196 | let mut objects_to_add = Vec::new(); |
197 | |
198 | let (adapter_index, root_id) = { |
199 | let tree = self.context.read_tree(); |
200 | let tree_state = tree.state(); |
201 | let mut app_context = self.context.write_app_context(); |
202 | app_context.name = tree_state.app_name(); |
203 | app_context.toolkit_name = tree_state.toolkit_name(); |
204 | app_context.toolkit_version = tree_state.toolkit_version(); |
205 | let adapter_index = app_context.adapter_index(self.id).unwrap(); |
206 | let root = tree_state.root(); |
207 | let root_id = root.id(); |
208 | let wrapper = NodeWrapper::Node(&root); |
209 | objects_to_add.push((root_id, wrapper.interfaces())); |
210 | add_children(root, &mut objects_to_add); |
211 | (adapter_index, root_id) |
212 | }; |
213 | |
214 | for (id, interfaces) in objects_to_add { |
215 | self.register_interfaces(id, interfaces); |
216 | if id == root_id { |
217 | self.window_created(adapter_index, id); |
218 | } |
219 | } |
220 | } |
221 | |
222 | pub fn platform_node(&self, id: NodeId) -> PlatformNode { |
223 | PlatformNode::new(&self.context, self.id, id) |
224 | } |
225 | |
226 | pub fn root_id(&self) -> NodeId { |
227 | self.context.read_tree().state().root_id() |
228 | } |
229 | |
230 | pub fn platform_root(&self) -> PlatformRoot { |
231 | PlatformRoot::new(&self.context.app_context) |
232 | } |
233 | |
234 | fn register_interfaces(&self, id: NodeId, new_interfaces: InterfaceSet) { |
235 | self.callback.register_interfaces(self, id, new_interfaces); |
236 | } |
237 | |
238 | fn unregister_interfaces(&self, id: NodeId, old_interfaces: InterfaceSet) { |
239 | self.callback |
240 | .unregister_interfaces(self, id, old_interfaces); |
241 | } |
242 | |
243 | pub(crate) fn emit_object_event(&self, target: NodeId, event: ObjectEvent) { |
244 | let target = NodeIdOrRoot::Node(target); |
245 | self.callback |
246 | .emit_event(self, Event::Object { target, event }); |
247 | } |
248 | |
249 | fn emit_root_object_event(&self, event: ObjectEvent) { |
250 | let target = NodeIdOrRoot::Root; |
251 | self.callback |
252 | .emit_event(self, Event::Object { target, event }); |
253 | } |
254 | |
255 | pub fn set_root_window_bounds(&self, new_bounds: WindowBounds) { |
256 | let mut bounds = self.context.root_window_bounds.write().unwrap(); |
257 | *bounds = new_bounds; |
258 | } |
259 | |
260 | pub fn update(&self, update: TreeUpdate) { |
261 | let mut handler = AdapterChangeHandler { adapter: self }; |
262 | let mut tree = self.context.tree.write().unwrap(); |
263 | tree.update_and_process_changes(update, &mut handler); |
264 | } |
265 | |
266 | pub fn update_window_focus_state(&self, is_focused: bool) { |
267 | let mut handler = AdapterChangeHandler { adapter: self }; |
268 | let mut tree = self.context.tree.write().unwrap(); |
269 | tree.update_host_focus_state_and_process_changes(is_focused, &mut handler); |
270 | } |
271 | |
272 | fn window_created(&self, adapter_index: usize, window: NodeId) { |
273 | self.emit_root_object_event(ObjectEvent::ChildAdded(adapter_index, window)); |
274 | } |
275 | |
276 | fn window_activated(&self, window: &NodeWrapper<'_>) { |
277 | self.callback.emit_event( |
278 | self, |
279 | Event::Window { |
280 | target: window.id(), |
281 | name: window.name().unwrap_or_default(), |
282 | event: WindowEvent::Activated, |
283 | }, |
284 | ); |
285 | self.emit_object_event(window.id(), ObjectEvent::StateChanged(State::Active, true)); |
286 | self.emit_root_object_event(ObjectEvent::ActiveDescendantChanged(window.id())); |
287 | } |
288 | |
289 | fn window_deactivated(&self, window: &NodeWrapper<'_>) { |
290 | self.callback.emit_event( |
291 | self, |
292 | Event::Window { |
293 | target: window.id(), |
294 | name: window.name().unwrap_or_default(), |
295 | event: WindowEvent::Deactivated, |
296 | }, |
297 | ); |
298 | self.emit_object_event(window.id(), ObjectEvent::StateChanged(State::Active, false)); |
299 | } |
300 | |
301 | fn window_destroyed(&self, window: NodeId) { |
302 | self.emit_root_object_event(ObjectEvent::ChildRemoved(window)); |
303 | } |
304 | |
305 | pub fn id(&self) -> usize { |
306 | self.id |
307 | } |
308 | } |
309 | |
310 | fn root_window(current_state: &TreeState) -> Option<Node> { |
311 | const WINDOW_ROLES: &[Role] = &[Role::AlertDialog, Role::Dialog, Role::Window]; |
312 | let root: Node<'_> = current_state.root(); |
313 | if WINDOW_ROLES.contains(&root.role()) { |
314 | Some(root) |
315 | } else { |
316 | None |
317 | } |
318 | } |
319 | |
320 | impl Drop for Adapter { |
321 | fn drop(&mut self) { |
322 | let root_id: NodeId = self.context.read_tree().state().root_id(); |
323 | self.window_destroyed(window:root_id); |
324 | // Note: We deliberately do the following here, not in a Drop |
325 | // implementation on context, because AppContext owns a second |
326 | // strong reference to Context, and we need that to be released. |
327 | self.context.write_app_context().remove_adapter(self.id); |
328 | } |
329 | } |
330 | |