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