Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
2a2c4cd7
Commit
2a2c4cd7
authored
Sep 13, 2023
by
Connor McAdams
Committed by
Alexandre Julliard
Sep 25, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
uiautomationcore: Add WinEvent hook on the UIA event thread.
Signed-off-by:
Connor McAdams
<
cmcadams@codeweavers.com
>
parent
336503f3
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
105 additions
and
16 deletions
+105
-16
uia_event.c
dlls/uiautomationcore/uia_event.c
+105
-16
No files found.
dlls/uiautomationcore/uia_event.c
View file @
2a2c4cd7
...
...
@@ -50,6 +50,20 @@ static SAFEARRAY *uia_get_desktop_rt_id(void)
return
uia_desktop_node_rt_id
;
}
static
int
win_event_to_uia_event_id
(
int
win_event
)
{
switch
(
win_event
)
{
case
EVENT_OBJECT_FOCUS
:
return
UIA_AutomationFocusChangedEventId
;
case
EVENT_SYSTEM_ALERT
:
return
UIA_SystemAlertEventId
;
default:
break
;
}
return
0
;
}
/*
* UI Automation event map.
*/
...
...
@@ -247,6 +261,7 @@ struct uia_event_thread
LONG
ref
;
struct
list
*
event_queue
;
HWINEVENTHOOK
hook
;
};
#define WM_UIA_EVENT_THREAD_STOP (WM_USER + 1)
...
...
@@ -264,12 +279,18 @@ static CRITICAL_SECTION event_thread_cs = { &event_thread_cs_debug, -1, 0, 0, 0,
enum
uia_queue_event_type
{
QUEUE_EVENT_TYPE_SERVERSIDE
,
QUEUE_EVENT_TYPE_CLIENTSIDE
,
QUEUE_EVENT_TYPE_WIN_EVENT
,
};
struct
uia_queue_event
{
struct
list
event_queue_entry
;
int
queue_event_type
;
};
struct
uia_queue_uia_event
{
struct
uia_queue_event
queue_entry
;
struct
uia_event_args
*
args
;
struct
uia_event
*
event
;
...
...
@@ -285,14 +306,40 @@ struct uia_queue_event
}
u
;
};
static
void
uia_event_queue_push
(
struct
uia_queue_event
*
event
)
struct
uia_queue_win_event
{
struct
uia_queue_event
queue_entry
;
HWINEVENTHOOK
hook
;
DWORD
event_id
;
HWND
hwnd
;
LONG
obj_id
;
LONG
child_id
;
DWORD
thread_id
;
DWORD
event_time
;
};
static
void
uia_event_queue_push
(
struct
uia_queue_event
*
event
,
int
queue_event_type
)
{
event
->
queue_event_type
=
queue_event_type
;
EnterCriticalSection
(
&
event_thread_cs
);
if
(
queue_event_type
==
QUEUE_EVENT_TYPE_WIN_EVENT
)
{
struct
uia_queue_win_event
*
win_event
=
(
struct
uia_queue_win_event
*
)
event
;
if
(
win_event
->
hook
!=
event_thread
.
hook
)
{
free
(
event
);
goto
exit
;
}
}
assert
(
event_thread
.
event_queue
);
list_add_tail
(
event_thread
.
event_queue
,
&
event
->
event_queue_entry
);
PostMessageW
(
event_thread
.
hwnd
,
WM_UIA_EVENT_THREAD_PROCESS_QUEUE
,
0
,
0
);
exit:
LeaveCriticalSection
(
&
event_thread_cs
);
}
...
...
@@ -322,7 +369,7 @@ static void uia_node_lresult_release(LRESULT lr)
static
HRESULT
uia_event_invoke
(
HUIANODE
node
,
HUIANODE
nav_start_node
,
struct
uia_event_args
*
args
,
struct
uia_event
*
event
);
static
HRESULT
uia_raise_clientside_event
(
struct
uia_queue_event
*
event
)
static
HRESULT
uia_raise_clientside_event
(
struct
uia_queue_
uia_
event
*
event
)
{
HUIANODE
node
,
nav_start_node
;
HRESULT
hr
;
...
...
@@ -354,7 +401,7 @@ static HRESULT uia_raise_clientside_event(struct uia_queue_event *event)
return
hr
;
}
static
HRESULT
uia_raise_serverside_event
(
struct
uia_queue_event
*
event
)
static
HRESULT
uia_raise_serverside_event
(
struct
uia_queue_
uia_
event
*
event
)
{
HRESULT
hr
=
S_OK
;
LRESULT
lr
,
lr2
;
...
...
@@ -397,29 +444,70 @@ static void uia_event_thread_process_queue(struct list *event_queue)
while
(
1
)
{
struct
uia_queue_event
*
event
;
HRESULT
hr
;
HRESULT
hr
=
S_OK
;
if
(
!
(
event
=
uia_event_queue_pop
(
event_queue
)))
break
;
if
(
event
->
queue_event_type
==
QUEUE_EVENT_TYPE_SERVERSIDE
)
hr
=
uia_raise_serverside_event
(
event
);
else
hr
=
uia_raise_clientside_event
(
event
);
switch
(
event
->
queue_event_type
)
{
case
QUEUE_EVENT_TYPE_SERVERSIDE
:
case
QUEUE_EVENT_TYPE_CLIENTSIDE
:
{
struct
uia_queue_uia_event
*
uia_event
=
(
struct
uia_queue_uia_event
*
)
event
;
if
(
event
->
queue_event_type
==
QUEUE_EVENT_TYPE_SERVERSIDE
)
hr
=
uia_raise_serverside_event
(
uia_event
);
else
hr
=
uia_raise_clientside_event
(
uia_event
);
uia_event_args_release
(
uia_event
->
args
);
IWineUiaEvent_Release
(
&
uia_event
->
event
->
IWineUiaEvent_iface
);
break
;
}
default:
break
;
}
if
(
FAILED
(
hr
))
WARN
(
"Failed to raise event type %d with hr %#lx
\n
"
,
event
->
queue_event_type
,
hr
);
uia_event_args_release
(
event
->
args
);
IWineUiaEvent_Release
(
&
event
->
event
->
IWineUiaEvent_iface
);
free
(
event
);
}
}
static
void
CALLBACK
uia_event_thread_win_event_proc
(
HWINEVENTHOOK
hook
,
DWORD
event_id
,
HWND
hwnd
,
LONG
obj_id
,
LONG
child_id
,
DWORD
thread_id
,
DWORD
event_time
)
{
struct
uia_queue_win_event
*
win_event
;
TRACE
(
"%p, %ld, %p, %ld, %ld, %ld, %ld
\n
"
,
hook
,
event_id
,
hwnd
,
obj_id
,
child_id
,
thread_id
,
event_time
);
if
(
!
win_event_to_uia_event_id
(
event_id
))
return
;
if
(
!
(
win_event
=
calloc
(
1
,
sizeof
(
*
win_event
))))
{
ERR
(
"Failed to allocate uia_queue_win_event structure
\n
"
);
return
;
}
win_event
->
hook
=
hook
;
win_event
->
event_id
=
event_id
;
win_event
->
hwnd
=
hwnd
;
win_event
->
obj_id
=
obj_id
;
win_event
->
child_id
=
child_id
;
win_event
->
thread_id
=
thread_id
;
win_event
->
event_time
=
event_time
;
uia_event_queue_push
(
&
win_event
->
queue_entry
,
QUEUE_EVENT_TYPE_WIN_EVENT
);
}
static
DWORD
WINAPI
uia_event_thread_proc
(
void
*
arg
)
{
HANDLE
initialized_event
=
arg
;
struct
list
event_queue
;
HWINEVENTHOOK
hook
;
HWND
hwnd
;
MSG
msg
;
...
...
@@ -435,6 +523,8 @@ static DWORD WINAPI uia_event_thread_proc(void *arg)
event_thread
.
hwnd
=
hwnd
;
event_thread
.
event_queue
=
&
event_queue
;
event_thread
.
hook
=
hook
=
SetWinEventHook
(
EVENT_MIN
,
EVENT_MAX
,
0
,
uia_event_thread_win_event_proc
,
0
,
0
,
WINEVENT_OUTOFCONTEXT
);
/* Initialization complete, thread can now process window messages. */
SetEvent
(
initialized_event
);
...
...
@@ -455,6 +545,7 @@ static DWORD WINAPI uia_event_thread_proc(void *arg)
TRACE
(
"Shutting down UI Automation event thread.
\n
"
);
UnhookWinEvent
(
hook
);
DestroyWindow
(
hwnd
);
CoUninitialize
();
FreeLibraryAndExitThread
(
huia_module
,
0
);
...
...
@@ -664,7 +755,7 @@ static HRESULT WINAPI uia_event_set_event_data(IWineUiaEvent *iface, const GUID
static
HRESULT
WINAPI
uia_event_raise_event
(
IWineUiaEvent
*
iface
,
VARIANT
in_node
,
VARIANT
in_nav_start_node
)
{
struct
uia_event
*
event
=
impl_from_IWineUiaEvent
(
iface
);
struct
uia_queue_event
*
queue_event
;
struct
uia_queue_
uia_
event
*
queue_event
;
struct
uia_event_args
*
args
;
TRACE
(
"%p, %s, %s
\n
"
,
iface
,
debugstr_variant
(
&
in_node
),
debugstr_variant
(
&
in_nav_start_node
));
...
...
@@ -680,7 +771,6 @@ static HRESULT WINAPI uia_event_raise_event(IWineUiaEvent *iface, VARIANT in_nod
return
E_OUTOFMEMORY
;
}
queue_event
->
queue_event_type
=
QUEUE_EVENT_TYPE_CLIENTSIDE
;
queue_event
->
args
=
args
;
queue_event
->
event
=
event
;
queue_event
->
u
.
clientside
.
node
=
V_I4
(
&
in_node
);
...
...
@@ -688,7 +778,7 @@ static HRESULT WINAPI uia_event_raise_event(IWineUiaEvent *iface, VARIANT in_nod
queue_event
->
u
.
clientside
.
nav_start_node
=
V_I4
(
&
in_nav_start_node
);
IWineUiaEvent_AddRef
(
&
event
->
IWineUiaEvent_iface
);
uia_event_queue_push
(
queue_event
);
uia_event_queue_push
(
&
queue_event
->
queue_entry
,
QUEUE_EVENT_TYPE_CLIENTSIDE
);
return
S_OK
;
}
...
...
@@ -1277,7 +1367,7 @@ static HRESULT uia_event_invoke(HUIANODE node, HUIANODE nav_start_node, struct u
}
else
{
struct
uia_queue_event
*
queue_event
;
struct
uia_queue_
uia_
event
*
queue_event
;
HUIANODE
node2
,
nav_start_node2
;
if
(
!
(
queue_event
=
calloc
(
1
,
sizeof
(
*
queue_event
))))
...
...
@@ -1302,7 +1392,6 @@ static HRESULT uia_event_invoke(HUIANODE node, HUIANODE nav_start_node, struct u
}
}
queue_event
->
queue_event_type
=
QUEUE_EVENT_TYPE_SERVERSIDE
;
queue_event
->
args
=
args
;
queue_event
->
event
=
event
;
queue_event
->
u
.
serverside
.
node
=
node2
;
...
...
@@ -1310,7 +1399,7 @@ static HRESULT uia_event_invoke(HUIANODE node, HUIANODE nav_start_node, struct u
InterlockedIncrement
(
&
args
->
ref
);
IWineUiaEvent_AddRef
(
&
event
->
IWineUiaEvent_iface
);
uia_event_queue_push
(
queue_event
);
uia_event_queue_push
(
&
queue_event
->
queue_entry
,
QUEUE_EVENT_TYPE_SERVERSIDE
);
}
return
hr
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment