Commit 2b8c8be7 authored by Connor McAdams's avatar Connor McAdams Committed by Alexandre Julliard

uiautomationcore: Add support for UIA_ValueIsReadOnlyPropertyId.

parent 44aa2ea8
......@@ -1103,12 +1103,19 @@ struct Provider_prop_override
VARIANT val;
};
struct Provider_value_pattern_data
{
BOOL is_supported;
BOOL is_read_only;
};
static struct Provider
{
IRawElementProviderSimple IRawElementProviderSimple_iface;
IRawElementProviderFragment IRawElementProviderFragment_iface;
IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot_iface;
IRawElementProviderHwndOverride IRawElementProviderHwndOverride_iface;
IValueProvider IValueProvider_iface;
LONG ref;
const char *prov_name;
......@@ -1129,6 +1136,7 @@ static struct Provider
struct Provider_prop_override *prop_override;
int prop_override_count;
struct UiaRect bounds_rect;
struct Provider_value_pattern_data value_pattern_data;
} Provider, Provider2, Provider_child, Provider_child2;
static struct Provider Provider_hwnd, Provider_nc, Provider_proxy, Provider_proxy2, Provider_override;
static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd, BOOL initialize_nav_links);
......@@ -1184,6 +1192,7 @@ static SAFEARRAY *create_unk_safearray(void)
enum {
PROV_GET_PROVIDER_OPTIONS,
PROV_GET_PATTERN_PROV,
PROV_GET_PROPERTY_VALUE,
PROV_GET_HOST_RAW_ELEMENT_PROVIDER,
FRAG_NAVIGATE,
......@@ -1195,6 +1204,7 @@ enum {
static const char *prov_method_str[] = {
"get_ProviderOptions",
"GetPatternProvider",
"GetPropertyValue",
"get_HostRawElementProvider",
"Navigate",
......@@ -1544,6 +1554,8 @@ HRESULT WINAPI ProviderSimple_QueryInterface(IRawElementProviderSimple *iface, R
*ppv = &This->IRawElementProviderFragmentRoot_iface;
else if (IsEqualIID(riid, &IID_IRawElementProviderHwndOverride))
*ppv = &This->IRawElementProviderHwndOverride_iface;
else if (IsEqualIID(riid, &IID_IValueProvider))
*ppv = &This->IValueProvider_iface;
else
return E_NOINTERFACE;
......@@ -1586,8 +1598,29 @@ HRESULT WINAPI ProviderSimple_get_ProviderOptions(IRawElementProviderSimple *ifa
HRESULT WINAPI ProviderSimple_GetPatternProvider(IRawElementProviderSimple *iface,
PATTERNID pattern_id, IUnknown **ret_val)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
struct Provider *This = impl_from_ProviderSimple(iface);
add_method_call(This, PROV_GET_PATTERN_PROV);
if (This->expected_tid)
ok(This->expected_tid == GetCurrentThreadId(), "Unexpected tid %ld\n", GetCurrentThreadId());
This->last_call_tid = GetCurrentThreadId();
*ret_val = NULL;
switch (pattern_id)
{
case UIA_ValuePatternId:
if (This->value_pattern_data.is_supported)
*ret_val = (IUnknown *)iface;
break;
default:
break;
}
if (*ret_val)
IUnknown_AddRef(*ret_val);
return S_OK;
}
HRESULT WINAPI ProviderSimple_GetPropertyValue(IRawElementProviderSimple *iface,
......@@ -2071,12 +2104,67 @@ static const IRawElementProviderHwndOverrideVtbl ProviderHwndOverrideVtbl = {
ProviderHwndOverride_GetOverrideProviderForHwnd,
};
static inline struct Provider *impl_from_ProviderValuePattern(IValueProvider *iface)
{
return CONTAINING_RECORD(iface, struct Provider, IValueProvider_iface);
}
static HRESULT WINAPI ProviderValuePattern_QueryInterface(IValueProvider *iface, REFIID riid,
void **ppv)
{
struct Provider *Provider = impl_from_ProviderValuePattern(iface);
return IRawElementProviderSimple_QueryInterface(&Provider->IRawElementProviderSimple_iface, riid, ppv);
}
static ULONG WINAPI ProviderValuePattern_AddRef(IValueProvider *iface)
{
struct Provider *Provider = impl_from_ProviderValuePattern(iface);
return IRawElementProviderSimple_AddRef(&Provider->IRawElementProviderSimple_iface);
}
static ULONG WINAPI ProviderValuePattern_Release(IValueProvider *iface)
{
struct Provider *Provider = impl_from_ProviderValuePattern(iface);
return IRawElementProviderSimple_Release(&Provider->IRawElementProviderSimple_iface);
}
static HRESULT WINAPI ProviderValuePattern_SetValue(IValueProvider *iface, LPCWSTR val)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI ProviderValuePattern_get_Value(IValueProvider *iface, BSTR *ret_val)
{
ok(0, "unexpected call\n");
return E_NOTIMPL;
}
static HRESULT WINAPI ProviderValuePattern_get_IsReadOnly(IValueProvider *iface, BOOL *ret_val)
{
struct Provider *Provider = impl_from_ProviderValuePattern(iface);
*ret_val = Provider->value_pattern_data.is_read_only;
return S_OK;
}
static const IValueProviderVtbl ProviderValuePatternVtbl = {
ProviderValuePattern_QueryInterface,
ProviderValuePattern_AddRef,
ProviderValuePattern_Release,
ProviderValuePattern_SetValue,
ProviderValuePattern_get_Value,
ProviderValuePattern_get_IsReadOnly,
};
static struct Provider Provider =
{
{ &ProviderSimpleVtbl },
{ &ProviderFragmentVtbl },
{ &ProviderFragmentRootVtbl },
{ &ProviderHwndOverrideVtbl },
{ &ProviderValuePatternVtbl },
1,
"Provider",
NULL, NULL,
......@@ -2091,6 +2179,7 @@ static struct Provider Provider2 =
{ &ProviderFragmentVtbl },
{ &ProviderFragmentRootVtbl },
{ &ProviderHwndOverrideVtbl },
{ &ProviderValuePatternVtbl },
1,
"Provider2",
NULL, NULL,
......@@ -2105,6 +2194,7 @@ static struct Provider Provider_child =
{ &ProviderFragmentVtbl },
{ &ProviderFragmentRootVtbl },
{ &ProviderHwndOverrideVtbl },
{ &ProviderValuePatternVtbl },
1,
"Provider_child",
&Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface,
......@@ -2119,6 +2209,7 @@ static struct Provider Provider_child2 =
{ &ProviderFragmentVtbl },
{ &ProviderFragmentRootVtbl },
{ &ProviderHwndOverrideVtbl },
{ &ProviderValuePatternVtbl },
1,
"Provider_child2",
&Provider.IRawElementProviderFragment_iface, &Provider.IRawElementProviderFragmentRoot_iface,
......@@ -2133,6 +2224,7 @@ static struct Provider Provider_hwnd =
{ &ProviderFragmentVtbl },
{ &ProviderFragmentRootVtbl },
{ &ProviderHwndOverrideVtbl },
{ &ProviderValuePatternVtbl },
1,
"Provider_hwnd",
NULL, NULL,
......@@ -2147,6 +2239,7 @@ static struct Provider Provider_nc =
{ &ProviderFragmentVtbl },
{ &ProviderFragmentRootVtbl },
{ &ProviderHwndOverrideVtbl },
{ &ProviderValuePatternVtbl },
1,
"Provider_nc",
NULL, NULL,
......@@ -2162,6 +2255,7 @@ static struct Provider Provider_proxy =
{ &ProviderFragmentVtbl },
{ &ProviderFragmentRootVtbl },
{ &ProviderHwndOverrideVtbl },
{ &ProviderValuePatternVtbl },
1,
"Provider_proxy",
NULL, NULL,
......@@ -2177,6 +2271,7 @@ static struct Provider Provider_proxy2 =
{ &ProviderFragmentVtbl },
{ &ProviderFragmentRootVtbl },
{ &ProviderHwndOverrideVtbl },
{ &ProviderValuePatternVtbl },
1,
"Provider_proxy2",
NULL, NULL,
......@@ -2192,6 +2287,7 @@ static struct Provider Provider_override =
{ &ProviderFragmentVtbl },
{ &ProviderFragmentRootVtbl },
{ &ProviderHwndOverrideVtbl },
{ &ProviderValuePatternVtbl },
1,
"Provider_override",
NULL, NULL,
......@@ -2208,6 +2304,7 @@ static struct Provider Provider_override =
{ &ProviderFragmentVtbl }, \
{ &ProviderFragmentRootVtbl }, \
{ &ProviderHwndOverrideVtbl }, \
{ &ProviderValuePatternVtbl }, \
1, \
"Provider_" # name "", \
NULL, NULL, \
......@@ -4699,6 +4796,11 @@ static const struct prov_method_sequence get_elem_arr_prop_seq[] = {
{ 0 }
};
static const struct prov_method_sequence get_pattern_prop_seq[] = {
{ &Provider, PROV_GET_PATTERN_PROV },
{ 0 }
};
static const struct prov_method_sequence get_bounding_rect_seq[] = {
NODE_CREATE_SEQ(&Provider_child),
{ &Provider_child, FRAG_GET_BOUNDING_RECT },
......@@ -5031,6 +5133,28 @@ static void test_UiaGetPropertyValue(void)
winetest_pop_context();
}
/* IValueProvider pattern property IDs. */
Provider.value_pattern_data.is_supported = FALSE;
hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &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));
ok_method_sequence(get_pattern_prop_seq, NULL);
VariantClear(&v);
Provider.value_pattern_data.is_supported = TRUE;
for (i = 0; i < 2; i++)
{
Provider.value_pattern_data.is_read_only = i;
hr = UiaGetPropertyValue(node, UIA_ValueIsReadOnlyPropertyId, &v);
ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
ok(V_VT(&v) == VT_BOOL, "Unexpected VT %d\n", V_VT(&v));
ok(check_variant_bool(&v, i), "Unexpected BOOL %#x\n", V_BOOL(&v));
ok_method_sequence(get_pattern_prop_seq, NULL);
VariantClear(&v);
}
ok(UiaNodeRelease(node), "UiaNodeRelease returned FALSE\n");
ok(Provider.ref == 1, "Unexpected refcnt %ld\n", Provider.ref);
initialize_provider(&Provider, ProviderOptions_ServerSideProvider, NULL, FALSE);
......@@ -8462,6 +8586,7 @@ static void initialize_provider(struct Provider *prov, int prov_opts, HWND hwnd,
prov->prop_override = NULL;
prov->prop_override_count = 0;
memset(&prov->bounds_rect, 0, sizeof(prov->bounds_rect));
memset(&prov->value_pattern_data, 0, sizeof(prov->value_pattern_data));
if (initialize_nav_links)
{
prov->frag_root = NULL;
......
......@@ -25,6 +25,7 @@ struct uia_prop_info {
int prop_id;
int prop_type;
int type;
int pattern_id;
};
struct uia_event_info {
......
......@@ -1437,6 +1437,46 @@ static HRESULT uia_provider_get_special_prop_val(struct uia_provider *prov,
return S_OK;
}
static HRESULT uia_provider_get_pattern_prop_val(struct uia_provider *prov,
const struct uia_prop_info *prop_info, VARIANT *ret_val)
{
const struct uia_pattern_info *pattern_info = uia_pattern_info_from_id(prop_info->pattern_id);
IUnknown *unk, *pattern_prov;
HRESULT hr;
unk = pattern_prov = NULL;
hr = IRawElementProviderSimple_GetPatternProvider(prov->elprov, prop_info->pattern_id, &unk);
if (FAILED(hr) || !unk)
return S_OK;
hr = IUnknown_QueryInterface(unk, pattern_info->pattern_iid, (void **)&pattern_prov);
IUnknown_Release(unk);
if (FAILED(hr) || !pattern_prov)
{
WARN("Failed to get pattern interface from object\n");
return S_OK;
}
switch (prop_info->prop_id)
{
case UIA_ValueIsReadOnlyPropertyId:
{
BOOL val;
hr = IValueProvider_get_IsReadOnly((IValueProvider *)pattern_prov, &val);
if (SUCCEEDED(hr))
variant_init_bool(ret_val, val);
break;
}
default:
break;
}
IUnknown_Release(pattern_prov);
return S_OK;
}
static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface,
const struct uia_prop_info *prop_info, VARIANT *ret_val)
{
......@@ -1453,6 +1493,9 @@ static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface,
case PROP_TYPE_SPECIAL:
return uia_provider_get_special_prop_val(prov, prop_info, ret_val);
case PROP_TYPE_PATTERN_PROP:
return uia_provider_get_pattern_prop_val(prov, prop_info, ret_val);
default:
break;
}
......
......@@ -97,7 +97,9 @@ static const struct uia_prop_info default_uia_properties[] = {
{ &IsDropTargetPatternAvailable_Property_GUID, UIA_IsDropTargetPatternAvailablePropertyId, },
{ &Dock_DockPosition_Property_GUID, UIA_DockDockPositionPropertyId, },
{ &Styles_StyleId_Property_GUID, UIA_StylesStyleIdPropertyId, },
{ &Value_IsReadOnly_Property_GUID, UIA_ValueIsReadOnlyPropertyId, },
{ &Value_IsReadOnly_Property_GUID, UIA_ValueIsReadOnlyPropertyId,
PROP_TYPE_PATTERN_PROP, UIAutomationType_Bool,
UIA_ValuePatternId, },
{ &IsSpreadsheetPatternAvailable_Property_GUID, UIA_IsSpreadsheetPatternAvailablePropertyId, },
{ &Styles_StyleName_Property_GUID, UIA_StylesStyleNamePropertyId, },
{ &IsAnnotationPatternAvailable_Property_GUID, UIA_IsAnnotationPatternAvailablePropertyId, },
......@@ -482,6 +484,17 @@ static const struct uia_pattern_info default_uia_patterns[] = {
&IID_ISpreadsheetItemProvider, },
};
static const int pattern_id_idx[] = {
0x1f, 0x1d, 0x10, 0x0c, 0x15, 0x13, 0x19, 0x0b,
0x1c, 0x04, 0x1e, 0x06, 0x0f, 0x17, 0x09, 0x0a,
0x1b, 0x00, 0x11, 0x02, 0x05, 0x14, 0x20, 0x1a,
0x12, 0x07, 0x18, 0x21, 0x01, 0x16, 0x03, 0x08,
0x0d, 0x0e,
};
#define PATTERN_ID_MIN 10000
#define PATTERN_ID_MAX (PATTERN_ID_MIN + ARRAY_SIZE(default_uia_patterns))
static const struct uia_pattern_info *uia_pattern_info_from_guid(const GUID *guid)
{
struct uia_pattern_info *pattern;
......@@ -493,6 +506,14 @@ static const struct uia_pattern_info *uia_pattern_info_from_guid(const GUID *gui
return NULL;
}
const struct uia_pattern_info *uia_pattern_info_from_id(PATTERNID pattern_id)
{
if ((pattern_id < PATTERN_ID_MIN) || (pattern_id > PATTERN_ID_MAX))
return NULL;
return &default_uia_patterns[pattern_id_idx[pattern_id - PATTERN_ID_MIN]];
}
/***********************************************************************
* UiaLookupId (uiautomationcore.@)
*/
......
......@@ -28,6 +28,7 @@ enum uia_prop_type {
PROP_TYPE_UNKNOWN,
PROP_TYPE_ELEM_PROP,
PROP_TYPE_SPECIAL,
PROP_TYPE_PATTERN_PROP,
};
/*
......@@ -91,6 +92,12 @@ static inline struct uia_provider *impl_from_IWineUiaProvider(IWineUiaProvider *
return CONTAINING_RECORD(iface, struct uia_provider, IWineUiaProvider_iface);
}
static inline void variant_init_bool(VARIANT *v, BOOL val)
{
V_VT(v) = VT_BOOL;
V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE;
}
/* uia_client.c */
int uia_compare_safearrays(SAFEARRAY *sa1, SAFEARRAY *sa2, int prop_type) DECLSPEC_HIDDEN;
int get_node_provider_type_at_idx(struct uia_node *node, int idx) DECLSPEC_HIDDEN;
......@@ -99,6 +106,7 @@ HRESULT create_uia_node_from_elprov(IRawElementProviderSimple *elprov, HUIANODE
/* uia_ids.c */
const struct uia_prop_info *uia_prop_info_from_id(PROPERTYID prop_id) DECLSPEC_HIDDEN;
const struct uia_pattern_info *uia_pattern_info_from_id(PATTERNID pattern_id) DECLSPEC_HIDDEN;
/* uia_provider.c */
void uia_stop_provider_thread(void) DECLSPEC_HIDDEN;
......
......@@ -35,12 +35,6 @@ static void variant_init_i4(VARIANT *v, int val)
V_I4(v) = val;
}
static void variant_init_bool(VARIANT *v, BOOL val)
{
V_VT(v) = VT_BOOL;
V_BOOL(v) = val ? VARIANT_TRUE : VARIANT_FALSE;
}
static BOOL msaa_check_acc_state(IAccessible *acc, VARIANT cid, ULONG flag)
{
HRESULT hr;
......
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