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
@@ -12,6 +12,7 @@
12
12
  #include <react/renderer/components/text/ParagraphProps.h>
13
13
  #include <windows.ui.composition.interop.h>
14
14
  #include <winrt/Windows.UI.Composition.h>
15
+ #include <chrono>
15
16
  #include "CompositionHelpers.h"
16
17
  #include "CompositionViewComponentView.h"
17
18
 
@@ -48,6 +49,33 @@ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView,
48
49
  static facebook::react::SharedViewProps defaultProps() noexcept;
49
50
  const facebook::react::ParagraphProps &paragraphProps() const noexcept;
50
51
 
52
+ facebook::react::Tag hitTest(
53
+ facebook::react::Point pt,
54
+ facebook::react::Point &localPt,
55
+ bool ignorePointerEvents = false) const noexcept override;
56
+
57
+ // Returns true when text is selectable
58
+ bool focusable() const noexcept override;
59
+
60
+ // Returns I-beam cursor for selectable text
61
+ std::pair<facebook::react::Cursor, HCURSOR> cursor() const noexcept override;
62
+
63
+ // Called when losing focus, when another text starts selection, or when clicking outside text bounds.
64
+ void ClearSelection() noexcept;
65
+
66
+ // Text selection pointer event handlers
67
+ void OnPointerPressed(
68
+ const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override;
69
+ void OnPointerMoved(
70
+ const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override;
71
+ void OnPointerReleased(
72
+ const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept override;
73
+ void OnPointerCaptureLost() noexcept override;
74
+ void onLostFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
75
+
76
+ // Keyboard event handler for copy
77
+ void OnKeyDown(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
78
+
51
79
  ParagraphComponentView(
52
80
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
53
81
  facebook::react::Tag tag,
@@ -56,7 +84,29 @@ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView,
56
84
  private:
57
85
  void updateVisualBrush() noexcept;
58
86
  void DrawText() noexcept;
87
+ void DrawSelectionHighlight(
88
+ ID2D1RenderTarget &renderTarget,
89
+ float offsetX,
90
+ float offsetY,
91
+ float pointScaleFactor) noexcept;
59
92
  void updateTextAlignment(const std::optional<facebook::react::TextAlignment> &fbAlignment) noexcept;
93
+ bool IsTextSelectableAtPoint(facebook::react::Point pt) noexcept;
94
+ std::optional<int32_t> GetTextPositionAtPoint(facebook::react::Point pt) noexcept;
95
+ std::optional<int32_t> GetClampedTextPosition(facebook::react::Point pt) noexcept;
96
+ std::string GetSelectedText() const noexcept;
97
+
98
+ // Copies currently selected text to the system clipboard
99
+ void CopySelectionToClipboard() noexcept;
100
+
101
+ // Selects the word at the given character position
102
+ void SelectWordAtPosition(int32_t charPosition) noexcept;
103
+ std::pair<int32_t, int32_t> GetWordBoundariesAtPosition(int32_t charPosition) noexcept;
104
+
105
+ // Shows a context menu with Copy/Select All options on right-click
106
+ void ShowContextMenu() noexcept;
107
+
108
+ // m_selectionStart <= m_selectionEnd
109
+ void SetSelection(int32_t start, int32_t end) noexcept;
60
110
 
61
111
  winrt::com_ptr<::IDWriteTextLayout> m_textLayout;
62
112
  facebook::react::AttributedStringBox m_attributedStringBox;
@@ -64,6 +114,19 @@ struct ParagraphComponentView : ParagraphComponentViewT<ParagraphComponentView,
64
114
 
65
115
  bool m_requireRedraw{true};
66
116
  winrt::Microsoft::ReactNative::Composition::Experimental::IDrawingSurfaceBrush m_drawingSurface;
117
+
118
+ std::optional<int32_t> m_selectionStart;
119
+ std::optional<int32_t> m_selectionEnd;
120
+ bool m_isSelecting{false};
121
+
122
+ // Double click + drag selection
123
+ bool m_isWordSelecting{false};
124
+ int32_t m_wordAnchorStart{0};
125
+ int32_t m_wordAnchorEnd{0};
126
+
127
+ // Double-click detection
128
+ std::chrono::steady_clock::time_point m_lastClickTime{};
129
+ std::optional<int32_t> m_lastClickPosition;
67
130
  };
68
131
 
69
132
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -227,6 +227,14 @@ void ReactCompositionViewComponentBuilder::SetUnmountChildComponentViewHandler(
227
227
  m_unmountChildComponentViewHandler = impl;
228
228
  }
229
229
 
230
+ void ReactCompositionViewComponentBuilder::SetCreateAutomationPeerHandler(CreateAutomationPeerDelegate impl) noexcept {
231
+ m_createAutomationPeerHandler = impl;
232
+ }
233
+
234
+ const CreateAutomationPeerDelegate &ReactCompositionViewComponentBuilder::CreateAutomationPeerHandler() const noexcept {
235
+ return m_createAutomationPeerHandler;
236
+ }
237
+
230
238
  const UnmountChildComponentViewDelegate &ReactCompositionViewComponentBuilder::UnmountChildComponentViewHandler()
231
239
  const noexcept {
232
240
  return m_unmountChildComponentViewHandler;
@@ -39,6 +39,7 @@ struct ReactCompositionViewComponentBuilder
39
39
  void SetUpdateEventEmitterHandler(UpdateEventEmitterDelegate impl) noexcept;
40
40
  void SetMountChildComponentViewHandler(MountChildComponentViewDelegate impl) noexcept;
41
41
  void SetUnmountChildComponentViewHandler(UnmountChildComponentViewDelegate impl) noexcept;
42
+ void SetCreateAutomationPeerHandler(CreateAutomationPeerDelegate impl) noexcept;
42
43
 
43
44
  public: // Composition::IReactCompositionViewComponentBuilder
44
45
  void SetViewComponentViewInitializer(const ViewComponentViewInitializer &initializer) noexcept;
@@ -77,6 +78,7 @@ struct ReactCompositionViewComponentBuilder
77
78
  const CreateVisualDelegate &CreateVisualHandler() const noexcept;
78
79
  const winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate &
79
80
  VisualToMountChildrenIntoHandler() const noexcept;
81
+ const CreateAutomationPeerDelegate &CreateAutomationPeerHandler() const noexcept;
80
82
 
81
83
  private:
82
84
  void InitializeComponentView(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
@@ -103,6 +105,7 @@ struct ReactCompositionViewComponentBuilder
103
105
  winrt::Microsoft::ReactNative::UpdateEventEmitterDelegate m_updateEventEmitterHandler;
104
106
  winrt::Microsoft::ReactNative::MountChildComponentViewDelegate m_mountChildComponentViewHandler;
105
107
  winrt::Microsoft::ReactNative::UnmountChildComponentViewDelegate m_unmountChildComponentViewHandler;
108
+ winrt::Microsoft::ReactNative::CreateAutomationPeerDelegate m_createAutomationPeerHandler;
106
109
 
107
110
  winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate m_createVisualHandler;
108
111
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisualToMountChildrenIntoDelegate
@@ -8,7 +8,10 @@
8
8
 
9
9
  #include <Fabric/FabricUIManagerModule.h>
10
10
  #include <winrt/Microsoft.UI.Input.h>
11
+ #include "CompositionDynamicAutomationProvider.h"
11
12
  #include "CompositionRootAutomationProvider.h"
13
+ #include "ContentIslandComponentView.h"
14
+ #include "ParagraphComponentView.h"
12
15
  #include "ReactNativeIsland.h"
13
16
  #include "Theme.h"
14
17
 
@@ -275,7 +278,7 @@ facebook::react::Point RootComponentView::getClientOffset() const noexcept {
275
278
  return {};
276
279
  }
277
280
 
278
- winrt::IInspectable RootComponentView::UiaProviderFromPoint(const POINT &ptPixels) noexcept {
281
+ winrt::IUnknown RootComponentView::UiaProviderFromPoint(const POINT &ptPixels, const POINT &ptScreen) noexcept {
279
282
  facebook::react::Point ptDips{
280
283
  static_cast<facebook::react::Float>(ptPixels.x) / m_layoutMetrics.pointScaleFactor,
281
284
  static_cast<facebook::react::Float>(ptPixels.y) / m_layoutMetrics.pointScaleFactor};
@@ -295,7 +298,41 @@ winrt::IInspectable RootComponentView::UiaProviderFromPoint(const POINT &ptPixel
295
298
  if (view == nullptr)
296
299
  return nullptr;
297
300
 
298
- return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view)->EnsureUiaProvider();
301
+ auto uiaProvider =
302
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view)->EnsureUiaProvider();
303
+
304
+ if (auto contentIsland =
305
+ view.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ContentIslandComponentView>()) {
306
+ if (contentIsland->InnerAutomationProvider()) {
307
+ if (auto childProvider = contentIsland->InnerAutomationProvider()->TryGetChildSiteLinkAutomationProvider()) {
308
+ // ChildProvider is the the automation provider from the ChildSiteLink. In the case of WinUI, this
309
+ // is a pointer to WinUI's internal CUIAHostWindow object.
310
+ // It seems odd, but even though this node doesn't behave as a fragment root in our case (the real fragment root
311
+ // is the RootComponentView's UIA provider), we still use its IRawElementProviderFragmentRoot -- just so
312
+ // we can do the ElementProviderFromPoint call. (this was recommended by the team who did the initial
313
+ // architecture work).
314
+ if (auto fragmentRoot = childProvider.try_as<IRawElementProviderFragmentRoot>()) {
315
+ com_ptr<IRawElementProviderFragment> frag;
316
+ // WinUI then does its own hitTest inside the XAML tree.
317
+ fragmentRoot->ElementProviderFromPoint(
318
+ ptScreen
319
+ .x, // Note since we're going through IRawElementProviderFragment the coordinates are in screen space.
320
+ ptScreen.y,
321
+ frag.put());
322
+ // We return the specific child provider(frag) when hosted XAML has an element
323
+ // under the cursor. This satisfies the UIA "element at point" contract and exposes
324
+ // the control’s patterns/properties. If the hosted tree finds nothing, we fall back
325
+ // to the RNW container’s provider (uiaProvider) to keep the island accessible.
326
+ // (A Microsoft_UI_Xaml!CUIAWrapper object)
327
+ if (frag) {
328
+ return frag.as<winrt::IUnknown>();
329
+ }
330
+ }
331
+ }
332
+ }
333
+ }
334
+
335
+ return uiaProvider;
299
336
  }
300
337
 
301
338
  float RootComponentView::FontSizeMultiplier() const noexcept {
@@ -349,4 +386,18 @@ HWND RootComponentView::GetHwndForParenting() noexcept {
349
386
  return base_type::GetHwndForParenting();
350
387
  }
351
388
 
389
+ void RootComponentView::ClearCurrentTextSelection() noexcept {
390
+ if (auto view = m_viewWithTextSelection.view()) {
391
+ if (auto paragraphView = view.try_as<ParagraphComponentView>()) {
392
+ paragraphView->ClearSelection();
393
+ }
394
+ }
395
+ m_viewWithTextSelection =
396
+ ::Microsoft::ReactNative::ReactTaggedView{winrt::Microsoft::ReactNative::ComponentView{nullptr}};
397
+ }
398
+
399
+ void RootComponentView::SetViewWithTextSelection(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
400
+ m_viewWithTextSelection = ::Microsoft::ReactNative::ReactTaggedView{view};
401
+ }
402
+
352
403
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -5,6 +5,7 @@
5
5
  #pragma once
6
6
 
7
7
  #include <Fabric/ComponentView.h>
8
+ #include <Fabric/ReactTaggedView.h>
8
9
  #include <Microsoft.ReactNative.Cxx/ReactContext.h>
9
10
 
10
11
  #include "CompositionViewComponentView.h"
@@ -64,7 +65,7 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
64
65
  facebook::react::LayoutMetrics const &layoutMetrics,
65
66
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
66
67
 
67
- winrt::Windows::Foundation::IInspectable UiaProviderFromPoint(const POINT &ptPixels) noexcept;
68
+ winrt::Windows::Foundation::IUnknown UiaProviderFromPoint(const POINT &ptPixels, const POINT &ptScreen) noexcept;
68
69
 
69
70
  RootComponentView(
70
71
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
@@ -86,6 +87,9 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
86
87
 
87
88
  HWND GetHwndForParenting() noexcept override;
88
89
 
90
+ void ClearCurrentTextSelection() noexcept;
91
+ void SetViewWithTextSelection(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
92
+
89
93
  private:
90
94
  // should this be a ReactTaggedView? - It shouldn't actually matter since if the view is going away it should always
91
95
  // be clearing its focus But being a reactTaggedView might make it easier to identify cases where that isn't
@@ -94,6 +98,9 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
94
98
  winrt::weak_ref<winrt::Microsoft::ReactNative::ReactNativeIsland> m_wkRootView{nullptr};
95
99
  winrt::weak_ref<winrt::Microsoft::ReactNative::Composition::PortalComponentView> m_wkPortal{nullptr};
96
100
  bool m_visualAddedToIsland{false};
101
+
102
+ ::Microsoft::ReactNative::ReactTaggedView m_viewWithTextSelection{
103
+ winrt::Microsoft::ReactNative::ComponentView{nullptr}};
97
104
  };
98
105
 
99
106
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -20,7 +20,6 @@
20
20
  #include <AutoDraw.h>
21
21
  #include <Fabric/DWriteHelpers.h>
22
22
  #include <unicode.h>
23
- #include "CompositionDynamicAutomationProvider.h"
24
23
  #include "JSValueReader.h"
25
24
  #include "RootComponentView.h"
26
25
 
@@ -7,7 +7,6 @@
7
7
  #include "SwitchComponentView.h"
8
8
  #include <AutoDraw.h>
9
9
  #include <Fabric/AbiViewProps.h>
10
- #include "CompositionDynamicAutomationProvider.h"
11
10
  #include "RootComponentView.h"
12
11
  #include "UiaHelpers.h"
13
12
 
@@ -6,7 +6,6 @@
6
6
  #include "WindowsTextInputComponentView.h"
7
7
 
8
8
  #include <AutoDraw.h>
9
- #include <Fabric/Composition/CompositionDynamicAutomationProvider.h>
10
9
  #include <Fabric/Composition/UiaHelpers.h>
11
10
  #include <Fabric/platform/react/renderer/graphics/PlatformColorUtils.h>
12
11
  #include <Utils/ThemeUtils.h>
@@ -1782,6 +1781,9 @@ WindowsTextInputComponentView::createVisual() noexcept {
1782
1781
  LRESULT res;
1783
1782
  winrt::check_hresult(m_textServices->TxSendMessage(EM_SETTEXTMODE, TM_PLAINTEXT, 0, &res));
1784
1783
 
1784
+ // Enable TSF support
1785
+ winrt::check_hresult(m_textServices->TxSendMessage(EM_SETEDITSTYLE, SES_USECTF, SES_USECTF, nullptr));
1786
+
1785
1787
  m_caretVisual = m_compContext.CreateCaretVisual();
1786
1788
  visual.InsertAt(m_caretVisual.InnerVisual(), 0);
1787
1789
  m_caretVisual.IsVisible(false);
@@ -174,6 +174,12 @@ bool Theme::TryGetPlatformColor(const std::string &platformColor, winrt::Windows
174
174
  return true;
175
175
  }
176
176
 
177
+ if (platformColor == "Highlight@40" && TryGetPlatformColor("Highlight", color)) {
178
+ color.A = static_cast<uint8_t>(static_cast<float>(color.A) * 0.4f);
179
+ m_colorCache[platformColor] = std::make_pair(true, color);
180
+ return true;
181
+ }
182
+
177
183
  auto uiColor = s_uiColorTypes.find(platformColor);
178
184
  if (uiColor != s_uiColorTypes.end()) {
179
185
  auto uiSettings{winrt::Windows::UI::ViewManagement::UISettings()};
@@ -267,7 +267,7 @@ void TooltipTracker::ShowTooltip(const winrt::Microsoft::ReactNative::ComponentV
267
267
  static_cast<int>((tm.width + tooltipHorizontalPadding + tooltipHorizontalPadding) * scaleFactor);
268
268
  tooltipData->height = static_cast<int>((tm.height + tooltipTopPadding + tooltipBottomPadding) * scaleFactor);
269
269
 
270
- POINT pt = {static_cast<LONG>(m_pos.X), static_cast<LONG>(m_pos.Y)};
270
+ POINT pt = {static_cast<LONG>(m_pos.X * scaleFactor), static_cast<LONG>(m_pos.Y * scaleFactor)};
271
271
  ClientToScreen(parentHwnd, &pt);
272
272
 
273
273
  RegisterTooltipWndClass();
@@ -48,7 +48,8 @@ HRESULT UiaNavigateHelper(
48
48
  uint32_t index = children.Size() - 1;
49
49
  do {
50
50
  auto child = children.GetAt(index).as<winrt::Microsoft::ReactNative::implementation::ComponentView>();
51
- if (uiaProvider = child->EnsureUiaProvider()) {
51
+ uiaProvider = child->EnsureUiaProvider();
52
+ if (uiaProvider) {
52
53
  break;
53
54
  }
54
55
  } while (index-- != 0);
@@ -60,7 +61,8 @@ HRESULT UiaNavigateHelper(
60
61
  uint32_t index = 0;
61
62
  do {
62
63
  auto child = children.GetAt(index).as<winrt::Microsoft::ReactNative::implementation::ComponentView>();
63
- if (uiaProvider = child->EnsureUiaProvider()) {
64
+ uiaProvider = child->EnsureUiaProvider();
65
+ if (uiaProvider) {
64
66
  break;
65
67
  }
66
68
  } while (++index != children.Size());
@@ -74,7 +76,8 @@ HRESULT UiaNavigateHelper(
74
76
 
75
77
  while (++it != children.end()) {
76
78
  auto nextchild = (*it).as<winrt::Microsoft::ReactNative::implementation::ComponentView>();
77
- if (uiaProvider = nextchild->EnsureUiaProvider()) {
79
+ uiaProvider = nextchild->EnsureUiaProvider();
80
+ if (uiaProvider) {
78
81
  break;
79
82
  }
80
83
  }
@@ -91,7 +94,8 @@ HRESULT UiaNavigateHelper(
91
94
  do {
92
95
  it--;
93
96
  auto prevchild = (*it).as<winrt::Microsoft::ReactNative::implementation::ComponentView>();
94
- if (uiaProvider = prevchild->EnsureUiaProvider()) {
97
+ uiaProvider = prevchild->EnsureUiaProvider();
98
+ if (uiaProvider) {
95
99
  break;
96
100
  }
97
101
  } while (it != children.begin());
@@ -513,27 +517,45 @@ ExpandCollapseState GetExpandCollapseState(const bool &expanded) noexcept {
513
517
  }
514
518
 
515
519
  void AddSelectionItemsToContainer(CompositionDynamicAutomationProvider *provider) noexcept {
516
- winrt::com_ptr<IRawElementProviderSimple> selectionContainer;
517
- provider->get_SelectionContainer(selectionContainer.put());
518
- if (!selectionContainer)
520
+ auto selectionContainerView = provider->GetSelectionContainer();
521
+ if (!selectionContainerView)
519
522
  return;
520
- auto selectionContainerProvider = selectionContainer.as<CompositionDynamicAutomationProvider>();
523
+
524
+ auto selectionContainerCompView =
525
+ selectionContainerView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ComponentView>();
526
+ if (!selectionContainerCompView)
527
+ return;
528
+
529
+ selectionContainerCompView->EnsureUiaProvider();
530
+
531
+ if (!selectionContainerCompView->InnerAutomationProvider())
532
+ return;
533
+
521
534
  auto simpleProvider = static_cast<IRawElementProviderSimple *>(provider);
522
535
  winrt::com_ptr<IRawElementProviderSimple> simpleProviderPtr;
523
536
  simpleProviderPtr.copy_from(simpleProvider);
524
- selectionContainerProvider->AddToSelectionItems(simpleProviderPtr);
537
+ selectionContainerCompView->InnerAutomationProvider()->AddToSelectionItems(simpleProviderPtr);
525
538
  }
526
539
 
527
540
  void RemoveSelectionItemsFromContainer(CompositionDynamicAutomationProvider *provider) noexcept {
528
- winrt::com_ptr<IRawElementProviderSimple> selectionContainer;
529
- provider->get_SelectionContainer(selectionContainer.put());
530
- if (!selectionContainer)
541
+ auto selectionContainerView = provider->GetSelectionContainer();
542
+ if (!selectionContainerView)
531
543
  return;
532
- auto selectionContainerProvider = selectionContainer.as<CompositionDynamicAutomationProvider>();
544
+
545
+ auto selectionContainerCompView =
546
+ selectionContainerView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ComponentView>();
547
+ if (!selectionContainerCompView)
548
+ return;
549
+
550
+ selectionContainerCompView->EnsureUiaProvider();
551
+
552
+ if (!selectionContainerCompView->InnerAutomationProvider())
553
+ return;
554
+
533
555
  auto simpleProvider = static_cast<IRawElementProviderSimple *>(provider);
534
556
  winrt::com_ptr<IRawElementProviderSimple> simpleProviderPtr;
535
557
  simpleProviderPtr.copy_from(simpleProvider);
536
- selectionContainerProvider->RemoveFromSelectionItems(simpleProviderPtr);
558
+ selectionContainerCompView->InnerAutomationProvider()->RemoveFromSelectionItems(simpleProviderPtr);
537
559
  }
538
560
 
539
561
  ToggleState GetToggleState(const std::optional<facebook::react::AccessibilityState> &state) noexcept {
@@ -8,7 +8,6 @@
8
8
 
9
9
  #include <AutoDraw.h>
10
10
  #include <Fabric/DWriteHelpers.h>
11
- #include "CompositionDynamicAutomationProvider.h"
12
11
  #include "Unicode.h"
13
12
 
14
13
  namespace winrt::Microsoft::ReactNative::Composition::implementation {
@@ -16,7 +16,7 @@ namespace Microsoft::ReactNative {
16
16
  */
17
17
  struct ReactTaggedView {
18
18
  ReactTaggedView(const winrt::Microsoft::ReactNative::ComponentView &componentView)
19
- : m_view(componentView), m_tag(componentView.Tag()) {}
19
+ : m_view(componentView), m_tag(componentView ? componentView.Tag() : -1) {}
20
20
 
21
21
  winrt::Microsoft::ReactNative::ComponentView view() noexcept {
22
22
  if (!m_view) {
@@ -56,8 +56,9 @@ class WindowsTextLayoutManager : public TextLayoutManager {
56
56
  TextMeasurement::Attachments &attachments,
57
57
  float minimumFontScale) noexcept;
58
58
 
59
- private:
60
59
  static winrt::hstring GetTransformedText(const AttributedStringBox &attributedStringBox);
60
+
61
+ private:
61
62
  static void GetTextLayout(
62
63
  const AttributedStringBox &attributedStringBox,
63
64
  const ParagraphAttributes &paragraphAttributes,
@@ -54,6 +54,10 @@ namespace Microsoft.ReactNative
54
54
  Boolean Handled;
55
55
  };
56
56
 
57
+ runtimeclass CreateAutomationPeerArgs {
58
+ Object DefaultAutomationPeer { get; };
59
+ };
60
+
57
61
  [experimental]
58
62
  DOC_STRING("A delegate that creates a @IComponentProps object for an instance of @ViewProps. See @IReactViewComponentBuilder.SetCreateProps")
59
63
  delegate IComponentProps ViewPropsFactory(ViewProps props, IComponentProps cloneFrom);
@@ -95,6 +99,9 @@ namespace Microsoft.ReactNative
95
99
  [experimental]
96
100
  delegate void UnmountChildComponentViewDelegate(ComponentView source, UnmountChildComponentViewArgs args);
97
101
 
102
+ [experimental]
103
+ delegate Object CreateAutomationPeerDelegate(ComponentView source, CreateAutomationPeerArgs args);
104
+
98
105
  [experimental]
99
106
  runtimeclass EventEmitter {
100
107
  void DispatchEvent(String eventName, JSValueArgWriter args);
@@ -124,6 +131,7 @@ namespace Microsoft.ReactNative
124
131
  void SetUpdateEventEmitterHandler(UpdateEventEmitterDelegate impl);
125
132
  void SetMountChildComponentViewHandler(MountChildComponentViewDelegate impl);
126
133
  void SetUnmountChildComponentViewHandler(UnmountChildComponentViewDelegate impl);
134
+ void SetCreateAutomationPeerHandler(CreateAutomationPeerDelegate impl);
127
135
  };
128
136
 
129
137
  // [exclusiveto(ShadowNode)]
@@ -313,6 +313,7 @@
313
313
  <ClInclude Include="Utils\TransformableText.h" />
314
314
  <ClInclude Include="Utils\UwpPreparedScriptStore.h" />
315
315
  <ClInclude Include="Utils\UwpScriptStore.h" />
316
+ <ClInclude Include="Utils\IcuUtils.h" />
316
317
  <ClInclude Include="Utils\ValueUtils.h" />
317
318
  <ClInclude Include="Utils\XamlIslandUtils.h" />
318
319
  <ClInclude Include="Utils\XamlUtils.h" />
@@ -30,20 +30,33 @@ using namespace xaml::Media::Imaging;
30
30
 
31
31
  namespace Microsoft::ReactNative {
32
32
 
33
+ static const char *ERROR_INVALID_URI = "E_INVALID_URI";
34
+ static const char *ERROR_GET_SIZE_FAILURE = "E_GET_SIZE_FAILURE";
35
+
33
36
  winrt::fire_and_forget GetImageSizeAsync(
34
37
  const winrt::Microsoft::ReactNative::IReactPropertyBag &properties,
35
38
  std::string uriString,
36
39
  winrt::Microsoft::ReactNative::JSValue &&headers,
37
40
  Mso::Functor<void(int32_t width, int32_t height)> successCallback,
38
- Mso::Functor<void()> errorCallback
41
+ Mso::Functor<void(const char *errorCode, std::string errorMessage)> errorCallback
39
42
  #ifdef USE_FABRIC
40
43
  ,
41
44
  bool useFabric
42
45
  #endif // USE_FABRIC
43
46
  ) {
44
47
  bool succeeded{false};
48
+ const char *errorCode = ERROR_GET_SIZE_FAILURE;
49
+ std::string errorMessage;
45
50
 
46
51
  try {
52
+ // Validate URI is not empty
53
+ if (uriString.empty()) {
54
+ errorCode = ERROR_INVALID_URI;
55
+ errorMessage = "Cannot get the size of an image for an empty URI";
56
+ errorCallback(errorCode, errorMessage);
57
+ co_return;
58
+ }
59
+
47
60
  ReactImageSource source;
48
61
  source.uri = uriString;
49
62
  if (!headers.IsNull()) {
@@ -56,9 +69,10 @@ winrt::fire_and_forget GetImageSizeAsync(
56
69
  winrt::hstring scheme{uri.SchemeName()};
57
70
  bool needsDownload = (scheme == L"http") || (scheme == L"https");
58
71
  bool inlineData = scheme == L"data";
72
+ bool isLocalFile = (scheme == L"file") || (scheme == L"ms-appx") || (scheme == L"ms-appdata");
59
73
 
60
74
  winrt::IRandomAccessStream memoryStream;
61
- if (needsDownload) {
75
+ if (needsDownload || isLocalFile) {
62
76
  memoryStream = co_await GetImageStreamAsync(properties, source);
63
77
  } else if (inlineData) {
64
78
  memoryStream = co_await GetImageInlineDataAsync(source);
@@ -77,23 +91,31 @@ winrt::fire_and_forget GetImageSizeAsync(
77
91
  }
78
92
  #ifdef USE_FABRIC
79
93
  } else {
80
- auto result = wicBitmapSourceFromStream(memoryStream);
81
- if (!std::get<std::shared_ptr<facebook::react::ImageErrorInfo>>(result)) {
82
- auto imagingFactory = std::get<winrt::com_ptr<IWICImagingFactory>>(result);
83
- auto wicBmpSource = std::get<winrt::com_ptr<IWICBitmapSource>>(result);
84
- UINT width, height;
85
- if (SUCCEEDED(wicBmpSource->GetSize(&width, &height))) {
86
- successCallback(width, height);
87
- succeeded = true;
94
+ if (memoryStream) { // Added nullcheck to prevent app from crashing if value is uninitialized
95
+ auto result = wicBitmapSourceFromStream(memoryStream);
96
+ if (!std::get<std::shared_ptr<facebook::react::ImageErrorInfo>>(result)) {
97
+ auto imagingFactory = std::get<winrt::com_ptr<IWICImagingFactory>>(result);
98
+ auto wicBmpSource = std::get<winrt::com_ptr<IWICBitmapSource>>(result);
99
+ UINT width, height;
100
+ if (SUCCEEDED(wicBmpSource->GetSize(&width, &height))) {
101
+ successCallback(width, height);
102
+ succeeded = true;
103
+ }
88
104
  }
89
105
  }
90
106
  }
91
107
  #endif // USE_FABRIC
92
- } catch (winrt::hresult_error const &) {
108
+ } catch (winrt::hresult_error const &e) {
109
+ errorMessage = "Failed to get image size: " + Microsoft::Common::Unicode::Utf16ToUtf8(std::wstring(e.message())) +
110
+ " for URI: " + uriString;
93
111
  }
94
112
 
95
- if (!succeeded)
96
- errorCallback();
113
+ if (!succeeded) {
114
+ if (errorMessage.empty()) {
115
+ errorMessage = "Failed to get image size for URI: " + uriString;
116
+ }
117
+ errorCallback(errorCode, errorMessage);
118
+ }
97
119
 
98
120
  co_return;
99
121
  }
@@ -112,7 +134,9 @@ void ImageLoader::getSize(std::string uri, React::ReactPromise<std::vector<doubl
112
134
  [result](double width, double height) noexcept {
113
135
  result.Resolve(std::vector<double>{width, height});
114
136
  },
115
- [result]() noexcept { result.Reject("Failed"); }
137
+ [result](const char *errorCode, std::string errorMessage) noexcept {
138
+ result.Reject(React::ReactError{errorCode, errorMessage});
139
+ }
116
140
  #ifdef USE_FABRIC
117
141
  ,
118
142
  IsFabricEnabled(context.Properties().Handle())
@@ -137,7 +161,9 @@ void ImageLoader::getSizeWithHeaders(
137
161
  [result](double width, double height) noexcept {
138
162
  result.Resolve(Microsoft::ReactNativeSpecs::ImageLoaderIOSSpec_getSizeWithHeaders_returnType{width, height});
139
163
  },
140
- [result]() noexcept { result.Reject("Failed"); }
164
+ [result](const char *errorCode, std::string errorMessage) noexcept {
165
+ result.Reject(React::ReactError{errorCode, errorMessage});
166
+ }
141
167
  #ifdef USE_FABRIC
142
168
  ,
143
169
  IsFabricEnabled(context.Properties().Handle())