react-native-windows 0.74.46 → 0.74.47

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 (41) hide show
  1. package/Libraries/Components/View/View.windows.js +13 -5
  2. package/Libraries/Components/View/ViewAccessibility.d.ts +67 -0
  3. package/Libraries/Components/View/ViewPropTypes.windows.js +2 -0
  4. package/Libraries/NativeComponent/BaseViewConfig.windows.js +4 -0
  5. package/Microsoft.ReactNative/Fabric/Composition/CompositionContextHelper.cpp +1 -1
  6. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.cpp +47 -0
  7. package/Microsoft.ReactNative/Fabric/Composition/CompositionDynamicAutomationProvider.h +1 -0
  8. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +81 -94
  9. package/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.h +1 -1
  10. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.cpp +115 -0
  11. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextProvider.h +41 -0
  12. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.cpp +319 -0
  13. package/Microsoft.ReactNative/Fabric/Composition/CompositionTextRangeProvider.h +59 -0
  14. package/Microsoft.ReactNative/Fabric/Composition/CompositionViewComponentView.cpp +47 -0
  15. package/Microsoft.ReactNative/Fabric/Composition/ParagraphComponentView.cpp +43 -34
  16. package/Microsoft.ReactNative/Fabric/Composition/SwitchComponentView.cpp +11 -0
  17. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.cpp +149 -17
  18. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputComponentView.h +5 -0
  19. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.cpp +2 -1
  20. package/Microsoft.ReactNative/Fabric/Composition/TextInput/WindowsTextInputProps.h +2 -1
  21. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.cpp +43 -1
  22. package/Microsoft.ReactNative/Fabric/Composition/UiaHelpers.h +27 -2
  23. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.cpp +22 -4
  24. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewEventEmitter.h +16 -3
  25. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.cpp +24 -0
  26. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/HostPlatformViewProps.h +4 -0
  27. package/Microsoft.ReactNative/Fabric/platform/react/renderer/components/view/MouseEvent.h +20 -0
  28. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.cpp +133 -32
  29. package/Microsoft.ReactNative/Fabric/platform/react/renderer/textlayoutmanager/TextLayoutManager.h +12 -0
  30. package/Microsoft.ReactNative/Microsoft.ReactNative.vcxproj.filters +1 -3
  31. package/Microsoft.ReactNative.Managed.CodeGen/Microsoft.ReactNative.Managed.CodeGen.csproj +1 -1
  32. package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Debug.pubxml +1 -1
  33. package/Microsoft.ReactNative.Managed.CodeGen/Properties/PublishProfiles/DeployAsTool-Release.pubxml +1 -1
  34. package/Microsoft.ReactNative.Managed.CodeGen/packages.lock.json +3 -3
  35. package/PropertySheets/External/Microsoft.ReactNative.WindowsSdk.Default.props +4 -4
  36. package/PropertySheets/Generated/PackageVersion.g.props +3 -3
  37. package/Scripts/Tfs/Start-TestServers.ps1 +2 -1
  38. package/Scripts/rnw-dependencies.ps1 +38 -25
  39. package/Shared/Shared.vcxitems +6 -0
  40. package/Shared/Shared.vcxitems.filters +8 -0
  41. package/package.json +3 -3
@@ -38,6 +38,7 @@ const View: React.AbstractComponent<
38
38
  accessibilityLabel,
39
39
  accessibilityLabelledBy,
40
40
  accessibilityLevel, // Windows
41
+ accessibilityDescription, //Windows
41
42
  accessibilityLiveRegion,
42
43
  accessibilityPosInSet, // Windows
43
44
  accessibilitySetSize, // Windows
@@ -49,6 +50,7 @@ const View: React.AbstractComponent<
49
50
  'aria-expanded': ariaExpanded,
50
51
  'aria-multiselectable': ariaMultiselectable, // Windows
51
52
  'aria-required': ariaRequired, // Windows
53
+ 'aria-description': ariaDescription, //Windows
52
54
  'aria-hidden': ariaHidden,
