react-native-windows 0.74.23 → 0.74.24

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 (44) hide show
  1. package/Microsoft.ReactNative/CompositionComponentView.idl +2 -1
  2. package/Microsoft.ReactNative/Fabric/AbiComponentDescriptor.cpp +4 -1
  3. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +1 -1
  4. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +7 -0
  5. package/Microsoft.ReactNative/Fabric/AbiViewProps.h +2 -0
  6. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +11 -4
  7. package/Microsoft.ReactNative/Fabric/ComponentView.h +3 -2
  8. package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.cpp +926 -0
  9. package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.h +76 -0
  10. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +31 -13
  11. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +27 -3
  12. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +3 -1
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +193 -892
  14. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +17 -22
  15. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +1 -1
  16. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +129 -122
  17. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +14 -8
  18. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +34 -20
  19. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +5 -3
  20. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +40 -2
  21. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +9 -0
  22. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +31 -3
  23. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +8 -8
  24. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +31 -1
  25. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +4 -0
  26. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +9 -3
  27. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +11 -0
  28. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +2 -0
  29. package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +1 -0
  30. package/Microsoft.ReactNative/IReactViewComponentBuilder.idl +1 -1
  31. package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +25 -129
  32. package/Microsoft.ReactNative/ReactNativeAppBuilder.h +5 -13
  33. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +13 -34
  34. package/Microsoft.ReactNative/ReactNativeIsland.idl +3 -2
  35. package/Microsoft.ReactNative/ReactNativeWin32App.cpp +129 -18
  36. package/Microsoft.ReactNative/ReactNativeWin32App.h +14 -5
  37. package/Microsoft.ReactNative/ViewProps.idl +2 -0
  38. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  39. package/Shared/Shared.vcxitems +3 -10
  40. package/Shared/Shared.vcxitems.filters +1 -0
  41. package/package.json +3 -3
  42. package/templates/cpp-app/windows/MyApp/MyApp.cpp +46 -130
  43. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.cpp +0 -59
  44. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.h +0 -23
@@ -127,6 +127,20 @@ ReactNativeIsland::ReactNativeIsland(const winrt::Microsoft::UI::Composition::Co
127
127
  InitTextScaleMultiplier();
128
128
  }
129
129
 
130
+ // Constructor to initialize ReactNativeIsland with context and componentView
131
+ ReactNativeIsland::ReactNativeIsland(
132
+ const winrt::Microsoft::UI::Composition::Compositor &compositor,
133
+ winrt::Microsoft::ReactNative::IReactContext context,
134
+ winrt::Microsoft::ReactNative::ComponentView componentView) noexcept
135
+ : m_compositor(compositor),
136
+ m_context(context),
137
+ m_layoutConstraints({{0, 0}, {0, 0}, winrt::Microsoft::ReactNative::LayoutDirection::Undefined}),
138
+ m_isFragment(true) {
139
+ m_rootTag = componentView.Tag();
140
+ InitTextScaleMultiplier();
141
+ AddFragmentCompositionEventHandler(context, componentView);
142
+ }
143
+
130
144
  ReactNativeIsland::ReactNativeIsland() noexcept : ReactNativeIsland(nullptr) {}
131
145
 
132
146
  ReactNativeIsland::~ReactNativeIsland() noexcept {
@@ -152,6 +166,7 @@ ReactNative::IReactViewHost ReactNativeIsland::ReactViewHost() noexcept {
152
166
  }
153
167
 
154
168
  void ReactNativeIsland::ReactViewHost(winrt::Microsoft::ReactNative::IReactViewHost const &value) noexcept {
169
+ assert(!m_isFragment); // make sure this isn't a FragmentIsalnd
155
170
  if (m_reactViewHost == value) {
156
171
  return;
157
172
  }
@@ -404,7 +419,7 @@ void ReactNativeIsland::InitRootView(
404
419
 
405
420
  m_context = winrt::Microsoft::ReactNative::ReactContext(std::move(context));
406
421
  m_reactViewOptions = std::move(viewOptions);
407
- m_CompositionEventHandler = std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this);
422
+ m_CompositionEventHandler = std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this, -1);
408
423
  m_CompositionEventHandler->Initialize();
409
424
 
410
425
  UpdateRootViewInternal();
@@ -412,6 +427,27 @@ void ReactNativeIsland::InitRootView(
412
427
  m_isInitialized = true;
413
428
  }
414
429
 
430
+ void ReactNativeIsland::AddFragmentCompositionEventHandler(
431
+ winrt::Microsoft::ReactNative::IReactContext context,
432
+ winrt::Microsoft::ReactNative::ComponentView componentView) noexcept {
433
+ m_uiDispatcher = context.Properties()
434
+ .Get(winrt::Microsoft::ReactNative::ReactDispatcherHelper::UIDispatcherProperty())
435
+ .try_as<IReactDispatcher>();
436
+ VerifyElseCrash(m_uiDispatcher.HasThreadAccess());
437
+ VerifyElseCrash(m_rootTag != -1);
438
+ auto uiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
439
+ winrt::Microsoft::ReactNative::ReactPropertyBag(context.Properties()));
440
+
441
+ if (!m_CompositionEventHandler) {
442
+ // Create CompositionEventHandler if not already created
443
+ m_context = winrt::Microsoft::ReactNative::ReactContext(context);
444
+ m_CompositionEventHandler =
445
+ std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this, componentView.Tag());
446
+ m_CompositionEventHandler->Initialize();
447
+ m_isInitialized = true;
448
+ }
449
+ }
450
+
415
451
  void ReactNativeIsland::UpdateRootView() noexcept {
416
452
  VerifyElseCrash(m_uiDispatcher.HasThreadAccess());
417
453
  VerifyElseCrash(m_isInitialized);
@@ -827,7 +863,9 @@ void ReactNativeIsland::OnMounted() noexcept {
827
863
  return;
828
864
  m_mounted = true;
829
865
  if (auto componentView = GetComponentView()) {
830
- componentView->onMounted();
866
+ if (!componentView->isMounted()) {
867
+ componentView->onMounted();
868
+ }
831
869
  }
832
870
  }
833
871
 
@@ -48,6 +48,10 @@ struct ReactNativeIsland
48
48
  ~ReactNativeIsland() noexcept;
49
49
 
50
50
  ReactNativeIsland(const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept;
51
+ ReactNativeIsland(
52
+ const winrt::Microsoft::UI::Composition::Compositor &compositor,
53
+ winrt::Microsoft::ReactNative::IReactContext context,
54
+ winrt::Microsoft::ReactNative::ComponentView componentView) noexcept;
51
55
  winrt::Microsoft::UI::Content::ContentIsland Island();
52
56
 
53
57
  // property ReactViewHost
@@ -117,6 +121,10 @@ struct ReactNativeIsland
117
121
  const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer,
118
122
  facebook::react::Tag tag) noexcept;
119
123
 
124
+ void AddFragmentCompositionEventHandler(
125
+ winrt::Microsoft::ReactNative::IReactContext context,
126
+ winrt::Microsoft::ReactNative::ComponentView componentView) noexcept;
127
+
120
128
  public: // IReactViewInstance UI-thread implementation
121
129
  void InitRootView(
122
130
  winrt::Microsoft::ReactNative::IReactContext &&context,
@@ -136,6 +144,7 @@ struct ReactNativeIsland
136
144
  #endif
137
145
 
138
146
  HWND m_hwnd{0};
147
+ bool m_isFragment{false};
139
148
  bool m_isInitialized{false};
140
149
  bool m_isJSViewAttached{false};
141
150
  bool m_hasRenderedVisual{false};
@@ -7,6 +7,7 @@
7
7
  #include "RootComponentView.h"
8
8
 
9
9
  #include <Fabric/FabricUIManagerModule.h>
10
+ #include <winrt/Microsoft.UI.Input.h>
10
11
  #include "CompositionRootAutomationProvider.h"
11
12
  #include "ReactNativeIsland.h"
12
13
  #include "Theme.h"
@@ -24,7 +25,7 @@ RootComponentView::RootComponentView(
24
25
  reactContext,
25
26
  ComponentViewFeatures::Default &
26
27
  ~(ComponentViewFeatures::Background | ComponentViewFeatures::ShadowProps |
27
- ComponentViewFeatures::NativeBorder)) {}
28
+ ComponentViewFeatures::NativeBorder | ComponentViewFeatures::FocusVisual)) {}
28
29
 
29
30
  RootComponentView::~RootComponentView() {
30
31
  if (auto rootView = m_wkRootView.get()) {
@@ -106,7 +107,10 @@ bool RootComponentView::TrySetFocusedComponent(
106
107
  auto target = view;
107
108
  auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
108
109
  if (selfView && !selfView->focusable()) {
109
- target = FocusManager::FindFirstFocusableElement(target);
110
+ target = (direction == winrt::Microsoft::ReactNative::FocusNavigationDirection::Last ||
111
+ direction == winrt::Microsoft::ReactNative::FocusNavigationDirection::Previous)
112
+ ? FocusManager::FindLastFocusableElement(target)
113
+ : FocusManager::FindFirstFocusableElement(target);
110
114
  if (!target)
111
115
  return false;
112
116
  selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
@@ -147,6 +151,9 @@ bool RootComponentView::TryMoveFocus(bool next) noexcept {
147
151
  [currentlyFocused = m_focusedComponent, next](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
148
152
  if (view == currentlyFocused)
149
153
  return false;
154
+ auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view);
155
+ if (!selfView->focusable())
156
+ return false;
150
157
 
151
158
  return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view)
152
159
  ->rootComponentView()
@@ -156,7 +163,28 @@ bool RootComponentView::TryMoveFocus(bool next) noexcept {
156
163
  : winrt::Microsoft::ReactNative::FocusNavigationDirection::Previous);
157
164
  };
158
165
 
159
- return winrt::Microsoft::ReactNative::implementation::walkTree(m_focusedComponent, next, fn);
166
+ if (winrt::Microsoft::ReactNative::implementation::walkTree(m_focusedComponent, next, fn)) {
167
+ return true;
168
+ }
169
+
170
+ // We reached the end of the focus loop. Notify the island in case the host wants to move focus somewhere outside the
171
+ // island.
172
+ auto island = parentContentIsland();
173
+ if (island) {
174
+ auto focusController = winrt::Microsoft::UI::Input::InputFocusController::GetForIsland(island);
175
+ auto request = winrt::Microsoft::UI::Input::FocusNavigationRequest::Create(
176
+ next ? winrt::Microsoft::UI::Input::FocusNavigationReason::Last
177
+ : winrt::Microsoft::UI::Input::FocusNavigationReason::First);
178
+ auto result = focusController.DepartFocus(request);
179
+ if (result == winrt::Microsoft::UI::Input::FocusNavigationResult::Moved) {
180
+ return true;
181
+ }
182
+ }
183
+
184
+ // Wrap focus around if nothing outside the island takes focus
185
+ return NavigateFocus(winrt::Microsoft::ReactNative::FocusNavigationRequest(
186
+ next ? winrt::Microsoft::ReactNative::FocusNavigationReason::First
187
+ : winrt::Microsoft::ReactNative::FocusNavigationReason::Last));
160
188
  }
161
189
 
162
190
  HRESULT RootComponentView::GetFragmentRoot(IRawElementProviderFragmentRoot **pRetVal) noexcept {
@@ -1108,9 +1108,9 @@ void ScrollViewComponentView::StartBringIntoView(
1108
1108
  options.TargetRect->origin.y > m_scrollVisual.ScrollPosition().y) {
1109
1109
  needsScroll = true;
1110
1110
  if (options.TargetRect->size.height > viewerHeight) {
1111
- scrollToVertical = options.TargetRect->origin.y + options.VerticalOffset;
1111
+ scrollToVertical = options.TargetRect->origin.y + options.VerticalOffset * m_layoutMetrics.pointScaleFactor;
1112
1112
  } else {
1113
- scrollToVertical = (targetBottom - viewerHeight) + options.VerticalOffset;
1113
+ scrollToVertical = (targetBottom - viewerHeight) + options.VerticalOffset * m_layoutMetrics.pointScaleFactor;
1114
1114
  }
1115
1115
  // Scroll Up
1116
1116
  } else if (
@@ -1118,9 +1118,9 @@ void ScrollViewComponentView::StartBringIntoView(
1118
1118
  targetBottom < (m_scrollVisual.ScrollPosition().y + viewerHeight)) {
1119
1119
  needsScroll = true;
1120
1120
  if (options.TargetRect->size.height > viewerHeight) {
1121
- scrollToVertical = targetBottom - viewerHeight - options.VerticalOffset;
1121
+ scrollToVertical = targetBottom - viewerHeight - options.VerticalOffset * m_layoutMetrics.pointScaleFactor;
1122
1122
  } else {
1123
- scrollToVertical = options.TargetRect->origin.y - options.VerticalOffset;
1123
+ scrollToVertical = options.TargetRect->origin.y - options.VerticalOffset * m_layoutMetrics.pointScaleFactor;
1124
1124
  }
1125
1125
  }
1126
1126
  } else {
@@ -1134,9 +1134,9 @@ void ScrollViewComponentView::StartBringIntoView(
1134
1134
  options.TargetRect->origin.x > m_scrollVisual.ScrollPosition().x) {
1135
1135
  needsScroll = true;
1136
1136
  if (options.TargetRect->size.width > viewerWidth) {
1137
- scrollToHorizontal = options.TargetRect->origin.x + options.HorizontalOffset;
1137
+ scrollToHorizontal = options.TargetRect->origin.x + options.HorizontalOffset * m_layoutMetrics.pointScaleFactor;
1138
1138
  } else {
1139
- scrollToHorizontal = (targetRight - viewerWidth) + options.HorizontalOffset;
1139
+ scrollToHorizontal = (targetRight - viewerWidth) + options.HorizontalOffset * m_layoutMetrics.pointScaleFactor;
1140
1140
  }
1141
1141
  // Scroll Left
1142
1142
  } else if (
@@ -1144,9 +1144,9 @@ void ScrollViewComponentView::StartBringIntoView(
1144
1144
  targetRight < (m_scrollVisual.ScrollPosition().x + viewerWidth)) {
1145
1145
  needsScroll = true;
1146
1146
  if (options.TargetRect->size.width > viewerWidth) {
1147
- scrollToHorizontal = targetRight - viewerWidth - options.HorizontalOffset;
1147
+ scrollToHorizontal = targetRight - viewerWidth - options.HorizontalOffset * m_layoutMetrics.pointScaleFactor;
1148
1148
  } else {
1149
- scrollToHorizontal = options.TargetRect->origin.x - options.HorizontalOffset;
1149
+ scrollToHorizontal = options.TargetRect->origin.x - options.HorizontalOffset * m_layoutMetrics.pointScaleFactor;
1150
1150
  }
1151
1151
  }
1152
1152
  } else {
@@ -870,6 +870,7 @@ void WindowsTextInputComponentView::OnCharacterReceived(
870
870
  emitter->onKeyPress(onKeyPressArgs);
871
871
 
872
872
  WPARAM wParam = static_cast<WPARAM>(args.KeyCode());
873
+
873
874
  LPARAM lParam = 0;
874
875
  lParam = args.KeyStatus().RepeatCount; // bits 0-15
875
876
  lParam |= args.KeyStatus().ScanCode << 16; // bits 16-23
@@ -1022,6 +1023,10 @@ void WindowsTextInputComponentView::updateProps(
1022
1023
  m_submitKeyEvents.clear();
1023
1024
  }
1024
1025
 
1026
+ if (oldTextInputProps.autoCapitalize != newTextInputProps.autoCapitalize) {
1027
+ autoCapitalizeOnUpdateProps(oldTextInputProps.autoCapitalize, newTextInputProps.autoCapitalize);
1028
+ }
1029
+
1025
1030
  UpdatePropertyBits();
1026
1031
  }
1027
1032
 
@@ -1476,4 +1481,29 @@ winrt::Microsoft::ReactNative::ComponentView WindowsTextInputComponentView::Crea
1476
1481
  return winrt::make<WindowsTextInputComponentView>(compContext, tag, reactContext);
1477
1482
  }
1478
1483
 
1479
- } // namespace winrt::Microsoft::ReactNative::Composition::implementation
1484
+ // This function assumes that previous and new capitalization types are different.
1485
+ void WindowsTextInputComponentView::autoCapitalizeOnUpdateProps(
1486
+ const std::string &previousCapitalizationType,
1487
+ const std::string &newCapitalizationType) noexcept {
1488
+ /*
1489
+ Possible values are:
1490
+ Characters - All characters.
1491
+ Words - First letter of each word.
1492
+ Sentences - First letter of each sentence.
1493
+ None - Do not autocapitalize anything.
1494
+
1495
+ For now, only characters and none are supported.
1496
+ */
1497
+
1498
+ if (previousCapitalizationType == "characters") {
1499
+ winrt::check_hresult(m_textServices->TxSendMessage(
1500
+ EM_SETEDITSTYLE, 0 /* disable */, SES_UPPERCASE /* flag affected */, nullptr /* LRESULT */));
1501
+ }
1502
+
1503
+ if (newCapitalizationType == "characters") {
1504
+ winrt::check_hresult(m_textServices->TxSendMessage(
1505
+ EM_SETEDITSTYLE, SES_UPPERCASE /* enable */, SES_UPPERCASE /* flag affected */, nullptr /* LRESULT */));
1506
+ }
1507
+ }
1508
+
1509
+ } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -104,6 +104,10 @@ struct WindowsTextInputComponentView
104
104
  void InternalFinalize() noexcept;
105
105
  void UpdatePropertyBits() noexcept;
106
106
 
107
+ void autoCapitalizeOnUpdateProps(
108
+ const std::string &previousCapitalizationType,
109
+ const std::string &newcapitalizationType) noexcept;
110
+
107
111
  winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
108
112
  winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
109
113
  winrt::Microsoft::ReactNative::Composition::Experimental::IDrawingSurfaceBrush m_drawingSurface{nullptr};
@@ -330,7 +330,9 @@ bool Theme::TryGetPlatformColor(const std::string &platformColor, winrt::Windows
330
330
  {"AcrylicInAppFillColorDefault", {0x9E, 0xFF, 0xFF, 0xFF}},
331
331
  {"SystemChromeMediumLowColor", {0xFF, 0xF2, 0xF2, 0xF2}},
332
332
  {"SystemControlForegroundBaseHighColor", {0xFF, 0x00, 0x00, 0x00}},
333
- {"SystemControlTransientBorderColor", {0x24, 0x00, 0x00, 0x00}}};
333
+ {"SystemControlTransientBorderColor", {0x24, 0x00, 0x00, 0x00}},
334
+ {"FocusVisualPrimary", {0xFF, 0x00, 0x00, 0x00}},
335
+ {"FocusVisualSecondary", {0x99, 0xFF, 0xFF, 0xFF}}};
334
336
 
335
337
  static std::unordered_map<std::string, winrt::Windows::UI::Color, std::hash<std::string_view>, std::equal_to<>>
336
338
  s_darkColors = {
@@ -362,7 +364,9 @@ bool Theme::TryGetPlatformColor(const std::string &platformColor, winrt::Windows
362
364
  {"AcrylicInAppFillColorDefault", {0x9E, 0x00, 0x00, 0x00}},
363
365
  {"SystemChromeMediumLowColor", {0xFF, 0x2B, 0x2B, 0x2B}},
364
366
  {"SystemControlForegroundBaseHighColor", {0xFF, 0xFF, 0xFF, 0xFF}},
365
- {"SystemControlTransientBorderColor", {0x5C, 0x00, 0x00, 0x00}}};
367
+ {"SystemControlTransientBorderColor", {0x5C, 0x00, 0x00, 0x00}},
368
+ {"FocusVisualPrimary", {0xFF, 0xFF, 0xFF, 0xFF}},
369
+ {"FocusVisualSecondary", {0x99, 0x00, 0x00, 0x00F}}};
366
370
 
367
371
  static std::unordered_map<
368
372
  std::string,
@@ -399,7 +403,9 @@ bool Theme::TryGetPlatformColor(const std::string &platformColor, winrt::Windows
399
403
  {"ControlStrongFillColorDisabled", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace, {}}},
400
404
  {"SystemChromeMediumLowColor", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace, {}}},
401
405
  {"SystemControlForegroundBaseHighColor", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonText, {}}},
402
- {"SystemControlTransientBorderColor", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonText, {}}}};
406
+ {"SystemControlTransientBorderColor", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonText, {}}},
407
+ {"FocusVisualPrimary", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonText, {}}},
408
+ {"FocusVisualSecondary", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace, {}}}};
403
409
 
404
410
  auto alias = s_xamlAliasedColors.find(platformColor);
405
411
  if (alias != s_xamlAliasedColors.end()) {
@@ -214,4 +214,15 @@ ExpandCollapseState GetExpandCollapseState(const bool &expanded) noexcept {
214
214
  }
215
215
  }
216
216
 
217
+ ToggleState GetToggleState(const std::optional<facebook::react::AccessibilityState> &state) noexcept {
218
+ if (state.has_value()) {
219
+ if (state->checked == facebook::react::AccessibilityState::Checked) {
220
+ return ToggleState::ToggleState_On;
221
+ } else if (state->checked == facebook::react::AccessibilityState::Mixed) {
222
+ return ToggleState::ToggleState_Indeterminate;
223
+ }
224
+ }
225
+ return ToggleState::ToggleState_Off;
226
+ }
227
+
217
228
  } // namespace winrt::Microsoft::ReactNative::implementation
