Commit 7aaf77a5 authored by Connor McAdams's avatar Connor McAdams Committed by Alexandre Julliard

uiautomationcore: Pass WinEvent data to IProxyProviderWinEventHandler::RespondToWinEvent.

parent 0254db34
......@@ -449,6 +449,11 @@ static void test_implements_interface_(IUnknown *unk, const GUID *iid, BOOL exp_
IUnknown_Release(unk2);
}
#define check_interface_marshal_proxy_creation( iface, iid, expect_proxy ) \
check_interface_marshal_proxy_creation_( (iface), (iid), (expect_proxy), __FILE__, __LINE__)
static void check_interface_marshal_proxy_creation_(IUnknown *iface, REFIID iid, BOOL expect_proxy, const char *file,
int line);
#define DEFINE_ACC_METHOD_EXPECT(method) \
int expect_ ## method , called_ ## method
......@@ -2824,6 +2829,11 @@ static HRESULT WINAPI ProviderWinEventHandler_RespondToWinEvent(IProxyProviderWi
if (data->responder_prov)
{
/*
* The IProxyProviderWinEventSink interface uses the free threaded
* marshaler, so no proxy will be created in-process.
*/
check_interface_marshal_proxy_creation((IUnknown *)event_sink, &IID_IProxyProviderWinEventSink, FALSE);
hr = IProxyProviderWinEventSink_AddAutomationEvent(event_sink, data->responder_prov, data->responder_event);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
}
......@@ -11976,8 +11986,6 @@ static DWORD WINAPI interface_marshal_proxy_thread(LPVOID param)
return 0;
}
#define check_interface_marshal_proxy_creation( iface, iid, expect_proxy ) \
check_interface_marshal_proxy_creation_( (iface), (iid), (expect_proxy), __FILE__, __LINE__)
static void check_interface_marshal_proxy_creation_(IUnknown *iface, REFIID iid, BOOL expect_proxy, const char *file,
int line)
{
......@@ -16717,8 +16725,8 @@ static const struct prov_method_sequence win_event_handler_seq[] = {
{ &Provider_hwnd2, PROV_GET_HOST_RAW_ELEMENT_PROVIDER, METHOD_OPTIONAL }, /* Only done on Win10v1809+. */
{ &Provider_nc2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
{ &Provider_hwnd2, FRAG_NAVIGATE }, /* NavigateDirection_Parent */
{ &Provider_nc2, WINEVENT_HANDLER_RESPOND_TO_WINEVENT, METHOD_TODO },
{ &Provider_hwnd2, WINEVENT_HANDLER_RESPOND_TO_WINEVENT, METHOD_TODO },
{ &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 */
......
......@@ -19,6 +19,7 @@
#pragma makedep regtypelib
import "oaidl.idl";
import "uiautomationcore.idl";
struct uia_prop_info {
const GUID *guid;
......@@ -92,6 +93,8 @@ library UIA_wine_private
HRESULT navigate([in]int nav_dir, [out, retval]VARIANT *ret_val);
HRESULT get_focus([out, retval]VARIANT *ret_val);
HRESULT attach_event([in]LONG_PTR huiaevent);
HRESULT respond_to_win_event([in]DWORD win_event, [in]ULONG hwnd, [in]LONG obj_id, [in]LONG child_id,
[in]IProxyProviderWinEventSink *sink);
}
[
......
......@@ -378,6 +378,22 @@ static HRESULT attach_event_to_node_provider(IWineUiaNode *node, int idx, HUIAEV
return hr;
}
HRESULT respond_to_win_event_on_node_provider(IWineUiaNode *node, int idx, DWORD win_event, HWND hwnd, LONG obj_id,
LONG child_id, IProxyProviderWinEventSink *sink)
{
IWineUiaProvider *prov;
HRESULT hr;
hr = IWineUiaNode_get_provider(node, idx, &prov);
if (FAILED(hr))
return hr;
hr = IWineUiaProvider_respond_to_win_event(prov, win_event, HandleToUlong(hwnd), obj_id, child_id, sink);
IWineUiaProvider_Release(prov);
return hr;
}
/*
* IWineUiaNode interface.
*/
......@@ -1939,6 +1955,23 @@ exit:
return hr;
}
static HRESULT WINAPI uia_provider_respond_to_win_event(IWineUiaProvider *iface, DWORD win_event, ULONG hwnd, LONG obj_id,
LONG child_id, IProxyProviderWinEventSink *sink)
{
struct uia_provider *prov = impl_from_IWineUiaProvider(iface);
IProxyProviderWinEventHandler *handler;
HRESULT hr;
hr = IRawElementProviderSimple_QueryInterface(prov->elprov, &IID_IProxyProviderWinEventHandler, (void **)&handler);
if (FAILED(hr))
return S_OK;
hr = IProxyProviderWinEventHandler_RespondToWinEvent(handler, win_event, UlongToHandle(hwnd), obj_id, child_id, sink);
IProxyProviderWinEventHandler_Release(handler);
return hr;
}
static const IWineUiaProviderVtbl uia_provider_vtbl = {
uia_provider_QueryInterface,
uia_provider_AddRef,
......@@ -1949,6 +1982,7 @@ static const IWineUiaProviderVtbl uia_provider_vtbl = {
uia_provider_navigate,
uia_provider_get_focus,
uia_provider_attach_event,
uia_provider_respond_to_win_event,
};
static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProviderSimple *elprov,
......@@ -2388,6 +2422,15 @@ static HRESULT WINAPI uia_nested_node_provider_attach_event(IWineUiaProvider *if
return hr;
}
static HRESULT WINAPI uia_nested_node_provider_respond_to_win_event(IWineUiaProvider *iface, DWORD win_event, ULONG hwnd,
LONG obj_id, LONG child_id, IProxyProviderWinEventSink *sink)
{
FIXME("%p, %#lx, #%lx, %#lx, %#lx, %p: stub\n", iface, win_event, hwnd, obj_id, child_id, sink);
/* This should not be called. */
assert(0);
return E_FAIL;
}
static const IWineUiaProviderVtbl uia_nested_node_provider_vtbl = {
uia_nested_node_provider_QueryInterface,
uia_nested_node_provider_AddRef,
......@@ -2398,6 +2441,7 @@ static const IWineUiaProviderVtbl uia_nested_node_provider_vtbl = {
uia_nested_node_provider_navigate,
uia_nested_node_provider_get_focus,
uia_nested_node_provider_attach_event,
uia_nested_node_provider_respond_to_win_event,
};
static BOOL is_nested_node_provider(IWineUiaProvider *iface)
......
......@@ -20,7 +20,6 @@
#include "wine/debug.h"
#include "wine/rbtree.h"
#include "assert.h"
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
......@@ -324,6 +323,118 @@ static void uia_event_args_release(struct uia_event_args *args)
}
/*
* IProxyProviderWinEventSink interface implementation.
*/
struct uia_proxy_win_event_sink {
IProxyProviderWinEventSink IProxyProviderWinEventSink_iface;
LONG ref;
int event_id;
IUnknown *marshal;
};
static inline struct uia_proxy_win_event_sink *impl_from_IProxyProviderWinEventSink(IProxyProviderWinEventSink *iface)
{
return CONTAINING_RECORD(iface, struct uia_proxy_win_event_sink, IProxyProviderWinEventSink_iface);
}
static HRESULT WINAPI uia_proxy_win_event_sink_QueryInterface(IProxyProviderWinEventSink *iface, REFIID riid, void **obj)
{
struct uia_proxy_win_event_sink *sink = impl_from_IProxyProviderWinEventSink(iface);
*obj = NULL;
if (IsEqualIID(riid, &IID_IProxyProviderWinEventSink) || IsEqualIID(riid, &IID_IUnknown))
*obj = iface;
else if (IsEqualIID(riid, &IID_IMarshal))
return IUnknown_QueryInterface(sink->marshal, riid, obj);
else
return E_NOINTERFACE;
IProxyProviderWinEventSink_AddRef(iface);
return S_OK;
}
static ULONG WINAPI uia_proxy_win_event_sink_AddRef(IProxyProviderWinEventSink *iface)
{
struct uia_proxy_win_event_sink *sink = impl_from_IProxyProviderWinEventSink(iface);
ULONG ref = InterlockedIncrement(&sink->ref);
TRACE("%p, refcount %ld\n", sink, ref);
return ref;
}
static ULONG WINAPI uia_proxy_win_event_sink_Release(IProxyProviderWinEventSink *iface)
{
struct uia_proxy_win_event_sink *sink = impl_from_IProxyProviderWinEventSink(iface);
ULONG ref = InterlockedDecrement(&sink->ref);
TRACE("%p, refcount %ld\n", sink, ref);
if (!ref)
{
IUnknown_Release(sink->marshal);
free(sink);
}
return ref;
}
static HRESULT WINAPI uia_proxy_win_event_sink_AddAutomationPropertyChangedEvent(IProxyProviderWinEventSink *iface,
IRawElementProviderSimple *elprov, PROPERTYID prop_id, VARIANT new_value)
{
FIXME("%p, %p, %d, %s: stub\n", iface, elprov, prop_id, debugstr_variant(&new_value));
return E_NOTIMPL;
}
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;
}
static HRESULT WINAPI uia_proxy_win_event_sink_AddStructureChangedEvent(IProxyProviderWinEventSink *iface,
IRawElementProviderSimple *elprov, enum StructureChangeType structure_change_type, SAFEARRAY *runtime_id)
{
FIXME("%p, %p, %d, %p: stub\n", iface, elprov, structure_change_type, runtime_id);
return E_NOTIMPL;
}
static const IProxyProviderWinEventSinkVtbl uia_proxy_event_sink_vtbl = {
uia_proxy_win_event_sink_QueryInterface,
uia_proxy_win_event_sink_AddRef,
uia_proxy_win_event_sink_Release,
uia_proxy_win_event_sink_AddAutomationPropertyChangedEvent,
uia_proxy_win_event_sink_AddAutomationEvent,
uia_proxy_win_event_sink_AddStructureChangedEvent,
};
static HRESULT create_proxy_win_event_sink(struct uia_proxy_win_event_sink **out_sink, int event_id)
{
struct uia_proxy_win_event_sink *sink = calloc(1, sizeof(*sink));
HRESULT hr;
*out_sink = NULL;
if (!sink)
return E_OUTOFMEMORY;
sink->IProxyProviderWinEventSink_iface.lpVtbl = &uia_proxy_event_sink_vtbl;
sink->ref = 1;
sink->event_id = event_id;
hr = CoCreateFreeThreadedMarshaler((IUnknown *)&sink->IProxyProviderWinEventSink_iface, &sink->marshal);
if (FAILED(hr))
{
free(sink);
return hr;
}
*out_sink = sink;
return S_OK;
}
/*
* UI Automation event thread.
*/
struct uia_event_thread
......@@ -576,9 +687,12 @@ static HRESULT create_msaa_provider_from_hwnd(HWND hwnd, int in_child_id, IRawEl
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 uia_proxy_win_event_sink *sink;
IRawElementProviderSimple *elprov;
struct uia_node *node_data;
HUIANODE node;
HRESULT hr;
int i;
/*
* Check if this HWND, or any of it's ancestors (excluding the desktop)
......@@ -605,10 +719,23 @@ static HRESULT uia_win_event_for_each_callback(struct uia_event *event, void *da
if (FAILED(hr))
return hr;
FIXME("IProxyProviderWinEventHandler usage is currently unimplemented.\n");
hr = create_proxy_win_event_sink(&sink, event->event_id);
if (SUCCEEDED(hr))
{
node_data = impl_from_IWineUiaNode((IWineUiaNode *)node);
for (i = 0; i < node_data->prov_count; i++)
{
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))
break;
}
IProxyProviderWinEventSink_Release(&sink->IProxyProviderWinEventSink_iface);
}
UiaNodeRelease(node);
return S_OK;
return hr;
}
static void uia_event_thread_process_queue(struct list *event_queue)
......
......@@ -22,6 +22,7 @@
#include "uia_classes.h"
#include "wine/list.h"
#include "wine/rbtree.h"
#include "assert.h"
extern HMODULE huia_module DECLSPEC_HIDDEN;
......@@ -210,6 +211,8 @@ static inline BOOL uia_array_reserve(void **elements, SIZE_T *capacity, SIZE_T c
/* uia_client.c */
int get_node_provider_type_at_idx(struct uia_node *node, int idx) DECLSPEC_HIDDEN;
HRESULT respond_to_win_event_on_node_provider(IWineUiaNode *node, int idx, DWORD win_event, HWND hwnd, LONG obj_id,
LONG child_id, IProxyProviderWinEventSink *sink) DECLSPEC_HIDDEN;
HRESULT attach_event_to_uia_node(HUIANODE node, struct uia_event *event) DECLSPEC_HIDDEN;
HRESULT clone_uia_node(HUIANODE in_node, HUIANODE *out_node) DECLSPEC_HIDDEN;
HRESULT navigate_uia_node(struct uia_node *node, int nav_dir, HUIANODE *out_node) DECLSPEC_HIDDEN;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment