accesskit_unix/atspi/
bus.rs

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_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}