uiautomationcore: Create HUIANODE for WinEvents that should invoke IProxyProviderWinEventHandler::RespondToWinEvent.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
bc063b67ab
commit
01d9a5ea2b
2 changed files with 91 additions and 15 deletions
|
@ -1761,6 +1761,15 @@ 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. */ \
|
||||
|
@ -16708,11 +16717,17 @@ 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 },
|
||||
{ &Provider_hwnd2, WINEVENT_HANDLER_RESPOND_TO_WINEVENT },
|
||||
NODE_CREATE_SEQ(&Provider_child),
|
||||
{ &Provider_child, FRAG_GET_RUNTIME_ID },
|
||||
{ &Provider_child, PROV_GET_PROPERTY_VALUE }, /* UIA_ProviderDescriptionPropertyId */
|
||||
/*
|
||||
* The following two are currently only done on Wine. Windows doesn't do
|
||||
* this because the node created is never passed out of the event thread.
|
||||
*/
|
||||
{ &Provider_nc2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
|
||||
{ &Provider_hwnd2, PROV_GET_PROVIDER_OPTIONS, METHOD_OPTIONAL },
|
||||
{ &Provider_nc2, WINEVENT_HANDLER_RESPOND_TO_WINEVENT, METHOD_TODO },
|
||||
{ &Provider_hwnd2, WINEVENT_HANDLER_RESPOND_TO_WINEVENT, METHOD_TODO },
|
||||
NODE_CREATE_SEQ_TODO(&Provider_child),
|
||||
{ &Provider_child, FRAG_GET_RUNTIME_ID, METHOD_TODO },
|
||||
{ &Provider_child, PROV_GET_PROPERTY_VALUE, METHOD_TODO }, /* UIA_ProviderDescriptionPropertyId */
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -16846,9 +16861,8 @@ 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);
|
||||
if (CALLED_COUNT(winproc_GETOBJECT_CLIENT))
|
||||
ok_method_sequence(win_event_handler_seq, "win_event_handler_seq");
|
||||
check_uia_hwnd_expects_at_least(1, TRUE, 1, TRUE, 1, TRUE, 1, FALSE, 1, TRUE);
|
||||
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;
|
||||
|
||||
/*
|
||||
|
@ -16894,7 +16908,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
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);
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, TRUE, 1, TRUE, 1, TRUE, 0, FALSE);
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
|
||||
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
|
||||
/*
|
||||
|
@ -16940,7 +16954,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);
|
||||
check_uia_hwnd_expects_at_least(1, TRUE, 1, TRUE, 1, TRUE, 1, FALSE, 1, TRUE);
|
||||
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. */
|
||||
child_win_prov_root = NULL;
|
||||
|
@ -16951,7 +16965,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
|
||||
ARRAY_SIZE(event_handles), TRUE, TRUE, TRUE);
|
||||
CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 2);
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 2, TRUE, 2, TRUE, 2, TRUE, 0, FALSE);
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 2, FALSE, 2, FALSE, 2, TRUE, 0, FALSE);
|
||||
|
||||
/*
|
||||
* Raise a WinEvent on a descendant HWND of our test HWND. If any ancestor
|
||||
|
@ -16971,7 +16985,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, tmp_hwnd2, OBJID_WINDOW, CHILDID_SELF, event_handles,
|
||||
ARRAY_SIZE(event_handles), TRUE, TRUE, TRUE);
|
||||
CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 2);
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 2, TRUE, 2, TRUE, 0, FALSE, 0, FALSE);
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 2, FALSE, 2, FALSE, 0, FALSE, 0, FALSE);
|
||||
|
||||
DestroyWindow(tmp_hwnd);
|
||||
Provider_nc3.hwnd = Provider_hwnd3.hwnd = hwnd[1];
|
||||
|
@ -17018,7 +17032,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
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);
|
||||
check_uia_hwnd_expects(0, FALSE, 1, TRUE, 1, TRUE, 0, FALSE, 0, FALSE);
|
||||
check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
|
||||
|
||||
/*
|
||||
* Top-level HWND, a child of the desktop HWND. Will not have an event
|
||||
|
@ -17059,14 +17073,14 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
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);
|
||||
check_uia_hwnd_expects(1, TRUE, 1, TRUE, 1, TRUE, 2, TRUE, 1, TRUE);
|
||||
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);
|
||||
check_uia_hwnd_expects(0, FALSE, 1, TRUE, 1, TRUE, 1, TRUE, 0, FALSE);
|
||||
check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
|
||||
|
||||
hr = UiaRemoveEvent(event);
|
||||
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
|
||||
|
|
|
@ -528,9 +528,57 @@ static BOOL uia_win_event_hwnd_map_contains_ancestors(struct rb_tree *hwnd_map,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static HRESULT create_msaa_provider_from_hwnd(HWND hwnd, int in_child_id, IRawElementProviderSimple **ret_elprov)
|
||||
{
|
||||
IRawElementProviderSimple *elprov;
|
||||
IAccessible *acc;
|
||||
int child_id;
|
||||
HRESULT hr;
|
||||
|
||||
*ret_elprov = NULL;
|
||||
hr = AccessibleObjectFromWindow(hwnd, OBJID_CLIENT, &IID_IAccessible, (void **)&acc);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
child_id = in_child_id;
|
||||
if (in_child_id != CHILDID_SELF)
|
||||
{
|
||||
IDispatch *disp;
|
||||
VARIANT cid;
|
||||
|
||||
disp = NULL;
|
||||
variant_init_i4(&cid, in_child_id);
|
||||
hr = IAccessible_get_accChild(acc, cid, &disp);
|
||||
if (FAILED(hr))
|
||||
TRACE("get_accChild failed with %#lx!\n", hr);
|
||||
|
||||
if (SUCCEEDED(hr) && disp)
|
||||
{
|
||||
IAccessible_Release(acc);
|
||||
hr = IDispatch_QueryInterface(disp, &IID_IAccessible, (void **)&acc);
|
||||
IDispatch_Release(disp);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
child_id = CHILDID_SELF;
|
||||
}
|
||||
}
|
||||
|
||||
hr = create_msaa_provider(acc, child_id, hwnd, in_child_id == CHILDID_SELF, &elprov);
|
||||
IAccessible_Release(acc);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
*ret_elprov = elprov;
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
IRawElementProviderSimple *elprov;
|
||||
HUIANODE node;
|
||||
HRESULT hr;
|
||||
|
||||
/*
|
||||
* Check if this HWND, or any of it's ancestors (excluding the desktop)
|
||||
|
@ -544,8 +592,22 @@ static HRESULT uia_win_event_for_each_callback(struct uia_event *event, void *da
|
|||
if (UiaHasServerSideProvider(win_event->hwnd))
|
||||
return S_OK;
|
||||
|
||||
/*
|
||||
* Regardless of the object ID of the WinEvent, OBJID_CLIENT is queried
|
||||
* for the HWND with the same child ID as the WinEvent.
|
||||
*/
|
||||
hr = create_msaa_provider_from_hwnd(win_event->hwnd, win_event->child_id, &elprov);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = create_uia_node_from_elprov(elprov, &node, TRUE);
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
FIXME("IProxyProviderWinEventHandler usage is currently unimplemented.\n");
|
||||
|
||||
UiaNodeRelease(node);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue