Last active
March 26, 2019 12:08
-
-
Save leiless/d7024348ee563f668b6be11a48faf1b4 to your computer and use it in GitHub Desktop.
Fetch AXUIElement attribute's value from a given list of attributes
This file contains hidden or 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 list of attributes | |
| * @attributes Attribute list | |
| * @return Attribute's value NULL if failed to get | |
| * You should use CFGetTypeID() to inspect type of return value before use it | |
| * If nonnull you must release it by CFRelease() | |
| * | |
| * NOTE: must pass NULL to terminate `attributes' parameter | |
| * otherwise undefined behaviour may happen | |
| */ | |
| + (CFTypeRef _Nullable)valueOfUIElement:(AXUIElementRef _Nonnull)element attributes:(CFStringRef)attr1, ... { | |
| AXError e; | |
| CFTypeRef value = NULL; | |
| CFTypeRef *heap; | |
| NSUInteger i = 0; | |
| NSUInteger sz = 0; | |
| CFStringRef attr = attr1; | |
| va_list ap; | |
| ASSERT_NONNULL(element); | |
| ASSERT_NONNULL(attr); | |
| va_start(ap, attr1); | |
| do { | |
| sz++; | |
| } while (va_arg(ap, CFStringRef) != NULL); | |
| va_end(ap); | |
| if ((heap = (CFTypeRef *) malloc(sz * sizeof(CFTypeRef))) != NULL) { | |
| (void) memset(heap, 0, sz * sizeof(CFTypeRef)); | |
| } else { | |
| goto out_exit; | |
| } | |
| va_start(ap, attr1); | |
| do { | |
| heap[i++] = value; | |
| e = AXUIElementCopyAttributeValue(element, attr, &value); | |
| if (e != kAXErrorSuccess) { | |
| LOG_ERR("AXUIElementCopyAttributeValue() fail attribute: %@ error: %@", attr, [self axErrorName:e]); | |
| value = nil; | |
| break; | |
| } | |
| /* Stop when we met first non-AXUIElementRef value */ | |
| if (CFGetTypeID(value) != AXUIElementGetTypeID()) { | |
| if (i != sz) { | |
| LOG_ERR("Met non-AXUIElementRef value in the interim idx: %lu sz: %lu attr: %@", i, sz, attr); | |
| value = nil; | |
| } | |
| break; | |
| } | |
| element = (AXUIElementRef) value; | |
| } while ((attr = va_arg(ap, CFStringRef)) != NULL); | |
| va_end(ap); | |
| /* Release interim AXUIElementRef */ | |
| for (i = 0; i < sz; i++) { | |
| CFSafeRelease(heap[i]); | |
| } | |
| free(heap); | |
| out_exit: | |
| return value; | |
| } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment