Soniox Mobile to Mac - Real-time Voice Dictation & Remote Input Control
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

76 lines
2.9 KiB

import Cocoa
import ApplicationServices
func findFocusedDescendant(_ elem: AXUIElement) -> AXUIElement? {
// Check if this element is a text field/text area or has value
var roleObj: CFTypeRef?
AXUIElementCopyAttributeValue(elem, kAXRoleAttribute as CFString, &roleObj)
let role = (roleObj as? String) ?? ""
if role == "AXTextField" || role == "AXTextArea" || role == "AXComboBox" || role == "AXSearchField" {
return elem
}
var focusedObj: CFTypeRef?
if AXUIElementCopyAttributeValue(elem, kAXFocusedAttribute as CFString, &focusedObj) == .success,
let isFocused = focusedObj as? Bool, isFocused {
// If it has value attribute, return it
var valObj: CFTypeRef?
if AXUIElementCopyAttributeValue(elem, kAXValueAttribute as CFString, &valObj) == .success {
return elem
}
}
// Check children
var childrenObj: CFTypeRef?
if AXUIElementCopyAttributeValue(elem, kAXChildrenAttribute as CFString, &childrenObj) == .success,
let children = childrenObj as? [AXUIElement] {
for child in children {
if let found = findFocusedDescendant(child) {
return found
}
}
}
return nil
}
func getDeepFocusedElement() -> (AXUIElement, String, String)? {
guard let frontApp = NSWorkspace.shared.frontmostApplication else { return nil }
let appElem = AXUIElementCreateApplication(frontApp.processIdentifier)
// First try standard focused element
var focusedObj: CFTypeRef?
if AXUIElementCopyAttributeValue(appElem, kAXFocusedUIElementAttribute as CFString, &focusedObj) == .success,
let elem = focusedObj as! AXUIElement? {
var roleObj: CFTypeRef?
AXUIElementCopyAttributeValue(elem, kAXRoleAttribute as CFString, &roleObj)
let role = (roleObj as? String) ?? ""
var valObj: CFTypeRef?
AXUIElementCopyAttributeValue(elem, kAXValueAttribute as CFString, &valObj)
let val = (valObj as? String) ?? ""
if !val.isEmpty || role == "AXTextField" || role == "AXTextArea" {
return (elem, role, val)
}
// If it's a window or web area, search descendants
if let deep = findFocusedDescendant(elem) {
var deepRoleObj: CFTypeRef?
AXUIElementCopyAttributeValue(deep, kAXRoleAttribute as CFString, &deepRoleObj)
let deepRole = (deepRoleObj as? String) ?? ""
var deepValObj: CFTypeRef?
AXUIElementCopyAttributeValue(deep, kAXValueAttribute as CFString, &deepValObj)
let deepVal = (deepValObj as? String) ?? ""
return (deep, deepRole, deepVal)
}
}
return nil
}
if let (elem, role, val) = getDeepFocusedElement() {
print("Found deep focused element! Role: \(role), Value: '\(val)'")
} else {
print("Deep focused element not found")
}