Module: wine Branch: master Commit: 7223d1956139b7f427763c14c6b24861644497dc URL: https://gitlab.winehq.org/wine/wine/-/commit/7223d1956139b7f427763c14c6b2486...
Author: Connor McAdams cmcadams@codeweavers.com Date: Thu Jun 15 10:40:49 2023 -0400
uiautomationcore: Create a new node when raising serverside events.
Signed-off-by: Connor McAdams cmcadams@codeweavers.com
---
dlls/uiautomationcore/uia_client.c | 67 +++++++++++++++++++++++++++++++++++++ dlls/uiautomationcore/uia_event.c | 11 ++++-- dlls/uiautomationcore/uia_private.h | 1 + 3 files changed, 77 insertions(+), 2 deletions(-)
diff --git a/dlls/uiautomationcore/uia_client.c b/dlls/uiautomationcore/uia_client.c index 492ca0e52de..5fe3078bec1 100644 --- a/dlls/uiautomationcore/uia_client.c +++ b/dlls/uiautomationcore/uia_client.c @@ -673,6 +673,73 @@ static HRESULT prepare_uia_node(struct uia_node *node) return S_OK; }
+static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProviderSimple *elprov, int prov_type); +HRESULT clone_uia_node(HUIANODE in_node, HUIANODE *out_node) +{ + struct uia_node *in_node_data = impl_from_IWineUiaNode((IWineUiaNode *)in_node); + struct uia_node *node; + HRESULT hr = S_OK; + int i; + + *out_node = NULL; + if (in_node_data->nested_node) + { + FIXME("Cloning of nested nodes currently unimplemented\n"); + return E_NOTIMPL; + } + + for (i = 0; i < PROV_TYPE_COUNT; i++) + { + if (in_node_data->prov[i] && is_nested_node_provider(in_node_data->prov[i])) + { + FIXME("Cloning of nested node providers currently unimplemented\n"); + return E_NOTIMPL; + } + } + + if (!(node = heap_alloc_zero(sizeof(*node)))) + return E_OUTOFMEMORY; + + node->IWineUiaNode_iface.lpVtbl = &uia_node_vtbl; + list_init(&node->prov_thread_list_entry); + list_init(&node->node_map_list_entry); + node->ref = 1; + node->hwnd = in_node_data->hwnd; + + for (i = 0; i < PROV_TYPE_COUNT; i++) + { + struct uia_provider *in_prov_data; + + if (!in_node_data->prov[i]) + continue; + + in_prov_data = impl_from_IWineUiaProvider(in_node_data->prov[i]); + hr = create_wine_uia_provider(node, in_prov_data->elprov, i); + if (FAILED(hr)) + goto exit; + + if (in_node_data->git_cookie[i]) + { + hr = register_interface_in_git((IUnknown *)node->prov[i], &IID_IWineUiaProvider, &node->git_cookie[i]); + if (FAILED(hr)) + goto exit; + } + } + + node->parent_link_idx = in_node_data->parent_link_idx; + node->creator_prov_idx = in_node_data->creator_prov_idx; + node->creator_prov_type = in_node_data->creator_prov_type; + + *out_node = (void *)&node->IWineUiaNode_iface; + TRACE("Created clone node %p from node %p\n", *out_node, in_node); + +exit: + if (FAILED(hr)) + IWineUiaNode_Release(&node->IWineUiaNode_iface); + + return hr; +} + static BOOL node_creator_is_parent_link(struct uia_node *node) { if (node->creator_prov_idx == node->parent_link_idx) diff --git a/dlls/uiautomationcore/uia_event.c b/dlls/uiautomationcore/uia_event.c index 963701fbff0..a77fe3dd30f 100644 --- a/dlls/uiautomationcore/uia_event.c +++ b/dlls/uiautomationcore/uia_event.c @@ -1147,17 +1147,24 @@ static HRESULT uia_event_invoke(HUIANODE node, struct uia_event_args *args, stru else { struct uia_queue_event *queue_event; + HUIANODE node2;
if (!(queue_event = heap_alloc_zero(sizeof(*queue_event)))) return E_OUTOFMEMORY;
+ hr = clone_uia_node(node, &node2); + if (FAILED(hr)) + { + heap_free(queue_event); + return hr; + } + queue_event->args = args; queue_event->event = event; - queue_event->node = node; + queue_event->node = node2;
InterlockedIncrement(&args->ref); IWineUiaEvent_AddRef(&event->IWineUiaEvent_iface); - IWineUiaNode_AddRef((IWineUiaNode *)node); uia_event_queue_push(queue_event); }
diff --git a/dlls/uiautomationcore/uia_private.h b/dlls/uiautomationcore/uia_private.h index 325206c6d90..727c0be6894 100644 --- a/dlls/uiautomationcore/uia_private.h +++ b/dlls/uiautomationcore/uia_private.h @@ -192,6 +192,7 @@ static inline BOOL uia_array_reserve(void **elements, SIZE_T *capacity, SIZE_T c /* uia_client.c */ int get_node_provider_type_at_idx(struct uia_node *node, int idx) DECLSPEC_HIDDEN; HRESULT attach_event_to_uia_node(HUIANODE node, struct uia_event *event) DECLSPEC_HIDDEN; +HRESULT clone_uia_node(HUIANODE in_node, HUIANODE *out_node) DECLSPEC_HIDDEN; HRESULT navigate_uia_node(struct uia_node *node, int nav_dir, HUIANODE *out_node) DECLSPEC_HIDDEN; HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE *out_node, BOOL get_hwnd_providers) DECLSPEC_HIDDEN;