Skip to content

Commit

Permalink
Add implementation of buttons property to PointerEvent interface
Browse files Browse the repository at this point in the history
Summary:
Changelog: [iOS][Internal] - Add `buttons` implementation to the PointerEvent interface

This diff adds an implementation of the `buttons` property by leveraging `UIEvent`'s `buttonMask` property.

Reviewed By: lunaleaps

Differential Revision: D37430270

fbshipit-source-id: 69fd3aebcb403e665349a24283a04c0eb82ff3e2
  • Loading branch information
vincentriemer authored and facebook-github-bot committed Jul 8, 2022
1 parent ff6c906 commit e89874c
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 12 deletions.
53 changes: 41 additions & 12 deletions React/Fabric/RCTSurfaceTouchHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ typedef NS_ENUM(NSInteger, RCTTouchEventType) {
*/
CGFloat azimuthAngle;

/*
* The button mask of the touch
*/
UIEventButtonMask buttonMask;

/*
* A component view on which the touch was begun.
*/
Expand Down Expand Up @@ -134,9 +139,19 @@ static CGFloat RadsToDegrees(CGFloat rads)
return rads * 180 / M_PI;
}

static int ButtonMaskToButtons(UIEventButtonMask buttonMask)
{
if (@available(iOS 13.4, *)) {
return (((buttonMask & UIEventButtonMaskPrimary) > 0) ? 1 : 0) |
(((buttonMask & UIEventButtonMaskSecondary) > 0) ? 2 : 0);
}
return 0;
}

static void UpdateActiveTouchWithUITouch(
ActiveTouch &activeTouch,
UITouch *uiTouch,
UIEvent *uiEvent,
UIView *rootComponentView,
CGPoint rootViewOriginOffset)
{
Expand All @@ -159,9 +174,15 @@ static void UpdateActiveTouchWithUITouch(
activeTouch.majorRadius = uiTouch.majorRadius;
activeTouch.altitudeAngle = uiTouch.altitudeAngle;
activeTouch.azimuthAngle = [uiTouch azimuthAngleInView:nil];
if (@available(iOS 13.4, *)) {
activeTouch.buttonMask = uiEvent.buttonMask;
} else {
activeTouch.buttonMask = 0;
}
}

static ActiveTouch CreateTouchWithUITouch(UITouch *uiTouch, UIView *rootComponentView, CGPoint rootViewOriginOffset)
static ActiveTouch
CreateTouchWithUITouch(UITouch *uiTouch, UIEvent *uiEvent, UIView *rootComponentView, CGPoint rootViewOriginOffset)
{
ActiveTouch activeTouch = {};

Expand All @@ -178,7 +199,7 @@ static ActiveTouch CreateTouchWithUITouch(UITouch *uiTouch, UIView *rootComponen
componentView = componentView.superview;
}

UpdateActiveTouchWithUITouch(activeTouch, uiTouch, rootComponentView, rootViewOriginOffset);
UpdateActiveTouchWithUITouch(activeTouch, uiTouch, uiEvent, rootComponentView, rootViewOriginOffset);
return activeTouch;
}

Expand Down Expand Up @@ -225,7 +246,7 @@ static SharedTouchEventEmitter GetTouchEmitterFromView(UIView *componentView, CG
}
}

static PointerEvent CreatePointerEventFromActiveTouch(ActiveTouch activeTouch)
static PointerEvent CreatePointerEventFromActiveTouch(ActiveTouch activeTouch, RCTTouchEventType eventType)
{
Touch touch = activeTouch.touch;

Expand All @@ -251,6 +272,13 @@ static PointerEvent CreatePointerEventFromActiveTouch(ActiveTouch activeTouch)

event.detail = 0;

event.buttons = ButtonMaskToButtons(activeTouch.buttonMask);
// UIEvent's button mask for touch end events still marks the button as down
// so this ensures it's set to 0 as per the pointer event spec
if (eventType == RCTTouchEventTypeTouchEnd) {
event.buttons = 0;
}

return event;
}

Expand All @@ -270,6 +298,7 @@ static PointerEvent CreatePointerEventFromActiveTouch(ActiveTouch activeTouch)
event.tiltX = 0;
event.tiltY = 0;
event.detail = 0;
event.buttons = 0;
return event;
}

Expand Down Expand Up @@ -396,16 +425,16 @@ - (void)detachFromView:(UIView *)view
}
}

- (void)_registerTouches:(NSSet<UITouch *> *)touches
- (void)_registerTouches:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
auto activeTouch = CreateTouchWithUITouch(touch, _rootComponentView, _viewOriginOffset);
auto activeTouch = CreateTouchWithUITouch(touch, event, _rootComponentView, _viewOriginOffset);
activeTouch.touch.identifier = _identifierPool.dequeue();
_activeTouches.emplace(touch, activeTouch);
}
}

- (void)_updateTouches:(NSSet<UITouch *> *)touches
- (void)_updateTouches:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches) {
auto iterator = _activeTouches.find(touch);
Expand All @@ -414,7 +443,7 @@ - (void)_updateTouches:(NSSet<UITouch *> *)touches
continue;
}

UpdateActiveTouchWithUITouch(iterator->second, touch, _rootComponentView, _viewOriginOffset);
UpdateActiveTouchWithUITouch(iterator->second, touch, event, _rootComponentView, _viewOriginOffset);
}
}

Expand Down Expand Up @@ -467,7 +496,7 @@ - (void)_dispatchActiveTouches:(std::vector<ActiveTouch>)activeTouches eventType

// emit w3c pointer events
if (RCTGetDispatchW3CPointerEvents()) {
PointerEvent pointerEvent = CreatePointerEventFromActiveTouch(activeTouch);
PointerEvent pointerEvent = CreatePointerEventFromActiveTouch(activeTouch, eventType);
switch (eventType) {
case RCTTouchEventTypeTouchStart:
activeTouch.eventEmitter->onPointerDown(pointerEvent);
Expand Down Expand Up @@ -529,7 +558,7 @@ - (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesBegan:touches withEvent:event];

[self _registerTouches:touches];
[self _registerTouches:touches withEvent:event];
[self _dispatchActiveTouches:[self _activeTouchesFromTouches:touches] eventType:RCTTouchEventTypeTouchStart];

if (self.state == UIGestureRecognizerStatePossible) {
Expand All @@ -543,7 +572,7 @@ - (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];

[self _updateTouches:touches];
[self _updateTouches:touches withEvent:event];
[self _dispatchActiveTouches:[self _activeTouchesFromTouches:touches] eventType:RCTTouchEventTypeTouchMove];

self.state = UIGestureRecognizerStateChanged;
Expand All @@ -553,7 +582,7 @@ - (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesEnded:touches withEvent:event];

[self _updateTouches:touches];
[self _updateTouches:touches withEvent:event];
[self _dispatchActiveTouches:[self _activeTouchesFromTouches:touches] eventType:RCTTouchEventTypeTouchEnd];
[self _unregisterTouches:touches];

Expand All @@ -568,7 +597,7 @@ - (void)touchesCancelled:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];

[self _updateTouches:touches];
[self _updateTouches:touches withEvent:event];
[self _dispatchActiveTouches:[self _activeTouchesFromTouches:touches] eventType:RCTTouchEventTypeTouchCancel];
[self _unregisterTouches:touches];

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ std::vector<DebugStringConvertibleObject> getDebugProps(
{"tiltX", getDebugDescription(pointerEvent.tiltX, options)},
{"tiltY", getDebugDescription(pointerEvent.tiltY, options)},
{"detail", getDebugDescription(pointerEvent.detail, options)},
{"buttons", getDebugDescription(pointerEvent.buttons, options)},
};
}

Expand Down
4 changes: 4 additions & 0 deletions ReactCommon/react/renderer/components/view/PointerEvent.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ struct PointerEvent {
* Returns a long with details about the event, depending on the event type.
*/
int detail;
/*
* The buttons being depressed (if any) when the mouse event was fired.
*/
int buttons;
};

#if RN_DEBUG_STRING_CONVERTIBLE
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ static jsi::Value pointerEventPayload(
object.setProperty(runtime, "tiltX", event.tiltX);
object.setProperty(runtime, "tiltY", event.tiltY);
object.setProperty(runtime, "detail", event.detail);
object.setProperty(runtime, "buttons", event.buttons);
return object;
}

Expand Down

0 comments on commit e89874c

Please sign in to comment.