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);
|
set_provider_method_event_data(&Provider, NULL, -1);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
todo_wine ok(wait_res != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
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);
|
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
|
* 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. */
|
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);
|
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");
|
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);
|
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
|
* 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_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. */
|
set_uia_hwnd_expects(0, 2, 3, 5, 0); /* Only done more than one of each on Win11. */
|
||||||
ShowWindow(test_child_hwnd, SW_SHOW);
|
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");
|
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);
|
check_uia_hwnd_expects_at_least(0, FALSE, 1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE);
|
||||||
todo_wine CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||||
|
|
||||||
/* Same deal as before, it will advise multiple times. */
|
/* 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_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. */
|
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);
|
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");
|
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);
|
check_uia_hwnd_expects_at_least(0, FALSE, 1, FALSE, 1, FALSE, 1, FALSE, 0, FALSE);
|
||||||
todo_wine CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||||
|
|
||||||
/* Break navigation chain, can't reach our test element so no advisement. */
|
/* Break navigation chain, can't reach our test element so no advisement. */
|
||||||
Provider_hwnd3.parent = NULL;
|
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);
|
set_uia_hwnd_expects(0, 1, 1, 1, 0);
|
||||||
NotifyWinEvent(EVENT_OBJECT_SHOW, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
|
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");
|
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);
|
check_uia_hwnd_expects(0, FALSE, 1, FALSE, 1, FALSE, 1, TRUE, 0, FALSE);
|
||||||
todo_wine CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
CHECK_CALLED(child_winproc_GETOBJECT_UiaRoot);
|
||||||
|
|
||||||
set_provider_method_event_data(&Provider_hwnd3, NULL, -1);
|
set_provider_method_event_data(&Provider_hwnd3, NULL, -1);
|
||||||
set_provider_method_event_data(&Provider_nc3, 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_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. */
|
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);
|
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(winproc_GETOBJECT_UiaRoot, 1);
|
||||||
CHECK_CALLED_AT_MOST(child_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_hwnd, NULL, -1);
|
||||||
set_provider_method_event_data(&Provider_nc, 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_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. */
|
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);
|
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_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 1);
|
||||||
check_uia_hwnd_expects_at_most(0, 2, 2, 7, 0);
|
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)
|
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;
|
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_OBJECT_FOCUS: return UIA_AutomationFocusChangedEventId;
|
||||||
case EVENT_SYSTEM_ALERT: return UIA_SystemAlertEventId;
|
case EVENT_SYSTEM_ALERT: return UIA_SystemAlertEventId;
|
||||||
|
case EVENT_OBJECT_SHOW: return UIA_StructureChangedEventId;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
|
@ -1579,13 +1580,27 @@ static HRESULT uia_event_advise(struct uia_event *event, BOOL advise_added, LONG
|
||||||
return hr;
|
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.@)
|
* UiaEventAddWindow (uiautomationcore.@)
|
||||||
*/
|
*/
|
||||||
HRESULT WINAPI UiaEventAddWindow(HUIAEVENT huiaevent, HWND hwnd)
|
HRESULT WINAPI UiaEventAddWindow(HUIAEVENT huiaevent, HWND hwnd)
|
||||||
{
|
{
|
||||||
struct uia_event *event = unsafe_impl_from_IWineUiaEvent((IWineUiaEvent *)huiaevent);
|
struct uia_event *event = unsafe_impl_from_IWineUiaEvent((IWineUiaEvent *)huiaevent);
|
||||||
int old_event_advisers_count;
|
|
||||||
HUIANODE node;
|
HUIANODE node;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
|
||||||
|
@ -1600,15 +1615,7 @@ HRESULT WINAPI UiaEventAddWindow(HUIAEVENT huiaevent, HWND hwnd)
|
||||||
if (FAILED(hr))
|
if (FAILED(hr))
|
||||||
return hr;
|
return hr;
|
||||||
|
|
||||||
old_event_advisers_count = event->event_advisers_count;
|
hr = uia_event_advise_node(event, node);
|
||||||
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:
|
|
||||||
UiaNodeRelease(node);
|
UiaNodeRelease(node);
|
||||||
|
|
||||||
return hr;
|
return hr;
|
||||||
|
@ -1734,8 +1741,6 @@ HRESULT WINAPI UiaRemoveEvent(HUIAEVENT huiaevent)
|
||||||
return S_OK;
|
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)
|
static HRESULT uia_event_invoke(HUIANODE node, HUIANODE nav_start_node, struct uia_event_args *args, struct uia_event *event)
|
||||||
{
|
{
|
||||||
HRESULT hr = S_OK;
|
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.
|
* If it isn't, return S_FALSE.
|
||||||
* Upon failure, return a failure HR.
|
* 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)
|
HUIANODE *clientside_nav_node_out)
|
||||||
{
|
{
|
||||||
struct UiaPropertyCondition prop_cond = { ConditionType_Property, UIA_RuntimeIdPropertyId };
|
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,
|
HRESULT uia_event_add_provider_event_adviser(IRawElementProviderAdviseEvents *advise_events,
|
||||||
struct uia_event *event) DECLSPEC_HIDDEN;
|
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_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,
|
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,
|
int prop_ids_count, struct UiaCacheRequest *cache_req, SAFEARRAY *rt_id, UiaWineEventCallback *cback,
|
||||||
void *cback_data, HUIAEVENT *huiaevent) DECLSPEC_HIDDEN;
|
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 */
|
/* uia_ids.c */
|
||||||
const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN;
|
const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN;
|
||||||
|
|
Loading…
Add table
Reference in a new issue