From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 96 ++++++++++------------ dlls/uiautomationcore/uia_provider.c | 64 ++++++++++++++- 2 files changed, 104 insertions(+), 56 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index b4958d2dc70..885e520bfd3 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -1078,38 +1078,35 @@ static void test_uia_prov_from_acc_navigation(void) elfrag2 = (void *)0xdeadbeef; hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2); ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(!elfrag2, "elfrag2 != NULL\n"); - todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT); - todo_wine CHECK_CALLED(Accessible_get_accRole); - todo_wine CHECK_CALLED(Accessible_get_accState); - todo_wine CHECK_CALLED(Accessible_get_accChildCount); - todo_wine CHECK_CALLED(Accessible_accLocation); - todo_wine CHECK_CALLED(Accessible_get_accName); - todo_wine CHECK_CALLED(Accessible2_get_accRole); - todo_wine CHECK_CALLED(Accessible2_get_accState); - todo_wine CHECK_CALLED(Accessible2_get_accChildCount); - todo_wine CHECK_CALLED(Accessible2_accLocation); - todo_wine CHECK_CALLED(Accessible2_get_accName); + CHECK_CALLED(winproc_GETOBJECT_CLIENT); + CHECK_CALLED(Accessible_get_accRole); + CHECK_CALLED(Accessible_get_accState); + CHECK_CALLED(Accessible_get_accChildCount); + CHECK_CALLED(Accessible_accLocation); + CHECK_CALLED(Accessible_get_accName); + CHECK_CALLED(Accessible2_get_accRole); + CHECK_CALLED(Accessible2_get_accState); + CHECK_CALLED(Accessible2_get_accChildCount); + CHECK_CALLED(Accessible2_accLocation); + CHECK_CALLED(Accessible2_get_accName); todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity); todo_wine CHECK_CALLED(Accessible2_get_accParent); acc_client = NULL;
- if (SUCCEEDED(hr)) - { - /* No check against root IAccessible, since it was done previously. */ - elprov2 = (void *)0xdeadbeef; - hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2); - ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2); - IRawElementProviderSimple_Release(elprov2); - } + /* No check against root IAccessible, since it was done previously. */ + elprov2 = (void *)0xdeadbeef; + hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!elprov2, "elprov == NULL, elprov %p\n", elprov2); + IRawElementProviderSimple_Release(elprov2);
/* Do nothing. */ elfrag2 = (void *)0xdeadbeef; hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2); ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); ok(!elfrag2, "elfrag2 != NULL\n");
elfrag2 = (void *)0xdeadbeef; @@ -1284,36 +1281,30 @@ static void test_uia_prov_from_acc_navigation(void) SET_EXPECT(Accessible2_QI_IAccIdentity); SET_EXPECT(Accessible2_get_accParent); hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2); - todo_wine ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!elfrag2, "elfrag2 == NULL\n"); - todo_wine CHECK_CALLED(Accessible_child_get_accParent); - todo_wine CHECK_CALLED(Accessible_child_get_accRole); - todo_wine CHECK_CALLED(Accessible2_get_accRole); + ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!elfrag2, "elfrag2 == NULL\n"); + CHECK_CALLED(Accessible_child_get_accParent); + CHECK_CALLED(Accessible_child_get_accRole); + CHECK_CALLED(Accessible2_get_accRole); todo_wine CHECK_CALLED(Accessible2_QI_IAccIdentity); todo_wine CHECK_CALLED(Accessible2_get_accParent); - todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT); - if (elfrag2) - { - check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF); - IRawElementProviderFragment_Release(elfrag2); - ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); - } + CHECK_CALLED(winproc_GETOBJECT_CLIENT); + check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF); + IRawElementProviderFragment_Release(elfrag2); + ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); acc_client = NULL;
/* Second call only does get_accParent, no root check. */ SET_EXPECT(Accessible_child_get_accParent); hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2); - todo_wine ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!elfrag2, "elfrag2 == NULL\n"); - todo_wine CHECK_CALLED(Accessible_child_get_accParent); - if (elfrag2) - { - check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF); - IRawElementProviderFragment_Release(elfrag2); - ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); - } + ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!elfrag2, "elfrag2 == NULL\n"); + CHECK_CALLED(Accessible_child_get_accParent); + check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF); + IRawElementProviderFragment_Release(elfrag2); + ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
/* ChildCount of 0, do nothing for First/Last child.*/ SET_EXPECT(Accessible_child_get_accChildCount); @@ -1434,15 +1425,12 @@ static void test_uia_prov_from_acc_navigation(void) * can't be the root IAccessible. */ hr = IRawElementProviderFragment_Navigate(elfrag, NavigateDirection_Parent, &elfrag2); - todo_wine ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!elfrag2, "elfrag2 == NULL\n"); - if (elfrag2) - { - check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF); - IRawElementProviderFragment_Release(elfrag2); - ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); - } + ok(Accessible.ref == 3, "Unexpected refcnt %ld\n", Accessible.ref); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!elfrag2, "elfrag2 == NULL\n"); + check_fragment_acc(elfrag2, &Accessible.IAccessible_iface, CHILDID_SELF); + IRawElementProviderFragment_Release(elfrag2); + ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref);
/* * Test NavigateDirection_First/LastChild on simple child element. Does diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index 8701d67a89f..1dfe447331e 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -205,6 +205,21 @@ exit: return matched; }
+static HRESULT msaa_acc_get_parent(IAccessible *acc, IAccessible **parent) +{ + IDispatch *disp = NULL; + HRESULT hr; + + *parent = NULL; + hr = IAccessible_get_accParent(acc, &disp); + if (FAILED(hr) || !disp) + return hr; + + hr = IDispatch_QueryInterface(disp, &IID_IAccessible, (void**)parent); + IDispatch_Release(disp); + return hr; +} + static LONG msaa_role_to_uia_control_type(LONG role) { switch (role) @@ -515,9 +530,54 @@ static ULONG WINAPI msaa_fragment_Release(IRawElementProviderFragment *iface) static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface, enum NavigateDirection direction, IRawElementProviderFragment **ret_val) { - FIXME("%p, %d, %p: stub!\n", iface, direction, ret_val); + struct msaa_provider *msaa_prov = impl_from_msaa_fragment(iface); + IRawElementProviderSimple *elprov; + IAccessible *acc; + HRESULT hr; + + TRACE("%p, %d, %p\n", iface, direction, ret_val); + *ret_val = NULL; - return E_NOTIMPL; + switch (direction) + { + case NavigateDirection_Parent: + if (msaa_check_root_acc(msaa_prov)) + break; + + if (V_I4(&msaa_prov->cid) == CHILDID_SELF) + { + hr = msaa_acc_get_parent(msaa_prov->acc, &acc); + if (FAILED(hr) || !acc) + break; + } + else + acc = msaa_prov->acc; + + hr = UiaProviderFromIAccessible(acc, CHILDID_SELF, 0, &elprov); + if (SUCCEEDED(hr)) + { + struct msaa_provider *prov = impl_from_msaa_provider(elprov); + *ret_val = &prov->IRawElementProviderFragment_iface; + } + + if (acc != msaa_prov->acc) + IAccessible_Release(acc); + + break; + + case NavigateDirection_FirstChild: + case NavigateDirection_LastChild: + case NavigateDirection_NextSibling: + case NavigateDirection_PreviousSibling: + FIXME("Unimplemented NavigateDirection %d\n", direction); + return E_NOTIMPL; + + default: + FIXME("Invalid NavigateDirection %d\n", direction); + return E_INVALIDARG; + } + + return S_OK; }
static HRESULT WINAPI msaa_fragment_GetRuntimeId(IRawElementProviderFragment *iface,