static COMPtr<IAccessible> findAccessibleObjectById(AccessibilityUIElement parentObject, BSTR idAttribute) { COMPtr<IAccessible> parentIAccessible = parentObject.platformUIElement(); COMPtr<IServiceProvider> serviceProvider(Query, parentIAccessible); if (!serviceProvider) return 0; COMPtr<IAccessibleComparable> comparable = comparableObject(serviceProvider); if (!comparable) return 0; _variant_t value; _bstr_t elementIdAttributeKey(L"AXDRTElementIdAttribute"); if (SUCCEEDED(comparable->get_attribute(elementIdAttributeKey, &value.GetVARIANT()))) { ASSERT(V_VT(&value) == VT_BSTR); if (VARCMP_EQ == ::VarBstrCmp(value.bstrVal, idAttribute, LOCALE_USER_DEFAULT, 0)) return parentIAccessible; } long childCount = parentObject.childrenCount(); if (!childCount) return nullptr; COMPtr<IAccessible> result; for (long i = 0; i < childCount; ++i) { AccessibilityUIElement childAtIndex = parentObject.getChildAtIndex(i); result = findAccessibleObjectById(childAtIndex, idAttribute); if (result) return result; } return nullptr; }
static JSValueRef getIsValidCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception) { AccessibilityUIElement* uiElement = toAXElement(thisObject); if (!uiElement->platformUIElement()) return JSValueMakeBoolean(context, false); // There might be other platform logic that one could check here... return JSValueMakeBoolean(context, true); }
static String attributesOfElement(AccessibilityUIElement* element) { StringBuilder builder; builder.append(String::format("%s\n", element->role()->string().utf8().data())); // For the parent we print its role and its name, if available. builder.append("AXParent: "); AccessibilityUIElement parent = element->parentElement(); if (AtkObject* atkParent = parent.platformUIElement()) { builder.append(roleToString(atk_object_get_role(atkParent))); const char* parentName = atk_object_get_name(atkParent); if (parentName && g_utf8_strlen(parentName, -1)) builder.append(String::format(": %s", parentName)); } else builder.append("(null)"); builder.append("\n"); builder.append(String::format("AXChildren: %d\n", element->childrenCount())); builder.append(String::format("AXPosition: { %f, %f }\n", element->x(), element->y())); builder.append(String::format("AXSize: { %f, %f }\n", element->width(), element->height())); String title = element->title()->string(); if (!title.isEmpty()) builder.append(String::format("%s\n", title.utf8().data())); String description = element->description()->string(); if (!description.isEmpty()) builder.append(String::format("%s\n", description.utf8().data())); String value = element->stringValue()->string(); if (!value.isEmpty()) builder.append(String::format("%s\n", value.utf8().data())); builder.append(String::format("AXFocusable: %d\n", element->isFocusable())); builder.append(String::format("AXFocused: %d\n", element->isFocused())); builder.append(String::format("AXSelectable: %d\n", element->isSelectable())); builder.append(String::format("AXSelected: %d\n", element->isSelected())); builder.append(String::format("AXMultiSelectable: %d\n", element->isMultiSelectable())); builder.append(String::format("AXEnabled: %d\n", element->isEnabled())); builder.append(String::format("AXExpanded: %d\n", element->isExpanded())); builder.append(String::format("AXRequired: %d\n", element->isRequired())); builder.append(String::format("AXChecked: %d\n", element->isChecked())); // We append the ATK specific attributes as a single line at the end. builder.append("AXPlatformAttributes: "); builder.append(getAtkAttributeSetAsString(element->platformUIElement())); return builder.toString(); }