accessibility_ng/
value.rs1#![allow(non_upper_case_globals)]
2use std::convert::TryFrom;
3use std::{ffi::c_void, mem::MaybeUninit};
4
5use crate::Error;
6
7use cocoa::appkit::CGPoint;
8use core_foundation::base::{CFRange, TCFType};
9use core_foundation::{declare_TCFType, impl_CFTypeDescription, impl_TCFType};
10
11use accessibility_sys_ng::{
12 kAXValueTypeAXError, kAXValueTypeCFRange, kAXValueTypeCGPoint, kAXValueTypeCGRect,
13 kAXValueTypeCGSize, kAXValueTypeIllegal, AXValueCreate, AXValueGetType, AXValueGetTypeID,
14 AXValueGetValue, AXValueRef, AXValueType,
15};
16use core_graphics_types::geometry::{CGRect, CGSize};
17
18declare_TCFType!(AXValue, AXValueRef);
19impl_TCFType!(AXValue, AXValueRef, AXValueGetTypeID);
20impl_CFTypeDescription!(AXValue);
21
22pub trait ValidAXValueType {}
24impl ValidAXValueType for CGRect {}
25impl ValidAXValueType for CGSize {}
26impl ValidAXValueType for CGPoint {}
27impl ValidAXValueType for CFRange {}
28
29impl AXValue {
30 #[allow(non_snake_case)]
31 pub fn from_CGSize(mut size: CGSize) -> Result<Self, Error> {
32 unsafe {
33 Ok(Self::wrap_under_create_rule(AXValueCreate(
34 kAXValueTypeCGSize,
35 &mut size as *mut _ as *mut c_void,
36 )))
37 }
38 }
39
40 #[allow(non_snake_case)]
41 pub fn from_CGPoint(mut point: CGPoint) -> Result<Self, Error> {
42 unsafe {
43 Ok(Self::wrap_under_create_rule(AXValueCreate(
44 kAXValueTypeCGPoint,
45 &mut point as *mut _ as *mut c_void,
46 )))
47 }
48 }
49
50 #[allow(non_snake_case)]
51 pub fn from_CGRect(mut rect: CGRect) -> Result<Self, Error> {
52 unsafe {
53 Ok(Self::wrap_under_create_rule(AXValueCreate(
54 kAXValueTypeCGRect,
55 &mut rect as *mut _ as *mut c_void,
56 )))
57 }
58 }
59
60 #[allow(non_snake_case)]
61 pub fn from_CFRange(mut range: CFRange) -> Result<Self, Error> {
62 unsafe {
63 Ok(Self::wrap_under_create_rule(AXValueCreate(
64 kAXValueTypeCFRange,
65 &mut range as *mut _ as *mut c_void,
66 )))
67 }
68 }
69
70 pub fn get_type(&self) -> AXValueType {
71 unsafe { AXValueGetType(self.0) }
72 }
73
74 pub fn get_value<T: ValidAXValueType>(&self) -> Result<T, Error> {
75 unsafe {
76 match self.get_type() {
78 kAXValueTypeAXError => {
79 return Err(Error::Ax(helper_u32_to_i32(kAXValueTypeAXError)));
80 }
81 kAXValueTypeIllegal => {
82 return Err(Error::Ax(helper_u32_to_i32(kAXValueTypeIllegal)));
83 }
84 kAXValueTypeCGPoint => {
85 if std::any::type_name::<T>() != "core_graphics_types::geometry::CGPoint" {
86 return Err(Error::Ax(helper_u32_to_i32(kAXValueTypeAXError)));
87 }
88 }
89 kAXValueTypeCGSize => {
90 if std::any::type_name::<T>() != "core_graphics_types::geometry::CGSize" {
91 return Err(Error::Ax(helper_u32_to_i32(kAXValueTypeAXError)));
92 }
93 }
94 kAXValueTypeCGRect => {
95 if std::any::type_name::<T>() != "core_graphics_types::geometry::CGRect" {
96 return Err(Error::Ax(helper_u32_to_i32(kAXValueTypeAXError)));
97 }
98 }
99 kAXValueTypeCFRange => {
100 if std::any::type_name::<T>() != "core_foundation_sys::base::CFRange" {
101 return Err(Error::Ax(helper_u32_to_i32(kAXValueTypeAXError)));
102 }
103 }
104 other => {
105 assert!(false, "unexpected AXValueType: {}", other);
106 }
107 }
108
109 let mut value = MaybeUninit::<T>::uninit();
110 let mut_ptr = &mut value as *mut _ as *mut c_void;
111
112 if AXValueGetValue(self.0, self.get_type(), mut_ptr) {
113 Ok(value.assume_init() as T)
114 } else {
115 Err(Error::Ax(helper_u32_to_i32(kAXValueTypeAXError)))
116 }
117 }
118 }
119}
120
121fn helper_u32_to_i32(v: u32) -> i32 {
123 i32::try_from(v).ok().unwrap()
124}