mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 12:47:16 +00:00
uiautomationcore: Add support for caching property values in UiaGetUpdatedCache.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
0c1dcfd354
commit
b9410e8c39
|
@ -1140,6 +1140,8 @@ static struct Provider
|
|||
} Provider, Provider2, Provider_child, Provider_child2;
|
||||
static struct Provider Provider_hwnd, Provider_nc, Provider_proxy, Provider_proxy2, Provider_override;
|
||||
static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links);
|
||||
static void set_provider_prop_override(struct Provider *prov, struct Provider_prop_override *override, int count);
|
||||
static void set_property_override(struct Provider_prop_override *override, int prop_id, VARIANT *val);
|
||||
|
||||
static const WCHAR *uia_bstr_prop_str = L"uia-string";
|
||||
static const ULONG uia_i4_prop_val = 0xdeadbeef;
|
||||
|
@ -7577,26 +7579,38 @@ static const struct prov_method_sequence cache_req_seq6[] = {
|
|||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct prov_method_sequence cache_req_seq7[] = {
|
||||
{ &Provider, FRAG_GET_RUNTIME_ID },
|
||||
{ &Provider, PROV_GET_PROPERTY_VALUE }, /* UIA_IsControlElementPropertyId. */
|
||||
{ &Provider, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId. */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
static const struct UiaCondition UiaTrueCondition = { ConditionType_True };
|
||||
static const struct UiaCondition UiaFalseCondition = { ConditionType_False };
|
||||
static void test_UiaGetUpdatedCache(void)
|
||||
{
|
||||
LONG exp_lbound[2], exp_elems[2], idx[2], i;
|
||||
struct Provider_prop_override prop_override;
|
||||
struct node_provider_desc exp_node_desc[2];
|
||||
struct UiaPropertyCondition prop_cond;
|
||||
struct UiaAndOrCondition and_or_cond;
|
||||
LONG exp_lbound[2], exp_elems[2], i;
|
||||
struct UiaCacheRequest cache_req;
|
||||
struct UiaCondition *cond_arr[2];
|
||||
struct UiaNotCondition not_cond;
|
||||
VARIANT v, v_arr[2];
|
||||
SAFEARRAY *out_req;
|
||||
IUnknown *unk_ns;
|
||||
BSTR tree_struct;
|
||||
int prop_ids[2];
|
||||
HUIANODE node;
|
||||
HRESULT hr;
|
||||
VARIANT v;
|
||||
|
||||
CoInitializeEx(NULL, COINIT_MULTITHREADED);
|
||||
|
||||
hr = UiaGetReservedNotSupportedValue(&unk_ns);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(exp_node_desc); i++)
|
||||
init_node_provider_desc(&exp_node_desc[i], GetCurrentProcessId(), NULL);
|
||||
|
||||
|
@ -8018,9 +8032,112 @@ static void test_UiaGetUpdatedCache(void)
|
|||
Provider.prop_override = NULL;
|
||||
Provider.prop_override_count = 0;
|
||||
|
||||
/*
|
||||
* Tests for property value caching.
|
||||
*/
|
||||
prop_ids[0] = UIA_RuntimeIdPropertyId;
|
||||
/* Invalid property ID, no work will be done. */
|
||||
prop_ids[1] = 1;
|
||||
tree_struct = NULL; out_req = NULL;
|
||||
set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
|
||||
hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
|
||||
ok(hr == E_INVALIDARG, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!out_req, "out_req != NULL\n");
|
||||
ok(!tree_struct, "tree_struct != NULL\n");
|
||||
|
||||
/*
|
||||
* Retrieve values for UIA_RuntimeIdPropertyId and
|
||||
* UIA_IsControlElementPropertyId in the returned cache.
|
||||
*/
|
||||
prop_ids[0] = UIA_RuntimeIdPropertyId;
|
||||
prop_ids[1] = UIA_IsControlElementPropertyId;
|
||||
initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
|
||||
init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
|
||||
add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
|
||||
|
||||
tree_struct = NULL; out_req = NULL;
|
||||
set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
|
||||
hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!out_req, "out_req == NULL\n");
|
||||
ok(!!tree_struct, "tree_struct == NULL\n");
|
||||
|
||||
exp_lbound[0] = exp_lbound[1] = 0;
|
||||
exp_elems[0] = 1;
|
||||
exp_elems[1] = 3;
|
||||
test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
|
||||
ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
|
||||
|
||||
idx[0] = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
|
||||
{
|
||||
idx[1] = 1 + i;
|
||||
VariantInit(&v_arr[i]);
|
||||
hr = SafeArrayGetElement(out_req, idx, &v_arr[i]);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
||||
}
|
||||
|
||||
ok(V_VT(&v_arr[0]) == VT_UNKNOWN, "Unexpected vt %d\n", V_VT(&v));
|
||||
ok(V_UNKNOWN(&v_arr[0]) == unk_ns, "unexpected IUnknown %p\n", V_UNKNOWN(&v_arr[0]));
|
||||
VariantClear(&v_arr[0]);
|
||||
|
||||
ok(check_variant_bool(&v_arr[1], TRUE), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr[1]));
|
||||
VariantClear(&v_arr[1]);
|
||||
|
||||
ok_method_sequence(cache_req_seq7, "cache_req_seq7");
|
||||
SafeArrayDestroy(out_req);
|
||||
SysFreeString(tree_struct);
|
||||
|
||||
/*
|
||||
* Again, but return a valid runtime ID and a different value for
|
||||
* UIA_IsControlElementPropertyId.
|
||||
*/
|
||||
V_VT(&v) = VT_BOOL;
|
||||
V_BOOL(&v) = VARIANT_FALSE;
|
||||
set_property_override(&prop_override, UIA_IsControlElementPropertyId, &v);
|
||||
set_provider_prop_override(&Provider, &prop_override, 1);
|
||||
Provider.runtime_id[0] = Provider.runtime_id[1] = 0xdeadbeef;
|
||||
init_node_provider_desc(&exp_node_desc[0], GetCurrentProcessId(), NULL);
|
||||
add_provider_desc(&exp_node_desc[0], L"Main", L"Provider", TRUE);
|
||||
|
||||
tree_struct = NULL; out_req = NULL;
|
||||
set_cache_request(&cache_req, NULL, TreeScope_Element, prop_ids, ARRAY_SIZE(prop_ids), NULL, 0, AutomationElementMode_Full);
|
||||
hr = UiaGetUpdatedCache(node, &cache_req, NormalizeState_None, NULL, &out_req, &tree_struct);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!out_req, "out_req == NULL\n");
|
||||
ok(!!tree_struct, "tree_struct == NULL\n");
|
||||
|
||||
exp_lbound[0] = exp_lbound[1] = 0;
|
||||
exp_elems[0] = 1;
|
||||
exp_elems[1] = 3;
|
||||
test_cache_req_sa(out_req, exp_lbound, exp_elems, exp_node_desc);
|
||||
ok(!wcscmp(tree_struct, L"P)"), "tree structure %s\n", debugstr_w(tree_struct));
|
||||
|
||||
idx[0] = 0;
|
||||
for (i = 0; i < ARRAY_SIZE(prop_ids); i++)
|
||||
{
|
||||
idx[1] = 1 + i;
|
||||
VariantInit(&v_arr[i]);
|
||||
hr = SafeArrayGetElement(out_req, idx, &v_arr[i]);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
||||
}
|
||||
|
||||
ok(V_VT(&v_arr[0]) == (VT_I4 | VT_ARRAY), "Unexpected vt %d\n", V_VT(&v_arr[0]));
|
||||
check_runtime_id(Provider.runtime_id, ARRAY_SIZE(Provider.runtime_id), V_ARRAY(&v_arr[0]));
|
||||
VariantClear(&v_arr[0]);
|
||||
|
||||
ok(check_variant_bool(&v_arr[1], FALSE), "V_BOOL(&v) = %#x\n", V_BOOL(&v_arr[1]));
|
||||
VariantClear(&v_arr[1]);
|
||||
|
||||
ok_method_sequence(cache_req_seq7, "cache_req_seq7");
|
||||
SafeArrayDestroy(out_req);
|
||||
SysFreeString(tree_struct);
|
||||
|
||||
ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
|
||||
ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
|
||||
initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
|
||||
|
||||
IUnknown_Release(unk_ns);
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
|
|
|
@ -2787,6 +2787,7 @@ HRESULT WINAPI UiaGetUpdatedCache(HUIANODE huianode, struct UiaCacheRequest *cac
|
|||
LONG idx[2];
|
||||
HRESULT hr;
|
||||
VARIANT v;
|
||||
int i;
|
||||
|
||||
TRACE("(%p, %p, %u, %p, %p, %p)\n", huianode, cache_req, normalize_state, normalize_cond, out_req, tree_struct);
|
||||
|
||||
|
@ -2802,6 +2803,18 @@ HRESULT WINAPI UiaGetUpdatedCache(HUIANODE huianode, struct UiaCacheRequest *cac
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
if (cache_req->cPatterns && cache_req->pPatterns)
|
||||
FIXME("Pattern caching currently unimplemented\n");
|
||||
|
||||
if (cache_req->cProperties && cache_req->pProperties)
|
||||
{
|
||||
for (i = 0; i < cache_req->cProperties; i++)
|
||||
{
|
||||
if (!uia_prop_info_from_id(cache_req->pProperties[i]))
|
||||
return E_INVALIDARG;
|
||||
}
|
||||
}
|
||||
|
||||
switch (normalize_state)
|
||||
{
|
||||
case NormalizeState_None:
|
||||
|
@ -2834,7 +2847,8 @@ HRESULT WINAPI UiaGetUpdatedCache(HUIANODE huianode, struct UiaCacheRequest *cac
|
|||
}
|
||||
}
|
||||
|
||||
sabound[0].cElements = sabound[1].cElements = 1;
|
||||
sabound[0].cElements = 1;
|
||||
sabound[1].cElements = 1 + cache_req->cProperties;
|
||||
sabound[0].lLbound = sabound[1].lLbound = 0;
|
||||
if (!(sa = SafeArrayCreate(VT_VARIANT, 2, sabound)))
|
||||
{
|
||||
|
@ -2852,6 +2866,28 @@ HRESULT WINAPI UiaGetUpdatedCache(HUIANODE huianode, struct UiaCacheRequest *cac
|
|||
return hr;
|
||||
}
|
||||
|
||||
idx[0] = 0;
|
||||
VariantClear(&v);
|
||||
for (i = 0; i < cache_req->cProperties; i++)
|
||||
{
|
||||
hr = UiaGetPropertyValue(huianode, cache_req->pProperties[i], &v);
|
||||
/* Don't fail on unimplemented properties. */
|
||||
if (FAILED(hr) && hr != E_NOTIMPL)
|
||||
{
|
||||
SafeArrayDestroy(sa);
|
||||
return hr;
|
||||
}
|
||||
|
||||
idx[1] = 1 + i;
|
||||
hr = SafeArrayPutElement(sa, idx, &v);
|
||||
VariantClear(&v);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
SafeArrayDestroy(sa);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AddRef huianode since we're returning a reference to the same node we
|
||||
* passed in, rather than creating a new one.
|
||||
|
|
Loading…
Reference in a new issue