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
407ce9a1
Commit
407ce9a1
authored
May 15, 2023
by
Connor McAdams
Committed by
Alexandre Julliard
May 26, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
uiautomationcore: Implement UiaAddEvent.
Signed-off-by:
Connor McAdams
<
cmcadams@codeweavers.com
>
parent
a3e71d4c
Hide whitespace changes
Inline
Side-by-side
Showing
7 changed files
with
237 additions
and
31 deletions
+237
-31
Makefile.in
dlls/uiautomationcore/Makefile.in
+1
-0
uiautomation.c
dlls/uiautomationcore/tests/uiautomation.c
+59
-20
uia_classes.idl
dlls/uiautomationcore/uia_classes.idl
+9
-0
uia_client.c
dlls/uiautomationcore/uia_client.c
+0
-11
uia_event.c
dlls/uiautomationcore/uia_event.c
+148
-0
uia_ids.c
dlls/uiautomationcore/uia_ids.c
+19
-0
uia_private.h
dlls/uiautomationcore/uia_private.h
+1
-0
No files found.
dlls/uiautomationcore/Makefile.in
View file @
407ce9a1
...
...
@@ -7,6 +7,7 @@ EXTRADLLFLAGS = -Wb,--prefer-native
C_SRCS
=
\
uia_client.c
\
uia_com_client.c
\
uia_event.c
\
uia_ids.c
\
uia_main.c
\
uia_provider.c
...
...
dlls/uiautomationcore/tests/uiautomation.c
View file @
407ce9a1
...
...
@@ -13819,6 +13819,45 @@ static DWORD WINAPI uia_add_event_test_thread(LPVOID param)
return
0
;
}
static
void
test_UiaAddEvent_args
(
HUIANODE
node
)
{
struct
UiaCacheRequest
cache_req
;
HUIAEVENT
event
;
HRESULT
hr
;
set_cache_request
(
&
cache_req
,
(
struct
UiaCondition
*
)
&
UiaTrueCondition
,
TreeScope_Element
,
NULL
,
0
,
NULL
,
0
,
AutomationElementMode_Full
);
/* NULL node. */
hr
=
UiaAddEvent
(
NULL
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Element
,
NULL
,
0
,
&
cache_req
,
&
event
);
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#lx.
\n
"
,
hr
);
/* NULL event callback. */
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
NULL
,
TreeScope_Element
,
NULL
,
0
,
&
cache_req
,
&
event
);
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#lx.
\n
"
,
hr
);
/* NULL cache request. */
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Element
,
NULL
,
0
,
NULL
,
&
event
);
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#lx.
\n
"
,
hr
);
/* NULL event handle. */
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Element
,
NULL
,
0
,
&
cache_req
,
NULL
);
ok
(
hr
==
E_INVALIDARG
,
"Unexpected hr %#lx.
\n
"
,
hr
);
/* Event IDs aren't checked for validity, 1 is not a valid UIA event ID. */
event
=
NULL
;
hr
=
UiaAddEvent
(
node
,
1
,
uia_event_callback
,
TreeScope_Element
,
NULL
,
0
,
&
cache_req
,
&
event
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!!
event
,
"event == NULL
\n
"
);
hr
=
UiaRemoveEvent
(
event
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
}
static
void
test_UiaAddEvent
(
void
)
{
IRawElementProviderFragmentRoot
*
embedded_roots
[
2
]
=
{
&
Provider_child
.
IRawElementProviderFragmentRoot_iface
,
...
...
@@ -13855,6 +13894,9 @@ static void test_UiaAddEvent(void)
check_node_provider_desc
(
V_BSTR
(
&
v
),
L"Main"
,
L"Provider"
,
TRUE
);
VariantClear
(
&
v
);
/* Test valid function input arguments. */
test_UiaAddEvent_args
(
node
);
/*
* Raise event without any registered event handlers.
*/
...
...
@@ -13875,11 +13917,10 @@ static void test_UiaAddEvent(void)
AutomationElementMode_Full
);
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Element
,
NULL
,
0
,
&
cache_req
,
&
event
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
!!
event
,
"event == NULL
\n
"
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!!
event
,
"event == NULL
\n
"
);
todo_wine
ok
(
Provider
.
ref
==
3
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
if
(
SUCCEEDED
(
hr
))
ok_method_sequence
(
event_seq2
,
"event_seq2"
);
ok_method_sequence
(
event_seq2
,
"event_seq2"
);
/*
* Even though we raise an event on the same provider as the one our node
...
...
@@ -13911,11 +13952,10 @@ static void test_UiaAddEvent(void)
Provider
.
runtime_id
[
0
]
=
Provider
.
runtime_id
[
1
]
=
0xdeadbeef
;
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Element
,
NULL
,
0
,
&
cache_req
,
&
event
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
!!
event
,
"event == NULL
\n
"
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!!
event
,
"event == NULL
\n
"
);
todo_wine
ok
(
Provider
.
ref
==
3
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
if
(
SUCCEEDED
(
hr
))
ok_method_sequence
(
event_seq2
,
"event_seq2"
);
ok_method_sequence
(
event_seq2
,
"event_seq2"
);
/* Event callback is now invoked since we can match by runtime ID. */
method_sequences_enabled
=
FALSE
;
...
...
@@ -13953,11 +13993,10 @@ static void test_UiaAddEvent(void)
/* Create an event with TreeScope_Children. */
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Children
,
NULL
,
0
,
&
cache_req
,
&
event
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
!!
event
,
"event == NULL
\n
"
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!!
event
,
"event == NULL
\n
"
);
todo_wine
ok
(
Provider
.
ref
==
3
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
if
(
SUCCEEDED
(
hr
))
ok_method_sequence
(
event_seq5
,
"event_seq5"
);
ok_method_sequence
(
event_seq5
,
"event_seq5"
);
/*
* Only TreeScope_Children and not TreeScope_Element, handler won't be
...
...
@@ -14001,8 +14040,8 @@ static void test_UiaAddEvent(void)
/* Create an event with TreeScope_Descendants. */
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Element
|
TreeScope_Descendants
,
NULL
,
0
,
&
cache_req
,
&
event
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
!!
event
,
"event == NULL
\n
"
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!!
event
,
"event == NULL
\n
"
);
todo_wine
ok
(
Provider
.
ref
==
3
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
/* Raised an event on Provider_child_child. */
...
...
@@ -14034,8 +14073,8 @@ static void test_UiaAddEvent(void)
Provider
.
frag_root
=
&
Provider2
.
IRawElementProviderFragmentRoot_iface
;
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Element
|
TreeScope_Descendants
,
NULL
,
0
,
&
cache_req
,
&
event
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
!!
event
,
"event == NULL
\n
"
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!!
event
,
"event == NULL
\n
"
);
ok
(
Provider
.
ref
==
2
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
todo_wine
ok
(
Provider2
.
ref
>
1
,
"Unexpected refcnt %ld
\n
"
,
Provider2
.
ref
);
ok
(
!
Provider
.
advise_events_added_event_id
,
"Unexpected advise event added, event ID %d
\n
"
,
Provider
.
advise_events_added_event_id
);
...
...
@@ -14069,8 +14108,8 @@ static void test_UiaAddEvent(void)
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Element
|
TreeScope_Descendants
,
NULL
,
0
,
&
cache_req
,
&
event
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
!!
event
,
"event == NULL
\n
"
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!!
event
,
"event == NULL
\n
"
);
todo_wine
ok
(
Provider
.
ref
==
3
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
todo_wine
ok
(
Provider_child
.
ref
==
2
,
"Unexpected refcnt %ld
\n
"
,
Provider_child
.
ref
);
todo_wine
ok
(
Provider_child2
.
ref
==
2
,
"Unexpected refcnt %ld
\n
"
,
Provider_child2
.
ref
);
...
...
@@ -14132,8 +14171,8 @@ static void test_UiaAddEvent(void)
AutomationElementMode_Full
);
hr
=
UiaAddEvent
(
node
,
UIA_AutomationFocusChangedEventId
,
uia_event_callback
,
TreeScope_Element
|
TreeScope_Children
,
NULL
,
0
,
&
cache_req
,
&
event
);
todo_wine
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
todo_wine
ok
(
!!
event
,
"event == NULL
\n
"
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!!
event
,
"event == NULL
\n
"
);
/*
* Raising an event on a serverside provider results in no clientside
...
...
dlls/uiautomationcore/uia_classes.idl
View file @
407ce9a1
...
...
@@ -56,6 +56,15 @@ library UIA_wine_private
[
object
,
uuid
(
5
e60162c
-
ab0e
-
4
e22
-
a61d
-
3
a3acd442aba
),
pointer_default
(
unique
),
]
interface
IWineUiaEvent
:
IUnknown
{
}
[
object
,
uuid
(
57865755
-
6
c05
-
4522
-
98
df
-
4
ca658b768ef
),
pointer_default
(
unique
),
oleautomation
,
...
...
dlls/uiautomationcore/uia_client.c
View file @
407ce9a1
...
...
@@ -3514,17 +3514,6 @@ exit:
}
/***********************************************************************
* UiaAddEvent (uiautomationcore.@)
*/
HRESULT
WINAPI
UiaAddEvent
(
HUIANODE
huianode
,
EVENTID
event_id
,
UiaEventCallback
*
callback
,
enum
TreeScope
scope
,
PROPERTYID
*
prop_ids
,
int
prop_ids_count
,
struct
UiaCacheRequest
*
cache_req
,
HUIAEVENT
*
huiaevent
)
{
FIXME
(
"(%p, %d, %p, %#x, %p, %d, %p, %p)
\n
"
,
huianode
,
event_id
,
callback
,
scope
,
prop_ids
,
prop_ids_count
,
cache_req
,
huiaevent
);
return
E_NOTIMPL
;
}
/***********************************************************************
* UiaRemoveEvent (uiautomationcore.@)
*/
HRESULT
WINAPI
UiaRemoveEvent
(
HUIAEVENT
huiaevent
)
...
...
dlls/uiautomationcore/uia_event.c
0 → 100644
View file @
407ce9a1
/*
* Copyright 2023 Connor McAdams for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "uia_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
uiautomation
);
struct
uia_event
{
IWineUiaEvent
IWineUiaEvent_iface
;
LONG
ref
;
SAFEARRAY
*
runtime_id
;
int
event_id
;
int
scope
;
UiaEventCallback
*
cback
;
};
/*
* IWineUiaEvent interface.
*/
static
inline
struct
uia_event
*
impl_from_IWineUiaEvent
(
IWineUiaEvent
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
uia_event
,
IWineUiaEvent_iface
);
}
static
HRESULT
WINAPI
uia_event_QueryInterface
(
IWineUiaEvent
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IWineUiaEvent
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
*
ppv
=
iface
;
else
return
E_NOINTERFACE
;
IWineUiaEvent_AddRef
(
iface
);
return
S_OK
;
}
static
ULONG
WINAPI
uia_event_AddRef
(
IWineUiaEvent
*
iface
)
{
struct
uia_event
*
event
=
impl_from_IWineUiaEvent
(
iface
);
ULONG
ref
=
InterlockedIncrement
(
&
event
->
ref
);
TRACE
(
"%p, refcount %ld
\n
"
,
event
,
ref
);
return
ref
;
}
static
ULONG
WINAPI
uia_event_Release
(
IWineUiaEvent
*
iface
)
{
struct
uia_event
*
event
=
impl_from_IWineUiaEvent
(
iface
);
ULONG
ref
=
InterlockedDecrement
(
&
event
->
ref
);
TRACE
(
"%p, refcount %ld
\n
"
,
event
,
ref
);
if
(
!
ref
)
{
SafeArrayDestroy
(
event
->
runtime_id
);
heap_free
(
event
);
}
return
ref
;
}
static
const
IWineUiaEventVtbl
uia_event_vtbl
=
{
uia_event_QueryInterface
,
uia_event_AddRef
,
uia_event_Release
,
};
static
HRESULT
create_uia_event
(
struct
uia_event
**
out_event
,
int
event_id
,
int
scope
,
UiaEventCallback
*
cback
,
SAFEARRAY
*
runtime_id
)
{
struct
uia_event
*
event
=
heap_alloc_zero
(
sizeof
(
*
event
));
*
out_event
=
NULL
;
if
(
!
event
)
return
E_OUTOFMEMORY
;
event
->
IWineUiaEvent_iface
.
lpVtbl
=
&
uia_event_vtbl
;
event
->
ref
=
1
;
event
->
runtime_id
=
runtime_id
;
event
->
event_id
=
event_id
;
event
->
scope
=
scope
;
event
->
cback
=
cback
;
*
out_event
=
event
;
return
S_OK
;
}
/***********************************************************************
* UiaAddEvent (uiautomationcore.@)
*/
HRESULT
WINAPI
UiaAddEvent
(
HUIANODE
huianode
,
EVENTID
event_id
,
UiaEventCallback
*
callback
,
enum
TreeScope
scope
,
PROPERTYID
*
prop_ids
,
int
prop_ids_count
,
struct
UiaCacheRequest
*
cache_req
,
HUIAEVENT
*
huiaevent
)
{
const
struct
uia_event_info
*
event_info
=
uia_event_info_from_id
(
event_id
);
struct
uia_event
*
event
;
SAFEARRAY
*
sa
;
HRESULT
hr
;
TRACE
(
"(%p, %d, %p, %#x, %p, %d, %p, %p)
\n
"
,
huianode
,
event_id
,
callback
,
scope
,
prop_ids
,
prop_ids_count
,
cache_req
,
huiaevent
);
if
(
!
huianode
||
!
callback
||
!
cache_req
||
!
huiaevent
)
return
E_INVALIDARG
;
if
(
!
event_info
)
WARN
(
"No event information for event ID %d
\n
"
,
event_id
);
*
huiaevent
=
NULL
;
if
(
event_info
&&
(
event_info
->
event_arg_type
==
EventArgsType_PropertyChanged
))
{
FIXME
(
"Property changed event registration currently unimplemented
\n
"
);
return
E_NOTIMPL
;
}
hr
=
UiaGetRuntimeId
(
huianode
,
&
sa
);
if
(
FAILED
(
hr
))
return
hr
;
hr
=
create_uia_event
(
&
event
,
event_id
,
scope
,
callback
,
sa
);
if
(
FAILED
(
hr
))
{
SafeArrayDestroy
(
sa
);
return
hr
;
}
*
huiaevent
=
(
HUIAEVENT
)
event
;
return
S_OK
;
}
dlls/uiautomationcore/uia_ids.c
View file @
407ce9a1
...
...
@@ -413,6 +413,17 @@ static const struct uia_event_info default_uia_events[] = {
EventArgsType_Simple
,
},
};
static
const
int
event_id_idx
[]
=
{
0x23
,
0x1d
,
0x0d
,
0x0b
,
0x19
,
0x06
,
0x07
,
0x0f
,
0x0a
,
0x1e
,
0x1b
,
0x1a
,
0x22
,
0x00
,
0x18
,
0x10
,
0x01
,
0x20
,
0x08
,
0x17
,
0x15
,
0x13
,
0x0e
,
0x0c
,
0x14
,
0x09
,
0x03
,
0x21
,
0x12
,
0x16
,
0x05
,
0x1c
,
0x02
,
0x11
,
0x04
,
0x1f
,
};
#define EVENT_ID_MIN 20000
#define EVENT_ID_MAX (EVENT_ID_MIN + ARRAY_SIZE(default_uia_events))
static
const
struct
uia_event_info
*
uia_event_info_from_guid
(
const
GUID
*
guid
)
{
struct
uia_event_info
*
event
;
...
...
@@ -424,6 +435,14 @@ static const struct uia_event_info *uia_event_info_from_guid(const GUID *guid)
return
NULL
;
}
const
struct
uia_event_info
*
uia_event_info_from_id
(
EVENTID
event_id
)
{
if
((
event_id
<
EVENT_ID_MIN
)
||
(
event_id
>=
EVENT_ID_MAX
))
return
NULL
;
return
&
default_uia_events
[
event_id_idx
[
event_id
-
EVENT_ID_MIN
]];
}
/* Sorted by GUID. */
static
const
struct
uia_pattern_info
default_uia_patterns
[]
=
{
{
&
ScrollItem_Pattern_GUID
,
UIA_ScrollItemPatternId
,
...
...
dlls/uiautomationcore/uia_private.h
View file @
407ce9a1
...
...
@@ -147,6 +147,7 @@ HRESULT create_uia_iface(IUnknown **iface, BOOL is_cui8) DECLSPEC_HIDDEN;
/* uia_ids.c */
const
struct
uia_prop_info
*
uia_prop_info_from_id
(
PROPERTYID
prop_id
)
DECLSPEC_HIDDEN
;
const
struct
uia_event_info
*
uia_event_info_from_id
(
EVENTID
event_id
)
DECLSPEC_HIDDEN
;
const
struct
uia_pattern_info
*
uia_pattern_info_from_id
(
PATTERNID
pattern_id
)
DECLSPEC_HIDDEN
;
const
struct
uia_control_type_info
*
uia_control_type_info_from_id
(
CONTROLTYPEID
control_type_id
)
DECLSPEC_HIDDEN
;
...
...
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