uiautomationcore: Pass WinEvent data to IProxyProviderWinEventHandler::RespondToWinEvent.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
0254db3492
commit
7aaf77a514
5 changed files with 192 additions and 7 deletions
|
@ -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);
|
||||
|
||||
|
@ -323,6 +322,118 @@ static void uia_event_args_release(struct uia_event_args *args)
|
|||
free(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.
|
||||
*/
|
||||
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue