uiautomationcore: Use EVENT_OBJECT_DESTROY to remove HWNDs from the COM API focus change HWND map.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
a275834bdd
commit
4569157b28
5 changed files with 75 additions and 0 deletions
|
@ -15475,6 +15475,30 @@ static void test_uia_com_event_handler_event_advisement(IUIAutomation *uia_iface
|
|||
check_uia_hwnd_expects_at_most(0, 1, 1, 3, 0);
|
||||
test_hwnd_providers_event_advise_added(&Provider, &Provider_hwnd2, &Provider_nc2, 0, FALSE);
|
||||
|
||||
/* HWND destruction is tracked with EVENT_OBJECT_DESTROY/OBJID_WINDOW. */
|
||||
NotifyWinEvent(EVENT_OBJECT_DESTROY, test_child_hwnd, OBJID_WINDOW, CHILDID_SELF);
|
||||
if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
|
||||
|
||||
/*
|
||||
* EVENT_OBJECT_DESTROY removed this HWND, EVENT_OBJECT_FOCUS will now
|
||||
* advise it again.
|
||||
*/
|
||||
reset_event_advise_values_for_hwnd_providers(&Provider2, &Provider_hwnd3, &Provider_nc3);
|
||||
set_provider_method_event_data(&Provider2, method_event[0], ADVISE_EVENTS_EVENT_ADDED);
|
||||
SET_EXPECT_MULTI(child_winproc_GETOBJECT_UiaRoot, 3); /* Only sent 3 times on Win11. */
|
||||
set_uia_hwnd_expects(0, 1, 1, 2, 0); /* Only Win11 sends WM_GETOBJECT 2 times. */
|
||||
|
||||
NotifyWinEvent(EVENT_OBJECT_FOCUS, test_child_hwnd, OBJID_CLIENT, CHILDID_SELF);
|
||||
ok(msg_wait_for_all_events(method_event, 1, 2000) != WAIT_TIMEOUT, "Wait for method_event(s) timed out.\n");
|
||||
if (wait_for_clientside_callbacks(2000)) trace("Kept getting callbacks up until timeout\n");
|
||||
|
||||
set_provider_method_event_data(&Provider2, NULL, -1);
|
||||
check_uia_hwnd_expects_at_most(0, 1, 1, 2, 0);
|
||||
CHECK_CALLED_AT_MOST(child_winproc_GETOBJECT_UiaRoot, 3);
|
||||
test_provider_event_advise_added(&Provider2, UIA_AutomationFocusChangedEventId, FALSE);
|
||||
test_provider_event_advise_added(&Provider_hwnd3, 0, FALSE);
|
||||
test_provider_event_advise_added(&Provider_nc3, 0, FALSE);
|
||||
|
||||
set_uia_hwnd_expects(0, 1, 1, 0, 0);
|
||||
hr = IUIAutomation_RemoveFocusChangedEventHandler(uia_iface,
|
||||
&FocusChangedHandler.IUIAutomationFocusChangedEventHandler_iface);
|
||||
|
|
|
@ -1108,6 +1108,38 @@ HRESULT uia_com_win_event_callback(DWORD event_id, HWND hwnd, LONG obj_id, LONG
|
|||
break;
|
||||
}
|
||||
|
||||
case EVENT_OBJECT_DESTROY:
|
||||
{
|
||||
static const int uia_event_id = UIA_AutomationFocusChangedEventId;
|
||||
struct rb_entry *rb_entry;
|
||||
|
||||
if (obj_id != OBJID_WINDOW)
|
||||
break;
|
||||
|
||||
EnterCriticalSection(&com_event_handlers_cs);
|
||||
|
||||
if ((rb_entry = rb_get(&com_event_handlers.handler_event_id_map, &uia_event_id)))
|
||||
{
|
||||
struct uia_event_handler_event_id_map_entry *event_id_map;
|
||||
struct uia_event_handler_map_entry *entry;
|
||||
|
||||
event_id_map = RB_ENTRY_VALUE(rb_entry, struct uia_event_handler_event_id_map_entry, entry);
|
||||
LIST_FOR_EACH_ENTRY(entry, &event_id_map->handlers_list, struct uia_event_handler_map_entry,
|
||||
handler_event_id_map_list_entry)
|
||||
{
|
||||
struct uia_com_event *event;
|
||||
|
||||
LIST_FOR_EACH_ENTRY(event, &entry->handlers_list, struct uia_com_event, event_handler_map_list_entry)
|
||||
{
|
||||
uia_hwnd_map_remove_hwnd(&event->focus_hwnd_map, hwnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&com_event_handlers_cs);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -56,6 +56,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;
|
||||
case EVENT_OBJECT_DESTROY: return UIA_StructureChangedEventId;
|
||||
|
||||
default:
|
||||
break;
|
||||
|
|
|
@ -270,5 +270,6 @@ 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_remove_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;
|
||||
|
|
|
@ -459,6 +459,23 @@ HRESULT uia_hwnd_map_add_hwnd(struct rb_tree *hwnd_map, HWND hwnd)
|
|||
return S_OK;
|
||||
}
|
||||
|
||||
void uia_hwnd_map_remove_hwnd(struct rb_tree *hwnd_map, HWND hwnd)
|
||||
{
|
||||
struct rb_entry *rb_entry = rb_get(hwnd_map, hwnd);
|
||||
struct uia_hwnd_map_entry *entry;
|
||||
|
||||
if (!rb_entry)
|
||||
{
|
||||
TRACE("hwnd %p not in map %p, nothing to remove.\n", hwnd, hwnd_map);
|
||||
return;
|
||||
}
|
||||
|
||||
TRACE("Removing hwnd %p from map %p\n", hwnd, hwnd_map);
|
||||
entry = RB_ENTRY_VALUE(rb_entry, struct uia_hwnd_map_entry, entry);
|
||||
rb_remove(hwnd_map, &entry->entry);
|
||||
free(entry);
|
||||
}
|
||||
|
||||
void uia_hwnd_map_init(struct rb_tree *hwnd_map)
|
||||
{
|
||||
rb_init(hwnd_map, uia_hwnd_map_hwnd_compare);
|
||||
|
|
Loading…
Add table
Reference in a new issue