react-native-gesture-handler 2.32.0 → 2.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (227) hide show
  1. package/android/build.gradle +27 -11
  2. package/android/gradle.properties +1 -1
  3. package/android/src/main/java/com/swmansion/gesturehandler/core/FlingGestureHandler.kt +1 -1
  4. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +32 -33
  5. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +144 -15
  6. package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +6 -3
  7. package/android/src/main/java/com/swmansion/gesturehandler/core/NativeViewGestureHandler.kt +23 -0
  8. package/android/src/main/java/com/swmansion/gesturehandler/core/PanGestureHandler.kt +4 -7
  9. package/android/src/main/java/com/swmansion/gesturehandler/core/TapGestureHandler.kt +1 -1
  10. package/android/src/main/java/com/swmansion/gesturehandler/react/Extensions.kt +3 -0
  11. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +2 -0
  12. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt +9 -0
  13. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt +8 -6
  14. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerTouchEvent.kt +2 -7
  15. package/apple/Handlers/RNFlingHandler.m +44 -4
  16. package/apple/Handlers/RNHoverHandler.m +24 -26
  17. package/apple/Handlers/RNLongPressHandler.m +4 -0
  18. package/apple/Handlers/RNPanHandler.m +44 -7
  19. package/apple/Handlers/RNTapHandler.m +35 -4
  20. package/apple/RNGHUIKit.h +10 -10
  21. package/apple/RNGestureHandler.h +2 -0
  22. package/apple/RNGestureHandler.mm +47 -6
  23. package/apple/RNGestureHandlerButton.mm +5 -3
  24. package/apple/RNGestureHandlerManager.mm +63 -6
  25. package/apple/RNGestureHandlerModule.mm +20 -0
  26. package/apple/RNGestureHandlerPointerTracker.m +64 -10
  27. package/apple/RNGestureHandlerPointerType.h +1 -0
  28. package/apple/RNManualActivationRecognizer.m +25 -6
  29. package/lib/commonjs/components/GestureComponents.js +21 -1
  30. package/lib/commonjs/components/GestureComponents.js.map +1 -1
  31. package/lib/commonjs/components/GestureHandlerButton.web.js +2 -1
  32. package/lib/commonjs/components/GestureHandlerButton.web.js.map +1 -1
  33. package/lib/commonjs/components/Pressable/Pressable.js +28 -3
  34. package/lib/commonjs/components/Pressable/Pressable.js.map +1 -1
  35. package/lib/commonjs/components/Pressable/index.js.map +1 -1
  36. package/lib/commonjs/components/ReanimatedDrawerLayout.js +4 -2
  37. package/lib/commonjs/components/ReanimatedDrawerLayout.js.map +1 -1
  38. package/lib/commonjs/components/ReanimatedSwipeable/ReanimatedSwipeable.js +32 -9
  39. package/lib/commonjs/components/ReanimatedSwipeable/ReanimatedSwipeable.js.map +1 -1
  40. package/lib/commonjs/components/Swipeable.js.map +1 -1
  41. package/lib/commonjs/components/Text.js.map +1 -1
  42. package/lib/commonjs/components/touchables/TouchableHighlight.js +1 -1
  43. package/lib/commonjs/components/touchables/TouchableHighlight.js.map +1 -1
  44. package/lib/commonjs/components/touchables/TouchableNativeFeedback.android.js.map +1 -1
  45. package/lib/commonjs/components/touchables/TouchableOpacity.js +1 -0
  46. package/lib/commonjs/components/touchables/TouchableOpacity.js.map +1 -1
  47. package/lib/commonjs/getShadowNodeFromRef.js +6 -2
  48. package/lib/commonjs/getShadowNodeFromRef.js.map +1 -1
  49. package/lib/commonjs/handlers/PanGestureHandler.js.map +1 -1
  50. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.js +56 -11
  51. package/lib/commonjs/handlers/gestures/GestureDetector/Wrap.js.map +1 -1
  52. package/lib/commonjs/handlers/gestures/GestureDetector/index.js +2 -1
  53. package/lib/commonjs/handlers/gestures/GestureDetector/index.js.map +1 -1
  54. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js +2 -1
  55. package/lib/commonjs/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
  56. package/lib/commonjs/handlers/gestures/GestureDetector/useMountReactions.js +6 -0
  57. package/lib/commonjs/handlers/gestures/GestureDetector/useMountReactions.js.map +1 -1
  58. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js +3 -2
  59. package/lib/commonjs/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
  60. package/lib/commonjs/handlers/gestures/gestureStateManager.web.js.map +1 -1
  61. package/lib/commonjs/handlers/gestures/panGesture.js +6 -3
  62. package/lib/commonjs/handlers/gestures/panGesture.js.map +1 -1
  63. package/lib/commonjs/hostInstance.js +39 -0
  64. package/lib/commonjs/hostInstance.js.map +1 -0
  65. package/lib/commonjs/index.js.map +1 -1
  66. package/lib/commonjs/mocks/mocks.js +1 -0
  67. package/lib/commonjs/mocks/mocks.js.map +1 -1
  68. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
  69. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.ts +16 -14
  70. package/lib/commonjs/specs/RNGestureHandlerRootViewNativeComponent.ts +3 -3
  71. package/lib/commonjs/web/detectors/RotationGestureDetector.js +1 -1
  72. package/lib/commonjs/web/handlers/LongPressGestureHandler.js +3 -1
  73. package/lib/commonjs/web/handlers/LongPressGestureHandler.js.map +1 -1
  74. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +9 -1
  75. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
  76. package/lib/commonjs/web/handlers/PanGestureHandler.js +8 -9
  77. package/lib/commonjs/web/handlers/PanGestureHandler.js.map +1 -1
  78. package/lib/commonjs/web/handlers/TapGestureHandler.js +1 -1
  79. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +14 -0
  80. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  81. package/lib/commonjs/web/tools/WheelEventManager.js +4 -0
  82. package/lib/commonjs/web/tools/WheelEventManager.js.map +1 -1
  83. package/lib/module/components/GestureComponents.js +23 -2
  84. package/lib/module/components/GestureComponents.js.map +1 -1
  85. package/lib/module/components/GestureHandlerButton.web.js +2 -1
  86. package/lib/module/components/GestureHandlerButton.web.js.map +1 -1
  87. package/lib/module/components/Pressable/Pressable.js +28 -3
  88. package/lib/module/components/Pressable/Pressable.js.map +1 -1
  89. package/lib/module/components/Pressable/index.js.map +1 -1
  90. package/lib/module/components/ReanimatedDrawerLayout.js +4 -2
  91. package/lib/module/components/ReanimatedDrawerLayout.js.map +1 -1
  92. package/lib/module/components/ReanimatedSwipeable/ReanimatedSwipeable.js +34 -11
  93. package/lib/module/components/ReanimatedSwipeable/ReanimatedSwipeable.js.map +1 -1
  94. package/lib/module/components/Swipeable.js.map +1 -1
  95. package/lib/module/components/Text.js.map +1 -1
  96. package/lib/module/components/touchables/TouchableHighlight.js +2 -2
  97. package/lib/module/components/touchables/TouchableHighlight.js.map +1 -1
  98. package/lib/module/components/touchables/TouchableNativeFeedback.android.js.map +1 -1
  99. package/lib/module/components/touchables/TouchableOpacity.js +1 -0
  100. package/lib/module/components/touchables/TouchableOpacity.js.map +1 -1
  101. package/lib/module/getShadowNodeFromRef.js +7 -2
  102. package/lib/module/getShadowNodeFromRef.js.map +1 -1
  103. package/lib/module/handlers/PanGestureHandler.js.map +1 -1
  104. package/lib/module/handlers/gestures/GestureDetector/Wrap.js +56 -11
  105. package/lib/module/handlers/gestures/GestureDetector/Wrap.js.map +1 -1
  106. package/lib/module/handlers/gestures/GestureDetector/index.js +2 -1
  107. package/lib/module/handlers/gestures/GestureDetector/index.js.map +1 -1
  108. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js +2 -1
  109. package/lib/module/handlers/gestures/GestureDetector/useDetectorUpdater.js.map +1 -1
  110. package/lib/module/handlers/gestures/GestureDetector/useMountReactions.js +6 -0
  111. package/lib/module/handlers/gestures/GestureDetector/useMountReactions.js.map +1 -1
  112. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js +3 -2
  113. package/lib/module/handlers/gestures/GestureDetector/useViewRefHandler.js.map +1 -1
  114. package/lib/module/handlers/gestures/gestureStateManager.web.js.map +1 -1
  115. package/lib/module/handlers/gestures/panGesture.js +6 -3
  116. package/lib/module/handlers/gestures/panGesture.js.map +1 -1
  117. package/lib/module/hostInstance.js +32 -0
  118. package/lib/module/hostInstance.js.map +1 -0
  119. package/lib/module/index.js.map +1 -1
  120. package/lib/module/mocks/mocks.js +3 -2
  121. package/lib/module/mocks/mocks.js.map +1 -1
  122. package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
  123. package/lib/module/specs/RNGestureHandlerButtonNativeComponent.ts +16 -14
  124. package/lib/module/specs/RNGestureHandlerRootViewNativeComponent.ts +3 -3
  125. package/lib/module/web/detectors/RotationGestureDetector.js +1 -1
  126. package/lib/module/web/handlers/LongPressGestureHandler.js +3 -1
  127. package/lib/module/web/handlers/LongPressGestureHandler.js.map +1 -1
  128. package/lib/module/web/handlers/NativeViewGestureHandler.js +9 -1
  129. package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
  130. package/lib/module/web/handlers/PanGestureHandler.js +8 -9
  131. package/lib/module/web/handlers/PanGestureHandler.js.map +1 -1
  132. package/lib/module/web/handlers/TapGestureHandler.js +1 -1
  133. package/lib/module/web/tools/GestureHandlerOrchestrator.js +14 -0
  134. package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  135. package/lib/module/web/tools/WheelEventManager.js +4 -0
  136. package/lib/module/web/tools/WheelEventManager.js.map +1 -1
  137. package/lib/typescript/components/GestureButtons.d.ts +3 -1
  138. package/lib/typescript/components/GestureButtons.d.ts.map +1 -1
  139. package/lib/typescript/components/GestureButtonsProps.d.ts +10 -0
  140. package/lib/typescript/components/GestureButtonsProps.d.ts.map +1 -1
  141. package/lib/typescript/components/GestureComponents.d.ts +8 -7
  142. package/lib/typescript/components/GestureComponents.d.ts.map +1 -1
  143. package/lib/typescript/components/GestureComponents.web.d.ts +12 -4
  144. package/lib/typescript/components/GestureComponents.web.d.ts.map +1 -1
  145. package/lib/typescript/components/GestureHandlerButton.web.d.ts +2 -2
  146. package/lib/typescript/components/GestureHandlerButton.web.d.ts.map +1 -1
  147. package/lib/typescript/components/Pressable/Pressable.d.ts.map +1 -1
  148. package/lib/typescript/components/Pressable/PressableProps.d.ts +1 -1
  149. package/lib/typescript/components/Pressable/PressableProps.d.ts.map +1 -1
  150. package/lib/typescript/components/Pressable/index.d.ts +1 -1
  151. package/lib/typescript/components/Pressable/index.d.ts.map +1 -1
  152. package/lib/typescript/components/ReanimatedDrawerLayout.d.ts.map +1 -1
  153. package/lib/typescript/components/ReanimatedSwipeable/ReanimatedSwipeable.d.ts.map +1 -1
  154. package/lib/typescript/components/Swipeable.d.ts.map +1 -1
  155. package/lib/typescript/components/touchables/TouchableHighlight.d.ts +1 -1
  156. package/lib/typescript/components/touchables/TouchableHighlight.d.ts.map +1 -1
  157. package/lib/typescript/components/touchables/TouchableNativeFeedback.android.d.ts +1 -1
  158. package/lib/typescript/components/touchables/TouchableNativeFeedback.android.d.ts.map +1 -1
  159. package/lib/typescript/components/touchables/TouchableOpacity.d.ts.map +1 -1
  160. package/lib/typescript/getShadowNodeFromRef.d.ts.map +1 -1
  161. package/lib/typescript/handlers/PanGestureHandler.d.ts +12 -0
  162. package/lib/typescript/handlers/PanGestureHandler.d.ts.map +1 -1
  163. package/lib/typescript/handlers/gestures/GestureDetector/Wrap.d.ts +11 -0
  164. package/lib/typescript/handlers/gestures/GestureDetector/Wrap.d.ts.map +1 -1
  165. package/lib/typescript/handlers/gestures/GestureDetector/index.d.ts.map +1 -1
  166. package/lib/typescript/handlers/gestures/GestureDetector/useDetectorUpdater.d.ts.map +1 -1
  167. package/lib/typescript/handlers/gestures/GestureDetector/useMountReactions.d.ts.map +1 -1
  168. package/lib/typescript/handlers/gestures/GestureDetector/useViewRefHandler.d.ts.map +1 -1
  169. package/lib/typescript/handlers/gestures/gestureStateManager.web.d.ts +8 -1
  170. package/lib/typescript/handlers/gestures/gestureStateManager.web.d.ts.map +1 -1
  171. package/lib/typescript/handlers/gestures/panGesture.d.ts +6 -3
  172. package/lib/typescript/handlers/gestures/panGesture.d.ts.map +1 -1
  173. package/lib/typescript/hostInstance.d.ts +10 -0
  174. package/lib/typescript/hostInstance.d.ts.map +1 -0
  175. package/lib/typescript/index.d.ts +1 -1
  176. package/lib/typescript/index.d.ts.map +1 -1
  177. package/lib/typescript/mocks/mocks.d.ts +67 -15
  178. package/lib/typescript/mocks/mocks.d.ts.map +1 -1
  179. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +6 -7
  180. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts.map +1 -1
  181. package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts +9 -10
  182. package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts.map +1 -1
  183. package/lib/typescript/specs/RNGestureHandlerRootViewNativeComponent.d.ts +2 -2
  184. package/lib/typescript/specs/RNGestureHandlerRootViewNativeComponent.d.ts.map +1 -1
  185. package/lib/typescript/web/handlers/LongPressGestureHandler.d.ts.map +1 -1
  186. package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +1 -0
  187. package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts.map +1 -1
  188. package/lib/typescript/web/handlers/PanGestureHandler.d.ts.map +1 -1
  189. package/lib/typescript/web/tools/GestureHandlerOrchestrator.d.ts +1 -0
  190. package/lib/typescript/web/tools/GestureHandlerOrchestrator.d.ts.map +1 -1
  191. package/lib/typescript/web/tools/WheelEventManager.d.ts.map +1 -1
  192. package/package.json +7 -7
  193. package/src/components/GestureButtonsProps.ts +14 -0
  194. package/src/components/GestureComponents.tsx +38 -7
  195. package/src/components/GestureHandlerButton.web.tsx +7 -3
  196. package/src/components/Pressable/Pressable.tsx +33 -4
  197. package/src/components/Pressable/PressableProps.tsx +1 -1
  198. package/src/components/Pressable/index.ts +1 -0
  199. package/src/components/ReanimatedDrawerLayout.tsx +4 -1
  200. package/src/components/ReanimatedSwipeable/ReanimatedSwipeable.tsx +49 -10
  201. package/src/components/Swipeable.tsx +6 -2
  202. package/src/components/Text.tsx +3 -3
  203. package/src/components/touchables/TouchableHighlight.tsx +4 -2
  204. package/src/components/touchables/TouchableNativeFeedback.android.tsx +8 -2
  205. package/src/components/touchables/TouchableOpacity.tsx +1 -0
  206. package/src/getShadowNodeFromRef.ts +11 -4
  207. package/src/handlers/PanGestureHandler.ts +15 -0
  208. package/src/handlers/gestures/GestureDetector/Wrap.tsx +78 -13
  209. package/src/handlers/gestures/GestureDetector/index.tsx +4 -1
  210. package/src/handlers/gestures/GestureDetector/useDetectorUpdater.ts +4 -1
  211. package/src/handlers/gestures/GestureDetector/useMountReactions.ts +6 -0
  212. package/src/handlers/gestures/GestureDetector/useViewRefHandler.ts +5 -2
  213. package/src/handlers/gestures/gestureStateManager.web.ts +9 -1
  214. package/src/handlers/gestures/panGesture.ts +6 -3
  215. package/src/hostInstance.ts +57 -0
  216. package/src/index.ts +1 -0
  217. package/src/mocks/mocks.tsx +6 -2
  218. package/src/specs/NativeRNGestureHandlerModule.ts +16 -10
  219. package/src/specs/RNGestureHandlerButtonNativeComponent.ts +16 -14
  220. package/src/specs/RNGestureHandlerRootViewNativeComponent.ts +3 -3
  221. package/src/web/detectors/RotationGestureDetector.ts +1 -1
  222. package/src/web/handlers/LongPressGestureHandler.ts +3 -1
  223. package/src/web/handlers/NativeViewGestureHandler.ts +11 -2
  224. package/src/web/handlers/PanGestureHandler.ts +8 -11
  225. package/src/web/handlers/TapGestureHandler.ts +1 -1
  226. package/src/web/tools/GestureHandlerOrchestrator.ts +19 -0
  227. package/src/web/tools/WheelEventManager.ts +1 -0
@@ -2,17 +2,18 @@ import groovy.json.JsonSlurper
2
2
  import com.android.build.gradle.tasks.ExternalNativeBuildJsonTask
3
3
 
4
4
  buildscript {
5
- def kotlin_version = rootProject.ext.has('kotlinVersion') ? rootProject.ext.get('kotlinVersion') : project.properties['RNGH_kotlinVersion']
6
-
7
5
  repositories {
8
6
  mavenCentral()
9
7
  google()
10
8
  }
11
9
 
12
10
  dependencies {
13
- classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
14
- classpath("com.android.tools.build:gradle:8.10.1")
15
- classpath("com.diffplug.spotless:spotless-plugin-gradle:7.0.4")
11
+ if (project == rootProject) {
12
+ def kotlin_version = project.properties['RNGH_kotlinVersion']
13
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version")
14
+ classpath("com.android.tools.build:gradle:8.10.1")
15
+ classpath("com.diffplug.spotless:spotless-plugin-gradle:7.0.4")
16
+ }
16
17
  }
17
18
  }
18
19
 
@@ -62,7 +63,22 @@ if (isNewArchitectureEnabled()) {
62
63
  }
63
64
 
64
65
  apply plugin: 'com.android.library'
65
- apply plugin: 'kotlin-android'
66
+
67
+ def shouldEnableAgpFallback() {
68
+ def agpMajorVersion = com.android.Version.ANDROID_GRADLE_PLUGIN_VERSION.tokenize('.')[0].toInteger()
69
+ if (agpMajorVersion <= 8) {
70
+ return true
71
+ }
72
+
73
+ def propertyVal = providers.gradleProperty("android.builtInKotlin").orNull
74
+ def isBuiltInKotlinEnabled = propertyVal != null ? propertyVal.toBoolean() : true
75
+
76
+ return !isBuiltInKotlinEnabled
77
+ }
78
+
79
+ if (shouldEnableAgpFallback()) {
80
+ apply plugin: 'kotlin-android'
81
+ }
66
82
 
67
83
  if (project == rootProject) {
68
84
  apply from: "spotless.gradle"
@@ -190,17 +206,17 @@ android {
190
206
  }
191
207
 
192
208
  sourceSets.main {
193
- java {
209
+ kotlin {
194
210
  if (shouldUseCommonInterfaceFromReanimated()) {
195
- srcDirs += 'reanimated/src/main/java'
211
+ directories.add('reanimated/src/main/java')
196
212
  } else {
197
- srcDirs += 'noreanimated/src/main/java'
213
+ directories.add('noreanimated/src/main/java')
198
214
  }
199
215
 
200
216
  if (shouldUseCommonInterfaceFromRNSVG()) {
201
- srcDirs += 'svg/src/main/java'
217
+ directories.add('svg/src/main/java')
202
218
  } else {
203
- srcDirs += 'nosvg/src/main/java'
219
+ directories.add('nosvg/src/main/java')
204
220
  }
205
221
 
206
222
  if (isNewArchitectureEnabled()) {
@@ -16,4 +16,4 @@ org.gradle.jvmargs=-Xmx2048m -XX:MaxMetaspaceSize=512m -XX:+HeapDumpOnOutOfMemor
16
16
  # This option should only be used with decoupled projects. More details, visit
17
17
  # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
18
18
  # org.gradle.parallel=true
19
- RNGH_kotlinVersion=2.0.21
19
+ RNGH_kotlinVersion=2.2.0
@@ -88,7 +88,7 @@ class FlingGestureHandler : GestureHandler() {
88
88
  }
89
89
 
90
90
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
91
- if (!shouldActivateWithMouse(sourceEvent)) {
91
+ if (shouldSkipEvent(sourceEvent)) {
92
92
  return
93
93
  }
94
94
 
@@ -4,7 +4,6 @@ import android.app.Activity
4
4
  import android.content.Context
5
5
  import android.content.ContextWrapper
6
6
  import android.graphics.PointF
7
- import android.os.Build
8
7
  import android.view.MotionEvent
9
8
  import android.view.MotionEvent.PointerCoords
10
9
  import android.view.MotionEvent.PointerProperties
@@ -426,10 +425,15 @@ open class GestureHandler {
426
425
  }
427
426
 
428
427
  private fun dispatchTouchUpEvent(event: MotionEvent, sourceEvent: MotionEvent) {
428
+ val pointerId = event.getPointerId(event.actionIndex)
429
+
430
+ if (trackedPointers[pointerId] == null) {
431
+ return
432
+ }
433
+
429
434
  extractAllPointersData()
430
435
  changedTouchesPayload = null
431
436
  touchEventType = RNGestureHandlerTouchEvent.EVENT_TOUCH_UP
432
- val pointerId = event.getPointerId(event.actionIndex)
433
437
  val offsetX = sourceEvent.rawX - sourceEvent.x
434
438
  val offsetY = sourceEvent.rawY - sourceEvent.y
435
439
 
@@ -754,44 +758,38 @@ open class GestureHandler {
754
758
  return clickedButton and mouseButton != 0
755
759
  }
756
760
 
757
- protected fun shouldActivateWithMouse(sourceEvent: MotionEvent): Boolean {
758
- // While using mouse, we get both sets of events, for example ACTION_DOWN and ACTION_BUTTON_PRESS. That's why we want to take actions to only one of them.
759
- // On API >= 23, we will use events with infix BUTTON, otherwise we use standard action events (like ACTION_DOWN).
761
+ // Decides whether the gesture should ignore this event. While using a mouse we receive both the
762
+ // touch-compatible stream (ACTION_DOWN/UP/...) and the BUTTON_* events, so we act on only the
763
+ // latter, and we drop events coming from a button other than the configured `mouseButton`.
764
+ // Non-mouse input is never skipped here.
765
+ protected fun shouldSkipEvent(sourceEvent: MotionEvent): Boolean {
766
+ if (sourceEvent.getToolType(0) != MotionEvent.TOOL_TYPE_MOUSE) {
767
+ return false
768
+ }
760
769
 
761
770
  with(sourceEvent) {
762
- // To use actionButton, we need API >= 23.
763
- if (getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE &&
764
- Build.VERSION.SDK_INT >= Build.VERSION_CODES.M
771
+ // While using mouse, we want to ignore default events for touch.
772
+ if (actionMasked == MotionEvent.ACTION_DOWN ||
773
+ actionMasked == MotionEvent.ACTION_UP ||
774
+ actionMasked == MotionEvent.ACTION_POINTER_UP ||
775
+ actionMasked == MotionEvent.ACTION_POINTER_DOWN
765
776
  ) {
766
- // While using mouse, we want to ignore default events for touch.
767
- if (action == MotionEvent.ACTION_DOWN ||
768
- action == MotionEvent.ACTION_UP ||
769
- action == MotionEvent.ACTION_POINTER_UP ||
770
- action == MotionEvent.ACTION_POINTER_DOWN
771
- ) {
772
- return@shouldActivateWithMouse false
773
- }
777
+ return@shouldSkipEvent true
778
+ }
774
779
 
775
- // We don't want to do anything if wrong button was clicked. If we received event for BUTTON, we have to use actionButton to get which one was clicked.
776
- if (action != MotionEvent.ACTION_MOVE && !isButtonInConfig(actionButton)) {
777
- return@shouldActivateWithMouse false
778
- }
780
+ // Skip events from a button other than the configured one. For BUTTON_* events the clicked
781
+ // button is read from `actionButton`.
782
+ if (actionMasked != MotionEvent.ACTION_MOVE && !isButtonInConfig(actionButton)) {
783
+ return@shouldSkipEvent true
784
+ }
779
785
 
780
- // When we receive ACTION_MOVE, we have to check buttonState field.
781
- if (action == MotionEvent.ACTION_MOVE && !isButtonInConfig(buttonState)) {
782
- return@shouldActivateWithMouse false
783
- }
784
- } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
785
- // We do not fully support mouse below API 23, so we will ignore BUTTON events.
786
- if (action == MotionEvent.ACTION_BUTTON_PRESS ||
787
- action == MotionEvent.ACTION_BUTTON_RELEASE
788
- ) {
789
- return@shouldActivateWithMouse false
790
- }
786
+ // For ACTION_MOVE the pressed button is read from `buttonState`.
787
+ if (actionMasked == MotionEvent.ACTION_MOVE && !isButtonInConfig(buttonState)) {
788
+ return@shouldSkipEvent true
791
789
  }
792
790
  }
793
791
 
794
- return true
792
+ return false
795
793
  }
796
794
 
797
795
  /**
@@ -984,7 +982,8 @@ open class GestureHandler {
984
982
  const val POINTER_TYPE_TOUCH = 0
985
983
  const val POINTER_TYPE_STYLUS = 1
986
984
  const val POINTER_TYPE_MOUSE = 2
987
- const val POINTER_TYPE_OTHER = 3
985
+ const val POINTER_TYPE_KEY = 3
986
+ const val POINTER_TYPE_OTHER = 4
988
987
  private const val MAX_POINTERS_COUNT = 12
989
988
  private lateinit var pointerProps: Array<PointerProperties?>
990
989
  private lateinit var pointerCoords: Array<PointerCoords?>
@@ -2,6 +2,7 @@ package com.swmansion.gesturehandler.core
2
2
 
3
3
  import android.graphics.Matrix
4
4
  import android.graphics.PointF
5
+ import android.util.SparseArray
5
6
  import android.view.MotionEvent
6
7
  import android.view.View
7
8
  import android.view.ViewGroup
@@ -26,7 +27,20 @@ class GestureHandlerOrchestrator(
26
27
  var minimumAlphaForTraversal = DEFAULT_MIN_ALPHA_FOR_TRAVERSAL
27
28
  private val gestureHandlers = arrayListOf<GestureHandler>()
28
29
  private val awaitingHandlers = arrayListOf<GestureHandler>()
29
- private val preparedHandlers = arrayListOf<GestureHandler>()
30
+
31
+ // Pool of reusable lists for snapshotting `gestureHandlers` during event delivery.
32
+ private val handlerListPool = ArrayDeque<ArrayList<GestureHandler>>()
33
+
34
+ private fun obtainHandlerList() = handlerListPool.pollLast() ?: ArrayList<GestureHandler>()
35
+
36
+ private fun recycleHandlerList(list: ArrayList<GestureHandler>) {
37
+ list.clear()
38
+ handlerListPool.addLast(list)
39
+ }
40
+
41
+ // Used by `cancelTouchesInInterceptedViews`.
42
+ private val viewsToCancel = arrayListOf<View>()
43
+ private val pointerDownPoints = SparseArray<PointF>()
30
44
 
31
45
  // In `onHandlerStateChange` method we iterate through `awaitingHandlers`, but calling `tryActivate` may modify this list.
32
46
  // To avoid `ConcurrentModificationException` we iterate through copy. There is one more problem though - if handler was
@@ -46,6 +60,7 @@ class GestureHandlerOrchestrator(
46
60
  fun onTouchEvent(event: MotionEvent): Boolean {
47
61
  isHandlingTouch = true
48
62
  val action = event.actionMasked
63
+ trackPointerDownPoints(event)
49
64
  if (action == MotionEvent.ACTION_DOWN ||
50
65
  action == MotionEvent.ACTION_POINTER_DOWN ||
51
66
  action == MotionEvent.ACTION_HOVER_MOVE
@@ -105,7 +120,7 @@ class GestureHandlerOrchestrator(
105
120
 
106
121
  private fun shouldBeCancelledByActiveHandler(handler: GestureHandler) = gestureHandlers.any {
107
122
  handler.hasCommonPointers(it) &&
108
- it.state == GestureHandler.STATE_ACTIVE &&
123
+ it.isActive &&
109
124
  !canRunSimultaneously(handler, it) &&
110
125
  handler.isDescendantOf(it)
111
126
  }
@@ -141,6 +156,13 @@ class GestureHandlerOrchestrator(
141
156
  /*package*/
142
157
  fun onHandlerStateChange(handler: GestureHandler, newState: Int, prevState: Int) {
143
158
  handlingChangeSemaphore += 1
159
+
160
+ if (handler.isAwaiting &&
161
+ (newState == GestureHandler.STATE_CANCELLED || newState == GestureHandler.STATE_FAILED)
162
+ ) {
163
+ handler.isAwaiting = false
164
+ }
165
+
144
166
  if (isFinished(newState)) {
145
167
  // We have to loop through copy in order to avoid modifying collection
146
168
  // while iterating over its elements
@@ -252,20 +274,24 @@ class GestureHandlerOrchestrator(
252
274
  }
253
275
 
254
276
  private fun deliverEventToGestureHandlers(event: MotionEvent) {
255
- // Copy handlers to "prepared handlers" array, because the list of active handlers can change
256
- // as a result of state updates
257
- preparedHandlers.clear()
258
- preparedHandlers.addAll(gestureHandlers)
277
+ // Snapshot handlers into a pooled list, because the list of active handlers can change
278
+ // as a result of state updates (and delivery can be re-entrant).
279
+ val handlersToProcess = obtainHandlerList()
280
+ handlersToProcess.addAll(gestureHandlers)
259
281
 
260
282
  // We want to deliver events to active handlers first in order of their activation (handlers
261
283
  // that activated first will first get event delivered). Otherwise we deliver events in the
262
284
  // order in which handlers has been added ("most direct" children goes first). Therefore we rely
263
285
  // on Arrays.sort providing a stable sort (as children are registered in order in which they
264
286
  // should be tested)
265
- preparedHandlers.sortWith(handlersComparator)
287
+ handlersToProcess.sortWith(handlersComparator)
266
288
 
267
- for (handler in preparedHandlers) {
268
- deliverEventToGestureHandler(handler, event)
289
+ try {
290
+ for (handler in handlersToProcess) {
291
+ deliverEventToGestureHandler(handler, event)
292
+ }
293
+ } finally {
294
+ recycleHandlerList(handlersToProcess)
269
295
  }
270
296
  }
271
297
 
@@ -276,12 +302,9 @@ class GestureHandlerOrchestrator(
276
302
  handler.cancel()
277
303
  }
278
304
 
279
- // Copy handlers to "prepared handlers" array, because the list of active handlers can change
305
+ // Iterate over a copy, because the list of active handlers can change
280
306
  // as a result of state updates
281
- preparedHandlers.clear()
282
- preparedHandlers.addAll(gestureHandlers)
283
-
284
- for (handler in gestureHandlers.asReversed()) {
307
+ for (handler in gestureHandlers.reversed()) {
285
308
  handler.cancel()
286
309
  }
287
310
  }
@@ -314,7 +337,7 @@ class GestureHandlerOrchestrator(
314
337
  if (!handler.isAwaiting || action != MotionEvent.ACTION_MOVE) {
315
338
  val isFirstEvent = handler.state == 0
316
339
  handler.handle(event, sourceEvent)
317
- if (handler.isActive) {
340
+ if (handler.state == GestureHandler.STATE_ACTIVE && handler.isActive) {
318
341
  // After handler is done waiting for other one to fail its progress should be
319
342
  // reset, otherwise there may be a visible jump in values sent by the handler.
320
343
  // When handler is waiting it's already activated but the `isAwaiting` flag
@@ -622,6 +645,112 @@ class GestureHandlerOrchestrator(
622
645
  return false
623
646
  }
624
647
 
648
+ private fun trackPointerDownPoints(event: MotionEvent) {
649
+ val index = event.actionIndex
650
+ when (event.actionMasked) {
651
+ MotionEvent.ACTION_DOWN, MotionEvent.ACTION_POINTER_DOWN ->
652
+ pointerDownPoints.put(event.getPointerId(index), PointF(event.getX(index), event.getY(index)))
653
+ MotionEvent.ACTION_POINTER_UP ->
654
+ pointerDownPoints.remove(event.getPointerId(index))
655
+ MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL ->
656
+ pointerDownPoints.clear()
657
+ }
658
+ }
659
+
660
+ fun cancelTouchesInInterceptedViews(event: MotionEvent) {
661
+ viewsToCancel.clear()
662
+ for (i in 0 until pointerDownPoints.size()) {
663
+ val point = pointerDownPoints.valueAt(i)
664
+ tempCoords[0] = point.x
665
+ tempCoords[1] = point.y
666
+ collectViewsAtPoint(wrapperView, tempCoords, viewsToCancel)
667
+ }
668
+
669
+ if (viewsToCancel.isEmpty()) {
670
+ return
671
+ }
672
+
673
+ val activeHandlers = gestureHandlers.filter { it.isActive }
674
+ val cancelEvent = MotionEvent.obtain(event).apply { action = MotionEvent.ACTION_CANCEL }
675
+
676
+ for (view in viewsToCancel) {
677
+ if (view === wrapperView || isViewDrivenByActiveNativeGesture(view, activeHandlers)) {
678
+ continue
679
+ }
680
+ view.onTouchEvent(cancelEvent)
681
+ }
682
+
683
+ cancelEvent.recycle()
684
+ viewsToCancel.clear()
685
+ }
686
+
687
+ // Whether the view's touch is still owned by a NativeViewGestureHandler that survived arbitration.
688
+ // Only those are fed through `onTouchEvent`, so only those break if cancelled. Other handlers are
689
+ // orchestrator-driven and unaffected.
690
+ private fun isViewDrivenByActiveNativeGesture(view: View, activeHandlers: List<GestureHandler>) =
691
+ handlerRegistry.getHandlersForView(view)?.let { handlers ->
692
+ synchronized(handlers) {
693
+ handlers.any { nativeGestureSurvivesArbitration(it, activeHandlers) }
694
+ }
695
+ } ?: false
696
+
697
+ // A native handler survives arbitration if it is active, or it does not conflict with any active handler.
698
+ private fun nativeGestureSurvivesArbitration(handler: GestureHandler, activeHandlers: List<GestureHandler>) =
699
+ handler is NativeViewGestureHandler &&
700
+ (handler.isActive || activeHandlers.none { shouldHandlerBeCancelledBy(handler, it) })
701
+
702
+ // Collects the view path under the point (topmost child first, like touch dispatch), leaf to root.
703
+ private fun collectViewsAtPoint(view: View, coords: FloatArray, out: MutableList<View>): Boolean {
704
+ if (shouldIgnoreSubtreeIfGestureHandlerRootView(view)) {
705
+ // A nested active root view manages its own subtree (and its own interception cancellation).
706
+ return false
707
+ }
708
+
709
+ val pointerEvents = viewConfigHelper.getPointerEventsConfigForView(view)
710
+ if (pointerEvents == PointerEventsConfig.NONE) {
711
+ return false
712
+ }
713
+
714
+ var found = false
715
+ if (view is ViewGroup && pointerEvents != PointerEventsConfig.BOX_ONLY) {
716
+ for (i in view.childCount - 1 downTo 0) {
717
+ val child = view.getChildAt(i)
718
+ if (!canReceiveEvents(child)) {
719
+ continue
720
+ }
721
+ val childPoint = tempPoint
722
+ transformPointToChildViewCoords(coords[0], coords[1], view, child, childPoint)
723
+ if (isClipping(child) && !isTransformedTouchPointInView(childPoint.x, childPoint.y, child)) {
724
+ continue
725
+ }
726
+ val restoreX = coords[0]
727
+ val restoreY = coords[1]
728
+ coords[0] = childPoint.x
729
+ coords[1] = childPoint.y
730
+ found = collectViewsAtPoint(child, coords, out)
731
+ coords[0] = restoreX
732
+ coords[1] = restoreY
733
+
734
+ if (found) {
735
+ break
736
+ }
737
+ }
738
+ }
739
+
740
+ // BOX_NONE views can't be the target themselves, only their children can
741
+ val selfIsTarget = pointerEvents != PointerEventsConfig.BOX_NONE &&
742
+ isTransformedTouchPointInView(coords[0], coords[1], view)
743
+
744
+ if (found || selfIsTarget) {
745
+ // `out` may already contain this view when several pointers share part of their path.
746
+ if (!out.contains(view)) {
747
+ out.add(view)
748
+ }
749
+ return true
750
+ }
751
+ return false
752
+ }
753
+
625
754
  private fun traverseWithPointerEvents(view: View, coords: FloatArray, pointerId: Int, event: MotionEvent): Boolean =
626
755
  if (shouldIgnoreSubtreeIfGestureHandlerRootView(view)) {
627
756
  // When we encounter another active root view while traversing the view hierarchy, we want
@@ -29,13 +29,14 @@ class LongPressGestureHandler(context: Context) : GestureHandler() {
29
29
  val systemDefaultMaxDist = DEFAULT_MAX_DIST_DP * context.resources.displayMetrics.density
30
30
  defaultMaxDist = systemDefaultMaxDist
31
31
  maxDist = defaultMaxDist
32
- numberOfPointersRequired = 1
32
+ numberOfPointersRequired = DEFAULT_NUMBER_OF_POINTERS_REQUIRED
33
33
  }
34
34
 
35
35
  override fun resetConfig() {
36
36
  super.resetConfig()
37
37
  minDurationMs = DEFAULT_MIN_DURATION_MS
38
38
  maxDist = defaultMaxDist
39
+ numberOfPointersRequired = DEFAULT_NUMBER_OF_POINTERS_REQUIRED
39
40
  shouldCancelWhenOutside = DEFAULT_SHOULD_CANCEL_WHEN_OUTSIDE
40
41
  }
41
42
 
@@ -66,7 +67,7 @@ class LongPressGestureHandler(context: Context) : GestureHandler() {
66
67
  }
67
68
 
68
69
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
69
- if (!shouldActivateWithMouse(sourceEvent)) {
70
+ if (shouldSkipEvent(sourceEvent)) {
70
71
  return
71
72
  }
72
73
 
@@ -99,7 +100,8 @@ class LongPressGestureHandler(context: Context) : GestureHandler() {
99
100
  currentPointers == numberOfPointersRequired &&
100
101
  (
101
102
  sourceEvent.actionMasked == MotionEvent.ACTION_DOWN ||
102
- sourceEvent.actionMasked == MotionEvent.ACTION_POINTER_DOWN
103
+ sourceEvent.actionMasked == MotionEvent.ACTION_POINTER_DOWN ||
104
+ sourceEvent.actionMasked == MotionEvent.ACTION_BUTTON_PRESS
103
105
  )
104
106
  ) {
105
107
  handler = Handler(Looper.getMainLooper())
@@ -207,5 +209,6 @@ class LongPressGestureHandler(context: Context) : GestureHandler() {
207
209
  private const val DEFAULT_SHOULD_CANCEL_WHEN_OUTSIDE = true
208
210
  private const val DEFAULT_MIN_DURATION_MS: Long = 500
209
211
  private const val DEFAULT_MAX_DIST_DP = 10f
212
+ private const val DEFAULT_NUMBER_OF_POINTERS_REQUIRED = 1
210
213
  }
211
214
  }
@@ -109,6 +109,9 @@ class NativeViewGestureHandler : GestureHandler() {
109
109
  cancel()
110
110
  } else {
111
111
  hook.sendTouchEvent(view, event)
112
+ if (shouldStopNestedScroll()) {
113
+ view.stopNestedScroll()
114
+ }
112
115
 
113
116
  if ((state == STATE_UNDETERMINED || state == STATE_BEGAN) && hook.canActivate(view)) {
114
117
  activate()
@@ -156,9 +159,19 @@ class NativeViewGestureHandler : GestureHandler() {
156
159
  action = MotionEvent.ACTION_CANCEL
157
160
  }
158
161
  hook.sendTouchEvent(view, event)
162
+ if (shouldStopNestedScroll()) {
163
+ view?.stopNestedScroll()
164
+ }
159
165
  event.recycle()
160
166
  }
161
167
 
168
+ // Once the handler is active, it delivers touches straight to the view's `onTouchEvent`. Normally
169
+ // touches arrive through `View.dispatchTouchEvent`, which also ends the nested scroll when the finger
170
+ // goes up. Because we skip it, the nested scroll stays open and the parent never finds out that the
171
+ // gesture is over - e.g. SwipeRefreshLayout never fires refresh (#4485). While the handler is not
172
+ // active, the view still receives touches the regular way, so Android takes care of it.
173
+ private fun shouldStopNestedScroll() = state == STATE_ACTIVE && hook.shouldStopNestedScroll()
174
+
162
175
  override fun onCancel() = dispatchCancelEventToView()
163
176
 
164
177
  override fun onFail() = dispatchCancelEventToView()
@@ -211,6 +224,12 @@ class NativeViewGestureHandler : GestureHandler() {
211
224
  */
212
225
  fun canBegin(event: MotionEvent) = true
213
226
 
227
+ /**
228
+ * Whether the view's nested scroll should be stopped when the active gesture ends. Touches
229
+ * are fed through `onTouchEvent`, so `View.dispatchTouchEvent` never gets to do it.
230
+ */
231
+ fun shouldStopNestedScroll() = false
232
+
214
233
  /**
215
234
  * Checks whether handler can activate. Used by TextViewHook.
216
235
  */
@@ -336,6 +355,10 @@ class NativeViewGestureHandler : GestureHandler() {
336
355
 
337
356
  private class ScrollViewHook : NativeViewGestureHandlerHook {
338
357
  override fun shouldCancelRootViewGestureHandlerIfNecessary() = true
358
+
359
+ // ScrollView starts a nested scroll on DOWN but never stops it itself. Without this the
360
+ // parent's `onStopNestedScroll` never runs, e.g. SwipeRefreshLayout never triggers refresh.
361
+ override fun shouldStopNestedScroll() = true
339
362
  }
340
363
 
341
364
  private class ReactViewGroupHook : NativeViewGestureHandlerHook {
@@ -11,6 +11,7 @@ import com.facebook.react.uimanager.PixelUtil
11
11
  import com.swmansion.gesturehandler.core.GestureUtils.getLastPointerX
12
12
  import com.swmansion.gesturehandler.core.GestureUtils.getLastPointerY
13
13
  import com.swmansion.gesturehandler.react.eventbuilders.PanGestureHandlerEventDataBuilder
14
+ import kotlin.math.abs
14
15
 
15
16
  class PanGestureHandler(context: Context?) : GestureHandler() {
16
17
  var velocityX = 0f
@@ -113,15 +114,11 @@ class PanGestureHandler(context: Context?) : GestureHandler() {
113
114
  return true
114
115
  }
115
116
  val vx = velocityX
116
- if (minVelocityX != MIN_VALUE_IGNORE &&
117
- (minVelocityX < 0 && vx <= minVelocityX || minVelocityX in 0.0f..vx)
118
- ) {
117
+ if (minVelocityX != MIN_VALUE_IGNORE && abs(vx) >= abs(minVelocityX)) {
119
118
  return true
120
119
  }
121
120
  val vy = velocityY
122
- if (minVelocityY != MIN_VALUE_IGNORE &&
123
- (minVelocityY < 0 && vx <= minVelocityY || minVelocityY in 0.0f..vx)
124
- ) {
121
+ if (minVelocityY != MIN_VALUE_IGNORE && abs(vy) >= abs(minVelocityY)) {
125
122
  return true
126
123
  }
127
124
  val velocitySq = vx * vx + vy * vy
@@ -149,7 +146,7 @@ class PanGestureHandler(context: Context?) : GestureHandler() {
149
146
  }
150
147
 
151
148
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
152
- if (!shouldActivateWithMouse(sourceEvent)) {
149
+ if (shouldSkipEvent(sourceEvent)) {
153
150
  return
154
151
  }
155
152
 
@@ -82,7 +82,7 @@ class TapGestureHandler : GestureHandler() {
82
82
  }
83
83
 
84
84
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
85
- if (!shouldActivateWithMouse(sourceEvent)) {
85
+ if (shouldSkipEvent(sourceEvent)) {
86
86
  return
87
87
  }
88
88
 
@@ -19,3 +19,6 @@ fun Context.isScreenReaderOn() =
19
19
  fun MotionEvent.isHoverAction(): Boolean = action == MotionEvent.ACTION_HOVER_MOVE ||
20
20
  action == MotionEvent.ACTION_HOVER_ENTER ||
21
21
  action == MotionEvent.ACTION_HOVER_EXIT
22
+
23
+ fun MotionEvent.isButtonAction(): Boolean = actionMasked == MotionEvent.ACTION_BUTTON_PRESS ||
24
+ actionMasked == MotionEvent.ACTION_BUTTON_RELEASE
@@ -554,6 +554,8 @@ class RNGestureHandlerButtonViewManager :
554
554
  // by default Viewgroup would pass hotspot change events
555
555
  }
556
556
 
557
+ override fun shouldDelayChildPressedState(): Boolean = false
558
+
557
559
  private fun findGestureHandlerRootView(): RNGestureHandlerRootView? {
558
560
  var parent: ViewParent? = this.parent
559
561
  var gestureHandlerRootView: RNGestureHandlerRootView? = null
@@ -19,6 +19,7 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
19
19
  private val jsGestureHandler: GestureHandler?
20
20
  val rootView: ViewGroup
21
21
  private var shouldIntercept = false
22
+ private var wasIntercepting = false
22
23
  private var passingTouch = false
23
24
 
24
25
  init {
@@ -118,6 +119,14 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
118
119
  passingTouch = true
119
120
  orchestrator!!.onTouchEvent(event)
120
121
  passingTouch = false
122
+
123
+ // On the transition into interception, cancel the native views the pointers landed on - the
124
+ // framework's ACTION_CANCEL never reaches them since RNGH ignores `onInterceptTouchEvent`
125
+ if (shouldIntercept && !wasIntercepting) {
126
+ orchestrator!!.cancelTouchesInInterceptedViews(event)
127
+ }
128
+ wasIntercepting = shouldIntercept
129
+
121
130
  return shouldIntercept
122
131
  }
123
132
 
@@ -40,12 +40,14 @@ class RNGestureHandlerRootView(context: Context?) : ReactViewGroup(context) {
40
40
  super.dispatchTouchEvent(event)
41
41
  }
42
42
 
43
- override fun dispatchGenericMotionEvent(ev: MotionEvent) =
44
- if (rootViewEnabled && ev.isHoverAction() && rootHelper!!.dispatchTouchEvent(ev)) {
45
- true
46
- } else {
47
- super.dispatchGenericMotionEvent(ev)
48
- }
43
+ override fun dispatchGenericMotionEvent(ev: MotionEvent) = if (rootViewEnabled &&
44
+ (ev.isHoverAction() || ev.isButtonAction()) &&
45
+ rootHelper!!.dispatchTouchEvent(ev)
46
+ ) {
47
+ true
48
+ } else {
49
+ super.dispatchGenericMotionEvent(ev)
50
+ }
49
51
 
50
52
  override fun requestDisallowInterceptTouchEvent(disallowIntercept: Boolean) {
51
53
  if (rootViewEnabled) {
@@ -54,13 +54,8 @@ class RNGestureHandlerTouchEvent private constructor() : Event<RNGestureHandlerT
54
54
  putInt("eventType", handler.touchEventType)
55
55
  putInt("pointerType", handler.pointerType)
56
56
 
57
- handler.consumeChangedTouchesPayload()?.let {
58
- putArray("changedTouches", it)
59
- }
60
-
61
- handler.consumeAllTouchesPayload()?.let {
62
- putArray("allTouches", it)
63
- }
57
+ putArray("changedTouches", handler.consumeChangedTouchesPayload() ?: Arguments.createArray())
58
+ putArray("allTouches", handler.consumeAllTouchesPayload() ?: Arguments.createArray())
64
59
 
65
60
  if (handler.isAwaiting && handler.state == GestureHandler.STATE_ACTIVE) {
66
61
  putInt("state", GestureHandler.STATE_BEGAN)