react-native-windows 0.74.4 → 0.74.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/Libraries/Components/TextInput/TextInput.windows.js +6 -2
  2. package/Libraries/Components/View/View.windows.js +3 -0
  3. package/Microsoft.ReactNative/ComponentView.idl +26 -0
  4. package/Microsoft.ReactNative/CompositionComponentView.idl +19 -7
  5. package/Microsoft.ReactNative/CompositionRootView.idl +1 -0
  6. package/Microsoft.ReactNative/CompositionUIService.idl +4 -0
  7. package/Microsoft.ReactNative/Fabric/AbiViewComponentDescriptor.cpp +2 -1
  8. package/Microsoft.ReactNative/Fabric/AbiViewProps.cpp +106 -19
  9. package/Microsoft.ReactNative/Fabric/AbiViewProps.h +45 -13
  10. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +83 -12
  11. package/Microsoft.ReactNative/Fabric/ComponentView.h +33 -2
  12. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.cpp +28 -64
  13. package/Microsoft.ReactNative/Fabric/Composition/ActivityIndicatorComponentView.h +7 -11
  14. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.cpp +30 -11
  15. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootView.h +4 -0
  16. package/Microsoft.ReactNative/Fabric/Composition/CompositionRootView_emptyimpl.cpp +4 -0
  17. package/Microsoft.ReactNative/Fabric/Composition/CompositionUIService.cpp +12 -0
  18. package/Microsoft.ReactNative/Fabric/Composition/CompositionUIService.h +4 -0
  19. package/Microsoft.ReactNative/Fabric/Composition/CompositionUIService_emptyimpl.cpp +6 -0
  20. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +60 -39
  21. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +19 -6
  22. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +1 -0
  23. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +152 -0
  24. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +85 -0
  25. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.cpp +49 -95
  26. package/Microsoft.ReactNative/Fabric/Composition/ImageComponentView.h +11 -15
  27. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +16 -31
  28. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +5 -8
  29. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +24 -81
  30. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.h +4 -13
  31. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +41 -40
  32. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +5 -1
  33. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +53 -68
  34. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +5 -7
  35. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +38 -84
  36. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h +6 -10
  37. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +59 -109
  38. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +9 -15
  39. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -0
  40. package/Microsoft.ReactNative/FocusManager.idl +22 -0
  41. package/Microsoft.ReactNative/ViewProps.idl +37 -3
  42. package/Microsoft.ReactNative.Cxx/JSValueComposition.h +4 -0
  43. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  44. package/Shared/Shared.vcxitems +6 -0
  45. package/package.json +1 -1
@@ -24,9 +24,13 @@ ActivityIndicatorComponentView::ActivityIndicatorComponentView(
24
24
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
25
25
  facebook::react::Tag tag,
26
26
  winrt::Microsoft::ReactNative::ReactContext const &reactContext)
27
- : Super(compContext, tag, reactContext, ComponentViewFeatures::Default, false) {
28
- m_props = std::make_shared<facebook::react::ActivityIndicatorViewProps const>();
29
- }
27
+ : Super(
28
+ ActivityIndicatorComponentView::defaultProps(),
29
+ compContext,
30
+ tag,
31
+ reactContext,
32
+ ComponentViewFeatures::Default,
33
+ false) {}
30
34
 
31
35
  void ActivityIndicatorComponentView::MountChildComponentView(
32
36
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
@@ -53,14 +57,11 @@ void ActivityIndicatorComponentView::updateProgressColor(const facebook::react::
53
57
  void ActivityIndicatorComponentView::updateProps(
54
58
  facebook::react::Props::Shared const &props,
55
59
  facebook::react::Props::Shared const &oldProps) noexcept {
56
- const auto oldViewProps = std::static_pointer_cast<const facebook::react::ActivityIndicatorViewProps>(m_props);
60
+ const auto oldViewProps =
61
+ std::static_pointer_cast<const facebook::react::ActivityIndicatorViewProps>(oldProps ? oldProps : viewProps());
57
62
  const auto newViewProps = std::static_pointer_cast<const facebook::react::ActivityIndicatorViewProps>(props);
58
63
 
59
- ensureVisual();
60
-
61
- if (newViewProps->testId != oldViewProps->testId) {
62
- m_visual.Comment(winrt::to_hstring(newViewProps->testId));
63
- }
64
+ Super::updateProps(props, oldProps);
64
65
 
65
66
  // update color if needed
66
67
  if (!oldProps || newViewProps->color != oldViewProps->color) {
@@ -70,10 +71,6 @@ void ActivityIndicatorComponentView::updateProps(
70
71
  if (newViewProps->animating != oldViewProps->animating) {
71
72
  m_ActivityIndicatorVisual.IsVisible(newViewProps->animating);
72
73
  }
73
-
74
- Super::updateProps(props, oldProps);
75
-
76
- m_props = std::static_pointer_cast<facebook::react::ViewProps const>(props);
77
74
  }
78
75
 
79
76
  void ActivityIndicatorComponentView::FinalizeUpdates(
@@ -81,8 +78,7 @@ void ActivityIndicatorComponentView::FinalizeUpdates(
81
78
  static constexpr float radiusSmall = 10.0f;
82
79
  static constexpr float radiusLarge = 18.0f;
83
80
 
84
- if (std::static_pointer_cast<const facebook::react::ActivityIndicatorViewProps>(m_props)->size ==
85
- facebook::react::ActivityIndicatorViewSize::Small) {
81
+ if (activityIndicatorViewProps().size == facebook::react::ActivityIndicatorViewSize::Small) {
86
82
  m_ActivityIndicatorVisual.Size(radiusSmall * m_layoutMetrics.pointScaleFactor);
87
83
  } else {
88
84
  m_ActivityIndicatorVisual.Size(radiusLarge * m_layoutMetrics.pointScaleFactor);
@@ -96,67 +92,35 @@ void ActivityIndicatorComponentView::updateState(
96
92
  void ActivityIndicatorComponentView::updateLayoutMetrics(
97
93
  facebook::react::LayoutMetrics const &layoutMetrics,
98
94
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept {
99
- // Set Position & Size Properties
100
- ensureVisual();
101
-
102
- if ((layoutMetrics.displayType != m_layoutMetrics.displayType)) {
103
- OuterVisual().IsVisible(layoutMetrics.displayType != facebook::react::DisplayType::None);
104
- }
105
-
106
95
  Super::updateLayoutMetrics(layoutMetrics, oldLayoutMetrics);
107
- m_visual.Size(
108
- {layoutMetrics.frame.size.width * layoutMetrics.pointScaleFactor,
109
- layoutMetrics.frame.size.height * layoutMetrics.pointScaleFactor});
110
96
  }
111
97
 
112
- void ActivityIndicatorComponentView::prepareForRecycle() noexcept {}
98
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual
99
+ ActivityIndicatorComponentView::createVisual() noexcept {
100
+ auto visual = m_compContext.CreateSpriteVisual();
101
+ m_ActivityIndicatorVisual = m_compContext.CreateActivityVisual();
113
102
 
114
- facebook::react::SharedViewProps ActivityIndicatorComponentView::viewProps() noexcept {
115
- return m_props;
116
- }
117
-
118
- void ActivityIndicatorComponentView::ensureVisual() noexcept {
119
- if (!m_visual) {
120
- m_visual = m_compContext.CreateSpriteVisual();
121
- m_ActivityIndicatorVisual = m_compContext.CreateActivityVisual();
122
-
123
- OuterVisual().InsertAt(m_ActivityIndicatorVisual, 0);
124
- OuterVisual().InsertAt(m_visual, 0);
125
- }
126
- }
127
-
128
- facebook::react::Tag ActivityIndicatorComponentView::hitTest(
129
- facebook::react::Point pt,
130
- facebook::react::Point &localPt,
131
- bool ignorePointerEvents) const noexcept {
132
- facebook::react::Point ptLocal{pt.x - m_layoutMetrics.frame.origin.x, pt.y - m_layoutMetrics.frame.origin.y};
133
-
134
- if ((ignorePointerEvents || m_props->pointerEvents == facebook::react::PointerEventsMode::Auto ||
135
- m_props->pointerEvents == facebook::react::PointerEventsMode::BoxOnly) &&
136
- ptLocal.x >= 0 && ptLocal.x <= m_layoutMetrics.frame.size.width && ptLocal.y >= 0 &&
137
- ptLocal.y <= m_layoutMetrics.frame.size.height) {
138
- localPt = ptLocal;
139
- return Tag();
140
- }
141
- return -1;
142
- }
143
-
144
- winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ActivityIndicatorComponentView::Visual()
145
- const noexcept {
146
- return m_visual;
103
+ OuterVisual().InsertAt(m_ActivityIndicatorVisual, 0);
104
+ return visual;
147
105
  }
148
106
 
149
107
  void ActivityIndicatorComponentView::onThemeChanged() noexcept {
150
- updateProgressColor(std::static_pointer_cast<const facebook::react::ActivityIndicatorViewProps>(m_props)->color);
108
+ updateProgressColor(activityIndicatorViewProps().color);
151
109
  Super::onThemeChanged();
152
110
  }
153
111
 
154
- bool ActivityIndicatorComponentView::focusable() const noexcept {
155
- return false;
156
- }
157
-
158
112
  std::string ActivityIndicatorComponentView::DefaultControlType() const noexcept {
159
113
  return "progressbar";
160
114
  }
161
115
 
116
+ facebook::react::SharedViewProps ActivityIndicatorComponentView::defaultProps() noexcept {
117
+ static auto const defaultProps = std::make_shared<facebook::react::ActivityIndicatorViewProps const>();
118
+ return defaultProps;
119
+ }
120
+
121
+ const facebook::react::ActivityIndicatorViewProps &ActivityIndicatorComponentView::activityIndicatorViewProps()
122
+ const noexcept {
123
+ return *std::static_pointer_cast<const facebook::react::ActivityIndicatorViewProps>(viewProps());
124
+ }
125
+
162
126
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -13,8 +13,9 @@
13
13
 
14
14
  namespace winrt::Microsoft::ReactNative::Composition::implementation {
15
15
 
16
- struct ActivityIndicatorComponentView : ActivityIndicatorComponentViewT<ActivityIndicatorComponentView, ComponentView> {
17
- using Super = ActivityIndicatorComponentViewT<ActivityIndicatorComponentView, ComponentView>;
16
+ struct ActivityIndicatorComponentView
17
+ : ActivityIndicatorComponentViewT<ActivityIndicatorComponentView, ViewComponentView> {
18
+ using Super = ActivityIndicatorComponentViewT<ActivityIndicatorComponentView, ViewComponentView>;
18
19
 
19
20
  [[nodiscard]] static winrt::Microsoft::ReactNative::ComponentView Create(
20
21
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
@@ -35,14 +36,8 @@ struct ActivityIndicatorComponentView : ActivityIndicatorComponentViewT<Activity
35
36
  facebook::react::LayoutMetrics const &layoutMetrics,
36
37
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
37
38
  void FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept override;
38
- void prepareForRecycle() noexcept override;
39
- facebook::react::SharedViewProps viewProps() noexcept override;
40
- bool focusable() const noexcept override;
41
39
  void onThemeChanged() noexcept override;
42
40
 
43
- facebook::react::Tag hitTest(facebook::react::Point pt, facebook::react::Point &localPt, bool ignorePointerEvents)
44
- const noexcept override;
45
- winrt::Microsoft::ReactNative::Composition::Experimental::IVisual Visual() const noexcept override;
46
41
  virtual std::string DefaultControlType() const noexcept;
47
42
 
48
43
  ActivityIndicatorComponentView(
@@ -50,14 +45,15 @@ struct ActivityIndicatorComponentView : ActivityIndicatorComponentViewT<Activity
50
45
  facebook::react::Tag tag,
51
46
  winrt::Microsoft::ReactNative::ReactContext const &reactContext);
52
47
 
48
+ static facebook::react::SharedViewProps defaultProps() noexcept;
49
+ const facebook::react::ActivityIndicatorViewProps &activityIndicatorViewProps() const noexcept;
50
+ winrt::Microsoft::ReactNative::Composition::Experimental::IVisual createVisual() noexcept override;
51
+
53
52
  private:
54
- void ensureVisual() noexcept;
55
53
  void updateVisualSize() noexcept;
56
54
  void updateProgressColor(const facebook::react::SharedColor &color) noexcept;
57
55
 
58
- winrt::Microsoft::ReactNative::Composition::Experimental::ISpriteVisual m_visual{nullptr};
59
56
  winrt::Microsoft::ReactNative::Composition::Experimental::IActivityVisual m_ActivityIndicatorVisual{nullptr};
60
- facebook::react::SharedViewProps m_props;
61
57
  };
62
58
 
63
59
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -132,6 +132,12 @@ CompositionRootView::CompositionRootView(const winrt::Microsoft::UI::Composition
132
132
  #endif
133
133
 
134
134
  CompositionRootView::~CompositionRootView() noexcept {
135
+ #ifdef USE_WINUI3
136
+ if (m_island && m_island.IsConnected()) {
137
+ m_island.AutomationProviderRequested(m_islandAutomationProviderRequestedToken);
138
+ }
139
+ #endif
140
+
135
141
  if (m_uiDispatcher) {
136
142
  assert(m_uiDispatcher.HasThreadAccess());
137
143
  UninitRootView();
@@ -193,7 +199,7 @@ void CompositionRootView::RemoveRenderedVisual(
193
199
 
194
200
  bool CompositionRootView::TrySetFocus() noexcept {
195
201
  #ifdef USE_WINUI3
196
- if (m_island) {
202
+ if (m_island && m_island.IsConnected()) {
197
203
  auto focusController = winrt::Microsoft::UI::Input::InputFocusController::GetForIsland(m_island);
198
204
  return focusController.TrySetFocus();
199
205
  }
@@ -247,6 +253,10 @@ void CompositionRootView::ScaleFactor(float value) noexcept {
247
253
  }
248
254
  }
249
255
 
256
+ int64_t CompositionRootView::RootTag() const noexcept {
257
+ return m_rootTag;
258
+ }
259
+
250
260
  winrt::Microsoft::ReactNative::Composition::ICustomResourceLoader CompositionRootView::Resources() noexcept {
251
261
  return m_resources;
252
262
  }
@@ -651,20 +661,29 @@ winrt::Microsoft::UI::Content::ContentIsland CompositionRootView::Island() noexc
651
661
  rootVisual));
652
662
  m_island = winrt::Microsoft::UI::Content::ContentIsland::Create(rootVisual);
653
663
 
654
- m_island.AutomationProviderRequested(
655
- [this](
664
+ // ContentIsland does not support weak_ref, so we cannot use auto_revoke for these events
665
+ m_islandAutomationProviderRequestedToken = m_island.AutomationProviderRequested(
666
+ [weakThis = get_weak()](
656
667
  winrt::Microsoft::UI::Content::ContentIsland const &,
657
668
  winrt::Microsoft::UI::Content::ContentIslandAutomationProviderRequestedEventArgs const &args) {
658
- auto provider = GetUiaProvider();
659
- auto pRootProvider =
660
- static_cast<winrt::Microsoft::ReactNative::implementation::CompositionRootAutomationProvider *>(
661
- provider.as<IRawElementProviderSimple>().get());
662
- if (pRootProvider != nullptr) {
663
- pRootProvider->SetIsland(m_island);
669
+ if (auto pThis = weakThis.get()) {
670
+ auto provider = pThis->GetUiaProvider();
671
+ auto pRootProvider =
672
+ static_cast<winrt::Microsoft::ReactNative::implementation::CompositionRootAutomationProvider *>(
673
+ provider.as<IRawElementProviderSimple>().get());
674
+ if (pRootProvider != nullptr) {
675
+ pRootProvider->SetIsland(pThis->m_island);
676
+ }
677
+ args.AutomationProvider(std::move(provider));
678
+ args.Handled(true);
664
679
  }
665
- args.AutomationProvider(std::move(provider));
666
- args.Handled(true);
667
680
  });
681
+
682
+ m_islandFrameworkClosedToken = m_island.FrameworkClosed([weakThis = get_weak()]() {
683
+ if (auto pThis = weakThis.get()) {
684
+ pThis->m_island = nullptr;
685
+ }
686
+ });
668
687
  }
669
688
  return m_island;
670
689
  }
@@ -88,6 +88,8 @@ struct CompositionRootView
88
88
 
89
89
  winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *GetComponentView() noexcept;
90
90
 
91
+ int64_t RootTag() const noexcept;
92
+
91
93
  IInspectable GetUiaProvider() noexcept;
92
94
 
93
95
  // When driving the rootview without an island
@@ -119,6 +121,8 @@ struct CompositionRootView
119
121
  #ifdef USE_WINUI3
120
122
  winrt::Microsoft::UI::Composition::Compositor m_compositor{nullptr};
121
123
  winrt::Microsoft::UI::Content::ContentIsland m_island{nullptr};
124
+ winrt::event_token m_islandFrameworkClosedToken;
125
+ winrt::event_token m_islandAutomationProviderRequestedToken;
122
126
  #endif
123
127
 
124
128
  HWND m_hwnd{0};
@@ -96,6 +96,10 @@ int64_t CompositionRootView::GetTag() const noexcept {
96
96
  return 0;
97
97
  }
98
98
 
99
+ int64_t CompositionRootView::RootTag() const noexcept {
100
+ return 0;
101
+ }
102
+
99
103
  void CompositionRootView::SetTag(int64_t) noexcept {}
100
104
 
101
105
  void CompositionRootView::SetWindow(uint64_t) noexcept {}
@@ -4,6 +4,7 @@
4
4
  #include "pch.h"
5
5
  #include "CompositionUIService.h"
6
6
  #include "Composition.CompositionUIService.g.cpp"
7
+ #include <Fabric/FabricUIManagerModule.h>
7
8
  #include <QuirkSettings.h>
8
9
 
9
10
  #include <ReactPropertyBag.h>
@@ -39,4 +40,15 @@ Experimental::ICompositionContext CompositionUIService::GetCompositionContext(
39
40
  return ReactPropertyBag(properties).Get(CompositionContextPropertyId());
40
41
  }
41
42
 
43
+ winrt::Microsoft::ReactNative::ComponentView CompositionUIService::ComponentFromReactTag(
44
+ const winrt::Microsoft::ReactNative::IReactContext &context,
45
+ int64_t reactTag) noexcept {
46
+ if (std::shared_ptr<::Microsoft::ReactNative::FabricUIManager> fabricuiManager =
47
+ ::Microsoft::ReactNative::FabricUIManager::FromProperties(ReactPropertyBag(context.Properties()))) {
48
+ return fabricuiManager->GetViewRegistry().findComponentViewWithTag(static_cast<facebook::react::Tag>(reactTag));
49
+ }
50
+
51
+ return nullptr;
52
+ }
53
+
42
54
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -16,6 +16,10 @@ struct CompositionUIService : CompositionUIServiceT<CompositionUIService> {
16
16
  static winrt::Microsoft::UI::Composition::Compositor GetCompositor(const IReactPropertyBag &properties) noexcept;
17
17
 
18
18
  static Experimental::ICompositionContext GetCompositionContext(const IReactPropertyBag &properties) noexcept;
19
+
20
+ static winrt::Microsoft::ReactNative::ComponentView ComponentFromReactTag(
21
+ const winrt::Microsoft::ReactNative::IReactContext &context,
22
+ int64_t reactTag) noexcept;
19
23
  };
20
24
 
21
25
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -18,4 +18,10 @@ winrt::Microsoft::UI::Composition::Compositor CompositionUIService::GetComposito
18
18
  return nullptr;
19
19
  }
20
20
 
21
+ winrt::Microsoft::ReactNative::ComponentView CompositionUIService::ComponentFromReactTag(
22
+ const winrt::Microsoft::ReactNative::IReactContext &,
23
+ int64_t) noexcept {
24
+ return nullptr;
25
+ }
26
+
21
27
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -121,6 +121,10 @@ winrt::Microsoft::ReactNative::Composition::Theme ComponentView::Theme() const n
121
121
  return theme()->get_strong().as<winrt::Microsoft::ReactNative::Composition::Theme>();
122
122
  }
123
123
 
124
+ winrt::Microsoft::ReactNative::Composition::RootComponentView ComponentView::Root() noexcept {
125
+ return *rootComponentView();
126
+ }
127
+
124
128
  winrt::Microsoft::UI::Composition::Compositor ComponentView::Compositor() const noexcept {
125
129
  return winrt::Microsoft::ReactNative::Composition::Experimental::MicrosoftCompositionContextHelper::InnerCompositor(
126
130
  m_compContext);
@@ -134,7 +138,8 @@ winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext Co
134
138
  void ComponentView::updateProps(
135
139
  facebook::react::Props::Shared const &props,
136
140
  facebook::react::Props::Shared const &oldProps) noexcept {
137
- const auto &oldViewProps = *viewProps();
141
+ const auto &oldViewProps =
142
+ oldProps ? (*std::static_pointer_cast<const facebook::react::ViewProps>(oldProps)) : (*viewProps());
138
143
  const auto &newViewProps = *std::static_pointer_cast<const facebook::react::ViewProps>(props);
139
144
 
140
145
  if ((m_flags & ComponentViewFeatures::Background) == ComponentViewFeatures::Background) {
@@ -178,32 +183,38 @@ void ComponentView::FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentView
178
183
  base_type::FinalizeUpdates(updateMask);
179
184
  }
180
185
 
181
- void ComponentView::onFocusLost() noexcept {
182
- m_eventEmitter->onBlur();
183
- showFocusVisual(false);
184
- if (m_uiaProvider) {
185
- winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
186
- m_uiaProvider, UIA_HasKeyboardFocusPropertyId, true, false);
186
+ void ComponentView::onLostFocus(
187
+ const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
188
+ if (args.OriginalSource() == Tag()) {
189
+ m_eventEmitter->onBlur();
190
+ showFocusVisual(false);
191
+ if (m_uiaProvider) {
192
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
193
+ m_uiaProvider, UIA_HasKeyboardFocusPropertyId, true, false);
194
+ }
187
195
  }
188
- base_type::onFocusLost();
196
+ base_type::onLostFocus(args);
189
197
  }
190
198
 
191
- void ComponentView::onFocusGained() noexcept {
192
- m_eventEmitter->onFocus();
193
- if (m_enableFocusVisual) {
194
- showFocusVisual(true);
195
- }
196
- if (m_uiaProvider) {
197
- auto spProviderSimple = m_uiaProvider.try_as<IRawElementProviderSimple>();
198
- if (spProviderSimple != nullptr) {
199
- winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
200
- m_uiaProvider, UIA_HasKeyboardFocusPropertyId, false, true);
201
- UiaRaiseAutomationEvent(spProviderSimple.get(), UIA_AutomationFocusChangedEventId);
199
+ void ComponentView::onGotFocus(
200
+ const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept {
201
+ if (args.OriginalSource() == Tag()) {
202
+ m_eventEmitter->onFocus();
203
+ if (m_enableFocusVisual) {
204
+ showFocusVisual(true);
205
+ }
206
+ if (m_uiaProvider) {
207
+ auto spProviderSimple = m_uiaProvider.try_as<IRawElementProviderSimple>();
208
+ if (spProviderSimple != nullptr) {
209
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
210
+ m_uiaProvider, UIA_HasKeyboardFocusPropertyId, false, true);
211
+ UiaRaiseAutomationEvent(spProviderSimple.get(), UIA_AutomationFocusChangedEventId);
212
+ }
202
213
  }
203
- }
204
214
 
205
- StartBringIntoView({});
206
- base_type::onFocusGained();
215
+ StartBringIntoView({});
216
+ }
217
+ base_type::onGotFocus(args);
207
218
  }
208
219
 
209
220
  void ComponentView::StartBringIntoView(
@@ -233,13 +244,13 @@ void ComponentView::HandleCommand(
233
244
  const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept {
234
245
  if (commandName == L"focus") {
235
246
  if (auto root = rootComponentView()) {
236
- root->SetFocusedComponent(*get_strong());
247
+ root->TrySetFocusedComponent(*get_strong());
237
248
  }
238
249
  return;
239
250
  }
240
251
  if (commandName == L"blur") {
241
252
  if (auto root = rootComponentView()) {
242
- root->SetFocusedComponent(nullptr); // Todo store this component as previously focused element
253
+ root->TrySetFocusedComponent(nullptr); // Todo store this component as previously focused element
243
254
  }
244
255
  return;
245
256
  }
@@ -1455,6 +1466,7 @@ std::string ComponentView::DefaultHelpText() const noexcept {
1455
1466
  ViewComponentView::ViewComponentView(
1456
1467
  const winrt::Microsoft::ReactNative::Composition::CreateCompositionComponentViewArgs &args)
1457
1468
  : ViewComponentView(
1469
+ ViewComponentView::defaultProps(),
1458
1470
  winrt::get_self<
1459
1471
  winrt::Microsoft::ReactNative::Composition::implementation::CreateCompositionComponentViewArgs>(args)
1460
1472
  ->CompositionContext(),
@@ -1463,16 +1475,20 @@ ViewComponentView::ViewComponentView(
1463
1475
  args.Features(),
1464
1476
  true) {}
1465
1477
 
1478
+ facebook::react::SharedViewProps ViewComponentView::defaultProps() noexcept {
1479
+ static auto const defaultViewProps = std::make_shared<facebook::react::ViewProps const>();
1480
+ return defaultViewProps;
1481
+ }
1482
+
1466
1483
  ViewComponentView::ViewComponentView(
1484
+ const facebook::react::SharedViewProps &defaultProps,
1467
1485
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
1468
1486
  facebook::react::Tag tag,
1469
1487
  winrt::Microsoft::ReactNative::ReactContext const &reactContext,
1470
1488
  ComponentViewFeatures flags,
1471
1489
  bool customComponent)
1472
- : base_type(compContext, tag, reactContext, flags, customComponent) {
1473
- static auto const defaultProps = std::make_shared<facebook::react::ViewProps const>();
1474
- m_props = defaultProps;
1475
- }
1490
+ : base_type(compContext, tag, reactContext, flags, customComponent),
1491
+ m_props(defaultProps ? defaultProps : ViewComponentView::defaultProps()) {}
1476
1492
 
1477
1493
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual ViewComponentView::createVisual() noexcept {
1478
1494
  return m_compContext.CreateSpriteVisual();
@@ -1507,7 +1523,8 @@ winrt::Microsoft::ReactNative::ComponentView ViewComponentView::Create(
1507
1523
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
1508
1524
  facebook::react::Tag tag,
1509
1525
  winrt::Microsoft::ReactNative::ReactContext const &reactContext) noexcept {
1510
- return winrt::make<ViewComponentView>(compContext, tag, reactContext, ComponentViewFeatures::Default, false);
1526
+ return winrt::make<ViewComponentView>(
1527
+ ViewComponentView::defaultProps(), compContext, tag, reactContext, ComponentViewFeatures::Default, false);
1511
1528
  }
1512
1529
 
1513
1530
  void ViewComponentView::MountChildComponentView(
@@ -1521,7 +1538,7 @@ void ViewComponentView::MountChildComponentView(
1521
1538
  // TODO if we get mixed children of composition and non-composition ComponentViews the indexes will get mixed up
1522
1539
  // We could offset the index based on non-composition children in m_children
1523
1540
  if (auto compositionChild = childComponentView.try_as<ComponentView>()) {
1524
- m_visual.InsertAt(compositionChild->OuterVisual(), index);
1541
+ Visual().InsertAt(compositionChild->OuterVisual(), index);
1525
1542
  }
1526
1543
  }
1527
1544
 
@@ -1532,27 +1549,27 @@ void ViewComponentView::UnmountChildComponentView(
1532
1549
 
1533
1550
  indexOffsetForBorder(index);
1534
1551
  if (auto compositionChild = childComponentView.try_as<ComponentView>()) {
1535
- m_visual.Remove(compositionChild->OuterVisual());
1552
+ Visual().Remove(compositionChild->OuterVisual());
1536
1553
  }
1537
1554
  }
1538
1555
 
1539
1556
  void ViewComponentView::updateProps(
1540
1557
  facebook::react::Props::Shared const &props,
1541
1558
  facebook::react::Props::Shared const &oldProps) noexcept {
1542
- const auto &oldViewProps = *std::static_pointer_cast<const facebook::react::ViewProps>(m_props);
1559
+ const auto &oldViewProps = *std::static_pointer_cast<const facebook::react::ViewProps>(oldProps ? oldProps : m_props);
1543
1560
  const auto &newViewProps = *std::static_pointer_cast<const facebook::react::ViewProps>(props);
1544
1561
 
1545
1562
  ensureVisual();
1546
1563
  if (oldViewProps.opacity != newViewProps.opacity) {
1547
- m_visual.Opacity(newViewProps.opacity);
1564
+ Visual().Opacity(newViewProps.opacity);
1548
1565
  }
1549
1566
  if (oldViewProps.testId != newViewProps.testId) {
1550
- m_visual.Comment(winrt::to_hstring(newViewProps.testId));
1567
+ Visual().Comment(winrt::to_hstring(newViewProps.testId));
1551
1568
  }
1552
1569
 
1553
1570
  // update BaseComponentView props
1554
1571
  updateAccessibilityProps(oldViewProps, newViewProps);
1555
- updateTransformProps(oldViewProps, newViewProps, m_visual);
1572
+ updateTransformProps(oldViewProps, newViewProps, Visual());
1556
1573
  base_type::updateProps(props, oldProps);
1557
1574
 
1558
1575
  m_props = std::static_pointer_cast<facebook::react::ViewProps const>(props);
@@ -1571,7 +1588,7 @@ facebook::react::Tag ViewComponentView::hitTest(
1571
1588
  bool ignorePointerEvents) const noexcept {
1572
1589
  facebook::react::Point ptLocal{pt.x - m_layoutMetrics.frame.origin.x, pt.y - m_layoutMetrics.frame.origin.y};
1573
1590
 
1574
- facebook::react::Tag targetTag;
1591
+ facebook::react::Tag targetTag = -1;
1575
1592
 
1576
1593
  if ((ignorePointerEvents || m_props->pointerEvents == facebook::react::PointerEventsMode::Auto ||
1577
1594
  m_props->pointerEvents == facebook::react::PointerEventsMode::BoxNone) &&
@@ -1637,7 +1654,7 @@ void ViewComponentView::OnKeyDown(
1637
1654
  (source.GetKeyState(winrt::Windows::System::VirtualKey::RightWindows) !=
1638
1655
  winrt::Windows::UI::Core::CoreVirtualKeyStates::None);
1639
1656
 
1640
- if (args.OriginalSource() == Tag()) {
1657
+ if (args.OriginalSource() == Tag() && !args.Handled()) {
1641
1658
  facebook::react::KeyEvent event;
1642
1659
  event.shiftKey = fShift;
1643
1660
  event.ctrlKey = fCtrl;
@@ -1712,16 +1729,20 @@ void ViewComponentView::updateLayoutMetrics(
1712
1729
  }
1713
1730
 
1714
1731
  void ViewComponentView::UpdateLayoutMetrics(const LayoutMetrics &metrics, const LayoutMetrics &oldMetrics) noexcept {
1715
- m_visual.Size({metrics.Frame.Width * metrics.PointScaleFactor, metrics.Frame.Height * metrics.PointScaleFactor});
1732
+ Visual().Size({metrics.Frame.Width * metrics.PointScaleFactor, metrics.Frame.Height * metrics.PointScaleFactor});
1716
1733
  }
1717
1734
 
1718
1735
  void ViewComponentView::prepareForRecycle() noexcept {}
1719
1736
 
1720
- facebook::react::SharedViewProps ViewComponentView::viewProps() noexcept {
1737
+ const facebook::react::SharedViewProps &ViewComponentView::viewProps() const noexcept {
1721
1738
  return m_props;
1722
1739
  }
1723
1740
 
1724
1741
  winrt::Microsoft::ReactNative::ViewProps ViewComponentView::ViewProps() noexcept {
1742
+ return ViewPropsInner();
1743
+ }
1744
+
1745
+ winrt::Microsoft::ReactNative::ViewProps ViewComponentView::ViewPropsInner() noexcept {
1725
1746
  // If we have AbiViewProps, then we dont need to new up a props wrapper
1726
1747
  if (m_customComponent) {
1727
1748
  const auto &abiViewProps = *std::static_pointer_cast<const ::Microsoft::ReactNative::AbiViewProps>(m_props);
@@ -23,7 +23,8 @@ namespace winrt::Microsoft::ReactNative::Composition::implementation {
23
23
  struct CreateCompositionComponentViewArgs
24
24
  : public CreateCompositionComponentViewArgsT<
25
25
  CreateCompositionComponentViewArgs,
26
- winrt::Microsoft::ReactNative::implementation::CreateComponentViewArgs> {
26
+ winrt::Microsoft::ReactNative::implementation::CreateComponentViewArgs,
27
+ winrt::Microsoft::ReactNative::Composition::Experimental::IInternalCreateComponentViewArgs> {
27
28
  CreateCompositionComponentViewArgs(
28
29
  const winrt::Microsoft::ReactNative::IReactContext &reactContext,
29
30
  facebook::react::Tag tag,
@@ -63,14 +64,19 @@ struct ComponentView
63
64
  void HandleCommand(winrt::hstring commandName, const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept
64
65
  override;
65
66
  facebook::react::Props::Shared props() noexcept override;
66
- virtual facebook::react::SharedViewProps viewProps() noexcept {
67
- return nullptr;
67
+ virtual const facebook::react::SharedViewProps &viewProps() const noexcept {
68
+ static facebook::react::SharedViewProps emptyProps;
69
+ assert(false);
70
+ return emptyProps;
68
71
  };
72
+
73
+ winrt::Microsoft::ReactNative::Composition::RootComponentView Root() noexcept;
74
+
69
75
  void Theme(const winrt::Microsoft::ReactNative::Composition::Theme &theme) noexcept;
70
76
  winrt::Microsoft::ReactNative::Composition::Theme Theme() const noexcept;
71
77
  void onThemeChanged() noexcept override;
72
- void onFocusLost() noexcept override;
73
- void onFocusGained() noexcept override;
78
+ void onLostFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
79
+ void onGotFocus(const winrt::Microsoft::ReactNative::Composition::Input::RoutedEventArgs &args) noexcept override;
74
80
  bool CapturePointer(const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer) noexcept;
75
81
  void ReleasePointerCapture(const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer) noexcept;
76
82
 
@@ -186,6 +192,7 @@ struct ViewComponentView : public ViewComponentViewT<ViewComponentView, Componen
186
192
  facebook::react::LayoutMetrics const &layoutMetrics,
187
193
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept override;
188
194
  void prepareForRecycle() noexcept override;
195
+ bool TryFocus() noexcept;
189
196
  bool focusable() const noexcept override;
190
197
  void OnKeyDown(
191
198
  const winrt::Microsoft::ReactNative::Composition::Input::KeyboardSource &source,
@@ -195,7 +202,7 @@ struct ViewComponentView : public ViewComponentViewT<ViewComponentView, Componen
195
202
  const winrt::Microsoft::ReactNative::Composition::Input::KeyRoutedEventArgs &args) noexcept override;
196
203
  std::string DefaultControlType() const noexcept override;
197
204
 
198
- facebook::react::SharedViewProps viewProps() noexcept override;
205
+ const facebook::react::SharedViewProps &viewProps() const noexcept override;
199
206
  winrt::Microsoft::ReactNative::ViewProps ViewProps() noexcept;
200
207
 
201
208
  facebook::react::Tag hitTest(
@@ -207,7 +214,10 @@ struct ViewComponentView : public ViewComponentViewT<ViewComponentView, Componen
207
214
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual Visual() const noexcept override;
208
215
  void ensureVisual() noexcept;
209
216
 
217
+ static facebook::react::SharedViewProps defaultProps() noexcept;
218
+
210
219
  ViewComponentView(
220
+ const facebook::react::SharedViewProps &defaultProps,
211
221
  const winrt::Microsoft::ReactNative::Composition::Experimental::ICompositionContext &compContext,
212
222
  facebook::react::Tag tag,
213
223
  winrt::Microsoft::ReactNative::ReactContext const &reactContext,
@@ -220,6 +230,9 @@ struct ViewComponentView : public ViewComponentViewT<ViewComponentView, Componen
220
230
  virtual winrt::Microsoft::UI::Composition::Visual CreateVisual() noexcept;
221
231
  virtual void UpdateLayoutMetrics(const LayoutMetrics &metrics, const LayoutMetrics &oldMetrics) noexcept;
222
232
 
233
+ protected:
234
+ virtual winrt::Microsoft::ReactNative::ViewProps ViewPropsInner() noexcept;
235
+
223
236
  private:
224
237
  facebook::react::SharedViewProps m_props;
225
238
  winrt::Microsoft::ReactNative::Composition::Experimental::IVisual m_visual{nullptr};
@@ -15,6 +15,7 @@ DebuggingOverlayComponentView::DebuggingOverlayComponentView(
15
15
  facebook::react::Tag tag,
16
16
  winrt::Microsoft::ReactNative::ReactContext const &reactContext)
17
17
  : base_type(
18
+ {}, // default ViewProps
18
19
  compContext,
19
20
  tag,
20
21
  reactContext,