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