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
9b1243fb
Commit
9b1243fb
authored
Mar 23, 2023
by
Connor McAdams
Committed by
Alexandre Julliard
Apr 17, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
uiautomationcore: Implement UIA_BoundingRectanglePropertyId for default HWND provider.
Signed-off-by:
Connor McAdams
<
cmcadams@codeweavers.com
>
parent
cee22e0c
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
219 additions
and
16 deletions
+219
-16
uiautomation.c
dlls/uiautomationcore/tests/uiautomation.c
+110
-16
uia_provider.c
dlls/uiautomationcore/uia_provider.c
+109
-0
No files found.
dlls/uiautomationcore/tests/uiautomation.c
View file @
9b1243fb
...
...
@@ -10211,6 +10211,19 @@ static HWND create_test_hwnd(const char *class_name)
0
,
0
,
100
,
100
,
NULL
,
NULL
,
NULL
,
NULL
);
}
static
HWND
create_child_test_hwnd
(
const
char
*
class_name
,
HWND
parent
)
{
WNDCLASSA
cls
=
{
0
};
cls
.
lpfnWndProc
=
child_test_wnd_proc
;
cls
.
hInstance
=
GetModuleHandleA
(
NULL
);
cls
.
lpszClassName
=
class_name
;
RegisterClassA
(
&
cls
);
return
CreateWindowA
(
class_name
,
"Test child window"
,
WS_CHILD
,
0
,
0
,
50
,
50
,
parent
,
NULL
,
NULL
,
NULL
);
}
static
IUIAutomationElement
*
create_test_element_from_hwnd
(
IUIAutomation
*
uia_iface
,
HWND
hwnd
,
BOOL
block_hwnd_provs
)
{
IUIAutomationElement
*
element
;
...
...
@@ -12397,18 +12410,67 @@ static const struct uia_hwnd_control_type_test hwnd_control_type_test[] = {
{
WS_CHILD
|
WS_CAPTION
,
WS_EX_TOOLWINDOW
,
UIA_WindowControlTypeId
,
PARENT_HWND_DESKTOP
},
};
static
void
create_base_hwnd_test_node
(
HWND
hwnd
,
BOOL
child_hwnd
,
struct
Provider
*
main
,
struct
Provider
*
nc
,
HUIANODE
*
ret_node
)
{
ULONG
main_ref
,
nc_ref
;
HRESULT
hr
;
initialize_provider
(
nc
,
ProviderOptions_ClientSideProvider
|
ProviderOptions_NonClientAreaProvider
,
hwnd
,
TRUE
);
initialize_provider
(
main
,
ProviderOptions_ClientSideProvider
,
hwnd
,
TRUE
);
nc
->
ignore_hwnd_prop
=
main
->
ignore_hwnd_prop
=
TRUE
;
main_ref
=
main
->
ref
;
nc_ref
=
nc
->
ref
;
if
(
!
child_hwnd
)
{
SET_EXPECT
(
winproc_GETOBJECT_UiaRoot
);
SET_EXPECT
(
winproc_GETOBJECT_CLIENT
);
prov_root
=
&
main
->
IRawElementProviderSimple_iface
;
}
else
{
SET_EXPECT
(
winproc_GETOBJECT_UiaRoot
);
SET_EXPECT
(
winproc_GETOBJECT_CLIENT
);
SET_EXPECT
(
child_winproc_GETOBJECT_UiaRoot
);
child_win_prov_root
=
&
main
->
IRawElementProviderSimple_iface
;
}
hr
=
UiaNodeFromProvider
(
&
nc
->
IRawElementProviderSimple_iface
,
ret_node
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
main
->
ref
==
(
main_ref
+
1
),
"Unexpected refcnt %ld
\n
"
,
main
->
ref
);
ok
(
nc
->
ref
==
(
nc_ref
+
1
),
"Unexpected refcnt %ld
\n
"
,
nc
->
ref
);
if
(
child_hwnd
)
{
/* Called while trying to get override provider. */
todo_wine
CHECK_CALLED
(
winproc_GETOBJECT_UiaRoot
);
CHECK_CALLED
(
child_winproc_GETOBJECT_UiaRoot
);
}
else
CHECK_CALLED
(
winproc_GETOBJECT_UiaRoot
);
called_winproc_GETOBJECT_CLIENT
=
expect_winproc_GETOBJECT_CLIENT
=
0
;
Provider
.
ret_invalid_prop_type
=
Provider_nc
.
ret_invalid_prop_type
=
TRUE
;
}
static
void
test_default_clientside_providers
(
void
)
{
struct
UiaRect
uia_rect
=
{
0
};
HWND
hwnd
,
hwnd_child
;
RECT
rect
=
{
0
};
IUnknown
*
unk_ns
;
HUIANODE
node
;
HRESULT
hr
;
HWND
hwnd
;
VARIANT
v
;
int
i
;
CoInitializeEx
(
NULL
,
COINIT_MULTITHREADED
);
hwnd
=
create_test_hwnd
(
"test_default_clientside_providers class"
);
hwnd_child
=
create_child_test_hwnd
(
"test_default_clientside_providers child class"
,
hwnd
);
method_sequences_enabled
=
FALSE
;
hr
=
UiaGetReservedNotSupportedValue
(
&
unk_ns
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
/*
* Test default BaseHwnd provider. Unlike the other default providers, the
* default BaseHwnd IRawElementProviderSimple is not available to test
...
...
@@ -12417,19 +12479,7 @@ static void test_default_clientside_providers(void)
* providers will return nothing so that we can isolate properties coming
* from the BaseHwnd provider.
*/
initialize_provider
(
&
Provider_nc
,
ProviderOptions_ClientSideProvider
|
ProviderOptions_NonClientAreaProvider
,
hwnd
,
TRUE
);
initialize_provider
(
&
Provider
,
ProviderOptions_ClientSideProvider
,
hwnd
,
TRUE
);
Provider_nc
.
ignore_hwnd_prop
=
Provider
.
ignore_hwnd_prop
=
TRUE
;
prov_root
=
&
Provider
.
IRawElementProviderSimple_iface
;
SET_EXPECT
(
winproc_GETOBJECT_UiaRoot
);
/* Only sent on Win7. */
SET_EXPECT
(
winproc_GETOBJECT_CLIENT
);
hr
=
UiaNodeFromProvider
(
&
Provider_nc
.
IRawElementProviderSimple_iface
,
&
node
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
Provider
.
ref
==
2
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
ok
(
Provider_nc
.
ref
==
2
,
"Unexpected refcnt %ld
\n
"
,
Provider_nc
.
ref
);
CHECK_CALLED
(
winproc_GETOBJECT_UiaRoot
);
called_winproc_GETOBJECT_CLIENT
=
expect_winproc_GETOBJECT_CLIENT
=
0
;
create_base_hwnd_test_node
(
hwnd
,
FALSE
,
&
Provider
,
&
Provider_nc
,
&
node
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_ProviderDescriptionPropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx
\n
"
,
hr
);
...
...
@@ -12443,17 +12493,58 @@ static void test_default_clientside_providers(void)
Provider
.
ret_invalid_prop_type
=
Provider_nc
.
ret_invalid_prop_type
=
TRUE
;
test_node_hwnd_provider
(
node
,
hwnd
);
ok_method_sequence
(
default_hwnd_prov_props_seq
,
"default_hwnd_prov_props_seq"
);
method_sequences_enabled
=
FALSE
;
/* Get the bounding rectangle from the default BaseHwnd provider. */
GetWindowRect
(
hwnd
,
&
rect
);
set_uia_rect
(
&
uia_rect
,
rect
.
left
,
rect
.
top
,
(
rect
.
right
-
rect
.
left
),
(
rect
.
bottom
-
rect
.
top
));
hr
=
UiaGetPropertyValue
(
node
,
UIA_BoundingRectanglePropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
check_uia_rect_val
(
&
v
,
&
uia_rect
);
VariantClear
(
&
v
);
/* Minimized top-level HWNDs don't return a bounding rectangle. */
ShowWindow
(
hwnd
,
SW_MINIMIZE
);
hr
=
UiaGetPropertyValue
(
node
,
UIA_BoundingRectanglePropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
ok
(
V_VT
(
&
v
)
==
VT_UNKNOWN
,
"Unexpected vt %d
\n
"
,
V_VT
(
&
v
));
ok
(
V_UNKNOWN
(
&
v
)
==
unk_ns
,
"unexpected IUnknown %p
\n
"
,
V_UNKNOWN
(
&
v
));
VariantClear
(
&
v
);
UiaNodeRelease
(
node
);
ok
(
Provider
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
ok
(
Provider_nc
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
Provider_nc
.
ref
);
/* Create a child window node. */
create_base_hwnd_test_node
(
hwnd_child
,
TRUE
,
&
Provider
,
&
Provider_nc
,
&
node
);
test_node_hwnd_provider
(
node
,
hwnd_child
);
/* Get the bounding rectangle from the default BaseHwnd provider. */
GetWindowRect
(
hwnd_child
,
&
rect
);
set_uia_rect
(
&
uia_rect
,
rect
.
left
,
rect
.
top
,
(
rect
.
right
-
rect
.
left
),
(
rect
.
bottom
-
rect
.
top
));
hr
=
UiaGetPropertyValue
(
node
,
UIA_BoundingRectanglePropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
check_uia_rect_val
(
&
v
,
&
uia_rect
);
VariantClear
(
&
v
);
/* Minimized non top-level HWNDs return a bounding rectangle. */
ShowWindow
(
hwnd_child
,
SW_MINIMIZE
);
GetWindowRect
(
hwnd_child
,
&
rect
);
set_uia_rect
(
&
uia_rect
,
rect
.
left
,
rect
.
top
,
(
rect
.
right
-
rect
.
left
),
(
rect
.
bottom
-
rect
.
top
));
hr
=
UiaGetPropertyValue
(
node
,
UIA_BoundingRectanglePropertyId
,
&
v
);
ok
(
hr
==
S_OK
,
"Unexpected hr %#lx.
\n
"
,
hr
);
check_uia_rect_val
(
&
v
,
&
uia_rect
);
VariantClear
(
&
v
);
UiaNodeRelease
(
node
);
ok
(
Provider
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
Provider
.
ref
);
ok
(
Provider_nc
.
ref
==
1
,
"Unexpected refcnt %ld
\n
"
,
Provider_nc
.
ref
);
method_sequences_enabled
=
FALSE
;
VariantInit
(
&
v
);
for
(
i
=
0
;
i
<
ARRAY_SIZE
(
hwnd_control_type_test
);
i
++
)
{
const
struct
uia_hwnd_control_type_test
*
test
=
&
hwnd_control_type_test
[
i
];
HWND
hwnd2
,
parent
;
HWND
parent
,
hwnd2
;
if
(
test
->
parent_hwnd_type
==
PARENT_HWND_HWND
)
parent
=
hwnd
;
...
...
@@ -12498,8 +12589,11 @@ static void test_default_clientside_providers(void)
method_sequences_enabled
=
TRUE
;
DestroyWindow
(
hwnd
);
DestroyWindow
(
hwnd_child
);
UnregisterClassA
(
"test_default_clientside_providers class"
,
NULL
);
UnregisterClassA
(
"test_default_clientside_providers child class"
,
NULL
);
IUnknown_Release
(
unk_ns
);
CoUninitialize
();
}
...
...
dlls/uiautomationcore/uia_provider.c
View file @
9b1243fb
...
...
@@ -1273,6 +1273,7 @@ static HRESULT get_uia_control_type_for_hwnd(HWND hwnd, int *control_type)
*/
struct
base_hwnd_provider
{
IRawElementProviderSimple
IRawElementProviderSimple_iface
;
IRawElementProviderFragment
IRawElementProviderFragment_iface
;
LONG
refcount
;
HWND
hwnd
;
...
...
@@ -1285,9 +1286,13 @@ static inline struct base_hwnd_provider *impl_from_base_hwnd_provider(IRawElemen
static
HRESULT
WINAPI
base_hwnd_provider_QueryInterface
(
IRawElementProviderSimple
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
struct
base_hwnd_provider
*
base_hwnd_prov
=
impl_from_base_hwnd_provider
(
iface
);
*
ppv
=
NULL
;
if
(
IsEqualIID
(
riid
,
&
IID_IRawElementProviderSimple
)
||
IsEqualIID
(
riid
,
&
IID_IUnknown
))
*
ppv
=
iface
;
else
if
(
IsEqualIID
(
riid
,
&
IID_IRawElementProviderFragment
))
*
ppv
=
&
base_hwnd_prov
->
IRawElementProviderFragment_iface
;
else
return
E_NOINTERFACE
;
...
...
@@ -1446,6 +1451,109 @@ static const IRawElementProviderSimpleVtbl base_hwnd_provider_vtbl = {
base_hwnd_provider_get_HostRawElementProvider
,
};
/*
* IRawElementProviderFragment interface for default ProviderType_BaseHwnd
* providers.
*/
static
inline
struct
base_hwnd_provider
*
impl_from_base_hwnd_fragment
(
IRawElementProviderFragment
*
iface
)
{
return
CONTAINING_RECORD
(
iface
,
struct
base_hwnd_provider
,
IRawElementProviderFragment_iface
);
}
static
HRESULT
WINAPI
base_hwnd_fragment_QueryInterface
(
IRawElementProviderFragment
*
iface
,
REFIID
riid
,
void
**
ppv
)
{
struct
base_hwnd_provider
*
base_hwnd_prov
=
impl_from_base_hwnd_fragment
(
iface
);
return
IRawElementProviderSimple_QueryInterface
(
&
base_hwnd_prov
->
IRawElementProviderSimple_iface
,
riid
,
ppv
);
}
static
ULONG
WINAPI
base_hwnd_fragment_AddRef
(
IRawElementProviderFragment
*
iface
)
{
struct
base_hwnd_provider
*
base_hwnd_prov
=
impl_from_base_hwnd_fragment
(
iface
);
return
IRawElementProviderSimple_AddRef
(
&
base_hwnd_prov
->
IRawElementProviderSimple_iface
);
}
static
ULONG
WINAPI
base_hwnd_fragment_Release
(
IRawElementProviderFragment
*
iface
)
{
struct
base_hwnd_provider
*
base_hwnd_prov
=
impl_from_base_hwnd_fragment
(
iface
);
return
IRawElementProviderSimple_Release
(
&
base_hwnd_prov
->
IRawElementProviderSimple_iface
);
}
static
HRESULT
WINAPI
base_hwnd_fragment_Navigate
(
IRawElementProviderFragment
*
iface
,
enum
NavigateDirection
direction
,
IRawElementProviderFragment
**
ret_val
)
{
FIXME
(
"%p, %d, %p: stub
\n
"
,
iface
,
direction
,
ret_val
);
*
ret_val
=
NULL
;
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
base_hwnd_fragment_GetRuntimeId
(
IRawElementProviderFragment
*
iface
,
SAFEARRAY
**
ret_val
)
{
FIXME
(
"%p, %p: stub!
\n
"
,
iface
,
ret_val
);
*
ret_val
=
NULL
;
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
base_hwnd_fragment_get_BoundingRectangle
(
IRawElementProviderFragment
*
iface
,
struct
UiaRect
*
ret_val
)
{
struct
base_hwnd_provider
*
base_hwnd_prov
=
impl_from_base_hwnd_fragment
(
iface
);
RECT
rect
=
{
0
};
TRACE
(
"%p, %p
\n
"
,
iface
,
ret_val
);
memset
(
ret_val
,
0
,
sizeof
(
*
ret_val
));
/* Top level minimized window - Return empty rect. */
if
(
is_top_level_hwnd
(
base_hwnd_prov
->
hwnd
)
&&
IsIconic
(
base_hwnd_prov
->
hwnd
))
return
S_OK
;
if
(
!
GetWindowRect
(
base_hwnd_prov
->
hwnd
,
&
rect
))
return
uia_get_hr_for_last_error
();
ret_val
->
left
=
rect
.
left
;
ret_val
->
top
=
rect
.
top
;
ret_val
->
width
=
(
rect
.
right
-
rect
.
left
);
ret_val
->
height
=
(
rect
.
bottom
-
rect
.
top
);
return
S_OK
;
}
static
HRESULT
WINAPI
base_hwnd_fragment_GetEmbeddedFragmentRoots
(
IRawElementProviderFragment
*
iface
,
SAFEARRAY
**
ret_val
)
{
FIXME
(
"%p, %p: stub!
\n
"
,
iface
,
ret_val
);
*
ret_val
=
NULL
;
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
base_hwnd_fragment_SetFocus
(
IRawElementProviderFragment
*
iface
)
{
FIXME
(
"%p: stub!
\n
"
,
iface
);
return
E_NOTIMPL
;
}
static
HRESULT
WINAPI
base_hwnd_fragment_get_FragmentRoot
(
IRawElementProviderFragment
*
iface
,
IRawElementProviderFragmentRoot
**
ret_val
)
{
FIXME
(
"%p, %p: stub!
\n
"
,
iface
,
ret_val
);
*
ret_val
=
NULL
;
return
E_NOTIMPL
;
}
static
const
IRawElementProviderFragmentVtbl
base_hwnd_fragment_vtbl
=
{
base_hwnd_fragment_QueryInterface
,
base_hwnd_fragment_AddRef
,
base_hwnd_fragment_Release
,
base_hwnd_fragment_Navigate
,
base_hwnd_fragment_GetRuntimeId
,
base_hwnd_fragment_get_BoundingRectangle
,
base_hwnd_fragment_GetEmbeddedFragmentRoots
,
base_hwnd_fragment_SetFocus
,
base_hwnd_fragment_get_FragmentRoot
,
};
HRESULT
create_base_hwnd_provider
(
HWND
hwnd
,
IRawElementProviderSimple
**
elprov
)
{
struct
base_hwnd_provider
*
base_hwnd_prov
;
...
...
@@ -1462,6 +1570,7 @@ HRESULT create_base_hwnd_provider(HWND hwnd, IRawElementProviderSimple **elprov)
return
E_OUTOFMEMORY
;
base_hwnd_prov
->
IRawElementProviderSimple_iface
.
lpVtbl
=
&
base_hwnd_provider_vtbl
;
base_hwnd_prov
->
IRawElementProviderFragment_iface
.
lpVtbl
=
&
base_hwnd_fragment_vtbl
;
base_hwnd_prov
->
refcount
=
1
;
base_hwnd_prov
->
hwnd
=
hwnd
;
*
elprov
=
&
base_hwnd_prov
->
IRawElementProviderSimple_iface
;
...
...
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