mirror of
git://source.winehq.org/git/wine.git
synced 2024-11-04 15:44:52 +00:00
uiautomationcore: Add support for UIAutomationType_Element properties.
Signed-off-by: Connor McAdams <cmcadams@codeweavers.com>
This commit is contained in:
parent
afb155145a
commit
0cea011921
3 changed files with 203 additions and 14 deletions
|
@ -4153,15 +4153,11 @@ static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, V
|
|||
VARIANT v1;
|
||||
|
||||
#ifdef _WIN64
|
||||
todo_wine ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v));
|
||||
ok(V_VT(v) == VT_I8, "Unexpected VT %d\n", V_VT(v));
|
||||
tmp_node = (HUIANODE)V_I8(v);
|
||||
if (V_VT(v) != VT_I8)
|
||||
break;
|
||||
#else
|
||||
todo_wine ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
|
||||
ok(V_VT(v) == VT_I4, "Unexpected VT %d\n", V_VT(v));
|
||||
tmp_node = (HUIANODE)V_I4(v);
|
||||
if (V_VT(v) != VT_I4)
|
||||
break;
|
||||
#endif
|
||||
ok(Provider_child.ref == 2, "Unexpected refcnt %ld\n", Provider_child.ref);
|
||||
|
||||
|
@ -4177,7 +4173,7 @@ static void check_uia_prop_val(PROPERTYID prop_id, enum UIAutomationType type, V
|
|||
}
|
||||
|
||||
case UIAutomationType_ElementArray:
|
||||
todo_wine ok(V_VT(v) == (VT_ARRAY | VT_UNKNOWN), "Unexpected VT %d\n", V_VT(v));
|
||||
ok(V_VT(v) == (VT_ARRAY | VT_UNKNOWN), "Unexpected VT %d\n", V_VT(v));
|
||||
if (V_VT(v) != (VT_ARRAY | VT_UNKNOWN))
|
||||
break;
|
||||
|
||||
|
|
|
@ -23,6 +23,131 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(uiautomation);
|
||||
|
||||
static void clear_uia_node_ptr_safearray(SAFEARRAY *sa, LONG elems)
|
||||
{
|
||||
HUIANODE node;
|
||||
HRESULT hr;
|
||||
LONG i;
|
||||
|
||||
for (i = 0; i < elems; i++)
|
||||
{
|
||||
hr = SafeArrayGetElement(sa, &i, &node);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
UiaNodeRelease(node);
|
||||
}
|
||||
}
|
||||
|
||||
static void create_uia_node_safearray(VARIANT *in, VARIANT *out)
|
||||
{
|
||||
LONG i, idx, lbound, ubound, elems;
|
||||
HUIANODE node;
|
||||
SAFEARRAY *sa;
|
||||
HRESULT hr;
|
||||
UINT dims;
|
||||
|
||||
dims = SafeArrayGetDim(V_ARRAY(in));
|
||||
if (!dims || (dims > 1))
|
||||
{
|
||||
WARN("Invalid dimensions %d for element safearray.\n", dims);
|
||||
return;
|
||||
}
|
||||
|
||||
hr = SafeArrayGetLBound(V_ARRAY(in), 1, &lbound);
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
hr = SafeArrayGetUBound(V_ARRAY(in), 1, &ubound);
|
||||
if (FAILED(hr))
|
||||
return;
|
||||
|
||||
elems = (ubound - lbound) + 1;
|
||||
if (!(sa = SafeArrayCreateVector(VT_UINT_PTR, 0, elems)))
|
||||
return;
|
||||
|
||||
for (i = 0; i < elems; i++)
|
||||
{
|
||||
IRawElementProviderSimple *elprov;
|
||||
IUnknown *unk;
|
||||
|
||||
idx = lbound + i;
|
||||
hr = SafeArrayGetElement(V_ARRAY(in), &idx, &unk);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
hr = IUnknown_QueryInterface(unk, &IID_IRawElementProviderSimple, (void **)&elprov);
|
||||
IUnknown_Release(unk);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
hr = UiaNodeFromProvider(elprov, &node);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
hr = SafeArrayPutElement(sa, &i, &node);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
}
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
clear_uia_node_ptr_safearray(sa, elems);
|
||||
SafeArrayDestroy(sa);
|
||||
return;
|
||||
}
|
||||
|
||||
V_VT(out) = VT_UINT_PTR | VT_ARRAY;
|
||||
V_ARRAY(out) = sa;
|
||||
}
|
||||
|
||||
/* Convert a VT_UINT_PTR SAFEARRAY to VT_UNKNOWN. */
|
||||
static void uia_node_ptr_to_unk_safearray(VARIANT *in)
|
||||
{
|
||||
SAFEARRAY *sa = NULL;
|
||||
LONG ubound, i;
|
||||
HUIANODE node;
|
||||
HRESULT hr;
|
||||
|
||||
hr = SafeArrayGetUBound(V_ARRAY(in), 1, &ubound);
|
||||
if (FAILED(hr))
|
||||
goto exit;
|
||||
|
||||
if (!(sa = SafeArrayCreateVector(VT_UNKNOWN, 0, ubound + 1)))
|
||||
{
|
||||
hr = E_FAIL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
for (i = 0; i < (ubound + 1); i++)
|
||||
{
|
||||
hr = SafeArrayGetElement(V_ARRAY(in), &i, &node);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
hr = SafeArrayPutElement(sa, &i, node);
|
||||
if (FAILED(hr))
|
||||
break;
|
||||
|
||||
UiaNodeRelease(node);
|
||||
}
|
||||
|
||||
exit:
|
||||
if (FAILED(hr))
|
||||
{
|
||||
clear_uia_node_ptr_safearray(V_ARRAY(in), ubound + 1);
|
||||
if (sa)
|
||||
SafeArrayDestroy(sa);
|
||||
}
|
||||
|
||||
VariantClear(in);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
V_VT(in) = VT_UNKNOWN | VT_ARRAY;
|
||||
V_ARRAY(in) = sa;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* IWineUiaNode interface.
|
||||
*/
|
||||
|
@ -150,6 +275,17 @@ static ULONG WINAPI uia_provider_Release(IWineUiaProvider *iface)
|
|||
return ref;
|
||||
}
|
||||
|
||||
static void get_variant_for_node(HUIANODE node, VARIANT *v)
|
||||
{
|
||||
#ifdef _WIN64
|
||||
V_VT(v) = VT_I8;
|
||||
V_I8(v) = (UINT64)node;
|
||||
#else
|
||||
V_VT(v) = VT_I4;
|
||||
V_I4(v) = (UINT32)node;
|
||||
#endif
|
||||
}
|
||||
|
||||
static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface,
|
||||
const struct uia_prop_info *prop_info, VARIANT *ret_val)
|
||||
{
|
||||
|
@ -184,6 +320,43 @@ static HRESULT WINAPI uia_provider_get_prop_val(IWineUiaProvider *iface,
|
|||
*ret_val = v;
|
||||
break;
|
||||
|
||||
case UIAutomationType_Element:
|
||||
{
|
||||
IRawElementProviderSimple *elprov;
|
||||
HUIANODE node;
|
||||
|
||||
if (V_VT(&v) != VT_UNKNOWN)
|
||||
{
|
||||
WARN("Invalid vt %d for UIAutomationType_Element\n", V_VT(&v));
|
||||
goto exit;
|
||||
}
|
||||
|
||||
hr = IUnknown_QueryInterface(V_UNKNOWN(&v), &IID_IRawElementProviderSimple,
|
||||
(void **)&elprov);
|
||||
if (FAILED(hr))
|
||||
goto exit;
|
||||
|
||||
hr = UiaNodeFromProvider(elprov, &node);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
get_variant_for_node(node, ret_val);
|
||||
VariantClear(&v);
|
||||
IRawElementProviderSimple_Release(elprov);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case UIAutomationType_ElementArray:
|
||||
if (V_VT(&v) != (VT_UNKNOWN | VT_ARRAY))
|
||||
{
|
||||
WARN("Invalid vt %d for UIAutomationType_ElementArray\n", V_VT(&v));
|
||||
goto exit;
|
||||
}
|
||||
create_uia_node_safearray(&v, ret_val);
|
||||
if (V_VT(ret_val) == (VT_UINT_PTR | VT_ARRAY))
|
||||
VariantClear(&v);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -315,7 +488,21 @@ HRESULT WINAPI UiaGetPropertyValue(HUIANODE huianode, PROPERTYID prop_id, VARIAN
|
|||
VariantInit(&v);
|
||||
hr = IWineUiaProvider_get_prop_val(prov, prop_info, &v);
|
||||
if (SUCCEEDED(hr) && V_VT(&v) != VT_EMPTY)
|
||||
*out_val = v;
|
||||
{
|
||||
/*
|
||||
* ElementArray types come back as an array of pointers to prevent the
|
||||
* HUIANODEs from getting marshaled. We need to convert them to
|
||||
* VT_UNKNOWN here.
|
||||
*/
|
||||
if (prop_info->type == UIAutomationType_ElementArray)
|
||||
{
|
||||
uia_node_ptr_to_unk_safearray(&v);
|
||||
if (V_VT(&v) != VT_EMPTY)
|
||||
*out_val = v;
|
||||
}
|
||||
else
|
||||
*out_val = v;
|
||||
}
|
||||
|
||||
IWineUiaProvider_Release(prov);
|
||||
|
||||
|
|
|
@ -51,7 +51,8 @@ static const struct uia_prop_info default_uia_properties[] = {
|
|||
{ &Size_Property_GUID, UIA_SizePropertyId, },
|
||||
{ &IsTextPattern2Available_Property_GUID, UIA_IsTextPattern2AvailablePropertyId, },
|
||||
{ &Styles_FillPatternStyle_Property_GUID, UIA_StylesFillPatternStylePropertyId, },
|
||||
{ &FlowsTo_Property_GUID, UIA_FlowsToPropertyId, },
|
||||
{ &FlowsTo_Property_GUID, UIA_FlowsToPropertyId,
|
||||
UIAutomationType_ElementArray, },
|
||||
{ &ItemStatus_Property_GUID, UIA_ItemStatusPropertyId, },
|
||||
{ &Scroll_VerticalViewSize_Property_GUID, UIA_ScrollVerticalViewSizePropertyId, },
|
||||
{ &Selection_IsSelectionRequired_Property_GUID, UIA_SelectionIsSelectionRequiredPropertyId, },
|
||||
|
@ -94,12 +95,14 @@ static const struct uia_prop_info default_uia_properties[] = {
|
|||
{ &IsRangeValuePatternAvailable_Property_GUID, UIA_IsRangeValuePatternAvailablePropertyId, },
|
||||
{ &IsScrollPatternAvailable_Property_GUID, UIA_IsScrollPatternAvailablePropertyId, },
|
||||
{ &IsTransformPattern2Available_Property_GUID, UIA_IsTransformPattern2AvailablePropertyId, },
|
||||
{ &LabeledBy_Property_GUID, UIA_LabeledByPropertyId, },
|
||||
{ &LabeledBy_Property_GUID, UIA_LabeledByPropertyId,
|
||||
UIAutomationType_Element, },
|
||||
{ &ItemType_Property_GUID, UIA_ItemTypePropertyId, },
|
||||
{ &Transform_CanMove_Property_GUID, UIA_TransformCanMovePropertyId, },
|
||||
{ &LocalizedControlType_Property_GUID, UIA_LocalizedControlTypePropertyId, },
|
||||
{ &Annotation_AnnotationTypeId_Property_GUID, UIA_AnnotationAnnotationTypeIdPropertyId, },
|
||||
{ &FlowsFrom_Property_GUID, UIA_FlowsFromPropertyId, },
|
||||
{ &FlowsFrom_Property_GUID, UIA_FlowsFromPropertyId,
|
||||
UIAutomationType_ElementArray, },
|
||||
{ &OptimizeForVisualContent_Property_GUID, UIA_OptimizeForVisualContentPropertyId, },
|
||||
{ &IsVirtualizedItemPatternAvailable_Property_GUID, UIA_IsVirtualizedItemPatternAvailablePropertyId, },
|
||||
{ &GridItem_Parent_Property_GUID, UIA_GridItemContainingGridPropertyId, },
|
||||
|
@ -148,7 +151,8 @@ static const struct uia_prop_info default_uia_properties[] = {
|
|||
{ &IsControlElement_Property_GUID, UIA_IsControlElementPropertyId, },
|
||||
{ &HelpText_Property_GUID, UIA_HelpTextPropertyId, },
|
||||
{ &Table_RowHeaders_Property_GUID, UIA_TableRowHeadersPropertyId, },
|
||||
{ &ControllerFor_Property_GUID, UIA_ControllerForPropertyId, },
|
||||
{ &ControllerFor_Property_GUID, UIA_ControllerForPropertyId,
|
||||
UIAutomationType_ElementArray, },
|
||||
{ &ProviderDescription_Property_GUID, UIA_ProviderDescriptionPropertyId, },
|
||||
{ &AriaProperties_Property_GUID, UIA_AriaPropertiesPropertyId, },
|
||||
{ &LiveSetting_Property_GUID, UIA_LiveSettingPropertyId,
|
||||
|
@ -185,7 +189,8 @@ static const struct uia_prop_info default_uia_properties[] = {
|
|||
{ &BoundingRectangle_Property_GUID, UIA_BoundingRectanglePropertyId, },
|
||||
{ &LegacyIAccessible_Value_Property_GUID, UIA_LegacyIAccessibleValuePropertyId, },
|
||||
{ &IsDragPatternAvailable_Property_GUID, UIA_IsDragPatternAvailablePropertyId, },
|
||||
{ &DescribedBy_Property_GUID, UIA_DescribedByPropertyId, },
|
||||
{ &DescribedBy_Property_GUID, UIA_DescribedByPropertyId,
|
||||
UIAutomationType_ElementArray, },
|
||||
{ &IsSelectionPatternAvailable_Property_GUID, UIA_IsSelectionPatternAvailablePropertyId, },
|
||||
{ &Grid_RowCount_Property_GUID, UIA_GridRowCountPropertyId, },
|
||||
{ &OutlineColor_Property_GUID, UIA_OutlineColorPropertyId,
|
||||
|
@ -195,7 +200,8 @@ static const struct uia_prop_info default_uia_properties[] = {
|
|||
{ &IsSynchronizedInputPatternAvailable_Property_GUID,UIA_IsSynchronizedInputPatternAvailablePropertyId, },
|
||||
{ &OutlineThickness_Property_GUID, UIA_OutlineThicknessPropertyId, },
|
||||
{ &IsLegacyIAccessiblePatternAvailable_Property_GUID,UIA_IsLegacyIAccessiblePatternAvailablePropertyId, },
|
||||
{ &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId, },
|
||||
{ &AnnotationObjects_Property_GUID, UIA_AnnotationObjectsPropertyId,
|
||||
UIAutomationType_ElementArray, },
|
||||
{ &IsRequiredForForm_Property_GUID, UIA_IsRequiredForFormPropertyId, },
|
||||
{ &SpreadsheetItem_AnnotationTypes_Property_GUID, UIA_SpreadsheetItemAnnotationTypesPropertyId, },
|
||||
{ &FillColor_Property_GUID, UIA_FillColorPropertyId,
|
||||
|
|
Loading…
Reference in a new issue