@@ -36,4 +36,6 @@ std::string extractAccessibilityValue(const facebook::react::AccessibilityValue
36
36
  void DispatchAccessibilityAction(::Microsoft::ReactNative::ReactTaggedView &view, const std::string &action) noexcept;
37
37
 
38
38
  ExpandCollapseState GetExpandCollapseState(const bool &expanded) noexcept;
39
+
40
+ ToggleState GetToggleState(const std::optional<facebook::react::AccessibilityState> &state) noexcept;
39
41
  } // namespace winrt::Microsoft::ReactNative::implementation
@@ -33,6 +33,7 @@ namespace Microsoft.ReactNative.Composition
33
33
  void SetViewComponentViewInitializer(ViewComponentViewInitializer initializer);
34
34
  void SetContentIslandComponentViewInitializer(ComponentIslandComponentViewInitializer initializer);
35
35
  void SetCreateVisualHandler(CreateVisualDelegate impl);
36
+ void SetViewFeatures(ComponentViewFeatures viewFeatures);
36
37
  };
37
38
 
38
39
  } // namespace Microsoft.ReactNative
@@ -56,7 +56,7 @@ namespace Microsoft.ReactNative
56
56
 
57
57
  [experimental]
58
58
  DOC_STRING("A delegate that creates a @IComponentProps object for an instance of @ViewProps. See @IReactViewComponentBuilder.SetCreateProps")
59
- delegate IComponentProps ViewPropsFactory(ViewProps props);
59
+ delegate IComponentProps ViewPropsFactory(ViewProps props, IComponentProps cloneFrom);
60
60
 
61
61
  [experimental]
62
62
  delegate Windows.Foundation.Size MeasureContentHandler(ShadowNode shadowNode, LayoutContext layoutContext, LayoutConstraints layoutConstraints);
@@ -1,43 +1,17 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+
1
4
  #include "pch.h"
2
5
  #include "ReactNativeAppBuilder.h"
3
6
  #include "ReactNativeAppBuilder.g.cpp"
4
- #include "IReactDispatcher.h"
5
- #include "ReactNativeHost.h"
7
+
6
8
  #include "ReactNativeWin32App.h"
9
+
10
+ #include "winrt/Microsoft.ReactNative.h"
7
11
  #include "winrt/Microsoft.UI.Composition.h"
8
12
  #include "winrt/Microsoft.UI.Dispatching.h"
13
+ #include "winrt/Microsoft.UI.Interop.h"
9
14
  #include "winrt/Microsoft.UI.Windowing.h"
10
- #include "winrt/microsoft.UI.Interop.h"
11
-
12
- // Scaling factor for the window's content based on the DPI of the display where the window is located.
13
- float ScaleFactor(HWND hwnd) noexcept {
14
- return GetDpiForWindow(hwnd) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
15
- }
16
-
17
- void UpdateRootViewSizeToAppWindow(
18
- winrt::Microsoft::ReactNative::ReactNativeIsland const &rootView,
19
- winrt::Microsoft::UI::Windowing::AppWindow const &window) {
20
- auto hwnd = winrt::Microsoft::UI::GetWindowFromWindowId(window.Id());
21
- auto scaleFactor = ScaleFactor(hwnd);
22
- winrt::Windows::Foundation::Size size{
23
- window.ClientSize().Width / scaleFactor, window.ClientSize().Height / scaleFactor};
24
- // Do not relayout when minimized
25
- if (window.Presenter().as<winrt::Microsoft::UI::Windowing::OverlappedPresenter>().State() !=
26
- winrt::Microsoft::UI::Windowing::OverlappedPresenterState::Minimized) {
27
- winrt::Microsoft::ReactNative::LayoutConstraints constraints;
28
- constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
29
- constraints.MaximumSize = constraints.MinimumSize = size;
30
- rootView.Arrange(constraints, {0, 0});
31
- }
32
- }
33
-
34
- namespace winrt::ReactNative {
35
- using namespace winrt::Microsoft::ReactNative;
36
- }
37
-
38
- namespace winrt::UI {
39
- using namespace winrt::Microsoft::UI;
40
- }
41
15
 
