1
0
Fork 0
mirror of synced 2025-03-07 03:53:26 +01:00

uiautomationcore: Add stub IProxyProviderWinEventHandler implementation for MSAA providers.

Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
Connor McAdams 2023-07-13 12:03:05 -04:00 committed by Alexandre Julliard
parent c7e976f819
commit c22bd318b3
2 changed files with 251 additions and 3 deletions

View file

@ -394,6 +394,9 @@ DEFINE_EXPECT(uia_event_callback);
DEFINE_EXPECT(uia_com_event_callback);
DEFINE_EXPECT(winproc_GETOBJECT_UiaRoot);
DEFINE_EXPECT(child_winproc_GETOBJECT_UiaRoot);
DEFINE_EXPECT(ProxyEventSink_AddAutomationPropertyChangedEvent);
DEFINE_EXPECT(ProxyEventSink_AddAutomationEvent);
DEFINE_EXPECT(ProxyEventSink_AddStructureChangedEvent);
static BOOL check_variant_i4(VARIANT *v, int val)
{
@ -3389,6 +3392,207 @@ static void test_uia_reserved_value_ifaces(void)
CoUninitialize();
}
static struct ProxyEventSink
{
IProxyProviderWinEventSink IProxyProviderWinEventSink_iface;
LONG ref;
IRawElementProviderSimple *event_elprov;
int event_id;
IRawElementProviderSimple *prop_change_elprov;
int prop_change_prop_id;
VARIANT prop_change_value;
IRawElementProviderSimple *structure_change_elprov;
int structure_change_type;
SAFEARRAY *structure_change_rt_id;
} ProxyEventSink;
static void proxy_event_sink_clear(void)
{
if (ProxyEventSink.event_elprov)
IRawElementProviderSimple_Release(ProxyEventSink.event_elprov);
ProxyEventSink.event_elprov = NULL;
ProxyEventSink.event_id = 0;
if (ProxyEventSink.prop_change_elprov)
IRawElementProviderSimple_Release(ProxyEventSink.prop_change_elprov);
ProxyEventSink.prop_change_elprov = NULL;
ProxyEventSink.prop_change_prop_id = 0;
VariantClear(&ProxyEventSink.prop_change_value);
if (ProxyEventSink.structure_change_elprov)
IRawElementProviderSimple_Release(ProxyEventSink.structure_change_elprov);
ProxyEventSink.structure_change_elprov = NULL;
ProxyEventSink.structure_change_type = 0;
SafeArrayDestroy(ProxyEventSink.structure_change_rt_id);
}
static inline struct ProxyEventSink *impl_from_ProxyEventSink(IProxyProviderWinEventSink *iface)
{
return CONTAINING_RECORD(iface, struct ProxyEventSink, IProxyProviderWinEventSink_iface);
}
static HRESULT WINAPI ProxyEventSink_QueryInterface(IProxyProviderWinEventSink *iface, REFIID riid, void **obj)
{
*obj = NULL;
if (IsEqualIID(riid, &IID_IProxyProviderWinEventSink) || IsEqualIID(riid, &IID_IUnknown))
*obj = iface;
else
return E_NOINTERFACE;
IProxyProviderWinEventSink_AddRef(iface);
return S_OK;
}
static ULONG WINAPI ProxyEventSink_AddRef(IProxyProviderWinEventSink *iface)
{
struct ProxyEventSink *This = impl_from_ProxyEventSink(iface);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI ProxyEventSink_Release(IProxyProviderWinEventSink *iface)
{
struct ProxyEventSink *This = impl_from_ProxyEventSink(iface);
return InterlockedDecrement(&This->ref);
}
static HRESULT WINAPI ProxyEventSink_AddAutomationPropertyChangedEvent(IProxyProviderWinEventSink *iface,
IRawElementProviderSimple *elprov, PROPERTYID prop_id, VARIANT new_value)
{
struct ProxyEventSink *This = impl_from_ProxyEventSink(iface);
CHECK_EXPECT(ProxyEventSink_AddAutomationPropertyChangedEvent);
This->prop_change_elprov = elprov;
if (elprov)
IRawElementProviderSimple_AddRef(elprov);
This->prop_change_prop_id = prop_id;
VariantCopy(&This->prop_change_value, &new_value);
return S_OK;
}
static HRESULT WINAPI ProxyEventSink_AddAutomationEvent(IProxyProviderWinEventSink *iface,
IRawElementProviderSimple *elprov, EVENTID event_id)
{
struct ProxyEventSink *This = impl_from_ProxyEventSink(iface);
CHECK_EXPECT(ProxyEventSink_AddAutomationEvent);
This->event_elprov = elprov;
if (elprov)
IRawElementProviderSimple_AddRef(elprov);
This->event_id = event_id;
return S_OK;
}
static HRESULT WINAPI ProxyEventSink_AddStructureChangedEvent(IProxyProviderWinEventSink *iface,
IRawElementProviderSimple *elprov, enum StructureChangeType structure_change_type, SAFEARRAY *runtime_id)
{
struct ProxyEventSink *This = impl_from_ProxyEventSink(iface);
HRESULT hr;
CHECK_EXPECT(ProxyEventSink_AddStructureChangedEvent);
This->structure_change_elprov = elprov;
if (elprov)
IRawElementProviderSimple_AddRef(elprov);
This->structure_change_type = structure_change_type;
hr = SafeArrayCopy(runtime_id, &This->structure_change_rt_id);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
return S_OK;
}
static const IProxyProviderWinEventSinkVtbl ProxyEventSinkVtbl = {
ProxyEventSink_QueryInterface,
ProxyEventSink_AddRef,
ProxyEventSink_Release,
ProxyEventSink_AddAutomationPropertyChangedEvent,
ProxyEventSink_AddAutomationEvent,
ProxyEventSink_AddStructureChangedEvent,
};
static struct ProxyEventSink ProxyEventSink =
{
{ &ProxyEventSinkVtbl },
1,
};
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_winevent_handler(HWND hwnd)
{
IProxyProviderWinEventHandler *handler;
IRawElementProviderSimple *elprov;
HRESULT hr;
set_accessible_props(&Accessible, ROLE_SYSTEM_DOCUMENT, 0, 0, L"acc_name", 0, 0, 0, 0);
Accessible.ow_hwnd = hwnd;
hr = pUiaProviderFromIAccessible(&Accessible.IAccessible_iface, CHILDID_SELF, UIA_PFIA_DEFAULT, &elprov);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IRawElementProviderSimple_QueryInterface(elprov, &IID_IProxyProviderWinEventHandler, (void **)&handler);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(!!handler, "Handler == NULL\n");
/* EVENT_SYSTEM_ALERT */
SET_EXPECT(ProxyEventSink_AddAutomationEvent);
hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_SYSTEM_ALERT, hwnd, OBJID_CLIENT, CHILDID_SELF,
&ProxyEventSink.IProxyProviderWinEventSink_iface);
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
todo_wine CHECK_CALLED(ProxyEventSink_AddAutomationEvent);
todo_wine ok(ProxyEventSink.event_id == UIA_SystemAlertEventId, "Unexpected event_id %d\n", ProxyEventSink.event_id);
todo_wine ok(ProxyEventSink.event_elprov == elprov, "Unexpected event_elprov %p\n", ProxyEventSink.event_elprov);
proxy_event_sink_clear();
/* EVENT_OBJECT_FOCUS is not handled. */
hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_OBJECT_FOCUS, hwnd, OBJID_CLIENT, CHILDID_SELF,
&ProxyEventSink.IProxyProviderWinEventSink_iface);
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
/* EVENT_OBJECT_NAMECHANGE. */
SET_EXPECT(ProxyEventSink_AddAutomationPropertyChangedEvent);
SET_ACC_METHOD_EXPECT(&Accessible, get_accName);
hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_OBJECT_NAMECHANGE, hwnd, OBJID_CLIENT, CHILDID_SELF,
&ProxyEventSink.IProxyProviderWinEventSink_iface);
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
todo_wine ok(ProxyEventSink.prop_change_elprov == elprov, "Unexpected prop_change_elprov %p\n", ProxyEventSink.prop_change_elprov);
todo_wine ok(ProxyEventSink.prop_change_prop_id == UIA_NamePropertyId, "Unexpected prop_change_prop_id %d\n",
ProxyEventSink.prop_change_prop_id);
todo_wine ok(V_VT(&ProxyEventSink.prop_change_value) == VT_BSTR, "Unexpected prop_change_value vt %d\n",
V_VT(&ProxyEventSink.prop_change_value));
if (V_VT(&ProxyEventSink.prop_change_value) == VT_BSTR)
ok(!lstrcmpW(V_BSTR(&ProxyEventSink.prop_change_value), Accessible.name), "Unexpected BSTR %s\n",
wine_dbgstr_w(V_BSTR(&ProxyEventSink.prop_change_value)));
todo_wine CHECK_CALLED(ProxyEventSink_AddAutomationPropertyChangedEvent);
todo_wine CHECK_ACC_METHOD_CALLED(&Accessible, get_accName);
proxy_event_sink_clear();
/* EVENT_OBJECT_REORDER. */
acc_client = &Accessible.IAccessible_iface;
SET_EXPECT(winproc_GETOBJECT_CLIENT);
SET_EXPECT(ProxyEventSink_AddStructureChangedEvent);
hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, EVENT_OBJECT_REORDER, hwnd, OBJID_CLIENT, CHILDID_SELF,
&ProxyEventSink.IProxyProviderWinEventSink_iface);
todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
todo_wine ok(ProxyEventSink.structure_change_elprov == elprov, "Unexpected structure_change_elprov %p\n",
ProxyEventSink.structure_change_elprov);
todo_wine ok(ProxyEventSink.structure_change_type == StructureChangeType_ChildrenInvalidated, "Unexpected structure_change_type %d\n",
ProxyEventSink.structure_change_type);
ok(!ProxyEventSink.structure_change_rt_id, "structure_change_rt_id != NULL\n");
todo_wine CHECK_CALLED(winproc_GETOBJECT_CLIENT);
todo_wine CHECK_CALLED(ProxyEventSink_AddStructureChangedEvent);
proxy_event_sink_clear();
acc_client = NULL;
IProxyProviderWinEventHandler_Release(handler);
IRawElementProviderSimple_Release(elprov);
}
DEFINE_GUID(SID_AccFromDAWrapper, 0x33f139ee, 0xe509, 0x47f7, 0xbf,0x39, 0x83,0x76,0x44,0xf7,0x45,0x76);
static IAccessible *msaa_acc_da_unwrap(IAccessible *acc)
{
@ -3467,9 +3671,6 @@ static void check_msaa_prov_host_elem_prov_(IUnknown *elem, BOOL exp_host_prov,
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 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;
@ -5506,6 +5707,7 @@ static void test_UiaProviderFromIAccessible(void)
test_uia_prov_from_acc_navigation();
test_uia_prov_from_acc_ia2();
test_uia_prov_from_acc_fragment_root(hwnd);
test_uia_prov_from_acc_winevent_handler(hwnd);
CoUninitialize();
DestroyWindow(hwnd);

View file

@ -530,6 +530,7 @@ struct msaa_provider {
IRawElementProviderFragment IRawElementProviderFragment_iface;
IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface;
ILegacyIAccessibleProvider ILegacyIAccessibleProvider_iface;
IProxyProviderWinEventHandler IProxyProviderWinEventHandler_iface;
LONG refcount;
IAccessible *acc;
@ -586,6 +587,8 @@ HRESULT WINAPI msaa_provider_QueryInterface(IRawElementProviderSimple *iface, RE
*ppv = &msaa_prov->IRawElementProviderFragmentRoot_iface;
else if (IsEqualIID(riid, &IID_ILegacyIAccessibleProvider))
*ppv = &msaa_prov->ILegacyIAccessibleProvider_iface;
else if (IsEqualIID(riid, &IID_IProxyProviderWinEventHandler))
*ppv = &msaa_prov->IProxyProviderWinEventHandler_iface;
else
return E_NOINTERFACE;
@ -1369,6 +1372,48 @@ static const ILegacyIAccessibleProviderVtbl msaa_acc_provider_vtbl = {
msaa_acc_provider_get_DefaultAction,
};
/*
* IProxyProviderWinEventHandler interface for UiaProviderFromIAccessible
* providers.
*/
static inline struct msaa_provider *impl_from_msaa_winevent_handler(IProxyProviderWinEventHandler *iface)
{
return CONTAINING_RECORD(iface, struct msaa_provider, IProxyProviderWinEventHandler_iface);
}
static HRESULT WINAPI msaa_winevent_handler_QueryInterface(IProxyProviderWinEventHandler *iface, REFIID riid,
void **ppv)
{
struct msaa_provider *msaa_prov = impl_from_msaa_winevent_handler(iface);
return IRawElementProviderSimple_QueryInterface(&msaa_prov->IRawElementProviderSimple_iface, riid, ppv);
}
static ULONG WINAPI msaa_winevent_handler_AddRef(IProxyProviderWinEventHandler *iface)
{
struct msaa_provider *msaa_prov = impl_from_msaa_winevent_handler(iface);
return IRawElementProviderSimple_AddRef(&msaa_prov->IRawElementProviderSimple_iface);
}
static ULONG WINAPI msaa_winevent_handler_Release(IProxyProviderWinEventHandler *iface)
{
struct msaa_provider *msaa_prov = impl_from_msaa_winevent_handler(iface);
return IRawElementProviderSimple_Release(&msaa_prov->IRawElementProviderSimple_iface);
}
static HRESULT WINAPI msaa_winevent_handler_RespondToWinEvent(IProxyProviderWinEventHandler *iface, DWORD event_id,
HWND hwnd, LONG objid, LONG cid, IProxyProviderWinEventSink *event_sink)
{
FIXME("%p, %ld, %p, %ld, %ld, %p: stub\n", iface, event_id, hwnd, objid, cid, event_sink);
return E_NOTIMPL;
}
static const IProxyProviderWinEventHandlerVtbl msaa_winevent_handler_vtbl = {
msaa_winevent_handler_QueryInterface,
msaa_winevent_handler_AddRef,
msaa_winevent_handler_Release,
msaa_winevent_handler_RespondToWinEvent,
};
HRESULT create_msaa_provider(IAccessible *acc, LONG child_id, HWND hwnd, BOOL known_root_acc,
IRawElementProviderSimple **elprov)
{
@ -1381,6 +1426,7 @@ HRESULT create_msaa_provider(IAccessible *acc, LONG child_id, HWND hwnd, BOOL kn
msaa_prov->IRawElementProviderFragment_iface.lpVtbl = &msaa_fragment_vtbl;
msaa_prov->IRawElementProviderFragmentRoot_iface.lpVtbl = &msaa_fragment_root_vtbl;
msaa_prov->ILegacyIAccessibleProvider_iface.lpVtbl = &msaa_acc_provider_vtbl;
msaa_prov->IProxyProviderWinEventHandler_iface.lpVtbl = &msaa_winevent_handler_vtbl;
msaa_prov->refcount = 1;
variant_init_i4(&msaa_prov->cid, child_id);
msaa_prov->acc = acc;