react-native-windows 0.76.1 → 0.76.3

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 (118) hide show
  1. package/Libraries/Components/View/View.windows.js +76 -52
  2. package/Libraries/Core/ReactNativeVersion.js +1 -1
  3. package/Libraries/Core/setUpErrorHandling.js +1 -7
  4. package/Libraries/LogBox/Data/LogBoxData.js +2 -2
  5. package/Libraries/Modal/Modal.windows.js +352 -0
  6. package/Libraries/ReactNative/AppRegistry.js +3 -3
  7. package/Libraries/Text/Text.windows.js +1 -1
  8. package/Microsoft.ReactNative/CompositionComponentView.idl +2 -1
  9. package/Microsoft.ReactNative/Fabric/AbiComponentDescriptor.cpp +4 -1
  10. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +1 -1
  11. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +7 -0
  12. package/Microsoft.ReactNative/Fabric/AbiViewProps.h +2 -0
  13. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +45 -50
  14. package/Microsoft.ReactNative/Fabric/ComponentView.h +14 -22
  15. package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.cpp +943 -0
  16. package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.h +80 -0
  17. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +26 -3
  18. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +187 -6
  19. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +10 -1
  20. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +8 -32
  21. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +336 -929
  22. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +32 -29
  23. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +9 -2
  24. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +2 -1
  25. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +1 -1
  26. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +181 -123
  27. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +16 -8
  28. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +99 -37
  29. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +25 -3
  30. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +63 -2
  31. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +12 -0
  32. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +51 -3
  33. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +3 -0
  34. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +18 -8
  35. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +3 -0
  36. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +54 -5
  37. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +8 -0
  38. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +9 -3
  39. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +11 -0
  40. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +2 -0
  41. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -1
  42. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewTraitsInitializer.h +1 -5
  43. package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +26 -0
  44. package/Microsoft.ReactNative/IReactViewComponentBuilder.idl +1 -1
  45. package/Microsoft.ReactNative/ReactNativeIsland.idl +3 -2
  46. package/Microsoft.ReactNative/ViewProps.idl +2 -0
  47. package/Microsoft.ReactNative.Cxx/ComponentView.Experimental.interop.h +14 -0
  48. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  49. package/Shared/Shared.vcxitems +3 -0
  50. package/Shared/Shared.vcxitems.filters +1 -0
  51. package/codegen/NativeAccessibilityInfoSpec.g.h +1 -0
  52. package/codegen/NativeAccessibilityManagerSpec.g.h +1 -0
  53. package/codegen/NativeActionSheetManagerSpec.g.h +1 -0
  54. package/codegen/NativeAlertManagerSpec.g.h +1 -0
  55. package/codegen/NativeAnimatedModuleSpec.g.h +1 -0
  56. package/codegen/NativeAnimatedTurboModuleSpec.g.h +1 -0
  57. package/codegen/NativeAppStateSpec.g.h +1 -0
  58. package/codegen/NativeAppThemeSpec.g.h +1 -0
  59. package/codegen/NativeAppearanceSpec.g.h +1 -0
  60. package/codegen/NativeBlobModuleSpec.g.h +1 -0
  61. package/codegen/NativeBugReportingSpec.g.h +1 -0
  62. package/codegen/NativeClipboardSpec.g.h +1 -0
  63. package/codegen/NativeDOMSpec.g.h +1 -0
  64. package/codegen/NativeDevLoadingViewSpec.g.h +1 -0
  65. package/codegen/NativeDevMenuSpec.g.h +1 -0
  66. package/codegen/NativeDevSettingsSpec.g.h +1 -0
  67. package/codegen/NativeDevToolsSettingsManagerSpec.g.h +1 -0
  68. package/codegen/NativeDeviceEventManagerSpec.g.h +1 -0
  69. package/codegen/NativeDeviceInfoSpec.g.h +1 -0
  70. package/codegen/NativeDialogManagerAndroidSpec.g.h +1 -0
  71. package/codegen/NativeDialogManagerWindowsSpec.g.h +1 -0
  72. package/codegen/NativeExceptionsManagerSpec.g.h +1 -0
  73. package/codegen/NativeFileReaderModuleSpec.g.h +1 -0
  74. package/codegen/NativeFrameRateLoggerSpec.g.h +1 -0
  75. package/codegen/NativeHeadlessJsTaskSupportSpec.g.h +1 -0
  76. package/codegen/NativeI18nManagerSpec.g.h +1 -0
  77. package/codegen/NativeIdleCallbacksSpec.g.h +1 -0
  78. package/codegen/NativeImageEditorSpec.g.h +1 -0
  79. package/codegen/NativeImageLoaderAndroidSpec.g.h +1 -0
  80. package/codegen/NativeImageLoaderIOSSpec.g.h +1 -0
  81. package/codegen/NativeImageStoreAndroidSpec.g.h +1 -0
  82. package/codegen/NativeImageStoreIOSSpec.g.h +1 -0
  83. package/codegen/NativeIntentAndroidSpec.g.h +1 -0
  84. package/codegen/NativeIntersectionObserverSpec.g.h +1 -0
  85. package/codegen/NativeJSCHeapCaptureSpec.g.h +1 -0
  86. package/codegen/NativeJSCSamplingProfilerSpec.g.h +1 -0
  87. package/codegen/NativeKeyboardObserverSpec.g.h +1 -0
  88. package/codegen/NativeLinkingManagerSpec.g.h +1 -0
  89. package/codegen/NativeLogBoxSpec.g.h +1 -0
  90. package/codegen/NativeMicrotasksSpec.g.h +1 -0
  91. package/codegen/NativeModalManagerSpec.g.h +1 -0
  92. package/codegen/NativeMutationObserverSpec.g.h +1 -0
  93. package/codegen/NativeNetworkingAndroidSpec.g.h +1 -0
  94. package/codegen/NativeNetworkingIOSSpec.g.h +1 -0
  95. package/codegen/NativePerformanceObserverSpec.g.h +1 -0
  96. package/codegen/NativePerformanceSpec.g.h +1 -0
  97. package/codegen/NativePermissionsAndroidSpec.g.h +1 -0
  98. package/codegen/NativePlatformConstantsAndroidSpec.g.h +1 -0
  99. package/codegen/NativePlatformConstantsIOSSpec.g.h +1 -0
  100. package/codegen/NativePlatformConstantsWindowsSpec.g.h +1 -0
  101. package/codegen/NativePushNotificationManagerIOSSpec.g.h +1 -0
  102. package/codegen/NativeReactNativeFeatureFlagsSpec.g.h +1 -0
  103. package/codegen/NativeRedBoxSpec.g.h +1 -0
  104. package/codegen/NativeSampleTurboModuleSpec.g.h +1 -0
  105. package/codegen/NativeSegmentFetcherSpec.g.h +1 -0
  106. package/codegen/NativeSettingsManagerSpec.g.h +1 -0
  107. package/codegen/NativeShareModuleSpec.g.h +1 -0
  108. package/codegen/NativeSoundManagerSpec.g.h +1 -0
  109. package/codegen/NativeSourceCodeSpec.g.h +1 -0
  110. package/codegen/NativeStatusBarManagerAndroidSpec.g.h +1 -0
  111. package/codegen/NativeStatusBarManagerIOSSpec.g.h +1 -0
  112. package/codegen/NativeTimingSpec.g.h +1 -0
  113. package/codegen/NativeToastAndroidSpec.g.h +1 -0
  114. package/codegen/NativeUIManagerSpec.g.h +1 -0
  115. package/codegen/NativeVibrationSpec.g.h +1 -0
  116. package/codegen/NativeWebSocketModuleSpec.g.h +1 -0
  117. package/package.json +12 -12
  118. package/types/modules/Codegen.d.ts +6 -0
@@ -8,6 +8,7 @@
8
8
  #include <Microsoft.ReactNative.Cxx/ReactContext.h>
9
9
  #include <react/renderer/components/view/ViewEventEmitter.h>
10
10
  #include <react/renderer/components/view/ViewProps.h>
11
+ #include "BorderPrimitive.h"
11
12
  #include "CompositionHelpers.h"
12
13
 
13
14
  #include "Composition.ComponentView.g.h"
@@ -19,17 +20,23 @@ struct CompContext;
19
20
 
20
21
  namespace winrt::Microsoft::ReactNative::Composition::implementation {
21
22
 
23
+ struct FocusPrimitive {
24
+ std::shared_ptr<BorderPrimitive> m_focusInnerPrimitive;
25
+ std::shared_ptr<BorderPrimitive> m_focusOuterPrimitive;
26
+ winrt::com_ptr<ComponentView> m_focusVisualComponent{nullptr}; // The owning component of focus visuals being hosted
27
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_focusVisual{nullptr};
28
+ };
29
+
22
30
  struct ComponentView : public ComponentViewT<
23
31
  ComponentView,
24
32
  winrt::Microsoft::ReactNative::implementation::ComponentView,
25
33
  winrt::Microsoft::ReactNative::Composition::Experimental::IInternalComponentView> {
26
- static constexpr size_t SpecialBorderLayerCount = 8;
27
-
28
34
  ComponentView(
29
35
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
30
36
  facebook::react::Tag tag,
31
37
  winrt::Microsoft::ReactNative::ReactContext const &reactContext,
32
- ComponentViewFeatures flags);
38
+ ComponentViewFeatures flags,
39
+ winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder);
33
40
  virtual ~ComponentView();
34
41
 
35
42
  virtual winrt::Microsoft::ReactNative::Composition::Experimental::IVisual Visual() const noexcept {
@@ -56,6 +63,7 @@ struct ComponentView : public ComponentViewT<
56
63
  void onGotFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
57
64
  bool CapturePointer(const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer) noexcept;
58
65
  void ReleasePointerCapture(const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer) noexcept;
66
+ void SetViewFeatures(ComponentViewFeatures viewFeatures) noexcept;
59
67
 
60
68
  std::vector<facebook::react::ComponentDescriptorProvider> supplementalComponentDescriptorProviders() noexcept
61
69
  override;
@@ -99,6 +107,8 @@ struct ComponentView : public ComponentViewT<
99
107
  void Toggle() noexcept override;
100
108
  virtual winrt::Microsoft::ReactNative::implementation::ClipState getClipState() noexcept;
101
109
 
110
+ virtual std::pair<facebook::react::Cursor, HCURSOR> cursor() const noexcept;
111
+
102
112
  const facebook::react::LayoutMetrics &layoutMetrics() const noexcept;
103
113
 
104
114
  virtual std::string DefaultControlType() const noexcept;
@@ -123,39 +133,32 @@ struct ComponentView : public ComponentViewT<
123
133
  winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext m_compContext;
124
134
  comp::CompositionPropertySet m_centerPropSet{nullptr};
125
135
  facebook::react::SharedViewEventEmitter m_eventEmitter;
126
- bool m_needsBorderUpdate{false};
127
- bool m_hasTransformMatrixFacade{false};
128
- bool m_enableFocusVisual{false};
129
- uint8_t m_numBorderVisuals{0};
130
136
 
131
137
  private:
132
- void updateBorderProps(
133
- const facebook::react::ViewProps &oldViewProps,
134
- const facebook::react::ViewProps &newViewProps) noexcept;
135
- void updateBorderLayoutMetrics(
138
+ void updateFocusLayoutMetrics() noexcept;
139
+ void updateClippingPath(
136
140
  facebook::react::LayoutMetrics const &layoutMetrics,
137
141
  const facebook::react::ViewProps &viewProps) noexcept;
138
- void finalizeBorderUpdates(
139
- facebook::react::LayoutMetrics const &layoutMetrics,
140
- const facebook::react::ViewProps &viewProps) noexcept;
141
- bool TryUpdateSpecialBorderLayers(
142
- winrt::Microsoft::ReactNative::Composition::implementation::Theme *theme,
143
- std::array<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual, SpecialBorderLayerCount>
144
- &spBorderVisuals,
145
- facebook::react::LayoutMetrics const &layoutMetrics,
146
- const facebook::react::ViewProps &viewProps) noexcept;
147
- std::array<winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual, SpecialBorderLayerCount>
148
- FindSpecialBorderLayers() const noexcept;
149
142
  void UpdateCenterPropertySet() noexcept;
150
143
  void FinalizeTransform(
151
144
  facebook::react::LayoutMetrics const &layoutMetrics,
152
145
  const facebook::react::ViewProps &viewProps) noexcept;
146
+ facebook::react::LayoutMetrics focusLayoutMetrics(bool inner) const noexcept;
147
+ facebook::react::BorderMetrics focusBorderMetrics(bool inner, const facebook::react::LayoutMetrics &layoutMetrics)
148
+ const noexcept;
149
+
150
+ virtual winrt::Microsoft::ReactNative::Composition::Experimental::IVisual visualToHostFocus() noexcept;
151
+ virtual winrt::com_ptr<ComponentView> focusVisualRoot(const facebook::react::Rect &focusRect) noexcept;
153
152
 
154
- bool m_FinalizeTransform{false};
155
- bool m_tooltipTracked{false};
153
+ bool m_hasTransformMatrixFacade : 1 {false};
154
+ bool m_FinalizeTransform : 1 {false};
155
+ bool m_tooltipTracked : 1 {false};
156
156
  ComponentViewFeatures m_flags;
157
- void showFocusVisual(bool show) noexcept;
158
- winrt::Microsoft::ReactNative::Composition::Experimental::IFocusVisual m_focusVisual{nullptr};
157
+ void hostFocusVisual(bool show, winrt::com_ptr<ComponentView> view) noexcept;
158
+ winrt::com_ptr<ComponentView>
159
+ m_componentHostingFocusVisual; // The component that we are showing our focus visuals within
160
+ std::shared_ptr<BorderPrimitive> m_borderPrimitive;
161
+ std::unique_ptr<FocusPrimitive> m_focusPrimitive{nullptr};
159
162
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_outerVisual{nullptr};
160
163
  winrt::event<winrt::Windows::Foundation::EventHandler<winrt::IInspectable>> m_themeChangedEvent;
161
164
  };
@@ -169,6 +172,7 @@ struct ViewComponentView : public ViewComponentViewT<
169
172
  facebook::react::Tag tag,
170
173
  winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept;
171
174
 
175
+ virtual winrt::Microsoft::ReactNative::Composition::Experimental::IVisual VisualToMountChildrenInto() noexcept;
172
176
  void MountChildComponentView(
173
177
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
174
178
  uint32_t index) noexcept override;
@@ -181,7 +185,6 @@ struct ViewComponentView : public ViewComponentViewT<
181
185
  facebook::react::LayoutMetrics const &layoutMetrics,
182
186
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
183
187
  void prepareForRecycle() noexcept override;
184
- bool TryFocus() noexcept;
185
188
  bool focusable() const noexcept override;
186
189
  void OnKeyDown(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
187
190
  void OnKeyUp(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
@@ -206,7 +209,8 @@ struct ViewComponentView : public ViewComponentViewT<
206
209
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
207
210
  facebook::react::Tag tag,
208
211
  winrt::Microsoft::ReactNative::ReactContext const &reactContext,
209
- ComponentViewFeatures flags);
212
+ ComponentViewFeatures flags,
213
+ winrt::Microsoft::ReactNative::Composition::ReactCompositionViewComponentBuilder *builder = nullptr);
210
214
 
211
215
  virtual winrt::Microsoft::ReactNative::Composition::Experimental::IVisual createVisual() noexcept;
212
216
 
@@ -224,7 +228,6 @@ struct ViewComponentView : public ViewComponentViewT<
224
228
  bool m_hasNonVisualChildren{false};
225
229
  facebook::react::SharedViewProps m_props;
226
230
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_visual{nullptr};
227
- winrt::Microsoft::ReactNative::Composition::CreateVisualDelegate m_createVisualHandler{nullptr};
228
231
  winrt::Microsoft::ReactNative::Composition::Experimental::CreateInternalVisualDelegate m_createInternalVisualHandler{
229
232
  nullptr};
230
233
  };
@@ -22,8 +22,15 @@ namespace winrt::Microsoft::ReactNative::Composition::implementation {
22
22
  ContentIslandComponentView::ContentIslandComponentView(
23
23
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
24
24
  facebook::react::Tag tag,
25
- winrt::Microsoft::ReactNative::ReactContext const &reactContext)
26
- : base_type(ViewComponentView::defaultProps(), compContext, tag, reactContext, ComponentViewFeatures::Default) {
25
+ winrt::Microsoft::ReactNative::ReactContext const &reactContext,
26
+ ReactCompositionViewComponentBuilder *builder)
27
+ : base_type(
28
+ ViewComponentView::defaultProps(),
29
+ compContext,
30
+ tag,
31
+ reactContext,
32
+ ComponentViewFeatures::Default,
33
+ builder) {
27
34
  m_mountedToken = Mounted([](const winrt::IInspectable &, const winrt::Microsoft::ReactNative::ComponentView &view) {
28
35
  view.as<ContentIslandComponentView>()->OnMounted();
29
36
  });
@@ -40,7 +40,8 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
40
40
  ContentIslandComponentView(
41
41
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
42
42
  facebook::react::Tag tag,
43
- winrt::Microsoft::ReactNative::ReactContext const &reactContext);
43
+ winrt::Microsoft::ReactNative::ReactContext const &reactContext,
44
+ ReactCompositionViewComponentBuilder *builder);
44
45
  ~ContentIslandComponentView() noexcept;
45
46
 
46
47
  private:
@@ -21,7 +21,7 @@ DebuggingOverlayComponentView::DebuggingOverlayComponentView(
21
21
  reactContext,
22
22
  ComponentViewFeatures::Default &
23
23
  ~(ComponentViewFeatures::Background | ComponentViewFeatures::ShadowProps |
24
- ComponentViewFeatures::NativeBorder)) {}
24
+ ComponentViewFeatures::NativeBorder | ComponentViewFeatures::FocusVisual)) {}
25
25
 
26
26
  void DebuggingOverlayComponentView::MountChildComponentView(
27
27
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
@@ -10,25 +10,53 @@
10
10
  #include "../CompositionDynamicAutomationProvider.h"
11
11
  #include "Unicode.h"
12
12
 
13
+ #include <DispatcherQueue.h>
14
+ #include <Fabric/ComponentView.h>
13
15
  #include <Fabric/Composition/CompositionContextHelper.h>
14
16
  #include <Fabric/Composition/CompositionUIService.h>
17
+ #include <Fabric/Composition/ReactNativeIsland.h>
18
+ #include <windows.ui.composition.interop.h>
19
+ #include <winrt/Microsoft.ReactNative.Composition.Experimental.h>
20
+ #include <winrt/Microsoft.UI.Content.h>
21
+ #include <winrt/Microsoft.UI.interop.h>
22
+ #include <winrt/Windows.UI.Composition.Desktop.h>
15
23
  #include <winrt/Windows.UI.Composition.h>
16
24
  #include "IReactContext.h"
17
25
  #include "ReactHost/ReactInstanceWin.h"
18
26
  #include "ReactNativeHost.h"
27
+ #include "WindowsModalHostViewShadowNode.h"
19
28
 
20
29
  namespace winrt::Microsoft::ReactNative::Composition::implementation {
21
30
  WindowsModalHostComponentView::WindowsModalHostComponentView(
22
31
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
23
32
  facebook::react::Tag tag,
24
33
  winrt::Microsoft::ReactNative::ReactContext const &reactContext)
25
- : Super(
26
- WindowsModalHostComponentView::defaultProps(),
27
- compContext,
28
- tag,
29
- reactContext,
30
- ComponentViewFeatures::Default & ~ComponentViewFeatures::Background) {
31
- m_context = reactContext; // save context
34
+ : Super(compContext, tag, reactContext) {}
35
+
36
+ WindowsModalHostComponentView::~WindowsModalHostComponentView() {
37
+ // dispatch onDismiss event
38
+ auto emitter = std::static_pointer_cast<const facebook::react::ModalHostViewEventEmitter>(m_eventEmitter);
39
+ facebook::react::ModalHostViewEventEmitter::OnDismiss onDismissArgs;
40
+ emitter->onDismiss(onDismissArgs);
41
+
42
+ // reset the topWindowID
43
+ if (m_prevWindowID) {
44
+ auto host =
45
+ winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties());
46
+ winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
47
+ host.InstanceSettings().Properties(), m_prevWindowID);
48
+ m_prevWindowID = 0;
49
+ }
50
+
51
+ // enable input to parent
52
+ EnableWindow(m_parentHwnd, true);
53
+
54
+ // Check if the window handle (m_hwnd) exists and destroy it if necessary
55
+ if (m_hwnd) {
56
+ // Close/Destroy the modal window
57
+ SendMessage(m_hwnd, WM_DESTROY, 0, 0);
58
+ m_hwnd = nullptr;
59
+ }
32
60
  }
33
61
 
34
62
  winrt::Microsoft::ReactNative::ComponentView WindowsModalHostComponentView::Create(
@@ -38,44 +66,48 @@ winrt::Microsoft::ReactNative::ComponentView WindowsModalHostComponentView::Crea
38
66
  return winrt::make<WindowsModalHostComponentView>(compContext, tag, reactContext);
39
67
  }
40
68
 
41
- // constants for creating a new windows (code mostly taken from LogBox)
69
+ // constants for creating a new windows
42
70
  constexpr PCWSTR c_modalWindowClassName = L"MS_REACTNATIVE_MODAL";
43
71
  constexpr auto CompHostProperty = L"CompHost";
44
- const int MODAL_DEFAULT_WIDTH = 500;
45
- const int MODAL_DEFAULT_HEIGHT = 500;
72
+ const int MODAL_MIN_WIDTH = 50;
73
+ const int MODAL_MIN_HEIGHT = 50;
74
+
75
+ float ScaleFactor(HWND hwnd) noexcept {
76
+ return GetDpiForWindow(hwnd) / static_cast<float>(USER_DEFAULT_SCREEN_DPI);
77
+ }
46
78
 
47
79
  // creates a new modal window
48
80
  void WindowsModalHostComponentView::EnsureModalCreated() {
49
81
  auto host =
50
- winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_context.Properties());
82
+ winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties());
83
+
51
84
  // return if hwnd already exists
52
85
  if (!host || m_hwnd) {
53
86
  return;
54
87
  }
55
88
 
56
- RegisterWndClass(); // creates and register a windows class
57
- auto CompositionHwndHost = winrt::Microsoft::ReactNative::CompositionHwndHost();
58
- winrt::Microsoft::ReactNative::ReactViewOptions viewOptions;
59
- viewOptions.ComponentName(L"Modal");
60
- CompositionHwndHost.ReactViewHost(winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(host, viewOptions));
89
+ RegisterWndClass();
90
+
61
91
  HINSTANCE hInstance = GetModuleHandle(NULL);
62
- winrt::impl::abi<winrt::Microsoft::ReactNative::ICompositionHwndHost>::type *pHost{nullptr};
63
92
  winrt::com_ptr<::IUnknown> spunk;
64
- CompositionHwndHost.as(spunk);
65
93
 
66
94
  // get the root hwnd
67
- auto roothwnd = reinterpret_cast<HWND>(
68
- winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(m_context.Properties().Handle()));
95
+ m_prevWindowID =
96
+ winrt::Microsoft::ReactNative::ReactCoreInjection::GetTopLevelWindowId(m_reactContext.Properties().Handle());
97
+
98
+ m_parentHwnd = GetHwndForParenting();
99
+
100
+ auto windowsStyle = m_showTitleBar ? WS_OVERLAPPEDWINDOW : WS_POPUP;
69
101
 
70
102
  m_hwnd = CreateWindow(
71
103
  c_modalWindowClassName,
72
104
  L"React-Native Modal",
73
- WS_OVERLAPPEDWINDOW,
105
+ windowsStyle,
74
106
  CW_USEDEFAULT,
75
107
  CW_USEDEFAULT,
76
- MODAL_DEFAULT_WIDTH,
77
- MODAL_DEFAULT_HEIGHT,
78
- roothwnd, // parent
108
+ MODAL_MIN_WIDTH,
109
+ MODAL_MIN_HEIGHT,
110
+ m_parentHwnd, // parent
79
111
  nullptr,
80
112
  hInstance,
81
113
  spunk.get());
@@ -85,20 +117,81 @@ void WindowsModalHostComponentView::EnsureModalCreated() {
85
117
  throw std::exception("Failed to create new hwnd for Modal: " + GetLastError());
86
118
  }
87
119
 
120
+ // Disable user sizing of the hwnd
121
+ ::SetWindowLong(m_hwnd, GWL_STYLE, GetWindowLong(m_hwnd, GWL_STYLE) & ~WS_SIZEBOX);
122
+
123
+ // set the top-level windows as the new hwnd
124
+ winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
125
+ host.InstanceSettings().Properties(), reinterpret_cast<uint64_t>(m_hwnd));
126
+
127
+ // get current compositor - handles the creation/manipulation of visual objects
128
+ auto compositionContext = CompositionContext();
129
+ auto compositor =
130
+ winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::InnerCompositor(
131
+ compositionContext);
132
+
133
+ // create a react native island - code taken from CompositionHwndHost
134
+ auto bridge = winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(
135
+ compositor, winrt::Microsoft::UI::GetWindowIdFromWindow(m_hwnd));
136
+ m_reactNativeIsland = winrt::Microsoft::ReactNative::ReactNativeIsland(compositor, m_reactContext.Handle(), *this);
137
+ auto contentIsland = m_reactNativeIsland.Island();
138
+ bridge.Connect(contentIsland);
139
+ bridge.Show();
140
+
141
+ // set ScaleFactor
142
+ ScaleFactor(m_hwnd);
143
+
144
+ // set layout contraints
145
+ winrt::Microsoft::ReactNative::LayoutConstraints constraints;
146
+ constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
147
+
148
+ RECT rc;
149
+ GetClientRect(m_parentHwnd, &rc);
150
+ // Maximum size is set to size of parent hwnd
151
+ constraints.MaximumSize = {(rc.right - rc.left) * ScaleFactor(m_hwnd), (rc.bottom - rc.top) / ScaleFactor(m_hwnd)};
152
+ constraints.MinimumSize = {MODAL_MIN_WIDTH * ScaleFactor(m_hwnd), MODAL_MIN_HEIGHT * ScaleFactor(m_hwnd)};
153
+ m_reactNativeIsland.Arrange(constraints, {0, 0});
154
+ bridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
155
+
88
156
  spunk.detach();