42
16
  namespace winrt::Microsoft::ReactNative::implementation {
43
17
  ReactNativeAppBuilder::ReactNativeAppBuilder() {
@@ -46,133 +20,55 @@ ReactNativeAppBuilder::ReactNativeAppBuilder() {
46
20
 
47
21
  ReactNativeAppBuilder::~ReactNativeAppBuilder() {}
48
22
 
49
- winrt::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::AddPackageProviders(
50
- winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::ReactNative::IReactPackageProvider> const
51
- &packageProviders) {
52
- for (auto const &provider : packageProviders) {
53
- m_reactNativeWin32App.ReactNativeHost().PackageProviders().Append(provider);
54
- }
55
-
56
- return *this;
57
- }
58
-
59
- winrt::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetReactInstanceSettings(
60
- winrt::Microsoft::ReactNative::ReactInstanceSettings const &settings) {
61
- m_reactNativeWin32App.ReactNativeHost().InstanceSettings(settings);
62
-
23
+ winrt::Microsoft::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetDispatcherQueueController(
24
+ winrt::Microsoft::UI::Dispatching::DispatcherQueueController const &dispatcherQueueController) {
25
+ m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->DispatcherQueueController(
26
+ dispatcherQueueController);
63
27
  return *this;
64
28
  }
65
29
 
66
- winrt::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetCompositor(
30
+ winrt::Microsoft::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetCompositor(
67
31
  winrt::Microsoft::UI::Composition::Compositor const &compositor) {
68
32
  m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->Compositor(compositor);
69
33
  return *this;
70
34
  }
71
35
 
72
- winrt::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetAppWindow(
36
+ winrt::Microsoft::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetAppWindow(
73
37
  winrt::Microsoft::UI::Windowing::AppWindow const &appWindow) {
74
38
  m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->AppWindow(appWindow);
75
39
 
76
40
  return *this;
77
41
  }
78
42
 
79
- winrt::Microsoft::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetReactViewOptions(
80
- winrt::Microsoft::ReactNative::ReactViewOptions const &reactViewOptions) {
81
- m_reactViewOptions = reactViewOptions;
43
+ winrt::Microsoft::ReactNative::ReactNativeWin32App ReactNativeAppBuilder::Build() {
44
+ // Create the DispatcherQueueController if the app developer doesn't provide one
45
+ if (m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->DispatcherQueueController() == nullptr) {
46
+ assert(m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->Compositor() == nullptr);
82
47
 
83
- return *this;
84
- }
85
-
86
- winrt::ReactNative::ReactNativeWin32App ReactNativeAppBuilder::Build() {
87
- if (m_reactNativeWin32App.Compositor() == nullptr) {
88
- // Create a DispatcherQueue for this thread. This is needed for Composition, Content, and
89
- // Input APIs.
48
+ // Create a DispatcherQueue for this thread. This is needed for Composition, Content, and Input APIs.
90
49
  auto dispatcherQueueController =
91
50
  winrt::Microsoft::UI::Dispatching::DispatcherQueueController::CreateOnCurrentThread();
92
51
 
93
- m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->DispatchQueueController(
52
+ m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->DispatcherQueueController(
94
53
  dispatcherQueueController);
54
+ }
95
55
 
96
- // Create the compositor on behalf of the App Developer
56
+ // Create the Compositor if the app developer doesn't provide one
57
+ if (m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->Compositor() == nullptr) {
58
+ // Create the compositor on behalf of the App Developer.
97
59
  auto compositor = winrt::Microsoft::UI::Composition::Compositor();
98
60
  m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->Compositor(compositor);
99
61
  }
100
62
 
101
- // Create the AppWindow if the developer doesn't provide one
63
+ // Create the AppWindow if the app developer doesn't provide one
102
64
  if (m_reactNativeWin32App.AppWindow() == nullptr) {
103
65
  auto appWindow = winrt::Microsoft::UI::Windowing::AppWindow::Create();
104
- appWindow.Title(L"SampleApplication");
66
+ appWindow.Title(L"ReactNativeWin32App");
105
67
  appWindow.Resize({1000, 1000});
106
- appWindow.Show();
107
68
 
108
69
  m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->AppWindow(appWindow);
109
70
  }
110
71
 
111
- // Currently set the property to use current thread dispatcher as a default UI dispatcher.
112
- // TODO: Provision for setting dispatcher based on the thread dispatcherQueueController is created.
113
- m_reactNativeWin32App.ReactNativeHost().InstanceSettings().Properties().Set(
114
- ReactDispatcherHelper::UIDispatcherProperty(), ReactDispatcherHelper::UIThreadDispatcher());
115
-
116
- auto hwnd{winrt::UI::GetWindowFromWindowId(m_reactNativeWin32App.AppWindow().Id())};
117
-
118
- winrt::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
119
- m_reactNativeWin32App.ReactNativeHost().InstanceSettings().Properties(), reinterpret_cast<uint64_t>(hwnd));
120
-
121
- winrt::ReactNative::Composition::CompositionUIService::SetCompositor(
122
- m_reactNativeWin32App.ReactNativeHost().InstanceSettings(), m_reactNativeWin32App.Compositor());
123
-
124
- // Start the react-native instance, which will create a JavaScript runtime and load the applications bundle.
125
- m_reactNativeWin32App.ReactNativeHost().ReloadInstance();
126
-
127
- // Create a RootView which will present a react-native component
128
- auto reactNativeIsland = winrt::Microsoft::ReactNative::ReactNativeIsland(m_reactNativeWin32App.Compositor());
129
- reactNativeIsland.ReactViewHost(winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(
130
- m_reactNativeWin32App.ReactNativeHost(), m_reactViewOptions));
131
-
132
- m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->ReactNativeIsland(
133
- std::move(reactNativeIsland));
134
-
135
- // Update the size of the RootView when the AppWindow changes size
136
- m_reactNativeWin32App.AppWindow().Changed(
137
- [wkRootView = winrt::make_weak(m_reactNativeWin32App.ReactNativeIsland())](
138
- winrt::Microsoft::UI::Windowing::AppWindow const &window,
139
- winrt::Microsoft::UI::Windowing::AppWindowChangedEventArgs const &args) {
140
- if (args.DidSizeChange() || args.DidVisibilityChange()) {
141
- if (auto rootView = wkRootView.get()) {
142
- UpdateRootViewSizeToAppWindow(rootView, window);
143
- }
144
- }
145
- });
146
-
147
- // Quit application when main window is closed
148
- m_reactNativeWin32App.AppWindow().Destroying([this](
149
- winrt::Microsoft::UI::Windowing::AppWindow const &window,
150
- winrt::Windows::Foundation::IInspectable const & /*args*/) {
151
- // Before we shutdown the application - unload the ReactNativeHost to give the javascript a chance to save any
152
- // state
153
- auto async = m_reactNativeWin32App.ReactNativeHost().UnloadInstance();
154
- async.Completed([this](auto asyncInfo, winrt::Windows::Foundation::AsyncStatus asyncStatus) {
155
- assert(asyncStatus == winrt::Windows::Foundation::AsyncStatus::Completed);
156
- m_reactNativeWin32App.ReactNativeHost().InstanceSettings().UIDispatcher().Post([]() { PostQuitMessage(0); });
157
- });
158
- });
159
-
160
- // DesktopChildSiteBridge create a ContentSite that can host the RootView ContentIsland
161
- auto desktopChildSiteBridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(
162
- m_reactNativeWin32App.Compositor(), m_reactNativeWin32App.AppWindow().Id());
163
-
164
- desktopChildSiteBridge.Connect(m_reactNativeWin32App.ReactNativeIsland().Island());
165
-
166
- desktopChildSiteBridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
167
-
168
- auto scaleFactor = ScaleFactor(hwnd);
169
- m_reactNativeWin32App.ReactNativeIsland().ScaleFactor(scaleFactor);
170
-
171
- UpdateRootViewSizeToAppWindow(reactNativeIsland, m_reactNativeWin32App.AppWindow());
172
-
173
- m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->DesktopChildSiteBridge(
174
- std::move(desktopChildSiteBridge));
175
-
176
72
  return m_reactNativeWin32App;
177
73
  }
178
74
 
@@ -1,6 +1,8 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
1
3
  #pragma once
4
+
2
5
  #include "ReactNativeAppBuilder.g.h"
3
- #include <winrt/Microsoft.UI.Content.h>
4
6
 
5
7
  namespace winrt::Microsoft::ReactNative::implementation {
6
8
  struct ReactNativeAppBuilder : ReactNativeAppBuilderT<ReactNativeAppBuilder> {
@@ -8,25 +10,15 @@ struct ReactNativeAppBuilder : ReactNativeAppBuilderT<ReactNativeAppBuilder> {
8
10
 
9
11
  ~ReactNativeAppBuilder();
10
12
 
11
- winrt::Microsoft::ReactNative::ReactNativeAppBuilder AddPackageProviders(
12
- winrt::Windows::Foundation::Collections::IVector<winrt::Microsoft::ReactNative::IReactPackageProvider> const
13
- &packageProviders);
14
- winrt::Microsoft::ReactNative::ReactNativeAppBuilder SetReactInstanceSettings(
15
- winrt::Microsoft::ReactNative::ReactInstanceSettings const &settings);
16
-
17
- // TODO: Currently, SetCompositor API is not exposed to the developer.
18
- // Compositor depends on the DispatcherQueue created by DispatcherQueueController on a current thread
19
- // or dedicated thread. So we also have to make a provision for setting DispatcherQueueController.
13
+ winrt::Microsoft::ReactNative::ReactNativeAppBuilder SetDispatcherQueueController(
14
+ winrt::Microsoft::UI::Dispatching::DispatcherQueueController const &dispatcherQueueController);
20
15
  winrt::Microsoft::ReactNative::ReactNativeAppBuilder SetCompositor(
21
16
  winrt::Microsoft::UI::Composition::Compositor const &compositor);
22
17
  winrt::Microsoft::ReactNative::ReactNativeAppBuilder SetAppWindow(
23
18
  winrt::Microsoft::UI::Windowing::AppWindow const &appWindow);
24
- winrt::Microsoft::ReactNative::ReactNativeAppBuilder SetReactViewOptions(
25
- winrt::Microsoft::ReactNative::ReactViewOptions const &reactViewOptions);
26
19
  winrt::Microsoft::ReactNative::ReactNativeWin32App Build();
27
20
 
28
21
  private:
29
- winrt::Microsoft::ReactNative::ReactViewOptions m_reactViewOptions{};
30
22
  winrt::Microsoft::ReactNative::ReactNativeWin32App m_reactNativeWin32App{nullptr};
31
23
  };
32
24
  } // namespace winrt::Microsoft::ReactNative::implementation