Skip to content

Commit 0c150b2

Browse files
vincentriemerfacebook-github-bot
authored andcommitted
Add explicit support for Apple Pencil hovering
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
1 parent 05ff52b commit 0c150b2

File tree

1 file changed

+41
-16
lines changed

1 file changed

+41
-16
lines changed

React/Fabric/RCTSurfaceTouchHandler.mm

+41-16
Original file line numberDiff line numberDiff line change
@@ -374,18 +374,17 @@ static PointerEvent CreatePointerEventFromActiveTouch(ActiveTouch activeTouch, R
374374
}
375375

376376
static PointerEvent CreatePointerEventFromIncompleteHoverData(
377+
int pointerId,
378+
std::string pointerType,
377379
CGPoint clientLocation,
378380
CGPoint screenLocation,
379381
CGPoint offsetLocation,
380382
UIKeyModifierFlags modifierFlags)
381383
{
382384
PointerEvent event = {};
383-
// "touch" events produced from a mouse cursor on iOS always have the ID 0 so
384-
// we can just assume that here since these sort of hover events only ever come
385-
// from the mouse
386-
event.pointerId = kMousePointerId;
385+
event.pointerId = pointerId;
387386
event.pressure = 0.0;
388-
event.pointerType = "mouse";
387+
event.pointerType = pointerType;
389388
event.clientPoint = RCTPointFromCGPoint(clientLocation);
390389
event.screenPoint = RCTPointFromCGPoint(screenLocation);
391390
event.offsetPoint = RCTPointFromCGPoint(offsetLocation);
@@ -473,7 +472,9 @@ @implementation RCTSurfaceTouchHandler {
473472
__weak UIView *_rootComponentView;
474473
IdentifierPool<11> _identifierPool;
475474

476-
UIHoverGestureRecognizer *_hoverRecognizer API_AVAILABLE(ios(13.0));
475+
UIHoverGestureRecognizer *_mouseHoverRecognizer API_AVAILABLE(ios(13.0));
476+
UIHoverGestureRecognizer *_penHoverRecognizer API_AVAILABLE(ios(13.0));
477+
477478
NSMutableDictionary<NSNumber *, NSOrderedSet<RCTReactTaggedView *> *> *_currentlyHoveredViewsPerPointer;
478479

479480
int _primaryTouchPointerId;
@@ -492,7 +493,9 @@ - (instancetype)init
492493

493494
self.delegate = self;
494495

495-
_hoverRecognizer = nil;
496+
_mouseHoverRecognizer = nil;
497+
_penHoverRecognizer = nil;
498+
496499
_currentlyHoveredViewsPerPointer = [[NSMutableDictionary alloc] init];
497500
_primaryTouchPointerId = -1;
498501
}
@@ -510,9 +513,14 @@ - (void)attachToView:(UIView *)view
510513
_rootComponentView = view;
511514

512515
if (RCTGetDispatchW3CPointerEvents()) {
513-
if (@available(iOS 13.0, *)) {
514-
_hoverRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(hovering:)];
515-
[view addGestureRecognizer:_hoverRecognizer];
516+
if (@available(iOS 13.4, *)) {
517+
_mouseHoverRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(mouseHovering:)];
518+
_mouseHoverRecognizer.allowedTouchTypes = @[ @(UITouchTypeIndirectPointer) ];
519+
[view addGestureRecognizer:_mouseHoverRecognizer];
520+
521+
_penHoverRecognizer = [[UIHoverGestureRecognizer alloc] initWithTarget:self action:@selector(penHovering:)];
522+
_penHoverRecognizer.allowedTouchTypes = @[ @(UITouchTypePencil) ];
523+
[view addGestureRecognizer:_penHoverRecognizer];
516524
}
517525
}
518526
}
@@ -525,9 +533,14 @@ - (void)detachFromView:(UIView *)view
525533
[view removeGestureRecognizer:self];
526534
_rootComponentView = nil;
527535

528-
if (_hoverRecognizer != nil) {
529-
[view removeGestureRecognizer:_hoverRecognizer];
530-
_hoverRecognizer = nil;
536+
if (_mouseHoverRecognizer != nil) {
537+
[view removeGestureRecognizer:_mouseHoverRecognizer];
538+
_mouseHoverRecognizer = nil;
539+
}
540+
541+
if (_penHoverRecognizer != nil) {
542+
[view removeGestureRecognizer:_penHoverRecognizer];
543+
_penHoverRecognizer = nil;
531544
}
532545
}
533546

@@ -845,7 +858,19 @@ - (void)_cancelTouches
845858
[self setEnabled:YES];
846859
}
847860

848-
- (void)hovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.0))
861+
- (void)penHovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.0))
862+
{
863+
[self hovering:recognizer pointerId:kPencilPointerId pointerType:"pen"];
864+
}
865+
866+
- (void)mouseHovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.0))
867+
{
868+
[self hovering:recognizer pointerId:kMousePointerId pointerType:"mouse"];
869+
}
870+
871+
- (void)hovering:(UIHoverGestureRecognizer *)recognizer
872+
pointerId:(int)pointerId
873+
pointerType:(std::string)pointerType API_AVAILABLE(ios(13.0))
849874
{
850875
UIView *listenerView = recognizer.view;
851876
CGPoint clientLocation = [recognizer locationInView:listenerView];
@@ -864,8 +889,8 @@ - (void)hovering:(UIHoverGestureRecognizer *)recognizer API_AVAILABLE(ios(13.0))
864889
modifierFlags = 0;
865890
}
866891

867-
PointerEvent event =
868-
CreatePointerEventFromIncompleteHoverData(clientLocation, screenLocation, offsetLocation, modifierFlags);
892+
PointerEvent event = CreatePointerEventFromIncompleteHoverData(
893+
pointerId, pointerType, clientLocation, screenLocation, offsetLocation, modifierFlags);
869894

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

0 commit comments

Comments
 (0)