Module: wine Branch: master Commit: 7e19aef0f3922f9e1b11b6686dbf7bb3d49e315e URL: https://gitlab.winehq.org/wine/wine/-/commit/7e19aef0f3922f9e1b11b6686dbf7bb...
Author: Connor McAdams cmcadams@codeweavers.com Date: Tue May 23 11:36:25 2023 -0400
uiautomationcore: Get IRawElementProviderAdviseEvents interfaces from embedded fragment root providers.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com
---
dlls/uiautomationcore/tests/uiautomation.c | 14 +++---- dlls/uiautomationcore/uia_client.c | 63 ++++++++++++++++++++++++++++-- 2 files changed, 66 insertions(+), 11 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 3ff530057f6..838ff3fbe11 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -13746,7 +13746,7 @@ static const struct prov_method_sequence event_seq5[] = { { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */ { &Provider, FRAG_GET_FRAGMENT_ROOT }, { &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL }, /* Called twice on Win11. */ - { &Provider, FRAG_GET_EMBEDDED_FRAGMENT_ROOTS, METHOD_TODO }, + { &Provider, FRAG_GET_EMBEDDED_FRAGMENT_ROOTS }, NODE_CREATE_SEQ_OPTIONAL(&Provider), /* Only done in Win11. */ { &Provider, FRAG_GET_RUNTIME_ID, METHOD_OPTIONAL }, /* Only done on Win8+. */ { &Provider, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */ @@ -13756,8 +13756,8 @@ static const struct prov_method_sequence event_seq5[] = {
static const struct prov_method_sequence event_seq6[] = { { &Provider, ADVISE_EVENTS_EVENT_REMOVED }, - { &Provider_child, ADVISE_EVENTS_EVENT_REMOVED, METHOD_TODO }, - { &Provider_child2, ADVISE_EVENTS_EVENT_REMOVED, METHOD_TODO }, + { &Provider_child, ADVISE_EVENTS_EVENT_REMOVED }, + { &Provider_child2, ADVISE_EVENTS_EVENT_REMOVED }, { 0 }, };
@@ -14121,13 +14121,13 @@ static void test_UiaAddEvent(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(!!event, "event == NULL\n"); ok(Provider.ref == 3, "Unexpected refcnt %ld\n", Provider.ref); - todo_wine ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); - todo_wine ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); + ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref); + ok(Provider_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child2.ref); ok(Provider.advise_events_added_event_id == UIA_AutomationFocusChangedEventId, "Unexpected advise event added, event ID %d\n", Provider.advise_events_added_event_id); - todo_wine ok(Provider_child.advise_events_added_event_id == UIA_AutomationFocusChangedEventId, + ok(Provider_child.advise_events_added_event_id == UIA_AutomationFocusChangedEventId, "Unexpected advise event added, event ID %d\n", Provider_child.advise_events_added_event_id); - todo_wine ok(Provider_child2.advise_events_added_event_id == UIA_AutomationFocusChangedEventId, + ok(Provider_child2.advise_events_added_event_id == UIA_AutomationFocusChangedEventId, "Unexpected advise event added, event ID %d\n", Provider_child2.advise_events_added_event_id);
method_sequences_enabled = TRUE; diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 32f16c0731d..9c5595eaf4b 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -1722,6 +1722,7 @@ static HRESULT WINAPI uia_provider_attach_event(IWineUiaProvider *iface, LONG_PT struct uia_event *event = (struct uia_event *)huiaevent; IRawElementProviderFragmentRoot *elroot; IRawElementProviderFragment *elfrag; + SAFEARRAY *embedded_roots = NULL; HRESULT hr;
TRACE("%p, %#Ix\n", iface, huiaevent); @@ -1731,9 +1732,19 @@ static HRESULT WINAPI uia_provider_attach_event(IWineUiaProvider *iface, LONG_PT return S_OK;
hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot); - IRawElementProviderFragment_Release(elfrag); if (FAILED(hr)) - return hr; + goto exit; + + /* + * For now, we only support embedded fragment roots on providers that + * don't represent a nested node. + */ + if (event->scope & (TreeScope_Descendants | TreeScope_Children) && !prov->return_nested_node) + { + hr = IRawElementProviderFragment_GetEmbeddedFragmentRoots(elfrag, &embedded_roots); + if (FAILED(hr)) + WARN("GetEmbeddedFragmentRoots failed with hr %#lx\n", hr); + }
if (elroot) { @@ -1747,11 +1758,55 @@ static HRESULT WINAPI uia_provider_attach_event(IWineUiaProvider *iface, LONG_PT hr = uia_event_add_provider_event_adviser(advise_events, event); IRawElementProviderAdviseEvents_Release(advise_events); if (FAILED(hr)) - return hr; + goto exit; } }
- return S_OK; + if (embedded_roots) + { + LONG lbound, elems, i; + HUIANODE node; + + hr = get_safearray_bounds(embedded_roots, &lbound, &elems); + if (FAILED(hr)) + goto exit; + + for (i = 0; i < elems; i++) + { + IRawElementProviderSimple *elprov; + IUnknown *unk; + LONG idx; + + idx = lbound + i; + hr = SafeArrayGetElement(embedded_roots, &idx, &unk); + if (FAILED(hr)) + goto exit; + + hr = IUnknown_QueryInterface(unk, &IID_IRawElementProviderSimple, (void **)&elprov); + IUnknown_Release(unk); + if (FAILED(hr)) + goto exit; + + hr = create_uia_node_from_elprov(elprov, &node, !prov->return_nested_node); + IRawElementProviderSimple_Release(elprov); + if (SUCCEEDED(hr)) + { + hr = attach_event_to_uia_node(node, event); + UiaNodeRelease(node); + if (FAILED(hr)) + { + WARN("attach_event_to_uia_node failed with hr %#lx\n", hr); + goto exit; + } + } + } + } + +exit: + IRawElementProviderFragment_Release(elfrag); + SafeArrayDestroy(embedded_roots); + + return hr; }
static const IWineUiaProviderVtbl uia_provider_vtbl = {