react-native-windows 0.75.3 → 0.75.5

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 (63) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +1 -1
  2. package/Libraries/StyleSheet/StyleSheetTypes.d.ts +17 -15
  3. package/Microsoft.ReactNative/ComponentView.idl +11 -0
  4. package/Microsoft.ReactNative/Composition.Input.idl +1 -0
  5. package/Microsoft.ReactNative/CompositionSwitcher.idl +3 -0
  6. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +7 -9
  7. package/Microsoft.ReactNative/Fabric/ComponentView.h +5 -6
  8. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +4 -0
  9. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +1 -0
  10. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +44 -13
  11. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +6 -1
  12. package/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp +1 -0
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +11 -8
  14. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +2 -3
  15. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +8 -6
  16. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.h +1 -2
  17. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +20 -6
  18. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +13 -6
  19. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +2 -3
  20. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +1 -2
  21. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +72 -54
  22. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +14 -4
  23. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +26 -8
  24. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +5 -2
  25. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +18 -7
  26. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +1 -2
  27. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +6 -6
  28. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h +1 -2
  29. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +97 -140
  30. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +8 -4
  31. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +14 -11
  32. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.h +4 -4
  33. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.cpp +0 -13
  34. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.h +0 -3
  35. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +29 -4
  36. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +2 -0
  37. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -2
  38. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.h +1 -2
  39. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +28 -3
  40. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +9 -2
  41. package/Microsoft.ReactNative/IReactViewComponentBuilder.idl +8 -1
  42. package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +9 -0
  43. package/Microsoft.ReactNative/Modules/LogBoxModule.h +2 -0
  44. package/Microsoft.ReactNative/Modules/SampleTurboModule.cpp +104 -0
  45. package/Microsoft.ReactNative/Modules/SampleTurboModule.h +78 -0
  46. package/Microsoft.ReactNative/ReactHost/MsoReactContext.cpp +0 -7
  47. package/Microsoft.ReactNative/ReactHost/MsoReactContext.h +0 -5
  48. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +17 -1
  49. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.cpp +59 -0
  50. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.h +23 -0
  51. package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +179 -0
  52. package/Microsoft.ReactNative/ReactNativeAppBuilder.h +35 -0
  53. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +69 -0
  54. package/Microsoft.ReactNative/ReactNativeIsland.idl +2 -0
  55. package/Microsoft.ReactNative/ReactNativeWin32App.cpp +82 -0
  56. package/Microsoft.ReactNative/ReactNativeWin32App.h +38 -0
  57. package/Microsoft.ReactNative/packages.lock.json +67 -40
  58. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  59. package/Shared/Shared.vcxitems +33 -0
  60. package/Shared/Shared.vcxitems.filters +1 -0
  61. package/Shared/TurboModuleManager.cpp +0 -3
  62. package/package.json +17 -16
  63. package/templates/cpp-app/windows/MyApp/MyApp.cpp +1 -0
@@ -58,10 +58,6 @@ struct CompositionReactViewInstance
58
58
  void UpdateRootView() noexcept;
59
59
  void UninitRootView() noexcept;
60
60
 
61
- private:
62
- template <class TAction>
63
- Mso::Future<void> PostInUIQueue(TAction &&action) noexcept;
64
-
65
61
  private:
66
62
  winrt::weak_ref<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland> m_weakRootControl;
67
63
  IReactDispatcher m_uiDispatcher{nullptr};
@@ -102,44 +98,36 @@ void CompositionReactViewInstance::UninitRootView() noexcept {
102
98
  }
103
99
  }
104
100
 
105
- //===========================================================================
106
- // ReactViewInstance inline implementation
107
- //===========================================================================
108
-
109
- template <class TAction>
110
- inline Mso::Future<void> CompositionReactViewInstance::PostInUIQueue(TAction &&action) noexcept {
111
- // ReactViewInstance has shorter lifetime than ReactRootControl. Thus, we capture this WeakPtr.
112
- auto promise = Mso::Promise<void>();
113
-
114
- m_uiDispatcher.Post([promise, weakThis{get_weak()}, action{std::forward<TAction>(action)}]() mutable {
115
- if (auto strongThis = weakThis.get()) {
116
- if (auto rootControl = strongThis->m_weakRootControl.get()) {
117
- action(rootControl);
118
- promise.SetValue();
119
- return;
120
- }
121
- }
122
- promise.TryCancel();
123
- });
124
-
125
- return promise.AsFuture();
126
- }
127
-
128
- void ApplyConstraints(
101
+ void ReactNativeIsland::ApplyConstraints(
129
102
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraintsIn,
130
- facebook::react::LayoutConstraints &layoutConstraintsOut) noexcept {
103
+ facebook::react::LayoutConstraints &layoutConstraintsOut) const noexcept {
131
104
  layoutConstraintsOut.minimumSize = {layoutConstraintsIn.MinimumSize.Width, layoutConstraintsIn.MinimumSize.Height};
132
105
  layoutConstraintsOut.maximumSize = {layoutConstraintsIn.MaximumSize.Width, layoutConstraintsIn.MaximumSize.Height};
133
- layoutConstraintsOut.layoutDirection =
134
- static_cast<facebook::react::LayoutDirection>(layoutConstraintsIn.LayoutDirection);
106
+ if (layoutConstraintsIn.LayoutDirection == winrt::Microsoft::ReactNative::LayoutDirection::Undefined) {
107
+ if (m_island) {
108
+ layoutConstraintsOut.layoutDirection =
109
+ (m_island.LayoutDirection() == winrt::Microsoft::UI::Content::ContentLayoutDirection::LeftToRight)
110
+ ? facebook::react::LayoutDirection::LeftToRight
111
+ : facebook::react::LayoutDirection::RightToLeft;
112
+ } else if (m_hwnd) {
113
+ auto styles = GetWindowLongPtrW(m_hwnd, GWL_EXSTYLE);
114
+ layoutConstraintsOut.layoutDirection = ((styles & WS_EX_LAYOUTRTL) == WS_EX_LAYOUTRTL)
115
+ ? facebook::react::LayoutDirection::RightToLeft
116
+ : facebook::react::LayoutDirection::LeftToRight;
117
+ }
118
+ } else {
119
+ layoutConstraintsOut.layoutDirection =
120
+ static_cast<facebook::react::LayoutDirection>(layoutConstraintsIn.LayoutDirection);
121
+ }
135
122
  }
136
123
 
137
- ReactNativeIsland::ReactNativeIsland() noexcept {}
138
-
139
- #ifdef USE_WINUI3
140
124
  ReactNativeIsland::ReactNativeIsland(const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept
141
- : m_compositor(compositor) {}
142
- #endif
125
+ : m_compositor(compositor),
126
+ m_layoutConstraints({{0, 0}, {0, 0}, winrt::Microsoft::ReactNative::LayoutDirection::Undefined}) {
127
+ InitTextScaleMultiplier();
128
+ }
129
+
130
+ ReactNativeIsland::ReactNativeIsland() noexcept : ReactNativeIsland(nullptr) {}
143
131
 
144
132
  ReactNativeIsland::~ReactNativeIsland() noexcept {
145
133
  #ifdef USE_WINUI3
@@ -275,6 +263,10 @@ void ReactNativeIsland::ScaleFactor(float value) noexcept {
275
263
  }
276
264
  }
277
265
 
266
+ float ReactNativeIsland::FontSizeMultiplier() const noexcept {
267
+ return m_textScaleMultiplier;
268
+ }
269
+
278
270
  int64_t ReactNativeIsland::RootTag() const noexcept {
279
271
  return m_rootTag;
280
272
  }
@@ -458,10 +450,9 @@ void ReactNativeIsland::UninitRootView() noexcept {
458
450
  uiManager->stopSurface(static_cast<facebook::react::SurfaceId>(RootTag()));
459
451
 
460
452
  // This is needed to ensure that the unmount JS logic is completed before the the instance is shutdown during
461
- // instance destruction. Aligns with similar code in ReactInstanceWin::DetachRootView for paper Future: Instead this
462
- // method should return a Promise, which should be resolved when the JS logic is complete.
463
- // The task will auto set the event on destruction to ensure that the event is set if the JS Queue has already been
464
- // shutdown
453
+ // instance destruction. Aligns with similar code in ReactInstanceWin::DetachRootView for paper Future: Instead
454
+ // this method should return a Promise, which should be resolved when the JS logic is complete. The task will auto
455
+ // set the event on destruction to ensure that the event is set if the JS Queue has already been shutdown
465
456
  Mso::ManualResetEvent mre;
466
457
  m_context.JSDispatcher().Post([autoMRE = std::make_unique<AutoMRE>(AutoMRE{mre})]() {});
467
458
  mre.Wait();
@@ -526,9 +517,8 @@ facebook::react::AttributedStringBox CreateLoadingAttributedString() noexcept {
526
517
  return facebook::react::AttributedStringBox{attributedString};
527
518
  }
528
519
 
529
- facebook::react::Size MeasureLoading(
530
- const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
531
- float scaleFactor) {
520
+ facebook::react::Size ReactNativeIsland::MeasureLoading(
521
+ const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints) const noexcept {
532
522
  facebook::react::LayoutConstraints fbLayoutConstraints;
533
523
  ApplyConstraints(layoutConstraints, fbLayoutConstraints);
534
524
 
@@ -541,7 +531,7 @@ facebook::react::Size MeasureLoading(
541
531
  winrt::check_hresult(textLayout->GetMetrics(&tm));
542
532
 
543
533
  return fbLayoutConstraints.clamp(
544
- {loadingActivityHorizontalOffset * scaleFactor + tm.width, loadingBarHeight * scaleFactor});
534
+ {loadingActivityHorizontalOffset * m_scaleFactor + tm.width, loadingBarHeight * m_scaleFactor});
545
535
  }
546
536
 
547
537
  winrt::event_token ReactNativeIsland::SizeChanged(
@@ -571,7 +561,7 @@ void ReactNativeIsland::NotifySizeChanged() noexcept {
571
561
  if (rootComponentView) {
572
562
  size = rootComponentView->layoutMetrics().frame.size;
573
563
  } else if (m_loadingVisual) {
574
- size = MeasureLoading(m_layoutConstraints, m_scaleFactor);
564
+ size = MeasureLoading(m_layoutConstraints);
575
565
  }
576
566
 
577
567
  m_size = {size.width, size.height};
@@ -665,11 +655,34 @@ void ReactNativeIsland::ShowInstanceLoading() noexcept {
665
655
  InternalRootVisual().InsertAt(m_loadingVisual, m_hasRenderedVisual ? 1 : 0);
666
656
  }
667
657
 
658
+ void ReactNativeIsland::InitTextScaleMultiplier() noexcept {
659
+ m_uiSettings = winrt::Windows::UI::ViewManagement::UISettings();
660
+ m_textScaleMultiplier = static_cast<float>(m_uiSettings.TextScaleFactor());
661
+ m_textScaleChangedRevoker = m_uiSettings.TextScaleFactorChanged(
662
+ winrt::auto_revoke,
663
+ [this](const winrt::Windows::UI::ViewManagement::UISettings &uiSettings, const winrt::IInspectable &) {
664
+ if (m_context) {
665
+ m_context.UIDispatcher().Post(
666
+ [wkThis = get_weak(), textScaleMultiplier = static_cast<float>(uiSettings.TextScaleFactor())]() {
667
+ if (auto strongThis = wkThis.get()) {
668
+ strongThis->m_textScaleMultiplier = textScaleMultiplier;
669
+ strongThis->Arrange(strongThis->m_layoutConstraints, strongThis->m_viewportOffset);
670
+ }
671
+ });
672
+ }
673
+ });
674
+ }
675
+
668
676
  winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
669
677
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
670
- const winrt::Windows::Foundation::Point &viewportOffset) const noexcept {
678
+ const winrt::Windows::Foundation::Point &viewportOffset) const {
671
679
  facebook::react::Size size{0, 0};
672
680
 
681
+ if (layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::LeftToRight &&
682
+ layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::RightToLeft &&
683
+ layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::Undefined)
684
+ winrt::throw_hresult(E_INVALIDARG);
685
+
673
686
  facebook::react::LayoutConstraints constraints;
674
687
  ApplyConstraints(layoutConstraints, constraints);
675
688
 
@@ -677,15 +690,14 @@ winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
677
690
  if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
678
691
  winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
679
692
  facebook::react::LayoutContext context;
680
- // TODO scaling factor
693
+ context.fontSizeMultiplier = m_textScaleMultiplier;
681
694
  context.pointScaleFactor = static_cast<facebook::react::Float>(m_scaleFactor);
682
- context.fontSizeMultiplier = static_cast<facebook::react::Float>(m_scaleFactor);
683
695
  context.viewportOffset = {viewportOffset.X, viewportOffset.Y};
684
696
 
685
697
  size = fabricuiManager->measureSurface(static_cast<facebook::react::SurfaceId>(m_rootTag), constraints, context);
686
698
  }
687
699
  } else if (m_loadingVisual) {
688
- size = MeasureLoading(layoutConstraints, m_scaleFactor);
700
+ size = MeasureLoading(layoutConstraints);
689
701
  }
690
702
 
691
703
  auto clampedSize = constraints.clamp(size);
@@ -694,7 +706,12 @@ winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
694
706
 
695
707
  void ReactNativeIsland::Arrange(
696
708
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
697
- const winrt::Windows::Foundation::Point &viewportOffset) noexcept {
709
+ const winrt::Windows::Foundation::Point &viewportOffset) {
710
+ if (layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::LeftToRight &&
711
+ layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::RightToLeft &&
712
+ layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::Undefined)
713
+ winrt::throw_hresult(E_INVALIDARG);
714
+
698
715
  m_layoutConstraints = layoutConstraints;
699
716
  m_viewportOffset = viewportOffset;
700
717
  facebook::react::LayoutConstraints fbLayoutConstraints;
@@ -704,8 +721,8 @@ void ReactNativeIsland::Arrange(
704
721
  if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
705
722
  winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
706
723
  facebook::react::LayoutContext context;
724
+ context.fontSizeMultiplier = m_textScaleMultiplier;
707
725
  context.pointScaleFactor = static_cast<facebook::react::Float>(m_scaleFactor);
708
- context.fontSizeMultiplier = static_cast<facebook::react::Float>(m_scaleFactor);
709
726
  context.viewportOffset = {viewportOffset.X, viewportOffset.Y};
710
727
 
711
728
  fabricuiManager->constraintSurfaceLayout(
@@ -713,12 +730,11 @@ void ReactNativeIsland::Arrange(
713
730
  }
714
731
  } else if (m_loadingVisual) {
715
732
  // TODO: Resize to align loading
716
- auto s = fbLayoutConstraints.clamp(MeasureLoading(layoutConstraints, m_scaleFactor));
733
+ auto s = fbLayoutConstraints.clamp(MeasureLoading(layoutConstraints));
717
734
  NotifySizeChanged();
718
735
  }
719
736
  }
720
737
 
721
- #ifdef USE_WINUI3
722
738
  winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
723
739
  if (!m_compositor) {
724
740
  return nullptr;
@@ -772,6 +788,9 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
772
788
  if (args.DidRasterizationScaleChange()) {
773
789
  pThis->ScaleFactor(island.RasterizationScale());
774
790
  }
791
+ if (args.DidLayoutDirectionChange()) {
792
+ pThis->Arrange(pThis->m_layoutConstraints, pThis->m_viewportOffset);
793
+ }
775
794
  #ifndef USE_EXPERIMENTAL_WINUI3 // Use this in place of Connected/Disconnected events for now. -- Its not quite what we
776
795
  // want, but it will do for now.
777
796
  if (args.DidSiteVisibleChange()) {
@@ -804,7 +823,6 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
804
823
  }
805
824
  return m_island;
806
825
  }
807
- #endif
808
826
 
809
827
  void ReactNativeIsland::OnMounted() noexcept {
810
828
  if (m_mounted)
@@ -10,6 +10,7 @@
10
10
  #include <react/renderer/core/LayoutConstraints.h>
11
11
  #include <winrt/Microsoft.ReactNative.Composition.Experimental.h>
12
12
  #include <winrt/Microsoft.ReactNative.h>
13
+ #include <winrt/Windows.UI.ViewManagement.h>
13
14
  #include "CompositionEventHandler.h"
14
15
  #include "ReactHost/React.h"
15
16
 
@@ -46,10 +47,8 @@ struct ReactNativeIsland
46
47
  ReactNativeIsland() noexcept;
47
48
  ~ReactNativeIsland() noexcept;
48
49
 
49
- #ifdef USE_WINUI3
50
50
  ReactNativeIsland(const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept;
51
51
  winrt::Microsoft::UI::Content::ContentIsland Island();
52
- #endif
53
52
 
54
53
  // property ReactViewHost
55
54
  ReactNative::IReactViewHost ReactViewHost() noexcept;
@@ -72,6 +71,8 @@ struct ReactNativeIsland
72
71
  float ScaleFactor() noexcept;
73
72
  void ScaleFactor(float value) noexcept;
74
73
 
74
+ float FontSizeMultiplier() const noexcept;
75
+
75
76
  winrt::event_token SizeChanged(
76
77
  winrt::Windows::Foundation::EventHandler<winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs> const
77
78
  &handler) noexcept;
@@ -90,10 +91,10 @@ struct ReactNativeIsland
90
91
 
91
92
  winrt::Windows::Foundation::Size Measure(
92
93
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
93
- const winrt::Windows::Foundation::Point &viewportOffset) const noexcept;
94
+ const winrt::Windows::Foundation::Point &viewportOffset) const;
94
95
  void Arrange(
95
96
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
96
- const winrt::Windows::Foundation::Point &viewportOffset) noexcept;
97
+ const winrt::Windows::Foundation::Point &viewportOffset);
97
98
 
98
99
  winrt::Microsoft::ReactNative::FocusNavigationResult NavigateFocus(
99
100
  const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept;
@@ -143,6 +144,9 @@ struct ReactNativeIsland
143
144
  winrt::IInspectable m_uiaProvider{nullptr};
144
145
  int64_t m_rootTag{-1};
145
146
  float m_scaleFactor{1.0};
147
+ float m_textScaleMultiplier{1.0};
148
+ winrt::Windows::UI::ViewManagement::UISettings::TextScaleFactorChanged_revoker m_textScaleChangedRevoker;
149
+ winrt::Windows::UI::ViewManagement::UISettings m_uiSettings{nullptr};
146
150
  winrt::Windows::Foundation::Size m_size{0, 0};
147
151
  winrt::Microsoft::ReactNative::ReactContext m_context;
148
152
  winrt::Microsoft::ReactNative::IReactViewHost m_reactViewHost;
@@ -168,6 +172,12 @@ struct ReactNativeIsland
168
172
  void UpdateRootVisualSize() noexcept;
169
173
  void UpdateLoadingVisualSize() noexcept;
170
174
  Composition::Experimental::IDrawingSurfaceBrush CreateLoadingVisualBrush() noexcept;
175
+ void ApplyConstraints(
176
+ const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraintsIn,
177
+ facebook::react::LayoutConstraints &layoutConstraintsOut) const noexcept;
178
+ facebook::react::Size MeasureLoading(
179
+ const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints) const noexcept;
180
+ void InitTextScaleMultiplier() noexcept;
171
181
  };
172
182
 
173
183
  } // namespace winrt::Microsoft::ReactNative::implementation
@@ -40,8 +40,8 @@ winrt::Microsoft::ReactNative::ComponentView RootComponentView::Create(
40
40
  return winrt::make<RootComponentView>(compContext, tag, reactContext);
41
41
  }
42
42
 
43
- RootComponentView *RootComponentView::rootComponentView() noexcept {
44
- return this;
43
+ RootComponentView *RootComponentView::rootComponentView() const noexcept {
44
+ return const_cast<RootComponentView *>(this);
45
45
  }
46
46
 
47
47
  void RootComponentView::updateLayoutMetrics(
@@ -91,12 +91,18 @@ bool RootComponentView::NavigateFocus(const winrt::Microsoft::ReactNative::Focus
91
91
  ? FocusManager::FindFirstFocusableElement(*this)
92
92
  : FocusManager::FindLastFocusableElement(*this);
93
93
  if (view) {
94
- TrySetFocusedComponent(view);
94
+ TrySetFocusedComponent(
95
+ view,
96
+ request.Reason() == winrt::Microsoft::ReactNative::FocusNavigationReason::First
97
+ ? winrt::Microsoft::ReactNative::FocusNavigationDirection::First
98
+ : winrt::Microsoft::ReactNative::FocusNavigationDirection::Last);
95
99
  }
96
100
  return view != nullptr;
97
101
  }
98
102
 
99
- bool RootComponentView::TrySetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
103
+ bool RootComponentView::TrySetFocusedComponent(
104
+ const winrt::Microsoft::ReactNative::ComponentView &view,
105
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction) noexcept {
100
106
  auto target = view;
101
107
  auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
102
108
  if (selfView && !selfView->focusable()) {
@@ -110,7 +116,7 @@ bool RootComponentView::TrySetFocusedComponent(const winrt::Microsoft::ReactNati
110
116
  return false;
111
117
 
112
118
  auto losingFocusArgs = winrt::make<winrt::Microsoft::ReactNative::implementation::LosingFocusEventArgs>(
113
- target, m_focusedComponent, target);
119
+ target, direction, m_focusedComponent, target);
114
120
  if (m_focusedComponent) {
115
121
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_focusedComponent)
116
122
  ->onLosingFocus(losingFocusArgs);
@@ -118,7 +124,7 @@ bool RootComponentView::TrySetFocusedComponent(const winrt::Microsoft::ReactNati
118
124
 
119
125
  if (losingFocusArgs.NewFocusedComponent()) {
120
126
  auto gettingFocusArgs = winrt::make<winrt::Microsoft::ReactNative::implementation::GettingFocusEventArgs>(
121
- target, m_focusedComponent, losingFocusArgs.NewFocusedComponent());
127
+ target, direction, m_focusedComponent, losingFocusArgs.NewFocusedComponent());
122
128
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(losingFocusArgs.NewFocusedComponent())
123
129
  ->onGettingFocus(gettingFocusArgs);
124
130
 
@@ -138,13 +144,16 @@ bool RootComponentView::TryMoveFocus(bool next) noexcept {
138
144
  }
139
145
 
140
146
  Mso::Functor<bool(const winrt::Microsoft::ReactNative::ComponentView &)> fn =
141
- [currentlyFocused = m_focusedComponent](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
147
+ [currentlyFocused = m_focusedComponent, next](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
142
148
  if (view == currentlyFocused)
143
149
  return false;
144
150
 
145
151
  return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view)
146
152
  ->rootComponentView()
147
- ->TrySetFocusedComponent(view);
153
+ ->TrySetFocusedComponent(
154
+ view,
155
+ next ? winrt::Microsoft::ReactNative::FocusNavigationDirection::Next
156
+ : winrt::Microsoft::ReactNative::FocusNavigationDirection::Previous);
148
157
  };
149
158
 
150
159
  return winrt::Microsoft::ReactNative::implementation::walkTree(m_focusedComponent, next, fn);
@@ -202,6 +211,15 @@ winrt::IInspectable RootComponentView::UiaProviderFromPoint(const POINT &ptPixel
202
211
  return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view)->EnsureUiaProvider();
203
212
  }
204
213
 
214
+ float RootComponentView::FontSizeMultiplier() const noexcept {
215
+ if (auto rootView = m_wkRootView.get()) {
216
+ return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)
217
+ ->FontSizeMultiplier();
218
+ }
219
+ assert(false);
220
+ return 1.0f;
221
+ }
222
+
205
223
  winrt::Microsoft::UI::Content::ContentIsland RootComponentView::parentContentIsland() noexcept {
206
224
  if (auto rootView = m_wkRootView.get()) {
207
225
  return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)->Island();
@@ -28,13 +28,15 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
28
28
 
29
29
  winrt::Microsoft::ReactNative::ComponentView GetFocusedComponent() noexcept;
30
30
  void SetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &value) noexcept;
31
- bool TrySetFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &view) noexcept;
31
+ bool TrySetFocusedComponent(
32
+ const winrt::Microsoft::ReactNative::ComponentView &view,
33
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction) noexcept;
32
34
 
33
35
  bool NavigateFocus(const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept;
34
36
 
35
37
  bool TryMoveFocus(bool next) noexcept;
36
38
 
37
- RootComponentView *rootComponentView() noexcept override;
39
+ RootComponentView *rootComponentView() const noexcept override;
38
40
 
39
41
  winrt::Microsoft::UI::Content::ContentIsland parentContentIsland() noexcept;
40
42
 
@@ -44,6 +46,7 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
44
46
 
45
47
  HRESULT GetFragmentRoot(IRawElementProviderFragmentRoot **pRetVal) noexcept;
46
48
  winrt::Microsoft::ReactNative::implementation::ClipState getClipState() noexcept override;
49
+ float FontSizeMultiplier() const noexcept;
47
50
 
48
51
  void updateLayoutMetrics(
49
52
  facebook::react::LayoutMetrics const &layoutMetrics,
@@ -749,6 +749,10 @@ void ScrollViewComponentView::updateProps(
749
749
  m_horizontalScrollbarComponent->UpdateColorForScrollBarRegions();
750
750
  m_verticalScrollbarComponent->UpdateColorForScrollBarRegions();
751
751
  }
752
+
753
+ if (!oldProps || oldViewProps.horizontal != newViewProps.horizontal) {
754
+ m_scrollVisual.Horizontal(newViewProps.horizontal);
755
+ }
752
756
  }
753
757
 
754
758
  void ScrollViewComponentView::updateState(
@@ -886,6 +890,12 @@ void ScrollViewComponentView::OnPointerPressed(
886
890
  m_verticalScrollbarComponent->OnPointerPressed(args);
887
891
  m_horizontalScrollbarComponent->OnPointerPressed(args);
888
892
  Super::OnPointerPressed(args);
893
+
894
+ if (!args.Handled()) {
895
+ auto f = args.Pointer();
896
+ auto g = f.PointerDeviceType();
897
+ m_scrollVisual.OnPointerPressed(args);
898
+ }
889
899
  }
890
900
 
891
901
  void ScrollViewComponentView::OnPointerReleased(
@@ -1045,13 +1055,16 @@ bool ScrollViewComponentView::scrollRight(float delta, bool animate) noexcept {
1045
1055
  return true;
1046
1056
  }
1047
1057
 
1048
- void ScrollViewComponentView::HandleCommand(
1049
- winrt::hstring commandName,
1050
- const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept {
1058
+ void ScrollViewComponentView::HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept {
1059
+ Super::HandleCommand(args);
1060
+ if (args.Handled())
1061
+ return;
1062
+
1063
+ auto commandName = args.CommandName();
1051
1064
  if (commandName == L"scrollTo") {
1052
1065
  double x, y;
1053
1066
  bool animate;
1054
- winrt::Microsoft::ReactNative::ReadArgs(args, x, y, animate);
1067
+ winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), x, y, animate);
1055
1068
  scrollTo(
1056
1069
  {static_cast<float>(x) * m_layoutMetrics.pointScaleFactor,
1057
1070
  static_cast<float>(y) * m_layoutMetrics.pointScaleFactor,
@@ -1061,12 +1074,10 @@ void ScrollViewComponentView::HandleCommand(
1061
1074
  // No-op for now
1062
1075
  } else if (commandName == L"scrollToEnd") {
1063
1076
  bool animate;
1064
- winrt::Microsoft::ReactNative::ReadArgs(args, animate);
1077
+ winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), animate);
1065
1078
  scrollToEnd(animate);
1066
1079
  } else if (commandName == L"zoomToRect") {
1067
1080
  // No-op for now
1068
- } else {
1069
- Super::HandleCommand(commandName, args);
1070
1081
  }
1071
1082
  }
1072
1083
 
@@ -74,8 +74,7 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
74
74
  void prepareForRecycle() noexcept override;
75
75
  void OnKeyDown(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
76
76
 
77
- void HandleCommand(winrt::hstring commandName, const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept
78
- override;
77
+ void HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept override;
79
78
  facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents)
80
79
  const noexcept override;
81
80
  facebook::react::Point getClientOffset() const noexcept override;
@@ -56,14 +56,14 @@ void SwitchComponentView::UnmountChildComponentView(
56
56
  base_type::UnmountChildComponentView(childComponentView, index);
57
57
  }
58
58
 
59
- void SwitchComponentView::HandleCommand(
60
- winrt::hstring commandName,
61
- const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept {
59
+ void SwitchComponentView::HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept {
60
+ Super::HandleCommand(args);
61
+ if (args.Handled())
62
+ return;
63
+ auto commandName = args.CommandName();
62
64
  if (commandName == L"setValue") {
63
65
  // TODO - Current implementation always aligns with JS value
64
66
  // This will be needed when we move to using WinUI controls
65
- } else {
66
- Super::HandleCommand(commandName, args);
67
67
  }
68
68
  }
69
69
 
@@ -261,7 +261,7 @@ void SwitchComponentView::OnPointerPressed(
261
261
  m_supressAnimationForNextFrame = true;
262
262
 
263
263
  if (auto root = rootComponentView()) {
264
- root->TrySetFocusedComponent(*get_strong());
264
+ root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
265
265
  }
266
266
 
267
267
  updateVisuals();
@@ -27,8 +27,7 @@ struct SwitchComponentView : SwitchComponentViewT<SwitchComponentView, ViewCompo
27
27
  void UnmountChildComponentView(
28
28
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
29
29
  uint32_t index) noexcept override;
30
- void HandleCommand(winrt::hstring commandName, const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept
31
- override;
30
+ void HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept override;
32
31
  void updateProps(facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept
33
32
  override;
34
33
  void updateState(facebook::react::State::Shared const &state, facebook::react::State::Shared const &oldState) noexcept