uiautomationcore: Use EVENT_OBJECT_SHOW to advise providers of events being listened for in the COM API.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
c21bc70af8
commit
3f4f116dc5
4 changed files with 107 additions and 29 deletions
|
@ -14943,8 +14943,8 @@ static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface
|
|||
set_provider_method_event_data(&Provider, NULL, -1);
|
||||
goto exit;
|
||||
}
|
||||
todo_wine ok(wait_res != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, TRUE, 1, TRUE, 1, TRUE, 0, FALSE);
|
||||
ok(wait_res != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE);
|
||||
|
||||
/*
|
||||
* Manually fire off EVENT_OBJECT_SHOW, providers will be advised of
|
||||
|
@ -14952,8 +14952,8 @@ static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface
|
|||
*/
|
||||
set_uia_hwnd_expects(0, 2, 2, 6, 0); /* Only done more than one of each on Win11. */
|
||||
NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
|
||||
todo_wine ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, TRUE, 1, TRUE, 1, TRUE, 0, FALSE);
|
||||
ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE);
|
||||
|
||||
/*
|
||||
* Providers are only advised of events being listened for if an event is
|
||||
|
@ -14977,17 +14977,17 @@ static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface
|
|||
SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 6); /* Only done more than once on Win11. */
|
||||
set_uia_hwnd_expects(0, 2, 3, 5, 0); /* Only done more than one of each on Win11. */
|
||||
ShowWindow(test_child_hwnd, SW_SHOW);
|
||||
todo_wine ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, TRUE, 1, TRUE, 1, TRUE, 0, FALSE);
|
||||
todo_wine CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE);
|
||||
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
|
||||
/* Same deal as before, it will advise multiple times. */
|
||||
SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 6); /* Only done more than once on Win11. */
|
||||
set_uia_hwnd_expects(0, 2, 3, 5, 0); /* Only done more than one of each on Win11. */
|
||||
NotifyWinEvent(EVENT_OBJECT_SHOW, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
|
||||
todo_wine ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, TRUE, 1, TRUE, 1, TRUE, 0, FALSE);
|
||||
todo_wine CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
ok(msg_wait_for_all_events(method_event, event_handle_count, 3000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE);
|
||||
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
|
||||
/* Break navigation chain, can't reach our test element so no advisement. */
|
||||
Provider_hwnd3.parent = NULL;
|
||||
|
@ -14995,8 +14995,8 @@ static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface
|
|||
set_uia_hwnd_expects(0, 1, 1, 1, 0);
|
||||
NotifyWinEvent(EVENT_OBJECT_SHOW, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
|
||||
ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) == WAIT_TIMEOUT, "Wait for method_event(s) didn't timeout.\n");
|
||||
check_uia_hwnd_expects(0, FALSE, 1, TRUE, 1, TRUE, 1, TRUE, 0, FALSE);
|
||||
todo_wine CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
|
||||
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||
|
||||
set_provider_method_event_data(&Provider_hwnd3, NULL, -1);
|
||||
set_provider_method_event_data(&Provider_nc3, NULL, -1);
|
||||
|
@ -15044,10 +15044,10 @@ static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface
|
|||
SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only done on Win11. */
|
||||
set_uia_hwnd_expects(0, 3, 3, 1, 0); /* Only done more than once on Win11. */
|
||||
NotifyWinEvent(EVENT_OBJECT_SHOW, GetDesktopWindow(), OBJID_WINDOW, CHILDID_SELF);
|
||||
todo_wine ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
CHECK_CALLED_AT_MOST(winproc_GETOBJECT_UiaRoot, 1);
|
||||
CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, TRUE, 1, TRUE, 0, FALSE, 0, FALSE);
|
||||
check_uia_hwnd_expects_at_least(0, FALSE, 1, FALSE, 1, FALSE, 0, FALSE, 0, FALSE);
|
||||
|
||||
set_provider_method_event_data(&Provider_hwnd, NULL, -1);
|
||||
set_provider_method_event_data(&Provider_nc, NULL, -1);
|
||||
|
@ -15063,7 +15063,7 @@ static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface
|
|||
SET_EXPECT(child_winproc_GETOBJECT_UiaRoot); /* Only done on Win11. */
|
||||
set_uia_hwnd_expects(0, 2, 2, 7, 0); /* Only done more than once on Win11. */
|
||||
NotifyWinEvent(EVENT_OBJECT_SHOW, test_hwnd, OBJID_WINDOW, CHILDID_SELF);
|
||||
todo_wine ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
ok(msg_wait_for_all_events(method_event, event_handle_count, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
|
||||
check_uia_hwnd_expects_at_most(0, 2, 2, 7, 0);
|
||||
|
||||
|
|
|
@ -960,7 +960,77 @@ struct uia_com_event {
|
|||
|
||||
HRESULT uia_com_win_event_callback(DWORD event_id, HWND hwnd, LONG obj_id, LONG child_id, DWORD thread_id, DWORD event_time)
|
||||
{
|
||||
FIXME("%ld, %p, %ld, %ld, %ld, %ld: stub\n", event_id, hwnd, obj_id, child_id, thread_id, event_time);
|
||||
LONG handler_count;
|
||||
|
||||
TRACE("%ld, %p, %ld, %ld, %ld, %ld\n", event_id, hwnd, obj_id, child_id, thread_id, event_time);
|
||||
|
||||
EnterCriticalSection(&com_event_handlers_cs);
|
||||
handler_count = com_event_handlers.handler_count;
|
||||
LeaveCriticalSection(&com_event_handlers_cs);
|
||||
|
||||
if (!handler_count)
|
||||
return S_OK;
|
||||
|
||||
switch (event_id)
|
||||
{
|
||||
case EVENT_OBJECT_SHOW:
|
||||
{
|
||||
struct uia_event_handler_map_entry *entry;
|
||||
SAFEARRAY *rt_id = NULL;
|
||||
HUIANODE node;
|
||||
HRESULT hr;
|
||||
|
||||
if (obj_id != OBJID_WINDOW || !uia_hwnd_is_visible(hwnd))
|
||||
break;
|
||||
|
||||
hr = UiaNodeFromHandle(hwnd, &node);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
hr = UiaGetRuntimeId(node, &rt_id);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
UiaNodeRelease(node);
|
||||
return hr;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&com_event_handlers_cs);
|
||||
|
||||
RB_FOR_EACH_ENTRY(entry, &com_event_handlers.handler_map, struct uia_event_handler_map_entry, entry)
|
||||
{
|
||||
struct uia_com_event *event;
|
||||
|
||||
/*
|
||||
* Focus change event handlers only listen for EVENT_OBJECT_SHOW
|
||||
* on the desktop HWND.
|
||||
*/
|
||||
if ((entry->event_id == UIA_AutomationFocusChangedEventId) && (hwnd != GetDesktopWindow()))
|
||||
continue;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(event, &entry->handlers_list, struct uia_com_event, event_handler_map_list_entry)
|
||||
{
|
||||
hr = uia_event_check_node_within_event_scope((struct uia_event *)event->event, node, rt_id, NULL);
|
||||
if (FAILED(hr))
|
||||
WARN("uia_event_check_node_within_scope failed with hr %#lx\n", hr);
|
||||
else if (hr == S_OK)
|
||||
{
|
||||
hr = uia_event_advise_node((struct uia_event *)event->event, node);
|
||||
if (FAILED(hr))
|
||||
WARN("uia_event_advise_node failed with hr %#lx\n", hr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&com_event_handlers_cs);
|
||||
|
||||
UiaNodeRelease(node);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ static int win_event_to_uia_event_id(int win_event)
|
|||
{
|
||||
case EVENT_OBJECT_FOCUS: return UIA_AutomationFocusChangedEventId;
|
||||
case EVENT_SYSTEM_ALERT: return UIA_SystemAlertEventId;
|
||||
case EVENT_OBJECT_SHOW: return UIA_StructureChangedEventId;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
@ -1579,13 +1580,27 @@ static HRESULT uia_event_advise(struct uia_event *event, BOOL advise_added, LONG
|
|||
return hr;
|
||||
}
|
||||
|
||||
HRESULT uia_event_advise_node(struct uia_event *event, HUIANODE node)
|
||||
{
|
||||
int old_event_advisers_count = event->event_advisers_count;
|
||||
HRESULT hr;
|
||||
|
||||
hr = attach_event_to_uia_node(node, event);
|
||||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
if (event->event_advisers_count != old_event_advisers_count)
|
||||
hr = uia_event_advise(event, TRUE, old_event_advisers_count);
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* UiaEventAddWindow (uiautomationcore.@)
|
||||
*/
|
||||
HRESULT WINAPI UiaEventAddWindow(HUIAEVENT huiaevent, HWND hwnd)
|
||||
{
|
||||
struct uia_event *event = unsafe_impl_from_IWineUiaEvent((IWineUiaEvent *)huiaevent);
|
||||
int old_event_advisers_count;
|
||||
HUIANODE node;
|
||||
HRESULT hr;
|
||||
|
||||
|
@ -1600,15 +1615,7 @@ HRESULT WINAPI UiaEventAddWindow(HUIAEVENT huiaevent, HWND hwnd)
|
|||
if (FAILED(hr))
|
||||
return hr;
|
||||
|
||||
old_event_advisers_count = event->event_advisers_count;
|
||||
hr = attach_event_to_uia_node(node, event);
|
||||
if (FAILED(hr))
|
||||
goto exit;
|
||||
|
||||
if (event->event_advisers_count != old_event_advisers_count)
|
||||
hr = uia_event_advise(event, TRUE, old_event_advisers_count);
|
||||
|
||||
exit:
|
||||
hr = uia_event_advise_node(event, node);
|
||||
UiaNodeRelease(node);
|
||||
|
||||
return hr;
|
||||
|
@ -1734,8 +1741,6 @@ HRESULT WINAPI UiaRemoveEvent(HUIAEVENT huiaevent)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT uia_event_check_node_within_event_scope(struct uia_event *event, HUIANODE node, SAFEARRAY *rt_id,
|
||||
HUIANODE *clientside_nav_node_out);
|
||||
static HRESULT uia_event_invoke(HUIANODE node, HUIANODE nav_start_node, struct uia_event_args *args, struct uia_event *event)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
|
@ -1812,7 +1817,7 @@ static void set_refuse_hwnd_providers(struct uia_node *node, BOOL refuse_hwnd_pr
|
|||
* If it isn't, return S_FALSE.
|
||||
* Upon failure, return a failure HR.
|
||||
*/
|
||||
static HRESULT uia_event_check_node_within_event_scope(struct uia_event *event, HUIANODE node, SAFEARRAY *rt_id,
|
||||
HRESULT uia_event_check_node_within_event_scope(struct uia_event *event, HUIANODE node, SAFEARRAY *rt_id,
|
||||
HUIANODE *clientside_nav_node_out)
|
||||
{
|
||||
struct UiaPropertyCondition prop_cond = { ConditionType_Property, UIA_RuntimeIdPropertyId };
|
||||
|
|
|
@ -234,9 +234,12 @@ HRESULT create_serverside_uia_event(struct uia_event **out_event, LONG process_i
|
|||
HRESULT uia_event_add_provider_event_adviser(IRawElementProviderAdviseEvents *advise_events,
|
||||
struct uia_event *event) DECLSPEC_HIDDEN;
|
||||
HRESULT uia_event_add_serverside_event_adviser(IWineUiaEvent *serverside_event, struct uia_event *event) DECLSPEC_HIDDEN;
|
||||
HRESULT uia_event_advise_node(struct uia_event *event, HUIANODE node) DECLSPEC_HIDDEN;
|
||||
HRESULT uia_add_clientside_event(HUIANODE huianode, EVENTID event_id, enum TreeScope scope, PROPERTYID *prop_ids,
|
||||
int prop_ids_count, struct UiaCacheRequest *cache_req, SAFEARRAY *rt_id, UiaWineEventCallback *cback,
|
||||
void *cback_data, HUIAEVENT *huiaevent) DECLSPEC_HIDDEN;
|
||||
HRESULT uia_event_check_node_within_event_scope(struct uia_event *event, HUIANODE node, SAFEARRAY *rt_id,
|
||||
HUIANODE *clientside_nav_node_out) DECLSPEC_HIDDEN;
|
||||
|
||||
/* uia_ids.c */
|
||||
const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN;
|
||||
|
|
Loading…
Add table
Reference in a new issue