Skip to content

Commit

Permalink
Add explicit support for Apple Pencil hovering
Browse files Browse the repository at this point in the history
Summary:
Changelog: [IOS][ADDED] - Add explicit support for M2 iPad Apple Pencil hovering in the Pointer Events implementation

I personally am not a huge fan of how this has to be implemented but it's literally the way Apple suggests to differentiate between mouse and pen hover events.

Reviewed By: lunaleaps

Differential Revision: D40962916

fbshipit-source-id: a6fb5bcfe19bcf500021922baac3fa7c4375a874
  • Loading branch information
vincentriemer authored and facebook-github-bot committed Jan 18, 2023
1 parent 05ff52b commit 0c150b2
Showing 1 changed file with 41 additions and 16 deletions.
57 changes: 41 additions & 16 deletions React/Fabric/RCTSurfaceTouchHandler.mm
Original file line number Diff line number Diff line change
Expand Up @@ -374,18 +374,17 @@ static PointerEvent CreatePointerEventFromActiveTouch(ActiveTouch activeTouch, R
}

static PointerEvent CreatePointerEventFromIncompleteHoverData(
int pointerId,
std::string pointerType,
CGPoint clientLocation,
CGPoint screenLocation,
CGPoint offsetLocation,
UIKeyModifierFlags modifierFlags)
{
PointerEvent event = {};
// "touch" events produced from a mouse cursor on iOS always have the ID 0 so
// we can just assume that here since these sort of hover events only ever come
// from the mouse
event.pointerId = kMousePointerId;
event.pointerId = pointerId;
event.pressure = 0.0;
event.pointerType = "mouse";
event.pointerType = pointerType;
event.clientPoint = RCTPointFromCGPoint(clientLocation);
event.screenPoint = RCTPointFromCGPoint(screenLocation);
event.offsetPoint = RCTPointFromCGPoint(offsetLocation);
Expand Down Expand Up @@ -473,7 +472,9 @@ @implementation RCTSurfaceTouchHandler {
__weak UIView *_rootComponentView;
IdentifierPool<11> _identifierPool;

UIHoverGestureRecognizer *_hoverRecognizer API_AVAILABLE(ios(13.0));
UIHoverGestureRecognizer *_mouseHoverRecognizer API_AVAILABLE(ios(13.0));
UIHoverGestureRecognizer *_penHoverRecognizer API_AVAILABLE(ios(13.0));

NSMutableDictionary<NSNumber *, NSOrderedSet<RCTReactTaggedView *> *> *_currentlyHoveredViewsPerPointer;

int _primaryTouchPointerId;
Expand All @@ -492,7 +493,9 @@ - (instancetype)init

self.delegate = self;

_hoverRecognizer = nil;
_mouseHoverRecognizer = nil;
_penHoverRecognizer = nil;

_currentlyHoveredViewsPerPointer = [[NSMutableDictionary alloc] init];
_primaryTouchPointerId = -1;
}
Expand All @@ -510,9 +513,14 @@ - (void)attachToView:(UIView *)view
_rootComponentView = view;

if (RCTGetDispatchW3CPointerEvents()) {
if (@available(iOS 13.0, *)) {
_hoverRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(hovering:)];
[view addGestureRecognizer:_hoverRecognizer];
if (@available(iOS 13.4, *)) {
_mouseHoverRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(mouseHovering:)];
_mouseHoverRecognizer.allowedTouchTypes = @[ @(UITouchTypeIndirectPointer) ];
[view addGestureRecognizer:_mouseHoverRecognizer];

_penHoverRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(penHovering:)];
_penHoverRecognizer.allowedTouchTypes = @[ @(UITouchTypePencil) ];
[view addGestureRecognizer:_penHoverRecognizer];
}
}
}
Expand All @@ -525,9 +533,14 @@ - (void)detachFromView:(UIView *)view
[view removeGestureRecognizer:self];
_rootComponentView = nil;

if (_hoverRecognizer != nil) {
[view removeGestureRecognizer:_hoverRecognizer];
_hoverRecognizer = nil;
if (_mouseHoverRecognizer != nil) {
[view removeGestureRecognizer:_mouseHoverRecognizer];
_mouseHoverRecognizer = nil;
}

if (_penHoverRecognizer != nil) {
[view removeGestureRecognizer:_penHoverRecognizer];
_penHoverRecognizer = nil;
}
}

Expand Down Expand Up @@ -845,7 +858,19 @@ - (void)_cancelTouches
[self setEnabled:YES];
}

- (void)hovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.0))
- (void)penHovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.0))
{
[self hovering:recognizer pointerId:kPencilPointerId pointerType:"pen"];
}

- (void)mouseHovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.0))
{
[self hovering:recognizer pointerId:kMousePointerId pointerType:"mouse"];
}

- (void)hovering:(UIHoverGestureRecognizer *)recognizer
pointerId:(int)pointerId
pointerType:(std::string)pointerType API_AVAILABLE(ios(13.0))
{
UIView *listenerView = recognizer.view;
CGPoint clientLocation = [recognizer locationInView:listenerView];
Expand All @@ -864,8 +889,8 @@ - (void)hovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.0))
modifierFlags = 0;
}

PointerEvent event =
CreatePointerEventFromIncompleteHoverData(clientLocation, screenLocation, offsetLocation, modifierFlags);
PointerEvent event = CreatePointerEventFromIncompleteHoverData(
pointerId, pointerType, clientLocation, screenLocation, offsetLocation, modifierFlags);

NSOrderedSet<RCTReactTaggedView *> *eventPathViews = [self handleIncomingPointerEvent:event onView:targetView];
SharedTouchEventEmitter eventEmitter = GetTouchEmitterFromView(targetView, offsetLocation);
Expand Down

0 comments on commit 0c150b2

Please sign in to comment.