From 27aed609c6ea0c2c06e5e66d957695bd5480641d Mon Sep 17 00:00:00 2001 From: Connor McAdams Date: Thu, 21 Sep 2023 11:31:49 -0400 Subject: [PATCH] uiautomationcore: Implement IUIAutomationElement::get_CachedBoundingRectangle. Signed-off-by: Connor McAdams --- dlls/uiautomationcore/tests/uiautomation.c | 19 ++++--- dlls/uiautomationcore/uia_com_client.c | 58 ++++++++++++++++------ 2 files changed, 51 insertions(+), 26 deletions(-) diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 2f2a5e1329c..b527e5bf98d 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -13675,11 +13675,11 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface) /* Cached UIA_BoundingRectanglePropertyId helper. */ hr = IUIAutomationElement_get_CachedBoundingRectangle(element, NULL); - todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); rect.left = rect.top = rect.bottom = rect.right = 1; hr = IUIAutomationElement_get_CachedBoundingRectangle(element, &rect); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ok(rect.left == 1, "Unexpected rect left %ld\n", rect.left); ok(rect.top == 1, "Unexpected rect top %ld\n", rect.top); ok(rect.right == 1, "Unexpected rect right %ld\n", rect.right); @@ -13687,17 +13687,16 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface) rect.left = rect.top = rect.bottom = rect.right = 1; hr = IUIAutomationElement_get_CachedBoundingRectangle(element2, &rect); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!rect.left, "Unexpected rect left %ld\n", rect.left); - todo_wine ok(!rect.top, "Unexpected rect top %ld\n", rect.top); - todo_wine ok(!rect.right, "Unexpected rect right %ld\n", rect.right); - todo_wine ok(!rect.bottom, "Unexpected rect bottom %ld\n", rect.bottom); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!rect.left, "Unexpected rect left %ld\n", rect.left); + ok(!rect.top, "Unexpected rect top %ld\n", rect.top); + ok(!rect.right, "Unexpected rect right %ld\n", rect.right); + ok(!rect.bottom, "Unexpected rect bottom %ld\n", rect.bottom); memset(&rect, 0, sizeof(rect)); hr = IUIAutomationElement_get_CachedBoundingRectangle(element3, &rect); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - check_uia_rect_rect_val(&rect, &Provider.bounds_rect); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + check_uia_rect_rect_val(&rect, &Provider.bounds_rect); IUIAutomationElement_Release(element3); IUIAutomationElement_Release(element2); diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index d383abe0d9b..5c0d0cd0b9e 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -2312,6 +2312,32 @@ static HRESULT WINAPI uia_element_get_CurrentItemStatus(IUIAutomationElement9 *i return E_NOTIMPL; } +static void uia_variant_rect_to_rect(VARIANT *v, RECT *ret_val) +{ + double *vals; + HRESULT hr; + + memset(ret_val, 0, sizeof(*ret_val)); + if (V_VT(v) != (VT_R8 | VT_ARRAY)) + return; + + hr = SafeArrayAccessData(V_ARRAY(v), (void **)&vals); + if (FAILED(hr)) + { + WARN("SafeArrayAccessData failed with hr %#lx\n", hr); + return; + } + + ret_val->left = vals[0]; + ret_val->top = vals[1]; + ret_val->right = ret_val->left + vals[2]; + ret_val->bottom = ret_val->top + vals[3]; + + hr = SafeArrayUnaccessData(V_ARRAY(v)); + if (FAILED(hr)) + WARN("SafeArrayUnaccessData failed with hr %#lx\n", hr); +} + static HRESULT WINAPI uia_element_get_CurrentBoundingRectangle(IUIAutomationElement9 *iface, RECT *ret_val) { struct uia_element *element = impl_from_IUIAutomationElement9(iface); @@ -2320,22 +2346,9 @@ static HRESULT WINAPI uia_element_get_CurrentBoundingRectangle(IUIAutomationElem TRACE("%p, %p\n", element, ret_val); - memset(ret_val, 0, sizeof(*ret_val)); VariantInit(&v); hr = UiaGetPropertyValue(element->node, UIA_BoundingRectanglePropertyId, &v); - if (SUCCEEDED(hr) && V_VT(&v) == (VT_R8 | VT_ARRAY)) - { - double vals[4]; - LONG idx; - - for (idx = 0; idx < ARRAY_SIZE(vals); idx++) - SafeArrayGetElement(V_ARRAY(&v), &idx, &vals[idx]); - - ret_val->left = vals[0]; - ret_val->top = vals[1]; - ret_val->right = ret_val->left + vals[2]; - ret_val->bottom = ret_val->top + vals[3]; - } + uia_variant_rect_to_rect(&v, ret_val); VariantClear(&v); return hr; @@ -2588,8 +2601,21 @@ static HRESULT WINAPI uia_element_get_CachedItemStatus(IUIAutomationElement9 *if static HRESULT WINAPI uia_element_get_CachedBoundingRectangle(IUIAutomationElement9 *iface, RECT *ret_val) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + const int prop_id = UIA_BoundingRectanglePropertyId; + struct uia_cache_property *cache_prop = NULL; + + TRACE("%p, %p\n", iface, ret_val); + + if (!ret_val) + return E_POINTER; + + if (!(cache_prop = bsearch(&prop_id, element->cached_props, element->cached_props_count, sizeof(*cache_prop), + uia_cached_property_id_compare))) + return E_INVALIDARG; + + uia_variant_rect_to_rect(&cache_prop->prop_val, ret_val); + return S_OK; } static HRESULT WINAPI uia_element_get_CachedLabeledBy(IUIAutomationElement9 *iface, IUIAutomationElement **ret_val)