Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
81caccbf
Commit
81caccbf
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: Track HWNDs that need WinEvent translation.
Signed-off-by:
Connor McAdams
<
cmcadams@codeweavers.com
>
parent
2a2c4cd7
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
115 additions
and
0 deletions
+115
-0
uia_client.c
dlls/uiautomationcore/uia_client.c
+4
-0
uia_event.c
dlls/uiautomationcore/uia_event.c
+25
-0
uia_private.h
dlls/uiautomationcore/uia_private.h
+7
-0
uia_utils.c
dlls/uiautomationcore/uia_utils.c
+79
-0
No files found.
dlls/uiautomationcore/uia_client.c
View file @
81caccbf
...
...
@@ -1870,6 +1870,9 @@ static HRESULT WINAPI uia_provider_attach_event(IWineUiaProvider *iface, LONG_PT
&
IID_IProxyProviderWinEventHandler
,
(
void
**
)
&
winevent_handler
)))
{
FIXME
(
"MSAA to UIA event bridge currently unimplemented
\n
"
);
hr
=
uia_event_add_win_event_hwnd
(
event
,
prov
->
hwnd
);
if
(
FAILED
(
hr
))
WARN
(
"Failed to add hwnd for win_event, hr %#lx
\n
"
,
hr
);
IProxyProviderWinEventHandler_Release
(
winevent_handler
);
}
else
if
(
SUCCEEDED
(
IRawElementProviderFragmentRoot_QueryInterface
(
elroot
,
&
IID_IRawElementProviderAdviseEvents
,
...
...
@@ -1954,6 +1957,7 @@ static HRESULT create_wine_uia_provider(struct uia_node *node, IRawElementProvid
prov
->
IWineUiaProvider_iface
.
lpVtbl
=
&
uia_provider_vtbl
;
prov
->
elprov
=
elprov
;
prov
->
ref
=
1
;
prov
->
hwnd
=
node
->
hwnd
;
node
->
prov
[
prov_type
]
=
&
prov
->
IWineUiaProvider_iface
;
if
(
!
node
->
prov_count
)
node
->
creator_prov_type
=
prov_type
;
...
...
dlls/uiautomationcore/uia_event.c
View file @
81caccbf
...
...
@@ -64,6 +64,29 @@ static int win_event_to_uia_event_id(int win_event)
return
0
;
}
static
BOOL
CALLBACK
uia_win_event_enum_top_level_hwnds
(
HWND
hwnd
,
LPARAM
lparam
)
{
struct
rb_tree
*
hwnd_map
=
(
struct
rb_tree
*
)
lparam
;
HRESULT
hr
;
if
(
!
uia_hwnd_is_visible
(
hwnd
))
return
TRUE
;
hr
=
uia_hwnd_map_add_hwnd
(
hwnd_map
,
hwnd
);
if
(
FAILED
(
hr
))
WARN
(
"Failed to add hwnd to map, hr %#lx
\n
"
,
hr
);
return
TRUE
;
}
HRESULT
uia_event_add_win_event_hwnd
(
struct
uia_event
*
event
,
HWND
hwnd
)
{
if
(
hwnd
==
GetDesktopWindow
())
EnumWindows
(
uia_win_event_enum_top_level_hwnds
,
(
LPARAM
)
&
event
->
u
.
clientside
.
win_event_hwnd_map
);
return
uia_hwnd_map_add_hwnd
(
&
event
->
u
.
clientside
.
win_event_hwnd_map
,
hwnd
);
}
/*
* UI Automation event map.
*/
...
...
@@ -658,6 +681,7 @@ static ULONG WINAPI uia_event_Release(IWineUiaEvent *iface)
uia_cache_request_destroy
(
&
event
->
u
.
clientside
.
cache_req
);
if
(
event
->
u
.
clientside
.
git_cookie
)
uia_stop_event_thread
();
uia_hwnd_map_destroy
(
&
event
->
u
.
clientside
.
win_event_hwnd_map
);
}
else
{
...
...
@@ -834,6 +858,7 @@ static HRESULT create_clientside_uia_event(struct uia_event **out_event, int eve
event
->
scope
=
scope
;
event
->
u
.
clientside
.
event_callback
=
cback
;
event
->
u
.
clientside
.
callback_data
=
cback_data
;
uia_hwnd_map_init
(
&
event
->
u
.
clientside
.
win_event_hwnd_map
);
*
out_event
=
event
;
return
S_OK
;
...
...
dlls/uiautomationcore/uia_private.h
View file @
81caccbf
...
...
@@ -95,6 +95,7 @@ struct uia_provider {
BOOL
return_nested_node
;
BOOL
parent_check_ran
;
BOOL
has_parent
;
HWND
hwnd
;
};
static
inline
struct
uia_provider
*
impl_from_IWineUiaProvider
(
IWineUiaProvider
*
iface
)
...
...
@@ -140,6 +141,7 @@ struct uia_event
HRESULT
(
*
event_callback
)(
struct
uia_event
*
,
struct
uia_event_args
*
,
SAFEARRAY
*
,
BSTR
);
void
*
callback_data
;
struct
rb_tree
win_event_hwnd_map
;
DWORD
git_cookie
;
}
clientside
;
struct
{
...
...
@@ -218,6 +220,7 @@ BOOL uia_condition_matched(HRESULT hr) DECLSPEC_HIDDEN;
HRESULT
create_uia_iface
(
IUnknown
**
iface
,
BOOL
is_cui8
)
DECLSPEC_HIDDEN
;
/* uia_event.c */
HRESULT
uia_event_add_win_event_hwnd
(
struct
uia_event
*
event
,
HWND
hwnd
)
DECLSPEC_HIDDEN
;
HRESULT
create_serverside_uia_event
(
struct
uia_event
**
out_event
,
LONG
process_id
,
LONG
event_cookie
)
DECLSPEC_HIDDEN
;
HRESULT
uia_event_add_provider_event_adviser
(
IRawElementProviderAdviseEvents
*
advise_events
,
struct
uia_event
*
event
)
DECLSPEC_HIDDEN
;
...
...
@@ -250,3 +253,7 @@ HRESULT uia_cache_request_clone(struct UiaCacheRequest *dst, struct UiaCacheRequ
HRESULT
get_safearray_dim_bounds
(
SAFEARRAY
*
sa
,
UINT
dim
,
LONG
*
lbound
,
LONG
*
elems
)
DECLSPEC_HIDDEN
;
HRESULT
get_safearray_bounds
(
SAFEARRAY
*
sa
,
LONG
*
lbound
,
LONG
*
elems
)
DECLSPEC_HIDDEN
;
int
uia_compare_safearrays
(
SAFEARRAY
*
sa1
,
SAFEARRAY
*
sa2
,
int
prop_type
)
DECLSPEC_HIDDEN
;
BOOL
uia_hwnd_is_visible
(
HWND
hwnd
)
DECLSPEC_HIDDEN
;
HRESULT
uia_hwnd_map_add_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
;
dlls/uiautomationcore/uia_utils.c
View file @
81caccbf
...
...
@@ -384,3 +384,82 @@ int uia_compare_safearrays(SAFEARRAY *sa1, SAFEARRAY *sa2, int prop_type)
return
0
;
}
/*
* HWND related helper functions.
*/
BOOL
uia_hwnd_is_visible
(
HWND
hwnd
)
{
RECT
rect
;
if
(
!
IsWindowVisible
(
hwnd
))
return
FALSE
;
if
(
!
GetWindowRect
(
hwnd
,
&
rect
))
return
FALSE
;
if
((
rect
.
right
-
rect
.
left
)
<=
0
||
(
rect
.
bottom
-
rect
.
top
)
<=
0
)
return
FALSE
;
return
TRUE
;
}
/*
* rbtree to efficiently store a collection of HWNDs.
*/
struct
uia_hwnd_map_entry
{
struct
rb_entry
entry
;
HWND
hwnd
;
};
static
int
uia_hwnd_map_hwnd_compare
(
const
void
*
key
,
const
struct
rb_entry
*
entry
)
{
struct
uia_hwnd_map_entry
*
hwnd_entry
=
RB_ENTRY_VALUE
(
entry
,
struct
uia_hwnd_map_entry
,
entry
);
HWND
hwnd
=
(
HWND
)
key
;
return
(
hwnd_entry
->
hwnd
>
hwnd
)
-
(
hwnd_entry
->
hwnd
<
hwnd
);
}
static
void
uia_hwnd_map_free
(
struct
rb_entry
*
entry
,
void
*
context
)
{
struct
uia_hwnd_map_entry
*
hwnd_entry
=
RB_ENTRY_VALUE
(
entry
,
struct
uia_hwnd_map_entry
,
entry
);
TRACE
(
"Removing hwnd %p from map %p
\n
"
,
hwnd_entry
->
hwnd
,
context
);
free
(
hwnd_entry
);
}
static
BOOL
uia_hwnd_map_check_hwnd
(
struct
rb_tree
*
hwnd_map
,
HWND
hwnd
)
{
return
!!
rb_get
(
hwnd_map
,
hwnd
);
}
HRESULT
uia_hwnd_map_add_hwnd
(
struct
rb_tree
*
hwnd_map
,
HWND
hwnd
)
{
struct
uia_hwnd_map_entry
*
entry
;
if
(
uia_hwnd_map_check_hwnd
(
hwnd_map
,
hwnd
))
{
TRACE
(
"hwnd %p already in map %p
\n
"
,
hwnd
,
hwnd_map
);
return
S_OK
;
}
if
(
!
(
entry
=
calloc
(
1
,
sizeof
(
*
entry
))))
return
E_OUTOFMEMORY
;
TRACE
(
"Adding hwnd %p to map %p
\n
"
,
hwnd
,
hwnd_map
);
entry
->
hwnd
=
hwnd
;
rb_put
(
hwnd_map
,
hwnd
,
&
entry
->
entry
);
return
S_OK
;
}
void
uia_hwnd_map_init
(
struct
rb_tree
*
hwnd_map
)
{
rb_init
(
hwnd_map
,
uia_hwnd_map_hwnd_compare
);
}
void
uia_hwnd_map_destroy
(
struct
rb_tree
*
hwnd_map
)
{
rb_destroy
(
hwnd_map
,
uia_hwnd_map_free
,
hwnd_map
);
}
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