Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,15 +1,27 @@
package com.swmansion.gesturehandler.react.events.eventbuilders

import com.facebook.react.bridge.WritableMap
import com.facebook.react.uimanager.PixelUtil
import com.swmansion.gesturehandler.core.NativeViewGestureHandler

class NativeGestureHandlerEventDataBuilder(handler: NativeViewGestureHandler) :
GestureHandlerEventDataBuilder<NativeViewGestureHandler>(handler) {
private val pointerInside: Boolean = handler.isWithinBounds
private val x: Float = handler.lastRelativePositionX
private val y: Float = handler.lastRelativePositionY
private val absoluteX: Float = handler.lastPositionInWindowX
private val absoluteY: Float = handler.lastPositionInWindowY

override fun buildEventData(eventData: WritableMap) {
super.buildEventData(eventData)

eventData.putBoolean("pointerInside", pointerInside)

with(eventData) {
putDouble("x", PixelUtil.toDIPFromPixel(x).toDouble())
putDouble("y", PixelUtil.toDIPFromPixel(y).toDouble())
putDouble("absoluteX", PixelUtil.toDIPFromPixel(absoluteX).toDouble())
putDouble("absoluteY", PixelUtil.toDIPFromPixel(absoluteY).toDouble())
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -197,14 +197,19 @@ - (void)unbindFromView
[super unbindFromView];
}

- (BOOL)shouldSuppressActiveEvent:(RNGestureHandlerEventExtraData *)extraData
- (RNGestureHandlerEventExtraData *)extraDataForView:(UIView *)sender
event:(UIEvent *)event
pointerInside:(BOOL)pointerInside
{
if (_lastActiveExtraData != nil && [_lastActiveExtraData.data isEqualToDictionary:extraData.data]) {
return YES;
}

_lastActiveExtraData = extraData;
return NO;
RNGHUITouch *touch = [[event allTouches] anyObject];
CGPoint position = touch ? [touch locationInView:sender] : CGPointZero;
CGPoint absolutePosition = touch ? [touch locationInView:nil] : [sender convertPoint:CGPointZero toView:nil];

return [RNGestureHandlerEventExtraData forPointerInside:pointerInside
withPosition:position
withAbsolutePosition:absolutePosition
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType];
}

- (void)sendActiveStateEventIfChangedForView:(UIView *)sender extraData:(RNGestureHandlerEventExtraData *)extraData
Expand All @@ -218,21 +223,19 @@ - (void)sendActiveStateEventIfChangedForView:(UIView *)sender extraData:(RNGestu

- (void)handleSwitch:(UIView *)sender
{
[self sendEventsInState:RNGestureHandlerStateBegan
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:1
withPointerType:_pointerType]];
[self sendEventsInState:RNGestureHandlerStateActive
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:1
withPointerType:_pointerType]];
[self sendEventsInState:RNGestureHandlerStateEnd
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:1
withPointerType:_pointerType]];
CGPoint center = CGPointMake(CGRectGetMidX(sender.bounds), CGRectGetMidY(sender.bounds));
CGPoint absoluteCenter = [sender convertPoint:center toView:nil];
RNGestureHandlerEventExtraData * (^extraData)(void) = ^{
return [RNGestureHandlerEventExtraData forPointerInside:YES
withPosition:center
withAbsolutePosition:absoluteCenter
withNumberOfTouches:1
withPointerType:self->_pointerType];
};

[self sendEventsInState:RNGestureHandlerStateBegan forViewWithTag:sender.reactTag withExtraData:extraData()];
[self sendEventsInState:RNGestureHandlerStateActive forViewWithTag:sender.reactTag withExtraData:extraData()];
[self sendEventsInState:RNGestureHandlerStateEnd forViewWithTag:sender.reactTag withExtraData:extraData()];

[self reset];
}
Expand Down Expand Up @@ -262,9 +265,7 @@ - (void)handleTouchDown:(UIView *)sender forEvent:(UIEvent *)event

[self sendEventsInState:RNGestureHandlerStateBegan
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
withExtraData:[self extraDataForView:sender event:event pointerInside:YES]];
}

- (void)handleTouchUpOutside:(UIView *)sender forEvent:(UIEvent *)event
Expand All @@ -275,16 +276,12 @@ - (void)handleTouchUpOutside:(UIView *)sender forEvent:(UIEvent *)event

[self sendEventsInState:RNGestureHandlerStateEnd
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:NO
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
withExtraData:[self extraDataForView:sender event:event pointerInside:NO]];
}

- (void)handleTouchUpInside:(UIView *)sender forEvent:(UIEvent *)event
{
RNGestureHandlerEventExtraData *extraData = [RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType];
RNGestureHandlerEventExtraData *extraData = [self extraDataForView:sender event:event pointerInside:YES];

[self sendActiveStateEventIfChangedForView:sender extraData:extraData];
[self sendEventsInState:RNGestureHandlerStateEnd forViewWithTag:sender.reactTag withExtraData:extraData];
Expand All @@ -298,26 +295,20 @@ - (void)handleDragExit:(UIView *)sender forEvent:(UIEvent *)event
[control cancelTrackingWithEvent:event];
} else {
[self sendActiveStateEventIfChangedForView:sender
extraData:[RNGestureHandlerEventExtraData forPointerInside:NO
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
extraData:[self extraDataForView:sender event:event pointerInside:NO]];
}
}

- (void)handleDragEnter:(UIView *)sender forEvent:(UIEvent *)event
{
[self sendActiveStateEventIfChangedForView:sender
extraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
extraData:[self extraDataForView:sender event:event pointerInside:YES]];
}

- (void)handleDragInside:(UIView *)sender forEvent:(UIEvent *)event
{
[self sendActiveStateEventIfChangedForView:sender
extraData:[RNGestureHandlerEventExtraData forPointerInside:YES
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
extraData:[self extraDataForView:sender event:event pointerInside:YES]];
}

- (void)handleDragOutside:(UIView *)sender forEvent:(UIEvent *)event
Expand All @@ -327,36 +318,61 @@ - (void)handleDragOutside:(UIView *)sender forEvent:(UIEvent *)event
}

[self sendActiveStateEventIfChangedForView:sender
extraData:[RNGestureHandlerEventExtraData forPointerInside:NO
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
extraData:[self extraDataForView:sender event:event pointerInside:NO]];
}

- (void)handleTouchCancel:(UIView *)sender forEvent:(UIEvent *)event
{
[self sendEventsInState:RNGestureHandlerStateCancelled
forViewWithTag:sender.reactTag
withExtraData:[RNGestureHandlerEventExtraData forPointerInside:NO
withNumberOfTouches:event.allTouches.count
withPointerType:_pointerType]];
withExtraData:[self extraDataForView:sender event:event pointerInside:NO]];
}

- (BOOL)wantsToAttachDirectlyToView
{
return YES;
}

#endif

- (void)reset
{
[super reset];
_lastActiveExtraData = nil;
}

#endif
- (BOOL)shouldSuppressActiveEvent:(RNGestureHandlerEventExtraData *)extraData
{
NSDictionary *last = _lastActiveExtraData.data;
NSDictionary *current = extraData.data;

if (last != nil && [last[@"pointerInside"] isEqual:current[@"pointerInside"]] &&
[last[@"numberOfPointers"] isEqual:current[@"numberOfPointers"]] &&
[last[@"pointerType"] isEqual:current[@"pointerType"]]) {
return YES;
}

_lastActiveExtraData = extraData;
return NO;
}

