1use crate::{
7 atspi::{interfaces::*, ObjectId},
8 context::get_or_init_app_context,
9 executor::{Executor, Task},
10};
11use accesskit_atspi_common::{
12 NodeId, NodeIdOrRoot, ObjectEvent, PlatformNode, PlatformRoot, Property, WindowEvent,
13};
14use atspi::{
15 events::EventBodyBorrowed,
16 proxy::{bus::BusProxy, socket::SocketProxy},
17 Interface, InterfaceSet,
18};
19use std::{env::var, io};
20use zbus::{
21 connection::Builder,
22 names::{BusName, InterfaceName, MemberName, OwnedUniqueName},
23 zvariant::{Str, Value},
24 Address, Connection, Result,
25};
26
27pub(crate) struct Bus {
28 conn: Connection,
29 _task: Task<()>,
30 socket_proxy: SocketProxy<'static>,
31}
32
33impl Bus {
34 pub(crate) async fn new(
35 session_bus: &Connection,
36 executor: &Executor<'_>,
37 ) -> zbus::Result<Self> {
38 let address = match var("AT_SPI_BUS_ADDRESS") {
39 Ok(address) if !address.is_empty() => address,
40 _ => BusProxy::new(session_bus).await?.get_address().await?,
41 };
42 let address: Address = address.as_str().try_into()?;
43 let conn = Builder::address(address)?
44 .internal_executor(false)
45 .build()
46 .await?;
47 let conn_copy = conn.clone();
48 let _task = executor.spawn(
49 async move {
50 loop {
51 conn_copy.executor().tick().await;
52 }
53 },
54 "accesskit_atspi_bus_task",
55 );
56 let socket_proxy = SocketProxy::new(&conn).await?;
57 let mut bus = Bus {
58 conn,
59 _task,
60 socket_proxy,
61 };
62 bus.register_root_node().await?;
63 Ok(bus)
64 }
65
66 fn unique_name(&self) -> &OwnedUniqueName {
67 self.conn.unique_name().unwrap()
68 }
69
70 async fn register_root_node(&mut self) -> Result<()> {
71 let node = PlatformRoot::new(get_or_init_app_context());
72 let path = ObjectId::Root.path();
73
74 if self
75 .conn
76 .object_server()
77 .at(path.clone(), ApplicationInterface(node.clone()))
78 .await?
79 {
80 self.socket_proxy
81 .embed(&(self.unique_name().as_str(), ObjectId::Root.path().into()))
82 .await?;
83
84 self.conn
85 .object_server()
86 .at(
87 path,
88 RootAccessibleInterface::new(self.unique_name().to_owned(), node),
89 )
90 .await?;
91 }
92
93 Ok(())
94 }
95
96 pub(crate) async fn register_interfaces(
97 &self,
98 node: PlatformNode,
99 new_interfaces: InterfaceSet,
100 ) -> zbus::Result<()> {
101 let path = ObjectId::from(&node).path();
102 let bus_name = self.unique_name().to_owned();
103 if new_interfaces.contains(Interface::Accessible) {
104 self.register_interface(
105 &path,
106 NodeAccessibleInterface::new(bus_name.clone(), node.clone()),
107 )
108 .await?;
109 }
110 if new_interfaces.contains(Interface::Action) {
111 self.register_interface(&path, ActionInterface::new(node.clone()))
112 .await?;
113 }
114 if new_interfaces.contains(Interface::Component) {
115 self.register_interface(
116 &path,
117 ComponentInterface::new(bus_name.clone(), node.clone()),
118 )
119 .await?;
120 }
121 if new_interfaces.contains(Interface::Hyperlink) {
122 self.register_interface(
123 &path,
124 HyperlinkInterface::new(bus_name.clone(), node.clone()),
125 )
126 .await?;
127 if new_interfaces.contains(Interface::Selection) {
128 self.register_interface(
129 &path,
130 SelectionInterface::new(bus_name.clone(), node.clone()),
131 )
132 .await?;
133 }
134 if new_interfaces.contains(Interface::Text) {
135 self.register_interface(&path, TextInterface::new(node.clone()))
136 .await?;
137 }
138 if new_interfaces.contains(Interface::Value) {
139 self.register_interface(&path, ValueInterface::new(node.clone()))
140 .await?;
141 }
142 }
143
144 Ok(())
145 }
146
147 async fn register_interface<T>(&self, path: &str, interface: T) -> Result<bool>
148 where
149 T: zbus::object_server::Interface,
150 {
151 map_or_ignoring_broken_pipe(
152 self.conn.object_server().at(path, interface).await,
153 false,
154 |result| result,
155 )
156 }
157
158 pub(crate) async fn unregister_interfaces(
159 &self,
160 adapter_id: usize,
161 node_id: NodeId,
162 old_interfaces: InterfaceSet,
163 ) -> zbus::Result<()> {
164 let path = ObjectId::Node {
165 adapter: adapter_id,
166 node: node_id,
167 }
168 .path();
169 if old_interfaces.contains(Interface::Accessible) {
170 self.unregister_interface::<NodeAccessibleInterface>(&path)
171 .await?;
172 }
173 if old_interfaces.contains(Interface::Action) {
174 self.unregister_interface::<ActionInterface>(&path).await?;
175 }
176 if old_interfaces.contains(Interface::Component) {
177 self.unregister_interface::<ComponentInterface>(&path)
178 .await?;
179 }
180 if old_interfaces.contains(Interface::Hyperlink) {
181 self.unregister_interface::<HyperlinkInterface>(&path)
182 .await?;
183 }
184 if old_interfaces.contains(Interface::Selection) {
185 self.unregister_interface::<SelectionInterface>(&path)
186 .await?;
187 }
188 if old_interfaces.contains(Interface::Text) {
189 self.unregister_interface::<TextInterface>(&path).await?;
190 }
191 if old_interfaces.contains(Interface::Value) {
192 self.unregister_interface::<ValueInterface>(&path).await?;
193 }
194
195 Ok(())
196 }
197
198 async fn unregister_interface<T>(&self, path: &str) -> Result<bool>
199 where
200 T: zbus::object_server::Interface,
201 {
202 map_or_ignoring_broken_pipe(
203 self.conn.object_server().remove::<T, _>(path).await,
204 false,
205 |result| result,
206 )
207 }
208
209 pub(crate) async fn emit_object_event(
210 &self,
211 adapter_id: usize,
212 target: NodeIdOrRoot,
213 event: ObjectEvent,
214 ) -> Result<()> {
215 let target = match target {
216 NodeIdOrRoot::Node(node) => ObjectId::Node {
217 adapter: adapter_id,
218 node,
219 },
220 NodeIdOrRoot::Root => ObjectId::Root,
221 };
222 let interface = "org.a11y.atspi.Event.Object";
223 let signal = match event {
224 ObjectEvent::ActiveDescendantChanged(_) => "ActiveDescendantChanged",
225 ObjectEvent::Announcement(_, _) => "Announcement",
226 ObjectEvent::BoundsChanged(_) => "BoundsChanged",
227 ObjectEvent::CaretMoved(_) => "TextCaretMoved",
228 ObjectEvent::ChildAdded(_, _) | ObjectEvent::ChildRemoved(_) => "ChildrenChanged",
229 ObjectEvent::PropertyChanged(_) => "PropertyChange",
230 ObjectEvent::SelectionChanged => "SelectionChanged",
231 ObjectEvent::StateChanged(_, _) => "StateChanged",
232 ObjectEvent::TextInserted { .. } | ObjectEvent::TextRemoved { .. } => "TextChanged",
233 ObjectEvent::TextSelectionChanged => "TextSelectionChanged",
234 };
235 match event {
236 ObjectEvent::ActiveDescendantChanged(child) => {
237 let child = ObjectId::Node {
238 adapter: adapter_id,
239 node: child,
240 };
241 let mut body = EventBodyBorrowed::default();
242 body.any_data = child.to_address(self.unique_name().inner()).into();
243 self.emit_event(target, interface, signal, body).await
244 }
245 ObjectEvent::Announcement(message, politeness) => {
246 let mut body = EventBodyBorrowed::default();
247 body.detail1 = politeness as i32;
248 body.any_data = message.into();
249 self.emit_event(target, interface, signal, body).await
250 }
251 ObjectEvent::BoundsChanged(bounds) => {
252 let mut body = EventBodyBorrowed::default();
253 body.any_data = Value::from(bounds);
254 self.emit_event(target, interface, signal, body).await
255 }
256 ObjectEvent::CaretMoved(offset) => {
257 let mut body = EventBodyBorrowed::default();
258 body.detail1 = offset;
259 self.emit_event(target, interface, signal, body).await
260 }
261 ObjectEvent::ChildAdded(index, child) => {
262 let child = ObjectId::Node {
263 adapter: adapter_id,
264 node: child,
265 };
266 let mut body = EventBodyBorrowed::default();
267 body.kind = "add";
268 body.detail1 = index as i32;
269 body.any_data = child.to_address(self.unique_name().inner()).into();
270 self.emit_event(target, interface, signal, body).await
271 }
272 ObjectEvent::ChildRemoved(child) => {
273 let child = ObjectId::Node {
274 adapter: adapter_id,
275 node: child,
276 };
277 let mut body = EventBodyBorrowed::default();
278 body.kind = "remove";
279 body.detail1 = -1;
280 body.any_data = child.to_address(self.unique_name().inner()).into();
281 self.emit_event(target, interface, signal, body).await
282 }
283 ObjectEvent::PropertyChanged(property) => {
284 let mut body = EventBodyBorrowed::default();
285 body.kind = match property {
286 Property::Name(_) => "accessible-name",
287 Property::Description(_) => "accessible-description",
288 Property::Parent(_) => "accessible-parent",
289 Property::Role(_) => "accessible-role",
290 Property::Value(_) => "accessible-value",
291 };
292 body.any_data = match property {
293 Property::Name(value) => Str::from(value).into(),
294 Property::Description(value) => Str::from(value).into(),
295 Property::Parent(parent) => {
296 let parent = match parent {
297 NodeIdOrRoot::Node(node) => ObjectId::Node {
298 adapter: adapter_id,
299 node,
300 },
301 NodeIdOrRoot::Root => ObjectId::Root,
302 };
303 parent.to_address(self.unique_name().inner()).into()
304 }
305 Property::Role(value) => Value::U32(value as u32),
306 Property::Value(value) => Value::F64(value),
307 };
308 self.emit_event(target, interface, signal, body).await
309 }
310 ObjectEvent::SelectionChanged => {
311 self.emit_event(target, interface, signal, EventBodyBorrowed::default())
312 .await
313 }
314 ObjectEvent::StateChanged(state, value) => {
315 let mut body = EventBodyBorrowed::default();
316 body.kind = state.to_static_str();
317 body.detail1 = value as i32;
318 self.emit_event(target, interface, signal, body).await
319 }
320 ObjectEvent::TextInserted {
321 start_index,
322 length,
323 content,
324 } => {
325 let mut body = EventBodyBorrowed::default();
326 body.kind = "insert";
327 body.detail1 = start_index;
328 body.detail2 = length;
329 body.any_data = content.into();
330 self.emit_event(target, interface, signal, body).await
331 }
332 ObjectEvent::TextRemoved {
333 start_index,
334 length,
335 content,
336 } => {
337 let mut body = EventBodyBorrowed::default();
338 body.kind = "delete";
339 body.detail1 = start_index;
340 body.detail2 = length;
341 body.any_data = content.into();
342 self.emit_event(target, interface, signal, body).await
343 }
344 ObjectEvent::TextSelectionChanged => {
345 self.emit_event(target, interface, signal, EventBodyBorrowed::default())
346 .await
347 }
348 }
349 }
350
351 pub(crate) async fn emit_window_event(
352 &self,
353 adapter_id: usize,
354 target: NodeId,
355 window_name: String,
356 event: WindowEvent,
357 ) -> Result<()> {
358 let target = ObjectId::Node {
359 adapter: adapter_id,
360 node: target,
361 };
362 let signal = match event {
363 WindowEvent::Activated => "Activate",
364 WindowEvent::Deactivated => "Deactivate",
365 };
366 let mut body = EventBodyBorrowed::default();
367 body.any_data = window_name.into();
368 self.emit_event(target, "org.a11y.atspi.Event.Window", signal, body)
369 .await
370 }
371
372 async fn emit_event(
373 &self,
374 target: ObjectId,
375 interface: &str,
376 signal_name: &str,
377 body: EventBodyBorrowed<'_>,
378 ) -> Result<()> {
379 map_or_ignoring_broken_pipe(
380 self.conn
381 .emit_signal(
382 Option::<BusName>::None,
383 target.path(),
384 InterfaceName::from_str_unchecked(interface),
385 MemberName::from_str_unchecked(signal_name),
386 &body,
387 )
388 .await,
389 (),
390 |_| (),
391 )
392 }
393}
394
395pub(crate) fn map_or_ignoring_broken_pipe<T, U, F>(
396 result: zbus::Result<T>,
397 default: U,
398 f: F,
399) -> zbus::Result<U>
400where
401 F: FnOnce(T) -> U,
402{
403 match result {
404 Ok(result) => Ok(f(result)),
405 Err(zbus::Error::InputOutput(error)) if error.kind() == io::ErrorKind::BrokenPipe => {
406 Ok(default)
407 }
408 Err(error) => Err(error),
409 }
410}