react-native-windows 0.74.21 → 0.74.23

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 (76) hide show
  1. package/Microsoft.ReactNative/ComponentView.idl +11 -0
  2. package/Microsoft.ReactNative/Composition.Input.idl +1 -0
  3. package/Microsoft.ReactNative/CompositionSwitcher.idl +3 -0
  4. package/Microsoft.ReactNative/Fabric/ComponentView.cpp +18 -8
  5. package/Microsoft.ReactNative/Fabric/ComponentView.h +7 -5
  6. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.cpp +4 -0
  7. package/Microsoft.ReactNative/Fabric/Composition/Composition.Input.h +1 -0
  8. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +44 -13
  9. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +75 -0
  10. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +8 -2
  11. package/Microsoft.ReactNative/Fabric/Composition/CompositionHwndHost.cpp +1 -0
  12. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +34 -7
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.h +3 -2
  14. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.cpp +8 -6
  15. package/Microsoft.ReactNative/Fabric/Composition/DebuggingOverlayComponentView.h +1 -2
  16. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.cpp +20 -6
  17. package/Microsoft.ReactNative/Fabric/Composition/FocusManager.h +13 -6
  18. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.cpp +2 -3
  19. package/Microsoft.ReactNative/Fabric/Composition/Modal/WindowsModalHostViewComponentView.h +1 -2
  20. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.cpp +80 -55
  21. package/Microsoft.ReactNative/Fabric/Composition/ReactNativeIsland.h +15 -4
  22. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.cpp +37 -8
  23. package/Microsoft.ReactNative/Fabric/Composition/RootComponentView.h +7 -2
  24. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.cpp +14 -7
  25. package/Microsoft.ReactNative/Fabric/Composition/ScrollViewComponentView.h +1 -2
  26. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +6 -6
  27. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.h +1 -2
  28. package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.cpp +1 -2
  29. package/Microsoft.ReactNative/Fabric/Composition/TextDrawing.h +1 -1
  30. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +104 -152
  31. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +7 -3
  32. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.cpp +14 -11
  33. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputShadowNode.h +4 -4
  34. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.cpp +0 -13
  35. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputState.h +0 -3
  36. package/Microsoft.ReactNative/Fabric/Composition/Theme.cpp +12 -4
  37. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.cpp +338 -0
  38. package/Microsoft.ReactNative/Fabric/Composition/TooltipService.h +66 -0
  39. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +37 -4
  40. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +3 -0
  41. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.cpp +1 -2
  42. package/Microsoft.ReactNative/Fabric/Composition/UnimplementedNativeViewComponentView.h +1 -2
  43. package/Microsoft.ReactNative/Fabric/FabricUIManagerModule.cpp +31 -3
  44. package/Microsoft.ReactNative/Fabric/ReactTaggedView.h +4 -0
  45. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +5 -0
  46. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h +1 -1
  47. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewTraitsInitializer.h +1 -1
  48. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +9 -2
  49. package/Microsoft.ReactNative/IReactViewComponentBuilder.idl +8 -1
  50. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj +1 -1
  51. package/Microsoft.ReactNative/Modules/LogBoxModule.cpp +9 -0
  52. package/Microsoft.ReactNative/Modules/LogBoxModule.h +2 -0
  53. package/Microsoft.ReactNative/Modules/SampleTurboModule.cpp +104 -0
  54. package/Microsoft.ReactNative/Modules/SampleTurboModule.h +78 -0
  55. package/Microsoft.ReactNative/ReactCoreInjection.h +0 -1
  56. package/Microsoft.ReactNative/ReactHost/MsoReactContext.cpp +0 -7
  57. package/Microsoft.ReactNative/ReactHost/MsoReactContext.h +0 -5
  58. package/Microsoft.ReactNative/ReactHost/ReactInstanceWin.cpp +17 -1
  59. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.cpp +59 -0
  60. package/Microsoft.ReactNative/ReactInstanceSettingsBuilder.h +23 -0
  61. package/Microsoft.ReactNative/ReactNativeAppBuilder.cpp +179 -0
  62. package/Microsoft.ReactNative/ReactNativeAppBuilder.h +35 -0
  63. package/Microsoft.ReactNative/ReactNativeAppBuilder.idl +69 -0
  64. package/Microsoft.ReactNative/ReactNativeIsland.idl +2 -0
  65. package/Microsoft.ReactNative/ReactNativeWin32App.cpp +82 -0
  66. package/Microsoft.ReactNative/ReactNativeWin32App.h +38 -0
  67. package/Microsoft.ReactNative/Timer.idl +1 -1
  68. package/Microsoft.ReactNative/packages.lock.json +0 -10
  69. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  70. package/Shared/Shared.vcxitems +36 -0
  71. package/Shared/Shared.vcxitems.filters +2 -0
  72. package/Shared/TurboModuleManager.cpp +0 -3
  73. package/package.json +3 -3
  74. package/templates/cpp-app/template.config.js +1 -1
  75. package/templates/cpp-app/windows/MyApp/MyApp.cpp +1 -0
  76. package/templates/cpp-lib/template.config.js +1 -1
@@ -49,6 +49,15 @@ namespace Microsoft.ReactNative
49
49
  All = 0x0000000F,
50
50
  };
51
51
 
52
+ enum FocusNavigationDirection
53
+ {
54
+ None,
55
+ Next,
56
+ Previous,
57
+ First,
58
+ Last,
59
+ };
60
+
52
61
  [webhosthidden]
53
62
  [experimental]
54
63
  interface IComponentState
@@ -63,6 +72,7 @@ namespace Microsoft.ReactNative
63
72
  [experimental]
64
73
  [webhosthidden]
65
74
  runtimeclass LosingFocusEventArgs : Microsoft.ReactNative.Composition.Input.RoutedEventArgs {
75
+ FocusNavigationDirection Direction { get; };
66
76
  Microsoft.ReactNative.ComponentView NewFocusedComponent { get; };
67
77
  Microsoft.ReactNative.ComponentView OldFocusedComponent { get; };
68
78
 
@@ -73,6 +83,7 @@ namespace Microsoft.ReactNative
73
83
  [experimental]
74
84
  [webhosthidden]
75
85
  runtimeclass GettingFocusEventArgs : Microsoft.ReactNative.Composition.Input.RoutedEventArgs {
86
+ FocusNavigationDirection Direction { get; };
76
87
  Microsoft.ReactNative.ComponentView NewFocusedComponent { get; };
77
88
  Microsoft.ReactNative.ComponentView OldFocusedComponent { get; };
78
89
 
@@ -106,6 +106,7 @@ namespace Microsoft.ReactNative.Composition.Input
106
106
  UInt64 Timestamp { get; };
107
107
  PointerPoint GetOffsetPoint(
108
108
  Windows.Foundation.Point offset);
109
+ Microsoft.UI.Input.PointerPoint Inner { get; };
109
110
  };
110
111
 
111
112
  runtimeclass PointerRoutedEventArgs : RoutedEventArgs
@@ -3,6 +3,7 @@
3
3
 
4
4
  #include "NamespaceRedirect.h"
5
5
  #include "DocString.h"
6
+ import "Composition.Input.idl";
6
7
 
7
8
  namespace Microsoft.ReactNative.Composition.Experimental
8
9
  {
@@ -112,6 +113,8 @@ namespace Microsoft.ReactNative.Composition.Experimental
112
113
  Windows.Foundation.Numerics.Vector3 ScrollPosition { get; };
113
114
  void ScrollBy(Windows.Foundation.Numerics.Vector3 offset, Boolean animate);
114
115
  void TryUpdatePosition(Windows.Foundation.Numerics.Vector3 position, Boolean animate);
116
+ void OnPointerPressed(Microsoft.ReactNative.Composition.Input.PointerRoutedEventArgs args);
117
+ Boolean Horizontal;
115
118
  }
116
119
 
117
120
  [webhosthidden]
@@ -14,6 +14,7 @@
14
14
  #include <Fabric/Composition/RootComponentView.h>
15
15
  #include "AbiEventEmitter.h"
16
16
  #include "AbiShadowNode.h"
17
+ #include "ReactCoreInjection.h"
17
18
 
18
19
  namespace winrt::Microsoft::ReactNative::Composition::implementation {
19
20
  struct RootComponentView;
@@ -256,16 +257,25 @@ void ComponentView::CustomCommandHandler(const HandleCommandDelegate &handler) n
256
257
  m_customCommandHandler = handler;
257
258
  }
258
259
 
259
- void ComponentView::HandleCommand(
260
- winrt::hstring commandName,
261
- const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept {
260
+ void ComponentView::HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept {
262
261
  if (m_customCommandHandler) {
263
- m_customCommandHandler(*this, commandName, args);
262
+ m_customCommandHandler(*this, args);
264
263
  }
265
264
  }
266
265
 
267
- winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *
268
- ComponentView::rootComponentView() noexcept {
266
+ HWND ComponentView::GetHwndForParenting() noexcept {
267
+ if (m_parent) {
268
+ return winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(m_parent)
269
+ ->GetHwndForParenting();
270
+ }
271
+
272
+ // Fallback if we do not know any more specific HWND
273
+ return reinterpret_cast<HWND>(winrt::Microsoft::ReactNative::implementation::ReactCoreInjection::GetTopLevelWindowId(
274
+ m_reactContext.Properties().Handle()));
275
+ }
276
+
277
+ winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *ComponentView::rootComponentView()
278
+ const noexcept {
269
279
  if (m_rootView)
270
280
  return m_rootView;
271
281
 
@@ -285,7 +295,7 @@ void ComponentView::parent(const winrt::Microsoft::ReactNative::ComponentView &p
285
295
  m_parent = parent;
286
296
  if (!parent) {
287
297
  if (oldRootView && oldRootView->GetFocusedComponent() == *this) {
288
- oldRootView->TrySetFocusedComponent(oldParent);
298
+ oldRootView->TrySetFocusedComponent(oldParent, winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
289
299
  }
290
300
  }
291
301
  if (parent) {
@@ -424,7 +434,7 @@ void ComponentView::GotFocus(winrt::event_token const &token) noexcept {
424
434
 
425
435
  bool ComponentView::TryFocus() noexcept {
426
436
  if (auto root = rootComponentView()) {
427
- return root->TrySetFocusedComponent(*get_strong());
437
+ return root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
428
438
  }
429
439
 
430
440
  return false;
@@ -93,7 +93,8 @@ struct ComponentView : public ComponentViewT<ComponentView> {
93
93
  facebook::react::LayoutMetrics const &oldLayoutMetrics) noexcept;
94
94
  virtual void prepareForRecycle() noexcept;
95
95
  virtual facebook::react::Props::Shared props() noexcept;
96
- virtual winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *rootComponentView() noexcept;
96
+ virtual winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *rootComponentView()
97
+ const noexcept;
97
98
  virtual void parent(const winrt::Microsoft::ReactNative::ComponentView &parent) noexcept;
98
99
  virtual winrt::Microsoft::ReactNative::ComponentView Parent() const noexcept;
99
100
  virtual winrt::IVectorView<winrt::Microsoft::ReactNative::ComponentView> Children() const noexcept;
@@ -208,6 +209,9 @@ struct ComponentView : public ComponentViewT<ComponentView> {
208
209
  // Notify up the tree to bring the rect into view by scrolling as needed
209
210
  virtual void StartBringIntoView(BringIntoViewOptions &&args) noexcept;
210
211
 
212
+ // Eventually PopupContentLink and similar APIs will remove the need for this.
213
+ virtual HWND GetHwndForParenting() noexcept;
214
+
211
215
  virtual const winrt::Microsoft::ReactNative::IComponentProps userProps(
212
216
  facebook::react::Props::Shared const &props) noexcept;
213
217
 
@@ -228,9 +232,7 @@ struct ComponentView : public ComponentViewT<ComponentView> {
228
232
  virtual void UnmountChildComponentView(
229
233
  const winrt::Microsoft::ReactNative::ComponentView &childComponentView,
230
234
  uint32_t index) noexcept;
231
- virtual void HandleCommand(
232
- winrt::hstring commandName,
233
- const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept;
235
+ virtual void HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept;
234
236
  virtual void FinalizeUpdates(winrt::Microsoft::ReactNative::ComponentViewUpdateMask updateMask) noexcept;
235
237
  virtual void OnPointerEntered(
236
238
  const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept;
@@ -255,7 +257,7 @@ struct ComponentView : public ComponentViewT<ComponentView> {
255
257
  bool m_mounted : 1 {false};
256
258
  const facebook::react::Tag m_tag;
257
259
  winrt::IInspectable m_userData;
258
- winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *m_rootView{nullptr};
260
+ mutable winrt::Microsoft::ReactNative::Composition::implementation::RootComponentView *m_rootView{nullptr};
259
261
  mutable winrt::Microsoft::ReactNative::Composition::implementation::Theme *m_theme{nullptr};
260
262
  const winrt::Microsoft::ReactNative::ReactContext m_reactContext;
261
263
  winrt::Microsoft::ReactNative::ComponentView m_parent{nullptr};
@@ -637,6 +637,10 @@ bool PointerPoint::IsPointerMessage(uint32_t message) const noexcept {
637
637
  return (message >= WM_POINTERFIRST && message <= WM_POINTERLAST);
638
638
  }
639
639
 
640
+ winrt::Microsoft::UI::Input::PointerPoint PointerPoint::Inner() const noexcept {
641
+ return m_sysPointerPoint;
642
+ }
643
+
640
644
  PointerRoutedEventArgs::PointerRoutedEventArgs(
641
645
  const winrt::Microsoft::ReactNative::ReactContext &context,
642
646
  facebook::react::Tag tag,
@@ -198,6 +198,7 @@ struct PointerPoint : PointerPointT<PointerPoint> {
198
198
  uint64_t Timestamp() const noexcept;
199
199
  winrt::Microsoft::ReactNative::Composition::Input::PointerPoint GetOffsetPoint(
200
200
  const winrt::Windows::Foundation::Point &offset) const noexcept;
201
+ winrt::Microsoft::UI::Input::PointerPoint Inner() const noexcept;
201
202
 
202
203
  private:
203
204
  bool IsPointerMessage(uint32_t message) const noexcept;
@@ -12,6 +12,7 @@
12
12
 
13
13
  #include <Windows.Graphics.Interop.h>
14
14
  #include <windows.ui.composition.interop.h>
15
+ #include <winrt/Microsoft.ReactNative.Composition.Input.h>
15
16
  #include <winrt/Windows.Graphics.DirectX.Direct3D11.h>
16
17
  #include <winrt/Windows.UI.Composition.h>
17
18
  #include <winrt/Windows.UI.Composition.interactions.h>
@@ -744,14 +745,9 @@ struct CompScrollerVisual : winrt::implements<
744
745
  m_interactionTracker.MaxScale(1.0);
745
746
 
746
747
  m_visualInteractionSource = TTypeRedirects::VisualInteractionSource::Create(m_visual);
747
-
748
- m_visualInteractionSource.PositionXSourceMode(TTypeRedirects::InteractionSourceMode::EnabledWithInertia);
749
- m_visualInteractionSource.PositionYSourceMode(TTypeRedirects::InteractionSourceMode::EnabledWithInertia);
750
748
  m_visualInteractionSource.ScaleSourceMode(TTypeRedirects::InteractionSourceMode::Disabled);
751
-
752
- m_visualInteractionSource.ManipulationRedirectionMode(
753
- TTypeRedirects::VisualInteractionSourceRedirectionMode::CapableTouchpadAndPointerWheel);
754
749
  m_interactionTracker.InteractionSources().Add(m_visualInteractionSource);
750
+ UpdateInteractionModes();
755
751
 
756
752
  auto positionExpression = compositor.CreateExpressionAnimation(L"-tracker.Position");
757
753
  positionExpression.SetReferenceParameter(L"tracker", m_interactionTracker);
@@ -762,6 +758,44 @@ struct CompScrollerVisual : winrt::implements<
762
758
  return m_visual;
763
759
  }
764
760
 
761
+ void OnPointerPressed(
762
+ const winrt::Microsoft::ReactNative::Composition::Input::PointerRoutedEventArgs &args) noexcept {
763
+ if constexpr (std::is_same_v<TTypeRedirects, MicrosoftTypeRedirects>) {
764
+ auto pointerDeviceType = args.Pointer().PointerDeviceType();
765
+ if (pointerDeviceType == winrt::Microsoft::ReactNative::Composition::Input::PointerDeviceType::Touch) {
766
+ m_visualInteractionSource.TryRedirectForManipulation(args.GetCurrentPoint(args.OriginalSource()).Inner());
767
+ }
768
+ }
769
+ }
770
+
771
+ bool Horizontal() const noexcept {
772
+ return m_horizontal;
773
+ }
774
+
775
+ void Horizontal(bool value) noexcept {
776
+ m_horizontal = value;
777
+
778
+ UpdateInteractionModes();
779
+ }
780
+
781
+ void UpdateInteractionModes() noexcept {
782
+ if (m_isScrollEnabled) {
783
+ m_visualInteractionSource.PositionXSourceMode(
784
+ m_horizontal ? TTypeRedirects::InteractionSourceMode::EnabledWithInertia
785
+ : TTypeRedirects::InteractionSourceMode::Disabled);
786
+ m_visualInteractionSource.PositionYSourceMode(
787
+ m_horizontal ? TTypeRedirects::InteractionSourceMode::Disabled
788
+ : TTypeRedirects::InteractionSourceMode::EnabledWithInertia);
789
+ m_visualInteractionSource.ManipulationRedirectionMode(
790
+ TTypeRedirects::VisualInteractionSourceRedirectionMode::CapableTouchpadAndPointerWheel);
791
+ } else {
792
+ m_visualInteractionSource.PositionXSourceMode(TTypeRedirects::InteractionSourceMode::Disabled);
793
+ m_visualInteractionSource.PositionYSourceMode(TTypeRedirects::InteractionSourceMode::Disabled);
794
+ m_visualInteractionSource.ManipulationRedirectionMode(
795
+ TTypeRedirects::VisualInteractionSourceRedirectionMode::Off);
796
+ }
797
+ }
798
+
765
799
  void InsertAt(
766
800
  const winrt::Microsoft::ReactNative::Composition::Experimental::IVisual &visual,
767
801
  uint32_t index) noexcept {
@@ -796,13 +830,8 @@ struct CompScrollerVisual : winrt::implements<
796
830
  }
797
831
 
798
832
  void ScrollEnabled(bool isScrollEnabled) noexcept {
799
- if (isScrollEnabled) {
800
- m_visualInteractionSource.ManipulationRedirectionMode(
801
- TTypeRedirects::VisualInteractionSourceRedirectionMode::CapableTouchpadAndPointerWheel);
802
- } else {
803
- m_visualInteractionSource.ManipulationRedirectionMode(
804
- TTypeRedirects::VisualInteractionSourceRedirectionMode::Off);
805
- }
833
+ m_isScrollEnabled = isScrollEnabled;
834
+ UpdateInteractionModes();
806
835
  }
807
836
 
808
837
  void Opacity(float opacity) noexcept {
@@ -970,6 +999,8 @@ struct CompScrollerVisual : winrt::implements<
970
999
  0});
971
1000
  }
972
1001
 
1002
+ bool m_isScrollEnabled{true};
1003
+ bool m_horizontal{false};
973
1004
  bool m_inertia{false};
974
1005
  bool m_custom{false};
975
1006
  winrt::Windows::Foundation::Numerics::float3 m_targetPosition;
@@ -125,6 +125,22 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::get_ProviderOptions(Prov
125
125
  return S_OK;
126
126
  }
127
127
 
128
+ bool accessibilityValueHasValue(const facebook::react::AccessibilityValue &value) {
129
+ return (value.min.has_value() && value.max.has_value()) || value.now.has_value() || value.text.has_value();
130
+ }
131
+
132
+ bool expandableControl(const facebook::react::SharedViewProps props) {
133
+ if (props->accessibilityState.has_value() && props->accessibilityState->expanded.has_value())
134
+ return true;
135
+ auto accessibilityActions = props->accessibilityActions;
136
+ for (size_t i = 0; i < accessibilityActions.size(); i++) {
137
+ if (accessibilityActions[i].name == "expand" || accessibilityActions[i].name == "collapse") {
138
+ return true;
139
+ }
140
+ }
141
+ return false;
142
+ }
143
+
128
144
  HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTERNID patternId, IUnknown **pRetVal) {
129
145
  if (pRetVal == nullptr)
130
146
  return E_POINTER;
@@ -165,6 +181,15 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
165
181
  AddRef();
166
182
  }
167
183
 
184
+ if (patternId == UIA_ExpandCollapsePatternId &&
185
+ (accessibilityRole == "combobox" || accessibilityRole == "splitbutton" || accessibilityRole == "treeitem" ||
186
+ (expandableControl(props) &&
187
+ (accessibilityRole == "toolbar" || accessibilityRole == "menuitem" || accessibilityRole == "menubar" ||
188
+ accessibilityRole == "listitem" || accessibilityRole == "group" || accessibilityRole == "button")))) {
189
+ *pRetVal = static_cast<IExpandCollapseProvider *>(this);
190
+ AddRef();
191
+ }
192
+
168
193
  return S_OK;
169
194
  }
170
195
 
@@ -333,6 +358,13 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
333
358
  pRetVal->lVal = GetLiveSetting(props->accessibilityLiveRegion);
334
359
  break;
335
360
  }
361
+ case UIA_ItemStatusPropertyId: {
362
+ pRetVal->vt = VT_BSTR;
363
+ pRetVal->bstrVal = (props->accessibilityState.has_value() && props->accessibilityState->busy)
364
+ ? SysAllocString(L"Busy")
365
+ : SysAllocString(L"");
366
+ break;
367
+ }
336
368
  }
337
369
 
338
370
  return hr;
@@ -365,6 +397,8 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Invoke() {
365
397
  if (spProviderSimple != nullptr) {
366
398
  UiaRaiseAutomationEvent(spProviderSimple.get(), UIA_Invoke_InvokedEventId);
367
399
  }
400
+ DispatchAccessibilityAction(m_view, "invoke");
401
+ DispatchAccessibilityAction(m_view, "activate");
368
402
 
369
403
  return S_OK;
370
404
  }
@@ -378,6 +412,7 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::ScrollIntoView() {
378
412
  winrt::Microsoft::ReactNative::implementation::BringIntoViewOptions scrollOptions;
379
413
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)
380
414
  ->StartBringIntoView(std::move(scrollOptions));
415
+ DispatchAccessibilityAction(m_view, "scrollIntoView");
381
416
 
382
417
  return S_OK;
383
418
  }
@@ -406,6 +441,7 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::SetValue(LPCWSTR val) {
406
441
 
407
442
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)
408
443
  ->setAcccessiblityValue(winrt::to_string(val));
444
+ DispatchAccessibilityAction(m_view, "setValue");
409
445
  return S_OK;
410
446
  }
411
447
 
@@ -456,6 +492,45 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Toggle() {
456
492
  return UIA_E_ELEMENTNOTAVAILABLE;
457
493
 
458
494
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->Toggle();
495
+ DispatchAccessibilityAction(m_view, "toggle");
496
+ return S_OK;
497
+ }
498
+
499
+ HRESULT __stdcall CompositionDynamicAutomationProvider::get_ExpandCollapseState(ExpandCollapseState *pRetVal) {
500
+ if (pRetVal == nullptr)
501
+ return E_POINTER;
502
+ auto strongView = m_view.view();
503
+
504
+ if (!strongView)
505
+ return UIA_E_ELEMENTNOTAVAILABLE;
506
+
507
+ auto props = std::static_pointer_cast<const facebook::react::ViewProps>(
508
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(strongView)->props());
509
+
510
+ if (props == nullptr)
511
+ return UIA_E_ELEMENTNOTAVAILABLE;
512
+
513
+ *pRetVal = props->accessibilityState->expanded.has_value()
514
+ ? GetExpandCollapseState(props->accessibilityState->expanded.value())
515
+ : ExpandCollapseState_Collapsed;
516
+ return S_OK;
517
+ }
518
+
519
+ HRESULT __stdcall CompositionDynamicAutomationProvider::Expand() {
520
+ auto strongView = m_view.view();
521
+
522
+ if (!strongView)
523
+ return UIA_E_ELEMENTNOTAVAILABLE;
524
+ DispatchAccessibilityAction(m_view, "expand");
525
+ return S_OK;
526
+ }
527
+
528
+ HRESULT __stdcall CompositionDynamicAutomationProvider::Collapse() {
529
+ auto strongView = m_view.view();
530
+
531
+ if (!strongView)
532
+ return UIA_E_ELEMENTNOTAVAILABLE;
533
+ DispatchAccessibilityAction(m_view, "collapse");
459
534
  return S_OK;
460
535
  }
461
536
 
@@ -16,7 +16,8 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
16
16
  IInvokeProvider,
17
17
  IScrollItemProvider,
18
18
  IValueProvider,
19
- IToggleProvider> {
19
+ IToggleProvider,
20
+ IExpandCollapseProvider> {
20
21
  public:
21
22
  CompositionDynamicAutomationProvider(
22
23
  const winrt::Microsoft::ReactNative::Composition::ComponentView &componentView) noexcept;
@@ -47,10 +48,15 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
47
48
  virtual HRESULT __stdcall get_Value(BSTR *pRetVal) override;
48
49
  virtual HRESULT __stdcall get_IsReadOnly(BOOL *pRetVal) override;
49
50
 
50
- // inherited via IToggleProivder
51
+ // inherited via IToggleProvider
51
52
  virtual HRESULT __stdcall get_ToggleState(ToggleState *pRetVal) override;
52
53
  virtual HRESULT __stdcall Toggle() override;
53
54
 
55
+ // inherited via IExpandCollapseProvider
56
+ virtual HRESULT __stdcall get_ExpandCollapseState(ExpandCollapseState *pRetVal) override;
57
+ virtual HRESULT __stdcall Expand() override;
58
+ virtual HRESULT __stdcall Collapse() override;
59
+
54
60
  private:
55
61
  ::Microsoft::ReactNative::ReactTaggedView m_view;
56
62
  };
@@ -102,6 +102,7 @@ void CompositionHwndHost::UpdateSize() noexcept {
102
102
  // Do not relayout when minimized
103
103
  if (!IsIconic(m_hwnd)) {
104
104
  winrt::Microsoft::ReactNative::LayoutConstraints constraints;
105
+ constraints.LayoutDirection = winrt::Microsoft::ReactNative::LayoutDirection::Undefined;
105
106
  constraints.MinimumSize = constraints.MaximumSize = size;
106
107
  m_compRootView.Arrange(constraints, {0, 0});
107
108
  }
@@ -23,6 +23,7 @@
23
23
  #include "CompositionHelpers.h"
24
24
  #include "RootComponentView.h"
25
25
  #include "Theme.h"
26
+ #include "TooltipService.h"
26
27
  #include "UiaHelpers.h"
27
28
  #include "d2d1helper.h"
28
29
 
@@ -43,6 +44,13 @@ ComponentView::ComponentView(
43
44
  m_outerVisual.InsertAt(m_focusVisual.InnerVisual(), 0);
44
45
  }
45
46
 
47
+ ComponentView::~ComponentView() {
48
+ if (m_tooltipTracked) {
49
+ TooltipService::GetCurrent(m_reactContext.Properties())->StopTracking(*this);
50
+ m_tooltipTracked = false;
51
+ }
52
+ }
53
+
46
54
  facebook::react::Tag ComponentView::Tag() const noexcept {
47
55
  return m_tag;
48
56
  }
@@ -130,6 +138,16 @@ void ComponentView::updateProps(
130
138
  updateShadowProps(oldViewProps, newViewProps);
131
139
  }
132
140
 
141
+ if (oldViewProps.tooltip != newViewProps.tooltip) {
142
+ if (!m_tooltipTracked && newViewProps.tooltip) {
143
+ TooltipService::GetCurrent(m_reactContext.Properties())->StartTracking(*this);
144
+ m_tooltipTracked = true;
145
+ } else if (m_tooltipTracked && !newViewProps.tooltip) {
146
+ TooltipService::GetCurrent(m_reactContext.Properties())->StopTracking(*this);
147
+ m_tooltipTracked = false;
148
+ }
149
+ }
150
+
133
151
  base_type::updateProps(props, oldProps);
134
152
  }
135
153
 
@@ -248,23 +266,26 @@ void ComponentView::updateEventEmitter(facebook::react::EventEmitter::Shared con
248
266
  base_type::updateEventEmitter(eventEmitter);
249
267
  }
250
268
 
251
- void ComponentView::HandleCommand(
252
- winrt::hstring commandName,
253
- const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept {
269
+ void ComponentView::HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept {
270
+ base_type::HandleCommand(args);
271
+ if (args.Handled())
272
+ return;
273
+
274
+ auto commandName = args.CommandName();
254
275
  if (commandName == L"focus") {
255
276
  if (auto root = rootComponentView()) {
256
- root->TrySetFocusedComponent(*get_strong());
277
+ root->TrySetFocusedComponent(*get_strong(), winrt::Microsoft::ReactNative::FocusNavigationDirection::None);
257
278
  }
258
279
  return;
259
280
  }
260
281
  if (commandName == L"blur") {
261
282
  if (auto root = rootComponentView()) {
262
- root->TrySetFocusedComponent(nullptr); // Todo store this component as previously focused element
283
+ root->TrySetFocusedComponent(
284
+ nullptr, winrt::Microsoft::ReactNative::FocusNavigationDirection::None); // Todo store this component as
285
+ // previously focused element
263
286
  }
264
287
  return;
265
288
  }
266
-
267
- base_type::HandleCommand(commandName, args);
268
289
  }
269
290
 
270
291
  bool ComponentView::CapturePointer(const winrt::Microsoft::ReactNative::Composition::Input::Pointer &pointer) noexcept {
@@ -1288,6 +1309,12 @@ void ComponentView::updateAccessibilityProps(
1288
1309
  !(oldViewProps.accessibilityState && oldViewProps.accessibilityState->disabled),
1289
1310
  !(newViewProps.accessibilityState && newViewProps.accessibilityState->disabled));
1290
1311
 
1312
+ winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
1313
+ m_uiaProvider,
1314
+ UIA_IsEnabledPropertyId,
1315
+ !(oldViewProps.accessibilityState && oldViewProps.accessibilityState->busy),
1316
+ !(newViewProps.accessibilityState && newViewProps.accessibilityState->busy));
1317
+
1291
1318
  winrt::Microsoft::ReactNative::implementation::UpdateUiaProperty(
1292
1319
  m_uiaProvider, UIA_ControlTypePropertyId, oldViewProps.accessibilityRole, newViewProps.accessibilityRole);
1293
1320
 
@@ -30,6 +30,7 @@ struct ComponentView : public ComponentViewT<
30
30
  facebook::react::Tag tag,
31
31
  winrt::Microsoft::ReactNative::ReactContext const &reactContext,
32
32
  ComponentViewFeatures flags);
33
+ virtual ~ComponentView();
33
34
 
34
35
  virtual winrt::Microsoft::ReactNative::Composition::Experimental::IVisual Visual() const noexcept {
35
36
  return nullptr;
@@ -38,8 +39,7 @@ struct ComponentView : public ComponentViewT<
38
39
  virtual winrt::Microsoft::ReactNative::Composition::Experimental::IVisual OuterVisual() const noexcept;
39
40
  void updateEventEmitter(facebook::react::EventEmitter::Shared const &eventEmitter) noexcept override;
40
41
  const facebook::react::SharedViewEventEmitter &GetEventEmitter() const noexcept;
41
- void HandleCommand(winrt::hstring commandName, const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept
42
- override;
42
+ void HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept override;
43
43
  facebook::react::Props::Shared props() noexcept override;
44
44
  virtual const facebook::react::SharedViewProps &viewProps() const noexcept {
45
45
  static facebook::react::SharedViewProps emptyProps;
@@ -152,6 +152,7 @@ struct ComponentView : public ComponentViewT<
152
152
  const facebook::react::ViewProps &viewProps) noexcept;
153
153
 
154
154
  bool m_FinalizeTransform{false};
155
+ bool m_tooltipTracked{false};
155
156
  ComponentViewFeatures m_flags;
156
157
  void showFocusVisual(bool show) noexcept;
157
158
  winrt::Microsoft::ReactNative::Composition::Experimental::IFocusVisual m_focusVisual{nullptr};
@@ -67,17 +67,21 @@ struct TraceUpdate {
67
67
  };
68
68
 
69
69
  void DebuggingOverlayComponentView::HandleCommand(
70
- winrt::hstring commandName,
71
- const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept {
70
+ const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept {
71
+ base_type::HandleCommand(args);
72
+ if (args.Handled())
73
+ return;
74
+
75
+ auto commandName = args.CommandName();
72
76
  if (commandName == L"highlightTraceUpdates") {
73
77
  std::vector<TraceUpdate> updates;
74
- winrt::Microsoft::ReactNative::ReadArgs(args, updates);
78
+ winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), updates);
75
79
  // TODO should create visuals that get removed after 2 seconds
76
80
  return;
77
81
  }
78
82
  if (commandName == L"highlightElements") {
79
83
  std::vector<ElementRectangle> elements;
80
- winrt::Microsoft::ReactNative::ReadArgs(args, elements);
84
+ winrt::Microsoft::ReactNative::ReadArgs(args.CommandArgs(), elements);
81
85
 
82
86
  if (auto root = rootComponentView()) {
83
87
  auto rootVisual = root->OuterVisual();
@@ -106,8 +110,6 @@ void DebuggingOverlayComponentView::HandleCommand(
106
110
  }
107
111
  return;
108
112
  }
109
-
110
- base_type::HandleCommand(commandName, args);
111
113
  }
112
114
 
113
115
  } // namespace winrt::Microsoft::ReactNative::Composition::implementation
@@ -29,8 +29,7 @@ struct DebuggingOverlayComponentView
29
29
  facebook::react::Tag tag,
30
30
  winrt::Microsoft::ReactNative::ReactContext const &reactContext);
31
31
 
32
- void HandleCommand(winrt::hstring commandName, const winrt::Microsoft::ReactNative::IJSValueReader &args) noexcept
33
- override;
32
+ void HandleCommand(const winrt::Microsoft::ReactNative::HandleCommandArgs &args) noexcept override;
34
33
 
35
34
  private:
36
35
  uint32_t m_activeOverlays{0};
@@ -22,19 +22,26 @@ int32_t GotFocusEventArgs::OriginalSource() noexcept {
22
22
 
23
23
  LosingFocusEventArgs::LosingFocusEventArgs(
24
24
  const winrt::Microsoft::ReactNative::ComponentView &originalSource,
25
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
25
26
  const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
26
27
  const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent)
27
28
  : m_originalSource(originalSource ? originalSource.Tag() : -1),
29
+ m_direction(direction),
28
30
  m_old(oldFocusedComponent),
29
31
  m_new(newFocusedComponent) {}
30
32
 
31
- int32_t LosingFocusEventArgs::OriginalSource() noexcept {
33
+ int32_t LosingFocusEventArgs::OriginalSource() const noexcept {
32
34
  return m_originalSource;
33
35
  }
34
- winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::NewFocusedComponent() noexcept {
36
+
37
+ winrt::Microsoft::ReactNative::FocusNavigationDirection LosingFocusEventArgs::Direction() const noexcept {
38
+ return m_direction;
39
+ }
40
+
41
+ winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::NewFocusedComponent() const noexcept {
35
42
  return m_new;
36
43
  }
37
- winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::OldFocusedComponent() noexcept {
44
+ winrt::Microsoft::ReactNative::ComponentView LosingFocusEventArgs::OldFocusedComponent() const noexcept {
38
45
  return m_old;
39
46
  }
40
47
 
@@ -58,19 +65,26 @@ void LosingFocusEventArgs::TrySetNewFocusedComponent(
58
65
 
59
66
  GettingFocusEventArgs::GettingFocusEventArgs(
60
67
  const winrt::Microsoft::ReactNative::ComponentView &originalSource,
68
+ winrt::Microsoft::ReactNative::FocusNavigationDirection direction,
61
69
  const winrt::Microsoft::ReactNative::ComponentView &oldFocusedComponent,
62
70
  const winrt::Microsoft::ReactNative::ComponentView &newFocusedComponent)
63
71
  : m_originalSource(originalSource ? originalSource.Tag() : -1),
72
+ m_direction(direction),
64
73
  m_old(oldFocusedComponent),
65
74
  m_new(newFocusedComponent) {}
66
75
 
67
- int32_t GettingFocusEventArgs::OriginalSource() noexcept {
76
+ int32_t GettingFocusEventArgs::OriginalSource() const noexcept {
68
77
  return m_originalSource;
69
78
  }
70
- winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::NewFocusedComponent() noexcept {
79
+
80
+ winrt::Microsoft::ReactNative::FocusNavigationDirection GettingFocusEventArgs::Direction() const noexcept {
81
+ return m_direction;
82
+ }
83
+
84
+ winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::NewFocusedComponent() const noexcept {
71
85
  return m_new;
72
86
  }
73
- winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::OldFocusedComponent() noexcept {
87
+ winrt::Microsoft::ReactNative::ComponentView GettingFocusEventArgs::OldFocusedComponent() const noexcept {
74
88
  return m_old;
75
89
  }
76
90