react-native-windows 0.76.7 → 0.76.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/Libraries/Components/Button.windows.js +9 -0
  2. package/Libraries/Components/Pressable/Pressable.windows.js +9 -0
  3. package/Libraries/Components/TextInput/TextInput.windows.js +11 -1
  4. package/Libraries/Components/Touchable/TouchableBounce.windows.js +229 -0
  5. package/Libraries/Components/Touchable/TouchableNativeFeedback.windows.js +373 -0
  6. package/Libraries/Components/Touchable/TouchableOpacity.windows.js +7 -0
  7. package/Libraries/Components/Touchable/TouchableWithoutFeedback.windows.js +8 -0
  8. package/Libraries/Components/View/View.windows.js +11 -1
  9. package/Libraries/Components/View/ViewAccessibility.d.ts +15 -0
  10. package/Libraries/Components/View/ViewAccessibility.windows.js +3 -0
  11. package/Libraries/Components/View/ViewPropTypes.windows.js +3 -0
  12. package/Libraries/Core/ReactNativeVersion.js +1 -1
  13. package/Libraries/Image/Image.windows.js +7 -0
  14. package/Libraries/Modal/Modal.windows.js +4 -1
  15. package/Libraries/Text/Text.windows.js +14 -1
  16. package/Libraries/Text/TextProps.windows.js +3 -0
  17. package/Microsoft.ReactNative/CompositionComponentView.idl +13 -1
  18. package/Microsoft.ReactNative/Fabric/AbiPortalShadowNode.cpp +97 -0
  19. package/Microsoft.ReactNative/Fabric/AbiPortalShadowNode.h +53 -0
  20. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.h +160 -17
  21. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +8 -10
  22. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +4 -2
  23. package/Microsoft.ReactNative/Fabric/Composition/ComponentViewRegistry.cpp +0 -5
  24. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +428 -39
  25. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +39 -1
  26. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +55 -33
  27. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +5 -3
  28. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +43 -5
  29. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.h +2 -1
  30. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp +115 -0
  31. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h +41 -0
  32. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp +298 -0
  33. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h +59 -0
  34. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +106 -56
  35. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +2 -0
  36. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +163 -10
  37. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +17 -1
  38. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +4 -2
  39. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +9 -1
  40. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +348 -316
  41. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +3 -61
  42. package/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.cpp +78 -0
  43. package/Microsoft.ReactNative/Fabric/Composition/PortalComponentView.h +52 -0
  44. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +22 -0
  45. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +7 -5
  46. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +99 -37
  47. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +12 -6
  48. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +81 -22
  49. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +21 -2
  50. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +6 -1
  51. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +41 -37
  52. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +76 -33
  53. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +8 -2
  54. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +1 -6
  55. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.h +0 -3
  56. package/Microsoft.ReactNative/Fabric/WindowsComponentDescriptorRegistry.cpp +0 -2
  57. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/HostPlatformColor.h +5 -8
  58. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorParser.h +1 -2
  59. package/Microsoft.ReactNative/Fabric/platform/react/renderer/graphics/PlatformColorUtils.cpp +1 -1
  60. package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +15 -1
  61. package/Microsoft.ReactNative/IReactContext.cpp +2 -2
  62. package/Microsoft.ReactNative/IReactContext.h +1 -1
  63. package/Microsoft.ReactNative/IReactContext.idl +2 -2
  64. package/Microsoft.ReactNative/IReactPackageBuilder.idl +3 -3
  65. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +97 -87
  66. package/Microsoft.ReactNative/Modules/AccessibilityInfoModule.cpp +4 -0
  67. package/Microsoft.ReactNative/Modules/AlertModule.cpp +9 -4
  68. package/Microsoft.ReactNative/Modules/Animated/NativeAnimatedNodeManager.cpp +1 -1
  69. package/Microsoft.ReactNative/Modules/Animated/PropsAnimatedNode.cpp +32 -35
  70. package/Microsoft.ReactNative/Modules/Animated/PropsAnimatedNode.h +7 -4
  71. package/Microsoft.ReactNative/Modules/AppStateModule.cpp +1 -1
  72. package/Microsoft.ReactNative/Modules/AppThemeModuleUwp.cpp +2 -2
  73. package/Microsoft.ReactNative/Modules/AppearanceModule.cpp +2 -2
  74. package/Microsoft.ReactNative/Modules/ClipboardModule.cpp +1 -1
  75. package/Microsoft.ReactNative/Modules/ClipboardModule.h +1 -1
  76. package/Microsoft.ReactNative/Modules/DeviceInfoModule.cpp +3 -3
  77. package/Microsoft.ReactNative/Modules/I18nManagerModule.cpp +1 -1
  78. package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +7 -5
  79. package/Microsoft.ReactNative/Modules/LogBoxModule.h +2 -1
  80. package/Microsoft.ReactNative/Modules/Timing.cpp +2 -2
  81. package/Microsoft.ReactNative/ReactHost/IReactInstance.h +5 -0
  82. package/Microsoft.ReactNative/ReactHost/React.h +0 -3
  83. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +36 -12
  84. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.h +1 -1
  85. package/Microsoft.ReactNative/ReactNativeHost.cpp +9 -4
  86. package/Microsoft.ReactNative/ReactNativeIsland.idl +5 -1
  87. package/Microsoft.ReactNative/ReactPackageBuilder.cpp +3 -3
  88. package/Microsoft.ReactNative/ReactPackageBuilder.h +4 -4
  89. package/Microsoft.ReactNative/Utils/Helpers.cpp +0 -2
  90. package/Microsoft.ReactNative/Views/DevMenu.cpp +6 -6
  91. package/Microsoft.ReactNative/Views/DevMenu.h +1 -1
  92. package/Microsoft.ReactNative/XamlUIService.cpp +13 -7
  93. package/Microsoft.ReactNative/XamlUIService.h +4 -1
  94. package/Microsoft.ReactNative/XamlUIService.idl +2 -0
  95. package/Microsoft.ReactNative.Cxx/JSI/JsiAbiApi.h +6 -2
  96. package/Microsoft.ReactNative.Cxx/NativeModules.h +29 -0
  97. package/Microsoft.ReactNative.Cxx/ReactContext.h +1 -1
  98. package/Microsoft.ReactNative.Cxx/XamlUtils.h +12 -0
  99. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  100. package/PropertySheets/React.Cpp.props +3 -0
  101. package/PropertySheets/WebView2.props +1 -1
  102. package/PropertySheets/WinUI.props +5 -4
  103. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/AccessibilityPrimitives.h +253 -0
  104. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/renderer/components/view/accessibilityPropsConversions.h +799 -0
  105. package/ReactCommon/TEMP_UntilReactCommonUpdate/react/runtime/ReactInstance.cpp +39 -35
  106. package/Shared/InspectorPackagerConnection.cpp +2 -5
  107. package/Shared/InspectorPackagerConnection.h +2 -2
  108. package/Shared/Networking/WinRTWebSocketResource.cpp +369 -7
  109. package/Shared/Networking/WinRTWebSocketResource.h +118 -0
  110. package/Shared/Shared.vcxitems +12 -5
  111. package/Shared/Shared.vcxitems.filters +11 -4
  112. package/codegen/NativeReactNativeFeatureFlagsSpec.g.h +91 -97
  113. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +212 -0
  114. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +295 -0
  115. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +200 -0
  116. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +224 -0
  117. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +250 -0
  118. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +267 -0
  119. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +234 -0
  120. package/codegen/react/components/rnwcore/InputAccessory.g.h +200 -0
  121. package/codegen/react/components/rnwcore/ModalHostView.g.h +279 -0
  122. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +246 -0
  123. package/codegen/react/components/rnwcore/SafeAreaView.g.h +197 -0
  124. package/codegen/react/components/rnwcore/Switch.g.h +263 -0
  125. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +200 -0
  126. package/codegen/rnwcoreJSI-generated.cpp +0 -6
  127. package/codegen/rnwcoreJSI.h +0 -9
  128. package/jest/setup.js +5 -1
  129. package/just-task.js +1 -1
  130. package/package.json +11 -11
  131. package/src/private/featureflags/ReactNativeFeatureFlags.js +1 -6
  132. package/src/private/featureflags/specs/NativeReactNativeFeatureFlags.js +1 -2
  133. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +0 -191
  134. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentDescriptor.h +0 -39
  135. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.cpp +0 -18
  136. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewShadowNode.h +0 -39
