Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"type": "prerelease",
"comment": "Add UIA HeadingLevel behaviour for Fabric architecture",
"packageName": "react-native-windows",
"email": "kvineeth@microsoft.com",
"dependentChangeType": "patch"
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class AccessibilityBaseExample extends React.Component {
style={{width: 50, height: 50, backgroundColor: 'blue'}}
accessible={true}
accessibilityLabel="A blue box"
role="heading"
accessibilityHint="A hint for the blue box."
accessibilityLevel={1}
accessibilityItemType="comment"
Expand All @@ -42,6 +43,7 @@ class AccessibilityBaseExample extends React.Component {
style={{width: 50, height: 50, backgroundColor: 'red'}}
accessible={true}
accessibilityLabel="A hint for the red box."
accessibilityRole="header"
accessibilityLevel={2}
testID="accessibility-base-view-2"
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ exports[`Accessibility Tests Accessibility data for Label and Level 1`] = `
{
"Automation Tree": {
"AutomationId": "accessibility-base-view-2",
"ControlType": 50026,
"ControlType": 50020,
"HeadingLevel": 80052,
"Level": 2,
"LocalizedControlType": "group",
"LocalizedControlType": "text",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ViewComponentView",
Expand Down Expand Up @@ -36,12 +37,13 @@ exports[`Accessibility Tests Accessibility data for Label,Level and Hint 1`] = `
"AnnotationPattern.TypeId": 60003,
"AnnotationPattern.TypeName": "Check Comment",
"AutomationId": "accessibility-base-view-1",
"ControlType": 50026,
"ControlType": 50020,
"Description": "Sample Description",
"HeadingLevel": 80051,
"HelpText": "A hint for the blue box.",
"ItemType": "comment",
"Level": 1,
"LocalizedControlType": "group",
"LocalizedControlType": "text",
},
"Component Tree": {
"Type": "Microsoft.ReactNative.Composition.ViewComponentView",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ exports[`snapshotAllPages Accessibility Windows 1`] = `
accessibilityLabel="A blue box"
accessibilityLevel={1}
accessible={true}
role="heading"
style={
{
"backgroundColor": "blue",
Expand All @@ -38,6 +39,7 @@ exports[`snapshotAllPages Accessibility Windows 1`] = `
<View
accessibilityLabel="A hint for the red box."
accessibilityLevel={2}
accessibilityRole="header"
accessible={true}
style={
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ winrt::Windows::Data::Json::JsonObject DumpUIATreeRecurse(
int positionInSet = 0;
int sizeOfSet = 0;
int level = 0;
int headingLevel = 0;
LiveSetting liveSetting = LiveSetting::Off;
BSTR itemStatus;
BSTR itemType;
Expand Down Expand Up @@ -551,6 +552,11 @@ winrt::Windows::Data::Json::JsonObject DumpUIATreeRecurse(
if (SUCCEEDED(hr) && pTarget6) {
pTarget6->get_CurrentFullDescription(&description);
}
IUIAutomationElement8 *pTarget8;
hr = pTarget->QueryInterface(__uuidof(IUIAutomationElement8), reinterpret_cast<void **>(&pTarget8));
if (SUCCEEDED(hr) && pTarget8) {
pTarget8->get_CurrentHeadingLevel(&headingLevel);
}
result.Insert(L"AutomationId", winrt::Windows::Data::Json::JsonValue::CreateStringValue(automationId));
result.Insert(L"ControlType", winrt::Windows::Data::Json::JsonValue::CreateNumberValue(controlType));
InsertStringValueIfNotEmpty(result, L"HelpText", helpText);
Expand All @@ -560,6 +566,7 @@ winrt::Windows::Data::Json::JsonObject DumpUIATreeRecurse(
L"LocalizedControlType", winrt::Windows::Data::Json::JsonValue::CreateStringValue(localizedControlType));
InsertStringValueIfNotEmpty(result, L"Name", name);
InsertIntValueIfNotDefault(result, L"PositionInSet", positionInSet);
InsertIntValueIfNotDefault(result, L"HeadingLevel", headingLevel, HeadingLevel_None);
InsertIntValueIfNotDefault(result, L"SizeofSet", sizeOfSet);
InsertIntValueIfNotDefault(result, L"Level", level);
InsertLiveSettingValueIfNotDefault(result, L"LiveSetting", liveSetting);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,161 +313,6 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
return S_OK;
}

long GetControlTypeFromString(const std::string &role) noexcept {
if (role == "adjustable") {
return UIA_SliderControlTypeId;
} else if (role == "group" || role == "search" || role == "radiogroup" || role == "timer" || role.empty()) {
return UIA_GroupControlTypeId;
} else if (role == "button" || role == "imagebutton" || role == "switch" || role == "togglebutton") {
return UIA_ButtonControlTypeId;
} else if (role == "checkbox") {
return UIA_CheckBoxControlTypeId;
} else if (role == "combobox") {
return UIA_ComboBoxControlTypeId;
} else if (role == "alert" || role == "header" || role == "summary" || role == "text") {
return UIA_TextControlTypeId;
} else if (role == "image") {
return UIA_ImageControlTypeId;
} else if (role == "keyboardkey") {
return UIA_CustomControlTypeId;
} else if (role == "link") {
return UIA_HyperlinkControlTypeId;
}
// list and listitem were added by RNW to better support UIA Control Types
else if (role == "list") {
return UIA_ListControlTypeId;
} else if (role == "listitem") {
return UIA_ListItemControlTypeId;
} else if (role == "menu") {
return UIA_MenuControlTypeId;
} else if (role == "menubar") {
return UIA_MenuBarControlTypeId;
} else if (role == "menuitem") {
return UIA_MenuItemControlTypeId;
}
// If role is "none", remove the element from the control tree
// and expose it as a plain element would in the raw tree.
else if (role == "none") {
return UIA_GroupControlTypeId;
} else if (role == "progressbar") {
return UIA_ProgressBarControlTypeId;
} else if (role == "radio") {
return UIA_RadioButtonControlTypeId;
} else if (role == "scrollbar") {
return UIA_ScrollBarControlTypeId;
} else if (role == "spinbutton") {
return UIA_SpinnerControlTypeId;
} else if (role == "splitbutton") {
return UIA_SplitButtonControlTypeId;
} else if (role == "tab") {
return UIA_TabItemControlTypeId;
} else if (role == "tablist") {
return UIA_TabControlTypeId;
} else if (role == "textinput" || role == "searchbox") {
return UIA_EditControlTypeId;
} else if (role == "toolbar") {
return UIA_ToolBarControlTypeId;
} else if (role == "tree") {
return UIA_TreeControlTypeId;
} else if (role == "treeitem") {
return UIA_TreeItemControlTypeId;
} else if (role == "pane") {
return UIA_PaneControlTypeId;
}
assert(false);
return UIA_GroupControlTypeId;
}

long GetControlTypeFromRole(const facebook::react::Role &role) noexcept {
switch (role) {
case facebook::react::Role::Alert:
return UIA_TextControlTypeId;
case facebook::react::Role::Application:
return UIA_WindowControlTypeId;
case facebook::react::Role::Button:
return UIA_ButtonControlTypeId;
case facebook::react::Role::Checkbox:
return UIA_CheckBoxControlTypeId;
case facebook::react::Role::Columnheader:
return UIA_HeaderControlTypeId;
case facebook::react::Role::Combobox:
return UIA_ComboBoxControlTypeId;
case facebook::react::Role::Document:
return UIA_DocumentControlTypeId;
case facebook::react::Role::Grid:
return UIA_GroupControlTypeId;
case facebook::react::Role::Group:
return UIA_GroupControlTypeId;
case facebook::react::Role::Heading:
return UIA_TextControlTypeId;
case facebook::react::Role::Img:
return UIA_ImageControlTypeId;
case facebook::react::Role::Link:
return UIA_HyperlinkControlTypeId;
case facebook::react::Role::List:
return UIA_ListControlTypeId;
case facebook::react::Role::Listitem:
return UIA_ListItemControlTypeId;
case facebook::react::Role::Menu:
return UIA_MenuControlTypeId;
case facebook::react::Role::Menubar:
return UIA_MenuBarControlTypeId;
case facebook::react::Role::Menuitem:
return UIA_MenuItemControlTypeId;
case facebook::react::Role::None:
return UIA_GroupControlTypeId;
case facebook::react::Role::Presentation:
return UIA_GroupControlTypeId;
case facebook::react::Role::Progressbar:
return UIA_ProgressBarControlTypeId;
case facebook::react::Role::Radio:
return UIA_RadioButtonControlTypeId;
case facebook::react::Role::Radiogroup:
return UIA_GroupControlTypeId;
case facebook::react::Role::Rowgroup:
return UIA_GroupControlTypeId;
case facebook::react::Role::Rowheader:
return UIA_HeaderControlTypeId;
case facebook::react::Role::Scrollbar:
return UIA_ScrollBarControlTypeId;
case facebook::react::Role::Searchbox:
return UIA_EditControlTypeId;
case facebook::react::Role::Separator:
return UIA_SeparatorControlTypeId;
case facebook::react::Role::Slider:
return UIA_SliderControlTypeId;
case facebook::react::Role::Spinbutton:
return UIA_SpinnerControlTypeId;
case facebook::react::Role::Status:
return UIA_StatusBarControlTypeId;
case facebook::react::Role::Summary:
return UIA_GroupControlTypeId;
case facebook::react::Role::Switch:
return UIA_ButtonControlTypeId;
case facebook::react::Role::Tab:
return UIA_TabItemControlTypeId;
case facebook::react::Role::Table:
return UIA_TableControlTypeId;
case facebook::react::Role::Tablist:
return UIA_TabControlTypeId;
case facebook::react::Role::Tabpanel:
return UIA_TabControlTypeId;
case facebook::react::Role::Timer:
return UIA_ButtonControlTypeId;
case facebook::react::Role::Toolbar:
return UIA_ToolBarControlTypeId;
case facebook::react::Role::Tooltip:
return UIA_ToolTipControlTypeId;
case facebook::react::Role::Tree:
return UIA_TreeControlTypeId;
case facebook::react::Role::Treegrid:
return UIA_TreeControlTypeId;
case facebook::react::Role::Treeitem:
return UIA_TreeItemControlTypeId;
}
return UIA_GroupControlTypeId;
}

HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERTYID propertyId, VARIANT *pRetVal) {
if (pRetVal == nullptr)
return E_POINTER;
Expand Down Expand Up @@ -640,6 +485,11 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
pRetVal->bstrVal = SysAllocString(desc.c_str());
break;
}
case UIA_HeadingLevelPropertyId: {
pRetVal->vt = VT_I4;
pRetVal->lVal = GetHeadingLevel(props->accessibilityLevel, props->accessibilityRole, props->role);
break;
}
}
return hr;
}
Expand Down
Loading
Loading