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
4cc7525a
Commit
4cc7525a
authored
Jun 26, 2023
by
Connor McAdams
Committed by
Alexandre Julliard
Jul 19, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
uiautomationcore: Partially implement IUIAutomation::AddAutomationEventHandler.
Signed-off-by:
Connor McAdams
<
cmcadams@codeweavers.com
>
parent
79313d01
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
159 additions
and
15 deletions
+159
-15
uiautomation.c
dlls/uiautomationcore/tests/uiautomation.c
+13
-13
uia_com_client.c
dlls/uiautomationcore/uia_com_client.c
+146
-2
No files found.
dlls/uiautomationcore/tests/uiautomation.c
View file @
4cc7525a
...
...
@@ -13089,11 +13089,11 @@ static void test_IUIAutomationEventHandler(IUIAutomation *uia_iface, IUIAutomati
*/
hr
=
IUIAutomation_AddAutomationEventHandler
(
uia_iface
,
UIA_LiveRegionChangedEventId
,
NULL
,
TreeScope_SubTree
,
NULL
,
&
AutomationEventHandler
.
IUIAutomationEventHandler_iface
);
todo_wine
ok
(
hr
==
E_POINTER
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
hr
==
E_POINTER
,
"Unexpected hr %#lx.
\n
"
,
hr
);
hr
=
IUIAutomation_AddAutomationEventHandler
(
uia_iface
,
UIA_LiveRegionChangedEventId
,
elem
,
TreeScope_SubTree
,
NULL
,
NULL
);
todo_wine
ok
(
hr
==
E_POINTER
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
hr
==
E_POINTER
,
"Unexpected hr %#lx.
\n
"
,
hr
);
/*
* Passing in a NULL element to this method results in an access violation
...
...
@@ -13118,21 +13118,21 @@ static void test_IUIAutomationEventHandler(IUIAutomation *uia_iface, IUIAutomati
*/
hr
=
IUIAutomation_AddAutomationEventHandler
(
uia_iface
,
UIA_AutomationFocusChangedEventId
,
elem
,
TreeScope_SubTree
,
NULL
,
&
AutomationEventHandler
.
IUIAutomationEventHandler_iface
);
todo_wine
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#lx.
\n
"
,
hr
);
/* Windows 11 queries the HWND for the element when adding a new handler. */
set_uia_hwnd_expects
(
3
,
2
,
2
,
3
,
0
);
/* All other event IDs are fine, only focus events are blocked. */
hr
=
IUIAutomation_AddAutomationEventHandler
(
uia_iface
,
1
,
elem
,
TreeScope_SubTree
,
NULL
,
&
AutomationEventHandler
.
IUIAutomationEventHandler_iface
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
AutomationEventHandler
.
ref
>
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
AutomationEventHandler
.
ref
>
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
check_uia_hwnd_expects_at_most
(
3
,
2
,
2
,
3
,
0
);
hr
=
IUIAutomation_RemoveAutomationEventHandler
(
uia_iface
,
1
,
elem
,
&
AutomationEventHandler
.
IUIAutomationEventHandler_iface
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
AutomationEventHandler
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
todo_wine
ok
(
AutomationEventHandler
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
/*
* Test event raising behavior.
...
...
@@ -13140,8 +13140,8 @@ static void test_IUIAutomationEventHandler(IUIAutomation *uia_iface, IUIAutomati
set_uia_hwnd_expects
(
3
,
2
,
2
,
3
,
0
);
hr
=
IUIAutomation_AddAutomationEventHandler
(
uia_iface
,
UIA_LiveRegionChangedEventId
,
elem
,
TreeScope_SubTree
,
NULL
,
&
AutomationEventHandler
.
IUIAutomationEventHandler_iface
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
AutomationEventHandler
.
ref
>
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
AutomationEventHandler
.
ref
>
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
check_uia_hwnd_expects_at_most
(
3
,
2
,
2
,
3
,
0
);
/* Same behavior as HUIAEVENTs, events are matched by runtime ID. */
...
...
@@ -13184,7 +13184,7 @@ static void test_IUIAutomationEventHandler(IUIAutomation *uia_iface, IUIAutomati
hr
=
IUIAutomation_RemoveAutomationEventHandler
(
uia_iface
,
UIA_LiveRegionChangedEventId
,
elem
,
&
AutomationEventHandler
.
IUIAutomationEventHandler_iface
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
AutomationEventHandler
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
todo_wine
ok
(
AutomationEventHandler
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
VariantInit
(
&
v
);
initialize_provider
(
&
Provider_child
,
ProviderOptions_ServerSideProvider
,
NULL
,
TRUE
);
...
...
@@ -13207,18 +13207,18 @@ static void test_IUIAutomationEventHandler(IUIAutomation *uia_iface, IUIAutomati
*/
hr
=
IUIAutomation_AddAutomationEventHandler
(
uia_iface
,
UIA_LiveRegionChangedEventId
,
elem2
,
TreeScope_SubTree
,
NULL
,
&
AutomationEventHandler
.
IUIAutomationEventHandler_iface
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
AutomationEventHandler
.
ref
>
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
AutomationEventHandler
.
ref
>
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
/* No removal will occur due to a lack of a runtime ID to match. */
hr
=
IUIAutomation_RemoveAutomationEventHandler
(
uia_iface
,
UIA_LiveRegionChangedEventId
,
elem2
,
&
AutomationEventHandler
.
IUIAutomationEventHandler_iface
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
AutomationEventHandler
.
ref
>
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
ok
(
AutomationEventHandler
.
ref
>
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
hr
=
IUIAutomation_RemoveAllEventHandlers
(
uia_iface
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
AutomationEventHandler
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
todo_wine
ok
(
AutomationEventHandler
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
AutomationEventHandler
.
ref
);
IUIAutomationElement_Release
(
elem2
);
}
...
...
dlls/uiautomationcore/uia_com_client.c
View file @
4cc7525a
...
...
@@ -899,6 +899,123 @@ static HRESULT get_uia_cache_request_struct_from_iface(IUIAutomationCacheRequest
}
/*
* COM API UI Automation event related functions.
*/
static
struct
uia_com_event_handlers
{
struct
rb_tree
handler_map
;
LONG
handler_count
;
}
com_event_handlers
;
static
CRITICAL_SECTION
com_event_handlers_cs
;
static
CRITICAL_SECTION_DEBUG
com_event_handlers_cs_debug
=
{
0
,
0
,
&
com_event_handlers_cs
,
{
&
com_event_handlers_cs_debug
.
ProcessLocksList
,
&
com_event_handlers_cs_debug
.
ProcessLocksList
},
0
,
0
,
{
(
DWORD_PTR
)(
__FILE__
": com_event_handlers_cs"
)
}
};
static
CRITICAL_SECTION
com_event_handlers_cs
=
{
&
com_event_handlers_cs_debug
,
-
1
,
0
,
0
,
0
,
0
};
struct
uia_event_handler_identifier
{
IUnknown
*
handler_iface
;
SAFEARRAY
*
runtime_id
;
int
event_id
;
};
struct
uia_event_handler_map_entry
{
struct
rb_entry
entry
;
IUnknown
*
handler_iface
;
SAFEARRAY
*
runtime_id
;
int
event_id
;
struct
list
handlers_list
;
};
static
int
uia_com_event_handler_id_compare
(
const
void
*
key
,
const
struct
rb_entry
*
entry
)
{
struct
uia_event_handler_map_entry
*
map_entry
=
RB_ENTRY_VALUE
(
entry
,
struct
uia_event_handler_map_entry
,
entry
);
struct
uia_event_handler_identifier
*
event_id
=
(
struct
uia_event_handler_identifier
*
)
key
;
if
(
event_id
->
event_id
!=
map_entry
->
event_id
)
return
(
event_id
->
event_id
>
map_entry
->
event_id
)
-
(
event_id
->
event_id
<
map_entry
->
event_id
);
else
if
(
event_id
->
handler_iface
!=
map_entry
->
handler_iface
)
return
(
event_id
->
handler_iface
>
map_entry
->
handler_iface
)
-
(
event_id
->
handler_iface
<
map_entry
->
handler_iface
);
else
if
(
event_id
->
runtime_id
&&
map_entry
->
runtime_id
)
return
uia_compare_safearrays
(
event_id
->
runtime_id
,
map_entry
->
runtime_id
,
UIAutomationType_IntArray
);
else
return
(
event_id
->
runtime_id
>
map_entry
->
runtime_id
)
-
(
event_id
->
runtime_id
<
map_entry
->
runtime_id
);
}
struct
uia_com_event
{
IUnknown
*
handler_iface
;
struct
list
event_handler_map_list_entry
;
struct
uia_event_handler_map_entry
*
handler_map
;
};
static
HRESULT
uia_event_handlers_add_handler
(
IUnknown
*
handler_iface
,
SAFEARRAY
*
runtime_id
,
int
event_id
)
{
struct
uia_event_handler_identifier
event_ident
=
{
handler_iface
,
runtime_id
,
event_id
};
struct
uia_event_handler_map_entry
*
event_map
;
struct
uia_com_event
*
event
;
struct
rb_entry
*
rb_entry
;
HRESULT
hr
=
S_OK
;
if
(
!
(
event
=
heap_alloc_zero
(
sizeof
(
*
event
))))
return
E_OUTOFMEMORY
;
event
->
handler_iface
=
handler_iface
;
IUnknown_AddRef
(
handler_iface
);
EnterCriticalSection
(
&
com_event_handlers_cs
);
if
(
!
com_event_handlers
.
handler_count
)
rb_init
(
&
com_event_handlers
.
handler_map
,
uia_com_event_handler_id_compare
);
if
((
rb_entry
=
rb_get
(
&
com_event_handlers
.
handler_map
,
&
event_ident
)))
event_map
=
RB_ENTRY_VALUE
(
rb_entry
,
struct
uia_event_handler_map_entry
,
entry
);
else
{
if
(
!
(
event_map
=
heap_alloc_zero
(
sizeof
(
*
event_map
))))
{
hr
=
E_OUTOFMEMORY
;
goto
exit
;
}
hr
=
SafeArrayCopy
(
runtime_id
,
&
event_map
->
runtime_id
);
if
(
FAILED
(
hr
))
{
heap_free
(
event_map
);
goto
exit
;
}
event_map
->
event_id
=
event_id
;
event_map
->
handler_iface
=
event
->
handler_iface
;
IUnknown_AddRef
(
event_map
->
handler_iface
);
list_init
(
&
event_map
->
handlers_list
);
rb_put
(
&
com_event_handlers
.
handler_map
,
&
event_ident
,
&
event_map
->
entry
);
}
list_add_tail
(
&
event_map
->
handlers_list
,
&
event
->
event_handler_map_list_entry
);
event
->
handler_map
=
event_map
;
com_event_handlers
.
handler_count
++
;
exit:
LeaveCriticalSection
(
&
com_event_handlers_cs
);
if
(
FAILED
(
hr
))
{
IUnknown_Release
(
event
->
handler_iface
);
heap_free
(
event
);
}
return
hr
;
}
/*
* IUIAutomationElementArray interface.
*/
struct
uia_element_array
{
...
...
@@ -3052,8 +3169,35 @@ static HRESULT WINAPI uia_iface_AddAutomationEventHandler(IUIAutomation6 *iface,
IUIAutomationElement
*
elem
,
enum
TreeScope
scope
,
IUIAutomationCacheRequest
*
cache_req
,
IUIAutomationEventHandler
*
handler
)
{
FIXME
(
"%p, %d, %p, %#x, %p, %p: stub
\n
"
,
iface
,
event_id
,
elem
,
scope
,
cache_req
,
handler
);
return
E_NOTIMPL
;
struct
uia_element
*
element
;
IUnknown
*
handler_iface
;
SAFEARRAY
*
runtime_id
;
HRESULT
hr
;
TRACE
(
"%p, %d, %p, %#x, %p, %p
\n
"
,
iface
,
event_id
,
elem
,
scope
,
cache_req
,
handler
);
if
(
!
elem
||
!
handler
)
return
E_POINTER
;
if
(
event_id
==
UIA_AutomationFocusChangedEventId
)
return
E_INVALIDARG
;
hr
=
IUIAutomationEventHandler_QueryInterface
(
handler
,
&
IID_IUnknown
,
(
void
**
)
&
handler_iface
);
if
(
FAILED
(
hr
))
return
hr
;
element
=
impl_from_IUIAutomationElement9
((
IUIAutomationElement9
*
)
elem
);
hr
=
UiaGetRuntimeId
(
element
->
node
,
&
runtime_id
);
if
(
FAILED
(
hr
))
goto
exit
;
hr
=
uia_event_handlers_add_handler
(
handler_iface
,
runtime_id
,
event_id
);
exit:
IUnknown_Release
(
handler_iface
);
SafeArrayDestroy
(
runtime_id
);
return
hr
;
}
static
HRESULT
WINAPI
uia_iface_RemoveAutomationEventHandler
(
IUIAutomation6
*
iface
,
EVENTID
event_id
,
...
...
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