@@ -77,14 +77,12 @@ winrt::Microsoft::ReactNative::Color Color::ReadValue(
77
77
  switch (reader.ValueType()) {
78
78
  case JSValueType::Int64: {
79
79
  auto argb = reader.GetInt64();
80
- return winrt::make<Color>(facebook::react::Color{
81
- /*m_isDefined*/ true,
82
- /*color*/
83
- {static_cast<uint8_t>((argb >> 24) & 0xFF),
84
- static_cast<uint8_t>((argb >> 16) & 0xFF),
85
- static_cast<uint8_t>((argb >> 8) & 0xFF),
86
- static_cast<uint8_t>(argb & 0xFF)},
87
- {}});
80
+ return winrt::make<Color>(facebook::react::Color{/*color*/
81
+ {static_cast<uint8_t>((argb >> 24) & 0xFF),
82
+ static_cast<uint8_t>((argb >> 16) & 0xFF),
83
+ static_cast<uint8_t>((argb >> 8) & 0xFF),
84
+ static_cast<uint8_t>(argb & 0xFF)},
85
+ {}});
88
86
  }
89
87
  case JSValueType::Object: {
90
88
  std::vector<std::string> platformColors;
@@ -96,10 +94,10 @@ winrt::Microsoft::ReactNative::Color Color::ReadValue(
96
94
  SkipValue<JSValue>(reader); // Skip this property
97
95
  }
98
96
  }
99
- return winrt::make<Color>(facebook::react::Color{/*m_isDefined*/ true, /*color*/ {}, std::move(platformColors)});
97
+ return winrt::make<Color>(facebook::react::Color{/*color*/ {}, std::move(platformColors)});
100
98
  }
101
99
  default:
102
- return winrt::make<Color>(facebook::react::Color{/*m_isDefined*/ false, /*color*/ {0, 0, 0, 0}, {}});
100
+ return winrt::make<Color>(facebook::react::Color{/*color*/ {0, 0, 0, 0}, {}});
103
101
  }
