react-native-windows 0.75.8 → 0.75.10

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 (49) hide show
  1. package/Microsoft.ReactNative/CompositionComponentView.idl +2 -1
  2. package/Microsoft.ReactNative/Fabric/AbiComponentDescriptor.cpp +4 -1
  3. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +1 -1
  4. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +7 -0
  5. package/Microsoft.ReactNative/Fabric/AbiViewProps.h +2 -0
  6. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +19 -4
  7. package/Microsoft.ReactNative/Fabric/ComponentView.h +8 -3
  8. package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.cpp +931 -0
  9. package/Microsoft.ReactNative/Fabric/Composition/BorderPrimitive.h +80 -0
  10. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +31 -13
  11. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +27 -3
  12. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +3 -1
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootAutomationProvider.cpp +8 -32
  14. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +302 -895
  15. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +26 -26
  16. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +1 -1
  17. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +130 -122
  18. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +14 -8
  19. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.cpp +34 -20
  20. package/Microsoft.ReactNative/Fabric/Composition/ReactCompositionViewComponentBuilder.h +5 -3
  21. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +63 -2
  22. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +12 -0
  23. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +51 -3
  24. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +3 -0
  25. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +18 -8
  26. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +3 -0
  27. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +46 -4
  28. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +5 -0
  29. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +9 -3
  30. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +11 -0
  31. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +2 -0
  32. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -1
  33. package/Microsoft.ReactNative/IReactCompositionViewComponentBuilder.idl +1 -0
  34. package/Microsoft.ReactNative/IReactViewComponentBuilder.idl +1 -1
  35. package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +25 -129
  36. package/Microsoft.ReactNative/ReactNativeAppBuilder.h +5 -13
  37. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +13 -34
  38. package/Microsoft.ReactNative/ReactNativeIsland.idl +3 -2
  39. package/Microsoft.ReactNative/ReactNativeWin32App.cpp +129 -18
  40. package/Microsoft.ReactNative/ReactNativeWin32App.h +14 -5
  41. package/Microsoft.ReactNative/ViewProps.idl +2 -0
  42. package/Microsoft.ReactNative.Cxx/ComponentView.Experimental.interop.h +14 -0
  43. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  44. package/Shared/Shared.vcxitems +3 -10
  45. package/Shared/Shared.vcxitems.filters +1 -0
  46. package/package.json +4 -4
  47. package/templates/cpp-app/windows/MyApp/MyApp.cpp +46 -130
  48. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.cpp +0 -59
  49. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.h +0 -23
@@ -127,6 +127,20 @@ ReactNativeIsland::ReactNativeIsland(const winrt::Microsoft::UI::Composition::Co
127
127
  InitTextScaleMultiplier();
128
128
  }
129
129
 
130
+ // Constructor to initialize ReactNativeIsland with context and componentView
131
+ ReactNativeIsland::ReactNativeIsland(
132
+ const winrt::Microsoft::UI::Composition::Compositor &compositor,
133
+ winrt::Microsoft::ReactNative::IReactContext context,
134
+ winrt::Microsoft::ReactNative::ComponentView componentView) noexcept
135
+ : m_compositor(compositor),
136
+ m_context(context),
137
+ m_layoutConstraints({{0, 0}, {0, 0}, winrt::Microsoft::ReactNative::LayoutDirection::Undefined}),
138
+ m_isFragment(true) {
139
+ m_rootTag = componentView.Tag();
140
+ InitTextScaleMultiplier();
141
+ AddFragmentCompositionEventHandler(context, componentView);
142
+ }
143
+
130
144
  ReactNativeIsland::ReactNativeIsland() noexcept : ReactNativeIsland(nullptr) {}
131
145
 
