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