uiautomationcore: Add support for raising events passed to our IProxyProviderWinEventSink interface.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
7aaf77a514
commit
60ff77754a
2 changed files with 90 additions and 34 deletions
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue