From 92e4ed6a28a9a78832e2173fbdfae103c695c325 Mon Sep 17 00:00:00 2001 From: Vincent Riemer Date: Mon, 15 Aug 2022 12:00:15 -0700 Subject: [PATCH] Add iOS implementation of the button property of the PointerEvent object Summary: Changelog: [iOS][Internal] - Add iOS implementation of the button property of the PointerEvent object This implements the `button` property on the PointerEvent object by storing the button which caused the down event in the `ActiveTouch` and reporting that button through `pointerdown` and `pointerup` events and -1 on all others. This diff also includes a small fix to the `pressure` property which was introduced due to `button` being correctly implemented. Reviewed By: yungsters Differential Revision: D38632543 fbshipit-source-id: 9dbbb23a9251f2e661faf37fdf206b9f0b26bc5f --- React/Fabric/RCTSurfaceTouchHandler.mm | 37 ++++++++++++++++++- .../renderer/components/view/PointerEvent.cpp | 1 + .../renderer/components/view/PointerEvent.h | 5 +++ .../components/view/TouchEventEmitter.cpp | 1 + 4 files changed, 43 insertions(+), 1 deletion(-) diff --git a/React/Fabric/RCTSurfaceTouchHandler.mm b/React/Fabric/RCTSurfaceTouchHandler.mm index 65371954e6..3891ff8ad7 100644 --- a/React/Fabric/RCTSurfaceTouchHandler.mm +++ b/React/Fabric/RCTSurfaceTouchHandler.mm @@ -94,6 +94,11 @@ struct ActiveTouch { */ bool isPrimary; + /* + * The button number that was pressed (if applicable) when the event was fired. + */ + int button; + /* * A component view on which the touch was begun. */ @@ -168,6 +173,16 @@ static int ButtonMaskToButtons(UIEventButtonMask buttonMask) return 0; } +static int ButtonMaskToButton(UIEventButtonMask buttonMask) +{ + if (@available(iOS 13.4, *)) { + if ((buttonMask & UIEventButtonMaskSecondary) > 0) { + return 2; + } + } + return 0; +} + static void UpdateActiveTouchWithUITouch( ActiveTouch &activeTouch, UITouch *uiTouch, @@ -291,12 +306,20 @@ static PointerEvent CreatePointerEventFromActiveTouch(ActiveTouch activeTouch, R PointerEvent event = {}; event.pointerId = touch.identifier; - event.pressure = touch.force; event.pointerType = PointerTypeCStringFromUITouchType(activeTouch.touchType); event.clientPoint = touch.pagePoint; event.screenPoint = touch.screenPoint; event.offsetPoint = touch.offsetPoint; + event.pressure = touch.force; + if (@available(iOS 13.4, *)) { + if (activeTouch.touchType == UITouchTypeIndirectPointer) { + // pointer events with a mouse button pressed should report a pressure of 0.5 + // when the touch is down and 0.0 when it is lifted regardless of how it is reported by the OS + event.pressure = eventType != RCTTouchEventTypeTouchEnd ? 0.5 : 0.0; + } + } + CGFloat pointerSize = activeTouch.majorRadius * 2.0; if (@available(iOS 13.4, *)) { if (activeTouch.touchType == UITouchTypeIndirectPointer) { @@ -313,6 +336,11 @@ static PointerEvent CreatePointerEventFromActiveTouch(ActiveTouch activeTouch, R event.detail = 0; + event.button = -1; + if (eventType == RCTTouchEventTypeTouchStart || eventType == RCTTouchEventTypeTouchEnd) { + event.button = activeTouch.button; + } + event.buttons = ButtonMaskToButtons(activeTouch.buttonMask); UpdatePointerEventModifierFlags(event, activeTouch.modifierFlags); @@ -351,11 +379,13 @@ static PointerEvent CreatePointerEventFromIncompleteHoverData( event.tiltX = 0; event.tiltY = 0; event.detail = 0; + event.button = -1; event.buttons = 0; UpdatePointerEventModifierFlags(event, modifierFlags); event.tangentialPressure = 0.0; event.twist = 0; event.isPrimary = true; + return event; } @@ -511,13 +541,18 @@ RCT_NOT_IMPLEMENTED(-(instancetype)initWithTarget : (id)target action : (SEL)act } break; } + + activeTouch.button = ButtonMaskToButton(event.buttonMask); } else { activeTouch.touch.identifier = _identifierPool.dequeue(); if (_primaryTouchPointerId == -1) { _primaryTouchPointerId = activeTouch.touch.identifier; activeTouch.isPrimary = true; } + + activeTouch.button = 0; } + _activeTouches.emplace(touch, activeTouch); } } diff --git a/ReactCommon/react/renderer/components/view/PointerEvent.cpp b/ReactCommon/react/renderer/components/view/PointerEvent.cpp index 7c5c1869dc..842c8a4408 100644 --- a/ReactCommon/react/renderer/components/view/PointerEvent.cpp +++ b/ReactCommon/react/renderer/components/view/PointerEvent.cpp @@ -40,6 +40,7 @@ std::vector getDebugProps( {"altKey", getDebugDescription(pointerEvent.altKey, options)}, {"metaKey", getDebugDescription(pointerEvent.metaKey, options)}, {"isPrimary", getDebugDescription(pointerEvent.isPrimary, options)}, + {"button", getDebugDescription(pointerEvent.button, options)}, }; } diff --git a/ReactCommon/react/renderer/components/view/PointerEvent.h b/ReactCommon/react/renderer/components/view/PointerEvent.h index 4812e55b33..bc724c54e9 100644 --- a/ReactCommon/react/renderer/components/view/PointerEvent.h +++ b/ReactCommon/react/renderer/components/view/PointerEvent.h @@ -105,6 +105,11 @@ struct PointerEvent { * type. */ bool isPrimary; + /* + * The button number that was pressed (if applicable) when the pointer event + * was fired. + */ + int button; }; #if RN_DEBUG_STRING_CONVERTIBLE diff --git a/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp b/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp index 5d5b17f28b..5d78c63315 100644 --- a/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp +++ b/ReactCommon/react/renderer/components/view/TouchEventEmitter.cpp @@ -92,6 +92,7 @@ static jsi::Value pointerEventPayload( object.setProperty(runtime, "altKey", event.altKey); object.setProperty(runtime, "metaKey", event.metaKey); object.setProperty(runtime, "isPrimary", event.isPrimary); + object.setProperty(runtime, "button", event.button); return object; }