Last active
February 22, 2019 13:04
-
-
Save leiless/94ed1ec405fe149918ff5a3207bac704 to your computer and use it in GitHub Desktop.
Fetch AXUIElement attribute's value from a given path
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Fetch AXUIElement attribute's value from a given path | |
* @attributePath Parent-child path string | |
* Example: "AXMenuBar" | |
* "AXFocusedWindow, AXDocument" | |
* "AXFocusedWindow, AXCloseButton, AXEdited" | |
* @return see [self valueOfUIElement: attribute:] | |
* | |
* TRYME: reprototype to [self valueOfUIElement:(AXUIElementRef) attributePath:(NSString *) ...] | |
*/ | |
+ (CFTypeRef _Nullable)valueOfUIElement:(AXUIElementRef _Nonnull)element attributePath:(nonnull NSString *)attributePath { | |
AXError e = kAXErrorFailure; | |
CFTypeRef value = NULL; | |
CFTypeRef *heap = NULL; | |
NSArray<NSString *> *list; | |
NSUInteger sz; | |
NSUInteger i; | |
NSString *attr; | |
ASSERT_NONNULL(element); | |
ASSERT_NONNULL(attributePath); | |
list = [attributePath componentsSeparatedByString:@","]; | |
sz = [list count]; | |
if (sz > 0) { | |
if ((heap = (CFTypeRef *) malloc(sz * sizeof(CFTypeRef))) != NULL) { | |
(void) memset(heap, 0, sz * sizeof(CFTypeRef)); | |
} | |
} | |
if (heap == NULL) goto out_exit; | |
for (i = 0; i < sz; i++) { | |
heap[i] = value; | |
attr = [[list objectAtIndex:i] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]; | |
e = AXUIElementCopyAttributeValue(element, (__bridge CFStringRef) attr, &value); | |
if (e != kAXErrorSuccess) { | |
LOG_ERR("AXUIElementCopyAttributeValue() fail attribute: %@ error: %@", attr, [self axErrorName:e]); | |
break; | |
} | |
/* Stop when we met first non-AXUIElementRef value */ | |
if (CFGetTypeID(value) != AXUIElementGetTypeID()) { | |
if (i != sz - 1) { | |
LOG_ERR("Met non-AXUIElementRef value in the interim idx: %lu attr: %@", i, attr); | |
e = kAXErrorFailure; | |
} | |
break; | |
} | |
element = (AXUIElementRef) value; | |
} | |
/* Release interim AXUIElementRef */ | |
for (i = 0; i < sz; i++) { | |
CFSafeRelease(heap[i]); | |
} | |
free(heap); | |
out_exit: | |
return e == kAXErrorSuccess ? value : nil; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Test: