From 63e5d6f426838b172e8a0848d5266ffb25428e84 Mon Sep 17 00:00:00 2001 From: Protik Biswas Date: Fri, 3 Oct 2025 14:48:17 +0530 Subject: [PATCH 1/5] Fixing heading level for accessibility --- .../CompositionDynamicAutomationProvider.cpp | 21 ++++++++---- .../CompositionViewComponentView.cpp | 33 +++++++++++-------- 2 files changed, 33 insertions(+), 21 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp index 5e34404bd31..a5ab3dde964 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include #include "RootComponentView.h" #include "UiaHelpers.h" @@ -484,6 +485,9 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT if (props == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; + // Cast to HostPlatformViewProps to access Windows-specific properties like accessibilityLevel + auto hostProps = std::static_pointer_cast(baseView->props()); + auto compositionView = strongView.try_as(); if (compositionView == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; @@ -597,17 +601,17 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT } case UIA_PositionInSetPropertyId: { pRetVal->vt = VT_I4; - pRetVal->lVal = props->accessibilityPosInSet; + pRetVal->lVal = hostProps ? hostProps->accessibilityPosInSet : 0; break; } case UIA_SizeOfSetPropertyId: { pRetVal->vt = VT_I4; - pRetVal->lVal = props->accessibilitySetSize; + pRetVal->lVal = hostProps ? hostProps->accessibilitySetSize : 0; break; } case UIA_LiveSettingPropertyId: { pRetVal->vt = VT_I4; - pRetVal->lVal = GetLiveSetting(props->accessibilityLiveRegion); + pRetVal->lVal = GetLiveSetting(hostProps ? hostProps->accessibilityLiveRegion : "none"); break; } case UIA_ItemStatusPropertyId: { @@ -619,24 +623,27 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT } case UIA_LevelPropertyId: { pRetVal->vt = VT_I4; - pRetVal->lVal = props->accessibilityLevel; + pRetVal->lVal = hostProps ? hostProps->accessibilityLevel : 0; break; } case UIA_AccessKeyPropertyId: { pRetVal->vt = VT_BSTR; - auto accessKey = ::Microsoft::Common::Unicode::Utf8ToUtf16(props->accessibilityAccessKey.value_or("")); + auto accessKey = + ::Microsoft::Common::Unicode::Utf8ToUtf16(hostProps ? hostProps->accessibilityAccessKey.value_or("") : ""); pRetVal->bstrVal = SysAllocString(accessKey.c_str()); break; } case UIA_ItemTypePropertyId: { pRetVal->vt = VT_BSTR; - auto itemtype = ::Microsoft::Common::Unicode::Utf8ToUtf16(props->accessibilityItemType.value_or("")); + auto itemtype = + ::Microsoft::Common::Unicode::Utf8ToUtf16(hostProps ? hostProps->accessibilityItemType.value_or("") : ""); pRetVal->bstrVal = SysAllocString(itemtype.c_str()); break; } case UIA_FullDescriptionPropertyId: { pRetVal->vt = VT_BSTR; - auto desc = ::Microsoft::Common::Unicode::Utf8ToUtf16(props->accessibilityDescription.value_or("")); + auto desc = + ::Microsoft::Common::Unicode::Utf8ToUtf16(hostProps ? hostProps->accessibilityDescription.value_or("") : ""); pRetVal->bstrVal = SysAllocString(desc.c_str()); break; } diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp index b53b7057344..9720e587ab6 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -747,6 +748,10 @@ void ComponentView::updateAccessibilityProps( if (!UiaClientsAreListening()) return; + // Cast to HostPlatformViewProps to access Windows-specific properties + auto oldHostProps = static_cast(&oldViewProps); + auto newHostProps = static_cast(&newViewProps); + winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_IsKeyboardFocusablePropertyId, oldViewProps.focusable, newViewProps.focusable); @@ -789,41 +794,41 @@ void ComponentView::updateAccessibilityProps( winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_PositionInSetPropertyId, - oldViewProps.accessibilityPosInSet, - newViewProps.accessibilityPosInSet); + oldHostProps->accessibilityPosInSet, + newHostProps->accessibilityPosInSet); winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_SizeOfSetPropertyId, - oldViewProps.accessibilitySetSize, - newViewProps.accessibilitySetSize); + oldHostProps->accessibilitySetSize, + newHostProps->accessibilitySetSize); winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_LiveSettingPropertyId, - oldViewProps.accessibilityLiveRegion, - newViewProps.accessibilityLiveRegion); + oldHostProps->accessibilityLiveRegion, + newHostProps->accessibilityLiveRegion); winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( - EnsureUiaProvider(), UIA_LevelPropertyId, oldViewProps.accessibilityLevel, newViewProps.accessibilityLevel); + EnsureUiaProvider(), UIA_LevelPropertyId, oldHostProps->accessibilityLevel, newHostProps->accessibilityLevel); winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_AccessKeyPropertyId, - oldViewProps.accessibilityAccessKey, - newViewProps.accessibilityAccessKey); + oldHostProps->accessibilityAccessKey, + newHostProps->accessibilityAccessKey); winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_ItemTypePropertyId, - oldViewProps.accessibilityItemType, - newViewProps.accessibilityItemType); + oldHostProps->accessibilityItemType, + newHostProps->accessibilityItemType); winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_FullDescriptionPropertyId, - oldViewProps.accessibilityDescription, - newViewProps.accessibilityDescription); + oldHostProps->accessibilityDescription, + newHostProps->accessibilityDescription); winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), @@ -833,7 +838,7 @@ void ComponentView::updateAccessibilityProps( // Handle annotation properties with single call winrt::Microsoft::ReactNative::implementation::UpdateUiaPropertiesForAnnotation( - EnsureUiaProvider(), oldViewProps.accessibilityAnnotation, newViewProps.accessibilityAnnotation); + EnsureUiaProvider(), oldHostProps->accessibilityAnnotation, newHostProps->accessibilityAnnotation); // Handle expand/collapse state changes if (oldViewProps.accessibilityState.has_value() != newViewProps.accessibilityState.has_value() || From 9c0486230c2982f6c37de70fd5056e2785af03ee Mon Sep 17 00:00:00 2001 From: Protik Biswas Date: Fri, 3 Oct 2025 14:54:20 +0530 Subject: [PATCH 2/5] Change files --- ...ative-windows-48182af8-4e3f-46a5-a980-f041f56ff6ce.json | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 change/react-native-windows-48182af8-4e3f-46a5-a980-f041f56ff6ce.json diff --git a/change/react-native-windows-48182af8-4e3f-46a5-a980-f041f56ff6ce.json b/change/react-native-windows-48182af8-4e3f-46a5-a980-f041f56ff6ce.json new file mode 100644 index 00000000000..113c1045905 --- /dev/null +++ b/change/react-native-windows-48182af8-4e3f-46a5-a980-f041f56ff6ce.json @@ -0,0 +1,7 @@ +{ + "comment": "Fixing heading level for accessibility", + "type": "prerelease", + "packageName": "react-native-windows", + "email": "protikbiswas100@microsoft.com", + "dependentChangeType": "patch" +} From 3440f1f692502bc3f6bf35fbba09b92d999de20e Mon Sep 17 00:00:00 2001 From: Protik Biswas <219775028+protikbiswas100@users.noreply.github.com> Date: Fri, 3 Oct 2025 17:11:26 +0530 Subject: [PATCH 3/5] Update vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Composition/CompositionDynamicAutomationProvider.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp index a5ab3dde964..abfcbd5d656 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp @@ -486,7 +486,11 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT return UIA_E_ELEMENTNOTAVAILABLE; // Cast to HostPlatformViewProps to access Windows-specific properties like accessibilityLevel - auto hostProps = std::static_pointer_cast(baseView->props()); + auto hostProps = std::dynamic_pointer_cast(baseView->props()); + if (hostProps == nullptr) { + // If hostProps is needed later, handle the null case appropriately. + // For now, we just proceed; add error handling if hostProps is dereferenced below. + } auto compositionView = strongView.try_as(); if (compositionView == nullptr) From a5caed4f0057c2692139e456415211b681969b76 Mon Sep 17 00:00:00 2001 From: Protik Biswas <219775028+protikbiswas100@users.noreply.github.com> Date: Fri, 3 Oct 2025 17:11:37 +0530 Subject: [PATCH 4/5] Update vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../Fabric/Composition/CompositionViewComponentView.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp index 9720e587ab6..29546b72d6d 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp @@ -749,8 +749,12 @@ void ComponentView::updateAccessibilityProps( return; // Cast to HostPlatformViewProps to access Windows-specific properties - auto oldHostProps = static_cast(&oldViewProps); - auto newHostProps = static_cast(&newViewProps); + auto oldHostProps = dynamic_cast(&oldViewProps); + auto newHostProps = dynamic_cast(&newViewProps); + if (!oldHostProps || !newHostProps) { + // The cast failed; cannot safely access HostPlatformViewProps-specific members. + return; + } winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_IsKeyboardFocusablePropertyId, oldViewProps.focusable, newViewProps.focusable); From f7008e354e59736511176b71692552e106810f6b Mon Sep 17 00:00:00 2001 From: Protik Biswas Date: Mon, 6 Oct 2025 10:07:06 +0530 Subject: [PATCH 5/5] adding dynamic pointer cast to viewProps --- .../CompositionDynamicAutomationProvider.cpp | 9 ++- .../CompositionViewComponentView.cpp | 81 ++++++++++--------- 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp index a5ab3dde964..1e76cf8cddb 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp @@ -481,13 +481,14 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT if (baseView == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; - auto props = std::static_pointer_cast(baseView->props()); + // Try to cast to HostPlatformViewProps first for Windows-specific properties + auto hostProps = std::dynamic_pointer_cast(baseView->props()); + + // If that fails, fall back to ViewProps for basic accessibility properties + auto props = hostProps ? hostProps : std::static_pointer_cast(baseView->props()); if (props == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; - // Cast to HostPlatformViewProps to access Windows-specific properties like accessibilityLevel - auto hostProps = std::static_pointer_cast(baseView->props()); - auto compositionView = strongView.try_as(); if (compositionView == nullptr) return UIA_E_ELEMENTNOTAVAILABLE; diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp index 9720e587ab6..c2e72f44bcc 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp @@ -748,9 +748,9 @@ void ComponentView::updateAccessibilityProps( if (!UiaClientsAreListening()) return; - // Cast to HostPlatformViewProps to access Windows-specific properties - auto oldHostProps = static_cast(&oldViewProps); - auto newHostProps = static_cast(&newViewProps); + // Try to safely cast to HostPlatformViewProps to access Windows-specific properties + auto oldHostProps = dynamic_cast(&oldViewProps); + auto newHostProps = dynamic_cast(&newViewProps); winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_IsKeyboardFocusablePropertyId, oldViewProps.focusable, newViewProps.focusable); @@ -791,44 +791,51 @@ void ComponentView::updateAccessibilityProps( winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), UIA_HelpTextPropertyId, oldViewProps.accessibilityHint, newViewProps.accessibilityHint); - winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( - EnsureUiaProvider(), - UIA_PositionInSetPropertyId, - oldHostProps->accessibilityPosInSet, - newHostProps->accessibilityPosInSet); + // Only update Windows-specific properties if we have HostPlatformViewProps + if (oldHostProps && newHostProps) { + winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( + EnsureUiaProvider(), + UIA_PositionInSetPropertyId, + oldHostProps->accessibilityPosInSet, + newHostProps->accessibilityPosInSet); - winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( - EnsureUiaProvider(), - UIA_SizeOfSetPropertyId, - oldHostProps->accessibilitySetSize, - newHostProps->accessibilitySetSize); + winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( + EnsureUiaProvider(), + UIA_SizeOfSetPropertyId, + oldHostProps->accessibilitySetSize, + newHostProps->accessibilitySetSize); - winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( - EnsureUiaProvider(), - UIA_LiveSettingPropertyId, - oldHostProps->accessibilityLiveRegion, - newHostProps->accessibilityLiveRegion); + winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( + EnsureUiaProvider(), + UIA_LiveSettingPropertyId, + oldHostProps->accessibilityLiveRegion, + newHostProps->accessibilityLiveRegion); - winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( - EnsureUiaProvider(), UIA_LevelPropertyId, oldHostProps->accessibilityLevel, newHostProps->accessibilityLevel); + winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( + EnsureUiaProvider(), UIA_LevelPropertyId, oldHostProps->accessibilityLevel, newHostProps->accessibilityLevel); - winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( - EnsureUiaProvider(), - UIA_AccessKeyPropertyId, - oldHostProps->accessibilityAccessKey, - newHostProps->accessibilityAccessKey); + winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( + EnsureUiaProvider(), + UIA_AccessKeyPropertyId, + oldHostProps->accessibilityAccessKey, + newHostProps->accessibilityAccessKey); - winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( - EnsureUiaProvider(), - UIA_ItemTypePropertyId, - oldHostProps->accessibilityItemType, - newHostProps->accessibilityItemType); + winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( + EnsureUiaProvider(), + UIA_ItemTypePropertyId, + oldHostProps->accessibilityItemType, + newHostProps->accessibilityItemType); - winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( - EnsureUiaProvider(), - UIA_FullDescriptionPropertyId, - oldHostProps->accessibilityDescription, - newHostProps->accessibilityDescription); + winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( + EnsureUiaProvider(), + UIA_FullDescriptionPropertyId, + oldHostProps->accessibilityDescription, + newHostProps->accessibilityDescription); + + // Handle annotation properties with single call + winrt::Microsoft::ReactNative::implementation::UpdateUiaPropertiesForAnnotation( + EnsureUiaProvider(), oldHostProps->accessibilityAnnotation, newHostProps->accessibilityAnnotation); + } winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty( EnsureUiaProvider(), @@ -836,10 +843,6 @@ void ComponentView::updateAccessibilityProps( oldViewProps.accessibilityValue.text, newViewProps.accessibilityValue.text); - // Handle annotation properties with single call - winrt::Microsoft::ReactNative::implementation::UpdateUiaPropertiesForAnnotation( - EnsureUiaProvider(), oldHostProps->accessibilityAnnotation, newHostProps->accessibilityAnnotation); - // Handle expand/collapse state changes if (oldViewProps.accessibilityState.has_value() != newViewProps.accessibilityState.has_value() || (oldViewProps.accessibilityState.has_value() && newViewProps.accessibilityState.has_value() &&