-- v2: uiautomationcore: Implement IUIAutomationElement::get_CachedBoundingRectangle. uiautomationcore: Implement IUIAutomationElement::get_CachedName. uiautomationcore: Implement IUIAutomationElement::get_CachedIsKeyboardFocusable. uiautomationcore: Implement IUIAutomationElement::get_CachedHasKeyboardFocus. uiautomationcore: Implement IUIAutomationElement::get_CachedControlType. uiautomationcore/tests: Add tests for cached value helper functions in the COM API.
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 177 ++++++++++++++++++++- 1 file changed, 176 insertions(+), 1 deletion(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index f34f020b814..1fd734bff65 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -13310,13 +13310,19 @@ static const struct prov_method_sequence get_cached_prop_val_seq3[] = {
static void test_Element_cache_methods(IUIAutomation *uia_iface) { + static const int cache_test_props[] = { UIA_IsKeyboardFocusablePropertyId, UIA_NamePropertyId, UIA_ControlTypePropertyId, + UIA_BoundingRectanglePropertyId, UIA_HasKeyboardFocusPropertyId, }; HWND hwnd = create_test_hwnd("test_Element_cache_methods class"); IUIAutomationElement *element, *element2, *element3; + struct Provider_prop_override prop_override; IUIAutomationCacheRequest *cache_req; IUIAutomationElementArray *elem_arr; - int tmp_rt_id[2], i, len; + int tmp_rt_id[2], i, len, tmp_int; IUnknown *unk_ns; + BSTR tmp_bstr; + BOOL tmp_bool; HRESULT hr; + RECT rect; VARIANT v;
element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE); @@ -13534,6 +13540,175 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface) ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref); IUnknown_Release(unk_ns);
+ /* + * Windows 7 will call get_FragmentRoot in an endless loop until the fragment root returns an HWND. + * It's the only version with this behavior. + */ + if (!UiaLookupId(AutomationIdentifierType_Property, &OptimizeForVisualContent_Property_GUID)) + { + win_skip("Skipping cached UIA_BoundingRectanglePropertyId tests for Win7\n"); + goto exit; + } + + /* + * Cached property value helper function tests. + */ + element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE); + method_sequences_enabled = FALSE; + + /* + * element has no cached values, element2 has cached values but they're + * all the equivalent of VT_EMPTY, element3 has valid cached values. + */ + cache_req = NULL; + hr = IUIAutomation_CreateCacheRequest(uia_iface, &cache_req); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!cache_req, "cache_req == NULL\n"); + + for (i = 0; i < ARRAY_SIZE(cache_test_props); i++) + { + hr = IUIAutomationCacheRequest_AddProperty(cache_req, cache_test_props[i]); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } + + /* element2, invalid values for all cached properties. */ + element2 = NULL; + Provider.ret_invalid_prop_type = TRUE; + set_uia_rect(&Provider.bounds_rect, 0, 0, 0, 0); + hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element2); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!element2, "element2 == NULL\n"); + Provider.ret_invalid_prop_type = FALSE; + + /* element3, valid values for all cached properties. */ + V_VT(&v) = VT_I4; + V_I4(&v) = UIA_HyperlinkControlTypeId; + set_property_override(&prop_override, UIA_ControlTypePropertyId, &v); + set_provider_prop_override(&Provider, &prop_override, 1); + set_uia_rect(&Provider.bounds_rect, 0, 0, 50, 50); + + element3 = NULL; + hr = IUIAutomationElement_BuildUpdatedCache(element, cache_req, &element3); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!element3, "element3 == NULL\n"); + set_provider_prop_override(&Provider, NULL, 0); + + IUIAutomationCacheRequest_Release(cache_req); + + /* Cached UIA_HasKeyboardFocusPropertyId helper. */ + hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + tmp_bool = 0xdeadbeef; + hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element, &tmp_bool); + todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(tmp_bool == 0xdeadbeef, "Unexpected tmp_bool %d\n", tmp_bool); + + tmp_bool = 0xdeadbeef; + hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element2, &tmp_bool); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(!tmp_bool, "tmp_bool != FALSE\n"); + + tmp_bool = FALSE; + hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element3, &tmp_bool); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(!!tmp_bool, "tmp_bool == FALSE\n"); + + /* Cached UIA_IsKeyboardFocusablePropertyId helper. */ + hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + tmp_bool = 0xdeadbeef; + hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element, &tmp_bool); + todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(tmp_bool == 0xdeadbeef, "Unexpected tmp_bool %d\n", tmp_bool); + + tmp_bool = 0xdeadbeef; + hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element2, &tmp_bool); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(!tmp_bool, "tmp_bool != FALSE\n"); + + tmp_bool = FALSE; + hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element3, &tmp_bool); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(!!tmp_bool, "tmp_bool == FALSE\n"); + + /* Cached UIA_NamePropertyId helper. */ + hr = IUIAutomationElement_get_CachedName(element, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + tmp_bstr = (void *)0xdeadbeef; + hr = IUIAutomationElement_get_CachedName(element, &tmp_bstr); + todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(tmp_bstr == (void *)0xdeadbeef, "Unexpected BSTR ptr %p\n", tmp_bstr); + + tmp_bstr = NULL; + hr = IUIAutomationElement_get_CachedName(element2, &tmp_bstr); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr)); + SysFreeString(tmp_bstr); + + tmp_bstr = NULL; + hr = IUIAutomationElement_get_CachedName(element3, &tmp_bstr); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (SUCCEEDED(hr)) + ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr)); + SysFreeString(tmp_bstr); + + /* Cached UIA_ControlTypePropertyId. */ + hr = IUIAutomationElement_get_CachedControlType(element, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + + tmp_int = 0xdeadbeef; + hr = IUIAutomationElement_get_CachedControlType(element, &tmp_int); + todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(tmp_int == 0xdeadbeef, "Unexpected control type %#x\n", tmp_int); + + tmp_int = 0; + hr = IUIAutomationElement_get_CachedControlType(element2, &tmp_int); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int); + + tmp_int = 0; + hr = IUIAutomationElement_get_CachedControlType(element3, &tmp_int); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int); + + /* Cached UIA_BoundingRectanglePropertyId helper. */ + hr = IUIAutomationElement_get_CachedBoundingRectangle(element, NULL); + todo_wine 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(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); + ok(rect.bottom == 1, "Unexpected rect bottom %ld\n", rect.bottom); + + 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); + + 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); + + IUIAutomationElement_Release(element3); + IUIAutomationElement_Release(element2); + IUIAutomationElement_Release(element); + + set_uia_rect(&Provider.bounds_rect, 0, 0, 0, 0); + method_sequences_enabled = TRUE; + +exit: DestroyWindow(hwnd); UnregisterClassA("test_Element_cache_methods class", NULL); }
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 12 +++--- dlls/uiautomationcore/uia_com_client.c | 43 ++++++++++++++++------ 2 files changed, 37 insertions(+), 18 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 1fd734bff65..4a5bca74b6a 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -13658,22 +13658,22 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface)
/* Cached UIA_ControlTypePropertyId. */ hr = IUIAutomationElement_get_CachedControlType(element, NULL); - todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
tmp_int = 0xdeadbeef; hr = IUIAutomationElement_get_CachedControlType(element, &tmp_int); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ok(tmp_int == 0xdeadbeef, "Unexpected control type %#x\n", tmp_int);
tmp_int = 0; hr = IUIAutomationElement_get_CachedControlType(element2, &tmp_int); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(tmp_int == UIA_CustomControlTypeId, "Unexpected control type %#x\n", tmp_int);
tmp_int = 0; hr = IUIAutomationElement_get_CachedControlType(element3, &tmp_int); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(tmp_int == UIA_HyperlinkControlTypeId, "Unexpected control type %#x\n", tmp_int);
/* Cached UIA_BoundingRectanglePropertyId helper. */ hr = IUIAutomationElement_get_CachedBoundingRectangle(element, NULL); diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index d138d4ed919..e47c64c479b 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -2143,27 +2143,33 @@ static HRESULT WINAPI uia_element_get_CurrentProcessId(IUIAutomationElement9 *if return E_NOTIMPL; }
+static void uia_elem_get_control_type(VARIANT *v, CONTROLTYPEID *ret_val) +{ + const struct uia_control_type_info *info = NULL; + + *ret_val = UIA_CustomControlTypeId; + if (V_VT(v) != VT_I4) + return; + + if ((info = uia_control_type_info_from_id(V_I4(v)))) + *ret_val = info->control_type_id; + else + WARN("Provider returned invalid control type ID %ld\n", V_I4(v)); +} + static HRESULT WINAPI uia_element_get_CurrentControlType(IUIAutomationElement9 *iface, CONTROLTYPEID *ret_val) { struct uia_element *element = impl_from_IUIAutomationElement9(iface); - const struct uia_control_type_info *control_type_info = NULL; HRESULT hr; VARIANT v;
TRACE("%p, %p\n", iface, ret_val);
VariantInit(&v); - *ret_val = UIA_CustomControlTypeId; hr = UiaGetPropertyValue(element->node, UIA_ControlTypePropertyId, &v); - if (SUCCEEDED(hr) && V_VT(&v) == VT_I4) - { - if ((control_type_info = uia_control_type_info_from_id(V_I4(&v)))) - *ret_val = control_type_info->control_type_id; - else - WARN("Provider returned invalid control type ID %ld\n", V_I4(&v)); - } - + uia_elem_get_control_type(&v, ret_val); VariantClear(&v); + return hr; }
@@ -2393,8 +2399,21 @@ static HRESULT WINAPI uia_element_get_CachedProcessId(IUIAutomationElement9 *ifa
static HRESULT WINAPI uia_element_get_CachedControlType(IUIAutomationElement9 *iface, CONTROLTYPEID *ret_val) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + const int prop_id = UIA_ControlTypePropertyId; + 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_elem_get_control_type(&cache_prop->prop_val, ret_val); + return S_OK; }
static HRESULT WINAPI uia_element_get_CachedLocalizedControlType(IUIAutomationElement9 *iface, BSTR *ret_val)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 12 ++++++------ dlls/uiautomationcore/uia_com_client.c | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 4a5bca74b6a..b3f4d2517f5 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -13597,22 +13597,22 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface)
/* Cached UIA_HasKeyboardFocusPropertyId helper. */ hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element, NULL); - todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
tmp_bool = 0xdeadbeef; hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element, &tmp_bool); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ok(tmp_bool == 0xdeadbeef, "Unexpected tmp_bool %d\n", tmp_bool);
tmp_bool = 0xdeadbeef; hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element2, &tmp_bool); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!tmp_bool, "tmp_bool != FALSE\n"); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!tmp_bool, "tmp_bool != FALSE\n");
tmp_bool = FALSE; hr = IUIAutomationElement_get_CachedHasKeyboardFocus(element3, &tmp_bool); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!tmp_bool, "tmp_bool == FALSE\n"); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!tmp_bool, "tmp_bool == FALSE\n");
/* Cached UIA_IsKeyboardFocusablePropertyId helper. */ hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element, NULL); diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index e47c64c479b..d949b3c0a92 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -2442,8 +2442,21 @@ static HRESULT WINAPI uia_element_get_CachedAccessKey(IUIAutomationElement9 *ifa
static HRESULT WINAPI uia_element_get_CachedHasKeyboardFocus(IUIAutomationElement9 *iface, BOOL *ret_val) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + const int prop_id = UIA_HasKeyboardFocusPropertyId; + 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; + + *ret_val = ((V_VT(&cache_prop->prop_val) == VT_BOOL) && (V_BOOL(&cache_prop->prop_val) == VARIANT_TRUE)); + return S_OK; }
static HRESULT WINAPI uia_element_get_CachedIsKeyboardFocusable(IUIAutomationElement9 *iface, BOOL *ret_val)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 14 ++++++-------- dlls/uiautomationcore/uia_com_client.c | 21 +++++++++++++++++++-- 2 files changed, 25 insertions(+), 10 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index 6eb1f204dbb..2f2a5e1329c 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -13635,25 +13635,23 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface)
/* Cached UIA_NamePropertyId helper. */ hr = IUIAutomationElement_get_CachedName(element, NULL); - todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
tmp_bstr = (void *)0xdeadbeef; hr = IUIAutomationElement_get_CachedName(element, &tmp_bstr); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ok(tmp_bstr == (void *)0xdeadbeef, "Unexpected BSTR ptr %p\n", tmp_bstr);
tmp_bstr = NULL; hr = IUIAutomationElement_get_CachedName(element2, &tmp_bstr); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(tmp_bstr, L""), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr)); SysFreeString(tmp_bstr);
tmp_bstr = NULL; hr = IUIAutomationElement_get_CachedName(element3, &tmp_bstr); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (SUCCEEDED(hr)) - ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!lstrcmpW(tmp_bstr, uia_bstr_prop_str), "Unexpected BSTR %s\n", wine_dbgstr_w(tmp_bstr)); SysFreeString(tmp_bstr);
/* Cached UIA_ControlTypePropertyId. */ diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index d517b680bdd..d383abe0d9b 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -2424,8 +2424,25 @@ static HRESULT WINAPI uia_element_get_CachedLocalizedControlType(IUIAutomationEl
static HRESULT WINAPI uia_element_get_CachedName(IUIAutomationElement9 *iface, BSTR *ret_val) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + struct uia_cache_property *cache_prop = NULL; + const int prop_id = UIA_NamePropertyId; + + 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; + + if ((V_VT(&cache_prop->prop_val) == VT_BSTR) && V_BSTR(&cache_prop->prop_val)) + *ret_val = SysAllocString(V_BSTR(&cache_prop->prop_val)); + else + *ret_val = SysAllocString(L""); + + return S_OK; }
static HRESULT WINAPI uia_element_get_CachedAcceleratorKey(IUIAutomationElement9 *iface, BSTR *ret_val)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- dlls/uiautomationcore/tests/uiautomation.c | 12 ++++++------ dlls/uiautomationcore/uia_com_client.c | 17 +++++++++++++++-- 2 files changed, 21 insertions(+), 8 deletions(-)
diff --git a/dlls/uiautomationcore/tests/uiautomation.c b/dlls/uiautomationcore/tests/uiautomation.c index b3f4d2517f5..6eb1f204dbb 100644 --- a/dlls/uiautomationcore/tests/uiautomation.c +++ b/dlls/uiautomationcore/tests/uiautomation.c @@ -13616,22 +13616,22 @@ static void test_Element_cache_methods(IUIAutomation *uia_iface)
/* Cached UIA_IsKeyboardFocusablePropertyId helper. */ hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element, NULL); - todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); + ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
tmp_bool = 0xdeadbeef; hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element, &tmp_bool); - todo_wine ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); + ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr); ok(tmp_bool == 0xdeadbeef, "Unexpected tmp_bool %d\n", tmp_bool);
tmp_bool = 0xdeadbeef; hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element2, &tmp_bool); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!tmp_bool, "tmp_bool != FALSE\n"); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!tmp_bool, "tmp_bool != FALSE\n");
tmp_bool = FALSE; hr = IUIAutomationElement_get_CachedIsKeyboardFocusable(element3, &tmp_bool); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - todo_wine ok(!!tmp_bool, "tmp_bool == FALSE\n"); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(!!tmp_bool, "tmp_bool == FALSE\n");
/* Cached UIA_NamePropertyId helper. */ hr = IUIAutomationElement_get_CachedName(element, NULL); diff --git a/dlls/uiautomationcore/uia_com_client.c b/dlls/uiautomationcore/uia_com_client.c index d949b3c0a92..d517b680bdd 100644 --- a/dlls/uiautomationcore/uia_com_client.c +++ b/dlls/uiautomationcore/uia_com_client.c @@ -2461,8 +2461,21 @@ static HRESULT WINAPI uia_element_get_CachedHasKeyboardFocus(IUIAutomationElemen
static HRESULT WINAPI uia_element_get_CachedIsKeyboardFocusable(IUIAutomationElement9 *iface, BOOL *ret_val) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + struct uia_element *element = impl_from_IUIAutomationElement9(iface); + const int prop_id = UIA_IsKeyboardFocusablePropertyId; + 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; + + *ret_val = ((V_VT(&cache_prop->prop_val) == VT_BOOL) && (V_BOOL(&cache_prop->prop_val) == VARIANT_TRUE)); + return S_OK; }
static HRESULT WINAPI uia_element_get_CachedIsEnabled(IUIAutomationElement9 *iface, BOOL *ret_val)
From: Connor McAdams cmcadams@codeweavers.com
Signed-off-by: Connor McAdams cmcadams@codeweavers.com --- 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)
On Wed Oct 18 11:27:48 2023 +0000, Connor McAdams wrote:
changed this line in [version 2 of the diff](/wine/wine/-/merge_requests/4128/diffs?diff_id=77168&start_sha=36b8e11f0d359c1c91004788045df2f78b523dcc#757856e6ad8b0244e53744faeb8594b6ec93b002_13580_13580)
Should be fixed now, good catch.
This merge request was approved by Esme Povirk.