react-native-windows 0.81.4 → 0.81.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) 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 +47 -23
  34. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +3 -0
  35. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +3 -1
  36. package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +20 -95
  37. package/Microsoft.ReactNative/Modules/LogBoxModule.h +1 -1
  38. package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +0 -41
  39. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +0 -11
  40. package/Microsoft.ReactNative/ReactNativeIsland.idl +2 -3
  41. package/Microsoft.ReactNative/ReactNativeWin32App.cpp +31 -101
  42. package/Microsoft.ReactNative/ReactNativeWin32App.h +2 -13
  43. package/Microsoft.ReactNative/ReactNativeWindow.idl +44 -0
  44. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  45. package/Shared/Shared.vcxitems +7 -0
  46. package/Shared/Shared.vcxitems.filters +6 -0
  47. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +2 -1
  48. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +26 -9
  49. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +2 -1
  50. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +2 -1
  51. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +8 -3
  52. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +8 -3
  53. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +1 -0
  54. package/codegen/react/components/rnwcore/InputAccessory.g.h +2 -1
  55. package/codegen/react/components/rnwcore/ModalHostView.g.h +26 -9
  56. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +8 -3
  57. package/codegen/react/components/rnwcore/SafeAreaView.g.h +1 -0
  58. package/codegen/react/components/rnwcore/Switch.g.h +8 -3
  59. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +2 -1
  60. package/codegen/react/components/rnwcore/VirtualView.g.h +8 -3
  61. package/package.json +21 -21
@@ -6,7 +6,7 @@
6
6
 
7
7
  #include "ScrollViewComponentView.h"
8
8
 
9
- #include <UI.Xaml.Controls.h>
9
+ #include <Fabric/ComponentView.h>
10
10
  #include <Utils/ValueUtils.h>
11
11
 
12
12
  #pragma warning(push)
@@ -20,6 +20,8 @@
20
20
  #include <AutoDraw.h>
21
21
  #include <Fabric/DWriteHelpers.h>
22
22
  #include <unicode.h>
23
+ #include <functional>
24
+ #include "ContentIslandComponentView.h"
23
25
  #include "JSValueReader.h"
24
26
  #include "RootComponentView.h"
25
27
 
