diff --git a/change/react-native-windows-39944bb5-d21b-45da-b750-d01f32e77200.json b/change/react-native-windows-39944bb5-d21b-45da-b750-d01f32e77200.json new file mode 100644 index 00000000000..f4abc90a495 --- /dev/null +++ b/change/react-native-windows-39944bb5-d21b-45da-b750-d01f32e77200.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Fix: Text component pressRetentionOffset issue on Windows", + "packageName": "react-native-windows", + "email": "abhijeetjha@microsoft.com", + "dependentChangeType": "none" +} diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp index e7d646f6bff..aafd46e25e5 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp @@ -1059,21 +1059,33 @@ void CompositionEventHandler::onPointerMoved( facebook::react::PointerEvent pointerEvent = CreatePointerEventFromIncompleteHoverData(ptScaled, ptLocal); - auto handler = [&targetView, - &pointerEvent](std::vector &eventPathViews) { + // check if this pointer corresponds to active touch that has a responder + auto activeTouch = m_activeTouches.find(pointerId); + bool isActiveTouch = activeTouch != m_activeTouches.end() && activeTouch->second.eventEmitter != nullptr; + + auto handler = [&targetView, &pointerEvent, isActiveTouch]( + std::vector &eventPathViews) { const auto eventEmitter = targetView ? winrt::get_self(targetView) ->eventEmitterAtPoint(pointerEvent.offsetPoint) : nullptr; - bool hasMoveEventListeners = + bool hasMoveEventListeners = isActiveTouch || IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMove) || IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMoveCapture); + if (eventEmitter != nullptr && hasMoveEventListeners) { + // Add logging before dispatching the event eventEmitter->onPointerMove(pointerEvent); } }; HandleIncomingPointerEvent(pointerEvent, targetView, pointerPoint, keyModifiers, handler); + + if (isActiveTouch) { + // For active touches with responders, also dispatch through touch event system + UpdateActiveTouch(activeTouch->second, ptScaled, ptLocal); + DispatchTouchEvent(TouchEventType::Move, pointerId, pointerPoint, keyModifiers); + } } } @@ -1387,12 +1399,7 @@ void CompositionEventHandler::DispatchTouchEvent( activeTouch.eventEmitter->onPointerDown(pointerEvent); break; case TouchEventType::Move: { - bool hasMoveEventListeners = - IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMove) || - IsAnyViewInPathListeningToEvent(eventPathViews, facebook::react::ViewEvents::Offset::PointerMoveCapture); - if (hasMoveEventListeners) { - activeTouch.eventEmitter->onPointerMove(pointerEvent); - } + activeTouch.eventEmitter->onPointerMove(pointerEvent); break; } case TouchEventType::End: diff --git a/vnext/src-win/Libraries/Text/Text.d.ts b/vnext/src-win/Libraries/Text/Text.d.ts index 89be47a0f5c..a800be38b57 100644 --- a/vnext/src-win/Libraries/Text/Text.d.ts +++ b/vnext/src-win/Libraries/Text/Text.d.ts @@ -224,6 +224,14 @@ export interface TextProps * Controls how touch events are handled. Similar to `View`'s `pointerEvents`. */ pointerEvents?: ViewStyle['pointerEvents'] | undefined; + + /** + * Insets for press retention. + * Example: { top: 20, left: 20, bottom: 20, right: 20 } + */ + pressRetentionOffset?: + | {top: number; left: number; bottom: number; right: number} + | undefined; } /**