89
157
  }
90
158
 
91
159
  void WindowsModalHostComponentView::ShowOnUIThread() {
92
- if (m_hwnd) {
160
+ if (m_hwnd && !IsWindowVisible(m_hwnd)) {
93
161
  ShowWindow(m_hwnd, SW_NORMAL);
94
162
  BringWindowToTop(m_hwnd);
95
163
  SetFocus(m_hwnd);
164
+
165
+ // disable input to parent
166
+ EnableWindow(m_parentHwnd, false);
167
+
168
+ // dispatch onShow event
169
+ auto emitter = std::static_pointer_cast<const facebook::react::ModalHostViewEventEmitter>(m_eventEmitter);
170
+ facebook::react::ModalHostViewEventEmitter::OnShow onShowArgs;
171
+ emitter->onShow(onShowArgs);
96
172
  }
97
173
  }
98
174
 
99
175
  void WindowsModalHostComponentView::HideOnUIThread() noexcept {
100
176
  if (m_hwnd) {
101
- ::ShowWindow(m_hwnd, SW_HIDE);
177
+ SendMessage(m_hwnd, WM_CLOSE, 0, 0);
178
+ }
179
+
180
+ // dispatch onDismiss event
181
+ auto emitter = std::static_pointer_cast<const facebook::react::ModalHostViewEventEmitter>(m_eventEmitter);
182
+ facebook::react::ModalHostViewEventEmitter::OnDismiss onDismissArgs;
183
+ emitter->onDismiss(onDismissArgs);
184
+
185
+ // enable input to parent
186
+ EnableWindow(m_parentHwnd, true);
187
+
188
+ // reset the topWindowID
189
+ if (m_prevWindowID) {
190
+ auto host =
191
+ winrt::Microsoft::ReactNative::implementation::ReactNativeHost::GetReactNativeHost(m_reactContext.Properties());
192
+ winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
193
+ host.InstanceSettings().Properties(), m_prevWindowID);
194
+ m_prevWindowID = 0;
102
195
  }
103
196
  }
104
197
 
@@ -121,23 +214,22 @@ LRESULT CALLBACK ModalBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM
121
214
  }
122
215
 
