I am trying to get the text range globally on MacOS from Accessibility API, AXUIElementCopyAttributeValue function. But having an error converting AXValue to CFTypeRef.
var focusedElement: CFTypeRef?
var rangeValue: AXValue? = nil
First Attempt:
if AXUIElementCopyAttributeValue(
focusedElement as! AXUIElement,
kAXSelectedTextRangeAttribute as CFString,
(CFTypeRef *)&rangeValue) == AXError.success {
} /* Compile error: Cannot convert value of type 'AXValue' to expected argument type 'UnsafeMutablePointer<CFTypeRef?>' (aka 'UnsafeMutablePointer<Optional<AnyObject>>') */
Second Attempt:
if AXUIElementCopyAttributeValue(
focusedElement as! AXUIElement,
kAXSelectedTextRangeAttribute as CFString,
((rangeValue as CFTypeRef) as? UnsafeMutablePointer<CFTypeRef?>)!)
== AXError.success {
} /* Throw Error: Could not cast value of type 'NSNull' (0x7fdf2d8a75a8) to 'Swift.UnsafeMutablePointer<Swift.Optional<Swift.AnyObject>>' */
extension AXUIElement {
func value(forAttribute attribute: String) -> CFTypeRef? {
var value: CFTypeRef?
let err = AXUIElementCopyAttributeValue(self, attribute as CFString, &value)
return value
}
var selectedTextRange: CFRange? {
let val = value(forAttribute: kAXSelectedTextRangeAttribute)
guard let val else { return nil }
let v = val as! AXValue
precondition(AXValueGetType(v) == .cfRange)
var range = CFRange()
let done = AXValueGetValue(v, .cfRange, &range)
precondition(done)
return range
}
}
Not sure if I am using it right. I kept getting case attributeUnsupported = -25205 (The attribute is not supported by the AXUIElementRef.) and nil value from the selectedTextRange.
This is how I use it:
extension AXUIElement {
func value(forAttribute attribute: String) -> CFTypeRef? {
var value: CFTypeRef?
let err = AXUIElementCopyAttributeValue(self, attribute as CFString, &value)
print(err.rawValue) // -25205 here
return value
}
var selectedTextRange: CFRange? {
let val = value(forAttribute: kAXSelectedTextRangeAttribute)
guard let val else {return nil}
let v = val as! AXValue
precondition(AXValueGetType(v) == .cfRange)
var range = CFRange()
let done = AXValueGetValue(v, .cfRange, &range)
precondition(done)
return range
}
}
eventHandler = GlobalEventMonitor(mask: .rightMouseDown){
(mouseEvent: NSEvent?) in
var system: AXUIElement = AXUIElementCreateSystemWide()
var application: CFTypeRef?
var focusedElement: CFTypeRef?
if(AXUIElementCopyAttributeValue(
system,
kAXFocusedApplicationAttribute as CFString,
&application
) == AXError.success){
if AXUIElementCopyAttributeValue(
application as! AXUIElement,
kAXFocusedUIElementAttribute as CFString,
&focusedElement) == AXError.success{
guard let aRange = (application as! AXUIElement).selectedTextRange
else {
return print("nil") // always nil
}
print("range: \(aRange)")
}
}
}
eventHandler?.start()
Am i using it right? I am trying right click and get range of the high-lighted text in Notes app on Mac.