Commit 9b1243fb authored by Connor McAdams's avatar Connor McAdams Committed by Alexandre Julliard

uiautomationcore: Implement UIA_BoundingRectanglePropertyId for default HWND provider.

parent cee22e0c
......@@ -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();
}
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment