From bb66ad4459059a338cbf788d64f77cd75986bcab Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Fri, 3 Feb 2023 10:17:43 -0500 Subject: [PATCH] uiautomationcore: Implement get_BoundingRectangle for MSAA providers. Signed-off-by: Connor McAdams --- dlls/uiautomationcore/tests/uiautomation.c | 79 ++++++++++++++++++++++++++++++ dlls/uiautomationcore/uia_provider.c | 30 +++++++++++- 2 files changed, 107 insertions(+), 2 deletions(-) diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 0ce2693d479..b30e592555c 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -3440,7 +3440,9 @@ static void test_UiaProviderFromIAccessible(void) { ILegacyIAccessibleProvider *accprov; IRawElementProviderSimple *elprov, *elprov2; + IRawElementProviderFragment *elfrag; enum ProviderOptions prov_opt; + struct UiaRect rect; IAccessible *acc; IUnknown *unk; WNDCLASSA cls; @@ -3958,6 +3960,83 @@ static void test_UiaProviderFromIAccessible(void) IRawElementProviderSimple_Release(elprov); ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); + /* + * Test IRawElementProviderFragment_get_BoundingRectangle. + */ + set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSABLE, 0, L"acc_name", 25, 25, 50, 50); + /* Test the case where Accessible is not the root for its HWND. */ + acc_client = NULL; + hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); + + hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!elfrag, "elfrag == NULL\n"); + + SET_EXPECT(winproc_GETOBJECT_CLIENT); + SET_EXPECT(Accessible_get_accRole); + SET_EXPECT(Accessible_get_accState); + SET_EXPECT(Accessible_accLocation); + hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(rect.left == (double)Accessible.left, "Unexpected left value %f\n", rect.left); + ok(rect.top == (double)Accessible.top, "Unexpected top value %f\n", rect.top); + ok(rect.width == (double)Accessible.width, "Unexpected width value %f\n", rect.width); + ok(rect.height == (double)Accessible.height, "Unexpected height value %f\n", rect.height); + CHECK_CALLED(winproc_GETOBJECT_CLIENT); + CHECK_CALLED(Accessible_get_accRole); + CHECK_CALLED(Accessible_get_accState); + CHECK_CALLED(Accessible_accLocation); + + /* If Accessible has STATE_SYSTEM_OFFSCREEN, it will return an empty rect. */ + set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_OFFSCREEN, 0, L"acc_name", 0, 0, 50, 50); + SET_EXPECT(Accessible_get_accState); + hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left); + ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top); + ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width); + ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height); + CHECK_CALLED(Accessible_get_accState); + + IRawElementProviderFragment_Release(elfrag); + IRawElementProviderSimple_Release(elprov); + ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); + + /* Test case where accessible is the root accessible. */ + set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0); + acc_client = &Accessible.IAccessible_iface; + hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(Accessible.ref == 2, "Unexpected refcnt %ld\n", Accessible.ref); + + hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!elfrag, "elfrag == NULL\n"); + + SET_EXPECT(winproc_GETOBJECT_CLIENT); + hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left); + ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top); + ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width); + ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height); + CHECK_CALLED(winproc_GETOBJECT_CLIENT); + + /* Second call does nothing. */ + hr = IRawElementProviderFragment_get_BoundingRectangle(elfrag, &rect); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(rect.left == 0.0, "Unexpected left value %f\n", rect.left); + ok(rect.top == 0.0, "Unexpected top value %f\n", rect.top); + ok(rect.width == 0.0, "Unexpected width value %f\n", rect.width); + ok(rect.height == 0.0, "Unexpected height value %f\n", rect.height); + + IRawElementProviderFragment_Release(elfrag); + IRawElementProviderSimple_Release(elprov); + ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref); + acc_client = NULL; + test_uia_prov_from_acc_properties(); test_uia_prov_from_acc_navigation(); test_uia_prov_from_acc_ia2(); diff --git a/dlls/uiautomationcore/uia_provider.c b/dlls/uiautomationcore/uia_provider.c index c851ecaf685..c4fbd181ada 100644 --- a/dlls/uiautomationcore/uia_provider.c +++ b/dlls/uiautomationcore/uia_provider.c @@ -868,8 +868,34 @@ static HRESULT WINAPI msaa_fragment_GetRuntimeId(IRawElementProviderFragment *if static HRESULT WINAPI msaa_fragment_get_BoundingRectangle(IRawElementProviderFragment *iface, struct UiaRect *ret_val) { - FIXME("%p, %p: stub!\n", iface, ret_val); - return E_NOTIMPL; + struct msaa_provider *msaa_prov = impl_from_msaa_fragment(iface); + LONG left, top, width, height; + HRESULT hr; + + TRACE("%p, %p\n", iface, ret_val); + + memset(ret_val, 0, sizeof(*ret_val)); + + /* + * If this IAccessible is at the root of its HWND, the BaseHwnd provider + * will supply the bounding rectangle. + */ + if (msaa_check_root_acc(msaa_prov)) + return S_OK; + + if (msaa_check_acc_state(msaa_prov->acc, msaa_prov->cid, STATE_SYSTEM_OFFSCREEN)) + return S_OK; + + hr = IAccessible_accLocation(msaa_prov->acc, &left, &top, &width, &height, msaa_prov->cid); + if (FAILED(hr)) + return hr; + + ret_val->left = left; + ret_val->top = top; + ret_val->width = width; + ret_val->height = height; + + return S_OK; } static HRESULT WINAPI msaa_fragment_GetEmbeddedFragmentRoots(IRawElementProviderFragment *iface, -- 2.11.4.GIT