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
cd9f3e5d
Commit
cd9f3e5d
authored
Mar 24, 2023
by
Connor McAdams
Committed by
Alexandre Julliard
Apr 19, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
uiautomationcore: Add normalization navigation to UiaGetUpdatedCache.
Signed-off-by:
Connor McAdams
<
cmcadams@codeweavers.com
>
parent
f93bd3ff
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
134 additions
and
32 deletions
+134
-32
uiautomation.c
dlls/uiautomationcore/tests/uiautomation.c
+86
-0
uia_client.c
dlls/uiautomationcore/uia_client.c
+48
-32
No files found.
dlls/uiautomationcore/tests/uiautomation.c
View file @
cd9f3e5d
...
...
@@ -7873,6 +7873,34 @@ static const struct prov_method_sequence cache_req_seq7[] = {
{
0
}
};
static
const
struct
prov_method_sequence
cache_req_seq8
[]
=
{
NODE_CREATE_SEQ
(
&
Provider_child
),
{
0
}
};
static
const
struct
prov_method_sequence
cache_req_seq9
[]
=
{
{
&
Provider_child
,
PROV_GET_PROPERTY_VALUE
},
/* UIA_IsControlElementPropertyId */
/* Done twice on Windows, but we shouldn't need to replicate this. */
{
&
Provider_child
,
PROV_GET_PROPERTY_VALUE
,
METHOD_OPTIONAL
},
/* UIA_IsControlElementPropertyId */
{
&
Provider_child
,
FRAG_NAVIGATE
},
/* NavigateDirection_Parent */
NODE_CREATE_SEQ
(
&
Provider
),
{
&
Provider
,
PROV_GET_PROPERTY_VALUE
},
/* UIA_IsControlElementPropertyId */
/* Only done on Win10v1507 and below. */
{
&
Provider
,
FRAG_NAVIGATE
,
METHOD_OPTIONAL
},
/* NavigateDirection_Parent */
{
0
}
};
static
const
struct
prov_method_sequence
cache_req_seq10
[]
=
{
{
&
Provider_child
,
PROV_GET_PROPERTY_VALUE
},
/* UIA_IsControlElementPropertyId */
/* Done twice on Windows, but we shouldn't need to replicate this. */
{
&
Provider_child
,
PROV_GET_PROPERTY_VALUE
,
METHOD_OPTIONAL
},
/* UIA_IsControlElementPropertyId */
{
&
Provider_child
,
FRAG_NAVIGATE
},
/* NavigateDirection_Parent */
NODE_CREATE_SEQ
(
&
Provider
),
{
&
Provider
,
PROV_GET_PROPERTY_VALUE
},
/* UIA_IsControlElementPropertyId */
{
&
Provider
,
PROV_GET_PROPERTY_VALUE
},
/* UIA_ProviderDescriptionPropertyId. */
{
0
}
};
static
const
struct
UiaCondition
UiaTrueCondition
=
{
ConditionType_True
};
static
const
struct
UiaCondition
UiaFalseCondition
=
{
ConditionType_False
};
static
void
test_UiaGetUpdatedCache
(
void
)
...
...
@@ -8419,7 +8447,65 @@ static void test_UiaGetUpdatedCache(void)
ok
(
UiaNodeRelease
(
node
),
"UiaNodeRelease returned FALSE
\n
"
);
ok
(
Provider
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
/* Normalization navigation tests. */
initialize_provider
(
&
Provider
,
ProviderOptions_ServerSideProvider
,
NULL
,
FALSE
);
initialize_provider
(
&
Provider_child
,
ProviderOptions_ServerSideProvider
,
NULL
,
FALSE
);
hr
=
UiaNodeFromProvider
(
&
Provider_child
.
IRawElementProviderSimple_iface
,
&
node
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
Provider_child
.
ref
==
2
,
"Unexpected refcnt %ld
\n
"
,
Provider_child
.
ref
);
ok_method_sequence
(
cache_req_seq8
,
"cache_req_seq8"
);
/*
* Neither Provider_child or Provider match this condition, return
* nothing.
*/
variant_init_bool
(
&
v
,
FALSE
);
set_property_condition
(
&
prop_cond
,
UIA_IsControlElementPropertyId
,
&
v
,
PropertyConditionFlags_None
);
set_cache_request
(
&
cache_req
,
(
struct
UiaCondition
*
)
&
prop_cond
,
TreeScope_Element
,
NULL
,
0
,
NULL
,
0
,
AutomationElementMode_Full
);
tree_struct
=
NULL
;
out_req
=
NULL
;
hr
=
UiaGetUpdatedCache
(
node
,
&
cache_req
,
NormalizeState_View
,
NULL
,
&
out_req
,
&
tree_struct
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!
out_req
,
"out_req != NULL
\n
"
);
ok
(
!!
tree_struct
,
"tree_struct == NULL
\n
"
);
ok
(
!
wcscmp
(
tree_struct
,
L""
),
"tree structure %s
\n
"
,
debugstr_w
(
tree_struct
));
SysFreeString
(
tree_struct
);
ok_method_sequence
(
cache_req_seq9
,
"cache_req_seq9"
);
/*
* Provider now matches our condition, we'll get Provider in the cache
* request.
*/
variant_init_bool
(
&
v
,
FALSE
);
set_property_override
(
&
prop_override
,
UIA_IsControlElementPropertyId
,
&
v
);
set_provider_prop_override
(
&
Provider
,
&
prop_override
,
1
);
init_node_provider_desc
(
&
exp_node_desc
[
0
],
GetCurrentProcessId
(),
NULL
);
add_provider_desc
(
&
exp_node_desc
[
0
],
L"Main"
,
L"Provider"
,
TRUE
);
set_cache_request
(
&
cache_req
,
(
struct
UiaCondition
*
)
&
prop_cond
,
TreeScope_Element
,
NULL
,
0
,
NULL
,
0
,
AutomationElementMode_Full
);
tree_struct
=
NULL
;
out_req
=
NULL
;
hr
=
UiaGetUpdatedCache
(
node
,
&
cache_req
,
NormalizeState_View
,
NULL
,
&
out_req
,
&
tree_struct
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
!!
out_req
,
"out_req == NULL
\n
"
);
ok
(
!!
tree_struct
,
"tree_struct == NULL
\n
"
);
ok
(
Provider
.
ref
==
2
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
exp_lbound
[
0
]
=
exp_lbound
[
1
]
=
0
;
exp_elems
[
0
]
=
exp_elems
[
1
]
=
1
;
test_cache_req_sa
(
out_req
,
exp_lbound
,
exp_elems
,
exp_node_desc
);
ok
(
!
wcscmp
(
tree_struct
,
L"P)"
),
"tree structure %s
\n
"
,
debugstr_w
(
tree_struct
));
ok_method_sequence
(
cache_req_seq10
,
"cache_req_seq10"
);
ok
(
Provider
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
SafeArrayDestroy
(
out_req
);
SysFreeString
(
tree_struct
);
VariantClear
(
&
v
);
ok
(
UiaNodeRelease
(
node
),
"UiaNodeRelease returned FALSE
\n
"
);
ok
(
Provider_child
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
Provider_child
.
ref
);
initialize_provider
(
&
Provider
,
ProviderOptions_ServerSideProvider
,
NULL
,
FALSE
);
initialize_provider
(
&
Provider_child
,
ProviderOptions_ServerSideProvider
,
NULL
,
FALSE
);
IUnknown_Release
(
unk_ns
);
CoUninitialize
();
...
...
dlls/uiautomationcore/uia_client.c
View file @
cd9f3e5d
...
...
@@ -2992,6 +2992,31 @@ static HRESULT uia_condition_check(HUIANODE node, struct UiaCondition *condition
}
}
static
HRESULT
uia_node_normalize
(
HUIANODE
huianode
,
struct
UiaCondition
*
cond
,
HUIANODE
*
normalized_node
)
{
struct
uia_node
*
node
=
impl_from_IWineUiaNode
((
IWineUiaNode
*
)
huianode
);
HRESULT
hr
;
*
normalized_node
=
NULL
;
if
(
cond
)
{
hr
=
uia_condition_check
(
huianode
,
cond
);
if
(
FAILED
(
hr
))
return
hr
;
/*
* If our initial node doesn't match our normalization condition, need
* to get the nearest ancestor that does.
*/
if
(
!
uia_condition_matched
(
hr
))
return
conditional_navigate_uia_node
(
node
,
NavigateDirection_Parent
,
cond
,
normalized_node
);
}
*
normalized_node
=
huianode
;
IWineUiaNode_AddRef
(
&
node
->
IWineUiaNode_iface
);
return
S_OK
;
}
/***********************************************************************
* UiaGetUpdatedCache (uiautomationcore.@)
*/
...
...
@@ -3001,6 +3026,7 @@ HRESULT WINAPI UiaGetUpdatedCache(HUIANODE huianode, struct UiaCacheRequest *cac
struct
uia_node
*
node
=
unsafe_impl_from_IWineUiaNode
((
IWineUiaNode
*
)
huianode
);
struct
UiaCondition
*
cond
;
SAFEARRAYBOUND
sabound
[
2
];
HUIANODE
ret_node
;
SAFEARRAY
*
sa
;
LONG
idx
[
2
];
HRESULT
hr
;
...
...
@@ -3052,17 +3078,14 @@ HRESULT WINAPI UiaGetUpdatedCache(HUIANODE huianode, struct UiaCacheRequest *cac
return
E_INVALIDARG
;
}
if
(
cond
)
{
hr
=
uia_condition_check
(
huianode
,
cond
);
if
(
FAILED
(
hr
))
return
hr
;
hr
=
uia_node_normalize
(
huianode
,
cond
,
&
ret_node
);
if
(
FAILED
(
hr
))
return
hr
;
if
(
!
uia_condition_matched
(
hr
))
{
*
tree_struct
=
SysAllocString
(
L""
);
return
S_OK
;
}
if
(
!
ret_node
)
{
*
tree_struct
=
SysAllocString
(
L""
);
return
S_OK
;
}
sabound
[
0
].
cElements
=
1
;
...
...
@@ -3071,51 +3094,44 @@ HRESULT WINAPI UiaGetUpdatedCache(HUIANODE huianode, struct UiaCacheRequest *cac
if
(
!
(
sa
=
SafeArrayCreate
(
VT_VARIANT
,
2
,
sabound
)))
{
WARN
(
"Failed to create safearray
\n
"
);
return
E_FAIL
;
hr
=
E_FAIL
;
goto
exit
;
}
get_variant_for_node
(
huia
node
,
&
v
);
get_variant_for_node
(
ret_
node
,
&
v
);
idx
[
0
]
=
idx
[
1
]
=
0
;
hr
=
SafeArrayPutElement
(
sa
,
idx
,
&
v
);
if
(
FAILED
(
hr
))
{
SafeArrayDestroy
(
sa
);
return
hr
;
}
goto
exit
;
idx
[
0
]
=
0
;
VariantClear
(
&
v
);
for
(
i
=
0
;
i
<
cache_req
->
cProperties
;
i
++
)
{
hr
=
UiaGetPropertyValue
(
huia
node
,
cache_req
->
pProperties
[
i
],
&
v
);
hr
=
UiaGetPropertyValue
(
ret_
node
,
cache_req
->
pProperties
[
i
],
&
v
);
/* Don't fail on unimplemented properties. */
if
(
FAILED
(
hr
)
&&
hr
!=
E_NOTIMPL
)
{
SafeArrayDestroy
(
sa
);
return
hr
;
}
goto
exit
;
idx
[
1
]
=
1
+
i
;
hr
=
SafeArrayPutElement
(
sa
,
idx
,
&
v
);
VariantClear
(
&
v
);
if
(
FAILED
(
hr
))
{
SafeArrayDestroy
(
sa
);
return
hr
;
}
goto
exit
;
}
/*
* AddRef huianode since we're returning a reference to the same node we
* passed in, rather than creating a new one.
*/
IWineUiaNode_AddRef
(
&
node
->
IWineUiaNode_iface
);
*
out_req
=
sa
;
*
tree_struct
=
SysAllocString
(
L"P)"
);
return
S_OK
;
exit:
if
(
FAILED
(
hr
))
{
SafeArrayDestroy
(
sa
);
UiaNodeRelease
(
ret_node
);
}
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