[PATCH 3/3] uiautomationcore: Implement NavigateDirection_Parent for MSAA Providers.
Connor McAdams
wine at gitlab.winehq.org
Sat Jun 11 16:57:54 CDT 2022
From: Connor McAdams <cmcadams at codeweavers.com>
Signed-off-by: Connor McAdams <cmcadams at 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,
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/230
More information about the wine-devel
mailing list