@@ -885,6 +887,13 @@ void ScrollViewComponentView::updateContentVisualSize() noexcept {
885
887
 
886
888
  void ScrollViewComponentView::prepareForRecycle() noexcept {}
887
889
 
890
+ void ScrollViewComponentView::updateChildrenClippingPath(
891
+ facebook::react::LayoutMetrics const & /*layoutMetrics*/,
892
+ const facebook::react::ViewProps & /*viewProps*/) noexcept {
893
+ // No-op: ScrollView mounts children into m_scrollVisual (not Visual()),
894
+ // and scroll visuals inherently clip their content.
895
+ }
896
+
888
897
  /*
889
898
  ScrollViewComponentView::ScrollInteractionTrackerOwner::ScrollInteractionTrackerOwner(
890
899
  ScrollViewComponentView *outer)
@@ -1326,6 +1335,10 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ScrollViewComp
1326
1335
  m_allowNextScrollNoMatterWhat = false;
1327
1336
  }
1328
1337
  }
1338
+
1339
+ // Issue #15557: Notify listeners that scroll position has changed,
1340
+ // so ContentIslandComponentView can update LocalToParentTransformMatrix
1341
+ FireViewChanged();
1329
1342
  });
1330
1343
 
1331
1344
  m_scrollBeginDragRevoker = m_scrollVisual.ScrollBeginDrag(
@@ -1333,6 +1346,9 @@ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ScrollViewComp
1333
1346
  [this](
1334
1347
  winrt::IInspectable const & /*sender*/,
1335
1348
  winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) {
1349
+ // Issue #15557: Notify listeners that scroll position has changed
1350
+ FireViewChanged();
1351
+
1336
1352
  m_allowNextScrollNoMatterWhat = true; // Ensure next scroll event is recorded, regardless of throttle
1337
1353
  updateStateWithContentOffset();
1338
1354
  auto eventEmitter = GetEventEmitter();
@@ -1479,4 +1495,20 @@ void ScrollViewComponentView::updateShowsVerticalScrollIndicator(bool value) noe
1479
1495
  void ScrollViewComponentView::updateDecelerationRate(float value) noexcept {
1480
1496
  m_scrollVisual.SetDecelerationRate({value, value, value});
1481
1497
  }
1498
+
1499
+ // Issue #15557: Notify listeners that scroll position has changed.
1500
+ // ContentIslandComponentView subscribes to this to update LocalToParentTransformMatrix.
1501
+ void ScrollViewComponentView::FireViewChanged() noexcept {
1502
+ m_viewChangedEvent(*this, nullptr);
1503
+ }
1504
+
1505
+ // Issue #15557: Event accessors for ViewChanged
1506
+ winrt::event_token ScrollViewComponentView::ViewChanged(
1507
+ winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable> const &handler) noexcept {
1508
+ return m_viewChangedEvent.add(handler);
1509
+ }
1510
+
1511
+ void ScrollViewComponentView::ViewChanged(winrt::event_token const &token) noexcept {
1512
+ m_viewChangedEvent.remove(token);
1513
+ }
1482
1514
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -118,6 +118,18 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
118
118
  double getVerticalSize() noexcept;
119
119
  double getHorizontalSize() noexcept;
120
120
 
121
+ // Issue #15557: Event accessors for ViewChanged (used by ContentIslandComponentView for transform update)
122
+ winrt::event_token ViewChanged(
123
+ winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable> const &handler) noexcept;
124
+ void ViewChanged(winrt::event_token const &token) noexcept;
125
+
126
+ protected:
127
+ // ScrollView mounts children into m_scrollVisual (not Visual()), and scroll visuals
128
+ // inherently clip their content, so we skip the children container clipping logic.
129
+ void updateChildrenClippingPath(
130
+ facebook::react::LayoutMetrics const &layoutMetrics,
131
+ const facebook::react::ViewProps &viewProps) noexcept override;
132
+
121
133
  private:
122
134
  void updateDecelerationRate(float value) noexcept;
123
135
  void updateContentVisualSize() noexcept;
@@ -129,6 +141,8 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
129
141
  bool scrollRight(float delta, bool animate) noexcept;
130
142
  void updateBackgroundColor(const facebook::react::SharedColor &color) noexcept;
131
143
  void updateStateWithContentOffset() noexcept;
144
+ // Issue #15557: Notify listeners that scroll position has changed
145
+ void FireViewChanged() noexcept;
132
146
  facebook::react::ScrollViewEventEmitter::Metrics getScrollMetrics(
133
147
  facebook::react::SharedViewEventEmitter const &eventEmitter,
134
148
  winrt::Microsoft::ReactNative::Composition::Experimental::IScrollPositionChangedArgs const &args) noexcept;
@@ -160,6 +174,9 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
160
174
  bool m_allowNextScrollNoMatterWhat{false};
161
175
  std::chrono::steady_clock::time_point m_lastScrollEventTime{};
162
176
  std::shared_ptr<facebook::react::ScrollViewShadowNode::ConcreteState const> m_state;
177
+
178
+ // Issue #15557: Event for notifying listeners when scroll position changes
179
+ winrt::event<winrt::Windows::Foundation::EventHandler<winrt::Windows::Foundation::IInspectable>> m_viewChangedEvent;
163
180
  };
164
181
 
165
182
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -186,6 +186,7 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
186
186
 
187
187
  auto pt = m_outer->getClientOffset();
188
188
  m_outer->m_caretVisual.Position({x - pt.x, y - pt.y});
189
+ m_outer->m_caretPosition = {x, y};
189
190
  return true;
190
191
  }
191
192
 
@@ -696,17 +697,10 @@ void WindowsTextInputComponentView::OnPointerPressed(
696
697
  }
697
698
 
698
699
  if (m_textServices && msg) {
699
- if (msg == WM_RBUTTONUP && !windowsTextInputProps().contextMenuHidden) {
700
- ShowContextMenu(position);
701
- args.Handled(true);
702
- } else if (msg == WM_RBUTTONUP && windowsTextInputProps().contextMenuHidden) {
703
- args.Handled(true);
704
- } else {
705
- LRESULT lresult;
706
- DrawBlock db(*this);
707
- auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
708
- args.Handled(hr != S_FALSE);
709
- }
700
+ LRESULT lresult;
701
+ DrawBlock db(*this);
702
+ auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
703
+ args.Handled(hr != S_FALSE);
710
704
  }
711
705
 
712
706
  // Emits the OnPressIn event
@@ -768,10 +762,18 @@ void WindowsTextInputComponentView::OnPointerReleased(
768
762
  }
