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