react-native-gesture-handler 2.8.0 → 2.9.0
Sign up to get free protection for your applications and to get access to all the features.
- package/RNGestureHandler.podspec +1 -1
- package/android/build.gradle +45 -43
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +1 -0
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerEvent.kt +14 -2
- package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +5 -1
- package/android/src/main/jni/CMakeLists.txt +10 -44
- package/android/src/main/jni/cpp-adapter.cpp +16 -13
- package/ios/Handlers/RNFlingHandler.m +39 -37
- package/ios/Handlers/RNForceTouchHandler.m +19 -17
- package/ios/Handlers/RNLongPressHandler.m +20 -22
- package/ios/Handlers/RNManualHandler.m +2 -3
- package/ios/Handlers/RNNativeViewHandler.mm +92 -88
- package/ios/Handlers/RNPanHandler.m +28 -32
- package/ios/Handlers/RNPinchHandler.m +9 -10
- package/ios/Handlers/RNRotationHandler.m +11 -14
- package/ios/Handlers/RNTapHandler.m +26 -26
- package/ios/RNGestureHandler.h +31 -24
- package/ios/RNGestureHandler.m +278 -273
- package/ios/RNGestureHandlerActionType.h +6 -4
- package/ios/RNGestureHandlerButton.m +11 -12
- package/ios/RNGestureHandlerButtonManager.m +6 -5
- package/ios/RNGestureHandlerDirection.h +4 -4
- package/ios/RNGestureHandlerEvents.h +3 -4
- package/ios/RNGestureHandlerEvents.m +114 -119
- package/ios/RNGestureHandlerManager.h +1 -2
- package/ios/RNGestureHandlerModule.h +1 -2
- package/ios/RNGestureHandlerModule.mm +126 -122
- package/ios/RNGestureHandlerPointerTracker.h +1 -1
- package/ios/RNGestureHandlerPointerTracker.m +40 -37
- package/ios/RNGestureHandlerRegistry.h +3 -1
- package/ios/RNGestureHandlerRegistry.m +24 -22
- package/ios/RNGestureHandlerState.h +6 -6
- package/ios/RNGestureHandlerStateManager.h +1 -1
- package/ios/RNManualActivationRecognizer.m +9 -9
- package/ios/RNRootViewGestureRecognizer.m +36 -39
- package/lib/commonjs/components/DrawerLayout.js.map +1 -1
- package/lib/commonjs/components/Swipeable.js.map +1 -1
- package/lib/commonjs/gestureHandlerRootHOC.js +2 -1
- package/lib/commonjs/gestureHandlerRootHOC.js.map +1 -1
- package/lib/commonjs/handlers/LongPressGestureHandler.js +3 -1
- package/lib/commonjs/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/commonjs/handlers/TapGestureHandler.js +3 -1
- package/lib/commonjs/handlers/TapGestureHandler.js.map +1 -1
- package/lib/commonjs/handlers/gestures/GestureDetector.js +70 -28
- package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
- package/lib/commonjs/handlers/gestures/longPressGesture.js +1 -0
- package/lib/commonjs/handlers/gestures/longPressGesture.js.map +1 -1
- package/lib/commonjs/handlers/gestures/tapGesture.js +1 -0
- package/lib/commonjs/handlers/gestures/tapGesture.js.map +1 -1
- package/lib/commonjs/web/handlers/LongPressGestureHandler.js +0 -1
- package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/commonjs/web/handlers/TapGestureHandler.js +0 -1
- package/lib/commonjs/web/handlers/TapGestureHandler.js.map +1 -1
- package/lib/module/components/DrawerLayout.js.map +1 -1
- package/lib/module/components/Swipeable.js.map +1 -1
- package/lib/module/gestureHandlerRootHOC.js +2 -1
- package/lib/module/gestureHandlerRootHOC.js.map +1 -1
- package/lib/module/handlers/LongPressGestureHandler.js +3 -1
- package/lib/module/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/module/handlers/TapGestureHandler.js +3 -1
- package/lib/module/handlers/TapGestureHandler.js.map +1 -1
- package/lib/module/handlers/gestures/GestureDetector.js +72 -29
- package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
- package/lib/module/handlers/gestures/longPressGesture.js +1 -0
- package/lib/module/handlers/gestures/longPressGesture.js.map +1 -1
- package/lib/module/handlers/gestures/tapGesture.js +1 -0
- package/lib/module/handlers/gestures/tapGesture.js.map +1 -1
- package/lib/module/web/handlers/LongPressGestureHandler.js +0 -1
- package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
- package/lib/module/web/handlers/TapGestureHandler.js +0 -1
- package/lib/module/web/handlers/TapGestureHandler.js.map +1 -1
- package/lib/typescript/components/DrawerLayout.d.ts +3 -1
- package/lib/typescript/components/Swipeable.d.ts +3 -2
- package/lib/typescript/fabric/RNGestureHandlerButtonNativeComponent.d.ts +1 -1
- package/lib/typescript/fabric/RNGestureHandlerRootViewNativeComponent.d.ts +1 -1
- package/lib/typescript/gestureHandlerRootHOC.d.ts +1 -1
- package/package.json +4 -5
- package/src/components/DrawerLayout.tsx +8 -4
- package/src/components/Swipeable.tsx +14 -9
- package/src/gestureHandlerRootHOC.tsx +4 -1
- package/src/handlers/LongPressGestureHandler.ts +3 -1
- package/src/handlers/TapGestureHandler.ts +3 -1
- package/src/handlers/gestures/GestureDetector.tsx +81 -28
- package/src/handlers/gestures/longPressGesture.ts +1 -0
- package/src/handlers/gestures/tapGesture.ts +1 -0
- package/src/web/handlers/LongPressGestureHandler.ts +0 -1
- package/src/web/handlers/TapGestureHandler.ts +0 -1
package/ios/RNGestureHandler.m
CHANGED
@@ -11,84 +11,84 @@
|
|
11
11
|
@property (nonatomic, readonly) RNGestureHandler *gestureHandler;
|
12
12
|
@end
|
13
13
|
|
14
|
-
|
15
14
|
@implementation UIGestureRecognizer (GestureHandler)
|
16
15
|
|
17
16
|
- (RNGestureHandler *)gestureHandler
|
18
17
|
{
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
id delegate = self.delegate;
|
19
|
+
if ([delegate isKindOfClass:[RNGestureHandler class]]) {
|
20
|
+
return (RNGestureHandler *)delegate;
|
21
|
+
}
|
22
|
+
return nil;
|
24
23
|
}
|
25
24
|
|
26
25
|
@end
|
27
26
|
|
28
27
|
typedef struct RNGHHitSlop {
|
29
|
-
|
28
|
+
CGFloat top, left, bottom, right, width, height;
|
30
29
|
} RNGHHitSlop;
|
31
30
|
|
32
|
-
static RNGHHitSlop RNGHHitSlopEmpty = {
|
31
|
+
static RNGHHitSlop RNGHHitSlopEmpty = {NAN, NAN, NAN, NAN, NAN, NAN};
|
33
32
|
|
34
33
|
#define RNGH_HIT_SLOP_GET(key) (prop[key] == nil ? NAN : [prop[key] doubleValue])
|
35
|
-
#define RNGH_HIT_SLOP_IS_SET(hitSlop)
|
36
|
-
|
34
|
+
#define RNGH_HIT_SLOP_IS_SET(hitSlop) \
|
35
|
+
(!isnan(hitSlop.left) || !isnan(hitSlop.right) || !isnan(hitSlop.top) || !isnan(hitSlop.bottom))
|
37
36
|
#define RNGH_HIT_SLOP_INSET(key) (isnan(hitSlop.key) ? 0. : hitSlop.key)
|
38
37
|
|
39
|
-
CGRect RNGHHitSlopInsetRect(CGRect rect, RNGHHitSlop hitSlop)
|
40
|
-
|
41
|
-
|
38
|
+
CGRect RNGHHitSlopInsetRect(CGRect rect, RNGHHitSlop hitSlop)
|
39
|
+
{
|
40
|
+
rect.origin.x -= RNGH_HIT_SLOP_INSET(left);
|
41
|
+
rect.origin.y -= RNGH_HIT_SLOP_INSET(top);
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
}
|
47
|
-
rect.size.width = hitSlop.width;
|
48
|
-
} else {
|
49
|
-
rect.size.width += (RNGH_HIT_SLOP_INSET(left) + RNGH_HIT_SLOP_INSET(right));
|
43
|
+
if (!isnan(hitSlop.width)) {
|
44
|
+
if (!isnan(hitSlop.right)) {
|
45
|
+
rect.origin.x = rect.size.width - hitSlop.width + RNGH_HIT_SLOP_INSET(right);
|
50
46
|
}
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
47
|
+
rect.size.width = hitSlop.width;
|
48
|
+
} else {
|
49
|
+
rect.size.width += (RNGH_HIT_SLOP_INSET(left) + RNGH_HIT_SLOP_INSET(right));
|
50
|
+
}
|
51
|
+
if (!isnan(hitSlop.height)) {
|
52
|
+
if (!isnan(hitSlop.bottom)) {
|
53
|
+
rect.origin.y = rect.size.height - hitSlop.height + RNGH_HIT_SLOP_INSET(bottom);
|
58
54
|
}
|
59
|
-
|
55
|
+
rect.size.height = hitSlop.height;
|
56
|
+
} else {
|
57
|
+
rect.size.height += (RNGH_HIT_SLOP_INSET(top) + RNGH_HIT_SLOP_INSET(bottom));
|
58
|
+
}
|
59
|
+
return rect;
|
60
60
|
}
|
61
61
|
|
62
62
|
static NSHashTable<RNGestureHandler *> *allGestureHandlers;
|
63
63
|
|
64
64
|
@implementation RNGestureHandler {
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
65
|
+
RNGestureHandlerPointerTracker *_pointerTracker;
|
66
|
+
RNGestureHandlerState _state;
|
67
|
+
RNManualActivationRecognizer *_manualActivationRecognizer;
|
68
|
+
NSArray<NSNumber *> *_handlersToWaitFor;
|
69
|
+
NSArray<NSNumber *> *_simultaneousHandlers;
|
70
|
+
RNGHHitSlop _hitSlop;
|
71
|
+
uint16_t _eventCoalescingKey;
|
72
72
|
}
|
73
73
|
|
74
74
|
- (instancetype)initWithTag:(NSNumber *)tag
|
75
75
|
{
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
76
|
+
if ((self = [super init])) {
|
77
|
+
_pointerTracker = [[RNGestureHandlerPointerTracker alloc] initWithGestureHandler:self];
|
78
|
+
_tag = tag;
|
79
|
+
_lastState = RNGestureHandlerStateUndetermined;
|
80
|
+
_hitSlop = RNGHHitSlopEmpty;
|
81
|
+
_state = RNGestureHandlerStateBegan;
|
82
|
+
_manualActivationRecognizer = nil;
|
83
|
+
|
84
|
+
static dispatch_once_t onceToken;
|
85
|
+
dispatch_once(&onceToken, ^{
|
86
|
+
allGestureHandlers = [NSHashTable weakObjectsHashTable];
|
87
|
+
});
|
88
|
+
|
89
|
+
[allGestureHandlers addObject:self];
|
90
|
+
}
|
91
|
+
return self;
|
92
92
|
}
|
93
93
|
|
94
94
|
- (void)resetConfig
|
@@ -107,197 +107,201 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
|
|
107
107
|
- (void)configure:(NSDictionary *)config
|
108
108
|
{
|
109
109
|
[self resetConfig];
|
110
|
-
|
111
|
-
|
110
|
+
_handlersToWaitFor = [RCTConvert NSNumberArray:config[@"waitFor"]];
|
111
|
+
_simultaneousHandlers = [RCTConvert NSNumberArray:config[@"simultaneousHandlers"]];
|
112
112
|
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
113
|
+
id prop = config[@"enabled"];
|
114
|
+
if (prop != nil) {
|
115
|
+
self.enabled = [RCTConvert BOOL:prop];
|
116
|
+
}
|
117
117
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
118
|
+
prop = config[@"shouldCancelWhenOutside"];
|
119
|
+
if (prop != nil) {
|
120
|
+
_shouldCancelWhenOutside = [RCTConvert BOOL:prop];
|
121
|
+
}
|
122
|
+
|
123
|
+
prop = config[@"cancelsTouchesInView"];
|
124
|
+
if (prop != nil) {
|
125
|
+
_recognizer.cancelsTouchesInView = [RCTConvert BOOL:prop];
|
126
|
+
}
|
127
|
+
|
128
|
+
prop = config[@"needsPointerData"];
|
129
|
+
if (prop != nil) {
|
130
|
+
_needsPointerData = [RCTConvert BOOL:prop];
|
131
|
+
}
|
132
|
+
|
133
|
+
prop = config[@"manualActivation"];
|
134
|
+
if (prop != nil) {
|
135
|
+
self.manualActivation = [RCTConvert BOOL:prop];
|
136
|
+
}
|
137
|
+
|
138
|
+
prop = config[@"hitSlop"];
|
139
|
+
if ([prop isKindOfClass:[NSNumber class]]) {
|
140
|
+
_hitSlop.left = _hitSlop.right = _hitSlop.top = _hitSlop.bottom = [prop doubleValue];
|
141
|
+
} else if (prop != nil) {
|
142
|
+
_hitSlop.left = _hitSlop.right = RNGH_HIT_SLOP_GET(@"horizontal");
|
143
|
+
_hitSlop.top = _hitSlop.bottom = RNGH_HIT_SLOP_GET(@"vertical");
|
144
|
+
_hitSlop.left = RNGH_HIT_SLOP_GET(@"left");
|
145
|
+
_hitSlop.right = RNGH_HIT_SLOP_GET(@"right");
|
146
|
+
_hitSlop.top = RNGH_HIT_SLOP_GET(@"top");
|
147
|
+
_hitSlop.bottom = RNGH_HIT_SLOP_GET(@"bottom");
|
148
|
+
_hitSlop.width = RNGH_HIT_SLOP_GET(@"width");
|
149
|
+
_hitSlop.height = RNGH_HIT_SLOP_GET(@"height");
|
150
|
+
if (isnan(_hitSlop.left) && isnan(_hitSlop.right) && !isnan(_hitSlop.width)) {
|
151
|
+
RCTLogError(@"When width is set one of left or right pads need to be defined");
|
126
152
|
}
|
127
|
-
|
128
|
-
|
129
|
-
if (prop != nil) {
|
130
|
-
_needsPointerData = [RCTConvert BOOL:prop];
|
153
|
+
if (!isnan(_hitSlop.width) && !isnan(_hitSlop.left) && !isnan(_hitSlop.right)) {
|
154
|
+
RCTLogError(@"Cannot have all of left, right and width defined");
|
131
155
|
}
|
132
|
-
|
133
|
-
|
134
|
-
if (prop != nil) {
|
135
|
-
self.manualActivation = [RCTConvert BOOL:prop];
|
156
|
+
if (isnan(_hitSlop.top) && isnan(_hitSlop.bottom) && !isnan(_hitSlop.height)) {
|
157
|
+
RCTLogError(@"When height is set one of top or bottom pads need to be defined");
|
136
158
|
}
|
137
|
-
|
138
|
-
|
139
|
-
if ([prop isKindOfClass:[NSNumber class]]) {
|
140
|
-
_hitSlop.left = _hitSlop.right = _hitSlop.top = _hitSlop.bottom = [prop doubleValue];
|
141
|
-
} else if (prop != nil) {
|
142
|
-
_hitSlop.left = _hitSlop.right = RNGH_HIT_SLOP_GET(@"horizontal");
|
143
|
-
_hitSlop.top = _hitSlop.bottom = RNGH_HIT_SLOP_GET(@"vertical");
|
144
|
-
_hitSlop.left = RNGH_HIT_SLOP_GET(@"left");
|
145
|
-
_hitSlop.right = RNGH_HIT_SLOP_GET(@"right");
|
146
|
-
_hitSlop.top = RNGH_HIT_SLOP_GET(@"top");
|
147
|
-
_hitSlop.bottom = RNGH_HIT_SLOP_GET(@"bottom");
|
148
|
-
_hitSlop.width = RNGH_HIT_SLOP_GET(@"width");
|
149
|
-
_hitSlop.height = RNGH_HIT_SLOP_GET(@"height");
|
150
|
-
if (isnan(_hitSlop.left) && isnan(_hitSlop.right) && !isnan(_hitSlop.width)) {
|
151
|
-
RCTLogError(@"When width is set one of left or right pads need to be defined");
|
152
|
-
}
|
153
|
-
if (!isnan(_hitSlop.width) && !isnan(_hitSlop.left) && !isnan(_hitSlop.right)) {
|
154
|
-
RCTLogError(@"Cannot have all of left, right and width defined");
|
155
|
-
}
|
156
|
-
if (isnan(_hitSlop.top) && isnan(_hitSlop.bottom) && !isnan(_hitSlop.height)) {
|
157
|
-
RCTLogError(@"When height is set one of top or bottom pads need to be defined");
|
158
|
-
}
|
159
|
-
if (!isnan(_hitSlop.height) && !isnan(_hitSlop.top) && !isnan(_hitSlop.bottom)) {
|
160
|
-
RCTLogError(@"Cannot have all of top, bottom and height defined");
|
161
|
-
}
|
159
|
+
if (!isnan(_hitSlop.height) && !isnan(_hitSlop.top) && !isnan(_hitSlop.bottom)) {
|
160
|
+
RCTLogError(@"Cannot have all of top, bottom and height defined");
|
162
161
|
}
|
162
|
+
}
|
163
163
|
}
|
164
164
|
|
165
165
|
- (void)setEnabled:(BOOL)enabled
|
166
166
|
{
|
167
|
-
|
168
|
-
|
167
|
+
_enabled = enabled;
|
168
|
+
self.recognizer.enabled = enabled;
|
169
169
|
}
|
170
170
|
|
171
171
|
- (void)bindToView:(UIView *)view
|
172
172
|
{
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
173
|
+
view.userInteractionEnabled = YES;
|
174
|
+
self.recognizer.delegate = self;
|
175
|
+
[view addGestureRecognizer:self.recognizer];
|
176
|
+
|
177
177
|
[self bindManualActivationToView:view];
|
178
178
|
}
|
179
179
|
|
180
180
|
- (void)unbindFromView
|
181
181
|
{
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
182
|
+
[self.recognizer.view removeGestureRecognizer:self.recognizer];
|
183
|
+
self.recognizer.delegate = nil;
|
184
|
+
|
185
|
+
[self unbindManualActivation];
|
186
186
|
}
|
187
187
|
|
188
188
|
- (RNGestureHandlerEventExtraData *)eventExtraData:(UIGestureRecognizer *)recognizer
|
189
189
|
{
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
withNumberOfTouches:recognizer.numberOfTouches];
|
190
|
+
return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:recognizer.view]
|
191
|
+
withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
|
192
|
+
withNumberOfTouches:recognizer.numberOfTouches];
|
194
193
|
}
|
195
194
|
|
196
195
|
- (void)handleGesture:(UIGestureRecognizer *)recognizer
|
197
196
|
{
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
197
|
+
// it may happen that the gesture recognizer is reset after it's been unbound from the view,
|
198
|
+
// it that recognizer tried to send event, the app would crash because the target of the event
|
199
|
+
// would be nil.
|
200
|
+
if (recognizer.view.reactTag == nil) {
|
201
|
+
return;
|
202
|
+
}
|
203
|
+
|
204
|
+
_state = [self recognizerState];
|
205
|
+
[self handleGesture:recognizer inState:_state];
|
207
206
|
}
|
208
207
|
|
209
208
|
- (void)handleGesture:(UIGestureRecognizer *)recognizer inState:(RNGestureHandlerState)state
|
210
209
|
{
|
211
|
-
|
212
|
-
|
213
|
-
|
210
|
+
_state = state;
|
211
|
+
RNGestureHandlerEventExtraData *eventData = [self eventExtraData:recognizer];
|
212
|
+
[self sendEventsInState:self.state forViewWithTag:recognizer.view.reactTag withExtraData:eventData];
|
214
213
|
}
|
215
214
|
|
216
215
|
- (void)sendEventsInState:(RNGestureHandlerState)state
|
217
216
|
forViewWithTag:(nonnull NSNumber *)reactTag
|
218
217
|
withExtraData:(RNGestureHandlerEventExtraData *)extraData
|
219
218
|
{
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
if (state == RNGestureHandlerStateActive) {
|
227
|
-
// Generate a unique coalescing-key each time the gesture-handler becomes active. All events will have
|
228
|
-
// the same coalescing-key allowing RCTEventDispatcher to coalesce RNGestureHandlerEvents when events are
|
229
|
-
// generated faster than they can be treated by JS thread
|
230
|
-
static uint16_t nextEventCoalescingKey = 0;
|
231
|
-
self->_eventCoalescingKey = nextEventCoalescingKey++;
|
232
|
-
|
233
|
-
} else if (state == RNGestureHandlerStateEnd && _lastState != RNGestureHandlerStateActive && !_manualActivation) {
|
234
|
-
id event = [[RNGestureHandlerStateChange alloc] initWithReactTag:reactTag
|
235
|
-
handlerTag:_tag
|
236
|
-
state:RNGestureHandlerStateActive
|
237
|
-
prevState:_lastState
|
238
|
-
extraData:extraData];
|
239
|
-
[self sendEvent:event];
|
240
|
-
_lastState = RNGestureHandlerStateActive;
|
241
|
-
}
|
242
|
-
id stateEvent = [[RNGestureHandlerStateChange alloc] initWithReactTag:reactTag
|
243
|
-
handlerTag:_tag
|
244
|
-
state:state
|
245
|
-
prevState:_lastState
|
246
|
-
extraData:extraData];
|
247
|
-
[self sendEvent:stateEvent];
|
248
|
-
_lastState = state;
|
219
|
+
if (state != _lastState) {
|
220
|
+
// don't send change events from END to FAILED or CANCELLED, this may happen when gesture is ended in `onTouchesUp`
|
221
|
+
// callback
|
222
|
+
if (_lastState == RNGestureHandlerStateEnd &&
|
223
|
+
(state == RNGestureHandlerStateFailed || state == RNGestureHandlerStateCancelled)) {
|
224
|
+
return;
|
249
225
|
}
|
250
226
|
|
251
227
|
if (state == RNGestureHandlerStateActive) {
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
228
|
+
// Generate a unique coalescing-key each time the gesture-handler becomes active. All events will have
|
229
|
+
// the same coalescing-key allowing RCTEventDispatcher to coalesce RNGestureHandlerEvents when events are
|
230
|
+
// generated faster than they can be treated by JS thread
|
231
|
+
static uint16_t nextEventCoalescingKey = 0;
|
232
|
+
self->_eventCoalescingKey = nextEventCoalescingKey++;
|
233
|
+
|
234
|
+
} else if (state == RNGestureHandlerStateEnd && _lastState != RNGestureHandlerStateActive && !_manualActivation) {
|
235
|
+
id event = [[RNGestureHandlerStateChange alloc] initWithReactTag:reactTag
|
236
|
+
handlerTag:_tag
|
237
|
+
state:RNGestureHandlerStateActive
|
238
|
+
prevState:_lastState
|
239
|
+
extraData:extraData];
|
240
|
+
[self sendEvent:event];
|
241
|
+
_lastState = RNGestureHandlerStateActive;
|
258
242
|
}
|
243
|
+
id stateEvent = [[RNGestureHandlerStateChange alloc] initWithReactTag:reactTag
|
244
|
+
handlerTag:_tag
|
245
|
+
state:state
|
246
|
+
prevState:_lastState
|
247
|
+
extraData:extraData];
|
248
|
+
[self sendEvent:stateEvent];
|
249
|
+
_lastState = state;
|
250
|
+
}
|
251
|
+
|
252
|
+
if (state == RNGestureHandlerStateActive) {
|
253
|
+
id touchEvent = [[RNGestureHandlerEvent alloc] initWithReactTag:reactTag
|
254
|
+
handlerTag:_tag
|
255
|
+
state:state
|
256
|
+
extraData:extraData
|
257
|
+
coalescingKey:self->_eventCoalescingKey];
|
258
|
+
[self sendEvent:touchEvent];
|
259
|
+
}
|
259
260
|
}
|
260
261
|
|
261
262
|
- (void)sendEvent:(RNGestureHandlerStateChange *)event
|
262
263
|
{
|
263
|
-
|
264
|
+
[self.emitter sendEvent:event withActionType:self.actionType];
|
264
265
|
}
|
265
266
|
|
266
|
-
- (void)sendTouchEventInState:(RNGestureHandlerState)state
|
267
|
-
forViewWithTag:(NSNumber *)reactTag
|
267
|
+
- (void)sendTouchEventInState:(RNGestureHandlerState)state forViewWithTag:(NSNumber *)reactTag
|
268
268
|
{
|
269
269
|
id extraData = [RNGestureHandlerEventExtraData forEventType:_pointerTracker.eventType
|
270
270
|
withChangedPointers:_pointerTracker.changedPointersData
|
271
271
|
withAllPointers:_pointerTracker.allPointersData
|
272
272
|
withNumberOfTouches:_pointerTracker.trackedPointersCount];
|
273
|
-
id event = [[RNGestureHandlerEvent alloc] initWithReactTag:reactTag
|
274
|
-
|
273
|
+
id event = [[RNGestureHandlerEvent alloc] initWithReactTag:reactTag
|
274
|
+
handlerTag:_tag
|
275
|
+
state:state
|
276
|
+
extraData:extraData
|
277
|
+
coalescingKey:[_tag intValue]];
|
278
|
+
|
275
279
|
[self.emitter sendEvent:event withActionType:self.actionType];
|
276
280
|
}
|
277
281
|
|
278
282
|
- (RNGestureHandlerState)recognizerState
|
279
283
|
{
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
284
|
+
switch (_recognizer.state) {
|
285
|
+
case UIGestureRecognizerStateBegan:
|
286
|
+
case UIGestureRecognizerStatePossible:
|
287
|
+
return RNGestureHandlerStateBegan;
|
288
|
+
case UIGestureRecognizerStateEnded:
|
289
|
+
return RNGestureHandlerStateEnd;
|
290
|
+
case UIGestureRecognizerStateFailed:
|
291
|
+
return RNGestureHandlerStateFailed;
|
292
|
+
case UIGestureRecognizerStateCancelled:
|
293
|
+
return RNGestureHandlerStateCancelled;
|
294
|
+
case UIGestureRecognizerStateChanged:
|
295
|
+
return RNGestureHandlerStateActive;
|
296
|
+
}
|
297
|
+
return RNGestureHandlerStateUndetermined;
|
294
298
|
}
|
295
299
|
|
296
300
|
- (RNGestureHandlerState)state
|
297
301
|
{
|
298
|
-
|
299
|
-
|
300
|
-
|
302
|
+
// instead of mapping state of the recognizer directly, use value mapped when handleGesture was
|
303
|
+
// called, making it correct while awaiting for another handler failure
|
304
|
+
return _state;
|
301
305
|
}
|
302
306
|
|
303
307
|
#pragma mark Manual activation
|
@@ -312,7 +316,7 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
|
|
312
316
|
- (void)setManualActivation:(BOOL)manualActivation
|
313
317
|
{
|
314
318
|
_manualActivation = manualActivation;
|
315
|
-
|
319
|
+
|
316
320
|
if (manualActivation) {
|
317
321
|
_manualActivationRecognizer = [[RNManualActivationRecognizer alloc] initWithGestureHandler:self];
|
318
322
|
|
@@ -343,135 +347,136 @@ static NSHashTable<RNGestureHandler *> *allGestureHandlers;
|
|
343
347
|
|
344
348
|
+ (RNGestureHandler *)findGestureHandlerByRecognizer:(UIGestureRecognizer *)recognizer
|
345
349
|
{
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
+
RNGestureHandler *handler = recognizer.gestureHandler;
|
351
|
+
if (handler != nil) {
|
352
|
+
return handler;
|
353
|
+
}
|
350
354
|
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
355
|
+
// We may try to extract "DummyGestureHandler" in case when "otherGestureRecognizer" belongs to
|
356
|
+
// a native view being wrapped with "NativeViewGestureHandler"
|
357
|
+
UIView *reactView = recognizer.view;
|
358
|
+
while (reactView != nil && reactView.reactTag == nil) {
|
359
|
+
reactView = reactView.superview;
|
360
|
+
}
|
357
361
|
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
}
|
362
|
+
for (UIGestureRecognizer *recognizer in reactView.gestureRecognizers) {
|
363
|
+
if ([recognizer isKindOfClass:[RNDummyGestureRecognizer class]]) {
|
364
|
+
return recognizer.gestureHandler;
|
362
365
|
}
|
366
|
+
}
|
363
367
|
|
364
|
-
|
368
|
+
return nil;
|
365
369
|
}
|
366
370
|
|
367
371
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
|
368
|
-
shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
372
|
+
shouldBeRequiredToFailByGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
369
373
|
{
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
}
|
374
|
+
RNGestureHandler *handler = [RNGestureHandler findGestureHandlerByRecognizer:otherGestureRecognizer];
|
375
|
+
if ([handler isKindOfClass:[RNNativeViewGestureHandler class]]) {
|
376
|
+
for (NSNumber *handlerTag in handler->_handlersToWaitFor) {
|
377
|
+
if ([_tag isEqual:handlerTag]) {
|
378
|
+
return YES;
|
379
|
+
}
|
377
380
|
}
|
381
|
+
}
|
378
382
|
|
379
|
-
|
383
|
+
return NO;
|
380
384
|
}
|
381
385
|
|
382
386
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
|
383
|
-
shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
387
|
+
shouldRequireFailureOfGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
384
388
|
{
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
}
|
392
|
-
}
|
389
|
+
if ([_handlersToWaitFor count]) {
|
390
|
+
RNGestureHandler *handler = [RNGestureHandler findGestureHandlerByRecognizer:otherGestureRecognizer];
|
391
|
+
if (handler != nil) {
|
392
|
+
for (NSNumber *handlerTag in _handlersToWaitFor) {
|
393
|
+
if ([handler.tag isEqual:handlerTag]) {
|
394
|
+
return YES;
|
393
395
|
}
|
396
|
+
}
|
394
397
|
}
|
395
|
-
|
398
|
+
}
|
399
|
+
return NO;
|
396
400
|
}
|
397
401
|
|
398
402
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer
|
399
|
-
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
403
|
+
shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
|
400
404
|
{
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
}
|
412
|
-
}
|
413
|
-
} else if (handler->_simultaneousHandlers) {
|
414
|
-
for (NSNumber *handlerTag in handler->_simultaneousHandlers) {
|
415
|
-
if ([self.tag isEqual:handlerTag]) {
|
416
|
-
return YES;
|
417
|
-
}
|
418
|
-
}
|
405
|
+
if (_recognizer.state == UIGestureRecognizerStateBegan && _recognizer.state == UIGestureRecognizerStatePossible) {
|
406
|
+
return YES;
|
407
|
+
}
|
408
|
+
|
409
|
+
RNGestureHandler *handler = [RNGestureHandler findGestureHandlerByRecognizer:otherGestureRecognizer];
|
410
|
+
if (handler != nil) {
|
411
|
+
if ([_simultaneousHandlers count]) {
|
412
|
+
for (NSNumber *handlerTag in _simultaneousHandlers) {
|
413
|
+
if ([handler.tag isEqual:handlerTag]) {
|
414
|
+
return YES;
|
419
415
|
}
|
416
|
+
}
|
417
|
+
} else if (handler->_simultaneousHandlers) {
|
418
|
+
for (NSNumber *handlerTag in handler->_simultaneousHandlers) {
|
419
|
+
if ([self.tag isEqual:handlerTag]) {
|
420
|
+
return YES;
|
421
|
+
}
|
422
|
+
}
|
420
423
|
}
|
421
|
-
|
424
|
+
}
|
425
|
+
return NO;
|
422
426
|
}
|
423
427
|
|
424
428
|
- (void)reset
|
425
429
|
{
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
430
|
+
// do not reset states while gesture is tracking pointers, as gestureRecognizerShouldBegin
|
431
|
+
// might be called after some pointers are down, and after state manipulation by the user.
|
432
|
+
// Pointer tracker calls this method when it resets, and in that case it no longer tracks
|
433
|
+
// any pointers, thus entering this if
|
434
|
+
if (!_needsPointerData || _pointerTracker.trackedPointersCount == 0) {
|
435
|
+
_lastState = RNGestureHandlerStateUndetermined;
|
436
|
+
_state = RNGestureHandlerStateBegan;
|
437
|
+
}
|
434
438
|
}
|
435
439
|
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
440
|
+
- (BOOL)containsPointInView
|
441
|
+
{
|
442
|
+
CGPoint pt = [_recognizer locationInView:_recognizer.view];
|
443
|
+
CGRect hitFrame = RNGHHitSlopInsetRect(_recognizer.view.bounds, _hitSlop);
|
444
|
+
return CGRectContainsPoint(hitFrame, pt);
|
445
|
+
}
|
442
446
|
|
443
447
|
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
|
444
448
|
{
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
}
|
449
|
+
if ([_handlersToWaitFor count]) {
|
450
|
+
for (RNGestureHandler *handler in [allGestureHandlers allObjects]) {
|
451
|
+
if (handler != nil &&
|
452
|
+
(handler.state == RNGestureHandlerStateActive ||
|
453
|
+
handler->_recognizer.state == UIGestureRecognizerStateBegan)) {
|
454
|
+
for (NSNumber *handlerTag in _handlersToWaitFor) {
|
455
|
+
if ([handler.tag isEqual:handlerTag]) {
|
456
|
+
return NO;
|
457
|
+
}
|
455
458
|
}
|
459
|
+
}
|
456
460
|
}
|
461
|
+
}
|
457
462
|
|
458
|
-
|
459
|
-
|
463
|
+
[self reset];
|
464
|
+
return YES;
|
460
465
|
}
|
461
466
|
|
462
467
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
|
463
468
|
{
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
469
|
+
// If hitSlop is set we use it to determine if a given gesture recognizer should start processing
|
470
|
+
// touch stream. This only works for negative values of hitSlop as this method won't be triggered
|
471
|
+
// unless touch startes in the bounds of the attached view. To acheve similar effect with positive
|
472
|
+
// values of hitSlop one should set hitSlop for the underlying view. This limitation is due to the
|
473
|
+
// fact that hitTest method is only available at the level of UIView
|
474
|
+
if (RNGH_HIT_SLOP_IS_SET(_hitSlop)) {
|
475
|
+
CGPoint location = [touch locationInView:gestureRecognizer.view];
|
476
|
+
CGRect hitFrame = RNGHHitSlopInsetRect(gestureRecognizer.view.bounds, _hitSlop);
|
477
|
+
return CGRectContainsPoint(hitFrame, location);
|
478
|
+
}
|
479
|
+
return YES;
|
475
480
|
}
|
476
481
|
|
477
482
|
@end
|