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 | |
9 | use crate::common::{InterfaceSet, ObjectRef, RelationType, Role, StateSet}; |
10 | use 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)] |
20 | 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::PushButton`] role. |
131 | /// |
132 | /// [`Role::PushButton`]: crate::common::Role::PushButton |
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 | |
232 | impl TryFrom<AccessibleProxy<'_>> for ObjectRef { |
233 | type Error = AtspiError; |
234 | fn try_from(proxy: AccessibleProxy<'_>) -> Result<ObjectRef, Self::Error> { |
235 | Ok(ObjectRef { |
236 | name: proxy.inner().destination().as_str().try_into()?, |
237 | path: proxy.inner().path().to_string().try_into()?, |
238 | }) |
239 | } |
240 | } |
241 | |
242 | impl TryFrom<&AccessibleProxy<'_>> for ObjectRef { |
243 | type Error = AtspiError; |
244 | fn try_from(proxy: &AccessibleProxy<'_>) -> Result<ObjectRef, Self::Error> { |
245 | Ok(ObjectRef { |
246 | name: proxy.inner().destination().as_str().try_into()?, |
247 | path: proxy.inner().path().to_string().try_into()?, |
248 | }) |
249 | } |
250 | } |
251 | |
252 | pub trait ObjectRefExt { |
253 | /// Returns an [`AccessibleProxy`], the handle to the object's `Accessible` interface. |
254 | /// |
255 | /// # Errors |
256 | /// |
257 | /// `UniqueName` or `ObjectPath` are assumed to be valid because they are obtained from a valid `ObjectRef`. |
258 | /// If the builder is lacking the necessary parameters to build a proxy. See [`zbus::ProxyBuilder::build`]. |
259 | /// If this method fails, you may want to check the `AccessibleProxy` default values for missing / invalid parameters. |
260 | fn as_accessible_proxy( |
261 | &self, |
262 | conn: &zbus::Connection, |
263 | ) -> impl std::future::Future<Output = Result<AccessibleProxy<'_>, zbus::Error>> + Send; |
264 | } |
265 | |
266 | impl ObjectRefExt for ObjectRef { |
267 | async fn as_accessible_proxy( |
268 | &self, |
269 | conn: &zbus::Connection, |
270 | ) -> Result<AccessibleProxy<'_>, zbus::Error> { |
271 | let builder: Result<{unknown}, Error> = AccessibleProxy::builder(conn).destination(self.name.as_str()); |
272 | let Ok(builder) = builder else { |
273 | return Err(builder.unwrap_err()); |
274 | }; |
275 | |
276 | let builder: Result<{unknown}, Error> = builder.path(self.path.as_str()); |
277 | let Ok(builder) = builder else { |
278 | return Err(builder.unwrap_err()); |
279 | }; |
280 | |
281 | builder |
282 | .cache_properties(zbus::proxy::CacheProperties::No) |
283 | .build() |
284 | .await |
285 | } |
286 | } |
287 | |
288 | impl PartialEq for AccessibleProxy<'_> { |
289 | fn eq<'a>(&self, other: &Self) -> bool { |
290 | self.inner().path() == other.inner().path() |
291 | } |
292 | } |
293 | impl Eq for AccessibleProxy<'_> {} |
294 | |
295 | #[cfg (test)] |
296 | mod tests { |
297 | use crate::accessible::Role; |
298 | |
299 | #[test ] |
300 | fn test_output_of_role_name() { |
301 | assert_eq!(Role::Invalid.name(), "invalid" ); |
302 | assert_eq!(Role::PushButtonMenu.name(), "push button menu" ); |
303 | } |
304 | } |
305 | |