| 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 ] |
| 13 | extern crate static_assertions; |
| 14 | #[macro_use ] |
| 15 | pub(crate) mod macros; |
| 16 | |
| 17 | pub mod object_ref; |
| 18 | pub use object_ref::ObjectRef; |
| 19 | pub mod interface; |
| 20 | pub use interface::{Interface, InterfaceSet}; |
| 21 | pub mod state; |
| 22 | pub use state::{State, StateSet}; |
| 23 | pub mod cache; |
| 24 | pub use cache::{CacheItem, LegacyCacheItem}; |
| 25 | pub mod error; |
| 26 | pub use error::AtspiError; |
| 27 | pub mod events; |
| 28 | pub use events::{BusProperties, Event, EventProperties, EventTypeProperties}; |
| 29 | mod role; |
| 30 | pub use role::Role; |
| 31 | mod relation_type; |
| 32 | pub use relation_type::RelationType; |
| 33 | |
| 34 | use serde::{Deserialize, Serialize}; |
| 35 | use zvariant::Type; |
| 36 | |
| 37 | pub type Result<T> = std::result::Result<T, AtspiError>; |
| 38 | |
| 39 | pub 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 |
| 57 | pub 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)] |
| 77 | pub 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 |
| 91 | pub 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. |
| 108 | pub 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. |
| 120 | pub 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. |
| 134 | pub 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)] |
| 162 | pub 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)] |
| 188 | pub 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)] |
| 212 | pub 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 | |
| 222 | impl 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)] |
| 236 | mod 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 | } |
| 307 | |