mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-16 05:56:24 +00:00
uiautomationcore: Implement IRawElementProviderFragment::get_FragmentRoot for MSAA providers.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
008c1c1128
commit
00799933bc
|
@ -3360,6 +3360,252 @@ static void test_uia_reserved_value_ifaces(void)
|
|||
CoUninitialize();
|
||||
}
|
||||
|
||||
DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
|
||||
static IAccessible *msaa_acc_da_unwrap(IAccessible *acc)
|
||||
{
|
||||
IServiceProvider *sp;
|
||||
HRESULT hr;
|
||||
|
||||
hr = IAccessible_QueryInterface(acc, &IID_IServiceProvider, (void**)&sp);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
IAccessible *acc2 = NULL;
|
||||
|
||||
hr = IServiceProvider_QueryService(sp, &SID_AccFromDAWrapper, &IID_IAccessible, (void**)&acc2);
|
||||
IServiceProvider_Release(sp);
|
||||
if (SUCCEEDED(hr) && acc2)
|
||||
return acc2;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#define check_msaa_prov_acc( elprov, acc, cid) \
|
||||
check_msaa_prov_acc_( ((IUnknown *)elprov), (acc), (cid), __LINE__)
|
||||
static void check_msaa_prov_acc_(IUnknown *elprov, IAccessible *acc, INT cid, int line)
|
||||
{
|
||||
ILegacyIAccessibleProvider *accprov;
|
||||
IAccessible *acc2, *acc3;
|
||||
INT child_id;
|
||||
HRESULT hr;
|
||||
|
||||
hr = IUnknown_QueryInterface(elprov, &IID_ILegacyIAccessibleProvider, (void **)&accprov);
|
||||
ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok_(__FILE__, line)(!!accprov, "accprov == NULL\n");
|
||||
|
||||
acc2 = acc3 = NULL;
|
||||
hr = ILegacyIAccessibleProvider_GetIAccessible(accprov, &acc2);
|
||||
ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
|
||||
/*
|
||||
* Potentially get our IAccessible out of a direct annotation wrapper
|
||||
* IAccessible.
|
||||
*/
|
||||
if (acc && acc2 && (acc != acc2) && (acc3 = msaa_acc_da_unwrap(acc2)))
|
||||
{
|
||||
IAccessible_Release(acc2);
|
||||
acc2 = acc3;
|
||||
}
|
||||
ok_(__FILE__, line)(acc2 == acc, "acc2 != acc\n");
|
||||
if (acc2)
|
||||
IAccessible_Release(acc2);
|
||||
|
||||
hr = ILegacyIAccessibleProvider_get_ChildId(accprov, &child_id);
|
||||
ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok_(__FILE__, line)(child_id == cid, "child_id != cid\n");
|
||||
|
||||
ILegacyIAccessibleProvider_Release(accprov);
|
||||
}
|
||||
|
||||
#define check_msaa_prov_host_elem_prov( elem, exp_host_prov) \
|
||||
check_msaa_prov_host_elem_prov_( ((IUnknown *)elem), (exp_host_prov), __LINE__)
|
||||
static void check_msaa_prov_host_elem_prov_(IUnknown *elem, BOOL exp_host_prov, int line)
|
||||
{
|
||||
IRawElementProviderSimple *elprov, *elprov2;
|
||||
HRESULT hr;
|
||||
|
||||
hr = IUnknown_QueryInterface(elem, &IID_IRawElementProviderSimple, (void **)&elprov);
|
||||
ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok_(__FILE__, line)(!!elprov, "elprov == NULL\n");
|
||||
|
||||
elprov2 = (void *)0xdeadbeef;
|
||||
hr = IRawElementProviderSimple_get_HostRawElementProvider(elprov, &elprov2);
|
||||
ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok_(__FILE__, line)((elprov2 != (void *)0xdeadbeef) && !!elprov2 == exp_host_prov, "Unexpected provider %p from get_HostRawElementProvider\n", elprov2);
|
||||
|
||||
if (elprov2)
|
||||
IRawElementProviderSimple_Release(elprov2);
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
}
|
||||
|
||||
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 test_uia_prov_from_acc_fragment_root(HWND hwnd)
|
||||
{
|
||||
IRawElementProviderFragmentRoot *elroot, *elroot2;
|
||||
IRawElementProviderFragment *elfrag, *elfrag2;
|
||||
IRawElementProviderSimple *elprov;
|
||||
HRESULT hr;
|
||||
|
||||
set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
|
||||
Accessible.ow_hwnd = hwnd;
|
||||
|
||||
elprov = NULL;
|
||||
hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elprov, "elprov == NULL\n");
|
||||
|
||||
hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag, "elfrag == NULL\n");
|
||||
|
||||
/*
|
||||
* get_FragmentRoot does the equivalent of calling
|
||||
* AccessibleObjectFromWindow with OBJID_CLIENT on the HWND associated
|
||||
* with our IAccessible. Unlike UiaProviderFromIAccessible, it will create
|
||||
* a provider from a default oleacc proxy.
|
||||
*/
|
||||
elroot = NULL;
|
||||
acc_client = NULL;
|
||||
SET_EXPECT(winproc_GETOBJECT_CLIENT);
|
||||
hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elroot, "elroot == NULL\n");
|
||||
CHECK_CALLED(winproc_GETOBJECT_CLIENT);
|
||||
|
||||
/*
|
||||
* Returns a provider from get_HostRawElementProvider without having
|
||||
* to query the HWND.
|
||||
*/
|
||||
check_msaa_prov_host_elem_prov(elroot, TRUE);
|
||||
|
||||
hr = IRawElementProviderFragmentRoot_QueryInterface(elroot, &IID_IRawElementProviderFragment, (void **)&elfrag2);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag2, "elfrag2 == NULL\n");
|
||||
|
||||
/*
|
||||
* Even on a provider retrieved from get_FragmentRoot, the HWND is
|
||||
* queried and a new fragment root is returned rather than just
|
||||
* returning our current fragment root interface.
|
||||
*/
|
||||
elroot2 = NULL;
|
||||
SET_EXPECT(winproc_GETOBJECT_CLIENT);
|
||||
hr = IRawElementProviderFragment_get_FragmentRoot(elfrag2, &elroot2);
|
||||
IRawElementProviderFragment_Release(elfrag2);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elroot2, "elroot2 == NULL\n");
|
||||
CHECK_CALLED(winproc_GETOBJECT_CLIENT);
|
||||
|
||||
ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elroot2), "elroot2 == elroot\n");
|
||||
IRawElementProviderFragmentRoot_Release(elroot2);
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
|
||||
/*
|
||||
* Accessible is now the IAccessible for our HWND, so we'll get it instead
|
||||
* of an oleacc proxy.
|
||||
*/
|
||||
acc_client = &Accessible.IAccessible_iface;
|
||||
elroot = NULL;
|
||||
SET_EXPECT(winproc_GETOBJECT_CLIENT);
|
||||
hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elroot, "elroot == NULL\n");
|
||||
CHECK_CALLED(winproc_GETOBJECT_CLIENT);
|
||||
check_msaa_prov_acc(elroot, &Accessible.IAccessible_iface, CHILDID_SELF);
|
||||
|
||||
/*
|
||||
* Returns a provider from get_HostRawElementProvider without having
|
||||
* to query the HWND, same as before.
|
||||
*/
|
||||
check_msaa_prov_host_elem_prov(elroot, TRUE);
|
||||
|
||||
hr = IRawElementProviderFragmentRoot_QueryInterface(elroot, &IID_IRawElementProviderFragment, (void **)&elfrag2);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag2, "elfrag2 == NULL\n");
|
||||
|
||||
/* Same deal as before, unique FragmentRoot even on a known root. */
|
||||
elroot2 = NULL;
|
||||
SET_EXPECT(winproc_GETOBJECT_CLIENT);
|
||||
hr = IRawElementProviderFragment_get_FragmentRoot(elfrag2, &elroot2);
|
||||
IRawElementProviderFragment_Release(elfrag2);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elroot2, "elroot2 == NULL\n");
|
||||
check_msaa_prov_acc(elroot2, &Accessible.IAccessible_iface, CHILDID_SELF);
|
||||
CHECK_CALLED(winproc_GETOBJECT_CLIENT);
|
||||
|
||||
ok(!iface_cmp((IUnknown *)elroot, (IUnknown *)elroot2), "elroot2 == elroot\n");
|
||||
IRawElementProviderFragmentRoot_Release(elroot2);
|
||||
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
|
||||
/*
|
||||
* Test simple child element.
|
||||
*/
|
||||
hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, 1, UIA_PFIA_DEFAULT, &elprov);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
|
||||
hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag, "elfrag == NULL\n");
|
||||
|
||||
/*
|
||||
* Simple child element queries HWND as well, does not just return its
|
||||
* parent.
|
||||
*/
|
||||
elroot = NULL;
|
||||
SET_EXPECT(winproc_GETOBJECT_CLIENT);
|
||||
hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elroot, "elroot == NULL\n");
|
||||
CHECK_CALLED(winproc_GETOBJECT_CLIENT);
|
||||
check_msaa_prov_acc(elroot, &Accessible.IAccessible_iface, CHILDID_SELF);
|
||||
check_msaa_prov_host_elem_prov(elroot, TRUE);
|
||||
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
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);
|
||||
|
||||
elprov = NULL;
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, get_accParent); /* Gets HWND from parent IAccessible. */
|
||||
SET_ACC_METHOD_EXPECT(&Accessible_child, accNavigate);
|
||||
hr = pUiaProviderFromIAccessible(&Accessible_child.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elprov, "elprov == NULL\n");
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, get_accParent);
|
||||
CHECK_ACC_METHOD_CALLED(&Accessible_child, accNavigate);
|
||||
|
||||
hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragment, (void **)&elfrag);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elfrag, "elfrag == NULL\n");
|
||||
|
||||
/*
|
||||
* Again, same behavior as simple children. It doesn't just retrieve the
|
||||
* parent IAccessible, it queries the HWND.
|
||||
*/
|
||||
elroot = NULL;
|
||||
SET_EXPECT(winproc_GETOBJECT_CLIENT);
|
||||
hr = IRawElementProviderFragment_get_FragmentRoot(elfrag, &elroot);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!elroot, "elroot == NULL\n");
|
||||
CHECK_CALLED(winproc_GETOBJECT_CLIENT);
|
||||
check_msaa_prov_acc(elroot, &Accessible.IAccessible_iface, CHILDID_SELF);
|
||||
|
||||
IRawElementProviderFragmentRoot_Release(elroot);
|
||||
IRawElementProviderFragment_Release(elfrag);
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
struct msaa_role_uia_type {
|
||||
INT acc_role;
|
||||
INT uia_control_type;
|
||||
|
@ -4955,6 +5201,7 @@ static void test_UiaProviderFromIAccessible(void)
|
|||
test_uia_prov_from_acc_properties();
|
||||
test_uia_prov_from_acc_navigation();
|
||||
test_uia_prov_from_acc_ia2();
|
||||
test_uia_prov_from_acc_fragment_root(hwnd);
|
||||
|
||||
CoUninitialize();
|
||||
DestroyWindow(hwnd);
|
||||
|
|
|
@ -964,9 +964,27 @@ static HRESULT WINAPI msaa_fragment_SetFocus(IRawElementProviderFragment *iface)
|
|||
static HRESULT WINAPI msaa_fragment_get_FragmentRoot(IRawElementProviderFragment *iface,
|
||||
IRawElementProviderFragmentRoot **ret_val)
|
||||
{
|
||||
FIXME("%p, %p: stub!\n", iface, ret_val);
|
||||
struct msaa_provider *msaa_prov = impl_from_msaa_fragment(iface);
|
||||
IRawElementProviderSimple *elprov;
|
||||
IAccessible *acc;
|
||||
HRESULT hr;
|
||||
|
||||
TRACE("%p, %p\n", iface, ret_val);
|
||||
|
||||
*ret_val = NULL;
|
||||
return E_NOTIMPL;
|
||||
hr = AccessibleObjectFromWindow(msaa_prov->hwnd, OBJID_CLIENT, &IID_IAccessible, (void **)&acc);
|
||||
if (FAILED(hr) || !acc)
|
||||
return hr;
|
||||
|
||||
hr = create_msaa_provider(acc, CHILDID_SELF, msaa_prov->hwnd, TRUE, &elprov);
|
||||
IAccessible_Release(acc);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IRawElementProviderFragmentRoot, (void **)ret_val);
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
static const IRawElementProviderFragmentVtbl msaa_fragment_vtbl = {
|
||||
|
|
Loading…
Reference in a new issue