@@ -636,17 +636,6 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
636
636
637
637
auto eventPathViews = GetTouchableViewsInPathToRoot (targetView);
638
638
639
- // Over
640
- if (targetView != nullptr && previousTargetTag != targetView.Tag ()) {
641
- bool shouldEmitOverEvent =
642
- IsAnyViewInPathListeningToEvent (eventPathViews, facebook::react::ViewEvents::Offset::PointerOver);
643
- const auto eventEmitter = winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(targetView)
644
- ->eventEmitterAtPoint (event.offsetPoint );
645
- if (shouldEmitOverEvent && eventEmitter != nullptr ) {
646
- eventEmitter->onPointerOver (event);
647
- }
648
- }
649
-
650
639
// Entering
651
640
652
641
// We only want to emit events to JS if there is a view that is currently listening to said event
@@ -663,7 +652,6 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
663
652
auto componentView = *itComponentView;
664
653
bool shouldEmitEvent = componentView != nullptr &&
665
654
(hasParentEnterListener ||
666
- IsViewListeningToEvent (componentView, facebook::react::ViewEvents::Offset::PointerEnter) ||
667
655
IsViewListeningToEvent (componentView, facebook::react::WindowsViewEvents::Offset::MouseEnter));
668
656
669
657
if (std::find (currentlyHoveredViews.begin (), currentlyHoveredViews.end (), componentView) ==
@@ -673,16 +661,12 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
673
661
m_context, componentView.Tag (), pointerPoint, keyModifiers);
674
662
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(componentView)
675
663
->OnPointerEntered (args);
676
-
677
664
if (shouldEmitEvent) {
678
665
const auto eventEmitter =
679
666
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(componentView)
680
667
->eventEmitter ();
681
- if (eventEmitter) {
682
- eventEmitter->onPointerEnter (event);
683
- if (IsMousePointerEvent (event)) {
684
- eventEmitter->onMouseEnter (event);
685
- }
668
+ if (eventEmitter && IsMousePointerEvent (event)) {
669
+ eventEmitter->onMouseEnter (event);
686
670
}
687
671
}
688
672
}
@@ -695,41 +679,25 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
695
679
// Call the underlaying pointer handler
696
680
handler (eventPathViews);
697
681
698
- // Out
699
- if (previousTargetTag != -1 && previousTargetTag != (targetView ? targetView.Tag () : -1 )) {
700
- bool shouldEmitOutEvent =
701
- IsAnyViewInPathListeningToEvent (currentlyHoveredViews, facebook::react::ViewEvents::Offset::PointerOut);
702
- const auto eventEmitter =
703
- winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(prevTargetView)->eventEmitter ();
704
- if (shouldEmitOutEvent && eventEmitter != nullptr ) {
705
- eventEmitter->onPointerOut (event);
706
- }
707
- }
708
-
709
682
// Leaving
710
683
711
684
// pointerleave events need to be emitted from the deepest target to the root but
712
685
// we also need to efficiently keep track of if a view has a parent which is listening to the leave events,
713
686
// so we first iterate from the root to the target, collecting the views which need events fired for, of which
714
687
// we reverse iterate (now from target to root), actually emitting the events.
715
- std::vector<winrt::Microsoft::ReactNative::ComponentView>
716
- viewsToEmitJSLeaveEventsTo; // NSMutableOrderedSet<UIView *> *viewsToEmitLeaveEventsTo =
717
- // [NSMutableOrderedSet orderedSet];
688
+ std::vector<winrt::Microsoft::ReactNative::ComponentView> viewsToEmitJSLeaveEventsTo;
718
689
719
690
std::vector<winrt::Microsoft::ReactNative::ComponentView> viewsToEmitLeaveEventsTo;
720
691
721
692
winrt::Microsoft::ReactNative::ComponentView viewToEmitNativeExitedEvent{nullptr };
722
693
723
694
bool hasParentLeaveListener = false ;
724
695
for (auto itComponentView = currentlyHoveredViews.rbegin (); itComponentView != currentlyHoveredViews.rend ();
725
- itComponentView++) { // for (RCTReactTaggedView *taggedView in [currentlyHoveredViews
726
- // reverseObjectEnumerator])
727
- // {
696
+ itComponentView++) {
728
697
auto componentView = *itComponentView;
729
698
730
699
bool shouldEmitJSEvent = componentView != nullptr &&
731
700
(hasParentLeaveListener ||
732
- IsViewListeningToEvent (componentView, facebook::react::ViewEvents::Offset::PointerLeave) ||
733
701
IsViewListeningToEvent (componentView, facebook::react::WindowsViewEvents::Offset::MouseLeave));
734
702
735
703
if (std::find (eventPathViews.begin (), eventPathViews.end (), componentView) == eventPathViews.end ()) {
@@ -754,17 +722,13 @@ void CompositionEventHandler::HandleIncomingPointerEvent(
754
722
}
755
723
756
724
for (auto itComponentView = viewsToEmitJSLeaveEventsTo.rbegin (); itComponentView != viewsToEmitJSLeaveEventsTo.rend ();
757
- itComponentView++) { // for (UIView *componentView in [viewsToEmitJSLeaveEventsTo
758
- // reverseObjectEnumerator]) {
725
+ itComponentView++) {
759
726
auto componentView = *itComponentView;
760
727
761
728
const auto eventEmitter =
762
729
winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(componentView)->eventEmitter ();
763
- if (eventEmitter) {
764
- eventEmitter->onPointerLeave (event);
765
- if (IsMousePointerEvent (event)) {
766
- eventEmitter->onMouseLeave (event);
767
- }
730
+ if (eventEmitter && IsMousePointerEvent (event)) {
731
+ eventEmitter->onMouseLeave (event);
768
732
}
769
733
}
770
734
@@ -1063,19 +1027,17 @@ void CompositionEventHandler::onPointerMoved(
1063
1027
auto activeTouch = m_activeTouches.find (pointerId);
1064
1028
bool isActiveTouch = activeTouch != m_activeTouches.end () && activeTouch->second .eventEmitter != nullptr ;
1065
1029
1066
- auto handler = [&targetView, & pointerEvent, isActiveTouch](
1030
+ auto handler = [&, targetView, pointerEvent, isActiveTouch](
1067
1031
std::vector<winrt::Microsoft::ReactNative::ComponentView> &eventPathViews) {
1068
1032
const auto eventEmitter = targetView
1069
1033
? winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(targetView)
1070
1034
->eventEmitterAtPoint (pointerEvent.offsetPoint )
1071
- : nullptr ;
1072
- bool hasMoveEventListeners = isActiveTouch ||
1073
- IsAnyViewInPathListeningToEvent (eventPathViews, facebook::react::ViewEvents::Offset::PointerMove) ||
1074
- IsAnyViewInPathListeningToEvent (eventPathViews, facebook::react::ViewEvents::Offset::PointerMoveCapture);
1035
+ : RootComponentView ().eventEmitterAtPoint (pointerEvent.offsetPoint );
1075
1036
1076
- if (eventEmitter != nullptr && hasMoveEventListeners) {
1077
- // Add logging before dispatching the event
1037
+ if (eventEmitter != nullptr ) {
1078
1038
eventEmitter->onPointerMove (pointerEvent);
1039
+ } else {
1040
+ ClearAllHoveredForPointer (pointerEvent);
1079
1041
}
1080
1042
};
1081
1043
@@ -1089,6 +1051,23 @@ void CompositionEventHandler::onPointerMoved(
1089
1051
}
1090
1052
}
1091
1053
1054
+ void CompositionEventHandler::ClearAllHoveredForPointer (const facebook::react::PointerEvent &pointerEvent) noexcept {
1055
+ // special case if we have no target
1056
+ // PointerEventsProcessor requires move events to keep track of the hovered components in core.
1057
+ // It also treats a onPointerLeave event as a special case that removes the hover state of all currently hovered
1058
+ // events. If we get null for the targetView, that means that the mouse is no over any components, so we have no
1059
+ // element to send the move event to. However we need to send something so that any previously hovered elements
1060
+ // are no longer hovered.
1061
+ auto children = RootComponentView ().Children ();
1062
+ if (auto size = children.Size ()) {
1063
+ auto firstChild = children.GetAt (0 );
1064
+ if (auto childEventEmitter =
1065
+ winrt::get_self<winrt::Microsoft::ReactNative::implementation::ComponentView>(firstChild)->eventEmitter ()) {
1066
+ childEventEmitter->onPointerLeave (pointerEvent);
1067
+ }
1068
+ }
1069
+ }
1070
+
1092
1071
void CompositionEventHandler::onPointerExited (
1093
1072
const winrt::Microsoft::ReactNative::Composition::Input::PointerPoint &pointerPoint,
1094
1073
winrt::Windows::System::VirtualKeyModifiers keyModifiers) noexcept {
@@ -1111,7 +1090,9 @@ void CompositionEventHandler::onPointerExited(
1111
1090
1112
1091
facebook::react::PointerEvent pointerEvent = CreatePointerEventFromIncompleteHoverData (ptScaled, ptLocal);
1113
1092
1114
- auto handler = [](std::vector<winrt::Microsoft::ReactNative::ComponentView> &eventPathViews) {};
1093
+ auto handler = [&](std::vector<winrt::Microsoft::ReactNative::ComponentView> &eventPathViews) {
1094
+ ClearAllHoveredForPointer (pointerEvent);
1095
+ };
1115
1096
1116
1097
HandleIncomingPointerEvent (pointerEvent, nullptr , pointerPoint, keyModifiers, handler);
1117
1098
}
0 commit comments