53
55
  'aria-label': ariaLabel,
54
56
  'aria-labelledby': ariaLabelledBy,
@@ -227,6 +229,13 @@ const View: React.AbstractComponent<
227
229
 
228
230
  // Windows]
229
231
 
232
+ const computedImportantForAccessibility =
233
+ ariaHidden === true ||
234
+ importantForAccessibility === 'no-hide-descendants' ||
235
+ accessibilityElementsHidden === true
236
+ ? 'no-hide-descendants'
237
+ : importantForAccessibility;
238
+
230
239
  return (
231
240
  // [Windows
232
241
  // In core this is a TextAncestor.Provider value={false} See
@@ -248,6 +257,9 @@ const View: React.AbstractComponent<
248
257
  }
249
258
  accessibilityLabel={ariaLabel ?? accessibilityLabel}
250
259
  accessibilityLevel={ariaLevel ?? accessibilityLevel}
260
+ accessibilityDescription={
261
+ ariaDescription ?? accessibilityDescription
262
+ }
251
263
  accessibilityPosInSet={ariaPosinset ?? accessibilityPosInSet}
252
264
  accessibilitySetSize={ariaSetsize ?? accessibilitySetSize}
253
265
  focusable={_focusable}
@@ -258,11 +270,7 @@ const View: React.AbstractComponent<
258
270
  }
259
271
  accessibilityLabelledBy={_accessibilityLabelledBy}
260
272
  accessibilityValue={_accessibilityValue}
261
- importantForAccessibility={
262
- ariaHidden === true
263
- ? 'no-hide-descendants'
264
- : importantForAccessibility
265
- }
273
+ importantForAccessibility={computedImportantForAccessibility}
266
274
  nativeID={id ?? nativeID}
267
275
  style={style}
268
276
  // $FlowFixMe[incompatible-type]
@@ -14,6 +14,7 @@ import {NativeSyntheticEvent} from '../../Types/CoreEventTypes';
14
14
  */
15
15
  export interface AccessibilityProps
16
16
  extends AccessibilityPropsAndroid,
17
+ AccessibilityPropsWindows,
17
18
  AccessibilityPropsIOS {
18
19
  /**
19
20
  * When true, indicates that the view is an accessibility element.
@@ -258,6 +259,72 @@ export type AccessibilityRole =
258
259
  | 'listitem' // Windows
259
260
  | 'toolbar';
260
261
 
262
+ // [Windows]
263
+ export type AnnotationType =
264
+ | 'AdvanceProofingIssue'
265
+ | 'Author'
266
+ | 'CircularReferenceError'
267
+ | 'Comment'
268
+ | 'ConflictingChange'
269
+ | 'DataValidationError'
270
+ | 'DeletionChange'
271
+ | 'EditingLockedChange'
272
+ | 'Endnote'
273
+ | 'ExternalChange'
274
+ | 'Footer'
275
+ | 'Footnote'
276
+ | 'FormatChange'
277
+ | 'FormulaError'
278
+ | 'GrammarError'
279
+ | 'Header'
280
+ | 'Highlighted'
281
+ | 'InsertionChange'
282
+ | 'Mathematics'
283
+ | 'MoveChange'
284
+ | 'SpellingError'
285
+ | 'TrackChanges'
286
+ | 'Unknown'
287
+ | 'UnsyncedChange';
288
+
289
+ // [Windows]
290
+ export type AccessibilityAnnotationInfo = Readonly<{
291
+ typeID: AnnotationType;
292
+ typeName?: string;
293
+ author?: string;
294
+ dateTime?: string;
295
+ target?: string;
296
+ }>;
297
+ export interface AccessibilityPropsWindows {
298
+ /**
299
+ * Tells a person using a screen reader what kind of annotation they
300
+ * have selected. If available, it will also tell a person the author of the annotation and
301
+ * the date and time the annotation was posted.
302
+ *
303
+ * Note: If typeID is 'Unknown', a typeName must be provided.
304
+ */
305
+ accessibilityAnnotation?: AccessibilityAnnotationInfo; //Windows
306
+
307
+ /**
308
+ * Identifies the ItemType property, which is a text string describing the type of the automation element.
309
+ * ItemType is used to obtain information about items in a list, tree view, or data grid. For example, an item in a file directory view might be a "Document File" or a "Folder".
310
+ */
311
+ accessibilityItemType?: string; //Windows
312
+
313
+ /**
314
+ * An access key to hook up to the UIA_AccessKey_Property.
315
+ * Access keys are used in keyboard navigation to allow quick navigation to UI in an application.
316
+ */
317
+ accessibilityAccessKey?: string; //Windows
318
+
319
+ /**
320
+ * accessibilityDescription provides more detailed information specific to the element (i.e. last edit date, full location for a file)
321
+ * while accessibilityHint provides information on what will happen when they perform an action.
322
+ *
323
+ */
324
+ accessibilityDescription?: string; // Windows
325
+ 'aria-description'?: string; // Windows
326
+ }
327
+
261
328
  export interface AccessibilityPropsAndroid {
262
329
  /**
263
330
  * Identifies the element that labels the element it is applied to. When the assistive technology focuses on the component with this props,
@@ -505,6 +505,8 @@ type WindowsViewProps = $ReadOnly<{|
505
505
  'aria-posinset'?: ?number,
506
506
  accessibilitySetSize?: ?number,
507
507
  'aria-setsize'?: ?number,
508
+ accessibilityDescription?: ?string,
509
+ 'aria-description'?: ?string,
508
510
 
509
511
  /**
510
512
  * Specifies if the control should show System focus visuals
@@ -359,6 +359,10 @@ const validAttributesForNonEventProps = {
359
359
  accessibilityLiveRegion: true, // [Windows]
360
360
  accessibilityPosInSet: true, // [Windows]
361
361
  accessibilitySetSize: true, // [Windows]
362
+ accessibilityAnnotation: true, // [Windows]
363
+ accessibilityItemType: true, // [Windows]
364
+ accessibilityAccessKey: true, // [Windows]
365
+ accessibilityDescription: true, // [Windows]
362
366
  disabled: true, // [Windows]
363
367
  focusable: true, // [Windows]
364
368
  keyDownEvents: true, // [Windows]
@@ -787,7 +787,7 @@ struct CompScrollerVisual : winrt::implements<
787
787
  m_horizontal ? TTypeRedirects::InteractionSourceMode::Disabled
788
788
  : TTypeRedirects::InteractionSourceMode::EnabledWithInertia);
789
789
  m_visualInteractionSource.ManipulationRedirectionMode(
790
- TTypeRedirects::VisualInteractionSourceRedirectionMode::CapableTouchpadAndPointerWheel);
790
+ TTypeRedirects::VisualInteractionSourceRedirectionMode::CapableTouchpadOnly);
791
791
  } else {
792
792
  m_visualInteractionSource.PositionXSourceMode(TTypeRedirects::InteractionSourceMode::Disabled);
793
793
  m_visualInteractionSource.PositionYSourceMode(TTypeRedirects::InteractionSourceMode::Disabled);
@@ -1,6 +1,8 @@
1
1
  #include "pch.h"
2
2
  #include "CompositionDynamicAutomationProvider.h"
3
3
  #include <Fabric/ComponentView.h>
4
+ #include <Fabric/Composition/CompositionTextRangeProvider.h>
5
+ #include <Fabric/Composition/ParagraphComponentView.h>
4
6
  #include <Fabric/Composition/SwitchComponentView.h>
5
7
  #include <Fabric/Composition/TextInput/WindowsTextInputComponentView.h>
6
8
  #include <Unicode.h>
@@ -26,6 +28,13 @@ CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
26
28
  if (props->accessibilityState.has_value() && props->accessibilityState->selected.has_value()) {
27
29
  AddSelectionItemsToContainer(this);
28
30
  }
31
+
32
+ if (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
33
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>()) {
34
+ m_textProvider = winrt::make<CompositionTextProvider>(
35
+ strongView.as<winrt::Microsoft::ReactNative::Composition::ComponentView>(), this)
36
+ .try_as<ITextProvider2>();
37
+ }
29
38
  }
30
39
 
31
40
  CompositionDynamicAutomationProvider::CompositionDynamicAutomationProvider(
@@ -253,6 +262,17 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPatternProvider(PATTE
253
262
  AddRef();
254
263
  }
255
264
 
265
+ if (patternId == UIA_TextPatternId &&
266
+ (strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>() ||
267
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::ParagraphComponentView>())) {
268
+ m_textProvider.as<IUnknown>().copy_to(pRetVal);
269
+ }
270
+
271
+ if (patternId == UIA_TextPattern2Id &&
272
+ strongView.try_as<winrt::Microsoft::ReactNative::Composition::implementation::WindowsTextInputComponentView>()) {
273
+ m_textProvider.as<IUnknown>().copy_to(pRetVal);
274
+ }
275
+
256
276
  return S_OK;
257
277
  }
258
278
 
@@ -527,6 +547,29 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::GetPropertyValue(PROPERT
527
547
  : SysAllocString(L"");
528
548
  break;
529
549
  }
550
+ case UIA_LevelPropertyId: {
551
+ pRetVal->vt = VT_I4;
552
+ pRetVal->lVal = props->accessibilityLevel;
553
+ break;
554
+ }
555
+ case UIA_AccessKeyPropertyId: {
556
+ pRetVal->vt = VT_BSTR;
557
+ auto accessKey = ::Microsoft::Common::Unicode::Utf8ToUtf16(props->accessibilityAccessKey.value_or(""));
558
+ pRetVal->bstrVal = SysAllocString(accessKey.c_str());
559
+ break;
560
+ }
561
+ case UIA_ItemTypePropertyId: {
562
+ pRetVal->vt = VT_BSTR;
563
+ auto itemtype = ::Microsoft::Common::Unicode::Utf8ToUtf16(props->accessibilityItemType.value_or(""));
564
+ pRetVal->bstrVal = SysAllocString(itemtype.c_str());
565
+ break;
566
+ }
567
+ case UIA_FullDescriptionPropertyId: {
568
+ pRetVal->vt = VT_BSTR;
569
+ auto desc = ::Microsoft::Common::Unicode::Utf8ToUtf16(props->accessibilityDescription.value_or(""));
570
+ pRetVal->bstrVal = SysAllocString(desc.c_str());
571
+ break;
572
+ }
530
573
  }
531
574
 
532
575
  return hr;
@@ -769,7 +812,9 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Expand() {
769
812
 
770
813
  if (!strongView)
771
814
  return UIA_E_ELEMENTNOTAVAILABLE;
815
+
772
816
  DispatchAccessibilityAction(m_view, "expand");
817
+
773
818
  return S_OK;
774
819
  }
775
820
 
@@ -778,7 +823,9 @@ HRESULT __stdcall CompositionDynamicAutomationProvider::Collapse() {
778
823
 
779
824
  if (!strongView)
780
825
  return UIA_E_ELEMENTNOTAVAILABLE;
826
+
781
827
  DispatchAccessibilityAction(m_view, "collapse");
828
+
782
829
  return S_OK;
783
830
  }
784
831
 
@@ -89,6 +89,7 @@ class CompositionDynamicAutomationProvider : public winrt::implements<
89
89
 
90
90
  private:
91
91
  ::Microsoft::ReactNative::ReactTaggedView m_view;
92
+ winrt::com_ptr<ITextProvider2> m_textProvider;
92
93
  std::vector<winrt::com_ptr<IRawElementProviderSimple>> m_selectionItems;
93
94
  // Non-null when this UIA node is the peer of a ContentIslandComponentView.
94
95
  winrt::Microsoft::UI::Content::ChildSiteLink m_childSiteLink{nullptr};
@@ -9,7 +9,6 @@
9
9
  #include <IReactContext.h>
10
10
  #include <React.h>
11
11
  #include <Views/DevMenu.h>
12
- #include <Views/ShadowNodeBase.h>
13
12
  #include <windows.h>
14
13
  #include <windowsx.h>
15
14
  #include <winrt/Windows.UI.Core.h>
@@ -637,17 +636,6 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
637
636
 
638
637
  auto eventPathViews = GetTouchableViewsInPathToRoot(targetView);
639
638
 
640
- // Over
641
- if (targetView != nullptr && previousTargetTag != targetView.Tag()) {
642
- bool shouldEmitOverEvent =
643
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerOver);
644
- const auto eventEmitter = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(targetView)
645
- ->eventEmitterAtPoint(event.offsetPoint);
646
- if (shouldEmitOverEvent && eventEmitter != nullptr) {
647
- eventEmitter->onPointerOver(event);
648
- }
649
- }
650
-
651
639
  // Entering
652
640
 
653
641
  // We only want to emit events to JS if there is a view that is currently listening to said event
@@ -664,7 +652,6 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
664
652
  auto componentView = *itComponentView;
665
653
  bool shouldEmitEvent = componentView != nullptr &&
666
654
  (hasParentEnterListener ||
667
- IsViewListeningToEvent(componentView, facebook::react::ViewEvents::Offset::PointerEnter) ||
668
655
  IsViewListeningToEvent(componentView, facebook::react::WindowsViewEvents::Offset::MouseEnter));
669
656
 
670
657
  if (std::find(currentlyHoveredViews.begin(), currentlyHoveredViews.end(), componentView) ==
@@ -674,16 +661,12 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
674
661
  m_context, componentView.Tag(), pointerPoint, keyModifiers);
675
662
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(componentView)
676
663
  ->OnPointerEntered(args);
677
-
678
664
  if (shouldEmitEvent) {
679
665
  const auto eventEmitter =
680
666
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(componentView)
681
667
  ->eventEmitter();
682
- if (eventEmitter) {
683
- eventEmitter->onPointerEnter(event);
684
- if (IsMousePointerEvent(event)) {
685
- eventEmitter->onMouseEnter(event);
686
- }
668
+ if (eventEmitter && IsMousePointerEvent(event)) {
669
+ eventEmitter->onMouseEnter(event);
687
670
  }
688
671
  }
689
672
  }
@@ -696,26 +679,13 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
696
679
  // Call the underlaying pointer handler
697
680
  handler(eventPathViews);
698
681
 
699
- // Out
700
- if (previousTargetTag != -1 && previousTargetTag != (targetView ? targetView.Tag() : -1)) {
701
- bool shouldEmitOutEvent =
702
- IsAnyViewInPathListeningToEvent(currentlyHoveredViews, facebook::react::ViewEvents::Offset::PointerOut);
703
- const auto eventEmitter =
704
- winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(prevTargetView)->eventEmitter();
705
- if (shouldEmitOutEvent && eventEmitter != nullptr) {
706
- eventEmitter->onPointerOut(event);
707
- }
708
- }
709
-
710
682
  // Leaving
711
683
 
712
684
  // pointerleave events need to be emitted from the deepest target to the root but
713
685
  // we also need to efficiently keep track of if a view has a parent which is listening to the leave events,
714
686
  // so we first iterate from the root to the target, collecting the views which need events fired for, of which
715
687
  // we reverse iterate (now from target to root), actually emitting the events.
716
- std::vector<winrt::Microsoft::ReactNative::ComponentView>
717
- viewsToEmitJSLeaveEventsTo; // NSMutableOrderedSet<UIView *> *viewsToEmitLeaveEventsTo =
718
- // [NSMutableOrderedSet orderedSet];
688
+ std::vector<winrt::Microsoft::ReactNative::ComponentView> viewsToEmitJSLeaveEventsTo;
719
689
 
720
690
  std::vector<winrt::Microsoft::ReactNative::ComponentView> viewsToEmitLeaveEventsTo;
721
691
 
@@ -723,14 +693,11 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
723
693
 
724
694
  bool hasParentLeaveListener = false;
725
695
  for (auto itComponentView = currentlyHoveredViews.rbegin(); itComponentView != currentlyHoveredViews.rend();
726
- itComponentView++) { // for (RCTReactTaggedView *taggedView in [currentlyHoveredViews
727
- // reverseObjectEnumerator])
728
- // {
696
+ itComponentView++) {
729
697
  auto componentView = *itComponentView;
730
698
 
731
699
  bool shouldEmitJSEvent = componentView != nullptr &&
732
700
  (hasParentLeaveListener ||
733
- IsViewListeningToEvent(componentView, facebook::react::ViewEvents::Offset::PointerLeave) ||
734
701
  IsViewListeningToEvent(componentView, facebook::react::WindowsViewEvents::Offset::MouseLeave));
735
702
 
736
703
  if (std::find(eventPathViews.begin(), eventPathViews.end(), componentView) == eventPathViews.end()) {
@@ -755,17 +722,13 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
755
722
  }
756
723
 
757
724
  for (auto itComponentView = viewsToEmitJSLeaveEventsTo.rbegin(); itComponentView != viewsToEmitJSLeaveEventsTo.rend();
758
- itComponentView++) { // for (UIView *componentView in [viewsToEmitJSLeaveEventsTo
759
- // reverseObjectEnumerator]) {
725
+ itComponentView++) {
760
726
  auto componentView = *itComponentView;
761
727
 
762
728
  const auto eventEmitter =
763
729
  winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(componentView)->eventEmitter();
764
- if (eventEmitter) {
765
- eventEmitter->onPointerLeave(event);
766
- if (IsMousePointerEvent(event)) {
767
- eventEmitter->onMouseLeave(event);
768
- }
730
+ if (eventEmitter && IsMousePointerEvent(event)) {
731
+ eventEmitter->onMouseLeave(event);
769
732
  }
770
733
  }
771
734
 
@@ -815,41 +778,41 @@ void CompositionEventHandler::SetCursor(facebook::react::Cursor cursor, HCURSOR
815
778
  case facebook::react::Cursor::Pointer:
816
779
  type = winrt::Windows::UI::Core::CoreCursorType::Hand;
817
780
  break;
818
- /* -- Additional cursors not added in core until later version
819
- case facebook::react::Cursor::Help:
820
- type = winrt::Windows::UI::Core::CoreCursorType::Help;
821
- break;
822
- case facebook::react::Cursor::NotAllowed:
823
- type = winrt::Windows::UI::Core::CoreCursorType::UniversalNo;
824
- break;
825
- case facebook::react::Cursor::Wait:
826
- type = winrt::Windows::UI::Core::CoreCursorType::Wait;
827
- break;
828
- case facebook::react::Cursor::Move:
829
- type = winrt::Windows::UI::Core::CoreCursorType::SizeAll;
830
- break;
831
- case facebook::react::Cursor::NESWResize:
832
- type = winrt::Windows::UI::Core::CoreCursorType::SizeNortheastSouthwest;
833
- break;
834
- case facebook::react::Cursor::NSResize:
835
- type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthSouth;
836
- break;
837
- case facebook::react::Cursor::NWSEResize:
838
- type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthwestSoutheast;
839
- break;
840
- case facebook::react::Cursor::EWResize:
841
- type = winrt::Windows::UI::Core::CoreCursorType::SizeWestEast;
842
- break;
843
- case facebook::react::Cursor::Text:
844
- type = winrt::Windows::UI::Core::CoreCursorType::IBeam;
845
- break;
846
- case facebook::react::Cursor::Progress:
847
- type = winrt::Windows::UI::Core::CoreCursorType::Wait; // IDC_APPSTARTING not mapped to CoreCursor?
848
- break;
849
- case facebook::react::Cursor::Crosshair:
850
- type = winrt::Windows::UI::Core::CoreCursorType::Cross;
851
- break;
852
- */
781
+ /*
782
+ case facebook::react::Cursor::Help:
783
+ type = winrt::Windows::UI::Core::CoreCursorType::Help;
784
+ break;
785
+ case facebook::react::Cursor::NotAllowed:
786
+ type = winrt::Windows::UI::Core::CoreCursorType::UniversalNo;
787
+ break;
788
+ case facebook::react::Cursor::Wait:
789
+ type = winrt::Windows::UI::Core::CoreCursorType::Wait;
790
+ break;
791
+ case facebook::react::Cursor::Move:
792
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeAll;
793
+ break;
794
+ case facebook::react::Cursor::NESWResize:
795
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeNortheastSouthwest;
796
+ break;
797
+ case facebook::react::Cursor::NSResize:
798
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthSouth;
799
+ break;
800
+ case facebook::react::Cursor::NWSEResize:
801
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeNorthwestSoutheast;
802
+ break;
803
+ case facebook::react::Cursor::EWResize:
804
+ type = winrt::Windows::UI::Core::CoreCursorType::SizeWestEast;
805
+ break;
806
+ case facebook::react::Cursor::Text:
807
+ type = winrt::Windows::UI::Core::CoreCursorType::IBeam;
808
+ break;
809
+ case facebook::react::Cursor::Progress:
810
+ type = winrt::Windows::UI::Core::CoreCursorType::Wait; // IDC_APPSTARTING not mapped to CoreCursor?
811
+ break;
812
+ case facebook::react::Cursor::Crosshair:
813
+ type = winrt::Windows::UI::Core::CoreCursorType::Cross;
814
+ break;
815
+ */
853
816
  default:
854
817
  break;
855
818
  }
@@ -880,7 +843,7 @@ void CompositionEventHandler::SetCursor(facebook::react::Cursor cursor, HCURSOR
880
843
  case facebook::react::Cursor::Pointer:
881
844
  idc = IDC_HAND;
882
845
  break;
883
- /* -- Additional cursors not added in core until later version
846
+ /*
884
847
  case facebook::react::Cursor::Help:
885
848
  idc = IDC_HELP;
886
849
  break;
@@ -1064,21 +1027,48 @@ void CompositionEventHandler::onPointerMoved(
1064
1027
 
1065
1028
  facebook::react::PointerEvent pointerEvent = CreatePointerEventFromIncompleteHoverData(ptScaled, ptLocal);
1066
1029
 
1067
- auto handler = [&targetView,
1068
- &pointerEvent](std::vector<winrt::Microsoft::ReactNative::ComponentView> &eventPathViews) {
1030
+ // check if this pointer corresponds to active touch that has a responder
1031
+ auto activeTouch = m_activeTouches.find(pointerId);
1032
+ bool isActiveTouch = activeTouch != m_activeTouches.end() && activeTouch->second.eventEmitter != nullptr;
1033
+
1034
+ auto handler = [&, targetView, pointerEvent, isActiveTouch](
1035
+ std::vector<winrt::Microsoft::ReactNative::ComponentView> &eventPathViews) {
1069
1036
  const auto eventEmitter = targetView
1070
1037
  ? winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(targetView)
1071
1038
  ->eventEmitterAtPoint(pointerEvent.offsetPoint)
1072
- : nullptr;
1073
- bool hasMoveEventListeners =
1074
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMove) ||
1075
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMoveCapture);
1076
- if (eventEmitter != nullptr && hasMoveEventListeners) {
1039
+ : RootComponentView().eventEmitterAtPoint(pointerEvent.offsetPoint);
1040
+
1041
+ if (eventEmitter != nullptr) {
1077
1042
  eventEmitter->onPointerMove(pointerEvent);
1043
+ } else {
1044
+ ClearAllHoveredForPointer(pointerEvent);
1078
1045
  }
1079
1046
  };
1080
1047
 
1081
1048
  HandleIncomingPointerEvent(pointerEvent, targetView, pointerPoint, keyModifiers, handler);
1049
+
1050
+ if (isActiveTouch) {
1051
+ // For active touches with responders, also dispatch through touch event system
1052
+ UpdateActiveTouch(activeTouch->second, ptScaled, ptLocal);
1053
+ DispatchTouchEvent(TouchEventType::Move, pointerId, pointerPoint, keyModifiers);
1054
+ }
1055
+ }
1056
+ }
1057
+
1058
+ void CompositionEventHandler::ClearAllHoveredForPointer(const facebook::react::PointerEvent &pointerEvent) noexcept {
1059
+ // special case if we have no target
1060
+ // PointerEventsProcessor requires move events to keep track of the hovered components in core.
1061
+ // It also treats a onPointerLeave event as a special case that removes the hover state of all currently hovered
1062
+ // events. If we get null for the targetView, that means that the mouse is no over any components, so we have no
1063
+ // element to send the move event to. However we need to send something so that any previously hovered elements
1064
+ // are no longer hovered.
1065
+ auto children = RootComponentView().Children();
1066
+ if (auto size = children.Size()) {
1067
+ auto firstChild = children.GetAt(0);
1068
+ if (auto childEventEmitter =
1069
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(firstChild)->eventEmitter()) {
1070
+ childEventEmitter->onPointerLeave(pointerEvent);
1071
+ }
1082
1072
  }
1083
1073
  }
1084
1074
 
@@ -1104,7 +1094,9 @@ void CompositionEventHandler::onPointerExited(
1104
1094
 
1105
1095
  facebook::react::PointerEvent pointerEvent = CreatePointerEventFromIncompleteHoverData(ptScaled, ptLocal);
1106
1096
 
1107
- auto handler = [](std::vector<winrt::Microsoft::ReactNative::ComponentView> &eventPathViews) {};
1097
+ auto handler = [&](std::vector<winrt::Microsoft::ReactNative::ComponentView> &eventPathViews) {
1098
+ ClearAllHoveredForPointer(pointerEvent);
1099
+ };
1108
1100
 
1109
1101
  HandleIncomingPointerEvent(pointerEvent, nullptr, pointerPoint, keyModifiers, handler);
1110
1102
  }
@@ -1392,12 +1384,7 @@ void CompositionEventHandler::DispatchTouchEvent(
1392
1384
  activeTouch.eventEmitter->onPointerDown(pointerEvent);
1393
1385
  break;
1394
1386
  case TouchEventType::Move: {
1395
- bool hasMoveEventListeners =
1396
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMove) ||
1397
- IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMoveCapture);
1398
- if (hasMoveEventListeners) {
1399
- activeTouch.eventEmitter->onPointerMove(pointerEvent);
1400
- }
1387
+ activeTouch.eventEmitter->onPointerMove(pointerEvent);
1401
1388
  break;
1402
1389
  }
1403
1390
  case TouchEventType::End:
@@ -14,7 +14,6 @@
14
14
  #include <winrt/Windows.Devices.Input.h>
15
15
  #include <optional>
16
16
  #include <set>
17
- #include "Utils/BatchingEventEmitter.h"
18
17
 
19
18
  namespace winrt {
20
19
  using namespace Windows::UI;
@@ -99,6 +98,7 @@ class CompositionEventHandler : public std::enable_shared_from_this<CompositionE
99
98
  const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
100
99
  winrt::Windows::System::VirtualKeyModifiers keyModifiers,
101
100
  std::function<void(std::vector<winrt::Microsoft::ReactNative::ComponentView> &)> handler);
101
+ void ClearAllHoveredForPointer(const facebook::react::PointerEvent &pointerEvent) noexcept;
102
102
 
103
103
  struct ActiveTouch {
104
104
  facebook::react::Touch touch;