- (RNGestureHandlerEventExtraData *)eventExtraData:(RNDummyGestureRecognizer *)recognizer
{
#if TARGET_OS_OSX
// macOS window coordinates are bottom-left origin; flip Y to match RN's
// top-left origin, mirroring RNGestureHandlerPointerTracker.
CGFloat windowHeight = recognizer.view.window.contentView.frame.size.height;
CGPoint yFlippedAbsolute = [recognizer locationInView:nil];
CGPoint absolutePosition = CGPointMake(yFlippedAbsolute.x, windowHeight - yFlippedAbsolute.y);
CGPoint position = [recognizer.view convertPoint:absolutePosition fromView:recognizer.view.window.contentView];
#else
CGPoint position = [recognizer locationInView:recognizer.view];
CGPoint absolutePosition = [recognizer locationInView:nil];
#endif

return [RNGestureHandlerEventExtraData forPointerInside:[self containsPointInView]
withPosition:position
withAbsolutePosition:absolutePosition
withNumberOfTouches:1
withPointerType:RNGestureHandlerMouse];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
withNumberOfTouches:(NSUInteger)numberOfTouches
withPointerType:(NSInteger)pointerType;
+ (RNGestureHandlerEventExtraData *)forPointerInside:(BOOL)pointerInside
withPosition:(CGPoint)position
withAbsolutePosition:(CGPoint)absolutePosition
withNumberOfTouches:(NSUInteger)numberOfTouches
withPointerType:(NSInteger)pointerType;
Comment thread
m-bert marked this conversation as resolved.
@end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,17 @@ + (RNGestureHandlerEventExtraData *)forEventType:(RNGHTouchEventType)eventType
}

+ (RNGestureHandlerEventExtraData *)forPointerInside:(BOOL)pointerInside
withPosition:(CGPoint)position
withAbsolutePosition:(CGPoint)absolutePosition
withNumberOfTouches:(NSUInteger)numberOfTouches
withPointerType:(NSInteger)pointerType
{
return [[RNGestureHandlerEventExtraData alloc] initWithData:@{
@"pointerInside" : @(pointerInside),
@"x" : @(position.x),
@"y" : @(position.y),
@"absoluteX" : @(absolutePosition.x),
@"absoluteY" : @(absolutePosition.y),
@"numberOfPointers" : @(numberOfTouches),
@"pointerType" : @(pointerType)
}];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ export const NativeHandlerNativeProperties = new Set<

export type NativeHandlerData = {
pointerInside: boolean;
x: number;
y: number;
absoluteX: number;
absoluteY: number;
};
Comment thread
m-bert marked this conversation as resolved.

export type NativeGestureProperties =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Platform } from 'react-native';

import { type ActionType } from '../../ActionType';
import { State } from '../../State';
import { deepEqual } from '../../utils';
import type { NativeHandlerData } from '../../v3/hooks/gestures/native/NativeTypes';
import type { HandlerData } from '../../v3/types';
import { SingleGestureName } from '../../v3/types';
Expand Down Expand Up @@ -284,20 +283,33 @@ export default class NativeViewGestureHandler extends GestureHandler {
}

protected override transformNativeEvent(): Record<string, unknown> {
const absolute = this.tracker.getAbsoluteCoordsAverage();
const relative = this.tracker.getRelativeCoordsAverage();
return {
pointerInside: this.delegate.isPointerInBounds(
this.tracker.getAbsoluteCoordsAverage()
),
pointerInside: this.delegate.isPointerInBounds(absolute),
x: relative.x,
y: relative.y,
absoluteX: absolute.x,
absoluteY: absolute.y,
};
}

private arePointerStatesEqual(
a: HandlerData<NativeHandlerData>,
b: HandlerData<NativeHandlerData>
): boolean {
return (
a.pointerInside === b.pointerInside &&
a.numberOfPointers === b.numberOfPointers &&
a.pointerType === b.pointerType
);
}

protected override shouldSuppressActiveUpdate(
handlerData: HandlerData<NativeHandlerData>
): boolean {
if (
this.lastActiveHandlerData &&
deepEqual(this.lastActiveHandlerData, handlerData)
) {
const last = this.lastActiveHandlerData;
if (last && this.arePointerStatesEqual(last, handlerData)) {
return true;
}
this.lastActiveHandlerData = handlerData;
Expand Down
Loading