react-native-windows 0.81.4 → 0.81.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 (62) hide show
  1. package/Libraries/Core/ReactNativeVersion.js +1 -1
  2. package/Libraries/NativeComponent/ViewConfigIgnore.windows.js +45 -0
  3. package/Libraries/Renderer/implementations/ReactFabric-dev.js +38 -35
  4. package/Libraries/Renderer/implementations/ReactFabric-prod.js +51 -22
  5. package/Libraries/Renderer/implementations/ReactFabric-profiling.js +54 -24
  6. package/Libraries/Renderer/implementations/ReactNativeRenderer-dev.js +36 -33
  7. package/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js +5 -5
  8. package/Libraries/Renderer/implementations/ReactNativeRenderer-profiling.js +5 -5
  9. package/Libraries/Renderer/shims/ReactNativeTypes.js +23 -11
  10. package/Libraries/Renderer/shims/ReactNativeTypes.windows.js +23 -12
  11. package/Microsoft.ReactNative/ComponentView.idl +2 -0
  12. package/Microsoft.ReactNative/Composition.Input.idl +7 -0
  13. package/Microsoft.ReactNative/CompositionComponentView.idl +5 -0
  14. package/Microsoft.ReactNative/CompositionHwndHost.idl +1 -0
  15. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +19 -1
  16. package/Microsoft.ReactNative/Fabric/ComponentView.h +10 -1
  17. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +12 -0
  18. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +15 -0
  19. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +75 -0
  20. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +1 -0
  21. package/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp +10 -45
  22. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +86 -98
  23. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +4 -0
  24. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +80 -48
  25. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +11 -3
  26. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +61 -74
  27. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +4 -3
  28. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +2 -1
  29. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeWindow.cpp +245 -0
  30. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeWindow.h +80 -0
  31. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +33 -1
  32. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +17 -0
  33. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +137 -84
  34. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +7 -1
  35. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +3 -1
  36. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/WindowsTextLayoutManager.cpp +7 -2
  37. package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +20 -95
  38. package/Microsoft.ReactNative/Modules/LogBoxModule.h +1 -1
  39. package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +0 -41
  40. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +0 -11
  41. package/Microsoft.ReactNative/ReactNativeIsland.idl +2 -3
  42. package/Microsoft.ReactNative/ReactNativeWin32App.cpp +31 -101
  43. package/Microsoft.ReactNative/ReactNativeWin32App.h +2 -13
  44. package/Microsoft.ReactNative/ReactNativeWindow.idl +44 -0
  45. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  46. package/Shared/Shared.vcxitems +7 -0
  47. package/Shared/Shared.vcxitems.filters +6 -0
  48. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +2 -1
  49. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +26 -9
  50. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +2 -1
  51. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +2 -1
  52. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +8 -3
  53. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +8 -3
  54. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +1 -0
  55. package/codegen/react/components/rnwcore/InputAccessory.g.h +2 -1
  56. package/codegen/react/components/rnwcore/ModalHostView.g.h +26 -9
  57. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +8 -3
  58. package/codegen/react/components/rnwcore/SafeAreaView.g.h +1 -0
  59. package/codegen/react/components/rnwcore/Switch.g.h +8 -3
  60. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +2 -1
  61. package/codegen/react/components/rnwcore/VirtualView.g.h +8 -3
  62. package/package.json +21 -21
@@ -32,6 +32,8 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
32
32
  uint32_t index) noexcept override;
33
33
  void Connect(const winrt::Microsoft::UI::Content::ContentIsland &contentIsland) noexcept;
34
34
 
