uiautomationcore: Unconditionally match all events registered on the desktop node with a scope of subtree.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
c5b2c0369b
commit
c7431990d8
5 changed files with 96 additions and 18 deletions
|
@ -14237,6 +14237,49 @@ static void test_UiaAddEvent(void)
|
|||
todo_wine CHECK_CALLED_MULTI(prov_callback_proxy, 2);
|
||||
CHECK_CALLED(uia_event_callback);
|
||||
|
||||
hr = UiaRemoveEvent(event);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
|
||||
/*
|
||||
* Register an event on the desktop HWND with a scope of TreeScope_Element
|
||||
* and TreeScope_Descendants. This is a special case where all providers
|
||||
* will match, regardless of whether or not they can navigate to the
|
||||
* desktop node.
|
||||
*/
|
||||
set_cache_request(&cache_req, (struct UiaCondition *)&UiaTrueCondition, TreeScope_Element, NULL, 0, NULL, 0,
|
||||
AutomationElementMode_Full);
|
||||
hr = UiaAddEvent(node, UIA_AutomationFocusChangedEventId, uia_event_callback, TreeScope_Element | TreeScope_Descendants, NULL, 0,
|
||||
&cache_req, &event);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
ok(!!event, "event == NULL\n");
|
||||
|
||||
/*
|
||||
* Raise an event on Provider2 - completely disconnected from all other
|
||||
* providers, will still trigger the event callback.
|
||||
*/
|
||||
initialize_provider(&Provider2, ProviderOptions_ServerSideProvider, NULL, TRUE);
|
||||
init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), NULL);
|
||||
add_provider_desc(&exp_node_desc, L"Main", L"Provider2", TRUE);
|
||||
set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
|
||||
SET_EXPECT(uia_event_callback);
|
||||
hr = UiaRaiseAutomationEvent(&Provider2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
CHECK_CALLED(uia_event_callback);
|
||||
|
||||
/*
|
||||
* No clientside providers to match us to the desktop node through
|
||||
* navigation, but event will still be triggered.
|
||||
*/
|
||||
init_node_provider_desc(&exp_node_desc, GetCurrentProcessId(), hwnd);
|
||||
add_provider_desc(&exp_node_desc, L"Main", L"Provider_hwnd2", TRUE);
|
||||
set_event_data(0, 0, 1, 1, &exp_node_desc, L"P)");
|
||||
SET_EXPECT(uia_event_callback);
|
||||
Provider_hwnd2.prov_opts = ProviderOptions_ServerSideProvider;
|
||||
Provider_hwnd2.ignore_hwnd_prop = TRUE;
|
||||
hr = UiaRaiseAutomationEvent(&Provider_hwnd2.IRawElementProviderSimple_iface, UIA_AutomationFocusChangedEventId);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
CHECK_CALLED(uia_event_callback);
|
||||
|
||||
hr = UiaRemoveEvent(event);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
UiaNodeRelease(node);
|
||||
|
|
|
@ -2692,30 +2692,12 @@ HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIAN
|
|||
return hr;
|
||||
}
|
||||
|
||||
#define UIA_RUNTIME_ID_PREFIX 42
|
||||
|
||||
enum fragment_root_prov_type_ids {
|
||||
FRAGMENT_ROOT_NONCLIENT_TYPE_ID = 0x03,
|
||||
FRAGMENT_ROOT_MAIN_TYPE_ID = 0x04,
|
||||
FRAGMENT_ROOT_OVERRIDE_TYPE_ID = 0x05,
|
||||
};
|
||||
|
||||
static HRESULT write_runtime_id_base(SAFEARRAY *sa, HWND hwnd)
|
||||
{
|
||||
const int rt_id[2] = { UIA_RUNTIME_ID_PREFIX, HandleToUlong(hwnd) };
|
||||
HRESULT hr;
|
||||
LONG idx;
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(rt_id); idx++)
|
||||
{
|
||||
hr = SafeArrayPutElement(sa, &idx, (void *)&rt_id[idx]);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static SAFEARRAY *append_uia_runtime_id(SAFEARRAY *sa, HWND hwnd, enum ProviderOptions root_opts)
|
||||
{
|
||||
LONG i, idx, lbound, elems;
|
||||
|
|
|
@ -24,6 +24,32 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
|
||||
|
||||
static SAFEARRAY *uia_desktop_node_rt_id;
|
||||
static BOOL WINAPI uia_init_desktop_rt_id(INIT_ONCE *once, void *param, void **ctx)
|
||||
{
|
||||
SAFEARRAY *sa;
|
||||
|
||||
if ((sa = SafeArrayCreateVector(VT_I4, 0, 2)))
|
||||
{
|
||||
if (SUCCEEDED(write_runtime_id_base(sa, GetDesktopWindow())))
|
||||
uia_desktop_node_rt_id = sa;
|
||||
else
|
||||
SafeArrayDestroy(sa);
|
||||
}
|
||||
|
||||
return !!uia_desktop_node_rt_id;
|
||||
}
|
||||
|
||||
static SAFEARRAY *uia_get_desktop_rt_id(void)
|
||||
{
|
||||
static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
|
||||
|
||||
if (!uia_desktop_node_rt_id)
|
||||
InitOnceExecuteOnce(&once, uia_init_desktop_rt_id, NULL, NULL);
|
||||
|
||||
return uia_desktop_node_rt_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* UI Automation event map.
|
||||
*/
|
||||
|
@ -81,8 +107,13 @@ static struct uia_event_map_entry *uia_get_event_map_entry_for_event(int event_i
|
|||
|
||||
static HRESULT uia_event_map_add_event(struct uia_event *event)
|
||||
{
|
||||
const int subtree_scope = TreeScope_Element | TreeScope_Descendants;
|
||||
struct uia_event_map_entry *event_entry;
|
||||
|
||||
if (((event->scope & subtree_scope) == subtree_scope) && event->runtime_id &&
|
||||
!uia_compare_safearrays(uia_get_desktop_rt_id(), event->runtime_id, UIAutomationType_IntArray))
|
||||
event->desktop_subtree_event = TRUE;
|
||||
|
||||
EnterCriticalSection(&event_map_cs);
|
||||
|
||||
if (!(event_entry = uia_get_event_map_entry_for_event(event->event_id)))
|
||||
|
@ -539,6 +570,9 @@ static HRESULT uia_event_check_match(HUIANODE node, SAFEARRAY *rt_id, struct Uia
|
|||
if (!event->runtime_id)
|
||||
return S_OK;
|
||||
|
||||
if (event->desktop_subtree_event)
|
||||
return uia_event_invoke(node, args, event);
|
||||
|
||||
if (rt_id && !uia_compare_safearrays(rt_id, event->runtime_id, UIAutomationType_IntArray))
|
||||
{
|
||||
if (event->scope & TreeScope_Element)
|
||||
|
|
|
@ -98,6 +98,7 @@ struct uia_event
|
|||
IWineUiaEvent IWineUiaEvent_iface;
|
||||
LONG ref;
|
||||
|
||||
BOOL desktop_subtree_event;
|
||||
SAFEARRAY *runtime_id;
|
||||
int event_id;
|
||||
int scope;
|
||||
|
@ -190,6 +191,7 @@ HRESULT create_msaa_provider(IAccessible *acc, long child_id, HWND hwnd, BOOL kn
|
|||
HRESULT register_interface_in_git(IUnknown *iface, REFIID riid, DWORD *ret_cookie) DECLSPEC_HIDDEN;
|
||||
HRESULT unregister_interface_in_git(DWORD git_cookie) DECLSPEC_HIDDEN;
|
||||
HRESULT get_interface_in_git(REFIID riid, DWORD git_cookie, IUnknown **ret_iface) DECLSPEC_HIDDEN;
|
||||
HRESULT write_runtime_id_base(SAFEARRAY *sa, HWND hwnd) DECLSPEC_HIDDEN;
|
||||
void uia_cache_request_destroy(struct UiaCacheRequest *cache_req) DECLSPEC_HIDDEN;
|
||||
HRESULT uia_cache_request_clone(struct UiaCacheRequest *dst, struct UiaCacheRequest *src) DECLSPEC_HIDDEN;
|
||||
HRESULT get_safearray_dim_bounds(SAFEARRAY *sa, UINT dim, LONG *lbound, LONG *elems) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -98,6 +98,23 @@ HRESULT get_interface_in_git(REFIID riid, DWORD git_cookie, IUnknown **ret_iface
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
#define UIA_RUNTIME_ID_PREFIX 42
|
||||
HRESULT write_runtime_id_base(SAFEARRAY *sa, HWND hwnd)
|
||||
{
|
||||
const int rt_id[2] = { UIA_RUNTIME_ID_PREFIX, HandleToUlong(hwnd) };
|
||||
HRESULT hr;
|
||||
LONG idx;
|
||||
|
||||
for (idx = 0; idx < ARRAY_SIZE(rt_id); idx++)
|
||||
{
|
||||
hr = SafeArrayPutElement(sa, &idx, (void *)&rt_id[idx]);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* UiaCondition cloning functions.
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue