diff --git a/change/react-native-windows-b93a8310-8489-4f09-8497-eb5807c505b9.json b/change/react-native-windows-b93a8310-8489-4f09-8497-eb5807c505b9.json new file mode 100644 index 00000000000..c5711a3aefc --- /dev/null +++ b/change/react-native-windows-b93a8310-8489-4f09-8497-eb5807c505b9.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "[Fabric] Implement announceForAccessibility in AccessibilityInfo Module", + "packageName": "react-native-windows", + "email": "kvineeth@microsoft.com", + "dependentChangeType": "patch" +} diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp index 63829c6adab..d1424fa0ebd 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp @@ -40,6 +40,14 @@ namespace winrt::Microsoft::ReactNative::implementation { +ReactPropertyId>> +ReactNativeIsland::LastFocusedReactNativeIslandProperty() noexcept { + static const ReactPropertyId>> + prop{L"ReactNative.Composition", L"ReactNativeIsland"}; + return prop; +} constexpr float loadingActivitySize = 12.0f; constexpr float loadingActivityHorizontalOffset = 16.0f; constexpr float loadingBarHeight = 36.0f; @@ -861,6 +869,20 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() { } } }); + focusController.GotFocus( + [weakThis = get_weak()](const auto &sender, const winrt::Microsoft::UI::Input::FocusChangedEventArgs &args) { + if (auto pThis = weakThis.get()) { + // Set the island to React context so it can be accessed by native modules + if (pThis->m_context && pThis->m_island) { + auto properties = pThis->m_context.Properties(); + properties.Set( + ReactNativeIsland::LastFocusedReactNativeIslandProperty(), + winrt::Microsoft::ReactNative::ReactNonAbiValue< + winrt::weak_ref>{ + std::in_place, weakThis}); + } + } + }); // ContentIsland does not support weak_ref, so we cannot use auto_revoke for these events m_islandAutomationProviderRequestedToken = m_island.AutomationProviderRequested( diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h index 0a306125890..2b959123387 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h @@ -49,6 +49,9 @@ struct ReactNativeIsland ~ReactNativeIsland() noexcept; ReactNativeIsland(const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept; + static ReactPropertyId>> + LastFocusedReactNativeIslandProperty() noexcept; ReactNativeIsland(const winrt::Microsoft::ReactNative::Composition::PortalComponentView &portal) noexcept; static winrt::Microsoft::ReactNative::ReactNativeIsland CreatePortal( diff --git a/vnext/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp b/vnext/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp index 9e287550eee..2c6915cd66e 100644 --- a/vnext/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +++ b/vnext/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp @@ -7,6 +7,8 @@ #include #include #include +#else +#include #endif #include #include @@ -79,6 +81,33 @@ void AccessibilityInfo::announceForAccessibility(std::wstring announcement) noex xaml::Automation::Peers::AutomationNotificationProcessing::ImportantMostRecent, hstr, hstr); +#else + if (auto weakIslandWrapper = context.Properties().Get( + winrt::Microsoft::ReactNative::implementation::ReactNativeIsland::LastFocusedReactNativeIslandProperty())) { + if (auto weakIsland = weakIslandWrapper.Value()) { + if (auto reactNativeIsland = weakIsland.get()) { + if (auto uiaprovider = reactNativeIsland->GetUiaProvider()) { + if (auto rawProvider = uiaprovider.try_as()) { + // Convert announcement to BSTR for UIA + winrt::hstring hstrAnnouncement{announcement}; + auto bstrAnnouncement = SysAllocString(hstrAnnouncement.c_str()); + if (bstrAnnouncement) { + // Raise the UIA notification event + HRESULT hr = UiaRaiseNotificationEvent( + rawProvider.get(), + NotificationKind_Other, + NotificationProcessing_ImportantMostRecent, + bstrAnnouncement, + bstrAnnouncement); + // Clean up BSTRs + SysFreeString(bstrAnnouncement); + } + } + } + } + } + } + #endif }); }