atspi_common/
lib.rs

1#![deny(clippy::all, clippy::pedantic, clippy::cargo, unsafe_code, rustdoc::all)]
2#![allow(clippy::module_name_repetitions)]
3#![allow(clippy::multiple_crate_versions)]
4
5//! # atspi-common
6//!
7//! Defines all common types, events, and data structures for `atspi-proxies` and `atspi-connection`.
8//! Since `atspi-proxies` and `atspi-connection` are downstream crates, the documentation can not link to it directly.
9//! Any type ending in `*Proxy` is in `atspi-proxies`.
10//!
11
12#[macro_use]
13extern crate static_assertions;
14#[macro_use]
15pub(crate) mod macros;
16
17pub mod object_ref;
18pub use object_ref::ObjectRef;
19pub mod interface;
20pub use interface::{Interface, InterfaceSet};
21pub mod state;
22pub use state::{State, StateSet};
23pub mod cache;
24pub use cache::{CacheItem, LegacyCacheItem};
25pub mod error;
26pub use error::AtspiError;
27pub mod events;
28pub use events::{BusProperties, Event, EventProperties, EventTypeProperties};
29mod role;
30pub use role::Role;
31mod relation_type;
32pub use relation_type::RelationType;
33
34use serde::{Deserialize, Serialize};
35use zvariant::Type;
36
37pub type Result<T> = std::result::Result<T, AtspiError>;
38
39pub type MatchArgs<'a> = (
40	&'a [i32],
41	MatchType,
42	std::collections::HashMap<&'a str, &'a str>,
43	MatchType,
44	&'a [i32],
45	MatchType,
46	&'a [&'a str],
47	MatchType,
48	bool,
49);
50
51#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Type)]
52#[repr(u32)]
53/// Enumeration used by interface `CollectionProxy` to specify the way [`ObjectRef`]
54/// objects should be sorted.
55///
56/// [`ObjectRef`]: crate::object_ref::ObjectRef
57pub enum SortOrder {
58	/// Invalid sort order
59	Invalid,
60	/// Canonical sort order
61	Canonical,
62	/// Flow sort order
63	Flow,
64	/// Tab sort order
65	Tab,
66	/// Reverse canonical sort order
67	ReverseCanonical,
68	/// Reverse flow sort order
69	ReverseFlow,
70	/// Reverse tab sort order
71	ReverseTab,
72}
73
74/// Method of traversing a tree in the `CollectionProxy`.
75#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Type)]
76#[repr(u32)]
77pub enum TreeTraversalType {
78	/// Restrict children tree traversal
79	RestrictChildren,
80	/// Restrict sibling tree traversal
81	RestrictSibling,
82	/// In-order tree traversal.
83	Inorder,
84}
85
86#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Type)]
87#[repr(i32)]
88/// Enumeration used by [`MatchArgs`] to specify how to interpret [`ObjectRef`] objects.
89///
90/// [`ObjectRef`]: crate::object_ref::ObjectRef
91pub enum MatchType {
92	/// Invalid match type
93	Invalid,
94	/// true if all of the criteria are met.
95	All,
96	/// true if any of the criteria are met.
97	Any,
98	/// true if none of the criteria are met.
99	NA,
100	/// Same as [`Self::All`] if the criteria is non-empty;
101	/// for empty criteria this rule requires returned value to also have empty set.
102	Empty,
103}
104
105#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Type)]
106#[repr(u32)]
107/// The coordinate type encodes the frame of reference.
108pub enum CoordType {
109	/// In relation to the entire screen.
110	Screen,
111	/// In relation to only the window.
112	Window,
113	/// In relation to the parent of the element being checked.
114	Parent,
115}
116
117#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Type)]
118#[repr(u32)]
119/// Enumeration used by `TextProxy` to indicate how to treat characters intersecting bounding boxes.
120pub enum ClipType {
121	/// No characters/glyphs are omitted.
122	Neither,
123	/// Characters/glyphs clipped by the minimum coordinate are omitted.
124	Min,
125	/// Characters/glyphs which intersect the maximum coordinate are omitted.
126	Max,
127	/// Only glyphs falling entirely within the region bounded by min and max are retained.
128	Both,
129}
130
131#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq, Serialize, Deserialize, Type)]
132#[repr(u32)]
133/// Level of granularity to get text of, in relation to a cursor position.
134pub enum Granularity {
135	/// Gives the character at the index of the cursor. With a line-style cursor (which is standard) this will get the character that appears after the cursor.
136	Char,
137	/// Gives the entire word in front of, or which contains, the cursor. TODO: confirm that it always chooses the word in front of the cursor.
138	Word,
139	/// Gives entire sentence in front of, or which contains, the cursor. TODO: confirm that it always chooses the sentence after the cursor.
140	Sentence,
141	/// Gives the line, as seen visually of which the cursor is situated within.
142	Line,
143	/// Gives the entire block of text, regardless of where the cursor lies within it.
144	Paragraph,
145}
146
147/// Indicates relative stacking order of a `atspi_proxies::component::ComponentProxy` with respect to the
148/// onscreen visual representation of the UI.
149///
150/// The layer index, in combination with the component's extents,
151/// can be used to compute the visibility of all or part of a component.
152/// This is important in programmatic determination of region-of-interest for magnification,
153/// and in flat screen review models of the screen, as well as for other uses.
154/// Objects residing in two of the `Layer` categories support further z-ordering information,
155/// with respect to their peers in the same layer:
156/// namely, [`Layer::Window`] and [`Layer::Mdi`].
157/// Relative stacking order for other objects within the same layer is not available;
158/// the recommended heuristic is first child paints first. In other words,
159/// assume that the first siblings in the child list are subject to being
160/// overpainted by later siblings if their bounds intersect.
161#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Type)]
162pub enum Layer {
163	/// Indicates an error condition or uninitialized value.
164	Invalid,
165	/// Reserved for the desktop background; this is the bottom-most layer,
166	/// over which everything else is painted.
167	Background,
168	/// The 'background' layer for most content renderers and
169	/// UI `atspi_proxies::component::ComponentProxy` containers.
170	Canvas,
171	/// The layer in which the majority of ordinary 'foreground' widgets reside.
172	Widget,
173	/// A special layer between [`Layer::Canvas`] and [`Layer::Widget`], in which the
174	/// 'pseudo windows' (e.g. the Multiple-Document Interface frames) reside.
175	///
176	/// See `atspi_proxies::component::ComponentProxy::get_mdizorder`.
177	Mdi,
178	/// A layer for popup window content, above [`Layer::Widget`].
179	Popup,
180	/// The topmost layer.
181	Overlay,
182	/// The layer in which a toplevel window background usually resides.
183	Window,
184}
185
186/// Enumeration used by interface the [`crate::interface::Interface::Accessible`] to specify where an object should be placed on the screen when using `scroll_to`.
187#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize, Type)]
188pub enum ScrollType {
189	/// Scroll the object to the top left corner of the window.
190	TopLeft,
191	/// Scroll the object to the bottom right corner of the window.
192	BottomRight,
193	/// Scroll the object to the top edge of the window.
194	TopEdge,
195	/// Scroll the object to the bottom edge of the window.
196	BottomEdge,
197	/// Scroll the object to the left edge of the window.
198	LeftEdge,
199	/// Scroll the object to the right edge of the window.
200	RightEdge,
201	/// Scroll the object to application-dependent position on the window.
202	Anywhere,
203}
204
205/// Enumeration used to indicate a type of live region and how assertive it
206/// should be in terms of speaking notifications. Currently, this is only used
207/// for `Announcement` events, but it may be used for additional purposes
208/// in the future.
209/// The argument in the `Announcement` event is named `politeness`.
210#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize, Type)]
211#[repr(i32)]
212pub enum Live {
213	/// No live region.
214	#[default]
215	None,
216	/// This live region should be considered polite.
217	Polite,
218	/// This live region should be considered assertive.
219	Assertive,
220}
221
222impl TryFrom<i32> for Live {
223	type Error = AtspiError;
224
225	fn try_from(value: i32) -> std::result::Result<Self, Self::Error> {
226		match value {
227			0 => Ok(Live::None),
228			1 => Ok(Live::Polite),
229			2 => Ok(Live::Assertive),
230			_ => Err(AtspiError::Conversion("Unknown Live variant")),
231		}
232	}
233}
234
235#[cfg(test)]
236mod tests {
237	use super::*;
238	use zbus_lockstep::{
239		method_args_signature, method_return_signature, signal_body_type_signature,
240	};
241
242	#[test]
243	fn convert_i32_to_live() {
244		assert_eq!(Live::None, Live::try_from(0).unwrap());
245		assert_eq!(Live::Polite, Live::try_from(1).unwrap());
246		assert_eq!(Live::Assertive, Live::try_from(2).unwrap());
247		assert!(Live::try_from(3).is_err());
248		assert!(Live::try_from(-1).is_err());
249	}
250
251	#[test]
252	fn validate_live_signature() {
253		let signature = signal_body_type_signature!("Announcement");
254		let politeness_signature = signature.slice(1..2);
255		assert_eq!(Live::signature(), politeness_signature);
256	}
257
258	#[test]
259	fn validate_scroll_type_signature() {
260		let signature = method_args_signature!(member: "ScrollTo", interface: "org.a11y.atspi.Component", argument: "type");
261		assert_eq!(ScrollType::signature(), signature);
262	}
263
264	#[test]
265	fn validate_layer_signature() {
266		let signature = method_return_signature!("GetLayer");
267		assert_eq!(Layer::signature(), signature);
268	}
269
270	#[test]
271	fn validate_granularity_signature() {
272		let signature = method_args_signature!(member: "GetStringAtOffset", interface: "org.a11y.atspi.Text", argument: "granularity");
273		assert_eq!(Granularity::signature(), signature);
274	}
275
276	#[test]
277	fn validate_clip_type_signature() {
278		let signature = method_args_signature!(member: "GetTextAtOffset", interface: "org.a11y.atspi.Text", argument: "type");
279		assert_eq!(ClipType::signature(), signature);
280	}
281
282	#[test]
283	fn validate_coord_type_signature() {
284		let signature = method_args_signature!(member: "GetImagePosition", interface: "org.a11y.atspi.Image", argument: "coordType");
285		assert_eq!(CoordType::signature(), signature);
286	}
287
288	#[test]
289	fn validate_match_type_signature() {
290		let rule_signature = method_args_signature!(member: "GetMatchesTo", interface: "org.a11y.atspi.Collection", argument: "rule");
291		let match_type_signature = rule_signature.slice(3..4);
292		assert_eq!(MatchType::signature(), match_type_signature);
293	}
294
295	#[test]
296	fn validate_tree_traversal_type_signature() {
297		let signature = method_args_signature!(member: "GetMatchesTo", interface: "org.a11y.atspi.Collection", argument: "tree");
298		assert_eq!(TreeTraversalType::signature(), signature);
299	}
300
301	#[test]
302	fn validate_sort_order_signature() {
303		let signature = method_args_signature!(member: "GetMatches", interface: "org.a11y.atspi.Collection", argument: "sortby");
304		assert_eq!(SortOrder::signature(), signature);
305	}
306}