mirror of
git://source.winehq.org/git/wine.git
synced 2024-10-31 12:54:13 +00:00
uiautomationcore: Shutdown provider thread when all returned nodes are released.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
d7c95765d0
commit
858596bbd5
3 changed files with 44 additions and 16 deletions
|
@ -269,21 +269,6 @@ static IRawElementProviderSimple *get_provider_hwnd_fragment_root(IRawElementPro
|
|||
/*
|
||||
* IWineUiaNode interface.
|
||||
*/
|
||||
struct uia_node {
|
||||
IWineUiaNode IWineUiaNode_iface;
|
||||
LONG ref;
|
||||
|
||||
IWineUiaProvider *prov;
|
||||
DWORD git_cookie;
|
||||
|
||||
HWND hwnd;
|
||||
};
|
||||
|
||||
static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct uia_node, IWineUiaNode_iface);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI uia_node_QueryInterface(IWineUiaNode *iface, REFIID riid, void **ppv)
|
||||
{
|
||||
*ppv = NULL;
|
||||
|
@ -328,6 +313,9 @@ static ULONG WINAPI uia_node_Release(IWineUiaNode *iface)
|
|||
}
|
||||
|
||||
IWineUiaProvider_Release(node->prov);
|
||||
if (node->nested_node)
|
||||
uia_stop_provider_thread();
|
||||
|
||||
heap_free(node);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,4 +29,24 @@ enum uia_prop_type {
|
|||
PROP_TYPE_SPECIAL,
|
||||
};
|
||||
|
||||
struct uia_node {
|
||||
IWineUiaNode IWineUiaNode_iface;
|
||||
LONG ref;
|
||||
|
||||
IWineUiaProvider *prov;
|
||||
DWORD git_cookie;
|
||||
|
||||
HWND hwnd;
|
||||
BOOL nested_node;
|
||||
};
|
||||
|
||||
static inline struct uia_node *impl_from_IWineUiaNode(IWineUiaNode *iface)
|
||||
{
|
||||
return CONTAINING_RECORD(iface, struct uia_node, IWineUiaNode_iface);
|
||||
}
|
||||
|
||||
/* uia_ids.c */
|
||||
const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN;
|
||||
|
||||
/* uia_provider.c */
|
||||
void uia_stop_provider_thread(void) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -1132,6 +1132,7 @@ struct uia_provider_thread
|
|||
{
|
||||
HANDLE hthread;
|
||||
HWND hwnd;
|
||||
LONG ref;
|
||||
};
|
||||
|
||||
static struct uia_provider_thread provider_thread;
|
||||
|
@ -1145,6 +1146,7 @@ static CRITICAL_SECTION_DEBUG provider_thread_cs_debug =
|
|||
static CRITICAL_SECTION provider_thread_cs = { &provider_thread_cs_debug, -1, 0, 0, 0, 0 };
|
||||
|
||||
#define WM_GET_OBJECT_UIA_NODE (WM_USER + 1)
|
||||
#define WM_UIA_PROVIDER_THREAD_STOP (WM_USER + 2)
|
||||
static LRESULT CALLBACK uia_provider_thread_msg_proc(HWND hwnd, UINT msg, WPARAM wparam,
|
||||
LPARAM lparam)
|
||||
{
|
||||
|
@ -1153,8 +1155,12 @@ static LRESULT CALLBACK uia_provider_thread_msg_proc(HWND hwnd, UINT msg, WPARAM
|
|||
case WM_GET_OBJECT_UIA_NODE:
|
||||
{
|
||||
HUIANODE node = (HUIANODE)lparam;
|
||||
struct uia_node *node_data;
|
||||
LRESULT lr;
|
||||
|
||||
node_data = impl_from_IWineUiaNode((IWineUiaNode *)node);
|
||||
node_data->nested_node = TRUE;
|
||||
|
||||
/*
|
||||
* LresultFromObject returns an index into the global atom string table,
|
||||
* which has a valid range of 0xc000-0xffff.
|
||||
|
@ -1204,6 +1210,8 @@ static DWORD WINAPI uia_provider_thread_proc(void *arg)
|
|||
TRACE("Provider thread started.\n");
|
||||
while (GetMessageW(&msg, NULL, 0, 0))
|
||||
{
|
||||
if (msg.message == WM_UIA_PROVIDER_THREAD_STOP)
|
||||
break;
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessageW(&msg);
|
||||
}
|
||||
|
@ -1220,7 +1228,7 @@ static BOOL uia_start_provider_thread(void)
|
|||
BOOL started = TRUE;
|
||||
|
||||
EnterCriticalSection(&provider_thread_cs);
|
||||
if (!provider_thread.hwnd)
|
||||
if (++provider_thread.ref == 1)
|
||||
{
|
||||
HANDLE ready_event;
|
||||
HANDLE events[2];
|
||||
|
@ -1261,6 +1269,18 @@ exit:
|
|||
return started;
|
||||
}
|
||||
|
||||
void uia_stop_provider_thread(void)
|
||||
{
|
||||
EnterCriticalSection(&provider_thread_cs);
|
||||
if (!--provider_thread.ref)
|
||||
{
|
||||
PostMessageW(provider_thread.hwnd, WM_UIA_PROVIDER_THREAD_STOP, 0, 0);
|
||||
CloseHandle(provider_thread.hthread);
|
||||
memset(&provider_thread, 0, sizeof(provider_thread));
|
||||
}
|
||||
LeaveCriticalSection(&provider_thread_cs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Pass our IWineUiaNode interface to the provider thread for marshaling. UI
|
||||
* Automation has to work regardless of whether or not COM is initialized on
|
||||
|
|
Loading…
Reference in a new issue