1
0
mirror of https://github.com/wine-mirror/wine synced 2024-07-01 07:14:31 +00:00

uiautomationcore: Implement IUIAutomationElement::get_CurrentBoundingRectangle.

Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
Connor McAdams 2023-02-03 12:37:41 -05:00 committed by Alexandre Julliard
parent c31e531318
commit ba960ed499
2 changed files with 128 additions and 4 deletions

View File

@ -4968,6 +4968,34 @@ static const struct prov_method_sequence get_bounding_rect_seq[] = {
{ 0 }
};
static const struct prov_method_sequence get_bounding_rect_seq2[] = {
{ &Provider, PROV_GET_PROPERTY_VALUE },
NODE_CREATE_SEQ(&Provider_child),
{ &Provider_child, FRAG_GET_BOUNDING_RECT },
/*
* Win10v21H2+ and above call these, attempting to get the fragment root's
* HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
*/
{ &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
{ &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
{ &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
{ 0 }
};
static const struct prov_method_sequence get_bounding_rect_seq3[] = {
{ &Provider_child, FRAG_GET_BOUNDING_RECT },
/*
* Win10v21H2+ and above call these, attempting to get the fragment root's
* HWND. I'm guessing this is an attempt to get the HWND's DPI for DPI scaling.
*/
{ &Provider_child, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
{ &Provider, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL },
{ &Provider, PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */
{ &Provider, FRAG_GET_FRAGMENT_ROOT, METHOD_OPTIONAL },
{ 0 }
};
static const struct prov_method_sequence get_empty_bounding_rect_seq[] = {
{ &Provider_child, FRAG_GET_BOUNDING_RECT },
{ 0 }
@ -5028,6 +5056,18 @@ static void check_uia_rect_val_(VARIANT *v, struct UiaRect *rect, const char *fi
ok_(file, line)(tmp[3] == rect->height, "Unexpected height value %f, expected %f\n", tmp[3], rect->height);
}
#define check_uia_rect_rect_val( rect, uia_rect ) \
check_uia_rect_rect_val_( (rect), (uia_rect), __FILE__, __LINE__)
static void check_uia_rect_rect_val_(RECT *rect, struct UiaRect *uia_rect, const char *file, int line)
{
ok_(file, line)(rect->left == (LONG)uia_rect->left, "Unexpected left value %ld, expected %ld\n", rect->left, (LONG)uia_rect->left);
ok_(file, line)(rect->top == (LONG)uia_rect->top, "Unexpected top value %ld, expected %ld\n", rect->top, (LONG)uia_rect->top);
ok_(file, line)(rect->right == (LONG)(uia_rect->left + uia_rect->width), "Unexpected right value %ld, expected %ld\n", rect->right,
(LONG)(uia_rect->left + uia_rect->width));
ok_(file, line)(rect->bottom == (LONG)(uia_rect->top + uia_rect->height), "Unexpected bottom value %ld, expected %ld\n", rect->bottom,
(LONG)(uia_rect->top + uia_rect->height));
}
static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, VARIANT *v, BOOL from_com)
{
LONG idx;
@ -9793,11 +9833,13 @@ static void test_Element_GetPropertyValue(IUIAutomation *uia_iface)
HWND hwnd = create_test_hwnd("test_Element_GetPropertyValue class");
const struct uia_element_property *elem_prop;
struct Provider_prop_override prop_override;
IUIAutomationElement *element;
IUIAutomationElement *element, *element2;
int i, prop_id, tmp_int;
struct UiaRect uia_rect;
IUnknown *unk_ns;
BSTR tmp_bstr;
HRESULT hr;
RECT rect;
VARIANT v;
element = create_test_element_from_hwnd(uia_iface, hwnd, TRUE);
@ -9902,9 +9944,68 @@ static void test_Element_GetPropertyValue(IUIAutomation *uia_iface)
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);
Provider.ret_invalid_prop_type = FALSE;
initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
ok_method_sequence(get_prop_invalid_type_seq, NULL);
/*
* 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 UIA_BoundingRectanglePropertyId tests for Win7\n");
goto exit;
}
/*
* IUIAutomationElement_get_CurrentBoundingRectangle/UIA_BoundRectanglePropertyId tests.
*/
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element, UIA_LabeledByPropertyId, TRUE, &v);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider.ref);
hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IUIAutomationElement, (void **)&element2);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(!!element2, "element2 == NULL\n");
VariantClear(&v);
/* Non-empty bounding rectangle, will return a VT_R8 SAFEARRAY. */
set_uia_rect(&uia_rect, 0, 0, 50, 50);
Provider_child.bounds_rect = uia_rect;
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
check_uia_rect_val(&v, &uia_rect);
VariantClear(&v);
ok_method_sequence(get_bounding_rect_seq2, "get_bounding_rect_seq2");
hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
check_uia_rect_rect_val(&rect, &uia_rect);
memset(&rect, 0, sizeof(rect));
ok_method_sequence(get_bounding_rect_seq3, "get_bounding_rect_seq3");
/* Empty bounding rectangle will return ReservedNotSupportedValue. */
set_uia_rect(&uia_rect, 0, 0, 0, 0);
Provider_child.bounds_rect = uia_rect;
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_BoundingRectanglePropertyId, TRUE, &v);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(V_VT(&v) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
ok(V_UNKNOWN(&v) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v));
VariantClear(&v);
ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
/* Returns an all 0 rect. */
hr = IUIAutomationElement_get_CurrentBoundingRectangle(element2, &rect);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
check_uia_rect_rect_val(&rect, &uia_rect);
ok_method_sequence(get_empty_bounding_rect_seq, "get_empty_bounding_rect_seq");
IUIAutomationElement_Release(element2);
ok(Provider_child.ref == 1, "Unexpected refcnt %ld\n", Provider_child.ref);
initialize_provider(&Provider_child, ProviderOptions_ServerSideProvider, NULL, FALSE);
exit:
IUIAutomationElement_Release(element);
ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);

View File

@ -402,8 +402,31 @@ static HRESULT WINAPI uia_element_get_CurrentItemStatus(IUIAutomationElement9 *i
static HRESULT WINAPI uia_element_get_CurrentBoundingRectangle(IUIAutomationElement9 *iface, RECT *ret_val)
{
FIXME("%p: stub\n", iface);
return E_NOTIMPL;
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
HRESULT hr;
VARIANT v;
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];
}
VariantClear(&v);
return hr;
}
static HRESULT WINAPI uia_element_get_CurrentLabeledBy(IUIAutomationElement9 *iface, IUIAutomationElement **ret_val)