react-native-windows 0.81.2 → 0.81.4

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 (66) hide show
  1. package/Libraries/Components/Pressable/Pressable.d.ts +8 -0
  2. package/Libraries/Components/Pressable/Pressable.windows.js +21 -2
  3. package/Microsoft.ReactNative/ABIViewManager.cpp +12 -1
  4. package/Microsoft.ReactNative/CompositionSwitcher.idl +16 -9
  5. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +26 -0
  6. package/Microsoft.ReactNative/Fabric/ComponentView.h +2 -0
  7. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.cpp +0 -1
  8. package/Microsoft.ReactNative/Fabric/Composition/CompositionAnnotationProvider.cpp +2 -5
  9. package/Microsoft.ReactNative/Fabric/Composition/CompositionAnnotationProvider.h +1 -4
  10. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +15 -0
  11. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +65 -32
  12. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +9 -0
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +8 -0
  14. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +2 -1
  15. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp +4 -7
  16. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h +1 -5
  17. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp +68 -53
  18. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h +1 -5
  19. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +98 -15
  20. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +10 -3
  21. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +73 -10
  22. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +11 -1
  23. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +3 -2
  24. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.cpp +0 -1
  25. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +609 -4
  26. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.h +63 -0
  27. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +8 -0
  28. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +3 -0
  29. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +53 -2
  30. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +8 -1
  31. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +0 -1
  32. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +0 -1
  33. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +3 -1
  34. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +6 -0
  35. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +1 -1
  36. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +36 -14
  37. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +0 -1
  38. package/Microsoft.ReactNative/Fabric/ReactTaggedView.h +1 -1
  39. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.h +2 -1
  40. package/Microsoft.ReactNative/IReactViewComponentBuilder.idl +8 -0
  41. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -0
  42. package/Microsoft.ReactNative/Modules/ImageViewManagerModule.cpp +41 -15
  43. package/Microsoft.ReactNative/Utils/IcuUtils.cpp +84 -0
  44. package/Microsoft.ReactNative/Utils/IcuUtils.h +42 -0
  45. package/Microsoft.ReactNative.Cxx/StructInfo.h +8 -1
  46. package/Mso/src/dispatchQueue/queueService.cpp +3 -1
  47. package/Mso/src/dispatchQueue/uiScheduler_winrt.cpp +2 -1
  48. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  49. package/Shared/Networking/OriginPolicyHttpFilter.cpp +2 -1
  50. package/Shared/Shared.vcxitems +1 -0
  51. package/Shared/Shared.vcxitems.filters +1 -0
  52. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +14 -0
  53. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +34 -20
  54. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +14 -0
  55. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +14 -0
  56. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +18 -4
  57. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +18 -4
  58. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +14 -0
  59. package/codegen/react/components/rnwcore/InputAccessory.g.h +14 -0
  60. package/codegen/react/components/rnwcore/ModalHostView.g.h +32 -18
  61. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +18 -4
  62. package/codegen/react/components/rnwcore/SafeAreaView.g.h +14 -0
  63. package/codegen/react/components/rnwcore/Switch.g.h +18 -4
  64. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +14 -0
  65. package/codegen/react/components/rnwcore/VirtualView.g.h +48 -6
  66. package/package.json +3 -3
@@ -11,18 +11,14 @@
11
11
  namespace winrt::Microsoft::ReactNative::implementation {
12
12
 
13
13
  CompositionTextRangeProvider::CompositionTextRangeProvider(
14
- const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
15
- CompositionDynamicAutomationProvider *parentProvider) noexcept
16
- : m_view{componentView} {
17
- m_parentProvider.copy_from(parentProvider);
18
- }
14
+ const winrt::Microsoft::ReactNative::ComponentView &componentView) noexcept
15
+ : m_view{componentView} {}
19
16
 
20
17
  HRESULT __stdcall CompositionTextRangeProvider::Clone(ITextRangeProvider **pRetVal) {
21
18
  if (pRetVal == nullptr)
22
19
  return E_POINTER;
23
20
 
24
- auto clone = winrt::make<winrt::Microsoft::ReactNative::implementation::CompositionTextRangeProvider>(
25
- m_view.view().as<winrt::Microsoft::ReactNative::Composition::ComponentView>(), m_parentProvider.get());
21
+ auto clone = winrt::make<winrt::Microsoft::ReactNative::implementation::CompositionTextRangeProvider>(m_view.view());
26
22
  *pRetVal = clone.detach();
27
23
  return S_OK;
28
24
  }
@@ -91,13 +87,13 @@ HRESULT __stdcall CompositionTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEI
91
87
  if (!strongView)
92
88
  return UIA_E_ELEMENTNOTAVAILABLE;
93
89
 
