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

uiautomationcore: Add support for raising events passed to our IProxyProviderWinEventSink interface.

Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
Connor McAdams 2023-09-27 14:17:46 -04:00 committed by Alexandre Julliard
parent 7aaf77a514
commit 60ff77754a
2 changed files with 90 additions and 34 deletions

View file

@ -1766,15 +1766,6 @@ static struct prov_method_sequence *sequence;
{ prov , FRAG_NAVIGATE }, /* NavigateDirection_Parent */ \
{ prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
#define NODE_CREATE_SEQ_TODO(prov) \
{ prov , PROV_GET_PROVIDER_OPTIONS, METHOD_TODO }, \
/* Win10v1507 and below call this. */ \
{ prov , PROV_GET_PROPERTY_VALUE, METHOD_OPTIONAL }, /* UIA_NativeWindowHandlePropertyId */ \
{ prov , PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_TODO }, \
{ prov , PROV_GET_PROPERTY_VALUE, METHOD_TODO }, \
{ prov , FRAG_NAVIGATE, METHOD_TODO }, /* NavigateDirection_Parent */ \
{ prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL } \
#define NODE_CREATE_SEQ_OPTIONAL(prov) \
{ prov , PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL }, \
/* Win10v1507 and below call this. */ \
@ -16727,9 +16718,9 @@ static const struct prov_method_sequence win_event_handler_seq[] = {
{ &Provider_hwnd2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
{ &Provider_nc2, WINEVENT_HANDLER_RESPOND_TO_WINEVENT },
{ &Provider_hwnd2, WINEVENT_HANDLER_RESPOND_TO_WINEVENT },
NODE_CREATE_SEQ_TODO(&Provider_child),
{ &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO },
{ &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
NODE_CREATE_SEQ(&Provider_child),
{ &Provider_child, FRAG_GET_RUNTIME_ID },
{ &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
{ 0 }
};
@ -16862,7 +16853,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
method_sequences_enabled = TRUE;
set_uia_hwnd_expects(1, 1, 1, 4, 3);
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
1, TRUE, FALSE, TRUE);
1, TRUE, FALSE, FALSE);
ok_method_sequence(win_event_handler_seq, "win_event_handler_seq");
check_uia_hwnd_expects_at_least(1, TRUE, 1, FALSE, 1, FALSE, 1, FALSE, 1, FALSE);
method_sequences_enabled = FALSE;
@ -16909,7 +16900,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
set_uia_hwnd_expects(0, 1, 1, 2, 0);
SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 4); /* Only sent 4 times on Win11. */
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
1, TRUE, FALSE, TRUE);
1, TRUE, FALSE, FALSE);
check_uia_hwnd_expects_at_least(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
@ -16955,7 +16946,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
*/
set_uia_hwnd_expects(1, 1, 1, 4, 3);
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
1, TRUE, FALSE, TRUE);
1, TRUE, FALSE, FALSE);
check_uia_hwnd_expects_at_least(1, TRUE, 1, FALSE, 1, FALSE, 1, FALSE, 1, FALSE);
/* Raise a WinEvent on our test child HWND, both event callbacks invoked. */
@ -16965,7 +16956,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
set_uia_hwnd_expects(0, 2, 2, 4, 0);
SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 8); /* Only sent 8 times on Win11. */
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
ARRAY_SIZE(event_handles), TRUE, TRUE, TRUE);
ARRAY_SIZE(event_handles), TRUE, TRUE, FALSE);
CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 2);
check_uia_hwnd_expects_at_least(0, FALSE, 2, FALSE, 2, FALSE, 2, TRUE, 0, FALSE);
@ -16985,7 +16976,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
set_uia_hwnd_expects(0, 2, 2, 0, 0);
SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 12); /* Only sent 12 times on Win11. */
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, tmp_hwnd2, OBJID_WINDOW, CHILDID_SELF, event_handles,
ARRAY_SIZE(event_handles), TRUE, TRUE, TRUE);
ARRAY_SIZE(event_handles), TRUE, TRUE, FALSE);
CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 2);
check_uia_hwnd_expects_at_least(0, FALSE, 2, FALSE, 2, FALSE, 0, FALSE, 0, FALSE);
@ -17033,7 +17024,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
UIA_AutomationFocusChangedEventId);
set_uia_hwnd_expects(0, 1, 1, 0, 0);
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, GetDesktopWindow(), OBJID_WINDOW, CHILDID_SELF, event_handles,
1, TRUE, FALSE, TRUE);
1, TRUE, FALSE, FALSE);
check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
/*
@ -17074,14 +17065,14 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
/* WinEvent handled. */
set_uia_hwnd_expects(1, 1, 1, 2, 1);
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
1, TRUE, FALSE, TRUE);
1, TRUE, FALSE, FALSE);
check_uia_hwnd_expects(1, TRUE, 1, FALSE, 1, FALSE, 2, FALSE, 1, FALSE);
/* Child HWNDs of our test window are handled as well. */
SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 2);
set_uia_hwnd_expects(0, 1, 1, 1, 0);
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
1, TRUE, FALSE, TRUE);
1, TRUE, FALSE, FALSE);
check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
hr = UiaRemoveEvent(event);
@ -17119,7 +17110,7 @@ skip_win_event_hwnd_filter_test:
/* WinEvent handled by default MSAA proxy provider. */
set_uia_hwnd_expects(1, 1, 1, 4, 5);
test_uia_event_win_event_mapping(EVENT_SYSTEM_ALERT, hwnd[0], OBJID_CLIENT, 2, event_handles,
1, TRUE, FALSE, TRUE);
1, TRUE, FALSE, FALSE);
check_uia_hwnd_expects_at_most(1, 1, 1, 4, 5);
hr = UiaRemoveEvent(event);

