diff --git a/change/react-native-windows-touch-primary-button-main.json b/change/react-native-windows-touch-primary-button-main.json new file mode 100644 index 00000000000..b8567189afb --- /dev/null +++ b/change/react-native-windows-touch-primary-button-main.json @@ -0,0 +1,7 @@ +{ + "type": "prerelease", + "comment": "Fix(fabric): dispatch touch/pen contacts with the W3C primary button (button 0, buttons 1) instead of button -1 / buttons 0, so pointer-event-driven press handling responds to finger taps the same as mouse left-clicks", + "packageName": "react-native-windows", + "email": "collindanielschneide@gmail.com", + "dependentChangeType": "patch" +} diff --git a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp index dda0804692d..5998592c5a7 100644 --- a/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp +++ b/vnext/Microsoft.ReactNative/Fabric/Composition/CompositionEventHandler.cpp @@ -1413,6 +1413,16 @@ void CompositionEventHandler::onPointerPressed( break; } + // A touch (or pen) contact has no mouse PointerUpdateKind, so it fell + // through to button = -1 — and the derived W3C buttons bitmask became 0. + // The dispatched pointerdown therefore told JS "no button is pressed", so + // press machinery driven by pointer events ignored finger taps while + // identical mouse clicks (button 0 / buttons 1) worked. Per W3C + // pointer-event semantics a touch/pen contact IS the primary button. + if (pointerPoint.PointerDeviceType() != Composition::Input::PointerDeviceType::Mouse && activeTouch.button < 0) { + activeTouch.button = 0; + } + while (targetComponentView) { if (auto eventEmitter = winrt::get_self(targetComponentView)