94
- auto props = std::static_pointer_cast<const facebook::react::ParagraphProps>(
90
+ auto props = std::static_pointer_cast<const facebook::react::BaseViewProps>(
95
91
  winrt::get_self<ComponentView>(strongView)->props());
96
92
 
97
- auto textinputProps = std::static_pointer_cast<const facebook::react::WindowsTextInputProps>(
98
- winrt::get_self<ComponentView>(strongView)->props());
93
+ auto asParagraph =
94
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>();
99
95
 
100
- auto isTextInput =
96
+ auto asTextInput =
101
97
  strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>();
102
98
 
103
99
  if (props == nullptr)
@@ -106,15 +102,16 @@ HRESULT __stdcall CompositionTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEI
106
102
  if (attributeId == UIA_BackgroundColorAttributeId) {
107
103
  pRetVal->vt = VT_I4;
108
104
  pRetVal->lVal = (*props->backgroundColor).AsColorRefWithAlpha();
109
- } else if (attributeId == UIA_CapStyleAttributeId) {
105
+ } else if (attributeId == UIA_CapStyleAttributeId && asParagraph) {
110
106
  pRetVal->vt = VT_I4;
111
107
  auto fontVariant = facebook::react::FontVariant::Default;
112
108
  auto textTransform = facebook::react::TextTransform::None;
113
- if (props->textAttributes.fontVariant.has_value()) {
114
- fontVariant = props->textAttributes.fontVariant.value();
109
+
110
+ if (asParagraph->paragraphProps().textAttributes.fontVariant.has_value()) {
111
+ fontVariant = asParagraph->paragraphProps().textAttributes.fontVariant.value();
115
112
  }
116
- if (props->textAttributes.textTransform.has_value()) {
117
- textTransform = props->textAttributes.textTransform.value();
113
+ if (asParagraph->paragraphProps().textAttributes.textTransform.has_value()) {
114
+ textTransform = asParagraph->paragraphProps().textAttributes.textTransform.value();
118
115
  }
119
116
  if (fontVariant == facebook::react::FontVariant::SmallCaps) {
120
117
  pRetVal->lVal = CapStyle_SmallCap;
@@ -125,39 +122,44 @@ HRESULT __stdcall CompositionTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEI
125
122
  } else if (textTransform == facebook::react::TextTransform::Uppercase) {
126
123
  pRetVal->lVal = CapStyle_AllCap;
127
124
  }
128
- } else if (attributeId == UIA_FontNameAttributeId) {
125
+ } else if (attributeId == UIA_FontNameAttributeId && asParagraph) {
129
126
  pRetVal->vt = VT_BSTR;
130
- auto fontName = props->textAttributes.fontFamily;
127
+ auto fontName = asParagraph->paragraphProps().textAttributes.fontFamily;
131
128
  if (fontName.empty()) {
132
129
  fontName = "Segoe UI";
133
130
  }
134
131
  std::wstring wfontName(fontName.begin(), fontName.end());
135
132
  pRetVal->bstrVal = SysAllocString(wfontName.c_str());
136
- } else if (attributeId == UIA_FontSizeAttributeId) {
133
+ } else if (attributeId == UIA_FontSizeAttributeId && asParagraph) {
137
134
  pRetVal->vt = VT_R8;
138
- pRetVal->dblVal = props->textAttributes.fontSize;
139
- } else if (attributeId == UIA_FontWeightAttributeId) {
140
- if (props->textAttributes.fontWeight.has_value()) {
135
+ pRetVal->dblVal = asParagraph->paragraphProps().textAttributes.fontSize;
136
+ } else if (attributeId == UIA_FontWeightAttributeId && asParagraph) {
137
+ if (asParagraph->paragraphProps().textAttributes.fontWeight.has_value()) {
141
138
  pRetVal->vt = VT_I4;
142
- pRetVal->lVal = static_cast<long>(props->textAttributes.fontWeight.value());
139
+ pRetVal->lVal = static_cast<long>(asParagraph->paragraphProps().textAttributes.fontWeight.value());
143
140
  }
144
- } else if (attributeId == UIA_ForegroundColorAttributeId) {
141
+ } else if (attributeId == UIA_ForegroundColorAttributeId && asParagraph) {
145
142
  pRetVal->vt = VT_I4;
146
- pRetVal->lVal = (*props->textAttributes.foregroundColor).AsColorRefWithAlpha();
147
- } else if (attributeId == UIA_IsItalicAttributeId) {
143
+ pRetVal->lVal = (*asParagraph->paragraphProps().textAttributes.foregroundColor).AsColorRefWithAlpha();
144
+ } else if (attributeId == UIA_IsItalicAttributeId && asParagraph) {
148
145
  pRetVal->vt = VT_BOOL;
149
- pRetVal->boolVal = (props->textAttributes.fontStyle.has_value() &&
150
- props->textAttributes.fontStyle.value() == facebook::react::FontStyle::Italic)
146
+ pRetVal->boolVal =
147
+ (asParagraph->paragraphProps().textAttributes.fontStyle.has_value() &&
148
+ asParagraph->paragraphProps().textAttributes.fontStyle.value() == facebook::react::FontStyle::Italic)
151
149
  ? VARIANT_TRUE
152
150
  : VARIANT_FALSE;
153
151
  } else if (attributeId == UIA_IsReadOnlyAttributeId) {
154
152
  pRetVal->vt = VT_BOOL;
155
- pRetVal->boolVal = isTextInput ? textinputProps->editable ? VARIANT_FALSE : VARIANT_TRUE : VARIANT_TRUE;
156
- } else if (attributeId == UIA_HorizontalTextAlignmentAttributeId) {
153
+ if (asTextInput) {
154
+ pRetVal->boolVal = asTextInput->windowsTextInputProps().editable ? VARIANT_FALSE : VARIANT_TRUE;
155
+ } else {
156
+ pRetVal->boolVal = VARIANT_TRUE;
157
+ }
158
+ } else if (attributeId == UIA_HorizontalTextAlignmentAttributeId && asParagraph) {
157
159
  pRetVal->vt = VT_I4;
158
160
  auto textAlign = facebook::react::TextAlignment::Center;
159
- if (props->textAttributes.alignment.has_value()) {
160
- textAlign = props->textAttributes.alignment.value();
161
+ if (asParagraph->paragraphProps().textAttributes.alignment.has_value()) {
162
+ textAlign = asParagraph->paragraphProps().textAttributes.alignment.value();
161
163
  }
162
164
  if (textAlign == facebook::react::TextAlignment::Left) {
163
165
  pRetVal->lVal = HorizontalTextAlignment_Left;
@@ -170,40 +172,42 @@ HRESULT __stdcall CompositionTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEI
170
172
  } else if (textAlign == facebook::react::TextAlignment::Natural) {
171
173
  pRetVal->lVal = HorizontalTextAlignment_Left;
172
174
  }
173
- } else if (attributeId == UIA_StrikethroughColorAttributeId) {
174
- if (props->textAttributes.textDecorationLineType.has_value() &&
175
- (props->textAttributes.textDecorationLineType.value() ==
175
+ } else if (attributeId == UIA_StrikethroughColorAttributeId && asParagraph) {
176
+ if (asParagraph->paragraphProps().textAttributes.textDecorationLineType.has_value() &&
177
+ (asParagraph->paragraphProps().textAttributes.textDecorationLineType.value() ==
176
178
  facebook::react::TextDecorationLineType::Strikethrough ||
177
- props->textAttributes.textDecorationLineType.value() ==
179
+ asParagraph->paragraphProps().textAttributes.textDecorationLineType.value() ==
178
180
  facebook::react::TextDecorationLineType::UnderlineStrikethrough)) {
179
181
  pRetVal->vt = VT_I4;
180
- pRetVal->lVal = (*props->textAttributes.textDecorationColor).AsColorRefWithAlpha();
182
+ pRetVal->lVal = (*asParagraph->paragraphProps().textAttributes.textDecorationColor).AsColorRefWithAlpha();
181
183
  }
182
- } else if (attributeId == UIA_StrikethroughStyleAttributeId) {
183
- if (props->textAttributes.textDecorationLineType.has_value() &&
184
- (props->textAttributes.textDecorationLineType.value() ==
184
+ } else if (attributeId == UIA_StrikethroughStyleAttributeId && asParagraph) {
185
+ if (asParagraph->paragraphProps().textAttributes.textDecorationLineType.has_value() &&
186
+ (asParagraph->paragraphProps().textAttributes.textDecorationLineType.value() ==
185
187
  facebook::react::TextDecorationLineType::Strikethrough ||
186
- props->textAttributes.textDecorationLineType.value() ==
188
+ asParagraph->paragraphProps().textAttributes.textDecorationLineType.value() ==
187
189
  facebook::react::TextDecorationLineType::UnderlineStrikethrough)) {
188
190
  pRetVal->vt = VT_I4;
189
- auto style = props->textAttributes.textDecorationStyle.value();
191
+ auto style = asParagraph->paragraphProps().textAttributes.textDecorationStyle.value();
190
192
  pRetVal->lVal = GetTextDecorationLineStyle(style);
191
193
  }
192
- } else if (attributeId == UIA_UnderlineColorAttributeId) {
193
- if (props->textAttributes.textDecorationLineType.has_value() &&
194
- (props->textAttributes.textDecorationLineType.value() == facebook::react::TextDecorationLineType::Underline ||
195
- props->textAttributes.textDecorationLineType.value() ==
194
+ } else if (attributeId == UIA_UnderlineColorAttributeId && asParagraph) {
195
+ if (asParagraph->paragraphProps().textAttributes.textDecorationLineType.has_value() &&
196
+ (asParagraph->paragraphProps().textAttributes.textDecorationLineType.value() ==
197
+ facebook::react::TextDecorationLineType::Underline ||
198
+ asParagraph->paragraphProps().textAttributes.textDecorationLineType.value() ==
196
199
  facebook::react::TextDecorationLineType::UnderlineStrikethrough)) {
197
200
  pRetVal->vt = VT_I4;
198
- pRetVal->lVal = (*props->textAttributes.textDecorationColor).AsColorRefWithAlpha();
201
+ pRetVal->lVal = (*asParagraph->paragraphProps().textAttributes.textDecorationColor).AsColorRefWithAlpha();
199
202
  }
200
- } else if (attributeId == UIA_UnderlineStyleAttributeId) {
201
- if (props->textAttributes.textDecorationLineType.has_value() &&
202
- (props->textAttributes.textDecorationLineType.value() == facebook::react::TextDecorationLineType::Underline ||
203
- props->textAttributes.textDecorationLineType.value() ==
203
+ } else if (attributeId == UIA_UnderlineStyleAttributeId && asParagraph) {
204
+ if (asParagraph->paragraphProps().textAttributes.textDecorationLineType.has_value() &&
205
+ (asParagraph->paragraphProps().textAttributes.textDecorationLineType.value() ==
206
+ facebook::react::TextDecorationLineType::Underline ||
207
+ asParagraph->paragraphProps().textAttributes.textDecorationLineType.value() ==
204
208
  facebook::react::TextDecorationLineType::UnderlineStrikethrough)) {
205
209
  pRetVal->vt = VT_I4;
206
- auto style = props->textAttributes.textDecorationStyle.value();
210
+ auto style = asParagraph->paragraphProps().textAttributes.textDecorationStyle.value();
207
211
  pRetVal->lVal = GetTextDecorationLineStyle(style);
208
212
  }
209
213
  }
@@ -214,7 +218,18 @@ HRESULT __stdcall CompositionTextRangeProvider::GetBoundingRectangles(SAFEARRAY
214
218
  if (pRetVal == nullptr)
215
219
  return E_POINTER;
216
220
  UiaRect rect;
217
- auto hr = m_parentProvider->get_BoundingRectangle(&rect);
221
+
222
+ auto strongView = m_view.view();
223
+ if (!strongView)
224
+ return UIA_E_ELEMENTNOTAVAILABLE;
225
+
226
+ auto componentView = strongView.as<winrt::Microsoft::ReactNative::implementation::ComponentView>();
227
+ auto provider = componentView->EnsureUiaProvider();
228
+ auto repf = provider.try_as<IRawElementProviderFragment>();
229
+ if (!repf)
230
+ return E_FAIL;
231
+
232
+ auto hr = repf->get_BoundingRectangle(&rect);
218
233
  if (FAILED(hr))
219
234
  return hr;
220
235
  *pRetVal = SafeArrayCreateVector(VT_R8, 0, 4);
@@ -1,6 +1,5 @@
1
1
  #pragma once
2
2
 
3
- #include <Fabric/Composition/CompositionDynamicAutomationProvider.h>
4
3
  #include <Fabric/Composition/CompositionTextProvider.h>
5
4
  #include <Fabric/Composition/CompositionViewComponentView.h>
6
5
  #include <Fabric/ReactTaggedView.h>
@@ -12,9 +11,7 @@ namespace winrt::Microsoft::ReactNative::implementation {
12
11
 
13
12
  class CompositionTextRangeProvider : public winrt::implements<CompositionTextRangeProvider, ITextRangeProvider> {
14
13
  public:
15
- CompositionTextRangeProvider(
16
- const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView,
17
- CompositionDynamicAutomationProvider *parentProvider) noexcept;
14
+ CompositionTextRangeProvider(const winrt::Microsoft::ReactNative::ComponentView &componentView) noexcept;
18
15
 
19
16
  // inherited via ITextRangeProvider
20
17
  virtual HRESULT __stdcall Clone(ITextRangeProvider **pRetVal) override;
@@ -53,7 +50,6 @@ class CompositionTextRangeProvider : public winrt::implements<CompositionTextRan
53
50
 
54
51
  private:
55
52
  ::Microsoft::ReactNative::ReactTaggedView m_view;
56
- winrt::com_ptr<CompositionDynamicAutomationProvider> m_parentProvider;
57
53
  };
58
54
 
59
55
  } // namespace winrt::Microsoft::ReactNative::implementation
@@ -710,7 +710,86 @@ void ComponentView::applyShadowProps(const facebook::react::ViewProps &viewProps
710
710
  shadow.Color(theme()->Color(*viewProps.shadowColor));
711
711
  }
712
712
 
713
- Visual().as<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual>().Shadow(shadow);
713
+ // Check if any border radius is set
714
+ auto borderMetrics = BorderPrimitive::resolveAndAlignBorderMetrics(m_layoutMetrics, viewProps);
715
+ bool hasBorderRadius = borderMetrics.borderRadii.topLeft.horizontal != 0 ||
716
+ borderMetrics.borderRadii.topRight.horizontal != 0 || borderMetrics.borderRadii.bottomLeft.horizontal != 0 ||
717
+ borderMetrics.borderRadii.bottomRight.horizontal != 0 || borderMetrics.borderRadii.topLeft.vertical != 0 ||
718
+ borderMetrics.borderRadii.topRight.vertical != 0 || borderMetrics.borderRadii.bottomLeft.vertical != 0 ||
719
+ borderMetrics.borderRadii.bottomRight.vertical != 0;
720
+
721
+ if (hasBorderRadius) {
722
+ // When borderRadius is set, we need to create a shadow mask that follows the rounded rectangle shape.
723
+ // Use CompositionVisualSurface to capture the clipped visual's appearance as the shadow mask.
724
+ bool maskSet = false;
725
+
726
+ // Try Microsoft (WinUI3) Composition first
727
+ auto msCompositor =
728
+ winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::InnerCompositor(
729
+ m_compContext);
730
+ if (msCompositor) {
731
+ auto innerVisual =
732
+ winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::InnerVisual(
733
+ Visual());
734
+ if (innerVisual) {
735
+ // Create a VisualSurface that captures the visual (with its clip applied)
736
+ auto visualSurface = msCompositor.CreateVisualSurface();
737
+ visualSurface.SourceVisual(innerVisual);
738
+ visualSurface.SourceSize(
739
+ {m_layoutMetrics.frame.size.width * m_layoutMetrics.pointScaleFactor,
740
+ m_layoutMetrics.frame.size.height * m_layoutMetrics.pointScaleFactor});
741
+
742
+ // Create a brush from the visual surface to use as shadow mask
743
+ auto maskBrush = msCompositor.CreateSurfaceBrush(visualSurface);
744
+ maskBrush.Stretch(winrt::Microsoft::UI::Composition::CompositionStretch::Fill);
745
+
746
+ // Get the inner shadow and set the mask
747
+ auto innerShadow = winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::
748
+ InnerDropShadow(shadow);
749
+ if (innerShadow) {
750
+ innerShadow.Mask(maskBrush);
751
+ maskSet = true;
752
+ }
753
+ }
754
+ }
755
+
756
+ // Fallback to System (Windows.UI) Composition if Microsoft Composition is not available
757
+ if (!maskSet) {
758
+ auto sysCompositor =
759
+ winrt::Microsoft::ReactNative::Composition::Experimental::SystemCompositionContextHelper::InnerCompositor(
760
+ m_compContext);
761
+ if (sysCompositor) {
762
+ auto innerVisual =
763
+ winrt::Microsoft::ReactNative::Composition::Experimental::SystemCompositionContextHelper::InnerVisual(
764
+ Visual());
765
+ if (innerVisual) {
766
+ auto visualSurface = sysCompositor.CreateVisualSurface();
767
+ visualSurface.SourceVisual(innerVisual);
768
+ visualSurface.SourceSize(
769
+ {m_layoutMetrics.frame.size.width * m_layoutMetrics.pointScaleFactor,
770
+ m_layoutMetrics.frame.size.height * m_layoutMetrics.pointScaleFactor});
771
+
772
+ auto maskBrush = sysCompositor.CreateSurfaceBrush(visualSurface);
773
+ maskBrush.Stretch(winrt::Windows::UI::Composition::CompositionStretch::Fill);
774
+
775
+ auto innerShadow =
776
+ winrt::Microsoft::ReactNative::Composition::Experimental::SystemCompositionContextHelper::InnerDropShadow(
777
+ shadow);
778
+ if (innerShadow) {
779
+ innerShadow.Mask(maskBrush);
780
+ }
781
+ }
782
+ }
783
+ }
784
+
785
+ // Apply shadow to OuterVisual (which is not clipped) so the shadow can extend beyond the clip
786
+ OuterVisual().as<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual>().Shadow(shadow);
787
+ Visual().as<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual>().Shadow(nullptr);
788
+ } else {
789
+ // No border radius - apply shadow directly to Visual (original behavior)
790
+ Visual().as<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual>().Shadow(shadow);
791
+ OuterVisual().as<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual>().Shadow(nullptr);
792
+ }
714
793
  }
715
794
 
716
795
  void ComponentView::updateTransformProps(
@@ -801,8 +880,8 @@ void ComponentView::updateAccessibilityProps(
801
880
  winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
802
881
  EnsureUiaProvider(),
803
882
  UIA_LiveSettingPropertyId,
804
- oldViewProps.accessibilityLiveRegion,
805
- newViewProps.accessibilityLiveRegion);
883
+ winrt::Microsoft::ReactNative::implementation::GetLiveSetting(oldViewProps.accessibilityLiveRegion),
884
+ winrt::Microsoft::ReactNative::implementation::GetLiveSetting(newViewProps.accessibilityLiveRegion));
806
885
 
807
886
  winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
808
887
  EnsureUiaProvider(), UIA_LevelPropertyId, oldViewProps.accessibilityLevel, newViewProps.accessibilityLevel);
@@ -857,14 +936,13 @@ void ComponentView::updateAccessibilityProps(
857
936
 
858
937
  if ((oldViewProps.accessibilityState.has_value() && oldViewProps.accessibilityState->selected.has_value()) !=
859
938
  ((newViewProps.accessibilityState.has_value() && newViewProps.accessibilityState->selected.has_value()))) {
860
- auto compProvider =
861
- EnsureUiaProvider()
862
- .try_as<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>();
863
- if (compProvider) {
939
+ EnsureUiaProvider();
940
+ if (m_innerAutomationProvider) {
864
941
  if ((newViewProps.accessibilityState.has_value() && newViewProps.accessibilityState->selected.has_value())) {
865
- winrt::Microsoft::ReactNative::implementation::AddSelectionItemsToContainer(compProvider.get());
942
+ winrt::Microsoft::ReactNative::implementation::AddSelectionItemsToContainer(m_innerAutomationProvider.get());
866
943
  } else {
867
- winrt::Microsoft::ReactNative::implementation::RemoveSelectionItemsFromContainer(compProvider.get());
944
+ winrt::Microsoft::ReactNative::implementation::RemoveSelectionItemsFromContainer(
945
+ m_innerAutomationProvider.get());
868
946
  }
869
947
  }
870
948
  }
@@ -1354,12 +1432,17 @@ std::string ViewComponentView::DefaultControlType() const noexcept {
1354
1432
  return "group";
1355
1433
  }
1356
1434
 
1357
- winrt::IInspectable ComponentView::EnsureUiaProvider() noexcept {
1358
- if (m_uiaProvider == nullptr) {
1359
- m_uiaProvider =
1360
- winrt::make<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>(*get_strong());
1361
- }
1362
- return m_uiaProvider;
1435
+ winrt::Windows::Foundation::IInspectable ComponentView::CreateAutomationProvider() noexcept {
1436
+ Assert(!m_innerAutomationProvider);
1437
+ m_innerAutomationProvider =
1438
+ winrt::make_self<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>(
1439
+ *get_strong());
1440
+ return *m_innerAutomationProvider;
1441
+ }
1442
+
1443
+ const winrt::com_ptr<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>
1444
+ &ComponentView::InnerAutomationProvider() const noexcept {
1445
+ return m_innerAutomationProvider;
1363
1446
  }
1364
1447
 
1365
1448
  bool IntersectRect(RECT *prcDst, const RECT &prcSrc1, const RECT &prcSrc2) {
@@ -19,8 +19,11 @@ namespace Microsoft::ReactNative {
19
19
  struct CompContext;
20
20
  } // namespace Microsoft::ReactNative
21
21
 
22
- namespace winrt::Microsoft::ReactNative::Composition::implementation {
22
+ namespace winrt::Microsoft::ReactNative::implementation {
23
+ class CompositionDynamicAutomationProvider;
24
+ }
23
25
 
26
+ namespace winrt::Microsoft::ReactNative::Composition::implementation {
24
27
  struct FocusPrimitive {
25
28
  std::shared_ptr<BorderPrimitive> m_focusInnerPrimitive;
26
29
  std::shared_ptr<BorderPrimitive> m_focusOuterPrimitive;
@@ -100,7 +103,9 @@ struct ComponentView : public ComponentViewT<
100
103
  comp::CompositionPropertySet EnsureCenterPointPropertySet() noexcept;
101
104
  void EnsureTransformMatrixFacade() noexcept;
102
105
 
103
- winrt::IInspectable EnsureUiaProvider() noexcept override;
106
+ winrt::Windows::Foundation::IInspectable CreateAutomationProvider() noexcept override;
107
+ const winrt::com_ptr<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>
108
+ &InnerAutomationProvider() const noexcept;
104
109
  std::optional<std::string> getAccessiblityValue() noexcept override;
105
110
  void setAcccessiblityValue(std::string &&value) noexcept override;
106
111
  bool getAcccessiblityIsReadOnly() noexcept override;
@@ -130,7 +135,9 @@ struct ComponentView : public ComponentViewT<
130
135
  facebook::react::Point &ptContent,
131
136
  facebook::react::Point &localPt) const noexcept;
132
137
 
133
- winrt::IInspectable m_uiaProvider{nullptr};
138
+ // Most access should be through EnsureUIAProvider, instead of direct access to this.
139
+ winrt::com_ptr<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>
140
+ m_innerAutomationProvider;
134
141
  winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext m_compContext;
135
142
  comp::CompositionPropertySet m_centerPropSet{nullptr};
136
143
  facebook::react::SharedViewEventEmitter m_eventEmitter;
@@ -43,9 +43,19 @@ ContentIslandComponentView::ContentIslandComponentView(
43
43
  });
44
44
  }
45
45
 
46
- void ContentIslandComponentView::OnMounted() noexcept {
46
+ winrt::Microsoft::UI::Content::ContentIsland ContentIslandComponentView::ParentContentIsland() noexcept {
47
+ auto root = rootComponentView();
48
+ if (!root)
49
+ return nullptr;
50
+ return root->parentContentIsland();
51
+ }
52
+
53
+ void ContentIslandComponentView::ConnectInternal() noexcept {
54
+ if (!m_islandToConnect)
55
+ return;
56
+
47
57
  m_childSiteLink = winrt::Microsoft::UI::Content::ChildSiteLink::Create(
48
- rootComponentView()->parentContentIsland(),
58
+ m_parentContentIsland,
49
59
  winrt::Microsoft::ReactNative::Composition::Experimental::CompositionContextHelper::InnerVisual(Visual())
50
60
  .as<winrt::Microsoft::UI::Composition::ContainerVisual>());
51
61
  m_childSiteLink.ActualSize({m_layoutMetrics.frame.size.width, m_layoutMetrics.frame.size.height});
@@ -69,6 +79,7 @@ void ContentIslandComponentView::OnMounted() noexcept {
69
79
  m_childSiteLink.Connect(m_islandToConnect);
70
80
  m_islandToConnect = nullptr;
71
81
  }
82
+ UnregisterForRootIslandEvents();
72
83
 
73
84
  ParentLayoutChanged();
74
85
  auto view = Parent();
@@ -85,12 +96,42 @@ void ContentIslandComponentView::OnMounted() noexcept {
85
96
  }
86
97
  }
87
98
 
99
+ void ContentIslandComponentView::RegisterForRootIslandEvents() noexcept {
100
+ m_parentContentIsland = ParentContentIsland();
101
+
102
+ if (m_parentContentIsland.IsConnected()) {
103
+ ConnectInternal();
104
+ } else {
105
+ m_islandStateChangedToken = m_parentContentIsland.StateChanged(
106
+ [wkThis = get_weak()](
107
+ const winrt::Microsoft::UI::Content::ContentIsland & /*island*/,
108
+ const winrt::Microsoft::UI::Content::ContentIslandStateChangedEventArgs & /*args*/) {
109
+ if (auto strongThis = wkThis.get()) {
110
+ strongThis->ConnectInternal();
111
+ }
112
+ });
113
+ }
114
+ }
115
+
116
+ void ContentIslandComponentView::UnregisterForRootIslandEvents() noexcept {
117
+ if (m_islandStateChangedToken) {
118
+ m_parentContentIsland.StateChanged(m_islandStateChangedToken);
119
+ m_islandStateChangedToken = {};
120
+ m_parentContentIsland = nullptr;
121
+ }
122
+ }
123
+
124
+ void ContentIslandComponentView::OnMounted() noexcept {
125
+ RegisterForRootIslandEvents();
126
+ }
127
+
88
128
  void ContentIslandComponentView::OnUnmounted() noexcept {
89
129
  m_layoutMetricChangedRevokers.clear();
90
130
  if (m_navigationHostDepartFocusRequestedToken && m_navigationHost) {
91
131
  m_navigationHost.DepartFocusRequested(m_navigationHostDepartFocusRequestedToken);
92
132
  m_navigationHostDepartFocusRequestedToken = {};
93
133
  }
134
+ UnregisterForRootIslandEvents();
94
135
  }
95
136
 
96
137
  void ContentIslandComponentView::ParentLayoutChanged() noexcept {
@@ -111,12 +152,11 @@ void ContentIslandComponentView::ParentLayoutChanged() noexcept {
111
152
  });
112
153
  }
113
154
 
114
- winrt::IInspectable ContentIslandComponentView::EnsureUiaProvider() noexcept {
115
- if (m_uiaProvider == nullptr) {
116
- m_uiaProvider = winrt::make<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>(
117
- *get_strong(), m_childSiteLink);
118
- }
119
- return m_uiaProvider;
155
+ winrt::Windows::Foundation::IInspectable ContentIslandComponentView::CreateAutomationProvider() noexcept {
156
+ m_innerAutomationProvider =
157
+ winrt::make_self<winrt::Microsoft::ReactNative::implementation::CompositionDynamicAutomationProvider>(
158
+ *get_strong(), m_childSiteLink);
159
+ return *m_innerAutomationProvider;
120
160
  }
121
161
 
122
162
  bool ContentIslandComponentView::focusable() const noexcept {
@@ -126,6 +166,27 @@ bool ContentIslandComponentView::focusable() const noexcept {
126
166
  return true;
127
167
  }
128
168
 
169
+ facebook::react::Tag ContentIslandComponentView::hitTest(
170
+ facebook::react::Point pt,
171
+ facebook::react::Point &localPt,
172
+ bool ignorePointerEvents) const noexcept {
173
+ facebook::react::Point ptLocal{pt.x - m_layoutMetrics.frame.origin.x, pt.y - m_layoutMetrics.frame.origin.y};
174
+
175
+ // Check if the point is within the bounds of this ContentIslandComponentView.
176
+ // This ensures that hit tests correctly return this view's tag for UIA purposes,
177
+ // even when the actual content (XAML buttons, etc.) is hosted in the ContentIsland.
178
+ auto props = viewProps();
179
+ if ((ignorePointerEvents || props->pointerEvents == facebook::react::PointerEventsMode::Auto ||
180
+ props->pointerEvents == facebook::react::PointerEventsMode::BoxOnly) &&
181
+ ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 &&
182
+ ptLocal.y <= m_layoutMetrics.frame.size.height) {
183
+ localPt = ptLocal;
184
+ return Tag();
185
+ }
186
+
187
+ return -1;
188
+ }
189
+
129
190
  // Helper to convert a FocusNavigationDirection to a FocusNavigationReason.
130
191
  winrt::Microsoft::UI::Input::FocusNavigationReason GetFocusNavigationReason(
131
192
  winrt::Microsoft::ReactNative::FocusNavigationDirection direction) noexcept {
@@ -178,14 +239,12 @@ ContentIslandComponentView::~ContentIslandComponentView() noexcept {
178
239
  void ContentIslandComponentView::MountChildComponentView(
179
240
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
180
241
  uint32_t index) noexcept {
181
- assert(false);
182
242
  base_type::MountChildComponentView(childComponentView, index);
183
243
  }
184
244
 
185
245
  void ContentIslandComponentView::UnmountChildComponentView(
186
246
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
187
247
  uint32_t index) noexcept {
188
- assert(false);
189
248
  base_type::UnmountChildComponentView(childComponentView, index);
190
249
  }
191
250
 
@@ -262,6 +321,10 @@ void ContentIslandComponentView::ConfigureChildSiteLinkAutomation() noexcept {
262
321
  args.AutomationProvider(nullptr);
263
322
  args.Handled(true);
264
323
  });
324
+
325
+ if (m_innerAutomationProvider) {
326
+ m_innerAutomationProvider->SetChildSiteLink(m_childSiteLink);
327
+ }
265
328
  }
266
329
 
267
330
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -40,7 +40,10 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
40
40
 
41
41
  bool focusable() const noexcept override;
42
42
 
43
- winrt::Windows::Foundation::IInspectable EnsureUiaProvider() noexcept override;
43
+ facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents)
44
+ const noexcept override;
45
+
46
+ winrt::Windows::Foundation::IInspectable CreateAutomationProvider() noexcept override;
44
47
 
45
48
  void onGotFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
46
49
 
@@ -55,9 +58,16 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
55
58
  void OnMounted() noexcept;
56
59
  void OnUnmounted() noexcept;
57
60
  void ParentLayoutChanged() noexcept;
61
+ void ConnectInternal() noexcept;
62
+ void RegisterForRootIslandEvents() noexcept;
63
+ void UnregisterForRootIslandEvents() noexcept;
64
+ winrt::Microsoft::UI::Content::ContentIsland ParentContentIsland() noexcept;
58
65
 
59
66
  bool m_layoutChangePosted{false};
67
+ winrt::Microsoft::UI::Content::ContentIsland m_parentContentIsland{nullptr};
60
68
  winrt::Microsoft::UI::Content::ContentIsland m_islandToConnect{nullptr};
69
+ winrt::event_token m_islandStateChangedToken;
70
+
61
71
  winrt::event_token m_mountedToken;
62
72
  winrt::event_token m_unmountedToken;
63
73
  std::vector<winrt::Microsoft::ReactNative::ComponentView::LayoutMetricsChanged_revoker> m_layoutMetricChangedRevokers;
@@ -86,10 +86,11 @@ void DebuggingOverlayComponentView::HandleCommand(
86
86
  if (auto root = rootComponentView()) {
87
87
  auto rootVisual = root->OuterVisual();
88
88
  auto brush = m_compContext.CreateColorBrush({204, 200, 230, 255});
89
+ float scaleFactor = m_layoutMetrics.pointScaleFactor;
89
90
  for (auto &element : elements) {
90
91
  auto overlayVisual = m_compContext.CreateSpriteVisual();
91
- overlayVisual.Size({element.width, element.height});
92
- overlayVisual.Offset({element.x, element.y, 0.0f});
92
+ overlayVisual.Size({element.width * scaleFactor, element.height * scaleFactor});
93
+ overlayVisual.Offset({element.x * scaleFactor, element.y * scaleFactor, 0.0f});
93
94
  overlayVisual.Brush(brush);
94
95
 
95
96
  rootVisual.InsertAt(overlayVisual, root->overlayIndex() + m_activeOverlays);
@@ -22,7 +22,6 @@
22
22
  #include <winrt/Windows.UI.Composition.h>
23
23
  #include <winrt/Windows.Web.Http.Headers.h>
24
24
  #include <winrt/Windows.Web.Http.h>
25
- #include "CompositionDynamicAutomationProvider.h"
26
25
  #include "CompositionHelpers.h"
27
26
  #include "RootComponentView.h"
28
27