104
102
  }
105
103
 
@@ -279,7 +279,10 @@ void ComponentView::parent(const winrt::Microsoft::ReactNative::ComponentView &p
279
279
  m_parent = parent;
280
280
  if (!parent) {
281
281
  if (oldRootView && oldRootView->GetFocusedComponent() == *this) {
282
- oldRootView->TrySetFocusedComponent(oldParent, winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
282
+ oldRootView->TrySetFocusedComponent(
283
+ oldParent,
284
+ winrt::Microsoft::ReactNative::FocusNavigationDirection::None,
285
+ true /*forceNoSelectionIfCannotMove*/);
283
286
  }
284
287
  }
285
288
  if (parent) {
@@ -639,7 +642,6 @@ facebook::react::Tag ComponentView::hitTest(
639
642
  }
640
643
 
641
644
  winrt::IInspectable ComponentView::EnsureUiaProvider() noexcept {
642
- assert(false);
643
645
  return nullptr;
644
646
  }
645
647
 
@@ -15,8 +15,6 @@
15
15
  #include <Fabric/Composition/CompositionViewComponentView.h>
16
16
  #include <Fabric/Composition/DebuggingOverlayComponentView.h>
17
17
  #include <Fabric/Composition/ImageComponentView.h>
18
- #include <Fabric/Composition/Modal/WindowsModalHostViewComponentView.h>
19
- #include <Fabric/Composition/Modal/WindowsModalHostViewShadowNode.h>
20
18
  #include <Fabric/Composition/ParagraphComponentView.h>
21
19
  #include <Fabric/Composition/RootComponentView.h>
22
20
  #include <Fabric/Composition/ScrollViewComponentView.h>
@@ -59,9 +57,6 @@ ComponentViewDescriptor const &ComponentViewRegistry::dequeueComponentViewWithCo
59
57
  } else if (componentHandle == facebook::react::ImageShadowNode::Handle()) {
60
58
  view = winrt::Microsoft::ReactNative::Composition::implementation::ImageComponentView::Create(
61
59
  compContext, tag, m_context);
62
- } else if (componentHandle == facebook::react::WindowsModalHostViewShadowNode::Handle()) {
63
- view = winrt::Microsoft::ReactNative::Composition::implementation::WindowsModalHostComponentView::Create(
64
- compContext, tag, m_context);
65
60
  } else if (componentHandle == facebook::react::WindowsTextInputShadowNode::Handle()) {
66
61
  view = winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView::Create(
67
62
  compContext, tag, m_context);
@@ -1,9 +1,12 @@
1
1
  #include "pch.h"
2
2
  #include "CompositionDynamicAutomationProvider.h"
3
3
  #include <Fabric/ComponentView.h>
4
+ #include <Fabric/Composition/CompositionTextRangeProvider.h>
5
+ #include <Fabric/Composition/ParagraphComponentView.h>
4
6
  #include <Fabric/Composition/SwitchComponentView.h>
5
7
  #include <Fabric/Composition/TextInput/WindowsTextInputComponentView.h>
6
8
  #include <Unicode.h>
9
+ #include <winrt/Microsoft.UI.Content.h>
7
10
  #include "RootComponentView.h"
8
11
  #include "UiaHelpers.h"
9
12
 
@@ -11,7 +14,35 @@ namespace winrt::Microsoft::ReactNative::implementation {
11
14
 
12
15
  CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
13
16
  const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView) noexcept
14
- : m_view{componentView} {}
17
+ : m_view{componentView} {
18
+ auto strongView = m_view.view();
19
+
20
+ if (!strongView)
21
+ return;
22
+
23
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
24
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
25
+ if (!props)
26
+ return;
27
+
28
+ if (props->accessibilityState.has_value() && props->accessibilityState->selected.has_value()) {
29
+ AddSelectionItemsToContainer(this);
30
+ }
31
+
32
+ if (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
33
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>()) {
34
+ m_textProvider = winrt::make<CompositionTextProvider>(
35
+ strongView.as<winrt::Microsoft::ReactNative::Composition::ComponentView>(), this)
36
+ .try_as<ITextProvider2>();
37
+ }
38
+ }
39
+
40
+ #ifdef USE_EXPERIMENTAL_WINUI3
41
+ CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
42
+ const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
43
+ const winrt::Microsoft::UI::Content::ChildSiteLink &childSiteLink) noexcept
44
+ : m_view{componentView}, m_childSiteLink{childSiteLink} {}
45
+ #endif // USE_EXPERIMENTAL_WINUI3
15
46
 
16
47
  HRESULT __stdcall CompositionDynamicAutomationProvider::Navigate(
17
48
  NavigateDirection direction,
@@ -19,6 +50,16 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Navigate(
19
50
  if (pRetVal == nullptr)
20
51
  return E_POINTER;
21
52
 
53
+ #ifdef USE_EXPERIMENTAL_WINUI3
54
+ if (m_childSiteLink) {
55
+ if (direction == NavigateDirection_FirstChild || direction == NavigateDirection_LastChild) {
56
+ auto fragment = m_childSiteLink.AutomationProvider().try_as<IRawElementProviderFragment>();
57
+ *pRetVal = fragment.detach();
58
+ return S_OK;
59
+ }
60
+ }
61
+ #endif // USE_EXPERIMENTAL_WINUI3
62
+
22
63
  return UiaNavigateHelper(m_view.view(), direction, *pRetVal);
23
64
  }
24
65
 
@@ -127,8 +168,12 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_ProviderOptions(Prov
127
168
  return S_OK;
128
169
  }
129
170
 
130
- bool accessibilityValueHasValue(const facebook::react::AccessibilityValue &value) {
131
- return (value.min.has_value() && value.max.has_value()) || value.now.has_value() || value.text.has_value();
171
+ bool accessibilityValueHasTextValue(const facebook::react::AccessibilityValue &value) {
172
+ return value.text.has_value();
173
+ }
174
+
175
+ bool accessibilityValueHasNumericValue(const facebook::react::AccessibilityValue &value) {
176
+ return (value.min.has_value() && value.max.has_value() && value.now.has_value());
132
177
  }
133
178
 
134
179
  bool expandableControl(const facebook::react::SharedViewProps props) {
@@ -174,14 +219,9 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
174
219
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
175
220
  if (props == nullptr)
176
221
  return UIA_E_ELEMENTNOTAVAILABLE;
177
- auto accessibilityRole =
178
- props->accessibilityRole.empty() ? compositionView->DefaultControlType() : props->accessibilityRole;
179
222
  // Invoke control pattern is used to support controls that do not maintain state
180
223
  // when activated but rather initiate or perform a single, unambiguous action.
181
- if (patternId == UIA_InvokePatternId &&
182
- (accessibilityRole == "button" || accessibilityRole == "imagebutton" || accessibilityRole == "link" ||
183
- accessibilityRole == "splitbutton" || (accessibilityRole == "menuitem" && props->onAccessibilityTap) ||
184
- (accessibilityRole == "treeitem" && props->onAccessibilityTap))) {
224
+ if (patternId == UIA_InvokePatternId && (props->onAccessibilityTap)) {
185
225
  *pRetVal = static_cast<IInvokeProvider *>(this);
186
226
  AddRef();
187
227
  }
@@ -192,14 +232,15 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
192
232
  }
193
233
 
194
234
  if (patternId == UIA_ValuePatternId &&
195
- (accessibilityRole == "textinput" || accessibilityRole == "searchbox" ||
196
- (accessibilityRole == "button" && accessibilityValueHasValue(props->accessibilityValue)) ||
197
- (accessibilityRole == "combobox" && accessibilityValueHasValue(props->accessibilityValue)) ||
198
- (accessibilityRole == "link" && accessibilityValueHasValue(props->accessibilityValue)) ||
199
- (accessibilityRole == "listitem" && accessibilityValueHasValue(props->accessibilityValue)) ||
200
- (accessibilityRole == "progressbar" && accessibilityValueHasValue(props->accessibilityValue)) ||
201
- (accessibilityRole == "adjustable" && accessibilityValueHasValue(props->accessibilityValue)) ||
202
- (accessibilityRole == "spinbutton" && accessibilityValueHasValue(props->accessibilityValue)))) {
235
+ ((strongView
236
+ .try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() &&
237
+ !accessibilityValueHasNumericValue(props->accessibilityValue)) ||
238
+ accessibilityValueHasTextValue(props->accessibilityValue))) {
239
+ *pRetVal = static_cast<IValueProvider *>(this);
240
+ AddRef();
241
+ }
242
+
243
+ if (patternId == UIA_RangeValuePatternId && accessibilityValueHasNumericValue(props->accessibilityValue)) {
203
244
  *pRetVal = static_cast<IValueProvider *>(this);
204
245
  AddRef();
205
246
  }
@@ -211,19 +252,38 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
211
252
  AddRef();
212
253
  }
213
254
 
214
- if (patternId == UIA_ExpandCollapsePatternId &&
215
- (accessibilityRole == "combobox" || accessibilityRole == "splitbutton" || accessibilityRole == "treeitem" ||
216
- (expandableControl(props) &&
217
- (accessibilityRole == "toolbar" || accessibilityRole == "menuitem" || accessibilityRole == "menubar" ||
218
- accessibilityRole == "listitem" || accessibilityRole == "group" || accessibilityRole == "button")))) {
255
+ if (patternId == UIA_ExpandCollapsePatternId && expandableControl(props)) {
219
256
  *pRetVal = static_cast<IExpandCollapseProvider *>(this);
220
257
  AddRef();
221
258
  }
222
259
 
260
+ if (patternId == UIA_SelectionPatternId && props->accessibilityState.has_value() &&
261
+ props->accessibilityState->multiselectable.has_value() && props->accessibilityState->required.has_value()) {
262
+ *pRetVal = static_cast<ISelectionProvider *>(this);
263
+ AddRef();
264
+ }
265
+
266
+ if (patternId == UIA_SelectionItemPatternId && props->accessibilityState.has_value() &&
267
+ props->accessibilityState->selected.has_value()) {
268
+ *pRetVal = static_cast<ISelectionItemProvider *>(this);
269
+ AddRef();
270
+ }
271
+
272
+ if (patternId == UIA_TextPatternId &&
273
+ (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
274
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>())) {
275
+ m_textProvider.as<IUnknown>().copy_to(pRetVal);
276
+ }
277
+
278
+ if (patternId == UIA_TextPattern2Id &&
279
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>()) {
280
+ m_textProvider.as<IUnknown>().copy_to(pRetVal);
281
+ }
282
+
223
283
  return S_OK;
224
284
  }
225
285
 
226
- long GetControlType(const std::string &role) noexcept {
286
+ long GetControlTypeFromString(const std::string &role) noexcept {
227
287
  if (role == "adjustable") {
228
288
  return UIA_SliderControlTypeId;
229
289
  } else if (role == "group" || role == "search" || role == "radiogroup" || role == "timer" || role.empty()) {
@@ -286,6 +346,96 @@ long GetControlType(const std::string &role) noexcept {
286
346
  return UIA_GroupControlTypeId;
287
347
  }
288
348
 
349
+ long GetControlTypeFromRole(const facebook::react::Role &role) noexcept {
350
+ switch (role) {
351
+ case facebook::react::Role::Alert:
352
+ return UIA_TextControlTypeId;
353
+ case facebook::react::Role::Application:
354
+ return UIA_WindowControlTypeId;
355
+ case facebook::react::Role::Button:
356
+ return UIA_ButtonControlTypeId;
357
+ case facebook::react::Role::Checkbox:
358
+ return UIA_CheckBoxControlTypeId;
359
+ case facebook::react::Role::Columnheader:
360
+ return UIA_HeaderControlTypeId;
361
+ case facebook::react::Role::Combobox:
362
+ return UIA_ComboBoxControlTypeId;
363
+ case facebook::react::Role::Document:
364
+ return UIA_DocumentControlTypeId;
365
+ case facebook::react::Role::Grid:
366
+ return UIA_GroupControlTypeId;
367
+ case facebook::react::Role::Group:
368
+ return UIA_GroupControlTypeId;
369
+ case facebook::react::Role::Heading:
370
+ return UIA_TextControlTypeId;
371
+ case facebook::react::Role::Img:
372
+ return UIA_ImageControlTypeId;
373
+ case facebook::react::Role::Link:
374
+ return UIA_HyperlinkControlTypeId;
375
+ case facebook::react::Role::List:
376
+ return UIA_ListControlTypeId;
377
+ case facebook::react::Role::Listitem:
378
+ return UIA_ListItemControlTypeId;
379
+ case facebook::react::Role::Menu:
380
+ return UIA_MenuControlTypeId;
381
+ case facebook::react::Role::Menubar:
382
+ return UIA_MenuBarControlTypeId;
383
+ case facebook::react::Role::Menuitem:
384
+ return UIA_MenuItemControlTypeId;
385
+ case facebook::react::Role::None:
386
+ return UIA_GroupControlTypeId;
387
+ case facebook::react::Role::Presentation:
388
+ return UIA_GroupControlTypeId;
389
+ case facebook::react::Role::Progressbar:
390
+ return UIA_ProgressBarControlTypeId;
391
+ case facebook::react::Role::Radio:
392
+ return UIA_RadioButtonControlTypeId;
393
+ case facebook::react::Role::Radiogroup:
394
+ return UIA_GroupControlTypeId;
395
+ case facebook::react::Role::Rowgroup:
396
+ return UIA_GroupControlTypeId;
397
+ case facebook::react::Role::Rowheader:
398
+ return UIA_HeaderControlTypeId;
399
+ case facebook::react::Role::Scrollbar:
400
+ return UIA_ScrollBarControlTypeId;
401
+ case facebook::react::Role::Searchbox:
402
+ return UIA_EditControlTypeId;
403
+ case facebook::react::Role::Separator:
404
+ return UIA_SeparatorControlTypeId;
405
+ case facebook::react::Role::Slider:
406
+ return UIA_SliderControlTypeId;
407
+ case facebook::react::Role::Spinbutton:
408
+ return UIA_SpinnerControlTypeId;
409
+ case facebook::react::Role::Status:
410
+ return UIA_StatusBarControlTypeId;
411
+ case facebook::react::Role::Summary:
412
+ return UIA_GroupControlTypeId;
413
+ case facebook::react::Role::Switch:
414
+ return UIA_ButtonControlTypeId;
415
+ case facebook::react::Role::Tab:
416
+ return UIA_TabItemControlTypeId;
417
+ case facebook::react::Role::Table:
418
+ return UIA_TableControlTypeId;
419
+ case facebook::react::Role::Tablist:
420
+ return UIA_TabControlTypeId;
421
+ case facebook::react::Role::Tabpanel:
422
+ return UIA_TabControlTypeId;
423
+ case facebook::react::Role::Timer:
424
+ return UIA_ButtonControlTypeId;
425
+ case facebook::react::Role::Toolbar:
426
+ return UIA_ToolBarControlTypeId;
427
+ case facebook::react::Role::Tooltip:
428
+ return UIA_ToolTipControlTypeId;
429
+ case facebook::react::Role::Tree:
430
+ return UIA_TreeControlTypeId;
431
+ case facebook::react::Role::Treegrid:
432
+ return UIA_TreeControlTypeId;
433
+ case facebook::react::Role::Treeitem:
434
+ return UIA_TreeItemControlTypeId;
435
+ }
436
+ return UIA_GroupControlTypeId;
437
+ }
438
+
289
439
  HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERTYID propertyId, VARIANT *pRetVal) {
290
440
  if (pRetVal == nullptr)
291
441
  return E_POINTER;
@@ -311,8 +461,10 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
311
461
  switch (propertyId) {
312
462
  case UIA_ControlTypePropertyId: {
313
463
  pRetVal->vt = VT_I4;
314
- auto role = props->accessibilityRole.empty() ? compositionView->DefaultControlType() : props->accessibilityRole;
315
- pRetVal->lVal = GetControlType(role);
464
+ pRetVal->lVal = props->role == facebook::react::Role::None ? props->accessibilityRole.empty()
465
+ ? GetControlTypeFromString(compositionView->DefaultControlType())
466
+ : GetControlTypeFromString(props->accessibilityRole)
467
+ : GetControlTypeFromRole(props->role);
316
468
  break;
317
469
  }
318
470
  case UIA_AutomationIdPropertyId: {
@@ -352,17 +504,24 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
352
504
  }
353
505
  case UIA_IsContentElementPropertyId: {
354
506
  pRetVal->vt = VT_BOOL;
355
- pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE;
507
+ pRetVal->boolVal =
508
+ (props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
509
+ ? VARIANT_TRUE
510
+ : VARIANT_FALSE;
356
511
  break;
357
512
  }
358
513
  case UIA_IsControlElementPropertyId: {
359
514
  pRetVal->vt = VT_BOOL;
360
- pRetVal->boolVal = (props->accessible && props->accessibilityRole != "none") ? VARIANT_TRUE : VARIANT_FALSE;
515
+ pRetVal->boolVal =
516
+ (props->accessible && (props->accessibilityRole != "none" || props->role != facebook::react::Role::None))
517
+ ? VARIANT_TRUE
518
+ : VARIANT_FALSE;
361
519
  break;
362
520
  }
363
521
  case UIA_IsOffscreenPropertyId: {
364
522
  pRetVal->vt = VT_BOOL;
365
523
  pRetVal->boolVal = (compositionView->getClipState() == ClipState::FullyClipped) ? VARIANT_TRUE : VARIANT_FALSE;
524
+ break;
366
525
  }
367
526
  case UIA_HelpTextPropertyId: {
368
527
  pRetVal->vt = VT_BSTR;
@@ -471,6 +630,8 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::SetValue(LPCWSTR val) {
471
630
 
472
631
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)
473
632
  ->setAcccessiblityValue(winrt::to_string(val));
633
+ // TODO: Edit once/if onAccessibilityAction props supports returning UIA event data. See
634
+ // https://github.com/react-native-community/discussions-and-proposals/issues/843.
474
635
  DispatchAccessibilityAction(m_view, "setValue");
475
636
  return S_OK;
476
637
  }
@@ -501,23 +662,86 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsReadOnly(BOOL *pRe
501
662
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
502
663
  if (props == nullptr)
503
664
  return UIA_E_ELEMENTNOTAVAILABLE;
504
- auto accessibilityRole = props->accessibilityRole;
505
- if (accessibilityRole.empty()) {
506
- // Control is using default control type. Use default IsReadOnly value.
507
- *pRetVal = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)
508
- ->getAcccessiblityIsReadOnly();
509
- } else if (
510
- accessibilityRole == "textinput" || accessibilityRole == "searchbox" || accessibilityRole == "adjustable" ||
511
- accessibilityRole == "spinbutton" || accessibilityRole == "combobox") {
512
- // Control is using customized control type which should not be IsReadOnly for value pattern.
513
- *pRetVal = false;
665
+ if (props->accessibilityState.has_value() && props->accessibilityState->readOnly.has_value()) {
666
+ *pRetVal = props->accessibilityState->readOnly.value();
514
667
  } else {
515
- // Control is using customized control type which should be IsReadOnly for value pattern.
516
- *pRetVal = true;
668
+ // Use default IsReadOnly value.
669
+ *pRetVal = false;
517
670
  }
518
671
  return S_OK;
519
672
  }
520
673
 
674
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_LargeChange(double *pRetVal) {
675
+ // no-op
676
+ return S_OK;
677
+ }
678
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_Maximum(double *pRetVal) {
679
+ if (pRetVal == nullptr)
680
+ return E_POINTER;
681
+ auto strongView = m_view.view();
682
+
683
+ if (!strongView)
684
+ return UIA_E_ELEMENTNOTAVAILABLE;
685
+
686
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
687
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
688
+
689
+ if (props == nullptr)
690
+ return UIA_E_ELEMENTNOTAVAILABLE;
691
+
692
+ *pRetVal = props->accessibilityValue.max.value();
693
+ return S_OK;
694
+ }
695
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_Minimum(double *pRetVal) {
696
+ if (pRetVal == nullptr)
697
+ return E_POINTER;
698
+ auto strongView = m_view.view();
699
+
700
+ if (!strongView)
701
+ return UIA_E_ELEMENTNOTAVAILABLE;
702
+
703
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
704
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
705
+
706
+ if (props == nullptr)
707
+ return UIA_E_ELEMENTNOTAVAILABLE;
708
+
709
+ *pRetVal = props->accessibilityValue.min.value();
710
+ return S_OK;
711
+ }
712
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_SmallChange(double *pRetVal) {
713
+ // no-op
714
+ return S_OK;
715
+ }
716
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_Value(double *pRetVal) {
717
+ if (pRetVal == nullptr)
718
+ return E_POINTER;
719
+ auto strongView = m_view.view();
720
+
721
+ if (!strongView)
722
+ return UIA_E_ELEMENTNOTAVAILABLE;
723
+
724
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
725
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
726
+
727
+ if (props == nullptr)
728
+ return UIA_E_ELEMENTNOTAVAILABLE;
729
+
730
+ *pRetVal = props->accessibilityValue.now.value();
731
+ return S_OK;
732
+ }
733
+ HRESULT __stdcall CompositionDynamicAutomationProvider::SetValue(double val) {
734
+ auto strongView = m_view.view();
735
+
736
+ if (!strongView)
737
+ return UIA_E_ELEMENTNOTAVAILABLE;
738
+
739
+ // TODO: Edit once/if onAccessibilityAction props supports returning UIA event data. See
740
+ // https://github.com/react-native-community/discussions-and-proposals/issues/843.
741
+ DispatchAccessibilityAction(m_view, "setValue");
742
+ return S_OK;
743
+ }
744
+
521
745
  HRESULT __stdcall CompositionDynamicAutomationProvider::get_ToggleState(ToggleState *pRetVal) {
522
746
  if (pRetVal == nullptr)
523
747
  return E_POINTER;
@@ -585,4 +809,169 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Collapse() {
585
809
  return S_OK;
586
810
  }
587
811
 
812
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_CanSelectMultiple(BOOL *pRetVal) {
813
+ if (pRetVal == nullptr)
814
+ return E_POINTER;
815
+ auto strongView = m_view.view();
816
+
817
+ if (!strongView)
818
+ return UIA_E_ELEMENTNOTAVAILABLE;
819
+
820
+ auto props =
821
+ std::static_pointer_cast<const facebook::react::ViewProps>(winrt::get_self<ComponentView>(strongView)->props());
822
+
823
+ if (props == nullptr)
824
+ return UIA_E_ELEMENTNOTAVAILABLE;
825
+
826
+ *pRetVal = (props->accessibilityState.has_value() && props->accessibilityState->multiselectable.has_value())
827
+ ? props->accessibilityState->multiselectable.value()
828
+ : false;
829
+
830
+ return S_OK;
831
+ }
832
+
833
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsSelectionRequired(BOOL *pRetVal) {
834
+ if (pRetVal == nullptr)
835
+ return E_POINTER;
836
+ auto strongView = m_view.view();
837
+
838
+ if (!strongView)
839
+ return UIA_E_ELEMENTNOTAVAILABLE;
840
+
841
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
842
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
843
+
844
+ if (props == nullptr)
845
+ return UIA_E_ELEMENTNOTAVAILABLE;
846
+
847
+ *pRetVal = (props->accessibilityState.has_value() && props->accessibilityState->required.has_value())
848
+ ? props->accessibilityState->required.value()
849
+ : false;
850
+
851
+ return S_OK;
852
+ }
853
+
854
+ HRESULT __stdcall CompositionDynamicAutomationProvider::GetSelection(SAFEARRAY **pRetVal) {
855
+ auto strongView = m_view.view();
856
+
857
+ if (!strongView)
858
+ return UIA_E_ELEMENTNOTAVAILABLE;
859
+
860
+ std::vector<int> selectedItems;
861
+ for (size_t i = 0; i < m_selectionItems.size(); i++) {
862
+ auto selectionItem = m_selectionItems.at(i);
863
+ auto provider = selectionItem.as<CompositionDynamicAutomationProvider>();
864
+ BOOL selected;
865
+ auto hr = provider->get_IsSelected(&selected);
866
+ if (hr == S_OK && selected) {
867
+ selectedItems.push_back(int(i));
868
+ }
869
+ }
870
+
871
+ *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, ULONG(selectedItems.size()));
872
+ if (*pRetVal == nullptr)
873
+ return E_OUTOFMEMORY;
874
+
875
+ for (size_t i = 0; i < selectedItems.size(); i++) {
876
+ auto pos = static_cast<long>(i);
877
+ SafeArrayPutElement(*pRetVal, &pos, m_selectionItems.at(selectedItems.at(i)).get());
878
+ }
879
+ return S_OK;
880
+ }
881
+
882
+ void CompositionDynamicAutomationProvider::AddToSelectionItems(winrt::com_ptr<IRawElementProviderSimple> &item) {
883
+ if (std::find(m_selectionItems.begin(), m_selectionItems.end(), item) != m_selectionItems.end()) {
884
+ return;
885
+ }
886
+ m_selectionItems.push_back(item);
887
+ }
888
+
889
+ void CompositionDynamicAutomationProvider::RemoveFromSelectionItems(winrt::com_ptr<IRawElementProviderSimple> &item) {
890
+ std::erase(m_selectionItems, item);
891
+ }
892
+
893
+ HRESULT __stdcall CompositionDynamicAutomationProvider::AddToSelection() {
894
+ auto strongView = m_view.view();
895
+
896
+ if (!strongView)
897
+ return UIA_E_ELEMENTNOTAVAILABLE;
898
+
899
+ DispatchAccessibilityAction(m_view, "addToSelection");
900
+ return S_OK;
901
+ }
902
+
903
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_IsSelected(BOOL *pRetVal) {
904
+ if (pRetVal == nullptr)
905
+ return E_POINTER;
906
+ auto strongView = m_view.view();
907
+
908
+ if (!strongView)
909
+ return UIA_E_ELEMENTNOTAVAILABLE;
910
+
911
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
912
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
913
+
914
+ if (props == nullptr)
915
+ return UIA_E_ELEMENTNOTAVAILABLE;
916
+
917
+ *pRetVal = (props->accessibilityState.has_value() && props->accessibilityState->selected.has_value())
918
+ ? props->accessibilityState->selected.value()
919
+ : false;
920
+
921
+ return S_OK;
922
+ }
923
+
924
+ IRawElementProviderSimple *findSelectionContainer(winrt::Microsoft::ReactNative::ComponentView current) {
925
+ if (!current)
926
+ return nullptr;
927
+
928
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
929
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(current)->props());
930
+ if (props->accessibilityState.has_value() && props->accessibilityState->multiselectable.has_value() &&
931
+ props->accessibilityState->required.has_value()) {
932
+ auto uiaProvider =
933
+ current.as<winrt::Microsoft::ReactNative::Composition::implementation::ComponentView>()->EnsureUiaProvider();
934
+ if (uiaProvider != nullptr) {
935
+ auto spProviderSimple = uiaProvider.try_as<IRawElementProviderSimple>();
936
+ if (spProviderSimple != nullptr) {
937
+ spProviderSimple->AddRef();
938
+ return spProviderSimple.get();
939
+ }
940
+ }
941
+ } else {
942
+ return findSelectionContainer(current.Parent());
943
+ }
944
+ return nullptr;
945
+ }
946
+
947
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_SelectionContainer(IRawElementProviderSimple **pRetVal) {
948
+ if (pRetVal == nullptr)
949
+ return E_POINTER;
950
+ auto strongView = m_view.view();
951
+
952
+ if (!strongView)
953
+ return UIA_E_ELEMENTNOTAVAILABLE;
954
+
955
+ *pRetVal = findSelectionContainer(strongView.Parent());
956
+ return S_OK;
957
+ }
958
+
959
+ HRESULT __stdcall CompositionDynamicAutomationProvider::RemoveFromSelection() {
960
+ auto strongView = m_view.view();
961
+
962
+ if (!strongView)
963
+ return UIA_E_ELEMENTNOTAVAILABLE;
964
+ DispatchAccessibilityAction(m_view, "removeFromSelection");
965
+ return S_OK;
966
+ }
967
+
968
+ HRESULT __stdcall CompositionDynamicAutomationProvider::Select() {
969
+ auto strongView = m_view.view();
970
+
971
+ if (!strongView)
972
+ return UIA_E_ELEMENTNOTAVAILABLE;
973
+ DispatchAccessibilityAction(m_view, "select");
974
+ return S_OK;
975
+ }
976
+
588
977
  } // namespace winrt::Microsoft::ReactNative::implementation