769
763
 
770
764
  if (m_textServices && msg) {
771
- LRESULT lresult;
772
- DrawBlock db(*this);
773
- auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
774
- args.Handled(hr != S_FALSE);
765
+ // Show context menu on right button release (standard Windows behavior)
766
+ if (msg == WM_RBUTTONUP && !windowsTextInputProps().contextMenuHidden) {
767
+ ShowContextMenu(LocalToScreen(position));
768
+ args.Handled(true);
769
+ } else if (msg == WM_RBUTTONUP) {
770
+ // Context menu is hidden - don't mark as handled, let app add custom behavior
771
+ } else {
772
+ LRESULT lresult;
773
+ DrawBlock db(*this);
774
+ auto hr = m_textServices->TxSendMessage(msg, static_cast<WPARAM>(wParam), static_cast<LPARAM>(lParam), &lresult);
775
+ args.Handled(hr != S_FALSE);
776
+ }
775
777
  }
776
778
 
777
779
  // Emits the OnPressOut event
@@ -1225,8 +1227,11 @@ void WindowsTextInputComponentView::updateState(
1225
1227
  if (m_mostRecentEventCount == m_state->getData().mostRecentEventCount) {
1226
1228
  m_comingFromState = true;
1227
1229
  auto &fragments = m_state->getData().attributedStringBox.getValue().getFragments();
1228
- UpdateText(fragments.size() ? fragments[0].string : "");
1229
-
1230
+ {
1231
+ // DrawBlock defers DrawText() until after UpdateText completes
1232
+ DrawBlock db(*this);
1233
+ UpdateText(fragments.size() ? fragments[0].string : "");
1234
+ }
1230
1235
  m_comingFromState = false;
1231
1236
  }
1232
1237
  }
@@ -1375,7 +1380,7 @@ void WindowsTextInputComponentView::EmitOnScrollEvent() noexcept {
1375
1380
  }
1376
1381
 
