react-native-windows 0.81.3 → 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 (71) 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/ABIViewManager.cpp +12 -1
  12. package/Microsoft.ReactNative/ComponentView.idl +2 -0
  13. package/Microsoft.ReactNative/Composition.Input.idl +7 -0
  14. package/Microsoft.ReactNative/CompositionComponentView.idl +5 -0
  15. package/Microsoft.ReactNative/CompositionHwndHost.idl +1 -0
  16. package/Microsoft.ReactNative/CompositionSwitcher.idl +16 -9
  17. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +19 -1
  18. package/Microsoft.ReactNative/Fabric/ComponentView.h +10 -1
  19. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +12 -0
  20. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +15 -0
  21. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +15 -0
  22. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +75 -0
  23. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +1 -0
  24. package/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp +10 -45
  25. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +86 -19
  26. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +4 -0
  27. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.cpp +95 -22
  28. package/Microsoft.ReactNative/Fabric/Composition/ContentIslandComponentView.h +15 -0
  29. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +61 -74
  30. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +71 -12
  31. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.h +11 -0
  32. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +4 -3
  33. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +2 -1
  34. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeWindow.cpp +245 -0
  35. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeWindow.h +80 -0
  36. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +33 -1
  37. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +17 -0
  38. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +47 -23
  39. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +3 -0
  40. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +3 -1
  41. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +8 -4
  42. package/Microsoft.ReactNative/Modules/ImageViewManagerModule.cpp +41 -15
  43. package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +20 -95
  44. package/Microsoft.ReactNative/Modules/LogBoxModule.h +1 -1
  45. package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +0 -41
  46. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +0 -11
  47. package/Microsoft.ReactNative/ReactNativeIsland.idl +2 -3
  48. package/Microsoft.ReactNative/ReactNativeWin32App.cpp +31 -101
  49. package/Microsoft.ReactNative/ReactNativeWin32App.h +2 -13
  50. package/Microsoft.ReactNative/ReactNativeWindow.idl +44 -0
  51. package/Mso/src/dispatchQueue/queueService.cpp +3 -1
  52. package/Mso/src/dispatchQueue/uiScheduler_winrt.cpp +2 -1
  53. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  54. package/Shared/Networking/OriginPolicyHttpFilter.cpp +2 -1
  55. package/Shared/Shared.vcxitems +7 -0
  56. package/Shared/Shared.vcxitems.filters +6 -0
  57. package/codegen/react/components/rnwcore/ActivityIndicatorView.g.h +2 -1
  58. package/codegen/react/components/rnwcore/AndroidDrawerLayout.g.h +42 -25
  59. package/codegen/react/components/rnwcore/AndroidHorizontalScrollContentView.g.h +2 -1
  60. package/codegen/react/components/rnwcore/AndroidProgressBar.g.h +2 -1
  61. package/codegen/react/components/rnwcore/AndroidSwipeRefreshLayout.g.h +11 -6
  62. package/codegen/react/components/rnwcore/AndroidSwitch.g.h +11 -6
  63. package/codegen/react/components/rnwcore/DebuggingOverlay.g.h +1 -0
  64. package/codegen/react/components/rnwcore/InputAccessory.g.h +2 -1
  65. package/codegen/react/components/rnwcore/ModalHostView.g.h +40 -23
  66. package/codegen/react/components/rnwcore/PullToRefreshView.g.h +11 -6
  67. package/codegen/react/components/rnwcore/SafeAreaView.g.h +1 -0
  68. package/codegen/react/components/rnwcore/Switch.g.h +11 -6
  69. package/codegen/react/components/rnwcore/UnimplementedNativeView.g.h +2 -1
  70. package/codegen/react/components/rnwcore/VirtualView.g.h +41 -8
  71. package/package.json +21 -21
@@ -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
@@ -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
@@ -48,7 +48,8 @@ HRESULT UiaNavigateHelper(
48
48
  uint32_t index = children.Size() - 1;
49
49
  do {
50
50
  auto child = children.GetAt(index).as<winrt::Microsoft::ReactNative::implementation::ComponentView>();
51
- if (uiaProvider = child->EnsureUiaProvider()) {
51
+ uiaProvider = child->EnsureUiaProvider();
52
+ if (uiaProvider) {
52
53
  break;
53
54
  }
54
55
  } while (index-- != 0);
@@ -60,7 +61,8 @@ HRESULT UiaNavigateHelper(
60
61
  uint32_t index = 0;
61
62
  do {
62
63
  auto child = children.GetAt(index).as<winrt::Microsoft::ReactNative::implementation::ComponentView>();
63
- if (uiaProvider = child->EnsureUiaProvider()) {
64
+ uiaProvider = child->EnsureUiaProvider();
65
+ if (uiaProvider) {
64
66
  break;
65
67
  }
66
68
  } while (++index != children.Size());
@@ -74,7 +76,8 @@ HRESULT UiaNavigateHelper(
74
76
 
75
77
  while (++it != children.end()) {
76
78
  auto nextchild = (*it).as<winrt::Microsoft::ReactNative::implementation::ComponentView>();
77
- if (uiaProvider = nextchild->EnsureUiaProvider()) {
79
+ uiaProvider = nextchild->EnsureUiaProvider();
80
+ if (uiaProvider) {
78
81
  break;
79
82
  }
80
83
  }
@@ -91,7 +94,8 @@ HRESULT UiaNavigateHelper(
91
94
  do {
92
95
  it--;
93
96
  auto prevchild = (*it).as<winrt::Microsoft::ReactNative::implementation::ComponentView>();
94
- if (uiaProvider = prevchild->EnsureUiaProvider()) {
97
+ uiaProvider = prevchild->EnsureUiaProvider();
98
+ if (uiaProvider) {
95
99
  break;
96
100
  }
97
101
  } while (it != children.begin());