35
+ winrt::Microsoft::UI::Content::ChildSiteLink ChildSiteLink() noexcept;
36
+
35
37
  void updateLayoutMetrics(
36
38
  facebook::react::LayoutMetrics const &layoutMetrics,
37
39
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept;
@@ -59,14 +61,12 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
59
61
  void OnUnmounted() noexcept;
60
62
  void ParentLayoutChanged() noexcept;
61
63
  void ConnectInternal() noexcept;
62
- void RegisterForRootIslandEvents() noexcept;
63
- void UnregisterForRootIslandEvents() noexcept;
64
64
  winrt::Microsoft::UI::Content::ContentIsland ParentContentIsland() noexcept;
65
65
 
66
66
  bool m_layoutChangePosted{false};
67
67
  winrt::Microsoft::UI::Content::ContentIsland m_parentContentIsland{nullptr};
68
68
  winrt::Microsoft::UI::Content::ContentIsland m_islandToConnect{nullptr};
69
- winrt::event_token m_islandStateChangedToken;
69
+ std::optional<winrt::Microsoft::UI::Input::FocusNavigationReason> m_pendingNavigateFocus;
70
70
 
71
71
  winrt::event_token m_mountedToken;
72
72
  winrt::event_token m_unmountedToken;
@@ -74,6 +74,14 @@ struct ContentIslandComponentView : ContentIslandComponentViewT<ContentIslandCom
74
74
  winrt::Microsoft::UI::Content::ChildSiteLink m_childSiteLink{nullptr};
75
75
  winrt::Microsoft::UI::Input::InputFocusNavigationHost m_navigationHost{nullptr};
76
76
  winrt::event_token m_navigationHostDepartFocusRequestedToken{};
77
+ std::optional<winrt::Microsoft::UI::Input::FocusNavigationReason> m_pendingFocus;
78
+
79
+ // Issue #15557: Store ViewChanged subscriptions to parent ScrollViews for transform updates
80
+ struct ViewChangedSubscription {
81
+ winrt::weak_ref<winrt::Microsoft::ReactNative::Composition::ScrollViewComponentView> scrollView;
82
+ winrt::event_token token;
83
+ };
84
+ std::vector<ViewChangedSubscription> m_viewChangedSubscriptions;
77
85
 
78
86
  // Automation
79
87
  void ConfigureChildSiteLinkAutomation() noexcept;
@@ -37,9 +37,9 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
37
37
  ~ModalHostView() {
38
38
  if (m_popUp) {
39
39
  // Unregister closing event handler
40
- if (m_appWindow && m_appWindowClosingToken) {
41
- m_appWindow.Closing(m_appWindowClosingToken);
42
- m_appWindowClosingToken.value = 0;
40
+ if (m_appWindowClosingToken) {
41
+ m_rnWindow.AppWindow().Closing(m_appWindowClosingToken);
42
+ m_appWindowClosingToken = {};
43
43
  }
44
44
 
45
45
  // Reset topWindowID before destroying
@@ -49,21 +49,15 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
49
49
  m_prevWindowID = 0;
50
50
  }
51
51
 
52
- // Close island
53
- if (m_reactNativeIsland) {
54
- m_reactNativeIsland.Island().Close();
55
- m_reactNativeIsland = nullptr;
56
- }
57
-
58
52
  // Hide popup
59
53
  if (m_popUp.IsVisible()) {
60
54
  m_popUp.Hide();
61
55
  }
62
56
 
63
57
  // Destroy AppWindow this automatically resumes parent window to receive inputs
64
- if (m_appWindow) {
65
- m_appWindow.Destroy();
66
- m_appWindow = nullptr;
58
+ if (m_rnWindow.AppWindow()) {
59
+ m_rnWindow.Close();
60
+ m_rnWindow = nullptr;
67
61
  }
68
62
 
69
63
  // Bring parent window to foreground
@@ -111,11 +105,11 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
111
105
  }
112
106
 
113
107
  // Update Title if changed and AppWindow exists
114
- if (m_appWindow && (!oldProps || newViewProps.title != oldViewProps.title)) {
108
+ if (m_rnWindow && (!oldProps || newViewProps.title != oldViewProps.title)) {
115
109
  // Use empty string if title is not set
116
110
  winrt::hstring titleValue =
117
111
  newViewProps.title.has_value() ? winrt::to_hstring(newViewProps.title.value()) : winrt::hstring();
118
- m_appWindow.Title(titleValue);
112
+ m_rnWindow.AppWindow().Title(titleValue);
119
113
  }
120
114
 
121
115
  ::Microsoft::ReactNativeSpecs::BaseModalHostView<ModalHostView>::UpdateProps(view, newProps, oldProps);
@@ -181,7 +175,7 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
181
175
  }
182
176
 
183
177
  void AdjustWindowSize(const winrt::Microsoft::ReactNative::LayoutMetrics &layoutMetrics) noexcept {
184
- if (!m_appWindow) {
178
+ if (!m_rnWindow) {
185
179
  return;
186
180
  }
187
181
 
@@ -198,17 +192,17 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
198
192
  clientHeightPx = std::max(100, clientHeightPx);
199
193
 
200
194
  // Size the client area directly
201
- m_appWindow.ResizeClient({clientWidthPx, clientHeightPx});
195
+ m_rnWindow.AppWindow().ResizeClient({clientWidthPx, clientHeightPx});
202
196
 
203
197
  // Center the window on its parent
204
198
  RECT parentRC;
205
199
  GetWindowRect(m_parentHwnd, &parentRC);
206
- auto outerSize = m_appWindow.Size();
200
+ auto outerSize = m_rnWindow.AppWindow().Size();
207
201
 
208
202
  int32_t xCor = parentRC.left + (parentRC.right - parentRC.left - outerSize.Width) / 2;
209
203
  int32_t yCor = parentRC.top + (parentRC.bottom - parentRC.top - outerSize.Height) / 2;
210
204
 
211
- m_appWindow.Move({xCor, yCor});
205
+ m_rnWindow.AppWindow().Move({xCor, yCor});
212
206
  };
213
207
 
214
208
  void ShowOnUIThread(const winrt::Microsoft::ReactNative::ComponentView &view) {
@@ -231,8 +225,7 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
231
225
 
232
226
  // dispatch onShow event
233
227
  if (auto eventEmitter = EventEmitter()) {
234
- ::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnShow eventArgs;
235
- eventEmitter->onShow(eventArgs);
228
+ eventEmitter->onShow({});
236
229
  }
237
230
  }
238
231
  }
@@ -261,8 +254,7 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
261
254
 
262
255
  // Dispatch onDismiss event
263
256
  if (auto eventEmitter = EventEmitter()) {
264
- ::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnDismiss eventArgs;
265
- eventEmitter->onDismiss(eventArgs);
257
+ eventEmitter->onDismiss({});
266
258
  }
267
259
  }
268
260
 
@@ -279,59 +271,55 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
279
271
  view.as<::Microsoft::ReactNative::Composition::Experimental::IComponentViewInterop>()->GetHwndForParenting();
280
272
 
281
273
  auto portal = view.as<winrt::Microsoft::ReactNative::Composition::PortalComponentView>();
282
- m_reactNativeIsland = winrt::Microsoft::ReactNative::ReactNativeIsland::CreatePortal(portal);
283
- auto contentIsland = m_reactNativeIsland.Island();
284
-
285
274
  m_popUp = winrt::Microsoft::UI::Content::DesktopPopupSiteBridge::Create(
286
275
  portal.Parent()
287
276
  .as<winrt::Microsoft::ReactNative::Composition::ComponentView>()
288
277
  .Root()
289
278
  .ReactNativeIsland()
290
279
  .Island());
291
- m_popUp.Connect(contentIsland);
292
280
 
293
281
  // Get AppWindow and configure presenter
294
- m_appWindow = winrt::Microsoft::UI::Windowing::AppWindow::GetFromWindowId(m_popUp.WindowId());
295
- if (m_appWindow) {
296
- auto overlappedPresenter = winrt::Microsoft::UI::Windowing::OverlappedPresenter::Create();
297
-
298
- // Configure presenter for modal behavior
299
- overlappedPresenter.IsModal(true);
300
- overlappedPresenter.SetBorderAndTitleBar(true, true);
301
-
302
- // modal should only have close button
303
- overlappedPresenter.IsMinimizable(false);
304
- overlappedPresenter.IsMaximizable(false);
305
-
306
- // Apply the presenter to the window
307
- m_appWindow.SetPresenter(overlappedPresenter);
308
-
309
- // Hide the title bar icon
310
- m_appWindow.TitleBar().IconShowOptions(winrt::Microsoft::UI::Windowing::IconShowOptions::HideIconAndSystemMenu);
311
-
312
- // Set initial title using the stored local props
313
- if (m_localProps && m_localProps->title.has_value()) {
314
- winrt::hstring titleValue = winrt::to_hstring(m_localProps->title.value());
315
- m_appWindow.Title(titleValue);
316
- } else {
317
- m_appWindow.Title(L""); // Empty title if not provided
318
- }
282
+ m_rnWindow = winrt::Microsoft::ReactNative::ReactNativeWindow::CreateFromContentSiteBridgeAndIsland(
283
+ m_popUp, winrt::Microsoft::ReactNative::ReactNativeIsland::CreatePortal(portal));
284
+ m_rnWindow.ResizePolicy(winrt::Microsoft::ReactNative::ContentSizePolicy::None);
285
+ auto overlappedPresenter = winrt::Microsoft::UI::Windowing::OverlappedPresenter::Create();
286
+
287
+ // Configure presenter for modal behavior
288
+ overlappedPresenter.IsModal(true);
289
+ overlappedPresenter.SetBorderAndTitleBar(true, true);
290
+
291
+ // modal should only have close button
292
+ overlappedPresenter.IsMinimizable(false);
293
+ overlappedPresenter.IsMaximizable(false);
294
+
295
+ // Apply the presenter to the window
296
+ m_rnWindow.AppWindow().SetPresenter(overlappedPresenter);
297
+
298
+ // Hide the title bar icon
299
+ m_rnWindow.AppWindow().TitleBar().IconShowOptions(
300
+ winrt::Microsoft::UI::Windowing::IconShowOptions::HideIconAndSystemMenu);
301
+
302
+ // Set initial title using the stored local props
303
+ if (m_localProps && m_localProps->title.has_value()) {
304
+ winrt::hstring titleValue = winrt::to_hstring(m_localProps->title.value());
305
+ m_rnWindow.AppWindow().Title(titleValue);
306
+ } else {
307
+ m_rnWindow.AppWindow().Title(L""); // Empty title if not provided
308
+ }
319
309
 
320
- // Handle close request ('X' button)
321
- m_appWindowClosingToken =
322
- m_appWindow.Closing([wkThis = get_weak()](
323
- const winrt::Microsoft::UI::Windowing::AppWindow & /*sender*/,
324
- const winrt::Microsoft::UI::Windowing::AppWindowClosingEventArgs &args) {
325
- args.Cancel(true); // Prevent default close
326
- if (auto strongThis = wkThis.get()) {
327
- // Dispatch onRequestClose event
328
- if (auto eventEmitter = strongThis->EventEmitter()) {
329
- ::Microsoft::ReactNativeSpecs::ModalHostViewEventEmitter::OnRequestClose eventArgs;
330
- eventEmitter->onRequestClose(eventArgs);
331
- }
310
+ // Handle close request ('X' button)
311
+ m_appWindowClosingToken =
312
+ m_rnWindow.AppWindow().Closing([wkThis = get_weak()](
313
+ const winrt::Microsoft::UI::Windowing::AppWindow & /*sender*/,
314
+ const winrt::Microsoft::UI::Windowing::AppWindowClosingEventArgs &args) {
315
+ args.Cancel(true); // Prevent default close
316
+ if (auto strongThis = wkThis.get()) {
317
+ // Dispatch onRequestClose event
318
+ if (auto eventEmitter = strongThis->EventEmitter()) {
319
+ eventEmitter->onRequestClose({});
332
320
  }
333
- });
334
- }
321
+ }
322
+ });
335
323
 
336
324
  // set the top-level windows as the new hwnd
337
325
  winrt::Microsoft::ReactNative::ReactCoreInjection::SetTopLevelWindowId(
@@ -352,10 +340,10 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
352
340
  });
353
341
  */
354
342
 
355
- m_islandStateChangedToken =
356
- contentIsland.StateChanged([weakThis = get_weak()](
357
- winrt::Microsoft::UI::Content::ContentIsland const &island,
358
- winrt::Microsoft::UI::Content::ContentIslandStateChangedEventArgs const &args) {
343
+ m_islandStateChangedToken = m_rnWindow.ReactNativeIsland().Island().StateChanged(
344
+ [weakThis = get_weak()](
345
+ winrt::Microsoft::UI::Content::ContentIsland const &island,
346
+ winrt::Microsoft::UI::Content::ContentIslandStateChangedEventArgs const &args) {
359
347
  if (auto pThis = weakThis.get()) {
360
348
  if (args.DidRasterizationScaleChange() || args.DidLayoutDirectionChange()) {
361
349
  pThis->UpdateConstraints();
@@ -375,7 +363,7 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
375
363
  m_popUp.SiteView().EnvironmentView().DisplayId());
376
364
  auto workArea = displayArea.WorkArea();
377
365
 
378
- float scale = m_reactNativeIsland.Island().RasterizationScale();
366
+ float scale = m_rnWindow.ReactNativeIsland().Island().RasterizationScale();
379
367
 
380
368
  winrt::Microsoft::ReactNative::LayoutConstraints constraints;
381
369
  constraints.MinimumSize = {0, 0};
@@ -384,7 +372,7 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
384
372
  static_cast<float>((workArea.Width / scale) * 0.9), static_cast<float>((workArea.Height / scale) * 0.9)};
385
373
  constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
386
374
 
387
- auto layoutDirection = m_reactNativeIsland.Island().LayoutDirection();
375
+ auto layoutDirection = m_rnWindow.ReactNativeIsland().Island().LayoutDirection();
388
376
  if (layoutDirection == winrt::Microsoft::UI::Content::ContentLayoutDirection::LeftToRight)
389
377
  constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::LeftToRight;
390
378
  else if (layoutDirection == winrt::Microsoft::UI::Content::ContentLayoutDirection::RightToLeft)
@@ -394,7 +382,7 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
394
382
  // When no constraint is set (maxSize is std::numeric_limits<Float>::infinity()), yoga will layout the content to a
395
383
  // desired size If we provide a specific max size, then contents with a flex:1 will expand to fill that size. We
396
384
  // might want to provide a windows specific property to control this behavior.
397
- m_state.UpdateState(winrt::make<ModalHostState>(constraints, m_reactNativeIsland.Island().RasterizationScale()));
385
+ m_state.UpdateState(winrt::make<ModalHostState>(constraints, scale));
398
386
  }
399
387
 
400
388
  static void TrySetFocus(const winrt::Microsoft::ReactNative::ComponentView &view) {
@@ -414,9 +402,8 @@ struct ModalHostView : public winrt::implements<ModalHostView, winrt::Windows::F
414
402
  winrt::event_token m_departFocusToken;
415
403
  winrt::event_token m_childLayoutMetricsToken;
416
404
  winrt::Microsoft::ReactNative::IComponentState m_state{nullptr};
417
- winrt::Microsoft::ReactNative::ReactNativeIsland m_reactNativeIsland{nullptr};
405
+ winrt::Microsoft::ReactNative::ReactNativeWindow m_rnWindow{nullptr};
418
406
  winrt::Microsoft::UI::Content::DesktopPopupSiteBridge m_popUp{nullptr};
419
- winrt::Microsoft::UI::Windowing::AppWindow m_appWindow{nullptr};
420
407
  winrt::event_token m_appWindowClosingToken;
421
408
  winrt::com_ptr<::Microsoft::ReactNativeSpecs::ModalHostViewProps> m_localProps{nullptr};
422
409
  };
@@ -168,9 +168,6 @@ winrt::Microsoft::ReactNative::ReactNativeIsland ReactNativeIsland::CreatePortal
168
168
  return winrt::make<ReactNativeIsland>(portal);
169
169
  }
170
170
 
171
- ReactNativeIsland::ReactNativeIsland() noexcept
172
- : ReactNativeIsland(winrt::Microsoft::UI::Composition::Compositor{nullptr}) {}
173
-
174
171
  ReactNativeIsland::~ReactNativeIsland() noexcept {
175
172
  #ifdef USE_WINUI3
176
173
  if (m_island) {
@@ -220,6 +217,10 @@ void ReactNativeIsland::ReactViewHost(winrt::Microsoft::ReactNative::IReactViewH
220
217
  }
221
218
  }
222
219
 
220
+ winrt::Microsoft::UI::Composition::Compositor ReactNativeIsland::Compositor() noexcept {
221
+ return m_compositor;
222
+ }
223
+
223
224
  winrt::Microsoft::UI::Composition::Visual ReactNativeIsland::RootVisual() noexcept {
224
225
  return winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::InnerVisual(
225
226
  m_rootVisual);
@@ -48,7 +48,6 @@ struct FocusNavigationResult : FocusNavigationResultT<FocusNavigationResult> {
48
48
 
49
49
  struct ReactNativeIsland
50
50
  : ReactNativeIslandT<ReactNativeIsland, Composition::Experimental::IInternalCompositionRootView> {
51
- ReactNativeIsland() noexcept;
52
51
  ~ReactNativeIsland() noexcept;
53
52
 
54
53
  ReactNativeIsland(const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept;
@@ -65,6 +64,8 @@ struct ReactNativeIsland
65
64
  ReactNative::IReactViewHost ReactViewHost() noexcept;
66
65
  void ReactViewHost(ReactNative::IReactViewHost const &value);
67
66
 
67
+ winrt::Microsoft::UI::Composition::Compositor Compositor() noexcept;
68
+
68
69
  winrt::Microsoft::UI::Composition::Visual RootVisual() noexcept;
69
70
 
70
71
  // property RootVisual
@@ -0,0 +1,245 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ #include "pch.h"
4
+ #include "ReactNativeWindow.h"
5
+ #include "ReactNativeWindow.g.cpp"
6
+
7
+ #include <Fabric/Composition/CompositionUIService.h>
8
+ #include <winrt/Microsoft.UI.Content.h>
9
+ #include <winrt/Microsoft.UI.Input.h>
10
+ #include <winrt/Microsoft.UI.interop.h>
11
+
12
+ namespace winrt::Microsoft::ReactNative::implementation {
13
+
14
+ void ReactNativeWindow::UpdateRootViewSizeToAppWindow(
15
+ winrt::Microsoft::ReactNative::ReactNativeIsland const &rootView,
16
+ winrt::Microsoft::UI::Windowing::AppWindow const &window) noexcept {
17
+ if (!rootView) {
18
+ return;
19
+ }
20
+
21
+ if (m_resizePolicy != winrt::Microsoft::ReactNative::ContentSizePolicy::ResizeContentToParentWindow) {
22
+ return;
23
+ }
24
+
25
+ auto scaleFactor = GetDpiForWindow(winrt::Microsoft::UI::GetWindowFromWindowId(window.Id())) /
26
+ static_cast<float>(USER_DEFAULT_SCREEN_DPI);
27
+ winrt::Windows::Foundation::Size size{
28
+ window.ClientSize().Width / scaleFactor, window.ClientSize().Height / scaleFactor};
29
+ // Do not relayout when minimized
30
+ auto presenter = window.Presenter().try_as<winrt::Microsoft::UI::Windowing::OverlappedPresenter>();
31
+ if (!presenter || presenter.State() != winrt::Microsoft::UI::Windowing::OverlappedPresenterState::Minimized) {
32
+ winrt::Microsoft::ReactNative::LayoutConstraints constraints;
33
+ constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
34
+ constraints.MaximumSize = constraints.MinimumSize = size;
35
+ rootView.Arrange(constraints, {0, 0});
36
+ }
37
+ }
38
+
39
+ ReactNativeWindow::ReactNativeWindow() noexcept {}
40
+
41
+ winrt::Microsoft::ReactNative::ReactNativeWindow ReactNativeWindow::CreateFromCompositor(
42
+ const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept {
43
+ auto reactNativeWindow = make_self<ReactNativeWindow>();
44
+ reactNativeWindow->m_compositor = compositor;
45
+ reactNativeWindow->AppWindow(winrt::Microsoft::UI::Windowing::AppWindow::Create());
46
+ return *reactNativeWindow;
47
+ }
48
+
49
+ winrt::Microsoft::ReactNative::ReactNativeWindow ReactNativeWindow::CreateFromWindow(
50
+ const winrt::Microsoft::UI::Windowing::AppWindow &appWindow,
51
+ const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept {
52
+ auto reactNativeWindow = make_self<ReactNativeWindow>();
53
+ reactNativeWindow->m_compositor = compositor;
54
+ reactNativeWindow->AppWindow(appWindow);
55
+ return *reactNativeWindow;
56
+ }
57
+
58
+ winrt::Microsoft::ReactNative::ReactNativeWindow ReactNativeWindow::CreateFromWindowAndIsland(
59
+ const winrt::Microsoft::UI::Windowing::AppWindow &appWindow,
60
+ const winrt::Microsoft::ReactNative::ReactNativeIsland &island) noexcept {
61
+ auto reactNativeWindow = make_self<ReactNativeWindow>();
62
+ reactNativeWindow->AppWindow(appWindow);
63
+ reactNativeWindow->ReactNativeIsland(island);
64
+ return *reactNativeWindow;
65
+ }
66
+
67
+ winrt::Microsoft::ReactNative::ReactNativeWindow ReactNativeWindow::CreateFromContentSiteBridgeAndIsland(
68
+ const winrt::Microsoft::UI::Content::IContentSiteBridge &bridge,
69
+ const winrt::Microsoft::ReactNative::ReactNativeIsland &island) {
70
+ auto reactNativeWindow = make_self<ReactNativeWindow>();
71
+ reactNativeWindow->m_bridge = bridge;
72
+
73
+ if (auto desktopSiteBridge = bridge.try_as<winrt::Microsoft::UI::Content::DesktopSiteBridge>()) {
74
+ reactNativeWindow->AppWindow(
75
+ winrt::Microsoft::UI::Windowing::AppWindow::GetFromWindowId(desktopSiteBridge.WindowId()));
76
+ } else if (auto desktopPopupSiteBridge = bridge.as<winrt::Microsoft::UI::Content::DesktopPopupSiteBridge>()) {
77
+ reactNativeWindow->AppWindow(
78
+ winrt::Microsoft::UI::Windowing::AppWindow::GetFromWindowId(desktopPopupSiteBridge.WindowId()));
79
+ } else {
80
+ throw winrt::hresult_not_implemented(L"Unsupported ContentSiteBridge type");
81
+ }
82
+
83
+ reactNativeWindow->ReactNativeIsland(island);
84
+ return *reactNativeWindow;
85
+ }
86
+
87
+ ReactNativeWindow::~ReactNativeWindow() noexcept {
88
+ Close();
89
+ }
90
+
91
+ winrt::Microsoft::UI::Windowing::AppWindow ReactNativeWindow::AppWindow() noexcept {
92
+ if (!m_appWindow) {
93
+ AppWindow(winrt::Microsoft::UI::Windowing::AppWindow::Create());
94
+ }
95
+
96
+ return m_appWindow;
97
+ }
98
+
99
+ void ReactNativeWindow::AppWindow(const winrt::Microsoft::UI::Windowing::AppWindow &appWindow) noexcept {
100
+ assert(!m_appWindow);
101
+
102
+ m_appWindow = appWindow;
103
+
104
+ if (!m_appWindow)
105
+ return;
106
+
107
+ // Update the size of the RootView when the AppWindow changes size
108
+ m_appWindowChangedToken = m_appWindow.Changed(
109
+ [this](
110
+ winrt::Microsoft::UI::Windowing::AppWindow const &window,
111
+ winrt::Microsoft::UI::Windowing::AppWindowChangedEventArgs const &args) { AppWindow_Changed(window, args); });
112
+
113
+ UpdateRootViewSizeToAppWindow(m_island, m_appWindow);
114
+ }
115
+
116
+ void ReactNativeWindow::AppWindow_Changed(
117
+ winrt::Microsoft::UI::Windowing::AppWindow const &window,
118
+ winrt::Microsoft::UI::Windowing::AppWindowChangedEventArgs const &args) noexcept {
119
+ if (args.DidSizeChange() || args.DidVisibilityChange()) {
120
+ UpdateRootViewSizeToAppWindow(m_island, m_appWindow);
121
+ }
122
+ }
123
+
124
+ winrt::Microsoft::ReactNative::ReactNativeIsland ReactNativeWindow::ReactNativeIsland() noexcept {
125
+ if (!m_island) {
126
+ ReactNativeIsland(winrt::Microsoft::ReactNative::ReactNativeIsland(Compositor()));
127
+ }
128
+
129
+ return m_island;
130
+ }
131
+
132
+ void ReactNativeWindow::Connect(winrt::Microsoft::UI::Content::ContentIsland contentIsland) noexcept {
133
+ if (auto desktopSiteBridge = ContentSiteBridge().try_as<winrt::Microsoft::UI::Content::DesktopChildSiteBridge>())
134
+ desktopSiteBridge.Connect(contentIsland);
135
+ else {
136
+ // Only support DesktopChildSiteBridge and DesktopPopupSiteBridge currently
137
+ auto popupSiteBridge = m_bridge.as<winrt::Microsoft::UI::Content::DesktopPopupSiteBridge>();
138
+ popupSiteBridge.Connect(contentIsland);
139
+ }
140
+ }
141
+
142
+ void ReactNativeWindow::ReactNativeIsland(const winrt::Microsoft::ReactNative::ReactNativeIsland &value) noexcept {
143
+ if (m_island && m_bridge) {
144
+ Connect(nullptr);
145
+ }
146
+
147
+ m_island = value;
148
+
149
+ if (m_island) {
150
+ m_island.as<winrt::Microsoft::ReactNative::Composition::Experimental::IInternalCompositionRootView>().SetWindow(
151
+ reinterpret_cast<uint64_t>(winrt::Microsoft::UI::GetWindowFromWindowId(m_appWindow.Id())));
152
+ Connect(m_island.Island());
153
+ UpdateIslandScaleFactor();
154
+ EnsureResizePolicyState();
155
+ }
156
+ }
157
+
158
+ winrt::Microsoft::UI::Composition::Compositor ReactNativeWindow::Compositor() noexcept {
159
+ if (!m_compositor)
160
+ m_compositor = ReactNativeIsland().Compositor();
161
+
162
+ return m_compositor;
163
+ }
164
+
165
+ winrt::Microsoft::UI::Content::IContentSiteBridge ReactNativeWindow::ContentSiteBridge() noexcept {
166
+ if (!m_bridge) {
167
+ auto desktopChildSiteBridge =
168
+ winrt::Microsoft::UI::Content::DesktopChildSiteBridge::Create(Compositor(), m_appWindow.Id());
169
+ desktopChildSiteBridge.ResizePolicy(winrt::Microsoft::UI::Content::ContentSizePolicy::ResizeContentToParentWindow);
170
+ m_bridge = desktopChildSiteBridge;
171
+
172
+ UpdateIslandScaleFactor();
173
+
174
+ desktopChildSiteBridge.Show();
175
+ }
176
+
177
+ return m_bridge;
178
+ }
179
+
180
+ void ReactNativeWindow::UpdateIslandScaleFactor() noexcept {
181
+ if (m_island) {
182
+ auto scaleFactor = GetDpiForWindow(winrt::Microsoft::UI::GetWindowFromWindowId(m_appWindow.Id())) /
183
+ static_cast<float>(USER_DEFAULT_SCREEN_DPI);
184
+ m_island.ScaleFactor(scaleFactor);
185
+ }
186
+ }
187
+
188
+ void ReactNativeWindow::ResizePolicy(winrt::Microsoft::ReactNative::ContentSizePolicy value) noexcept {
189
+ if (m_resizePolicy == value) {
190
+ return;
191
+ }
192
+
193
+ m_sizeChangedRevoker.revoke();
194
+
195
+ m_resizePolicy = value;
196
+
197
+ EnsureResizePolicyState();
198
+ }
199
+
200
+ void ReactNativeWindow::EnsureResizePolicyState() noexcept {
201
+ if (!m_island)
202
+ return;
203
+
204
+ if (m_resizePolicy == winrt::Microsoft::ReactNative::ContentSizePolicy::ResizeParentWindowToContent) {
205
+ m_sizeChangedRevoker = ReactNativeIsland().SizeChanged(
206
+ winrt::auto_revoke,
207
+ [compositor = Compositor(), appWindow = m_appWindow](
208
+ auto /*sender*/, const winrt::Microsoft::ReactNative::RootViewSizeChangedEventArgs &args) {
209
+ auto async = compositor.RequestCommitAsync();
210
+ async.Completed([appWindow, size = args.Size()](
211
+ auto /*asyncInfo*/, winrt::Windows::Foundation::AsyncStatus /*asyncStatus*/) {
212
+ appWindow.ResizeClient({static_cast<int>(size.Width), static_cast<int>(size.Height)});
213
+ });
214
+ });
215
+ ReactNativeIsland().Arrange(m_layoutConstraints, {0, 0});
216
+ }
217
+
218
+ if (m_island && m_resizePolicy == winrt::Microsoft::ReactNative::ContentSizePolicy::ResizeContentToParentWindow)
219
+ UpdateRootViewSizeToAppWindow(m_island, m_appWindow);
220
+ }
221
+
222
+ winrt::Microsoft::ReactNative::ContentSizePolicy ReactNativeWindow::ResizePolicy() const noexcept {
223
+ return m_resizePolicy;
224
+ }
225
+
226
+ winrt::Microsoft::ReactNative::LayoutConstraints ReactNativeWindow::LayoutConstraints() const noexcept {
227
+ return m_layoutConstraints;
228
+ }
229
+
230
+ void ReactNativeWindow::LayoutConstraints(winrt::Microsoft::ReactNative::LayoutConstraints const &value) noexcept {
231
+ m_layoutConstraints = value;
232
+ ReactNativeIsland().Arrange(m_layoutConstraints, {0, 0});
233
+ }
234
+
235
+ void ReactNativeWindow::Close() noexcept {
236
+ if (m_bridge)
237
+ m_bridge.Close();
238
+
239
+ if (m_appWindow) {
240
+ m_appWindow.Changed(m_appWindowChangedToken);
241
+ m_appWindow.Destroy();
242
+ }
243
+ }
244
+
245
+ } // namespace winrt::Microsoft::ReactNative::implementation
@@ -0,0 +1,80 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ #pragma once
4
+
5
+ #include "ReactNativeWindow.g.h"
6
+
7
+ #include <ReactContext.h>
8
+ #include <winrt/Microsoft.ReactNative.Composition.Experimental.h>
9
+ #include <winrt/Microsoft.ReactNative.h>
10
+ #include <winrt/Microsoft.UI.Content.h>
11
+ #include <winrt/Microsoft.UI.Windowing.h>
12
+ #include <winrt/Windows.UI.ViewManagement.h>
13
+
14
+ namespace winrt::Microsoft::ReactNative::implementation {
15
+
16
+ struct ReactNativeWindow : ReactNativeWindowT<ReactNativeWindow> {
17
+ ~ReactNativeWindow() noexcept;
18
+ ReactNativeWindow() noexcept;
19
+
20
+ static winrt::Microsoft::ReactNative::ReactNativeWindow CreateFromCompositor(
21
+ const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept;
22
+ static winrt::Microsoft::ReactNative::ReactNativeWindow CreateFromWindow(
23
+ const winrt::Microsoft::UI::Windowing::AppWindow &appWindow,
24
+ const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept;
25
+ static winrt::Microsoft::ReactNative::ReactNativeWindow CreateFromWindowAndIsland(
26
+ const winrt::Microsoft::UI::Windowing::AppWindow &appWindow,
27
+ const winrt::Microsoft::ReactNative::ReactNativeIsland &island) noexcept;
28
+ static winrt::Microsoft::ReactNative::ReactNativeWindow CreateFromContentSiteBridgeAndIsland(
29
+ const winrt::Microsoft::UI::Content::IContentSiteBridge &bridge,
30
+ const winrt::Microsoft::ReactNative::ReactNativeIsland &island);
31
+
32
+ winrt::Microsoft::ReactNative::ReactNativeIsland ReactNativeIsland() noexcept;
33
+
34
+ winrt::Microsoft::UI::Windowing::AppWindow AppWindow() noexcept;
35
+
36
+ winrt::Microsoft::UI::Content::IContentSiteBridge ContentSiteBridge() noexcept;
37
+
38
+ winrt::Microsoft::ReactNative::ContentSizePolicy ResizePolicy() const noexcept;
39
+ void ResizePolicy(winrt::Microsoft::ReactNative::ContentSizePolicy value) noexcept;
40
+
41
+ winrt::Microsoft::ReactNative::LayoutConstraints LayoutConstraints() const noexcept;
42
+ void LayoutConstraints(winrt::Microsoft::ReactNative::LayoutConstraints const &value) noexcept;
43
+
44
+ void Close() noexcept;
45
+
46
+ private:
47
+ void Connect(winrt::Microsoft::UI::Content::ContentIsland contentIsland) noexcept;
48
+ winrt::Microsoft::UI::Composition::Compositor Compositor() noexcept;
49
+ void AppWindow(const winrt::Microsoft::UI::Windowing::AppWindow &appWindow) noexcept;
50
+ void AppWindow_Changed(
51
+ winrt::Microsoft::UI::Windowing::AppWindow const &window,
52
+ winrt::Microsoft::UI::Windowing::AppWindowChangedEventArgs const &args) noexcept;
53
+
54
+ void ReactNativeIsland(const winrt::Microsoft::ReactNative::ReactNativeIsland &value) noexcept;
55
+
56
+ void UpdateIslandScaleFactor() noexcept;
57
+ void EnsureResizePolicyState() noexcept;
58
+ void UpdateRootViewSizeToAppWindow(
59
+ winrt::Microsoft::ReactNative::ReactNativeIsland const &rootView,
60
+ winrt::Microsoft::UI::Windowing::AppWindow const &window) noexcept;
61
+
62
+ winrt::Microsoft::UI::Composition::Compositor m_compositor{nullptr};
63
+ winrt::Microsoft::ReactNative::ReactNativeIsland m_island{nullptr};
64
+ winrt::event_token m_appWindowChangedToken;
65
+ winrt::Microsoft::ReactNative::ReactNativeIsland::SizeChanged_revoker m_sizeChangedRevoker;
66
+ winrt::Microsoft::ReactNative::ContentSizePolicy m_resizePolicy{
67
+ winrt::Microsoft::ReactNative::ContentSizePolicy::ResizeContentToParentWindow};
68
+ winrt::Microsoft::UI::Content::IContentSiteBridge m_bridge{nullptr};
69
+ winrt::Microsoft::UI::Windowing::AppWindow m_appWindow{nullptr};
70
+ winrt::Microsoft::ReactNative::LayoutConstraints m_layoutConstraints{
71
+ {0, 0},
72
+ {0, 0},
73
+ winrt::Microsoft::ReactNative::LayoutDirection::Undefined};
74
+ };
75
+
76
+ } // namespace winrt::Microsoft::ReactNative::implementation
77
+
78
+ namespace winrt::Microsoft::ReactNative::factory_implementation {
79
+ struct ReactNativeWindow : ReactNativeWindowT<ReactNativeWindow, implementation::ReactNativeWindow> {};
80
+ } // namespace winrt::Microsoft::ReactNative::factory_implementation