mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-14 09:57:19 +00:00
uiautomationcore: Implement IUIAutomationElement::FindFirst{BuildCache}.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
fdb3c9f93a
commit
eeb098e7b6
|
@ -11418,62 +11418,53 @@ static void test_Element_Find(IUIAutomation *uia_iface)
|
||||||
* root is TRUE. element2 now represents Provider_child.
|
* root is TRUE. element2 now represents Provider_child.
|
||||||
*/
|
*/
|
||||||
hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_Children, condition, cache_req, &element2);
|
hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_Children, condition, cache_req, &element2);
|
||||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||||
todo_wine ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
|
ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
|
||||||
|
|
||||||
|
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
|
||||||
|
todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
|
check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
|
||||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
|
||||||
if (SUCCEEDED(hr))
|
VariantClear(&v);
|
||||||
{
|
|
||||||
check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
|
|
||||||
check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child", TRUE);
|
|
||||||
VariantClear(&v);
|
|
||||||
}
|
|
||||||
|
|
||||||
ok_method_sequence(find_seq4, "find_seq4");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element2)
|
ok_method_sequence(find_seq4, "find_seq4");
|
||||||
{
|
|
||||||
/*
|
|
||||||
* Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
|
|
||||||
* root is FALSE. Provider_child doesn't have a runtime id for UI
|
|
||||||
* Automation to use as a way to check if it has navigated back to the
|
|
||||||
* node that began the search, so it will get siblings.
|
|
||||||
*/
|
|
||||||
hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
|
|
||||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 2);
|
|
||||||
add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
|
|
||||||
set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
|
|
||||||
add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
|
|
||||||
|
|
||||||
test_uia_element_arr(element_arr, exp_elems, 2);
|
/*
|
||||||
ok_method_sequence(find_seq5, "find_seq5");
|
* Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
|
||||||
}
|
* root is FALSE. Provider_child doesn't have a runtime id for UI
|
||||||
|
* Automation to use as a way to check if it has navigated back to the
|
||||||
|
* node that began the search, so it will get siblings.
|
||||||
|
*/
|
||||||
|
hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
|
||||||
|
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||||
|
|
||||||
/*
|
set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 2);
|
||||||
* Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
|
add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
|
||||||
* root is FALSE. Provider_child now has a runtime ID, so we don't get
|
set_elem_desc(&exp_elems[1], &Provider_child2, NULL, GetCurrentProcessId(), 2, 1);
|
||||||
* its sibling.
|
add_provider_desc(&exp_elems[1].prov_desc, L"Main", L"Provider_child2", TRUE);
|
||||||
*/
|
|
||||||
Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
|
|
||||||
hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
|
|
||||||
IUIAutomationElement_Release(element2);
|
|
||||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
|
||||||
if (SUCCEEDED(hr))
|
|
||||||
{
|
|
||||||
set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
|
|
||||||
add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
|
|
||||||
|
|
||||||
test_uia_element_arr(element_arr, exp_elems, 1);
|
test_uia_element_arr(element_arr, exp_elems, 2);
|
||||||
ok_method_sequence(find_seq6, "find_seq6");
|
ok_method_sequence(find_seq5, "find_seq5");
|
||||||
}
|
|
||||||
initialize_provider_tree(FALSE);
|
/*
|
||||||
}
|
* Equivalent to: Maximum find depth of 0, find first is FALSE, exclude
|
||||||
|
* root is FALSE. Provider_child now has a runtime ID, so we don't get
|
||||||
|
* its sibling.
|
||||||
|
*/
|
||||||
|
Provider_child.runtime_id[0] = Provider_child.runtime_id[1] = 0xdeadbeef;
|
||||||
|
hr = IUIAutomationElement_FindAllBuildCache(element2, TreeScope_Element, condition, cache_req, &element_arr);
|
||||||
|
IUIAutomationElement_Release(element2);
|
||||||
|
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||||
|
|
||||||
|
set_elem_desc(&exp_elems[0], &Provider_child, NULL, GetCurrentProcessId(), 2, 1);
|
||||||
|
add_provider_desc(&exp_elems[0].prov_desc, L"Main", L"Provider_child", TRUE);
|
||||||
|
|
||||||
|
test_uia_element_arr(element_arr, exp_elems, 1);
|
||||||
|
ok_method_sequence(find_seq6, "find_seq6");
|
||||||
|
initialize_provider_tree(FALSE);
|
||||||
|
|
||||||
IUIAutomationCondition_Release(condition);
|
IUIAutomationCondition_Release(condition);
|
||||||
|
|
||||||
|
@ -11618,22 +11609,20 @@ static void test_Element_Find(IUIAutomation *uia_iface)
|
||||||
* to match our condition.
|
* to match our condition.
|
||||||
*/
|
*/
|
||||||
hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_SubTree, condition, cache_req, &element2);
|
hr = IUIAutomationElement_FindFirstBuildCache(element, TreeScope_SubTree, condition, cache_req, &element2);
|
||||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||||
todo_wine ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
|
ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
|
||||||
|
|
||||||
|
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
|
||||||
|
todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
|
check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
|
||||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
|
||||||
if (SUCCEEDED(hr))
|
VariantClear(&v);
|
||||||
{
|
|
||||||
check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
|
|
||||||
check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
|
|
||||||
VariantClear(&v);
|
|
||||||
}
|
|
||||||
|
|
||||||
IUIAutomationElement_Release(element2);
|
|
||||||
ok_method_sequence(find_seq11, "find_seq11");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IUIAutomationElement_Release(element2);
|
||||||
|
ok_method_sequence(find_seq11, "find_seq11");
|
||||||
initialize_provider_tree(FALSE);
|
initialize_provider_tree(FALSE);
|
||||||
|
|
||||||
IUIAutomationCondition_Release(condition);
|
IUIAutomationCondition_Release(condition);
|
||||||
|
@ -11688,23 +11677,20 @@ static void test_Element_Find(IUIAutomation *uia_iface)
|
||||||
set_provider_prop_override(&Provider_child_child, &prop_override, 1);
|
set_provider_prop_override(&Provider_child_child, &prop_override, 1);
|
||||||
|
|
||||||
hr = IUIAutomationElement_FindFirst(element, TreeScope_SubTree, condition, &element2);
|
hr = IUIAutomationElement_FindFirst(element, TreeScope_SubTree, condition, &element2);
|
||||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||||
todo_wine ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
|
ok(Provider_child_child2.ref == 2, "Unexpected refcnt %ld\n", Provider_child_child2.ref);
|
||||||
|
|
||||||
|
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
|
||||||
|
todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
||||||
if (SUCCEEDED(hr))
|
if (SUCCEEDED(hr))
|
||||||
{
|
{
|
||||||
hr = IUIAutomationElement_GetCurrentPropertyValueEx(element2, UIA_ProviderDescriptionPropertyId, TRUE, &v);
|
check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
|
||||||
todo_wine ok(hr == S_OK, "Unexpected hr %#lx\n", hr);
|
check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
|
||||||
if (SUCCEEDED(hr))
|
VariantClear(&v);
|
||||||
{
|
|
||||||
check_node_provider_desc_prefix(V_BSTR(&v), GetCurrentProcessId(), NULL);
|
|
||||||
check_node_provider_desc(V_BSTR(&v), L"Main", L"Provider_child_child2", TRUE);
|
|
||||||
VariantClear(&v);
|
|
||||||
}
|
|
||||||
|
|
||||||
IUIAutomationElement_Release(element2);
|
|
||||||
ok_method_sequence(element_find_seq2, "element_find_seq2");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IUIAutomationElement_Release(element2);
|
||||||
|
ok_method_sequence(element_find_seq2, "element_find_seq2");
|
||||||
initialize_provider_tree(TRUE);
|
initialize_provider_tree(TRUE);
|
||||||
|
|
||||||
IUIAutomationCondition_Release(condition);
|
IUIAutomationCondition_Release(condition);
|
||||||
|
|
|
@ -1110,8 +1110,23 @@ static HRESULT WINAPI uia_element_GetRuntimeId(IUIAutomationElement9 *iface, SAF
|
||||||
static HRESULT WINAPI uia_element_FindFirst(IUIAutomationElement9 *iface, enum TreeScope scope,
|
static HRESULT WINAPI uia_element_FindFirst(IUIAutomationElement9 *iface, enum TreeScope scope,
|
||||||
IUIAutomationCondition *condition, IUIAutomationElement **found)
|
IUIAutomationCondition *condition, IUIAutomationElement **found)
|
||||||
{
|
{
|
||||||
FIXME("%p: stub\n", iface);
|
IUIAutomationCacheRequest *cache_req;
|
||||||
return E_NOTIMPL;
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE("%p, %#x, %p, %p\n", iface, scope, condition, found);
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
return E_POINTER;
|
||||||
|
|
||||||
|
*found = NULL;
|
||||||
|
hr = create_uia_cache_request_iface(&cache_req);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = IUIAutomationElement9_FindFirstBuildCache(iface, scope, condition, cache_req, found);
|
||||||
|
IUIAutomationCacheRequest_Release(cache_req);
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI uia_element_FindAll(IUIAutomationElement9 *iface, enum TreeScope scope,
|
static HRESULT WINAPI uia_element_FindAll(IUIAutomationElement9 *iface, enum TreeScope scope,
|
||||||
|
@ -1136,13 +1151,93 @@ static HRESULT WINAPI uia_element_FindAll(IUIAutomationElement9 *iface, enum Tre
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT set_find_params_struct(struct UiaFindParams *params, IUIAutomationCondition *cond, int scope,
|
||||||
|
BOOL find_first)
|
||||||
|
{
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
hr = get_uia_condition_struct_from_iface(cond, ¶ms->pFindCondition);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
if (!scope || (scope & (~TreeScope_SubTree)))
|
||||||
|
return E_INVALIDARG;
|
||||||
|
|
||||||
|
params->FindFirst = find_first;
|
||||||
|
if (scope & TreeScope_Element)
|
||||||
|
params->ExcludeRoot = FALSE;
|
||||||
|
else
|
||||||
|
params->ExcludeRoot = TRUE;
|
||||||
|
|
||||||
|
if (scope & TreeScope_Descendants)
|
||||||
|
params->MaxDepth = -1;
|
||||||
|
else if (scope & TreeScope_Children)
|
||||||
|
params->MaxDepth = 1;
|
||||||
|
else
|
||||||
|
params->MaxDepth = 0;
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT create_uia_element_from_cache_req(IUIAutomationElement **iface, BOOL from_cui8,
|
static HRESULT create_uia_element_from_cache_req(IUIAutomationElement **iface, BOOL from_cui8,
|
||||||
struct UiaCacheRequest *cache_req, LONG start_idx, SAFEARRAY *req_data, BSTR tree_struct);
|
struct UiaCacheRequest *cache_req, LONG start_idx, SAFEARRAY *req_data, BSTR tree_struct);
|
||||||
static HRESULT WINAPI uia_element_FindFirstBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope,
|
static HRESULT WINAPI uia_element_FindFirstBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope,
|
||||||
IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **found)
|
IUIAutomationCondition *condition, IUIAutomationCacheRequest *cache_req, IUIAutomationElement **found)
|
||||||
{
|
{
|
||||||
FIXME("%p: stub\n", iface);
|
struct uia_element *element = impl_from_IUIAutomationElement9(iface);
|
||||||
return E_NOTIMPL;
|
LONG lbound_offsets, lbound_tree_structs, elems_count, offset_idx;
|
||||||
|
struct UiaFindParams find_params = { 0 };
|
||||||
|
struct UiaCacheRequest *cache_req_struct;
|
||||||
|
SAFEARRAY *sa, *tree_structs, *offsets;
|
||||||
|
IUIAutomationElement *elem;
|
||||||
|
BSTR tree_struct_str;
|
||||||
|
HRESULT hr;
|
||||||
|
|
||||||
|
TRACE("%p, %#x, %p, %p, %p\n", iface, scope, condition, cache_req, found);
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
return E_POINTER;
|
||||||
|
|
||||||
|
*found = elem = NULL;
|
||||||
|
hr = get_uia_cache_request_struct_from_iface(cache_req, &cache_req_struct);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
hr = set_find_params_struct(&find_params, condition, scope, TRUE);
|
||||||
|
if (FAILED(hr))
|
||||||
|
return hr;
|
||||||
|
|
||||||
|
sa = offsets = tree_structs = NULL;
|
||||||
|
hr = UiaFind(element->node, &find_params, cache_req_struct, &sa, &offsets, &tree_structs);
|
||||||
|
if (FAILED(hr) || !sa)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
hr = get_safearray_bounds(tree_structs, &lbound_tree_structs, &elems_count);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
hr = SafeArrayGetElement(tree_structs, &lbound_tree_structs, &tree_struct_str);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
hr = get_safearray_bounds(offsets, &lbound_offsets, &elems_count);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
hr = SafeArrayGetElement(offsets, &lbound_offsets, &offset_idx);
|
||||||
|
if (FAILED(hr))
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
hr = create_uia_element_from_cache_req(&elem, element->from_cui8, cache_req_struct, offset_idx, sa, tree_struct_str);
|
||||||
|
if (SUCCEEDED(hr))
|
||||||
|
*found = elem;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
SafeArrayDestroy(tree_structs);
|
||||||
|
SafeArrayDestroy(offsets);
|
||||||
|
SafeArrayDestroy(sa);
|
||||||
|
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT WINAPI uia_element_FindAllBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope,
|
static HRESULT WINAPI uia_element_FindAllBuildCache(IUIAutomationElement9 *iface, enum TreeScope scope,
|
||||||
|
@ -1168,25 +1263,10 @@ static HRESULT WINAPI uia_element_FindAllBuildCache(IUIAutomationElement9 *iface
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
hr = get_uia_condition_struct_from_iface(condition, &find_params.pFindCondition);
|
hr = set_find_params_struct(&find_params, condition, scope, FALSE);
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
if (!scope || (scope & (~TreeScope_SubTree)))
|
|
||||||
return E_INVALIDARG;
|
|
||||||
|
|
||||||
if (scope & TreeScope_Element)
|
|
||||||
find_params.ExcludeRoot = FALSE;
|
|
||||||
else
|
|
||||||
find_params.ExcludeRoot = TRUE;
|
|
||||||
|
|
||||||
if (scope & TreeScope_Descendants)
|
|
||||||
find_params.MaxDepth = -1;
|
|
||||||
else if (scope & TreeScope_Children)
|
|
||||||
find_params.MaxDepth = 1;
|
|
||||||
else
|
|
||||||
find_params.MaxDepth = 0;
|
|
||||||
|
|
||||||
sa = offsets = tree_structs = NULL;
|
sa = offsets = tree_structs = NULL;
|
||||||
hr = UiaFind(element->node, &find_params, cache_req_struct, &sa, &offsets, &tree_structs);
|
hr = UiaFind(element->node, &find_params, cache_req_struct, &sa, &offsets, &tree_structs);
|
||||||
if (FAILED(hr) || !sa)
|
if (FAILED(hr) || !sa)
|
||||||
|
|
Loading…
Reference in a new issue