1377
1382
  void WindowsTextInputComponentView::OnSelectionChanged(LONG start, LONG end) noexcept {
1378
- if (m_eventEmitter && !m_comingFromState /* && !m_comingFromJS ?? */) {
1383
+ if (m_eventEmitter && !m_comingFromState && !m_comingFromJS) {
1379
1384
  auto emitter = std::static_pointer_cast<const facebook::react::WindowsTextInputEventEmitter>(m_eventEmitter);
1380
1385
  facebook::react::WindowsTextInputEventEmitter::OnSelectionChange onSelectionChangeArgs;
1381
1386
  onSelectionChangeArgs.selection.start = start;
@@ -1676,7 +1681,8 @@ void WindowsTextInputComponentView::DrawText() noexcept {
1676
1681
  }
1677
1682
 
1678
1683
  bool isZeroSized =
1679
- m_layoutMetrics.frame.size.width <= (m_layoutMetrics.contentInsets.left + m_layoutMetrics.contentInsets.right);
1684
+ m_layoutMetrics.frame.size.width <= (m_layoutMetrics.contentInsets.left + m_layoutMetrics.contentInsets.right) ||
1685
+ m_layoutMetrics.frame.size.height <= (m_layoutMetrics.contentInsets.top + m_layoutMetrics.contentInsets.bottom);
1680
1686
  if (!m_drawingSurface || isZeroSized)
1681
1687
  return;
1682
1688
 
@@ -1870,6 +1876,21 @@ void WindowsTextInputComponentView::updateSpellCheck(bool enable) noexcept {
1870
1876
  m_textServices->TxSendMessage(EM_SETLANGOPTIONS, IMF_SPELLCHECKING, enable ? newLangOptions : 0, &lresult));
1871
1877
  }
1872
1878
 
1879
+ void WindowsTextInputComponentView::OnContextMenuKey(
1880
+ const winrt::Microsoft::ReactNative::Composition::Input::ContextMenuKeyEventArgs &args) noexcept {
1881
+ // Handle context menu key event (SHIFT+F10 or Context Menu key)
1882
+ if (!windowsTextInputProps().contextMenuHidden) {
1883
+ // m_caretPosition is stored from TxSetCaretPos in RichEdit client rect space (physical pixels).
1884
+ // LocalToScreen expects logical (DIP) coordinates, so divide by pointScaleFactor.
1885
+ auto screenPt = LocalToScreen(winrt::Windows::Foundation::Point{
1886
+ static_cast<float>(m_caretPosition.x) / m_layoutMetrics.pointScaleFactor,
1887
+ static_cast<float>(m_caretPosition.y) / m_layoutMetrics.pointScaleFactor});
1888
+ ShowContextMenu(screenPt);
1889
+ args.Handled(true);
1890
+ }
1891
+ // If contextMenuHidden, don't mark as handled - let app handle it
1892
+ }
1893
+
1873
1894
  void WindowsTextInputComponentView::ShowContextMenu(const winrt::Windows::Foundation::Point &position) noexcept {
1874
1895
  HMENU menu = CreatePopupMenu();
1875
1896
  if (!menu)
@@ -1889,13 +1910,16 @@ void WindowsTextInputComponentView::ShowContextMenu(const winrt::Windows::Founda
1889
1910
  AppendMenuW(menu, MF_STRING | (canPaste ? 0 : MF_GRAYED), 3, L"Paste");
1890
1911
  AppendMenuW(menu, MF_STRING | (!isEmpty && !isReadOnly ? 0 : MF_GRAYED), 4, L"Select All");
1891
1912
 
1892
- POINT cursorPos;
1893
- GetCursorPos(&cursorPos);
1894
-
1895
1913
  HWND hwnd = GetActiveWindow();
1896
1914
 
1897
1915
  int cmd = TrackPopupMenu(
1898
- menu, TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY, cursorPos.x, cursorPos.y, 0, hwnd, NULL);
1916
+ menu,
1917
+ TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RETURNCMD | TPM_NONOTIFY,
1918
+ static_cast<int>(position.X),
1919
+ static_cast<int>(position.Y),
1920
+ 0,
1921
+ hwnd,
1922
+ NULL);
1899
1923
 
1900
1924
  if (cmd == 1) { // Cut
1901
1925
  m_textServices->TxSendMessage(WM_CUT, 0, 0, &res);
@@ -67,6 +67,8 @@ struct WindowsTextInputComponentView
67
67
  void OnKeyUp(const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
68
68
  void OnCharacterReceived(const winrt::Microsoft::ReactNative::Composition::Input::CharacterReceivedRoutedEventArgs
69
69
  &args) noexcept override;
70
+ void OnContextMenuKey(
71
+ const winrt::Microsoft::ReactNative::Composition::Input::ContextMenuKeyEventArgs &args) noexcept override;
70
72
  void onMounted() noexcept override;
71
73
 
72
74
  std::optional<std::string> getAccessiblityValue() noexcept override;
@@ -146,6 +148,7 @@ struct WindowsTextInputComponentView
146
148
  DWORD m_propBitsMask{0};
147
149
  DWORD m_propBits{0};
148
150
  HCURSOR m_hcursor{nullptr};
151
+ POINT m_caretPosition{0, 0};
149
152
  std::chrono::steady_clock::time_point m_lastClickTime{};
150
153
  std::vector<facebook::react::CompWindowsTextInputSubmitKeyEventsStruct> m_submitKeyEvents;
151
154
  };
@@ -5,6 +5,7 @@
5
5
 
6
6
  #include <react/featureflags/ReactNativeFeatureFlags.h>
7
7
  #include <react/renderer/attributedstring/AttributedStringBox.h>
8
+ #include <react/renderer/attributedstring/PlaceholderAttributedString.h>
8
9
  #include <react/renderer/attributedstring/TextAttributes.h>
9
10
  #include <react/renderer/components/text/BaseTextShadowNode.h>
10
11
  #include <react/renderer/core/LayoutConstraints.h>
@@ -185,6 +186,7 @@ AttributedString WindowsTextInputShadowNode::getPlaceholderAttributedString(cons
185
186
  const auto &props = getConcreteProps();
186
187
 
187
188
  AttributedString attributedString;
189
+ attributedString.setBaseTextAttributes(props.textAttributes);
188
190
  //[windows
189
191
  if (!props.placeholder.empty()) {
190
192
  auto textAttributes = TextAttributes::defaultTextAttributes();
@@ -203,7 +205,7 @@ AttributedString WindowsTextInputShadowNode::getPlaceholderAttributedString(cons
203
205
  }
204
206
  // windows]
205
207
 
206
- return attributedString;
208
+ return ensurePlaceholderIfEmpty_DO_NOT_USE(attributedString);
207
209
  }
208
210
 
209
211
  #pragma mark - LayoutableShadowNode
@@ -12,6 +12,7 @@
12
12
  #ifdef USE_FABRIC
13
13
  #include <Fabric/Composition/CompositionContextHelper.h>
14
14
  #include <Fabric/Composition/CompositionUIService.h>
15
+ #include <winrt/Microsoft.UI.Windowing.h>
15
16
  #include <winrt/Windows.UI.Composition.h>
16
17
  #else
17
18
  #include <UI.Xaml.Controls.Primitives.h>
@@ -22,16 +23,14 @@ namespace Microsoft::ReactNative {
22
23
 
23
24
  LogBox::~LogBox() {
24
25
  #ifdef USE_FABRIC
25
- if (m_hwnd) {
26
- m_context.UIDispatcher().Post([hwnd = m_hwnd]() { DestroyWindow(hwnd); });
27
- m_hwnd = nullptr;
26
+ if (m_rnWindow) {
27
+ m_context.UIDispatcher().Post([rnWindow = m_rnWindow]() { rnWindow.Close(); });
28
+ m_rnWindow = nullptr;
28
29
  }
29
30
  #endif
30
31
  }
31
32
 
32
33
  #ifdef USE_FABRIC
33
- constexpr PCWSTR c_logBoxWindowClassName = L"MS_REACTNATIVE_LOGBOX";
34
- constexpr auto CompHostProperty = L"CompHost";
35
34
  const int LOGBOX_DEFAULT_WIDTH = 700;
36
35
  const int LOGBOX_DEFAULT_HEIGHT = 1000;
37
36
  #endif // USE_FABRIC
@@ -55,69 +54,6 @@ void LogBox::Hide() noexcept {
55
54
  });
56
55
  }
57
56
 
58
- #ifdef USE_FABRIC
59
- LRESULT CALLBACK LogBoxWndProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam) noexcept {
60
- auto data = reinterpret_cast<::IUnknown *>(GetProp(hwnd, CompHostProperty));
61
- winrt::com_ptr<winrt::IUnknown> spunk;
62
- React::CompositionHwndHost host{nullptr};
63
-
64
- if (data) {
65
- winrt::check_hresult(data->QueryInterface(winrt::guid_of<React::CompositionHwndHost>(), winrt::put_abi(host)));
66
- auto result = static_cast<LRESULT>(host.TranslateMessage(message, wparam, lparam));
67
- if (result)
68
- return result;
69
- }
70
-
71
- switch (message) {
72
- case WM_NCCREATE: {
73
- auto cs = reinterpret_cast<CREATESTRUCT *>(lparam);
74
- auto windowData = static_cast<::IUnknown *>(cs->lpCreateParams);
75
- SetProp(hwnd, CompHostProperty, reinterpret_cast<::IUnknown *>(windowData));
76
- break;
77
- }
78
- case WM_CREATE: {
79
- host.Initialize((uint64_t)hwnd);
80
- break;
81
- }
82
- case WM_CLOSE: {
83
- // Just hide the window instead of destroying it
84
- ::ShowWindow(hwnd, SW_HIDE);
85
- return 0;
86
- }
87
- case WM_DESTROY: {
88
- data->Release();
89
- SetProp(hwnd, CompHostProperty, nullptr);
90
- }
91
- }
92
-
93
- return DefWindowProc(hwnd, message, wparam, lparam);
94
- }
95
-
96
- void LogBox::RegisterWndClass() noexcept {
97
- static bool registered = false;
98
- if (registered)
99
- return;
100
-
101
- HINSTANCE hInstance = GetModuleHandle(NULL);
102
-
103
- WNDCLASSEXW wcex = {};
104
- wcex.cbSize = sizeof(WNDCLASSEX);
105
- wcex.style = CS_HREDRAW | CS_VREDRAW;
106
- wcex.lpfnWndProc = &LogBoxWndProc;
107
- wcex.cbClsExtra = DLGWINDOWEXTRA;
108
- wcex.cbWndExtra = sizeof(winrt::impl::abi<winrt::Microsoft::ReactNative::ICompositionHwndHost>::type *);
109
- wcex.hInstance = hInstance;
110
- wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
111
- wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
112
- wcex.lpszClassName = c_logBoxWindowClassName;
113
- ATOM classId = RegisterClassEx(&wcex);
114
- WINRT_VERIFY(classId);
115
- winrt::check_win32(!classId);
116
-
117
- registered = true;
118
- }
119
- #endif // USE_FABRIC
120
-
121
57
  void LogBox::ShowOnUIThread() noexcept {
122
58
  auto host = React::implementation::ReactNativeHost::GetReactNativeHost(m_context.Properties());
123
59
  if (!host)
@@ -173,45 +109,34 @@ void LogBox::ShowOnUIThread() noexcept {
173
109
  }
174
110
  #else
175
111
  else {
176
- RegisterWndClass();
177
-
178
- if (!m_hwnd) {
112
+ if (!m_rnWindow) {
113
+ m_rnWindow = winrt::Microsoft::ReactNative::ReactNativeWindow::CreateFromCompositor(
114
+ winrt::Microsoft::ReactNative::Composition::CompositionUIService::GetCompositor(
115
+ host.InstanceSettings().Properties()));
179
116
  auto CompositionHwndHost = React::CompositionHwndHost();
180
117
  winrt::Microsoft::ReactNative::ReactViewOptions viewOptions;
181
118
  viewOptions.ComponentName(L"LogBox");
182
- CompositionHwndHost.ReactViewHost(
119
+ m_rnWindow.AppWindow().Title(L"LogBox");
120
+ m_rnWindow.AppWindow().Closing([](winrt::Microsoft::UI::Windowing::AppWindow const & /*appWindow*/,
121
+ winrt::Microsoft::UI::Windowing::AppWindowClosingEventArgs const &args) {
122
+ // Prevent default close behavior - as JS will never try to show the logbox again if it isn't hidden through JS
123
+ args.Cancel(true);
124
+ });
125
+ m_rnWindow.ReactNativeIsland().ReactViewHost(
183
126
  winrt::Microsoft::ReactNative::ReactCoreInjection::MakeViewHost(host, viewOptions));
184
- HINSTANCE hInstance = GetModuleHandle(NULL);
185
- winrt::impl::abi<winrt::Microsoft::ReactNative::ICompositionHwndHost>::type *pHost{nullptr};
186
- winrt::com_ptr<::IUnknown> spunk;
187
- CompositionHwndHost.as(spunk);
188
- spunk->AddRef(); // Will be stored in windowData
189
-
190
- m_hwnd = CreateWindow(
191
- c_logBoxWindowClassName,
192
- L"React-Native LogBox",
193
- WS_OVERLAPPEDWINDOW,
194
- CW_USEDEFAULT,
195
- CW_USEDEFAULT,
196
- LOGBOX_DEFAULT_WIDTH,
197
- LOGBOX_DEFAULT_HEIGHT,
198
- nullptr,
199
- nullptr,
200
- hInstance,
201
- spunk.get());
127
+ m_rnWindow.AppWindow().ResizeClient({LOGBOX_DEFAULT_WIDTH, LOGBOX_DEFAULT_HEIGHT});
202
128
  }
203
129
 
204
- ShowWindow(m_hwnd, SW_NORMAL);
205
- BringWindowToTop(m_hwnd);
206
- SetFocus(m_hwnd);
130
+ m_rnWindow.AppWindow().Show(true);
131
+ m_rnWindow.AppWindow().MoveInZOrderAtTop();
207
132
  }
208
133
  #endif // USE_FABRIC
209
134
  }
210
135
 
211
136
  void LogBox::HideOnUIThread() noexcept {
212
137
  #ifdef USE_FABRIC
213
- if (m_hwnd) {
214
- ::ShowWindow(m_hwnd, SW_HIDE);
138
+ if (m_rnWindow) {
139
+ m_rnWindow.AppWindow().Hide();
215
140
  }
216
141
  #else // USE_FABRIC
217
142
  if (m_popup) {
@@ -31,7 +31,7 @@ struct LogBox : public std::enable_shared_from_this<LogBox> {
31
31
 
32
32
  winrt::Microsoft::ReactNative::ReactContext m_context;
33
33
  #ifdef USE_FABRIC
34
- HWND m_hwnd{nullptr};
34
+ winrt::Microsoft::ReactNative::ReactNativeWindow m_rnWindow{nullptr};
35
35
  #else
36
36
  xaml::Controls::Primitives::Popup m_popup{nullptr};
37
37
  winrt::Microsoft::ReactNative::ReactRootView m_logBoxContent{nullptr};
@@ -20,19 +20,6 @@ ReactNativeAppBuilder::ReactNativeAppBuilder() {
20
20
 
21
21
  ReactNativeAppBuilder::~ReactNativeAppBuilder() {}
22
22
 
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);
27
- return *this;
28
- }
29
-
30
- winrt::Microsoft::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetCompositor(
31
- winrt::Microsoft::UI::Composition::Compositor const &compositor) {
32
- m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->Compositor(compositor);
33
- return *this;
34
- }
35
-
36
23
  winrt::Microsoft::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetAppWindow(
37
24
  winrt::Microsoft::UI::Windowing::AppWindow const &appWindow) {
38
25
  m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->AppWindow(appWindow);
@@ -41,34 +28,6 @@ winrt::Microsoft::ReactNative::ReactNativeAppBuilder ReactNativeAppBuilder::SetA
41
28
  }
42
29
 
43
30
  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);
47
-
48
- // Create a DispatcherQueue for this thread. This is needed for Composition, Content, and Input APIs.
49
- auto dispatcherQueueController =
50
- winrt::Microsoft::UI::Dispatching::DispatcherQueueController::CreateOnCurrentThread();
51
-
52
- m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->DispatcherQueueController(
53
- dispatcherQueueController);
54
- }
55
-
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.
59
- auto compositor = winrt::Microsoft::UI::Composition::Compositor();
60
- m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->Compositor(compositor);
61
- }
62
-
63
- // Create the AppWindow if the app developer doesn't provide one
64
- if (m_reactNativeWin32App.AppWindow() == nullptr) {
65
- auto appWindow = winrt::Microsoft::UI::Windowing::AppWindow::Create();
66
- appWindow.Title(L"ReactNativeWin32App");
67
- appWindow.Resize({1000, 1000});
68
-
69
- m_reactNativeWin32App.as<implementation::ReactNativeWin32App>().get()->AppWindow(appWindow);
70
- }
71
-
72
31
  return m_reactNativeWin32App;
73
32
  }
74
33
 
@@ -18,12 +18,6 @@ namespace Microsoft.ReactNative {
18
18
 
19
19
  ReactViewOptions ReactViewOptions {get;};
20
20
 
21
- // TODO: Hide these APIs for now until we're sure we need to expose them and can do so safely
22
- // Microsoft.UI.Composition.Compositor Compositor {get;};
23
- // Microsoft.UI.Content.DesktopChildSiteBridge DesktopChildSiteBridge {get;};
24
- // Microsoft.UI.Dispatching DispatcherQueueController {get;};
25
- // ReactNativeIsland ReactNativeIsland {get;};
26
-
27
21
  // Methods
28
22
  void Start();
29
23
  }
@@ -38,11 +32,6 @@ namespace Microsoft.ReactNative {
38
32
 
39
33
  ReactNativeAppBuilder SetAppWindow(Microsoft.UI.Windowing.AppWindow appWindow);
40
34
 
41
- // TODO: Hide these APIs for now until we're sure we need to expose them and can do so safely
42
- // Compositor depends on the DispatcherQueue created by DispatcherQueueController
43
- // ReactNativeAppBuilder SetCompositor(Microsoft.UI.Composition.Compositor compositor);
44
- // ReactNativeAppBuilder SetDispatcherQueueController(Microsoft.UI.Dispatching DispatcherQueueController);
45
-
46
35
  ReactNativeWin32App Build();
47
36
  }
48
37
  }
@@ -80,9 +80,6 @@ namespace Microsoft.ReactNative
80
80
  DOC_STRING("A windows composition component that hosts React Native UI elements.")
81
81
  runtimeclass ReactNativeIsland
82
82
  {
83
- DOC_STRING("Creates a new instance of @ReactNativeIsland. Can be implemented with a ReactViewHost or a ComponentView with reactContext")
84
- ReactNativeIsland();
85
-
86
83
  #ifdef USE_WINUI3
87
84
  ReactNativeIsland(Microsoft.UI.Composition.Compositor compositor);
88
85
 
@@ -100,6 +97,8 @@ namespace Microsoft.ReactNative
100
97
 
101
98
  Windows.Foundation.Size Size { get; };
102
99
 
100
+ Microsoft.UI.Composition.Compositor Compositor { get; };
101
+
103
102
  DOC_STRING("ScaleFactor for this windows (DPI/96)")
104
103
  Single ScaleFactor {get; set;};
105
104