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