uiautomationcore: Check if we should try to invoke IProxyProviderWinEventHandler::RespondToWinEvent for registered UIA events.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
b9cf4e9896
commit
bc063b67ab
5 changed files with 65 additions and 16 deletions
|
@ -16823,7 +16823,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
SET_EXPECT_MULTI(winproc_GETOBJECT_UiaRoot, 2); /* Only called twice on Win11. */
|
||||
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[0], OBJID_WINDOW, CHILDID_SELF, event_handles,
|
||||
1, FALSE, FALSE, FALSE);
|
||||
todo_wine CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
|
||||
CHECK_CALLED(winproc_GETOBJECT_UiaRoot);
|
||||
|
||||
/*
|
||||
* Get rid of our serverside provider and raise EVENT_OBJECT_FOCUS
|
||||
|
@ -16848,7 +16848,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
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, TRUE, 1, TRUE);
|
||||
check_uia_hwnd_expects_at_least(1, TRUE, 1, TRUE, 1, TRUE, 1, FALSE, 1, TRUE);
|
||||
method_sequences_enabled = FALSE;
|
||||
|
||||
/*
|
||||
|
@ -16895,7 +16895,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,
|
||||
1, TRUE, FALSE, TRUE);
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, TRUE, 1, TRUE, 1, TRUE, 0, FALSE);
|
||||
todo_wine CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
|
||||
/*
|
||||
* Child HWND now has a serverside provider, WinEvent is ignored.
|
||||
|
@ -16906,7 +16906,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 2); /* Only sent 2 times on Win11. */
|
||||
test_uia_event_win_event_mapping(EVENT_OBJECT_FOCUS, hwnd[1], OBJID_WINDOW, CHILDID_SELF, event_handles,
|
||||
1, FALSE, FALSE, FALSE);
|
||||
todo_wine CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
CHECK_CALLED_AT_MOST(winproc_GETOBJECT_UiaRoot, 1);
|
||||
|
||||
/*
|
||||
|
@ -16940,7 +16940,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, TRUE, 1, TRUE);
|
||||
check_uia_hwnd_expects_at_least(1, TRUE, 1, TRUE, 1, TRUE, 1, FALSE, 1, TRUE);
|
||||
|
||||
/* Raise a WinEvent on our test child HWND, both event callbacks invoked. */
|
||||
child_win_prov_root = NULL;
|
||||
|
@ -16950,7 +16950,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
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);
|
||||
todo_wine CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 2);
|
||||
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);
|
||||
|
||||
/*
|
||||
|
@ -16970,7 +16970,7 @@ static DWORD WINAPI uia_proxy_provider_win_event_handler_test_thread(LPVOID para
|
|||
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);
|
||||
todo_wine CHECK_CALLED_AT_LEAST(child_winproc_GETOBJECT_UiaRoot, 2);
|
||||
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);
|
||||
|
||||
DestroyWindow(tmp_hwnd);
|
||||
|
|
|
@ -511,6 +511,44 @@ static HRESULT uia_raise_serverside_event(struct uia_queue_uia_event *event)
|
|||
return hr;
|
||||
}
|
||||
|
||||
/* Check the parent chain of HWNDs, excluding the desktop. */
|
||||
static BOOL uia_win_event_hwnd_map_contains_ancestors(struct rb_tree *hwnd_map, HWND hwnd)
|
||||
{
|
||||
HWND parent = GetAncestor(hwnd, GA_PARENT);
|
||||
const HWND desktop = GetDesktopWindow();
|
||||
|
||||
while (parent && (parent != desktop))
|
||||
{
|
||||
if (uia_hwnd_map_check_hwnd(hwnd_map, parent))
|
||||
return TRUE;
|
||||
|
||||
parent = GetAncestor(parent, GA_PARENT);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/*
|
||||
* Check if this HWND, or any of it's ancestors (excluding the desktop)
|
||||
* are in our scope.
|
||||
*/
|
||||
if (!uia_hwnd_map_check_hwnd(&event->u.clientside.win_event_hwnd_map, win_event->hwnd) &&
|
||||
!uia_win_event_hwnd_map_contains_ancestors(&event->u.clientside.win_event_hwnd_map, win_event->hwnd))
|
||||
return S_OK;
|
||||
|
||||
/* Has a native serverside provider, no need to do WinEvent translation. */
|
||||
if (UiaHasServerSideProvider(win_event->hwnd))
|
||||
return S_OK;
|
||||
|
||||
FIXME("IProxyProviderWinEventHandler usage is currently unimplemented.\n");
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void uia_event_thread_process_queue(struct list *event_queue)
|
||||
{
|
||||
while (1)
|
||||
|
@ -538,6 +576,15 @@ static void uia_event_thread_process_queue(struct list *event_queue)
|
|||
break;
|
||||
}
|
||||
|
||||
case QUEUE_EVENT_TYPE_WIN_EVENT:
|
||||
{
|
||||
struct uia_queue_win_event *win_event = (struct uia_queue_win_event *)event;
|
||||
|
||||
hr = uia_event_for_each(win_event_to_uia_event_id(win_event->event_id), uia_win_event_for_each_callback,
|
||||
(void *)win_event, TRUE);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -255,6 +255,8 @@ HRESULT get_safearray_dim_bounds(SAFEARRAY *sa, UINT dim, LONG *lbound, LONG *el
|
|||
HRESULT get_safearray_bounds(SAFEARRAY *sa, LONG *lbound, LONG *elems) DECLSPEC_HIDDEN;
|
||||
int uia_compare_safearrays(SAFEARRAY *sa1, SAFEARRAY *sa2, int prop_type) DECLSPEC_HIDDEN;
|
||||
BOOL uia_hwnd_is_visible(HWND hwnd) DECLSPEC_HIDDEN;
|
||||
BOOL uia_is_top_level_hwnd(HWND hwnd) DECLSPEC_HIDDEN;
|
||||
BOOL uia_hwnd_map_check_hwnd(struct rb_tree *hwnd_map, HWND hwnd) DECLSPEC_HIDDEN;
|
||||
HRESULT uia_hwnd_map_add_hwnd(struct rb_tree *hwnd_map, HWND hwnd) DECLSPEC_HIDDEN;
|
||||
void uia_hwnd_map_init(struct rb_tree *hwnd_map) DECLSPEC_HIDDEN;
|
||||
void uia_hwnd_map_destroy(struct rb_tree *hwnd_map) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -1545,11 +1545,6 @@ static HRESULT uia_send_message_timeout(HWND hwnd, UINT msg, WPARAM wparam, LPAR
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static BOOL is_top_level_hwnd(HWND hwnd)
|
||||
{
|
||||
return GetAncestor(hwnd, GA_PARENT) == GetDesktopWindow();
|
||||
}
|
||||
|
||||
static HRESULT get_uia_control_type_for_hwnd(HWND hwnd, int *control_type)
|
||||
{
|
||||
LONG_PTR style, ex_style;
|
||||
|
@ -1576,7 +1571,7 @@ static HRESULT get_uia_control_type_for_hwnd(HWND hwnd, int *control_type)
|
|||
}
|
||||
|
||||
/* Non top-level HWNDs are considered panes as well. */
|
||||
if (!is_top_level_hwnd(hwnd))
|
||||
if (!uia_is_top_level_hwnd(hwnd))
|
||||
*control_type = UIA_PaneControlTypeId;
|
||||
else
|
||||
*control_type = UIA_WindowControlTypeId;
|
||||
|
@ -1816,7 +1811,7 @@ static HRESULT WINAPI base_hwnd_fragment_Navigate(IRawElementProviderFragment *i
|
|||
* Top level owned windows have their owner window as a parent instead
|
||||
* of the desktop window.
|
||||
*/
|
||||
if (is_top_level_hwnd(base_hwnd_prov->hwnd) && (owner = GetWindow(base_hwnd_prov->hwnd, GW_OWNER)))
|
||||
if (uia_is_top_level_hwnd(base_hwnd_prov->hwnd) && (owner = GetWindow(base_hwnd_prov->hwnd, GW_OWNER)))
|
||||
parent = owner;
|
||||
else
|
||||
parent = GetAncestor(base_hwnd_prov->hwnd, GA_PARENT);
|
||||
|
@ -1866,7 +1861,7 @@ static HRESULT WINAPI base_hwnd_fragment_get_BoundingRectangle(IRawElementProvid
|
|||
memset(ret_val, 0, sizeof(*ret_val));
|
||||
|
||||
/* Top level minimized window - Return empty rect. */
|
||||
if (is_top_level_hwnd(base_hwnd_prov->hwnd) && IsIconic(base_hwnd_prov->hwnd))
|
||||
if (uia_is_top_level_hwnd(base_hwnd_prov->hwnd) && IsIconic(base_hwnd_prov->hwnd))
|
||||
return S_OK;
|
||||
|
||||
if (!GetWindowRect(base_hwnd_prov->hwnd, &rect))
|
||||
|
|
|
@ -404,6 +404,11 @@ BOOL uia_hwnd_is_visible(HWND hwnd)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL uia_is_top_level_hwnd(HWND hwnd)
|
||||
{
|
||||
return GetAncestor(hwnd, GA_PARENT) == GetDesktopWindow();
|
||||
}
|
||||
|
||||
/*
|
||||
* rbtree to efficiently store a collection of HWNDs.
|
||||
*/
|
||||
|
@ -429,7 +434,7 @@ static void uia_hwnd_map_free(struct rb_entry *entry, void *context)
|
|||
free(hwnd_entry);
|
||||
}
|
||||
|
||||
static BOOL uia_hwnd_map_check_hwnd(struct rb_tree *hwnd_map, HWND hwnd)
|
||||
BOOL uia_hwnd_map_check_hwnd(struct rb_tree *hwnd_map, HWND hwnd)
|
||||
{
|
||||
return !!rb_get(hwnd_map, hwnd);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue