react-native-windows 0.75.4 → 0.75.6

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 (73) hide show
  1. package/Microsoft.ReactNative/ComponentView.idl +11 -0
  2. package/Microsoft.ReactNative/Composition.Input.idl +1 -0
  3. package/Microsoft.ReactNative/CompositionSwitcher.idl +3 -0
  4. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +19 -9
  5. package/Microsoft.ReactNative/Fabric/ComponentView.h +8 -6
  6. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +4 -0
  7. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +1 -0
  8. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +44 -13
  9. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +76 -1
  10. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +8 -2
  11. package/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp +1 -0
  12. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +35 -8
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +4 -3
  14. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +8 -6
  15. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.h +1 -2
  16. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +20 -6
  17. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +13 -6
  18. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +2 -3
  19. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +1 -2
  20. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +80 -57
  21. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +15 -4
  22. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +37 -8
  23. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +7 -2
  24. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +18 -7
  25. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +1 -2
  26. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +6 -6
  27. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h +1 -2
  28. package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.cpp +1 -2
  29. package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.h +1 -1
  30. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +97 -140
  31. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +8 -4
  32. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +14 -11
  33. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.h +4 -4
  34. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.cpp +0 -13
  35. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.h +0 -3
  36. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +12 -4
  37. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +338 -0
  38. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.h +66 -0
  39. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +37 -4
  40. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +3 -0
  41. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -2
  42. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.h +1 -2
  43. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +31 -3
  44. package/Microsoft.ReactNative/Fabric/ReactTaggedView.h +4 -0
  45. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +5 -0
  46. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h +1 -1
  47. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewTraitsInitializer.h +1 -1
  48. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +9 -2
  49. package/Microsoft.ReactNative/IReactViewComponentBuilder.idl +8 -1
  50. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -1
  51. package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +9 -0
  52. package/Microsoft.ReactNative/Modules/LogBoxModule.h +2 -0
  53. package/Microsoft.ReactNative/Modules/SampleTurboModule.cpp +104 -0
  54. package/Microsoft.ReactNative/Modules/SampleTurboModule.h +78 -0
  55. package/Microsoft.ReactNative/ReactCoreInjection.h +0 -1
  56. package/Microsoft.ReactNative/ReactHost/MsoReactContext.cpp +0 -7
  57. package/Microsoft.ReactNative/ReactHost/MsoReactContext.h +0 -5
  58. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +17 -1
  59. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.cpp +59 -0
  60. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.h +23 -0
  61. package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +179 -0
  62. package/Microsoft.ReactNative/ReactNativeAppBuilder.h +35 -0
  63. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +69 -0
  64. package/Microsoft.ReactNative/ReactNativeIsland.idl +2 -0
  65. package/Microsoft.ReactNative/ReactNativeWin32App.cpp +82 -0
  66. package/Microsoft.ReactNative/ReactNativeWin32App.h +38 -0
  67. package/Microsoft.ReactNative/packages.lock.json +67 -40
  68. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  69. package/Shared/Shared.vcxitems +36 -0
  70. package/Shared/Shared.vcxitems.filters +3 -0
  71. package/Shared/TurboModuleManager.cpp +0 -3
  72. package/package.json +3 -3
  73. package/templates/cpp-app/windows/MyApp/MyApp.cpp +1 -0
@@ -22,19 +22,26 @@ int32_t GotFocusEventArgs::OriginalSource() noexcept {
22
22
 
23
23
  LosingFocusEventArgs::LosingFocusEventArgs(
24
24
  const winrt::Microsoft::ReactNative::ComponentView &originalSource,
25
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
25
26
  const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
26
27
  const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent)
27
28
  : m_originalSource(originalSource ? originalSource.Tag() : -1),
29
+ m_direction(direction),
28
30
  m_old(oldFocusedComponent),
29
31
  m_new(newFocusedComponent) {}
30
32
 
31
- int32_t LosingFocusEventArgs::OriginalSource() noexcept {
33
+ int32_t LosingFocusEventArgs::OriginalSource() const noexcept {
32
34
  return m_originalSource;
33
35
  }
34
- winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::NewFocusedComponent() noexcept {
36
+
37
+ winrt::Microsoft::ReactNative::FocusNavigationDirection LosingFocusEventArgs::Direction() const noexcept {
38
+ return m_direction;
39
+ }
40
+
41
+ winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::NewFocusedComponent() const noexcept {
35
42
  return m_new;
36
43
  }
37
- winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::OldFocusedComponent() noexcept {
44
+ winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::OldFocusedComponent() const noexcept {
38
45
  return m_old;
39
46
  }
40
47
 
@@ -58,19 +65,26 @@ void LosingFocusEventArgs::TrySetNewFocusedComponent(
58
65
 
59
66
  GettingFocusEventArgs::GettingFocusEventArgs(
60
67
  const winrt::Microsoft::ReactNative::ComponentView &originalSource,
68
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
61
69
  const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
62
70
  const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent)
63
71
  : m_originalSource(originalSource ? originalSource.Tag() : -1),
72
+ m_direction(direction),
64
73
  m_old(oldFocusedComponent),
65
74
  m_new(newFocusedComponent) {}
66
75
 
67
- int32_t GettingFocusEventArgs::OriginalSource() noexcept {
76
+ int32_t GettingFocusEventArgs::OriginalSource() const noexcept {
68
77
  return m_originalSource;
69
78
  }
70
- winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::NewFocusedComponent() noexcept {
79
+
80
+ winrt::Microsoft::ReactNative::FocusNavigationDirection GettingFocusEventArgs::Direction() const noexcept {
81
+ return m_direction;
82
+ }
83
+
84
+ winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::NewFocusedComponent() const noexcept {
71
85
  return m_new;
72
86
  }
73
- winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::OldFocusedComponent() noexcept {
87
+ winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::OldFocusedComponent() const noexcept {
74
88
  return m_old;
75
89
  }
76
90
 
@@ -32,17 +32,21 @@ struct LosingFocusEventArgs
32
32
  : winrt::Microsoft::ReactNative::implementation::LosingFocusEventArgsT<LosingFocusEventArgs> {
33
33
  LosingFocusEventArgs(
34
34
  const winrt::Microsoft::ReactNative::ComponentView &originalSource,
35
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
35
36
  const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
36
37
  const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent);
37
- int32_t OriginalSource() noexcept;
38
- winrt::Microsoft::ReactNative::ComponentView NewFocusedComponent() noexcept;
39
- winrt::Microsoft::ReactNative::ComponentView OldFocusedComponent() noexcept;
38
+ int32_t OriginalSource() const noexcept;
39
+ winrt::Microsoft::ReactNative::FocusNavigationDirection Direction() const noexcept;
40
+
41
+ winrt::Microsoft::ReactNative::ComponentView NewFocusedComponent() const noexcept;
42
+ winrt::Microsoft::ReactNative::ComponentView OldFocusedComponent() const noexcept;
40
43
 
41
44
  void TryCancel() noexcept;
42
45
  void TrySetNewFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent) noexcept;
43
46
 
44
47
  private:
45
48
  const int32_t m_originalSource;
49
+ const winrt::Microsoft::ReactNative::FocusNavigationDirection m_direction;
46
50
  winrt::Microsoft::ReactNative::ComponentView m_old{nullptr};
47
51
  winrt::Microsoft::ReactNative::ComponentView m_new{nullptr};
48
52
  };
@@ -51,17 +55,20 @@ struct GettingFocusEventArgs
51
55
  : winrt::Microsoft::ReactNative::implementation::GettingFocusEventArgsT<GettingFocusEventArgs> {
52
56
  GettingFocusEventArgs(
53
57
  const winrt::Microsoft::ReactNative::ComponentView &originalSource,
58
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
54
59
  const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
55
60
  const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent);
56
- int32_t OriginalSource() noexcept;
57
- winrt::Microsoft::ReactNative::ComponentView NewFocusedComponent() noexcept;
58
- winrt::Microsoft::ReactNative::ComponentView OldFocusedComponent() noexcept;
61
+ int32_t OriginalSource() const noexcept;
62
+ winrt::Microsoft::ReactNative::FocusNavigationDirection Direction() const noexcept;
63
+ winrt::Microsoft::ReactNative::ComponentView NewFocusedComponent() const noexcept;
64
+ winrt::Microsoft::ReactNative::ComponentView OldFocusedComponent() const noexcept;
59
65
 
60
66
  void TryCancel() noexcept;
61
67
  void TrySetNewFocusedComponent(const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent) noexcept;
62
68
 
63
69
  private:
64
70
  const int32_t m_originalSource;
71
+ const winrt::Microsoft::ReactNative::FocusNavigationDirection m_direction;
65
72
  winrt::Microsoft::ReactNative::ComponentView m_old{nullptr};
66
73
  winrt::Microsoft::ReactNative::ComponentView m_new{nullptr};
67
74
  };
@@ -191,9 +191,8 @@ void WindowsModalHostComponentView::UnmountChildComponentView(
191
191
  }
192
192
 
193
193
  void WindowsModalHostComponentView::HandleCommand(
194
- winrt::hstring commandName,
195
- const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept {
196
- Super::HandleCommand(commandName, args);
194
+ const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept {
195
+ Super::HandleCommand(args);
197
196
  }
198
197
 
199
198
  void WindowsModalHostComponentView::updateProps(
@@ -28,8 +28,7 @@ struct WindowsModalHostComponentView
28
28
  void UnmountChildComponentView(
29
29
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
30
30
  uint32_t index) noexcept override;
31
- void HandleCommand(winrt::hstring commandName, const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept
32
- override;
31
+ void HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept override;
33
32
  void updateState(facebook::react::State::Shared const &state, facebook::react::State::Shared const &oldState) noexcept
34
33
  override;
35
34
 
@@ -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
@@ -169,6 +157,7 @@ void ReactNativeIsland::ReactViewHost(winrt::Microsoft::ReactNative::IReactViewH
169
157
  }
170
158
 
171
159
  if (m_reactViewHost) {
160
+ UninitRootView();
172
161
  m_reactViewHost.DetachViewInstance();
173
162
  }
174
163
 
@@ -275,6 +264,10 @@ void ReactNativeIsland::ScaleFactor(float value) noexcept {
275
264
  }
276
265
  }
277
266
 
267
+ float ReactNativeIsland::FontSizeMultiplier() const noexcept {
268
+ return m_textScaleMultiplier;
269
+ }
270
+
278
271
  int64_t ReactNativeIsland::RootTag() const noexcept {
279
272
  return m_rootTag;
280
273
  }
@@ -340,7 +333,7 @@ winrt::IInspectable ReactNativeIsland::GetUiaProvider() noexcept {
340
333
  if (m_uiaProvider == nullptr) {
341
334
  m_uiaProvider =
342
335
  winrt::make<winrt::Microsoft::ReactNative::implementation::CompositionRootAutomationProvider>(*this);
343
- if (m_hwnd) {
336
+ if (m_hwnd && !m_island) {
344
337
  auto pRootProvider =
345
338
  static_cast<winrt::Microsoft::ReactNative::implementation::CompositionRootAutomationProvider *>(
346
339
  m_uiaProvider.as<IRawElementProviderSimple>().get());
@@ -356,6 +349,10 @@ void ReactNativeIsland::SetWindow(uint64_t hwnd) noexcept {
356
349
  m_hwnd = reinterpret_cast<HWND>(hwnd);
357
350
  }
358
351
 
352
+ HWND ReactNativeIsland::GetHwndForParenting() noexcept {
353
+ return m_hwnd;
354
+ }
355
+
359
356
  int64_t ReactNativeIsland::SendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept {
360
357
  if (m_rootTag == -1)
361
358
  return 0;
@@ -375,7 +372,7 @@ int64_t ReactNativeIsland::SendMessage(uint32_t msg, uint64_t wParam, int64_t lP
375
372
  bool ReactNativeIsland::CapturePointer(
376
373
  const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer,
377
374
  facebook::react::Tag tag) noexcept {
378
- if (m_hwnd) {
375
+ if (m_hwnd && !m_island) {
379
376
  SetCapture(m_hwnd);
380
377
  }
381
378
  return m_CompositionEventHandler->CapturePointer(pointer, tag);
@@ -385,7 +382,7 @@ void ReactNativeIsland::ReleasePointerCapture(
385
382
  const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer,
386
383
  facebook::react::Tag tag) noexcept {
387
384
  if (m_CompositionEventHandler->ReleasePointerCapture(pointer, tag)) {
388
- if (m_hwnd) {
385
+ if (m_hwnd && !m_island) {
389
386
  if (m_hwnd == GetCapture()) {
390
387
  ReleaseCapture();
391
388
  }
@@ -458,10 +455,9 @@ void ReactNativeIsland::UninitRootView() noexcept {
458
455
  uiManager->stopSurface(static_cast<facebook::react::SurfaceId>(RootTag()));
459
456
 
460
457
  // 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
458
+ // instance destruction. Aligns with similar code in ReactInstanceWin::DetachRootView for paper Future: Instead
459
+ // this method should return a Promise, which should be resolved when the JS logic is complete. The task will auto
460
+ // set the event on destruction to ensure that the event is set if the JS Queue has already been shutdown
465
461
  Mso::ManualResetEvent mre;
466
462
  m_context.JSDispatcher().Post([autoMRE = std::make_unique<AutoMRE>(AutoMRE{mre})]() {});
467
463
  mre.Wait();
@@ -526,9 +522,8 @@ facebook::react::AttributedStringBox CreateLoadingAttributedString() noexcept {
526
522
  return facebook::react::AttributedStringBox{attributedString};
527
523
  }
528
524
 
529
- facebook::react::Size MeasureLoading(
530
- const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
531
- float scaleFactor) {
525
+ facebook::react::Size ReactNativeIsland::MeasureLoading(
526
+ const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints) const noexcept {
532
527
  facebook::react::LayoutConstraints fbLayoutConstraints;
533
528
  ApplyConstraints(layoutConstraints, fbLayoutConstraints);
534
529
 
@@ -541,7 +536,7 @@ facebook::react::Size MeasureLoading(
541
536
  winrt::check_hresult(textLayout->GetMetrics(&tm));
542
537
 
543
538
  return fbLayoutConstraints.clamp(
544
- {loadingActivityHorizontalOffset * scaleFactor + tm.width, loadingBarHeight * scaleFactor});
539
+ {loadingActivityHorizontalOffset * m_scaleFactor + tm.width, loadingBarHeight * m_scaleFactor});
545
540
  }
546
541
 
547
542
  winrt::event_token ReactNativeIsland::SizeChanged(
@@ -571,7 +566,7 @@ void ReactNativeIsland::NotifySizeChanged() noexcept {
571
566
  if (rootComponentView) {
572
567
  size = rootComponentView->layoutMetrics().frame.size;
573
568
  } else if (m_loadingVisual) {
574
- size = MeasureLoading(m_layoutConstraints, m_scaleFactor);
569
+ size = MeasureLoading(m_layoutConstraints);
575
570
  }
576
571
 
577
572
  m_size = {size.width, size.height};
@@ -665,11 +660,34 @@ void ReactNativeIsland::ShowInstanceLoading() noexcept {
665
660
  InternalRootVisual().InsertAt(m_loadingVisual, m_hasRenderedVisual ? 1 : 0);
666
661
  }
667
662
 
663
+ void ReactNativeIsland::InitTextScaleMultiplier() noexcept {
664
+ m_uiSettings = winrt::Windows::UI::ViewManagement::UISettings();
665
+ m_textScaleMultiplier = static_cast<float>(m_uiSettings.TextScaleFactor());
666
+ m_textScaleChangedRevoker = m_uiSettings.TextScaleFactorChanged(
667
+ winrt::auto_revoke,
668
+ [this](const winrt::Windows::UI::ViewManagement::UISettings &uiSettings, const winrt::IInspectable &) {
669
+ if (m_context) {
670
+ m_context.UIDispatcher().Post(
671
+ [wkThis = get_weak(), textScaleMultiplier = static_cast<float>(uiSettings.TextScaleFactor())]() {
672
+ if (auto strongThis = wkThis.get()) {
673
+ strongThis->m_textScaleMultiplier = textScaleMultiplier;
674
+ strongThis->Arrange(strongThis->m_layoutConstraints, strongThis->m_viewportOffset);
675
+ }
676
+ });
677
+ }
678
+ });
679
+ }
680
+
668
681
  winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
669
682
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
670
- const winrt::Windows::Foundation::Point &viewportOffset) const noexcept {
683
+ const winrt::Windows::Foundation::Point &viewportOffset) const {
671
684
  facebook::react::Size size{0, 0};
672
685
 
686
+ if (layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::LeftToRight &&
687
+ layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::RightToLeft &&
688
+ layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::Undefined)
689
+ winrt::throw_hresult(E_INVALIDARG);
690
+
673
691
  facebook::react::LayoutConstraints constraints;
674
692
  ApplyConstraints(layoutConstraints, constraints);
675
693
 
@@ -677,15 +695,14 @@ winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
677
695
  if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
678
696
  winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
679
697
  facebook::react::LayoutContext context;
680
- // TODO scaling factor
698
+ context.fontSizeMultiplier = m_textScaleMultiplier;
681
699
  context.pointScaleFactor = static_cast<facebook::react::Float>(m_scaleFactor);
682
- context.fontSizeMultiplier = static_cast<facebook::react::Float>(m_scaleFactor);
683
700
  context.viewportOffset = {viewportOffset.X, viewportOffset.Y};
684
701
 
685
702
  size = fabricuiManager->measureSurface(static_cast<facebook::react::SurfaceId>(m_rootTag), constraints, context);
686
703
  }
687
704
  } else if (m_loadingVisual) {
688
- size = MeasureLoading(layoutConstraints, m_scaleFactor);
705
+ size = MeasureLoading(layoutConstraints);
689
706
  }
690
707
 
691
708
  auto clampedSize = constraints.clamp(size);
@@ -694,7 +711,12 @@ winrt::Windows::Foundation::Size ReactNativeIsland::Measure(
694
711
 
695
712
  void ReactNativeIsland::Arrange(
696
713
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
697
- const winrt::Windows::Foundation::Point &viewportOffset) noexcept {
714
+ const winrt::Windows::Foundation::Point &viewportOffset) {
715
+ if (layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::LeftToRight &&
716
+ layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::RightToLeft &&
717
+ layoutConstraints.LayoutDirection != winrt::Microsoft::ReactNative::LayoutDirection::Undefined)
718
+ winrt::throw_hresult(E_INVALIDARG);
719
+
698
720
  m_layoutConstraints = layoutConstraints;
699
721
  m_viewportOffset = viewportOffset;
700
722
  facebook::react::LayoutConstraints fbLayoutConstraints;
@@ -704,8 +726,8 @@ void ReactNativeIsland::Arrange(
704
726
  if (auto fabricuiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
705
727
  winrt::Microsoft::ReactNative::ReactPropertyBag(m_context.Properties()))) {
706
728
  facebook::react::LayoutContext context;
729
+ context.fontSizeMultiplier = m_textScaleMultiplier;
707
730
  context.pointScaleFactor = static_cast<facebook::react::Float>(m_scaleFactor);
708
- context.fontSizeMultiplier = static_cast<facebook::react::Float>(m_scaleFactor);
709
731
  context.viewportOffset = {viewportOffset.X, viewportOffset.Y};
710
732
 
711
733
  fabricuiManager->constraintSurfaceLayout(
@@ -713,12 +735,11 @@ void ReactNativeIsland::Arrange(
713
735
  }
714
736
  } else if (m_loadingVisual) {
715
737
  // TODO: Resize to align loading
716
- auto s = fbLayoutConstraints.clamp(MeasureLoading(layoutConstraints, m_scaleFactor));
738
+ auto s = fbLayoutConstraints.clamp(MeasureLoading(layoutConstraints));
717
739
  NotifySizeChanged();
718
740
  }
719
741
  }
720
742
 
721
- #ifdef USE_WINUI3
722
743
  winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
723
744
  if (!m_compositor) {
724
745
  return nullptr;
@@ -772,6 +793,9 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
772
793
  if (args.DidRasterizationScaleChange()) {
773
794
  pThis->ScaleFactor(island.RasterizationScale());
774
795
  }
796
+ if (args.DidLayoutDirectionChange()) {
797
+ pThis->Arrange(pThis->m_layoutConstraints, pThis->m_viewportOffset);
798
+ }
775
799
  #ifndef USE_EXPERIMENTAL_WINUI3 // Use this in place of Connected/Disconnected events for now. -- Its not quite what we
776
800
  // want, but it will do for now.
777
801
  if (args.DidSiteVisibleChange()) {
@@ -804,7 +828,6 @@ winrt::Microsoft::UI::Content::ContentIsland ReactNativeIsland::Island() {
804
828
  }
805
829
  return m_island;
806
830
  }
807
- #endif
808
831
 
809
832
  void ReactNativeIsland::OnMounted() noexcept {
810
833
  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;
@@ -81,6 +82,7 @@ struct ReactNativeIsland
81
82
  void AddRenderedVisual(const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual) noexcept;
82
83
  void RemoveRenderedVisual(const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual) noexcept;
83
84
  bool TrySetFocus() noexcept;
85
+ HWND GetHwndForParenting() noexcept;
84
86
 
85
87
  winrt::Microsoft::ReactNative::Composition::ICustomResourceLoader Resources() noexcept;
86
88
  void Resources(const winrt::Microsoft::ReactNative::Composition::ICustomResourceLoader &resources) noexcept;
@@ -90,10 +92,10 @@ struct ReactNativeIsland
90
92
 
91
93
  winrt::Windows::Foundation::Size Measure(
92
94
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
93
- const winrt::Windows::Foundation::Point &viewportOffset) const noexcept;
95
+ const winrt::Windows::Foundation::Point &viewportOffset) const;
94
96
  void Arrange(
95
97
  const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints,
96
- const winrt::Windows::Foundation::Point &viewportOffset) noexcept;
98
+ const winrt::Windows::Foundation::Point &viewportOffset);
97
99
 
98
100
  winrt::Microsoft::ReactNative::FocusNavigationResult NavigateFocus(
99
101
  const winrt::Microsoft::ReactNative::FocusNavigationRequest &request) noexcept;
@@ -143,6 +145,9 @@ struct ReactNativeIsland
143
145
  winrt::IInspectable m_uiaProvider{nullptr};
144
146
  int64_t m_rootTag{-1};
145
147
  float m_scaleFactor{1.0};
148
+ float m_textScaleMultiplier{1.0};
149
+ winrt::Windows::UI::ViewManagement::UISettings::TextScaleFactorChanged_revoker m_textScaleChangedRevoker;
150
+ winrt::Windows::UI::ViewManagement::UISettings m_uiSettings{nullptr};
146
151
  winrt::Windows::Foundation::Size m_size{0, 0};
147
152
  winrt::Microsoft::ReactNative::ReactContext m_context;
148
153
  winrt::Microsoft::ReactNative::IReactViewHost m_reactViewHost;
@@ -168,6 +173,12 @@ struct ReactNativeIsland
168
173
  void UpdateRootVisualSize() noexcept;
169
174
  void UpdateLoadingVisualSize() noexcept;
170
175
  Composition::Experimental::IDrawingSurfaceBrush CreateLoadingVisualBrush() noexcept;
176
+ void ApplyConstraints(
177
+ const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraintsIn,
178
+ facebook::react::LayoutConstraints &layoutConstraintsOut) const noexcept;
179
+ facebook::react::Size MeasureLoading(
180
+ const winrt::Microsoft::ReactNative::LayoutConstraints &layoutConstraints) const noexcept;
181
+ void InitTextScaleMultiplier() noexcept;
171
182
  };
172
183
 
173
184
  } // 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();
@@ -213,4 +231,15 @@ winrt::Microsoft::ReactNative::implementation::ClipState RootComponentView::getC
213
231
  return winrt::Microsoft::ReactNative::implementation::ClipState::NoClip;
214
232
  }
215
233
 
234
+ HWND RootComponentView::GetHwndForParenting() noexcept {
235
+ if (auto rootView = m_wkRootView.get()) {
236
+ auto hwnd = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)
237
+ ->GetHwndForParenting();
238
+ if (hwnd)
239
+ return hwnd;
240
+ }
241
+
242
+ return base_type::GetHwndForParenting();
243
+ }
244
+
216
245
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -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,
@@ -61,6 +64,8 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
61
64
  winrt::Microsoft::ReactNative::ComponentView FindFirstFocusableElement() noexcept;
62
65
  winrt::Microsoft::ReactNative::ComponentView FindLastFocusableElement() noexcept;
63
66
 
67
+ HWND GetHwndForParenting() noexcept override;
68
+
64
69
  private:
65
70
  // should this be a ReactTaggedView? - It shouldn't actually matter since if the view is going away it should always
66
71
  // be clearing its focus But being a reactTaggedView might make it easier to identify cases where that isn't