uiautomationcore: Implement IRawElementProviderFragmentRoot::GetFocus for MSAA providers.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
ef1d5a0e0a
commit
c7e976f819
2 changed files with 419 additions and 3 deletions
|
@ -510,6 +510,8 @@ static struct Accessible
|
|||
LONG left, top, width, height;
|
||||
BOOL enable_ia2;
|
||||
LONG unique_id;
|
||||
INT focus_child_id;
|
||||
IAccessible *focus_acc;
|
||||
DEFINE_ACC_METHOD_EXPECTS;
|
||||
} Accessible, Accessible2, Accessible_child, Accessible_child2;
|
||||
|
||||
|
@ -674,6 +676,9 @@ static HRESULT WINAPI Accessible_get_accChild(IAccessible *iface, VARIANT child_
|
|||
case 4:
|
||||
return IAccessible_QueryInterface(&Accessible_child2.IAccessible_iface, &IID_IDispatch, (void **)out_child);
|
||||
|
||||
case 7:
|
||||
return IAccessible_QueryInterface(&Accessible.IAccessible_iface, &IID_IDispatch, (void **)out_child);
|
||||
|
||||
default:
|
||||
break;
|
||||
|
||||
|
@ -808,8 +813,28 @@ static HRESULT WINAPI Accessible_get_accKeyboardShortcut(IAccessible *iface, VAR
|
|||
static HRESULT WINAPI Accessible_get_accFocus(IAccessible *iface, VARIANT *pchild_id)
|
||||
{
|
||||
struct Accessible *This = impl_from_Accessible(iface);
|
||||
|
||||
CHECK_ACC_METHOD_EXPECT(This, get_accFocus);
|
||||
ACC_METHOD_TRACE(This, get_accFocus);
|
||||
|
||||
VariantInit(pchild_id);
|
||||
if (This->focus_acc)
|
||||
{
|
||||
HRESULT hr;
|
||||
|
||||
hr = IAccessible_QueryInterface(This->focus_acc, &IID_IDispatch, (void **)&V_DISPATCH(pchild_id));
|
||||
if (SUCCEEDED(hr))
|
||||
V_VT(pchild_id) = VT_DISPATCH;
|
||||
|
||||
return hr;
|
||||
}
|
||||
else if (This->focus_child_id >= 0)
|
||||
{
|
||||
V_VT(pchild_id) = VT_I4;
|
||||
V_I4(pchild_id) = This->focus_child_id;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
|
@ -1457,6 +1482,7 @@ static struct Accessible Accessible =
|
|||
0, 0, 0, NULL,
|
||||
0, 0, 0, 0,
|
||||
FALSE, 0,
|
||||
CHILDID_SELF, NULL,
|
||||
};
|
||||
|
||||
static struct Accessible Accessible2 =
|
||||
|
@ -1472,6 +1498,7 @@ static struct Accessible Accessible2 =
|
|||
0, 0, 0, NULL,
|
||||
0, 0, 0, 0,
|
||||
FALSE, 0,
|
||||
CHILDID_SELF, NULL,
|
||||
};
|
||||
|
||||
static struct Accessible Accessible_child =
|
||||
|
@ -1487,6 +1514,7 @@ static struct Accessible Accessible_child =
|
|||
0, 0, 0, NULL,
|
||||
0, 0, 0, 0,
|
||||
FALSE, 0,
|
||||
CHILDID_SELF, NULL,
|
||||
};
|
||||
|
||||
static struct Accessible Accessible_child2 =
|
||||
|
@ -1502,6 +1530,7 @@ static struct Accessible Accessible_child2 =
|
|||
0, 0, 0, NULL,
|
||||
0, 0, 0, 0,
|
||||
FALSE, 0,
|
||||
CHILDID_SELF, NULL,
|
||||
};
|
||||
|
||||
struct Provider_prop_override
|
||||
|
@ -3440,14 +3469,17 @@ static void check_msaa_prov_host_elem_prov_(IUnknown *elem, BOOL exp_host_prov,
|
|||
|
||||
static void set_accessible_props(struct Accessible *acc, INT role, INT state,
|
||||
LONG child_count, LPCWSTR name, LONG left, LONG top, LONG width, LONG height);
|
||||
static void set_accessible_ia2_props(struct Accessible *acc, BOOL enable_ia2, LONG unique_id);
|
||||
static void test_uia_prov_from_acc_fragment_root(HWND hwnd)
|
||||
{
|
||||
IRawElementProviderFragmentRoot *elroot, *elroot2;
|
||||
IRawElementProviderFragment *elfrag, *elfrag2;
|
||||
IRawElementProviderSimple *elprov;
|
||||
ULONG old_ref;
|
||||
HRESULT hr;
|
||||
|
||||
set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
|
||||
set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, STATE_SYSTEM_FOCUSED, 0, L"acc_name", 0, 0, 0, 0);
|
||||
set_accessible_ia2_props(&Accessible, FALSE, 0);
|
||||
Accessible.ow_hwnd = hwnd;
|
||||
|
||||
elprov = NULL;
|
||||
|
@ -3545,6 +3577,217 @@ static void test_uia_prov_from_acc_fragment_root(HWND hwnd)
|
|||
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
|
||||
/*
|
||||
* IRawElementProviderFragmentRoot::GetFocus will call get_accFocus.
|
||||
*/
|
||||
hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)&elroot);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elroot, "elroot == NULL\n");
|
||||
|
||||
/* Focus is CHILDID_SELF, returns NULL. */
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
Accessible.focus_child_id = CHILDID_SELF;
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!elfrag, "elfrag != NULL\n");
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
|
||||
/*
|
||||
* get_accFocus returns child ID 1, which is a simple child element.
|
||||
* get_accState for child ID 1 returns STATE_SYSTEM_INVISIBLE, so no
|
||||
* element will be returned.
|
||||
*/
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
Accessible.focus_child_id = 1;
|
||||
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!elfrag, "elfrag != NULL\n");
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
|
||||
|
||||
/*
|
||||
* get_accFocus returns child ID 3, which is another simple child
|
||||
* element. get_accState for child ID 3 does not have
|
||||
* STATE_SYSTEM_INVISIBLE set, so it will return an element.
|
||||
*/
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
Accessible.focus_child_id = 3;
|
||||
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag, "elfrag == NULL\n");
|
||||
check_msaa_prov_acc(elfrag, &Accessible.IAccessible_iface, 3);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
|
||||
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
|
||||
/*
|
||||
* get_accFocus returns child ID 2 which is a full IAccessible,
|
||||
* Accessible_child.
|
||||
*/
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
Accessible.focus_child_id = 2;
|
||||
Accessible_child.state = STATE_SYSTEM_FOCUSABLE | STATE_SYSTEM_OFFSCREEN;
|
||||
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accState);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accFocus);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag, "elfrag == NULL\n");
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accState);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accFocus);
|
||||
|
||||
check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
|
||||
/*
|
||||
* get_accFocus returns child ID 2 which is a full IAccessible,
|
||||
* Accessible_child. It returns failure from get_accState so it isn't
|
||||
* returned.
|
||||
*/
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
Accessible.focus_child_id = 2;
|
||||
Accessible_child.state = 0;
|
||||
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accState);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!elfrag, "elfrag != NULL\n");
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accState);
|
||||
|
||||
/*
|
||||
* get_accFocus returns child ID 7 which is a full IAccessible,
|
||||
* Accessible. This is the same IAccessible interface as the one we called
|
||||
* get_accFocus on, so it is ignored. Same behavior as CHILDID_SELF.
|
||||
*/
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
Accessible.focus_child_id = 7;
|
||||
Accessible.state = STATE_SYSTEM_FOCUSABLE;
|
||||
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accChild);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!elfrag, "elfrag != NULL\n");
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accChild);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
|
||||
|
||||
/*
|
||||
* Return E_NOTIMPL from get_accFocus, returns a new provider representing
|
||||
* the same IAccessible.
|
||||
*/
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
old_ref = Accessible.ref;
|
||||
Accessible.focus_child_id = -1;
|
||||
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag, "elfrag == NULL\n");
|
||||
ok(Accessible.ref > old_ref, "Unexpected ref %ld\n", Accessible.ref);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
|
||||
/* Two unique COM objects that represent the same IAccessible. */
|
||||
ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elfrag), "elroot == elfrag\n");
|
||||
check_msaa_prov_acc(elfrag, &Accessible.IAccessible_iface, CHILDID_SELF);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
ok(Accessible.ref == old_ref, "Unexpected ref %ld\n", Accessible.ref);
|
||||
Accessible.focus_child_id = CHILDID_SELF;
|
||||
|
||||
/*
|
||||
* Similar to CHILDID_SELF, if the same IAccessible interface is returned
|
||||
* as a VT_DISPATCH, we'll get no element.
|
||||
*/
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
Accessible.focus_acc = &Accessible.IAccessible_iface;
|
||||
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accState);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!elfrag, "elfrag != NULL\n");
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accState);
|
||||
|
||||
/*
|
||||
* Return Accessible_child as a VT_DISPATCH - will get an element.
|
||||
*/
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
Accessible.focus_acc = &Accessible_child.IAccessible_iface;
|
||||
Accessible_child.state = STATE_SYSTEM_FOCUSABLE;
|
||||
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accState);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accFocus);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag, "elfrag == NULL\n");
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accState);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accFocus);
|
||||
|
||||
check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
|
||||
/*
|
||||
* Fail get_accFocus on child.
|
||||
*/
|
||||
Accessible_child.focus_child_id = -1;
|
||||
Accessible_child.state = STATE_SYSTEM_FOCUSABLE;
|
||||
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
SET_ACC_METHOD_EXPECT(&Accessible, get_accFocus);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accState);
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accFocus);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag, "elfrag == NULL\n");
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible, get_accFocus);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accState);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accFocus);
|
||||
|
||||
check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
|
||||
/*
|
||||
|
@ -3572,12 +3815,28 @@ static void test_uia_prov_from_acc_fragment_root(HWND hwnd)
|
|||
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
|
||||
/*
|
||||
* IRawElementProviderFragmentRoot::GetFocus will not call get_accFocus
|
||||
* on a simple child IAccessible.
|
||||
*/
|
||||
hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)&elroot);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elroot, "elroot == NULL\n");
|
||||
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!elfrag, "elfrag != NULL\n");
|
||||
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
|
||||
/*
|
||||
* Test child of root HWND IAccessible.
|
||||
*/
|
||||
set_accessible_props(&Accessible_child, ROLE_SYSTEM_TEXT, 0, 0, L"acc_child_name", 0, 0, 0, 0);
|
||||
set_accessible_ia2_props(&Accessible_child, FALSE, 0);
|
||||
|
||||
elprov = NULL;
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent); /* Gets HWND from parent IAccessible. */
|
||||
|
@ -3606,8 +3865,38 @@ static void test_uia_prov_from_acc_fragment_root(HWND hwnd)
|
|||
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
|
||||
/*
|
||||
* GetFocus tests.
|
||||
*/
|
||||
hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)&elroot);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elroot, "elroot == NULL\n");
|
||||
|
||||
/*
|
||||
* get_accFocus returns E_NOTIMPL, returns new provider for same
|
||||
* IAccessible.
|
||||
*/
|
||||
elfrag = (void *)0xdeadbeef;
|
||||
old_ref = Accessible_child.ref;
|
||||
Accessible_child.focus_child_id = -1;
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accFocus);
|
||||
hr = IRawElementProviderFragmentRoot_GetFocus(elroot, &elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag, "elfrag == NULL\n");
|
||||
ok(Accessible_child.ref > old_ref, "Unexpected ref %ld\n", Accessible.ref);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accFocus);
|
||||
|
||||
/* Again, two unique COM objects that represent the same IAccessible. */
|
||||
ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elfrag), "elroot == elfrag\n");
|
||||
check_msaa_prov_acc(elfrag, &Accessible_child.IAccessible_iface, CHILDID_SELF);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
ok(Accessible_child.ref == old_ref, "Unexpected ref %ld\n", Accessible.ref);
|
||||
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
|
||||
Accessible.focus_child_id = Accessible_child.focus_child_id = CHILDID_SELF;
|
||||
ok(Accessible.ref == 1, "Unexpected refcnt %ld\n", Accessible.ref);
|
||||
ok(Accessible_child.ref == 1, "Unexpected refcnt %ld\n", Accessible_child.ref);
|
||||
acc_client = NULL;
|
||||
|
|
|
@ -178,6 +178,25 @@ static HRESULT msaa_acc_prop_match(IAccessible *acc, IAccessible *acc2)
|
|||
return S_FALSE;
|
||||
}
|
||||
|
||||
static BOOL msaa_acc_iface_cmp(IAccessible *acc, IAccessible *acc2)
|
||||
{
|
||||
IUnknown *unk, *unk2;
|
||||
BOOL matched;
|
||||
|
||||
acc = msaa_acc_da_unwrap(acc);
|
||||
acc2 = msaa_acc_da_unwrap(acc2);
|
||||
IAccessible_QueryInterface(acc, &IID_IUnknown, (void**)&unk);
|
||||
IAccessible_QueryInterface(acc2, &IID_IUnknown, (void**)&unk2);
|
||||
matched = (unk == unk2);
|
||||
|
||||
IAccessible_Release(acc);
|
||||
IUnknown_Release(unk);
|
||||
IAccessible_Release(acc2);
|
||||
IUnknown_Release(unk2);
|
||||
|
||||
return matched;
|
||||
}
|
||||
|
||||
static BOOL msaa_acc_compare(IAccessible *acc, IAccessible *acc2)
|
||||
{
|
||||
IAccessible2 *ia2[2] = { NULL, NULL };
|
||||
|
@ -1068,12 +1087,120 @@ static HRESULT WINAPI msaa_fragment_root_ElementProviderFromPoint(IRawElementPro
|
|||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
static HRESULT msaa_acc_get_focus(struct msaa_provider *prov, struct msaa_provider **out_prov)
|
||||
{
|
||||
IRawElementProviderSimple *elprov;
|
||||
IAccessible *focus_acc = NULL;
|
||||
INT focus_cid = CHILDID_SELF;
|
||||
HWND hwnd = NULL;
|
||||
HRESULT hr;
|
||||
VARIANT v;
|
||||
|
||||
*out_prov = NULL;
|
||||
|
||||
if (V_I4(&prov->cid) != CHILDID_SELF)
|
||||
return S_OK;
|
||||
|
||||
VariantInit(&v);
|
||||
hr = IAccessible_get_accFocus(prov->acc, &v);
|
||||
if (FAILED(hr) || (V_VT(&v) != VT_I4 && V_VT(&v) != VT_DISPATCH))
|
||||
{
|
||||
VariantClear(&v);
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (V_VT(&v) == VT_I4)
|
||||
{
|
||||
IDispatch *disp = NULL;
|
||||
|
||||
if (V_I4(&v) == CHILDID_SELF)
|
||||
return S_OK;
|
||||
|
||||
hr = IAccessible_get_accChild(prov->acc, v, &disp);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (hr == S_FALSE)
|
||||
{
|
||||
hwnd = prov->hwnd;
|
||||
focus_acc = prov->acc;
|
||||
IAccessible_AddRef(focus_acc);
|
||||
focus_cid = V_I4(&v);
|
||||
}
|
||||
else if (disp)
|
||||
{
|
||||
V_VT(&v) = VT_DISPATCH;
|
||||
V_DISPATCH(&v) = disp;
|
||||
}
|
||||
else
|
||||
return E_FAIL;
|
||||
}
|
||||
|
||||
if (V_VT(&v) == VT_DISPATCH)
|
||||
{
|
||||
hr = IDispatch_QueryInterface(V_DISPATCH(&v), &IID_IAccessible, (void **)&focus_acc);
|
||||
VariantClear(&v);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = WindowFromAccessibleObject(focus_acc, &hwnd);
|
||||
if (FAILED(hr) || !hwnd)
|
||||
{
|
||||
IAccessible_Release(focus_acc);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
|
||||
hr = create_msaa_provider(focus_acc, focus_cid, hwnd, FALSE, &elprov);
|
||||
IAccessible_Release(focus_acc);
|
||||
if (SUCCEEDED(hr))
|
||||
*out_prov = impl_from_msaa_provider(elprov);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI msaa_fragment_root_GetFocus(IRawElementProviderFragmentRoot *iface,
|
||||
IRawElementProviderFragment **ret_val)
|
||||
{
|
||||
FIXME("%p, %p: stub!\n", iface, ret_val);
|
||||
struct msaa_provider *msaa_prov = impl_from_msaa_fragment_root(iface);
|
||||
struct msaa_provider *prov, *prov2;
|
||||
IRawElementProviderSimple *elprov;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("%p, %p\n", iface, ret_val);
|
||||
|
||||
*ret_val = NULL;
|
||||
return E_NOTIMPL;
|
||||
if (V_I4(&msaa_prov->cid) != CHILDID_SELF)
|
||||
return S_OK;
|
||||
|
||||
hr = create_msaa_provider(msaa_prov->acc, CHILDID_SELF, msaa_prov->hwnd, FALSE, &elprov);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
prov = impl_from_msaa_provider(elprov);
|
||||
while (SUCCEEDED(msaa_acc_get_focus(prov, &prov2)))
|
||||
{
|
||||
if (!prov2 || (msaa_check_acc_state_hres(prov2->acc, prov2->cid, STATE_SYSTEM_INVISIBLE) != S_FALSE) ||
|
||||
((V_I4(&prov2->cid) == CHILDID_SELF) && msaa_acc_iface_cmp(prov->acc, prov2->acc)))
|
||||
{
|
||||
if (prov2)
|
||||
IRawElementProviderSimple_Release(&prov2->IRawElementProviderSimple_iface);
|
||||
|
||||
if (msaa_acc_iface_cmp(prov->acc, msaa_prov->acc) && V_I4(&prov->cid) == CHILDID_SELF)
|
||||
{
|
||||
IRawElementProviderSimple_Release(&prov->IRawElementProviderSimple_iface);
|
||||
return S_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
IRawElementProviderSimple_Release(&prov->IRawElementProviderSimple_iface);
|
||||
prov = prov2;
|
||||
}
|
||||
|
||||
hr = IRawElementProviderSimple_QueryInterface(&prov->IRawElementProviderSimple_iface, &IID_IRawElementProviderFragment, (void **)ret_val);
|
||||
IRawElementProviderSimple_Release(&prov->IRawElementProviderSimple_iface);
|
||||
return hr;
|
||||
}
|
||||
|
||||
static const IRawElementProviderFragmentRootVtbl msaa_fragment_root_vtbl = {
|
||||
|
|
Loading…
Add table
Reference in a new issue