1use accessibility_sys_ng::{
2 kAXAXNextLineRangeForIndexParameterizedAttribute,
3 kAXAXPreviousLineRangeForIndexParameterizedAttribute, kAXAllowedValuesAttribute,
4 kAXAttributedStringForRangeParameterizedAttribute, kAXBoundsForRangeParameterizedAttribute,
5 kAXChildrenAttribute, kAXContentsAttribute, kAXDescriptionAttribute, kAXDocumentAttribute,
6 kAXElementBusyAttribute, kAXEnabledAttribute, kAXFocusedApplicationAttribute,
7 kAXFocusedAttribute, kAXFocusedUIElementAttribute, kAXFocusedWindowAttribute,
8 kAXFrameAttribute, kAXFrontmostAttribute, kAXHelpAttribute, kAXIdentifierAttribute,
9 kAXLabelValueAttribute, kAXLineForIndexParameterizedAttribute, kAXMainAttribute,
10 kAXMainWindowAttribute, kAXMaxValueAttribute, kAXMenuItemCmdCharAttribute,
11 kAXMenuItemCmdGlyphAttribute, kAXMenuItemCmdModifiersAttribute,
12 kAXMenuItemCmdVirtualKeyAttribute, kAXMenuItemMarkCharAttribute, kAXMinValueAttribute,
13 kAXMinimizedAttribute, kAXNumberOfCharactersAttribute, kAXParentAttribute,
14 kAXPlaceholderValueAttribute, kAXPositionAttribute, kAXRangeForLineParameterizedAttribute,
15 kAXRangeForPositionParameterizedAttribute, kAXRoleAttribute, kAXRoleDescriptionAttribute,
16 kAXSelectedChildrenAttribute, kAXSelectedTextAttribute, kAXSelectedTextRangeAttribute,
17 kAXSizeAttribute, kAXSubroleAttribute, kAXTitleAttribute, kAXTopLevelUIElementAttribute,
18 kAXValueAttribute, kAXValueDescriptionAttribute, kAXValueIncrementAttribute,
19 kAXVisibleCharacterRangeAttribute, kAXVisibleChildrenAttribute, kAXWindowAttribute,
20 kAXWindowsAttribute,
21};
22use core_foundation::{
23 array::CFArray,
24 attributed_string::CFAttributedString,
25 base::{CFType, TCFType},
26 boolean::CFBoolean,
27 number::CFNumber,
28 string::CFString,
29};
30use std::marker::PhantomData;
31
32use crate::{AXUIElement, AXValue, ElementFinder, Error};
33
34pub trait TAXAttribute {
35 type Value: TCFType;
36}
37
38#[derive(Clone, Debug)]
39pub struct AXAttribute<T>(CFString, PhantomData<*const T>);
40
41impl<T: TCFType> TAXAttribute for AXAttribute<T> {
42 type Value = T;
43}
44
45impl<T> AXAttribute<T> {
46 #[allow(non_snake_case)]
47 pub fn as_CFString(&self) -> &CFString {
48 &self.0
49 }
50}
51
52macro_rules! accessor {
53 (@decl $name:ident, $typ:ty, $const:ident, $setter:ident) => {
54 accessor!(@decl $name, $typ, $const);
55 fn $setter(&self, value: impl Into<$typ>) -> Result<(), Error>;
56 };
57 (@decl $name:ident, $typ:ty, $const:ident) => {
58 fn $name(&self) -> Result<$typ, Error>;
59 };
60 (@impl $name:ident, $typ:ty, $const:ident, $setter:ident) => {
61 accessor!(@impl $name, $typ, $const);
62 fn $setter(&self, value: impl Into<$typ>) -> Result<(), Error> {
63 self.set_attribute(&AXAttribute::$name(), value)
64 }
65 };
66 (@impl $name:ident, $typ:ty, $const:ident) => {
67 fn $name(&self) -> Result<$typ, Error> {
68 self.attribute(&AXAttribute::$name())
69 }
70 };
71}
72
73macro_rules! define_attributes {
74 ($(($name:ident, $typ:ty, $const:ident $(,$setter:ident)?)),*,) => {
75 impl AXAttribute<()> {
76 $(
77 pub fn $name() -> AXAttribute<$typ> {
78 AXAttribute(CFString::from_static_string($const), PhantomData)
79 }
80 )*
81 }
82
83 pub trait AXUIElementAttributes {
84 $(accessor!(@decl $name, $typ, $const $(, $setter)? );)*
85 }
86
87 impl AXUIElementAttributes for AXUIElement {
88 $(accessor!(@impl $name, $typ, $const $(, $setter)? );)*
89 }
90
91 impl AXUIElementAttributes for ElementFinder {
92 $(accessor!(@impl $name, $typ, $const $(, $setter)? );)*
93 }
94 }
95}
96
97impl AXAttribute<CFType> {
98 pub fn new(name: &CFString) -> Self {
99 AXAttribute(name.to_owned(), PhantomData)
100 }
101}
102
103define_attributes![
104 (allowed_values, CFArray<CFType>, kAXAllowedValuesAttribute),
105 (children, CFArray<AXUIElement>, kAXChildrenAttribute),
106 (contents, AXUIElement, kAXContentsAttribute),
107 (description, CFString, kAXDescriptionAttribute),
108 (document, CFString, kAXDocumentAttribute),
109 (element_busy, CFBoolean, kAXElementBusyAttribute),
110 (enabled, CFBoolean, kAXEnabledAttribute),
111 (
112 focused_application,
113 AXUIElement,
114 kAXFocusedApplicationAttribute
115 ),
116 (focused_uielement, AXUIElement, kAXFocusedUIElementAttribute),
117 (focused, CFBoolean, kAXFocusedAttribute),
118 (focused_window, AXUIElement, kAXFocusedWindowAttribute),
119 (frontmost, CFBoolean, kAXFrontmostAttribute, set_frontmost),
120 (frame, AXValue, kAXFrameAttribute),
121 (help, CFString, kAXHelpAttribute),
122 (identifier, CFString, kAXIdentifierAttribute),
123 (label_value, CFString, kAXLabelValueAttribute),
124 (main, CFBoolean, kAXMainAttribute, set_main),
125 (main_window, AXUIElement, kAXMainWindowAttribute),
126 (max_value, CFType, kAXMaxValueAttribute),
127 (
128 menu_item_cmd_modifier,
129 CFNumber,
130 kAXMenuItemCmdModifiersAttribute
131 ),
132 (menu_item_cmd_char, CFString, kAXMenuItemCmdCharAttribute),
133 (
134 menu_item_cmd_virtual_key,
135 CFString,
136 kAXMenuItemCmdVirtualKeyAttribute
137 ),
138 (menu_item_mark_char, CFString, kAXMenuItemMarkCharAttribute),
139 (menu_item_cmd_glyph, CFString, kAXMenuItemCmdGlyphAttribute),
140 (min_value, CFType, kAXMinValueAttribute),
141 (minimized, CFBoolean, kAXMinimizedAttribute),
142 (
143 number_of_characters,
144 CFNumber,
145 kAXNumberOfCharactersAttribute
146 ),
147 (parent, AXUIElement, kAXParentAttribute),
148 (placeholder_value, CFString, kAXPlaceholderValueAttribute),
149 (position, AXValue, kAXPositionAttribute),
150 (role, CFString, kAXRoleAttribute),
151 (role_description, CFString, kAXRoleDescriptionAttribute),
152 (
153 selected_children,
154 CFArray<AXUIElement>,
155 kAXSelectedChildrenAttribute
156 ),
157 (subrole, CFString, kAXSubroleAttribute),
158 (size, AXValue, kAXSizeAttribute),
159 (selected_text, CFString, kAXSelectedTextAttribute),
160 (selected_text_range, AXValue, kAXSelectedTextRangeAttribute),
161 (title, CFString, kAXTitleAttribute),
162 (
163 top_level_ui_element,
164 AXUIElement,
165 kAXTopLevelUIElementAttribute
166 ),
167 (value, CFType, kAXValueAttribute, set_value),
168 (value_description, CFString, kAXValueDescriptionAttribute),
169 (value_increment, CFType, kAXValueIncrementAttribute),
170 (
171 visible_children,
172 CFArray<AXUIElement>,
173 kAXVisibleChildrenAttribute
174 ),
175 (window, AXUIElement, kAXWindowAttribute),
176 (windows, CFArray<AXUIElement>, kAXWindowsAttribute),
177 (
178 visible_character_range,
179 AXValue,
180 kAXVisibleCharacterRangeAttribute
181 ),
182 (
184 bounds_for_range,
185 AXValue,
186 kAXBoundsForRangeParameterizedAttribute
187 ),
188 (
189 line_for_index,
190 CFNumber,
191 kAXLineForIndexParameterizedAttribute
192 ),
193 (
194 range_for_line,
195 AXValue,
196 kAXRangeForLineParameterizedAttribute
197 ),
198 (
199 range_for_position,
200 AXValue,
201 kAXRangeForPositionParameterizedAttribute
202 ),
203 (
204 next_line_range_for_index,
205 AXValue,
206 kAXAXNextLineRangeForIndexParameterizedAttribute
207 ),
208 (
209 previous_line_range_for_index,
210 AXValue,
211 kAXAXPreviousLineRangeForIndexParameterizedAttribute
212 ),
213 (
214 attributed_string_for_range,
215 CFAttributedString,
216 kAXAttributedStringForRangeParameterizedAttribute
217 ),
218];