132
146
  ReactNativeIsland::~ReactNativeIsland() noexcept {
@@ -152,6 +166,7 @@ ReactNative::IReactViewHost ReactNativeIsland::ReactViewHost() noexcept {
152
166
  }
153
167
 
154
168
  void ReactNativeIsland::ReactViewHost(winrt::Microsoft::ReactNative::IReactViewHost const &value) noexcept {
169
+ assert(!m_isFragment); // make sure this isn't a FragmentIsalnd
155
170
  if (m_reactViewHost == value) {
156
171
  return;
157
172
  }
@@ -345,6 +360,29 @@ winrt::IInspectable ReactNativeIsland::GetUiaProvider() noexcept {
345
360
  return m_uiaProvider;
346
361
  }
347
362
 
363
+ winrt::Windows::Foundation::Point ReactNativeIsland::ConvertScreenToLocal(
364
+ winrt::Windows::Foundation::Point pt) noexcept {
365
+ if (m_island) {
366
+ auto pp = m_island.CoordinateConverter().ConvertScreenToLocal(
367
+ winrt::Windows::Graphics::PointInt32{static_cast<int32_t>(pt.X), static_cast<int32_t>(pt.Y)});
368
+ return {static_cast<float>(pp.X), static_cast<float>(pp.Y)};
369
+ }
370
+ POINT p{static_cast<LONG>(pt.X), static_cast<LONG>(pt.Y)};
371
+ ScreenToClient(m_hwnd, &p);
372
+ return {static_cast<float>(p.x) / m_scaleFactor, static_cast<float>(p.y) / m_scaleFactor};
373
+ }
374
+
375
+ winrt::Windows::Foundation::Point ReactNativeIsland::ConvertLocalToScreen(
376
+ winrt::Windows::Foundation::Point pt) noexcept {
377
+ if (m_island) {
378
+ auto pp = m_island.CoordinateConverter().ConvertLocalToScreen(pt);
379
+ return {static_cast<float>(pp.X), static_cast<float>(pp.Y)};
380
+ }
381
+ POINT p{static_cast<LONG>(pt.X * m_scaleFactor), static_cast<LONG>(pt.Y * m_scaleFactor)};
382
+ ClientToScreen(m_hwnd, &p);
383
+ return {static_cast<float>(p.x), static_cast<float>(p.y)};
384
+ }
385
+
348
386
  void ReactNativeIsland::SetWindow(uint64_t hwnd) noexcept {
349
387
  m_hwnd = reinterpret_cast<HWND>(hwnd);
350
388
  }
@@ -404,7 +442,7 @@ void ReactNativeIsland::InitRootView(
404
442
 
405
443
  m_context = winrt::Microsoft::ReactNative::ReactContext(std::move(context));
406
444
  m_reactViewOptions = std::move(viewOptions);
407
- m_CompositionEventHandler = std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this);
445
+ m_CompositionEventHandler = std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this, -1);
408
446
  m_CompositionEventHandler->Initialize();
409
447
 
410
448
  UpdateRootViewInternal();
@@ -412,6 +450,27 @@ void ReactNativeIsland::InitRootView(
412
450
  m_isInitialized = true;
413
451
  }
414
452
 
453
+ void ReactNativeIsland::AddFragmentCompositionEventHandler(
454
+ winrt::Microsoft::ReactNative::IReactContext context,
455
+ winrt::Microsoft::ReactNative::ComponentView componentView) noexcept {
456
+ m_uiDispatcher = context.Properties()
457
+ .Get(winrt::Microsoft::ReactNative::ReactDispatcherHelper::UIDispatcherProperty())
458
+ .try_as<IReactDispatcher>();
459
+ VerifyElseCrash(m_uiDispatcher.HasThreadAccess());
460
+ VerifyElseCrash(m_rootTag != -1);
461
+ auto uiManager = ::Microsoft::ReactNative::FabricUIManager::FromProperties(
462
+ winrt::Microsoft::ReactNative::ReactPropertyBag(context.Properties()));
463
+
464
+ if (!m_CompositionEventHandler) {
465
+ // Create CompositionEventHandler if not already created
466
+ m_context = winrt::Microsoft::ReactNative::ReactContext(context);
467
+ m_CompositionEventHandler =
468
+ std::make_shared<::Microsoft::ReactNative::CompositionEventHandler>(m_context, *this, componentView.Tag());
469
+ m_CompositionEventHandler->Initialize();
470
+ m_isInitialized = true;
471
+ }
472
+ }
473
+
415
474
  void ReactNativeIsland::UpdateRootView() noexcept {
416
475
  VerifyElseCrash(m_uiDispatcher.HasThreadAccess());
417
476
  VerifyElseCrash(m_isInitialized);
@@ -834,7 +893,9 @@ void ReactNativeIsland::OnMounted() noexcept {
834
893
  return;
835
894
  m_mounted = true;
836
895
  if (auto componentView = GetComponentView()) {
837
- componentView->onMounted();
896
+ if (!componentView->isMounted()) {
897
+ componentView->onMounted();
898
+ }
838
899
  }
839
900
  }
840
901
 
@@ -48,6 +48,10 @@ struct ReactNativeIsland
48
48
  ~ReactNativeIsland() noexcept;
49
49
 
50
50
  ReactNativeIsland(const winrt::Microsoft::UI::Composition::Compositor &compositor) noexcept;
51
+ ReactNativeIsland(
52
+ const winrt::Microsoft::UI::Composition::Compositor &compositor,
53
+ winrt::Microsoft::ReactNative::IReactContext context,
54
+ winrt::Microsoft::ReactNative::ComponentView componentView) noexcept;
51
55
  winrt::Microsoft::UI::Content::ContentIsland Island();
52
56
 
53
57
  // property ReactViewHost
@@ -110,6 +114,9 @@ struct ReactNativeIsland
110
114
  void SetWindow(uint64_t hwnd) noexcept;
111
115
  int64_t SendMessage(uint32_t msg, uint64_t wParam, int64_t lParam) noexcept;
112
116
 
117
+ winrt::Windows::Foundation::Point ConvertScreenToLocal(winrt::Windows::Foundation::Point pt) noexcept;
118
+ winrt::Windows::Foundation::Point ConvertLocalToScreen(winrt::Windows::Foundation::Point pt) noexcept;
119
+
113
120
  bool CapturePointer(
114
121
  const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer,
115
122
  facebook::react::Tag tag) noexcept;
@@ -117,6 +124,10 @@ struct ReactNativeIsland
117
124
  const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer,
118
125
  facebook::react::Tag tag) noexcept;
119
126
 
127
+ void AddFragmentCompositionEventHandler(
128
+ winrt::Microsoft::ReactNative::IReactContext context,
129
+ winrt::Microsoft::ReactNative::ComponentView componentView) noexcept;
130
+
120
131
  public: // IReactViewInstance UI-thread implementation
121
132
  void InitRootView(
122
133
  winrt::Microsoft::ReactNative::IReactContext &&context,
@@ -136,6 +147,7 @@ struct ReactNativeIsland
136
147
  #endif
137
148
 
138
149
  HWND m_hwnd{0};
150
+ bool m_isFragment{false};
139
151
  bool m_isInitialized{false};
140
152
  bool m_isJSViewAttached{false};
141
153
  bool m_hasRenderedVisual{false};
@@ -7,6 +7,7 @@
7
7
  #include "RootComponentView.h"
8
8
 
9
9
  #include <Fabric/FabricUIManagerModule.h>
10
+ #include <winrt/Microsoft.UI.Input.h>
10
11
  #include "CompositionRootAutomationProvider.h"
11
12
  #include "ReactNativeIsland.h"
12
13
  #include "Theme.h"
@@ -24,7 +25,7 @@ RootComponentView::RootComponentView(
24
25
  reactContext,
25
26
  ComponentViewFeatures::Default &
26
27
  ~(ComponentViewFeatures::Background | ComponentViewFeatures::ShadowProps |
27
- ComponentViewFeatures::NativeBorder)) {}
28
+ ComponentViewFeatures::NativeBorder | ComponentViewFeatures::FocusVisual)) {}
28
29
 
29
30
  RootComponentView::~RootComponentView() {
30
31
  if (auto rootView = m_wkRootView.get()) {
@@ -106,7 +107,10 @@ bool RootComponentView::TrySetFocusedComponent(
106
107
  auto target = view;
107
108
  auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
108
109
  if (selfView && !selfView->focusable()) {
109
- target = FocusManager::FindFirstFocusableElement(target);
110
+ target = (direction == winrt::Microsoft::ReactNative::FocusNavigationDirection::Last ||
111
+ direction == winrt::Microsoft::ReactNative::FocusNavigationDirection::Previous)
112
+ ? FocusManager::FindLastFocusableElement(target)
113
+ : FocusManager::FindFirstFocusableElement(target);
110
114
  if (!target)
111
115
  return false;
112
116
  selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(target);
@@ -147,6 +151,9 @@ bool RootComponentView::TryMoveFocus(bool next) noexcept {
147
151
  [currentlyFocused = m_focusedComponent, next](const winrt::Microsoft::ReactNative::ComponentView &view) noexcept {
148
152
  if (view == currentlyFocused)
149
153
  return false;
154
+ auto selfView = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view);
155
+ if (!selfView->focusable())
156
+ return false;
150
157
 
151
158
  return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(view)
152
159
  ->rootComponentView()
@@ -156,7 +163,28 @@ bool RootComponentView::TryMoveFocus(bool next) noexcept {
156
163
  : winrt::Microsoft::ReactNative::FocusNavigationDirection::Previous);
157
164
  };
158
165
 
159
- return winrt::Microsoft::ReactNative::implementation::walkTree(m_focusedComponent, next, fn);
166
+ if (winrt::Microsoft::ReactNative::implementation::walkTree(m_focusedComponent, next, fn)) {
167
+ return true;
168
+ }
169
+
170
+ // We reached the end of the focus loop. Notify the island in case the host wants to move focus somewhere outside the
171
+ // island.
172
+ auto island = parentContentIsland();
173
+ if (island) {
174
+ auto focusController = winrt::Microsoft::UI::Input::InputFocusController::GetForIsland(island);
175
+ auto request = winrt::Microsoft::UI::Input::FocusNavigationRequest::Create(
176
+ next ? winrt::Microsoft::UI::Input::FocusNavigationReason::Last
177
+ : winrt::Microsoft::UI::Input::FocusNavigationReason::First);
178
+ auto result = focusController.DepartFocus(request);
179
+ if (result == winrt::Microsoft::UI::Input::FocusNavigationResult::Moved) {
180
+ return true;
181
+ }
182
+ }
183
+
184
+ // Wrap focus around if nothing outside the island takes focus
185
+ return NavigateFocus(winrt::Microsoft::ReactNative::FocusNavigationRequest(
186
+ next ? winrt::Microsoft::ReactNative::FocusNavigationReason::First
187
+ : winrt::Microsoft::ReactNative::FocusNavigationReason::Last));
160
188
  }
161
189
 
162
190
  HRESULT RootComponentView::GetFragmentRoot(IRawElementProviderFragmentRoot **pRetVal) noexcept {
@@ -220,6 +248,26 @@ float RootComponentView::FontSizeMultiplier() const noexcept {
220
248
  return 1.0f;
221
249
  }
222
250
 
251
+ winrt::Windows::Foundation::Point RootComponentView::ConvertScreenToLocal(
252
+ winrt::Windows::Foundation::Point pt) noexcept {
253
+ if (auto rootView = m_wkRootView.get()) {
254
+ return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)
255
+ ->ConvertScreenToLocal(pt);
256
+ }
257
+ assert(false);
258
+ return {};
259
+ }
260
+
261
+ winrt::Windows::Foundation::Point RootComponentView::ConvertLocalToScreen(
262
+ winrt::Windows::Foundation::Point pt) noexcept {
263
+ if (auto rootView = m_wkRootView.get()) {
264
+ return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)
265
+ ->ConvertLocalToScreen(pt);
266
+ }
267
+ assert(false);
268
+ return {};
269
+ }
270
+
223
271
  winrt::Microsoft::UI::Content::ContentIsland RootComponentView::parentContentIsland() noexcept {
224
272
  if (auto rootView = m_wkRootView.get()) {
225
273
  return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ReactNativeIsland>(rootView)->Island();
@@ -38,6 +38,9 @@ struct RootComponentView : RootComponentViewT<RootComponentView, ViewComponentVi
38
38
 
39
39
  RootComponentView *rootComponentView() const noexcept override;
40
40
 
41
+ winrt::Windows::Foundation::Point ConvertScreenToLocal(winrt::Windows::Foundation::Point pt) noexcept;
42
+ winrt::Windows::Foundation::Point ConvertLocalToScreen(winrt::Windows::Foundation::Point pt) noexcept;
43
+
41
44
  winrt::Microsoft::UI::Content::ContentIsland parentContentIsland() noexcept;
42
45
 
43
46
  // Index that visuals can be inserted into OuterVisual for debugging UI
@@ -1112,9 +1112,9 @@ void ScrollViewComponentView::StartBringIntoView(
1112
1112
  options.TargetRect->origin.y > m_scrollVisual.ScrollPosition().y) {
1113
1113
  needsScroll = true;
1114
1114
  if (options.TargetRect->size.height > viewerHeight) {
1115
- scrollToVertical = options.TargetRect->origin.y + options.VerticalOffset;
1115
+ scrollToVertical = options.TargetRect->origin.y + options.VerticalOffset * m_layoutMetrics.pointScaleFactor;
1116
1116
  } else {
1117
- scrollToVertical = (targetBottom - viewerHeight) + options.VerticalOffset;
1117
+ scrollToVertical = (targetBottom - viewerHeight) + options.VerticalOffset * m_layoutMetrics.pointScaleFactor;
1118
1118
  }
1119
1119
  // Scroll Up
1120
1120
  } else if (
@@ -1122,9 +1122,9 @@ void ScrollViewComponentView::StartBringIntoView(
1122
1122
  targetBottom < (m_scrollVisual.ScrollPosition().y + viewerHeight)) {
1123
1123
  needsScroll = true;
1124
1124
  if (options.TargetRect->size.height > viewerHeight) {
1125
- scrollToVertical = targetBottom - viewerHeight - options.VerticalOffset;
1125
+ scrollToVertical = targetBottom - viewerHeight - options.VerticalOffset * m_layoutMetrics.pointScaleFactor;
1126
1126
  } else {
1127
- scrollToVertical = options.TargetRect->origin.y - options.VerticalOffset;
1127
+ scrollToVertical = options.TargetRect->origin.y - options.VerticalOffset * m_layoutMetrics.pointScaleFactor;
1128
1128
  }
1129
1129
  }
1130
1130
  } else {
@@ -1138,9 +1138,9 @@ void ScrollViewComponentView::StartBringIntoView(
1138
1138
  options.TargetRect->origin.x > m_scrollVisual.ScrollPosition().x) {
1139
1139
  needsScroll = true;
1140
1140
  if (options.TargetRect->size.width > viewerWidth) {
1141
- scrollToHorizontal = options.TargetRect->origin.x + options.HorizontalOffset;
1141
+ scrollToHorizontal = options.TargetRect->origin.x + options.HorizontalOffset * m_layoutMetrics.pointScaleFactor;
1142
1142
  } else {
1143
- scrollToHorizontal = (targetRight - viewerWidth) + options.HorizontalOffset;
1143
+ scrollToHorizontal = (targetRight - viewerWidth) + options.HorizontalOffset * m_layoutMetrics.pointScaleFactor;
1144
1144
  }
1145
1145
  // Scroll Left
1146
1146
  } else if (
@@ -1148,9 +1148,9 @@ void ScrollViewComponentView::StartBringIntoView(
1148
1148
  targetRight < (m_scrollVisual.ScrollPosition().x + viewerWidth)) {
1149
1149
  needsScroll = true;
1150
1150
  if (options.TargetRect->size.width > viewerWidth) {
1151
- scrollToHorizontal = targetRight - viewerWidth - options.HorizontalOffset;
1151
+ scrollToHorizontal = targetRight - viewerWidth - options.HorizontalOffset * m_layoutMetrics.pointScaleFactor;
1152
1152
  } else {
1153
- scrollToHorizontal = options.TargetRect->origin.x - options.HorizontalOffset;
1153
+ scrollToHorizontal = options.TargetRect->origin.x - options.HorizontalOffset * m_layoutMetrics.pointScaleFactor;
1154
1154
  }
1155
1155
  }
1156
1156
  } else {
@@ -1262,4 +1262,14 @@ std::string ScrollViewComponentView::DefaultControlType() const noexcept {
1262
1262
  return "scrollbar";
1263
1263
  }
1264
1264
 
1265
+ winrt::com_ptr<ComponentView> ScrollViewComponentView::focusVisualRoot(
1266
+ const facebook::react::Rect &focusRect) noexcept {
1267
+ return get_strong();
1268
+ }
1269
+
1270
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual
1271
+ ScrollViewComponentView::visualToHostFocus() noexcept {
1272
+ return m_scrollVisual;
1273
+ }
1274
+
1265
1275
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -110,6 +110,9 @@ struct ScrollInteractionTrackerOwner : public winrt::implements<
110
110
  bool lineRight(bool animate) noexcept;
111
111
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual createVisual() noexcept override;
112
112
 
113
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual visualToHostFocus() noexcept override;
114
+ winrt::com_ptr<ComponentView> focusVisualRoot(const facebook::react::Rect &focusRect) noexcept override;
115
+
113
116
  private:
114
117
  void updateContentVisualSize() noexcept;
115
118
  bool scrollToEnd(bool animate) noexcept;
@@ -165,6 +165,10 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
165
165
 
166
166
  //@cmember Show the caret
167
167
  BOOL TxShowCaret(BOOL fShow) override {
168
+ // Only show the caret if we have focus
169
+ if (fShow && !m_outer->m_hasFocus) {
170
+ return false;
171
+ }
168
172
  m_outer->ShowCaret(m_outer->windowsTextInputProps().caretHidden ? false : fShow);
169
173
  return true;
170
174
  }
@@ -237,14 +241,20 @@ struct CompTextHost : public winrt::implements<CompTextHost, ITextHost> {
237
241
 
238
242
  //@cmember Converts screen coordinates of a specified point to the client coordinates
239
243
  BOOL TxScreenToClient(LPPOINT lppt) override {
240
- assert(false);
241
- return {};
244
+ winrt::Windows::Foundation::Point pt{static_cast<float>(lppt->x), static_cast<float>(lppt->y)};
245
+ auto localpt = m_outer->ScreenToLocal(pt);
246
+ lppt->x = static_cast<LONG>(localpt.X);
247
+ lppt->y = static_cast<LONG>(localpt.Y);
248
+ return true;
242
249
  }
243
250
 
244
251
  //@cmember Converts the client coordinates of a specified point to screen coordinates
245
252
  BOOL TxClientToScreen(LPPOINT lppt) override {
246
- assert(false);
247
- return {};
253
+ winrt::Windows::Foundation::Point pt{static_cast<float>(lppt->x), static_cast<float>(lppt->y)};
254
+ auto screenpt = m_outer->LocalToScreen(pt);
255
+ lppt->x = static_cast<LONG>(screenpt.X);
256
+ lppt->y = static_cast<LONG>(screenpt.Y);
257
+ return true;
248
258
  }
249
259
 
250
260
  //@cmember Request host to activate text services
@@ -870,6 +880,7 @@ void WindowsTextInputComponentView::OnCharacterReceived(
870
880
  emitter->onKeyPress(onKeyPressArgs);
871
881
 
872
882
  WPARAM wParam = static_cast<WPARAM>(args.KeyCode());
883
+
873
884
  LPARAM lParam = 0;
874
885
  lParam = args.KeyStatus().RepeatCount; // bits 0-15
875
886
  lParam |= args.KeyStatus().ScanCode << 16; // bits 16-23
@@ -908,6 +919,7 @@ void WindowsTextInputComponentView::UnmountChildComponentView(
908
919
 
909
920
  void WindowsTextInputComponentView::onLostFocus(
910
921
  const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
922
+ m_hasFocus = false;
911
923
  Super::onLostFocus(args);
912
924
  if (m_textServices) {
913
925
  LRESULT lresult;
@@ -919,6 +931,7 @@ void WindowsTextInputComponentView::onLostFocus(
919
931
 
920
932
  void WindowsTextInputComponentView::onGotFocus(
921
933
  const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
934
+ m_hasFocus = true;
922
935
  Super::onGotFocus(args);
923
936
  if (m_textServices) {
924
937
  LRESULT lresult;
@@ -1022,6 +1035,10 @@ void WindowsTextInputComponentView::updateProps(
1022
1035
  m_submitKeyEvents.clear();
1023
1036
  }
1024
1037
 
1038
+ if (oldTextInputProps.autoCapitalize != newTextInputProps.autoCapitalize) {
1039
+ autoCapitalizeOnUpdateProps(oldTextInputProps.autoCapitalize, newTextInputProps.autoCapitalize);
1040
+ }
1041
+
1025
1042
  UpdatePropertyBits();
1026
1043
  }
1027
1044
 
@@ -1476,4 +1493,29 @@ winrt::Microsoft::ReactNative::ComponentView WindowsTextInputComponentView::Crea
1476
1493
  return winrt::make<WindowsTextInputComponentView>(compContext, tag, reactContext);
1477
1494
  }
1478
1495
 
1496
+ // This function assumes that previous and new capitalization types are different.
1497
+ void WindowsTextInputComponentView::autoCapitalizeOnUpdateProps(
1498
+ const std::string &previousCapitalizationType,
1499
+ const std::string &newCapitalizationType) noexcept {
1500
+ /*
1501
+ Possible values are:
1502
+ Characters - All characters.
1503
+ Words - First letter of each word.
1504
+ Sentences - First letter of each sentence.
1505
+ None - Do not autocapitalize anything.
1506
+
1507
+ For now, only characters and none are supported.
1508
+ */
1509
+
1510
+ if (previousCapitalizationType == "characters") {
1511
+ winrt::check_hresult(m_textServices->TxSendMessage(
1512
+ EM_SETEDITSTYLE, 0 /* disable */, SES_UPPERCASE /* flag affected */, nullptr /* LRESULT */));
1513
+ }
1514
+
1515
+ if (newCapitalizationType == "characters") {
1516
+ winrt::check_hresult(m_textServices->TxSendMessage(
1517
+ EM_SETEDITSTYLE, SES_UPPERCASE /* enable */, SES_UPPERCASE /* flag affected */, nullptr /* LRESULT */));
1518
+ }
1519
+ }
1520
+
1479
1521
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -104,6 +104,10 @@ struct WindowsTextInputComponentView
104
104
  void InternalFinalize() noexcept;
105
105
  void UpdatePropertyBits() noexcept;
106
106
 
107
+ void autoCapitalizeOnUpdateProps(
108
+ const std::string &previousCapitalizationType,
109
+ const std::string &newcapitalizationType) noexcept;
110
+
107
111
  winrt::Windows::UI::Composition::CompositionSurfaceBrush m_brush{nullptr};
108
112
  winrt::Microsoft::ReactNative::Composition::Experimental::ICaretVisual m_caretVisual{nullptr};
109
113
  winrt::Microsoft::ReactNative::Composition::Experimental::IDrawingSurfaceBrush m_drawingSurface{nullptr};
@@ -124,6 +128,7 @@ struct WindowsTextInputComponentView
124
128
  int m_cDrawBlock{0};
125
129
  bool m_needsRedraw{false};
126
130
  bool m_drawing{false};
131
+ bool m_hasFocus{false};
127
132
  bool m_clearTextOnSubmit{false};
128
133
  bool m_multiline{false};
129
134
  DWORD m_propBitsMask{0};
@@ -330,7 +330,9 @@ bool Theme::TryGetPlatformColor(const std::string &platformColor, winrt::Windows
330
330
  {"AcrylicInAppFillColorDefault", {0x9E, 0xFF, 0xFF, 0xFF}},
331
331
  {"SystemChromeMediumLowColor", {0xFF, 0xF2, 0xF2, 0xF2}},
332
332
  {"SystemControlForegroundBaseHighColor", {0xFF, 0x00, 0x00, 0x00}},
333
- {"SystemControlTransientBorderColor", {0x24, 0x00, 0x00, 0x00}}};
333
+ {"SystemControlTransientBorderColor", {0x24, 0x00, 0x00, 0x00}},
334
+ {"FocusVisualPrimary", {0xFF, 0x00, 0x00, 0x00}},
335
+ {"FocusVisualSecondary", {0x99, 0xFF, 0xFF, 0xFF}}};
334
336
 
335
337
  static std::unordered_map<std::string, winrt::Windows::UI::Color, std::hash<std::string_view>, std::equal_to<>>
336
338
  s_darkColors = {
@@ -362,7 +364,9 @@ bool Theme::TryGetPlatformColor(const std::string &platformColor, winrt::Windows
362
364
  {"AcrylicInAppFillColorDefault", {0x9E, 0x00, 0x00, 0x00}},
363
365
  {"SystemChromeMediumLowColor", {0xFF, 0x2B, 0x2B, 0x2B}},
364
366
  {"SystemControlForegroundBaseHighColor", {0xFF, 0xFF, 0xFF, 0xFF}},
365
- {"SystemControlTransientBorderColor", {0x5C, 0x00, 0x00, 0x00}}};
367
+ {"SystemControlTransientBorderColor", {0x5C, 0x00, 0x00, 0x00}},
368
+ {"FocusVisualPrimary", {0xFF, 0xFF, 0xFF, 0xFF}},
369
+ {"FocusVisualSecondary", {0x99, 0x00, 0x00, 0x00F}}};
366
370
 
367
371
  static std::unordered_map<
368
372
  std::string,
@@ -399,7 +403,9 @@ bool Theme::TryGetPlatformColor(const std::string &platformColor, winrt::Windows
399
403
  {"ControlStrongFillColorDisabled", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace, {}}},
400
404
  {"SystemChromeMediumLowColor", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace, {}}},
401
405
  {"SystemControlForegroundBaseHighColor", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonText, {}}},
402
- {"SystemControlTransientBorderColor", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonText, {}}}};
406
+ {"SystemControlTransientBorderColor", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonText, {}}},
407
+ {"FocusVisualPrimary", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonText, {}}},
408
+ {"FocusVisualSecondary", {winrt::Windows::UI::ViewManagement::UIElementType::ButtonFace, {}}}};
403
409
 
404
410
  auto alias = s_xamlAliasedColors.find(platformColor);
405
411
  if (alias != s_xamlAliasedColors.end()) {
@@ -214,4 +214,15 @@ ExpandCollapseState GetExpandCollapseState(const bool &expanded) noexcept {
214
214
  }
215
215
  }
216
216
 
217
+ ToggleState GetToggleState(const std::optional<facebook::react::AccessibilityState> &state) noexcept {
218
+ if (state.has_value()) {
219
+ if (state->checked == facebook::react::AccessibilityState::Checked) {
220
+ return ToggleState::ToggleState_On;
221
+ } else if (state->checked == facebook::react::AccessibilityState::Mixed) {
222
+ return ToggleState::ToggleState_Indeterminate;
223
+ }
224
+ }
225
+ return ToggleState::ToggleState_Off;
226
+ }
227
+
217
228
  } // namespace winrt::Microsoft::ReactNative::implementation
@@ -36,4 +36,6 @@ std::string extractAccessibilityValue(const facebook::react::AccessibilityValue
36
36
  void DispatchAccessibilityAction(::Microsoft::ReactNative::ReactTaggedView &view, const std::string &action) noexcept;
37
37
 
38
38
  ExpandCollapseState GetExpandCollapseState(const bool &expanded) noexcept;
39
+
40
+ ToggleState GetToggleState(const std::optional<facebook::react::AccessibilityState> &state) noexcept;
39
41
  } // namespace winrt::Microsoft::ReactNative::implementation
@@ -26,7 +26,7 @@ UnimplementedNativeViewComponentView::UnimplementedNativeViewComponentView(
26
26
  ~(ComponentViewFeatures::Background | ComponentViewFeatures::ShadowProps |
27
27
  ComponentViewFeatures::NativeBorder)) {
28
28
  m_labelVisual = compContext.CreateSpriteVisual();
29
- OuterVisual().InsertAt(m_labelVisual, 1);
29
+ OuterVisual().InsertAt(m_labelVisual, 0);
30
30
  }
31
31
 
32
32
  winrt::Microsoft::ReactNative::ComponentView UnimplementedNativeViewComponentView::Create(
@@ -33,6 +33,7 @@ namespace Microsoft.ReactNative.Composition
33
33
  void SetViewComponentViewInitializer(ViewComponentViewInitializer initializer);
34
34
  void SetContentIslandComponentViewInitializer(ComponentIslandComponentViewInitializer initializer);
35
35
  void SetCreateVisualHandler(CreateVisualDelegate impl);
36
+ void SetViewFeatures(ComponentViewFeatures viewFeatures);
36
37
  };
37
38
 
38
39
  } // namespace Microsoft.ReactNative
@@ -56,7 +56,7 @@ namespace Microsoft.ReactNative
56
56
 
57
57
  [experimental]
58
58
  DOC_STRING("A delegate that creates a @IComponentProps object for an instance of @ViewProps. See @IReactViewComponentBuilder.SetCreateProps")
59
- delegate IComponentProps ViewPropsFactory(ViewProps props);
59
+ delegate IComponentProps ViewPropsFactory(ViewProps props, IComponentProps cloneFrom);
60
60
 
61
61
  [experimental]
62
62
  delegate Windows.Foundation.Size MeasureContentHandler(ShadowNode shadowNode, LayoutContext layoutContext, LayoutConstraints layoutConstraints);