View file

@ -322,6 +322,32 @@ static void uia_event_args_release(struct uia_event_args *args)
free(args);
}
struct event_sink_event
{
struct list event_sink_list_entry;
IRawElementProviderSimple *elprov;
struct uia_event_args *args;
};
static HRESULT uia_event_sink_list_add_event(struct list *sink_events, IRawElementProviderSimple *elprov,
struct uia_event_args *args)
{
struct event_sink_event *sink_event = calloc(1, sizeof(*sink_event));
if (!sink_event)
return E_OUTOFMEMORY;
IRawElementProviderSimple_AddRef(elprov);
InterlockedIncrement(&args->ref);
sink_event->elprov = elprov;
sink_event->args = args;
list_add_tail(sink_events, &sink_event->event_sink_list_entry);
return S_OK;
}
/*
* IProxyProviderWinEventSink interface implementation.
*/
@ -331,6 +357,8 @@ struct uia_proxy_win_event_sink {
int event_id;
IUnknown *marshal;
LONG sink_defunct;
struct list sink_events;
};
static inline struct uia_proxy_win_event_sink *impl_from_IProxyProviderWinEventSink(IProxyProviderWinEventSink *iface)
@ -373,6 +401,7 @@ static ULONG WINAPI uia_proxy_win_event_sink_Release(IProxyProviderWinEventSink
if (!ref)
{
assert(list_empty(&sink->sink_events));
IUnknown_Release(sink->marshal);
free(sink);
}
@ -390,8 +419,23 @@ static HRESULT WINAPI uia_proxy_win_event_sink_AddAutomationPropertyChangedEvent
static HRESULT WINAPI uia_proxy_win_event_sink_AddAutomationEvent(IProxyProviderWinEventSink *iface,
IRawElementProviderSimple *elprov, EVENTID event_id)
{
FIXME("%p, %p, %d: stub\n", iface, elprov, event_id);
return S_OK;
struct uia_proxy_win_event_sink *sink = impl_from_IProxyProviderWinEventSink(iface);
struct uia_event_args *args;
HRESULT hr = S_OK;
TRACE("%p, %p, %d\n", iface, elprov, event_id);
if (event_id != sink->event_id)
return S_OK;
args = create_uia_event_args(uia_event_info_from_id(event_id));
if (!args)
return E_OUTOFMEMORY;
if (InterlockedCompareExchange(&sink->sink_defunct, 0, 0) == 0)
hr = uia_event_sink_list_add_event(&sink->sink_events, elprov, args);
uia_event_args_release(args);
return hr;
}
static HRESULT WINAPI uia_proxy_win_event_sink_AddStructureChangedEvent(IProxyProviderWinEventSink *iface,
@ -422,6 +466,7 @@ static HRESULT create_proxy_win_event_sink(struct uia_proxy_win_event_sink **out
sink->IProxyProviderWinEventSink_iface.lpVtbl = &uia_proxy_event_sink_vtbl;
sink->ref = 1;
sink->event_id = event_id;
list_init(&sink->sink_events);
hr = CoCreateFreeThreadedMarshaler((IUnknown *)&sink->IProxyProviderWinEventSink_iface, &sink->marshal);
if (FAILED(hr))
@ -684,9 +729,21 @@ static HRESULT create_msaa_provider_from_hwnd(HWND hwnd, int in_child_id, IRawEl
return S_OK;
}
struct uia_elprov_event_data
{
IRawElementProviderSimple *elprov;
struct uia_event_args *args;
BOOL clientside_only;
SAFEARRAY *rt_id;
HUIANODE node;
};
static HRESULT uia_raise_elprov_event_callback(struct uia_event *event, void *data);
static HRESULT uia_win_event_for_each_callback(struct uia_event *event, void *data)
{
struct uia_queue_win_event *win_event = (struct uia_queue_win_event *)data;
struct event_sink_event *sink_event, *sink_event2;
struct uia_proxy_win_event_sink *sink;
IRawElementProviderSimple *elprov;
struct uia_node *node_data;
@ -727,10 +784,28 @@ static HRESULT uia_win_event_for_each_callback(struct uia_event *event, void *da
{
hr = respond_to_win_event_on_node_provider((IWineUiaNode *)node, i, win_event->event_id, win_event->hwnd, win_event->obj_id,
win_event->child_id, &sink->IProxyProviderWinEventSink_iface);
if (FAILED(hr))
if (FAILED(hr) || !list_empty(&sink->sink_events))
break;
}
InterlockedIncrement(&sink->sink_defunct);
LIST_FOR_EACH_ENTRY_SAFE(sink_event, sink_event2, &sink->sink_events, struct event_sink_event, event_sink_list_entry)
{
struct uia_elprov_event_data event_data = { sink_event->elprov, sink_event->args, TRUE };
list_remove(&sink_event->event_sink_list_entry);
hr = uia_raise_elprov_event_callback(event, (void *)&event_data);
if (FAILED(hr))
WARN("uia_raise_elprov_event_callback failed with hr %#lx\n", hr);
UiaNodeRelease(event_data.node);
SafeArrayDestroy(event_data.rt_id);
IRawElementProviderSimple_Release(sink_event->elprov);
uia_event_args_release(sink_event->args);
free(sink_event);
}
IProxyProviderWinEventSink_Release(&sink->IProxyProviderWinEventSink_iface);
}
@ -1806,16 +1881,6 @@ static HRESULT uia_event_check_match(HUIANODE node, HUIANODE nav_start_node, SAF
return hr;
}
struct uia_elprov_event_data
{
IRawElementProviderSimple *elprov;
struct uia_event_args *args;
BOOL clientside_only;
SAFEARRAY *rt_id;
HUIANODE node;
};
static HRESULT uia_raise_elprov_event_callback(struct uia_event *event, void *data)
{
struct uia_elprov_event_data *event_data = (struct uia_elprov_event_data *)data;