atspi_proxies/accessible.rs
1//! # `AccessibleProxy`
2//!
3//! A handle for a remote object implementing the `org.a11y.atspi.Accessible`
4//! interface.
5//!
6//! Accessible is the interface which is implemented by all accessible objects.
7//!
8
9use crate::common::{InterfaceSet, ObjectRef, RelationType, Role, StateSet};
10use crate::AtspiError;
11
12/// # `AccessibleProxy`
13///
14/// A handle for a remote object implementing the `org.a11y.atspi.Accessible`
15/// interface.
16///
17/// Accessible is the interface which is implemented by all accessible objects.
18///
19#[zbus::proxy(interface = "org.a11y.atspi.Accessible", assume_defaults = true)]
20pub trait Accessible {
21 /// Returns an [`ObjectRef`] which refers to the `Application` object of the application.
22 /// This object will have [`Application`] interface implemented.
23 ///
24 /// The application object is the root of the accessibility hierarchy for the application.
25 /// It is the only object in the hierarchy that does not have a parent.
26 ///
27 /// ## Notes
28 /// The application object is the only object in the accessibility hierarchy that is
29 /// guaranteed to be persistent for the lifetime of the application.
30 /// All other objects in the accessibility hierarchy may be created and destroyed dynamically.
31 ///
32 /// [`ObjectRef`]: ../crate::common::events::ObjectRef
33 /// [`Application`]: crate::application::ApplicationProxy
34 fn get_application(&self) -> zbus::Result<ObjectRef>;
35
36 /// Gets a list of name/value pairs of attributes or annotations for this object.
37 ///
38 /// ## Disambiguation
39 /// For typographic, textual, or textually-semantic attributes,
40 /// see [`TextProxy`]'s [`get_attributes`] method instead.
41 ///
42 /// [`TextProxy`]: crate::text::TextProxy
43 /// [`get_attributes`]: crate::text::TextProxy#method.get_attributes
44 fn get_attributes(&self) -> zbus::Result<std::collections::HashMap<String, String>>;
45
46 /// Retrieve child by index (starting from 0),
47 ///
48 /// Queries the N-th accessible child of `self`. It is expected that this
49 /// will correspond to the order that the [`get_children`] method would return.
50 ///
51 /// ## Notes
52 /// Implementations vary in their behavior when the index is out of range.
53 /// GTK4 returns an error, while atk-adaptor (e.g. Gtk3) returns the
54 /// null object path "/org/a11y/atspi/null".
55 ///
56 /// Documentation advises implementors to return a DBus Error when the index is
57 /// out of range, to "keep the type system gods happy".
58 ///
59 /// [`get_children`]: #method.get_children
60 fn get_child_at_index(&self, index: i32) -> zbus::Result<ObjectRef>;
61
62 /// Retrieves a list of the object's accessible children.
63 ///
64 /// Each array element is an [`Accessible`] representing the accessible child object.
65 ///
66 /// ## Registry
67 ///
68 /// On the [`Accessible`] interface of `org.a11y.atspi.Registry`, the registry daemon, this method retrieves a list
69 /// of all accessible applications' root objects on the bus.
70 ///
71 /// [`Accessible`]: crate::accessible::AccessibleProxy
72 fn get_children(&self) -> zbus::Result<Vec<ObjectRef>>;
73
74 /// This object resides in its parent's list of children.
75 /// This returns its position in this list of children, starting from 0.
76 ///
77 /// The function returns -1 if the object does not have a parent or
78 /// if an exception occurs.
79 fn get_index_in_parent(&self) -> zbus::Result<i32>;
80
81 /// Returns an [`InterfaceSet`] accessible interface names supported by the `self` object.
82 /// [`InterfaceSet`]: crate::common::InterfaceSet
83 fn get_interfaces(&self) -> zbus::Result<InterfaceSet>;
84
85 /// Gets a `String` corresponding to the name of the role played by an object,
86 /// translated to the current locale.
87 ///
88 /// ## Notes
89 ///
90 /// This method will return useful values for roles that fall outside the
91 /// enumeration used in the [`get_role`] method.
92 ///
93 /// For applications, implementing this method is optional, and it may be removed
94 /// in a future version of the API.
95 ///
96 /// For example, [`libatspi`] will only call it in the event of an unknown role.
97 ///
98 /// [`libatspi`]: <https://gitlab.gnome.org/GNOME/at-spi2-core/main/atspi>
99 /// [`get_role`]: #method.get_role
100 fn get_localized_role_name(&self) -> zbus::Result<String>;
101
102 /// Returns a set of relationships between the this `self` object and others.
103 ///
104 /// This vector of tuples contains a [`RelationType`] and a vector of [`Accessible`]'s to which that
105 /// relationship applies.
106 /// These relationships allow for better identification of how objects are associated with one another.
107 ///
108 /// For example, the relationship [`RelationType::LabelledBy`] can be used to identify labeling information
109 /// that should accompany the accessible [`name`] property when presenting an object's content or identity
110 /// to the end user.
111 ///
112 /// Similarly, [`RelationType::ControllerFor`] can be used to specify the context in which a valuator is useful
113 /// and/or the other UI components that are directly affected by user interactions with the valuator.
114 /// Common examples include the association of scrollbars with the viewport or panel that they control.
115 ///
116 /// [`RelationType`]: crate::common::RelationType
117 /// [`RelationType::LabelledBy`]: crate::common::RelationType::LabelledBy
118 /// [`RelationType::ControllerFor`]: crate::common::RelationType::ControllerFor
119 /// [`name`]: #method.name
120 /// [`Accessible`]: ../crate::common::events::Accessible
121 fn get_relation_set(&self) -> zbus::Result<Vec<(RelationType, Vec<ObjectRef>)>>;
122
123 /// Gets the [`Role`] that the current accessible object represents.
124 ///
125 /// Roles make it possible for various UI toolkits to expose their controls to
126 /// assistive technologies (ATs) with a standard interface, regardless of toolkit.
127 ///
128 /// For example, a widget that acts like a conventional push button
129 /// (appears unpressed; presses when acted upon; invokes a certain action
130 /// when pressed) can expose an [`Role::Button`] role.
131 ///
132 /// [`Role::Button`]: crate::common::Role::Button
133 /// [`Role`]: crate::common::Role
134 fn get_role(&self) -> zbus::Result<Role>;
135
136 /// Gets a `String` corresponding to the name of the role played by an object,
137 /// translated to the current locale.
138 ///
139 /// ## Notes
140 ///
141 /// This method will return useful values for roles that fall outside the
142 /// enumeration used in the `get_role` method.
143 ///
144 /// For applications, implementing this method is optional, and it may be removed
145 /// in a future version of the API.
146 ///
147 /// [`libatspi`]: <https://gitlab.gnome.org/GNOME/at-spi2-core/main/atspi>
148 /// [`libatspi`]: <https://gitlab.gnome.org/GNOME/at-spi2-core/>
149 fn get_role_name(&self) -> zbus::Result<String>;
150
151 /// Method to retrieve the [`StateSet`] of states currently held by `self`.
152 /// [`StateSet`]: crate::common::StateSet
153 fn get_state(&self) -> zbus::Result<StateSet>;
154
155 /// Application-specific identifier for the current object.
156 ///
157 /// A special id given to an object.
158 /// Accessible application developers can use this to give a special id to an object
159 /// to use in tests, for example, "my_widget".
160 ///
161 /// Note that there is no way to directly find an object by its id;
162 /// a test program may have to recursively get the children to find a specific id.
163 /// This is because accessible objects can be created dynamically, and they do not always
164 /// correspond to a static view of an application's data.
165 #[zbus(property)]
166 fn accessible_id(&self) -> zbus::Result<String>;
167
168 /// Number of accessible children for the current object.
169 #[zbus(property)]
170 fn child_count(&self) -> zbus::Result<i32>;
171
172 /// Human-readable, localized description of `self` in more detail.
173 ///
174 /// This is a longer description than the [`Name`][name] property.
175 ///
176 /// For example, a button might have a name of "OK", but a description of "OK button".
177 ///
178 /// While the Name property is meant to be a short string that screen readers say
179 /// during normal navigation, the Description property is for when the user asks for
180 /// more detail.
181 ///
182 /// [name]: #method.name
183 #[zbus(property)]
184 fn description(&self) -> zbus::Result<String>;
185
186 /// Unix locale for the current object.
187 ///
188 /// This is a string in the form of "language_territory.codeset".
189 /// For example, "en_US.UTF-8" or "de_DE.UTF-8".
190 ///
191 /// For an application, this may be the locale for the language that the application
192 /// shows in its user interface.
193 ///
194 /// For a document being shown in an application, or a paragraph within a document,
195 /// the locale may refer to that object exclusively. For example:
196 /// an application may be showing itself in English ("en"), but it may be used to
197 /// display a document in Spanish ("es").
198 /// In the latter case, a screen reader will want to know that it should switch to
199 /// Spanish while reading the document.
200 #[zbus(property)]
201 fn locale(&self) -> zbus::Result<String>;
202
203 /// Human-readable, localized, short name for the object.
204 ///
205 /// Applications should have this set for objects which do not
206 /// have a [`RelationType::LabelledBy`] relation.
207 ///
208 /// Consider a widget to select RGB colors by setting three sliders.
209 /// The names for the sliders would be "Red", "Green", "Blue", respectively, or
210 /// their translations to application's locale. The names would be unnecessary if each
211 /// slider had a `LabeledBy` relation to corresponding labels visible in the user
212 /// interface.
213 ///
214 /// [`RelationType::LabelledBy`]: crate::common::RelationType::LabelledBy
215 #[zbus(property)]
216 fn name(&self) -> zbus::Result<String>;
217
218 /// ObjectRef parent object of the current object.
219 ///
220 /// Null parent:
221 /// If the object has no parent (e.g. the application's root object is being queried),
222 /// The application should return "" for the application name name and "/org/a11y/atspi/null"
223 /// for the object path.
224 ///
225 /// Root object:
226 /// An application must have a single root object, called "/org/a11y/atspi/accessible/root".
227 /// All other objects should have that one as their highest-level ancestor.
228 #[zbus(property)]
229 fn parent(&self) -> zbus::Result<ObjectRef>;
230
231 /// Help text for the current object.
232 #[zbus(property)]
233 fn help_text(&self) -> zbus::Result<String>;
234}
235
236impl TryFrom<AccessibleProxy<'_>> for ObjectRef {
237 type Error = AtspiError;
238 fn try_from(proxy: AccessibleProxy<'_>) -> Result<ObjectRef, Self::Error> {
239 Ok(ObjectRef {
240 name: proxy.inner().destination().as_str().try_into()?,
241 path: proxy.inner().path().to_string().try_into()?,
242 })
243 }
244}
245
246impl TryFrom<&AccessibleProxy<'_>> for ObjectRef {
247 type Error = AtspiError;
248 fn try_from(proxy: &AccessibleProxy<'_>) -> Result<ObjectRef, Self::Error> {
249 Ok(ObjectRef {
250 name: proxy.inner().destination().as_str().try_into()?,
251 path: proxy.inner().path().to_string().try_into()?,
252 })
253 }
254}
255
256pub trait ObjectRefExt {
257 /// Returns an [`AccessibleProxy`], the handle to the object's `Accessible` interface.
258 ///
259 /// # Errors
260 ///
261 /// `UniqueName` or `ObjectPath` are assumed to be valid because they are obtained from a valid `ObjectRef`.
262 /// If the builder is lacking the necessary parameters to build a proxy. See [`zbus::proxy::Builder::build`].
263 /// If this method fails, you may want to check the `AccessibleProxy` default values for missing / invalid parameters.
264 fn as_accessible_proxy(
265 &self,
266 conn: &zbus::Connection,
267 ) -> impl std::future::Future<Output = Result<AccessibleProxy<'_>, zbus::Error>> + Send;
268
269 /// Returns an [`AccessibleProxy`], the handle to the object's `Accessible` interface.
270 ///
271 /// # Errors
272 ///
273 /// `UniqueName` or `ObjectPath` are assumed to be valid because they are obtained from a valid `ObjectRef`.
274 /// If the builder is lacking the necessary parameters to build a proxy. See [`zbus::proxy::Builder::build`].
275 /// If this method fails, you may want to check the `AccessibleProxy` default values for missing / invalid parameters.
276 fn into_accessible_proxy(
277 self,
278 conn: &zbus::Connection,
279 ) -> impl std::future::Future<Output = Result<AccessibleProxy<'_>, zbus::Error>> + Send;
280}
281
282impl ObjectRefExt for ObjectRef {
283 async fn as_accessible_proxy(
284 &self,
285 conn: &zbus::Connection,
286 ) -> Result<AccessibleProxy<'_>, zbus::Error> {
287 AccessibleProxy::builder(conn)
288 .destination(self.name.clone())?
289 .path(self.path.clone())?
290 .cache_properties(zbus::proxy::CacheProperties::No)
291 .build()
292 .await
293 }
294
295 async fn into_accessible_proxy(
296 self,
297 conn: &zbus::Connection,
298 ) -> Result<AccessibleProxy<'_>, zbus::Error> {
299 AccessibleProxy::builder(conn)
300 .destination(self.name)?
301 .path(self.path)?
302 .cache_properties(zbus::proxy::CacheProperties::No)
303 .build()
304 .await
305 }
306}
307
308impl PartialEq for AccessibleProxy<'_> {
309 fn eq<'a>(&self, other: &Self) -> bool {
310 self.inner().path() == other.inner().path()
311 }
312}
313impl Eq for AccessibleProxy<'_> {}
314
315#[cfg(test)]
316mod tests {
317 use crate::accessible::Role;
318
319 #[test]
320 fn test_output_of_role_name() {
321 assert_eq!(Role::Invalid.name(), "invalid");
322 assert_eq!(Role::PushButtonMenu.name(), "push button menu");
323 }
324}