diff options
Diffstat (limited to 'chromium/docs/accessibility/ia2_to_uia.md')
-rw-r--r-- | chromium/docs/accessibility/ia2_to_uia.md | 139 |
1 files changed, 139 insertions, 0 deletions
diff --git a/chromium/docs/accessibility/ia2_to_uia.md b/chromium/docs/accessibility/ia2_to_uia.md new file mode 100644 index 00000000000..5dffbad8e29 --- /dev/null +++ b/chromium/docs/accessibility/ia2_to_uia.md @@ -0,0 +1,139 @@ +# Runtime two way IAccessible2 to UI Automation elements look up via unique id +Assistive technologies (ATs) who currently rely on IAccessible2 (IA2) that want +to take advantage of the UI Automation (UIA) features at runtime can convert an +IA2 element to an UIA element via a unique id and directly access UIA's API. +This enables ATs who want to gradually transition from IA2 to UIA to experiment +with individual UIA elements at runtime without switching entirely to UIA. + + +To look up an UIA element through a unique id, an AT can utilize +`IUIAutomationItemContainerPattern::FindItemByProperty()` with the custom UIA +unique id property and the element's unique id as parameters. +To look up an IA2 element from an UIA element, an AT can simply +utilize IUIAutomationLegacyIAccessiblePattern::GetIAccessible() and +then query for IAccessible2 interface. The unique id is not needed to +look up the IA2 element from UIA element. + +## Convert an IA2 element to UIA element via unique id +An IA2 element can be converted to an UIA element at runtime via a unique id +that is shared between the two APIs. + +*Note: For the purpose of brevity and clarity, the code snippets below do not +include clean-up of COM references neither does it have error handling.* + +~~~c++ + #include <uiautomation.h> + #include <uiautomationclient.h> + + // Consider the following HTML: + // <html> + // <button>button</button> + // </html> + + // Register custom UIA property for retrieving the unique id of IA2 object. + // {cc7eeb32-4b62-4f4c-aff6-1c2e5752ad8e} + GUID UiaPropertyUniqueIdGuid = { + 0xcc7eeb32, + 0x4b62, + 0x4f4c, + {0xaf, 0xf6, 0x1c, 0x2e, 0x57, 0x52, 0xad, 0x8e}}; + + // Create the registrar object and get the IUIAutomationRegistrar + // interface pointer. + IUIAutomationRegistrar* registrar; + CoCreateInstance(CLSID_CUIAutomationRegistrar, nullptr, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(®istrar)); + + // Custom UIA property id used to retrieve the unique id between UIA/IA2. + PROPERTYID uia_unique_id_property_id; + + // Register the custom UIA property that represents the unique id of an UIA + // element which also matches its corresponding IA2 element's unique id. + // Custom property registration only needs to be done once per process + // lifetime. + UIAutomationPropertyInfo unique_id_property_info = { + UiaPropertyUniqueIdGuid, L"UniqueId", UIAutomationType_String}; + registrar->RegisterProperty(&unique_id_property_info, + &uia_unique_id_property_id); + + // Assume we are given the IAccessible2 element for button, and we want to + // retrieve its corresponding UIA element for the final result. + IAccessible2* button_ia2; /* Initialized */ + + // Retrieve button IA2 element's unique id, which will be used to look up the + // corresponding UIA element later. + LONG unique_id_long; + button_ia2->get_uniqueID(&unique_id_long); + + // Assume we are given the Window Handle hwnd for the root. + UIA_HWND hwnd; /* Initialized */ + + // Instantiating an IUIAutomation object. + IUIAutomation* ui_automation; + CoCreateInstance(CLSID_CUIAutomation, NULL, CLSCTX_INPROC_SERVER, + IID_PPV_ARGS(&ui_automation)); + + // Retrieve the root element from the window handle. + IUIAutomationElement* root_element; + ui_automation->ElementFromHandle(hwnd, &root_element); + + // Retrieve the ItemContainerPattern of the root element. + IUIAutomationItemContainerPattern* item_container_pattern; + root_element->GetCurrentPatternAs(UIA_ItemContainerPatternId, + IID_PPV_ARGS(&item_container_pattern)); + + // We also need to convert the retrieved IA2 element unique id from long to + // VARIANT.VT_BSTR to be consumed by UIA. For demo purpose, I utilize + // std::string here as an intermediary step to convert to VARIANT.VT_BSTR. + std::string unique_id_str = std::to_string(unique_id_long); + + VARIANT unique_id_variant; + unique_id_variant.vt = VT_BSTR; + unique_id_variant.bstrVal = SysAllocString(unique_id_str.c_str()); + + // Retrieving the corresponding UIAutomation element from the unique id of IA2 + // object. + IUIAutomationElement* button_uia; + item_container_pattern->FindItemByProperty(nullptr, uia_unique_id_property_id, + unique_id_variant, + &button_uia /* final result */); +~~~ + +## Convert an UIA element to IA2 element. +Converting an UIA element to an IA2 element is a lot more straightforward and +does not require the shared unique id. Consider the same example above. +~~~c++ + #include <uiautomationclient.h> + + // Assume we are given the UIAutomation element for button, and we want to + // retrieve its corresponding IAccessible2 element for the final result. + IUIAutomationElement* button_uia; /* Initialized */ + + // Retrieve the LegacyIAccessiblePattern of the button UIA element. + IUIAutomationLegacyIAccessiblePattern* legacy_iaccessible_pattern; + legacy_iaccessible_pattern->GetCurrentPatternAs( + UIA_LegacyIAccessiblePatternId, + IID_PPV_ARGS(&legacy_iaccessible_pattern)); + + // Retrieve the IAccessible element from button UIA element. + IAccessible* button_iaccessible; + legacy_iaccessible_pattern->GetIAccessible(&iaccessible); + + // Use QueryService to retrieve button's IAccessible2 element from IAccessible + // element. + IServiceProvider* service_provider; + IAccessible2* button_ia2; + if (SUCCEEDED(button_iaccessible->QueryInterface( + IID_PPV_ARGS(&service_provider)))) { + service_provider->QueryService( + IID_PPV_ARGS(&button_ia2 /* final result */)); + } +~~~ + +## Docs & References: +[Custom UIA Property and Pattern registration in Chromium](https://chromium.googlesource.com/chromium/src/+/master/ui/accessibility/platform/uia_registrar_win.h) + +[UI Automation IItemContainerPattern. It is used to look up IAccessible2 element +via a unique id](https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/nn-uiautomationclient-iuiautomationitemcontainerpattern) + +[UI Automation Client](https://docs.microsoft.com/en-us/windows/win32/api/uiautomationclient/) |