123
216
  switch (message) {
124
- case WM_NCCREATE: { // sent before WM_CREATE, lparam should be identical to members of CreateWindowEx
217
+ case WM_NCCREATE: { // called before WM_CREATE, lparam should be identical to members of CreateWindowEx
125
218
  auto createStruct = reinterpret_cast<CREATESTRUCT *>(lparam); // CreateStruct
126
219
  data = static_cast<::IUnknown *>(createStruct->lpCreateParams);
127
220
  SetProp(hwnd, CompHostProperty, data); // adds new properties to window
128
221
  break;
129
222
  }
130
- case WM_CREATE: { // recieves after window is created but before visible
131
- // host.Initialize((uint64_t)hwnd); cause Modal to throw a not registered error
132
- break;
133
- }
134
223
  case WM_CLOSE: {
135
224
  // Just hide the window instead of destroying it
136
225
  ::ShowWindow(hwnd, SW_HIDE);
137
226
  return 0;
138
227
  }
139
228
  case WM_DESTROY: { // called when we want to destroy the window
140
- data->Release();
229
+ ::ShowWindow(hwnd, SW_HIDE);
230
+ if (data) {
231
+ data->Release();
232
+ }
141
233
  SetProp(hwnd, CompHostProperty, nullptr);
142
234
  break;
143
235
  }
@@ -174,121 +266,87 @@ void WindowsModalHostComponentView::RegisterWndClass() noexcept {
174
266
  registered = true;
175
267
  }
176
268
 
269
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual
270
+ WindowsModalHostComponentView::VisualToMountChildrenInto() noexcept {
271
+ return m_reactNativeIsland
272
+ .as<winrt::Microsoft::ReactNative::Composition::Experimental::IInternalCompositionRootView>()
273
+ .InternalRootVisual();
274
+ }
275
+
276
+ // childComponentView - reference to the child component view
277
+ // index - the position in which the childComponentView should be mounted
177
278
  void WindowsModalHostComponentView::MountChildComponentView(
178
279
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
179
280
  uint32_t index) noexcept {
180
- // Disabled due to partial Modal implementation. Tracking re-enablement with task list here:
181
- // https://github.com/microsoft/react-native-windows/issues/11157 assert(false);
281
+ EnsureModalCreated();
182
282
  base_type::MountChildComponentView(childComponentView, index);
183
283
  }
184
284
 
185
285
  void WindowsModalHostComponentView::UnmountChildComponentView(
186
286
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
187
287
  uint32_t index) noexcept {
188
- // Disabled due to partial Modal implementation.Tracking re-enablement with task list here : https : //
189
- // github.com/microsoft/react-native-windows/issues/11157 assert(false);
190
288
  base_type::UnmountChildComponentView(childComponentView, index);
191
289
  }
192
290
 
193
- void WindowsModalHostComponentView::HandleCommand(
194
- const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept {
195
- Super::HandleCommand(args);
291
+ void WindowsModalHostComponentView::updateLayoutMetrics(
292
+ facebook::react::LayoutMetrics const &layoutMetrics,
293
+ facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
294
+ base_type::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
295
+ if (m_hwnd) {
296
+ EnsureModalCreated();
297
+ AdjustWindowSize();
298
+ ShowOnUIThread();
299
+ }
196
300
  }
197
301
 
302
+ void WindowsModalHostComponentView::AdjustWindowSize() noexcept {
303
+ if (m_layoutMetrics.overflowInset.right == 0 && m_layoutMetrics.overflowInset.bottom == 0) {
304
+ return;
305
+ }
306
+
307
+ // Modal's size is based on it's children, use the overflow to calculate the width/height
308
+ float xPos = (-m_layoutMetrics.overflowInset.right * (m_layoutMetrics.pointScaleFactor));
309
+ float yPos = (-m_layoutMetrics.overflowInset.bottom * (m_layoutMetrics.pointScaleFactor));
310
+ RECT rc;
311
+ GetClientRect(m_hwnd, &rc);
312
+ RECT rect = {0, 0, (int)xPos, (int)yPos};
313
+
314
+ if (m_showTitleBar) {
315
+ AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE); // Adjust for title bar and borders
316
+ }
317
+
318
+ // set the layoutMetrics
319
+ m_layoutMetrics.frame.size = {(float)rect.right - rect.left, (float)rect.bottom - rect.top};
320
+ m_layoutMetrics.overflowInset.right = 0;
321
+ m_layoutMetrics.overflowInset.bottom = 0;
322
+
323
+ // get Modal's position based on parent
324
+ RECT parentRC;
325
+ GetWindowRect(m_parentHwnd, &parentRC);
326
+ float xCor = (parentRC.left + parentRC.right - m_layoutMetrics.frame.size.width) / 2; // midpointx - width / 2
327
+ float yCor = (parentRC.top + parentRC.bottom - m_layoutMetrics.frame.size.height) / 2; // midpointy - height / 2
328
+
329
+ // Adjust window position and size
330
+ MoveWindow(m_hwnd, (int)xCor, (int)yCor, (int)(rect.right - rect.left), (int)(rect.bottom - rect.top), true);
331
+
332
+ // Let RNWIsland know that Modal's size has changed
333
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(m_reactNativeIsland)
334
+ ->NotifySizeChanged();
335
+ };
336
+
198
337
  void WindowsModalHostComponentView::updateProps(
199
338
  facebook::react::Props::Shared const &props,
200
339
  facebook::react::Props::Shared const &oldProps) noexcept {
201
340
  const auto &oldModalProps =
202
341
  *std::static_pointer_cast<const facebook::react::ModalHostViewProps>(oldProps ? oldProps : viewProps());
203
342
  const auto &newModalProps = *std::static_pointer_cast<const facebook::react::ModalHostViewProps>(props);
204
-
205
- // currently Modal only gets Destroyed by closing the window
206
- if (newModalProps.visible) {
207
- EnsureModalCreated();
208
- ShowOnUIThread();
343
+ newModalProps.visible ? m_isVisible = true : m_isVisible = false;
344
+ if (!m_isVisible) {
345
+ HideOnUIThread();
209
346
  }
210
-
211
347
  base_type::updateProps(props, oldProps);
212
348
  }
213
349
 
214
- void WindowsModalHostComponentView::updateLayoutMetrics(
215
- facebook::react::LayoutMetrics const &layoutMetrics,
216
- facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
217
- Super::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
218
-
219
- // Temporary placeholder for Modal, draws on main hwnd
220
- if (m_layoutMetrics.frame.size != layoutMetrics.frame.size ||
221
- m_layoutMetrics.pointScaleFactor != layoutMetrics.pointScaleFactor || m_layoutMetrics.frame.size.width == 0) {
222
- // Always make visual a min size, so that even if its laid out at zero size, its clear an unimplemented view was
223
- // rendered
224
- float width = std::max(m_layoutMetrics.frame.size.width, 200.0f);
225
- float height = std::max(m_layoutMetrics.frame.size.width, 50.0f);
226
-
227
- winrt::Windows::Foundation::Size surfaceSize = {
228
- width * m_layoutMetrics.pointScaleFactor, height * m_layoutMetrics.pointScaleFactor};
229
- auto drawingSurface = m_compContext.CreateDrawingSurfaceBrush(
230
- surfaceSize,
231
- winrt::Windows::Graphics::DirectX::DirectXPixelFormat::B8G8R8A8UIntNormalized,
232
- winrt::Windows::Graphics::DirectX::DirectXAlphaMode::Premultiplied);
233
-
234
- drawingSurface.HorizontalAlignmentRatio(0.f);
235
- drawingSurface.VerticalAlignmentRatio(0.f);
236
- drawingSurface.Stretch(winrt::Microsoft::ReactNative::Composition::Experimental::CompositionStretch::None);
237
- Visual().as<Experimental::ISpriteVisual>().Brush(drawingSurface);
238
- Visual().Size(surfaceSize);
239
- Visual().Offset({
240
- layoutMetrics.frame.origin.x * layoutMetrics.pointScaleFactor,
241
- layoutMetrics.frame.origin.y * layoutMetrics.pointScaleFactor,
242
- 0.0f,
243
- });
244
-
245
- POINT offset;
246
- {
247
- ::Microsoft::ReactNative::Composition::AutoDrawDrawingSurface autoDraw(
248
- drawingSurface, m_layoutMetrics.pointScaleFactor, &offset);
249
- if (auto d2dDeviceContext = autoDraw.GetRenderTarget()) {
250
- d2dDeviceContext->Clear(D2D1::ColorF(D2D1::ColorF::Blue, 0.3f));
251
- assert(d2dDeviceContext->GetUnitMode() == D2D1_UNIT_MODE_DIPS);
252
-
253
- float offsetX = static_cast<float>(offset.x / m_layoutMetrics.pointScaleFactor);
254
- float offsetY = static_cast<float>(offset.y / m_layoutMetrics.pointScaleFactor);
255
-
256
- winrt::com_ptr<IDWriteTextFormat> spTextFormat;
257
- winrt::check_hresult(::Microsoft::ReactNative::DWriteFactory()->CreateTextFormat(
258
- L"Segoe UI",
259
- nullptr, // Font collection (nullptr sets it to use the system font collection).
260
- DWRITE_FONT_WEIGHT_REGULAR,
261
- DWRITE_FONT_STYLE_NORMAL,
262
- DWRITE_FONT_STRETCH_NORMAL,
263
- 12,
264
- L"",
265
- spTextFormat.put()));
266
-
267
- winrt::com_ptr<ID2D1SolidColorBrush> textBrush;
268
- winrt::check_hresult(
269
- d2dDeviceContext->CreateSolidColorBrush(D2D1::ColorF(D2D1::ColorF::White), textBrush.put()));
270
-
271
- const D2D1_RECT_F rect = {
272
- static_cast<float>(offset.x), static_cast<float>(offset.y), width + offset.x, height + offset.y};
273
-
274
- auto label = ::Microsoft::Common::Unicode::Utf8ToUtf16(std::string("This is a Modal"));
275
- d2dDeviceContext->DrawText(
276
- label.c_str(),
277
- static_cast<UINT32>(label.length()),
278
- spTextFormat.get(),
279
- rect,
280
- textBrush.get(),
281
- D2D1_DRAW_TEXT_OPTIONS_NONE,
282
- DWRITE_MEASURING_MODE_NATURAL);
283
- }
284
- }
285
- }
286
- }
287
-
288
- void WindowsModalHostComponentView::updateState(
289
- facebook::react::State::Shared const &state,
290
- facebook::react::State::Shared const &oldState) noexcept {}
291
-
292
350
  facebook::react::SharedViewProps WindowsModalHostComponentView::defaultProps() noexcept {
293
351
  static auto const defaultProps = std::make_shared<facebook::react::ModalHostViewProps const>();
294
352
  return defaultProps;
@@ -9,34 +9,38 @@
9
9
  #include "Composition.WindowsModalHostComponentView.g.h"
10
10
  #include "../CompositionViewComponentView.h"
11
11
 
12
+ #include <Fabric/Composition/RootComponentView.h>
12
13
  #include <react/components/rnwcore/ShadowNodes.h>
13
14
 
14
15
  namespace winrt::Microsoft::ReactNative::Composition::implementation {
15
16
 
16
17
  struct WindowsModalHostComponentView
17
- : WindowsModalHostComponentViewT<WindowsModalHostComponentView, ViewComponentView> {
18
- using Super = WindowsModalHostComponentViewT<WindowsModalHostComponentView, ViewComponentView>;
18
+ : WindowsModalHostComponentViewT<WindowsModalHostComponentView, RootComponentView> {
19
+ using Super = WindowsModalHostComponentViewT<WindowsModalHostComponentView, RootComponentView>;
20
+
21
+ ~WindowsModalHostComponentView();
19
22
 
20
23
  [[nodiscard]] static winrt::Microsoft::ReactNative::ComponentView Create(
21
24
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
22
25
  facebook::react::Tag tag,
23
26
  winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept;
24
27
 
28
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual VisualToMountChildrenInto() noexcept override;
25
29
  void MountChildComponentView(
26
30
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
27
31
  uint32_t index) noexcept override;
28
32
  void UnmountChildComponentView(
29
33
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
30
34
  uint32_t index) noexcept override;
31
- void HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept override;
32
- void updateState(facebook::react::State::Shared const &state, facebook::react::State::Shared const &oldState) noexcept
33
- override;
34
35
 
35
- void updateProps(facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept
36
- override;
36
+ void AdjustWindowSize() noexcept;
37
+
37
38
  void updateLayoutMetrics(
38
39
  facebook::react::LayoutMetrics const &layoutMetrics,
39
40
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
41
+
42
+ void updateProps(facebook::react::Props::Shared const &props, facebook::react::Props::Shared const &oldProps) noexcept
43
+ override;
40
44
  static facebook::react::SharedViewProps defaultProps() noexcept;
41
45
  const facebook::react::ModalHostViewProps &modalHostViewProps() const noexcept;
42
46
  bool focusable() const noexcept override;
@@ -56,8 +60,12 @@ struct WindowsModalHostComponentView
56
60
  static void RegisterWndClass() noexcept;
57
61
 
58
62
  private:
63
+ HWND m_parentHwnd{nullptr};
59
64
  HWND m_hwnd{nullptr};
60
- winrt::Microsoft::ReactNative::ReactContext m_context;
65
+ uint64_t m_prevWindowID;
66
+ bool m_isVisible{false};
67
+ bool m_showTitleBar{false};
68
+ winrt::Microsoft::ReactNative::ReactNativeIsland m_reactNativeIsland;
61
69
  };
62
70
 
63
71
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation