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}