Commit 163e9c5b authored by Connor McAdams's avatar Connor McAdams Committed by Alexandre Julliard

uiautomationcore: Implement NavigateDirection_{Previous/Next}Sibling for MSAA providers.

parent 66b6786e
...@@ -223,7 +223,7 @@ static HRESULT msaa_acc_get_parent(IAccessible *acc, IAccessible **parent) ...@@ -223,7 +223,7 @@ static HRESULT msaa_acc_get_parent(IAccessible *acc, IAccessible **parent)
#define DIR_FORWARD 0 #define DIR_FORWARD 0
#define DIR_REVERSE 1 #define DIR_REVERSE 1
static HRESULT msaa_acc_get_next_child(IAccessible *acc, LONG start_pos, LONG direction, static HRESULT msaa_acc_get_next_child(IAccessible *acc, LONG start_pos, LONG direction,
IAccessible **child, LONG *child_id, LONG *child_pos) IAccessible **child, LONG *child_id, LONG *child_pos, BOOL check_visible)
{ {
LONG child_count, cur_pos; LONG child_count, cur_pos;
IDispatch *disp; IDispatch *disp;
...@@ -246,7 +246,7 @@ static HRESULT msaa_acc_get_next_child(IAccessible *acc, LONG start_pos, LONG di ...@@ -246,7 +246,7 @@ static HRESULT msaa_acc_get_next_child(IAccessible *acc, LONG start_pos, LONG di
if (hr == S_FALSE) if (hr == S_FALSE)
{ {
if (!msaa_check_acc_state(acc, cid, STATE_SYSTEM_INVISIBLE)) if (!check_visible || !msaa_check_acc_state(acc, cid, STATE_SYSTEM_INVISIBLE))
{ {
*child = acc; *child = acc;
*child_id = *child_pos = cur_pos; *child_id = *child_pos = cur_pos;
...@@ -264,7 +264,7 @@ static HRESULT msaa_acc_get_next_child(IAccessible *acc, LONG start_pos, LONG di ...@@ -264,7 +264,7 @@ static HRESULT msaa_acc_get_next_child(IAccessible *acc, LONG start_pos, LONG di
break; break;
variant_init_i4(&cid, CHILDID_SELF); variant_init_i4(&cid, CHILDID_SELF);
if (!msaa_check_acc_state(acc_child, cid, STATE_SYSTEM_INVISIBLE)) if (!check_visible || !msaa_check_acc_state(acc_child, cid, STATE_SYSTEM_INVISIBLE))
{ {
*child = acc_child; *child = acc_child;
*child_id = CHILDID_SELF; *child_id = CHILDID_SELF;
...@@ -287,6 +287,86 @@ static HRESULT msaa_acc_get_next_child(IAccessible *acc, LONG start_pos, LONG di ...@@ -287,6 +287,86 @@ static HRESULT msaa_acc_get_next_child(IAccessible *acc, LONG start_pos, LONG di
return hr; return hr;
} }
static HRESULT msaa_acc_get_child_pos(IAccessible *acc, IAccessible **out_parent,
LONG *out_child_pos)
{
LONG child_count, child_id, child_pos, match_pos;
IAccessible *child, *parent, *match, **children;
HRESULT hr;
int i;
*out_parent = NULL;
*out_child_pos = 0;
hr = msaa_acc_get_parent(acc, &parent);
if (FAILED(hr) || !parent)
return hr;
hr = IAccessible_get_accChildCount(parent, &child_count);
if (FAILED(hr) || !child_count)
{
IAccessible_Release(parent);
return hr;
}
children = heap_alloc_zero(sizeof(*children) * child_count);
if (!children)
return E_OUTOFMEMORY;
match = NULL;
for (i = 0; i < child_count; i++)
{
hr = msaa_acc_get_next_child(parent, i + 1, DIR_FORWARD, &child, &child_id, &child_pos, FALSE);
if (FAILED(hr) || !child)
goto exit;
if (child != parent)
children[i] = child;
else
IAccessible_Release(child);
}
for (i = 0; i < child_count; i++)
{
if (!children[i])
continue;
if (msaa_acc_compare(acc, children[i]))
{
if (!match)
{
match = children[i];
match_pos = i + 1;
}
/* Can't have more than one IAccessible match. */
else
{
match = NULL;
match_pos = 0;
break;
}
}
}
exit:
if (match)
{
*out_parent = parent;
*out_child_pos = match_pos;
}
else
IAccessible_Release(parent);
for (i = 0; i < child_count; i++)
{
if (children[i])
IAccessible_Release(children[i]);
}
heap_free(children);
return hr;
}
static LONG msaa_role_to_uia_control_type(LONG role) static LONG msaa_role_to_uia_control_type(LONG role)
{ {
switch (role) switch (role)
...@@ -649,10 +729,10 @@ static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface, ...@@ -649,10 +729,10 @@ static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface,
if (direction == NavigateDirection_FirstChild) if (direction == NavigateDirection_FirstChild)
hr = msaa_acc_get_next_child(msaa_prov->acc, 1, DIR_FORWARD, &acc, &child_id, hr = msaa_acc_get_next_child(msaa_prov->acc, 1, DIR_FORWARD, &acc, &child_id,
&child_pos); &child_pos, TRUE);
else else
hr = msaa_acc_get_next_child(msaa_prov->acc, child_count, DIR_REVERSE, &acc, &child_id, hr = msaa_acc_get_next_child(msaa_prov->acc, child_count, DIR_REVERSE, &acc, &child_id,
&child_pos); &child_pos, TRUE);
if (FAILED(hr) || !acc) if (FAILED(hr) || !acc)
break; break;
...@@ -676,8 +756,53 @@ static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface, ...@@ -676,8 +756,53 @@ static HRESULT WINAPI msaa_fragment_Navigate(IRawElementProviderFragment *iface,
case NavigateDirection_NextSibling: case NavigateDirection_NextSibling:
case NavigateDirection_PreviousSibling: case NavigateDirection_PreviousSibling:
FIXME("Unimplemented NavigateDirection %d\n", direction); if (msaa_check_root_acc(msaa_prov))
return E_NOTIMPL; break;
if (!msaa_prov->parent)
{
if (V_I4(&msaa_prov->cid) != CHILDID_SELF)
{
msaa_prov->parent = msaa_prov->acc;
IAccessible_AddRef(msaa_prov->acc);
msaa_prov->child_pos = V_I4(&msaa_prov->cid);
}
else
{
hr = msaa_acc_get_child_pos(msaa_prov->acc, &acc, &child_pos);
if (FAILED(hr) || !acc)
break;
msaa_prov->parent = acc;
msaa_prov->child_pos = child_pos;
}
}
if (direction == NavigateDirection_NextSibling)
hr = msaa_acc_get_next_child(msaa_prov->parent, msaa_prov->child_pos + 1, DIR_FORWARD,
&acc, &child_id, &child_pos, TRUE);
else
hr = msaa_acc_get_next_child(msaa_prov->parent, msaa_prov->child_pos - 1, DIR_REVERSE,
&acc, &child_id, &child_pos, TRUE);
if (FAILED(hr) || !acc)
break;
hr = UiaProviderFromIAccessible(acc, child_id, 0, &elprov);
if (SUCCEEDED(hr))
{
struct msaa_provider *prov = impl_from_msaa_provider(elprov);
*ret_val = &prov->IRawElementProviderFragment_iface;
prov->parent = msaa_prov->parent;
IAccessible_AddRef(msaa_prov->parent);
if (acc != msaa_prov->acc)
prov->child_pos = child_pos;
else
prov->child_pos = child_id;
}
IAccessible_Release(acc);
break;
default: default:
FIXME("Invalid NavigateDirection %d\n", direction); FIXME("Invalid NavigateDirection %d\n", direction);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment