react-native-gesture-handler 2.15.0 → 2.16.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 (254) hide show
  1. package/RNGestureHandler.podspec +2 -23
  2. package/android/build.gradle +1 -1
  3. package/android/noreanimated/src/main/java/com/swmansion/gesturehandler/ReanimatedEventDispatcher.kt +2 -0
  4. package/android/paper/src/main/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerDelegate.java +9 -0
  5. package/android/paper/src/main/java/com/facebook/react/viewmanagers/RNGestureHandlerButtonManagerInterface.java +3 -0
  6. package/android/src/main/java/com/swmansion/gesturehandler/RNGestureHandlerPackage.kt +11 -6
  7. package/android/src/main/java/com/swmansion/gesturehandler/core/DiagonalDirections.kt +8 -0
  8. package/android/src/main/java/com/swmansion/gesturehandler/core/FlingGestureHandler.kt +65 -24
  9. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +86 -22
  10. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +54 -29
  11. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureUtils.kt +3 -0
  12. package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +5 -1
  13. package/android/src/main/java/com/swmansion/gesturehandler/core/PanGestureHandler.kt +5 -1
  14. package/android/src/main/java/com/swmansion/gesturehandler/core/TapGestureHandler.kt +7 -3
  15. package/android/src/main/java/com/swmansion/gesturehandler/core/Vector.kt +66 -0
  16. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerButtonViewManager.kt +119 -19
  17. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerEnabledRootView.kt +2 -2
  18. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerEvent.kt +1 -4
  19. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +8 -5
  20. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt +7 -4
  21. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootView.kt +1 -1
  22. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerStateChangeEvent.kt +1 -4
  23. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerTouchEvent.kt +4 -7
  24. package/android/src/main/java/com/swmansion/gesturehandler/react/eventbuilders/GestureHandlerEventDataBuilder.kt +3 -0
  25. package/android/src/main/jni/cpp-adapter.cpp +18 -22
  26. package/apple/Handlers/RNFlingHandler.m +5 -4
  27. package/apple/Handlers/RNForceTouchHandler.m +3 -1
  28. package/apple/Handlers/RNHoverHandler.m +2 -1
  29. package/apple/Handlers/RNLongPressHandler.m +8 -14
  30. package/apple/Handlers/RNManualHandler.m +1 -0
  31. package/apple/Handlers/RNNativeViewHandler.mm +9 -7
  32. package/apple/Handlers/RNPanHandler.m +7 -2
  33. package/apple/Handlers/RNPinchHandler.m +50 -26
  34. package/apple/Handlers/RNRotationHandler.m +43 -29
  35. package/apple/Handlers/RNTapHandler.m +6 -4
  36. package/apple/RNGestureHandler.h +9 -0
  37. package/apple/RNGestureHandler.m +41 -4
  38. package/apple/RNGestureHandlerEvents.h +18 -9
  39. package/apple/RNGestureHandlerEvents.m +29 -11
  40. package/apple/RNGestureHandlerManager.h +5 -0
  41. package/apple/RNGestureHandlerManager.mm +32 -6
  42. package/apple/RNGestureHandlerModule.h +5 -3
  43. package/apple/RNGestureHandlerModule.mm +33 -19
  44. package/apple/RNGestureHandlerPointerType.h +8 -0
  45. package/lib/commonjs/Directions.js +19 -6
  46. package/lib/commonjs/Directions.js.map +1 -1
  47. package/lib/commonjs/PointerType.js +16 -0
  48. package/lib/commonjs/PointerType.js.map +1 -0
  49. package/lib/commonjs/RNGestureHandlerModule.web.js +7 -61
  50. package/lib/commonjs/RNGestureHandlerModule.web.js.map +1 -1
  51. package/lib/commonjs/components/DrawerLayout.js.map +1 -1
  52. package/lib/commonjs/components/GestureHandlerRootView.android.js +17 -2
  53. package/lib/commonjs/components/GestureHandlerRootView.android.js.map +1 -1
  54. package/lib/commonjs/components/GestureHandlerRootView.js +15 -2
  55. package/lib/commonjs/components/GestureHandlerRootView.js.map +1 -1
  56. package/lib/commonjs/components/GestureHandlerRootView.web.js +15 -2
  57. package/lib/commonjs/components/GestureHandlerRootView.web.js.map +1 -1
  58. package/lib/commonjs/components/Swipeable.js +3 -1
  59. package/lib/commonjs/components/Swipeable.js.map +1 -1
  60. package/lib/commonjs/components/touchables/GenericTouchable.js +1 -0
  61. package/lib/commonjs/components/touchables/GenericTouchable.js.map +1 -1
  62. package/lib/commonjs/getShadowNodeFromRef.js +19 -2
  63. package/lib/commonjs/getShadowNodeFromRef.js.map +1 -1
  64. package/lib/commonjs/handlers/createHandler.js +5 -0
  65. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  66. package/lib/commonjs/handlers/customDirectEventTypes.js +14 -0
  67. package/lib/commonjs/handlers/customDirectEventTypes.js.map +1 -0
  68. package/lib/commonjs/handlers/customDirectEventTypes.web.js +11 -0
  69. package/lib/commonjs/handlers/customDirectEventTypes.web.js.map +1 -0
  70. package/lib/commonjs/handlers/gestureHandlerCommon.js +13 -2
  71. package/lib/commonjs/handlers/gestureHandlerCommon.js.map +1 -1
  72. package/lib/commonjs/handlers/gestures/GestureDetector.js +10 -0
  73. package/lib/commonjs/handlers/gestures/GestureDetector.js.map +1 -1
  74. package/lib/commonjs/handlers/gestures/gesture.js.map +1 -1
  75. package/lib/commonjs/index.js +11 -3
  76. package/lib/commonjs/index.js.map +1 -1
  77. package/lib/commonjs/mocks.js +2 -0
  78. package/lib/commonjs/mocks.js.map +1 -1
  79. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
  80. package/lib/commonjs/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  81. package/lib/commonjs/web/Gestures.js +66 -0
  82. package/lib/commonjs/web/Gestures.js.map +1 -0
  83. package/lib/commonjs/web/constants.js +3 -8
  84. package/lib/commonjs/web/constants.js.map +1 -1
  85. package/lib/commonjs/web/handlers/FlingGestureHandler.js +36 -12
  86. package/lib/commonjs/web/handlers/FlingGestureHandler.js.map +1 -1
  87. package/lib/commonjs/web/handlers/GestureHandler.js +10 -5
  88. package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
  89. package/lib/commonjs/web/handlers/IGestureHandler.js +2 -0
  90. package/lib/commonjs/web/handlers/IGestureHandler.js.map +1 -0
  91. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js +5 -6
  92. package/lib/commonjs/web/handlers/NativeViewGestureHandler.js.map +1 -1
  93. package/lib/commonjs/web/interfaces.js +1 -23
  94. package/lib/commonjs/web/interfaces.js.map +1 -1
  95. package/lib/commonjs/web/tools/EventManager.js.map +1 -1
  96. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +117 -118
  97. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  98. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js +10 -5
  99. package/lib/commonjs/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  100. package/lib/commonjs/web/tools/InteractionManager.js +12 -3
  101. package/lib/commonjs/web/tools/InteractionManager.js.map +1 -1
  102. package/lib/commonjs/web/tools/NodeManager.js.map +1 -1
  103. package/lib/commonjs/web/tools/PointerEventManager.js +77 -27
  104. package/lib/commonjs/web/tools/PointerEventManager.js.map +1 -1
  105. package/lib/commonjs/web/tools/TouchEventManager.js +29 -6
  106. package/lib/commonjs/web/tools/TouchEventManager.js.map +1 -1
  107. package/lib/commonjs/web/tools/Vector.js +58 -0
  108. package/lib/commonjs/web/tools/Vector.js.map +1 -0
  109. package/lib/commonjs/web/utils.js +14 -0
  110. package/lib/commonjs/web/utils.js.map +1 -1
  111. package/lib/commonjs/web_hammer/NodeManager.js.map +1 -1
  112. package/lib/module/Directions.js +16 -4
  113. package/lib/module/Directions.js.map +1 -1
  114. package/lib/module/PointerType.js +9 -0
  115. package/lib/module/PointerType.js.map +1 -0
  116. package/lib/module/RNGestureHandlerModule.web.js +2 -39
  117. package/lib/module/RNGestureHandlerModule.web.js.map +1 -1
  118. package/lib/module/components/DrawerLayout.js.map +1 -1
  119. package/lib/module/components/GestureHandlerRootView.android.js +15 -2
  120. package/lib/module/components/GestureHandlerRootView.android.js.map +1 -1
  121. package/lib/module/components/GestureHandlerRootView.js +15 -3
  122. package/lib/module/components/GestureHandlerRootView.js.map +1 -1
  123. package/lib/module/components/GestureHandlerRootView.web.js +15 -3
  124. package/lib/module/components/GestureHandlerRootView.web.js.map +1 -1
  125. package/lib/module/components/Swipeable.js +3 -1
  126. package/lib/module/components/Swipeable.js.map +1 -1
  127. package/lib/module/components/touchables/GenericTouchable.js +1 -0
  128. package/lib/module/components/touchables/GenericTouchable.js.map +1 -1
  129. package/lib/module/getShadowNodeFromRef.js +19 -2
  130. package/lib/module/getShadowNodeFromRef.js.map +1 -1
  131. package/lib/module/handlers/createHandler.js +5 -1
  132. package/lib/module/handlers/createHandler.js.map +1 -1
  133. package/lib/module/handlers/customDirectEventTypes.js +3 -0
  134. package/lib/module/handlers/customDirectEventTypes.js.map +1 -0
  135. package/lib/module/handlers/customDirectEventTypes.web.js +5 -0
  136. package/lib/module/handlers/customDirectEventTypes.web.js.map +1 -0
  137. package/lib/module/handlers/gestureHandlerCommon.js +11 -1
  138. package/lib/module/handlers/gestureHandlerCommon.js.map +1 -1
  139. package/lib/module/handlers/gestures/GestureDetector.js +10 -0
  140. package/lib/module/handlers/gestures/GestureDetector.js.map +1 -1
  141. package/lib/module/handlers/gestures/gesture.js.map +1 -1
  142. package/lib/module/index.js +2 -1
  143. package/lib/module/index.js.map +1 -1
  144. package/lib/module/mocks.js +2 -0
  145. package/lib/module/mocks.js.map +1 -1
  146. package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
  147. package/lib/module/specs/RNGestureHandlerButtonNativeComponent.js.map +1 -1
  148. package/lib/module/web/Gestures.js +39 -0
  149. package/lib/module/web/Gestures.js.map +1 -0
  150. package/lib/module/web/constants.js +1 -6
  151. package/lib/module/web/constants.js.map +1 -1
  152. package/lib/module/web/handlers/FlingGestureHandler.js +34 -12
  153. package/lib/module/web/handlers/FlingGestureHandler.js.map +1 -1
  154. package/lib/module/web/handlers/GestureHandler.js +7 -4
  155. package/lib/module/web/handlers/GestureHandler.js.map +1 -1
  156. package/lib/module/web/handlers/IGestureHandler.js +2 -0
  157. package/lib/module/web/handlers/IGestureHandler.js.map +1 -0
  158. package/lib/module/web/handlers/NativeViewGestureHandler.js +5 -6
  159. package/lib/module/web/handlers/NativeViewGestureHandler.js.map +1 -1
  160. package/lib/module/web/interfaces.js +0 -20
  161. package/lib/module/web/interfaces.js.map +1 -1
  162. package/lib/module/web/tools/EventManager.js.map +1 -1
  163. package/lib/module/web/tools/GestureHandlerOrchestrator.js +116 -117
  164. package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  165. package/lib/module/web/tools/GestureHandlerWebDelegate.js +9 -4
  166. package/lib/module/web/tools/GestureHandlerWebDelegate.js.map +1 -1
  167. package/lib/module/web/tools/InteractionManager.js +9 -3
  168. package/lib/module/web/tools/InteractionManager.js.map +1 -1
  169. package/lib/module/web/tools/NodeManager.js.map +1 -1
  170. package/lib/module/web/tools/PointerEventManager.js +75 -27
  171. package/lib/module/web/tools/PointerEventManager.js.map +1 -1
  172. package/lib/module/web/tools/TouchEventManager.js +28 -6
  173. package/lib/module/web/tools/TouchEventManager.js.map +1 -1
  174. package/lib/module/web/tools/Vector.js +47 -0
  175. package/lib/module/web/tools/Vector.js.map +1 -0
  176. package/lib/module/web/utils.js +4 -0
  177. package/lib/module/web/utils.js.map +1 -1
  178. package/lib/module/web_hammer/NodeManager.js.map +1 -1
  179. package/lib/typescript/Directions.d.ts +7 -0
  180. package/lib/typescript/PointerType.d.ts +6 -0
  181. package/lib/typescript/RNGestureHandlerModule.web.d.ts +4 -39
  182. package/lib/typescript/components/DrawerLayout.d.ts +1 -2
  183. package/lib/typescript/components/GestureHandlerRootView.android.d.ts +1 -1
  184. package/lib/typescript/components/GestureHandlerRootView.d.ts +1 -1
  185. package/lib/typescript/components/GestureHandlerRootView.web.d.ts +1 -1
  186. package/lib/typescript/components/touchables/GenericTouchable.d.ts +2 -1
  187. package/lib/typescript/getShadowNodeFromRef.d.ts +1 -1
  188. package/lib/typescript/handlers/NativeViewGestureHandler.d.ts +1 -1
  189. package/lib/typescript/handlers/customDirectEventTypes.d.ts +1 -0
  190. package/lib/typescript/handlers/customDirectEventTypes.web.d.ts +2 -0
  191. package/lib/typescript/handlers/gestureHandlerCommon.d.ts +13 -2
  192. package/lib/typescript/handlers/gestures/GestureDetector.d.ts +2 -1
  193. package/lib/typescript/handlers/gestures/gesture.d.ts +1 -2
  194. package/lib/typescript/index.d.ts +2 -1
  195. package/lib/typescript/mocks.d.ts +1 -0
  196. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +6 -6
  197. package/lib/typescript/specs/RNGestureHandlerButtonNativeComponent.d.ts +4 -1
  198. package/lib/typescript/web/Gestures.d.ts +36 -0
  199. package/lib/typescript/web/constants.d.ts +1 -6
  200. package/lib/typescript/web/handlers/FlingGestureHandler.d.ts +3 -3
  201. package/lib/typescript/web/handlers/GestureHandler.d.ts +12 -9
  202. package/lib/typescript/web/handlers/IGestureHandler.d.ts +38 -0
  203. package/lib/typescript/web/handlers/NativeViewGestureHandler.d.ts +1 -0
  204. package/lib/typescript/web/interfaces.d.ts +9 -16
  205. package/lib/typescript/web/tools/EventManager.d.ts +15 -12
  206. package/lib/typescript/web/tools/GestureHandlerDelegate.d.ts +3 -4
  207. package/lib/typescript/web/tools/GestureHandlerOrchestrator.d.ts +7 -5
  208. package/lib/typescript/web/tools/GestureHandlerWebDelegate.d.ts +3 -3
  209. package/lib/typescript/web/tools/InteractionManager.d.ts +6 -6
  210. package/lib/typescript/web/tools/NodeManager.d.ts +4 -3
  211. package/lib/typescript/web/tools/PointerEventManager.d.ts +11 -2
  212. package/lib/typescript/web/tools/TouchEventManager.d.ts +6 -1
  213. package/lib/typescript/web/tools/Vector.d.ts +15 -0
  214. package/lib/typescript/web/utils.d.ts +6 -4
  215. package/lib/typescript/web_hammer/NodeManager.d.ts +1 -1
  216. package/package.json +2 -1
  217. package/src/Directions.ts +21 -4
  218. package/src/PointerType.ts +6 -0
  219. package/src/RNGestureHandlerModule.web.ts +3 -44
  220. package/src/components/DrawerLayout.tsx +1 -1
  221. package/src/components/GestureHandlerRootView.android.tsx +13 -5
  222. package/src/components/GestureHandlerRootView.tsx +10 -5
  223. package/src/components/GestureHandlerRootView.web.tsx +10 -5
  224. package/src/components/Swipeable.tsx +2 -0
  225. package/src/components/touchables/GenericTouchable.tsx +3 -0
  226. package/src/getShadowNodeFromRef.ts +28 -6
  227. package/src/handlers/createHandler.tsx +14 -2
  228. package/src/handlers/customDirectEventTypes.ts +2 -0
  229. package/src/handlers/customDirectEventTypes.web.ts +5 -0
  230. package/src/handlers/gestureHandlerCommon.ts +30 -1
  231. package/src/handlers/gestures/GestureDetector.tsx +15 -0
  232. package/src/handlers/gestures/gesture.ts +1 -1
  233. package/src/index.ts +2 -1
  234. package/src/mocks.ts +2 -0
  235. package/src/specs/NativeRNGestureHandlerModule.ts +8 -8
  236. package/src/specs/RNGestureHandlerButtonNativeComponent.ts +4 -0
  237. package/src/web/Gestures.ts +41 -0
  238. package/src/web/constants.ts +1 -7
  239. package/src/web/handlers/FlingGestureHandler.ts +54 -24
  240. package/src/web/handlers/GestureHandler.ts +17 -12
  241. package/src/web/handlers/IGestureHandler.ts +50 -0
  242. package/src/web/handlers/NativeViewGestureHandler.ts +5 -6
  243. package/src/web/interfaces.ts +15 -17
  244. package/src/web/tools/EventManager.ts +16 -14
  245. package/src/web/tools/GestureHandlerDelegate.ts +3 -4
  246. package/src/web/tools/GestureHandlerOrchestrator.ts +162 -147
  247. package/src/web/tools/GestureHandlerWebDelegate.ts +14 -9
  248. package/src/web/tools/InteractionManager.ts +18 -12
  249. package/src/web/tools/NodeManager.ts +4 -3
  250. package/src/web/tools/PointerEventManager.ts +189 -154
  251. package/src/web/tools/TouchEventManager.ts +128 -120
  252. package/src/web/tools/Vector.ts +60 -0
  253. package/src/web/utils.ts +16 -4
  254. package/src/web_hammer/NodeManager.ts +1 -1
@@ -1,8 +1,5 @@
1
1
  require "json"
2
2
 
3
- new_arch_enabled = ENV['RCT_NEW_ARCH_ENABLED'] == '1'
4
- apple_platform = new_arch_enabled ? '11.0' : '9.0'
5
-
6
3
  Pod::Spec.new do |s|
7
4
  # NPM package specification
8
5
  package = JSON.parse(File.read(File.join(File.dirname(__FILE__), "package.json")))
@@ -16,29 +13,11 @@ Pod::Spec.new do |s|
16
13
  s.source = { :git => "https://github.com/software-mansion/react-native-gesture-handler", :tag => "#{s.version}" }
17
14
  s.source_files = "apple/**/*.{h,m,mm}"
18
15
  s.requires_arc = true
19
- s.platforms = { ios: apple_platform, tvos: apple_platform, osx: '10.15', visionos: '1.0' }
16
+ s.platforms = { ios: '11.0', tvos: '11.0', osx: '10.15', visionos: '1.0' }
20
17
 
21
18
  if defined?(install_modules_dependencies()) != nil
22
19
  install_modules_dependencies(s);
23
20
  else
24
- if new_arch_enabled
25
- folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
26
-
27
- s.pod_target_xcconfig = {
28
- 'HEADER_SEARCH_PATHS' => '"$(PODS_ROOT)/boost" "$(PODS_ROOT)/boost-for-react-native" "$(PODS_ROOT)/RCT-Folly"',
29
- 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17',
30
- }
31
- s.compiler_flags = folly_compiler_flags + ' -DRCT_NEW_ARCH_ENABLED'
32
-
33
- s.dependency "React"
34
- s.dependency "React-RCTFabric" # This is for fabric component
35
- s.dependency "React-Codegen"
36
- s.dependency "RCT-Folly"
37
- s.dependency "RCTRequired"
38
- s.dependency "RCTTypeSafety"
39
- s.dependency "ReactCommon/turbomodule/core"
40
- else
41
- s.dependency "React-Core"
42
- end
21
+ s.dependency "React-Core"
43
22
  end
44
23
  end
@@ -136,7 +136,7 @@ android {
136
136
  var appProject = rootProject.allprojects.find {it.plugins.hasPlugin('com.android.application')}
137
137
  externalNativeBuild {
138
138
  cmake {
139
- cppFlags "-O2", "-frtti", "-fexceptions", "-Wall", "-Werror", "-std=c++17", "-DANDROID"
139
+ cppFlags "-O2", "-frtti", "-fexceptions", "-Wall", "-Werror", "-std=c++20", "-DANDROID"
140
140
  arguments "-DAPP_BUILD_DIR=${appProject.buildDir}",
141
141
  "-DREACT_NATIVE_DIR=${REACT_NATIVE_DIR}",
142
142
  "-DREACT_NATIVE_MINOR_VERSION=${REACT_NATIVE_MINOR_VERSION}",
@@ -4,6 +4,8 @@ import com.facebook.react.bridge.ReactContext
4
4
  import com.facebook.react.uimanager.events.Event
5
5
 
6
6
  class ReanimatedEventDispatcher {
7
+ @Suppress("UNUSED_PARAMETER", "COMMENT_IN_SUPPRESSION")
8
+ // This is necessary on new architecture
7
9
  fun <T : Event<T>>sendEvent(event: T, reactApplicationContext: ReactContext) {
8
10
  // no-op
9
11
  }
@@ -43,6 +43,15 @@ public class RNGestureHandlerButtonManagerDelegate<T extends View, U extends Bas
43
43
  case "touchSoundDisabled":
44
44
  mViewManager.setTouchSoundDisabled(view, value == null ? false : (boolean) value);
45
45
  break;
46
+ case "borderWidth":
47
+ mViewManager.setBorderWidth(view, value == null ? 0f : ((Double) value).floatValue());
48
+ break;
49
+ case "borderColor":
50
+ mViewManager.setBorderColor(view, ColorPropConverter.getColor(value, view.getContext()));
51
+ break;
52
+ case "borderStyle":
53
+ mViewManager.setBorderStyle(view, value == null ? "solid" : (String) value);
54
+ break;
46
55
  default:
47
56
  super.setProperty(view, propName, value);
48
57
  }
@@ -20,4 +20,7 @@ public interface RNGestureHandlerButtonManagerInterface<T extends View> {
20
20
  void setRippleColor(T view, @Nullable Integer value);
21
21
  void setRippleRadius(T view, int value);
22
22
  void setTouchSoundDisabled(T view, boolean value);
23
+ void setBorderWidth(T view, float value);
24
+ void setBorderColor(T view, @Nullable Integer value);
25
+ void setBorderStyle(T view, @Nullable String value);
23
26
  }
@@ -6,14 +6,19 @@ import com.facebook.react.bridge.ModuleSpec
6
6
  import com.facebook.react.bridge.NativeModule
7
7
  import com.facebook.react.bridge.ReactApplicationContext
8
8
  import com.facebook.react.module.annotations.ReactModule
9
+ import com.facebook.react.module.annotations.ReactModuleList
9
10
  import com.facebook.react.module.model.ReactModuleInfo
10
11
  import com.facebook.react.module.model.ReactModuleInfoProvider
11
- import com.facebook.react.turbomodule.core.interfaces.TurboModule
12
12
  import com.facebook.react.uimanager.ViewManager
13
13
  import com.swmansion.gesturehandler.react.RNGestureHandlerButtonViewManager
14
14
  import com.swmansion.gesturehandler.react.RNGestureHandlerModule
15
15
  import com.swmansion.gesturehandler.react.RNGestureHandlerRootViewManager
16
16
 
17
+ @ReactModuleList(
18
+ nativeModules = [
19
+ RNGestureHandlerModule::class
20
+ ]
21
+ )
17
22
  class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPackage {
18
23
  private val viewManagers: Map<String, ModuleSpec> by lazy {
19
24
  mapOf(
@@ -44,7 +49,7 @@ class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPac
44
49
  ) = viewManagers[viewManagerName]?.provider?.get() as? ViewManager<*, *>
45
50
 
46
51
  override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
47
- return if (name == RNGestureHandlerModule.MODULE_NAME) {
52
+ return if (name == RNGestureHandlerModule.NAME) {
48
53
  RNGestureHandlerModule(reactContext)
49
54
  } else {
50
55
  null
@@ -55,20 +60,20 @@ class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPac
55
60
  try {
56
61
  val reactModuleInfoProviderClass =
57
62
  Class.forName("com.swmansion.gesturehandler.RNGestureHandlerPackage$\$ReactModuleInfoProvider")
58
- return reactModuleInfoProviderClass.newInstance() as ReactModuleInfoProvider
63
+ return reactModuleInfoProviderClass.getDeclaredConstructor().newInstance() as ReactModuleInfoProvider
59
64
  } catch (e: ClassNotFoundException) {
60
65
  return ReactModuleInfoProvider {
61
66
  val reactModule: ReactModule = RNGestureHandlerModule::class.java.getAnnotation(ReactModule::class.java)!!
62
67
 
63
68
  mutableMapOf(
64
- RNGestureHandlerModule.MODULE_NAME to ReactModuleInfo(
69
+ RNGestureHandlerModule.NAME to ReactModuleInfo(
65
70
  reactModule.name,
66
71
  RNGestureHandlerModule::class.java.name,
67
72
  reactModule.canOverrideExistingModule,
68
73
  reactModule.needsEagerInit,
69
- reactModule.hasConstants,
74
+ true, // Has constants is hardcoded to return true, so replacing it with `true` changes nothing.
70
75
  reactModule.isCxxModule,
71
- TurboModule::class.java.isAssignableFrom(RNGestureHandlerModule::class.java)
76
+ true
72
77
  )
73
78
  )
74
79
  }
@@ -0,0 +1,8 @@
1
+ package com.swmansion.gesturehandler.core
2
+
3
+ object DiagonalDirections {
4
+ const val DIRECTION_RIGHT_UP = GestureHandler.DIRECTION_RIGHT or GestureHandler.DIRECTION_UP
5
+ const val DIRECTION_RIGHT_DOWN = GestureHandler.DIRECTION_RIGHT or GestureHandler.DIRECTION_DOWN
6
+ const val DIRECTION_LEFT_UP = GestureHandler.DIRECTION_LEFT or GestureHandler.DIRECTION_UP
7
+ const val DIRECTION_LEFT_DOWN = GestureHandler.DIRECTION_LEFT or GestureHandler.DIRECTION_DOWN
8
+ }
@@ -3,18 +3,18 @@ package com.swmansion.gesturehandler.core
3
3
  import android.os.Handler
4
4
  import android.os.Looper
5
5
  import android.view.MotionEvent
6
+ import android.view.VelocityTracker
6
7
 
7
8
  class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
8
9
  var numberOfPointersRequired = DEFAULT_NUMBER_OF_TOUCHES_REQUIRED
9
10
  var direction = DEFAULT_DIRECTION
10
11
 
11
12
  private val maxDurationMs = DEFAULT_MAX_DURATION_MS
12
- private val minAcceptableDelta = DEFAULT_MIN_ACCEPTABLE_DELTA
13
- private var startX = 0f
14
- private var startY = 0f
13
+ private val minVelocity = DEFAULT_MIN_VELOCITY
15
14
  private var handler: Handler? = null
16
15
  private var maxNumberOfPointersSimultaneously = 0
17
16
  private val failDelayed = Runnable { fail() }
17
+ private var velocityTracker: VelocityTracker? = null
18
18
 
19
19
  override fun resetConfig() {
20
20
  super.resetConfig()
@@ -23,8 +23,7 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
23
23
  }
24
24
 
25
25
  private fun startFling(event: MotionEvent) {
26
- startX = event.rawX
27
- startY = event.rawY
26
+ velocityTracker = VelocityTracker.obtain()
28
27
  begin()
29
28
  maxNumberOfPointersSimultaneously = 1
30
29
  if (handler == null) {
@@ -35,26 +34,48 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
35
34
  handler!!.postDelayed(failDelayed, maxDurationMs)
36
35
  }
37
36
 
38
- private fun tryEndFling(event: MotionEvent) = if (
39
- maxNumberOfPointersSimultaneously == numberOfPointersRequired &&
40
- (
41
- direction and DIRECTION_RIGHT != 0 &&
42
- event.rawX - startX > minAcceptableDelta ||
43
- direction and DIRECTION_LEFT != 0 &&
44
- startX - event.rawX > minAcceptableDelta ||
45
- direction and DIRECTION_UP != 0 &&
46
- startY - event.rawY > minAcceptableDelta ||
47
- direction and DIRECTION_DOWN != 0 &&
48
- event.rawY - startY > minAcceptableDelta
37
+ private fun tryEndFling(event: MotionEvent): Boolean {
38
+ addVelocityMovement(velocityTracker, event)
39
+
40
+ val velocityVector = Vector.fromVelocity(velocityTracker!!)
41
+
42
+ fun getVelocityAlignment(
43
+ direction: Int,
44
+ maxDeviationCosine: Double,
45
+ ): Boolean = (
46
+ (this.direction and direction) == direction &&
47
+ velocityVector.isSimilar(Vector.fromDirection(direction), maxDeviationCosine)
49
48
  )
50
- ) {
51
- handler!!.removeCallbacksAndMessages(null)
52
- activate()
53
- true
54
- } else {
55
- false
56
- }
57
49
 
50
+ val axialAlignmentsList = arrayOf(
51
+ DIRECTION_LEFT,
52
+ DIRECTION_RIGHT,
53
+ DIRECTION_UP,
54
+ DIRECTION_DOWN,
55
+ ).map { direction -> getVelocityAlignment(direction, MAX_AXIAL_DEVIATION) }
56
+
57
+ val diagonalAlignmentsList = arrayOf(
58
+ DiagonalDirections.DIRECTION_RIGHT_UP,
59
+ DiagonalDirections.DIRECTION_RIGHT_DOWN,
60
+ DiagonalDirections.DIRECTION_LEFT_UP,
61
+ DiagonalDirections.DIRECTION_LEFT_DOWN,
62
+ ).map { direction -> getVelocityAlignment(direction, MAX_DIAGONAL_DEVIATION) }
63
+
64
+ val isAligned = axialAlignmentsList.any { it } or diagonalAlignmentsList.any { it }
65
+ val isFast = velocityVector.magnitude > this.minVelocity
66
+
67
+ return if (
68
+ maxNumberOfPointersSimultaneously == numberOfPointersRequired &&
69
+ isAligned &&
70
+ isFast
71
+ ) {
72
+ handler!!.removeCallbacksAndMessages(null)
73
+ activate()
74
+ true
75
+ } else {
76
+ false
77
+ }
78
+ }
58
79
  override fun activate(force: Boolean) {
59
80
  super.activate(force)
60
81
  end()
@@ -67,6 +88,10 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
67
88
  }
68
89
 
69
90
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
91
+ if (!shouldActivateWithMouse(sourceEvent)) {
92
+ return
93
+ }
94
+
70
95
  val state = state
71
96
  if (state == STATE_UNDETERMINED) {
72
97
  startFling(sourceEvent)
@@ -88,13 +113,29 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
88
113
  }
89
114
 
90
115
  override fun onReset() {
116
+ velocityTracker?.recycle()
117
+ velocityTracker = null
91
118
  handler?.removeCallbacksAndMessages(null)
92
119
  }
93
120
 
121
+ private fun addVelocityMovement(tracker: VelocityTracker?, event: MotionEvent) {
122
+ val offsetX = event.rawX - event.x
123
+ val offsetY = event.rawY - event.y
124
+ event.offsetLocation(offsetX, offsetY)
125
+ tracker!!.addMovement(event)
126
+ event.offsetLocation(-offsetX, -offsetY)
127
+ }
128
+
94
129
  companion object {
95
130
  private const val DEFAULT_MAX_DURATION_MS: Long = 800
96
- private const val DEFAULT_MIN_ACCEPTABLE_DELTA: Long = 160
131
+ private const val DEFAULT_MIN_VELOCITY: Long = 2000
132
+ private const val DEFAULT_ALIGNMENT_CONE: Double = 30.0
97
133
  private const val DEFAULT_DIRECTION = DIRECTION_RIGHT
98
134
  private const val DEFAULT_NUMBER_OF_TOUCHES_REQUIRED = 1
135
+
136
+ private val MAX_AXIAL_DEVIATION: Double =
137
+ GestureUtils.coneToDeviation(DEFAULT_ALIGNMENT_CONE)
138
+ private val MAX_DIAGONAL_DEVIATION: Double =
139
+ GestureUtils.coneToDeviation(90 - DEFAULT_ALIGNMENT_CONE)
99
140
  }
100
141
  }
@@ -4,13 +4,13 @@ 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.graphics.Rect
7
+ import android.os.Build
8
8
  import android.view.MotionEvent
9
9
  import android.view.MotionEvent.PointerCoords
10
10
  import android.view.MotionEvent.PointerProperties
11
11
  import android.view.View
12
- import android.view.Window
13
12
  import com.facebook.react.bridge.Arguments
13
+ import com.facebook.react.bridge.ReactContext
14
14
  import com.facebook.react.bridge.UiThreadUtil
15
15
  import com.facebook.react.bridge.WritableArray
16
16
  import com.facebook.react.uimanager.PixelUtil
@@ -67,6 +67,10 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
67
67
  protected var orchestrator: GestureHandlerOrchestrator? = null
68
68
  private var onTouchEventListener: OnTouchEventListener? = null
69
69
  private var interactionController: GestureHandlerInteractionController? = null
70
+ var pointerType: Int = POINTER_TYPE_OTHER
71
+ private set
72
+
73
+ protected var mouseButton = 0
70
74
 
71
75
  @Suppress("UNCHECKED_CAST")
72
76
  protected fun self(): ConcreteGestureHandlerT = this as ConcreteGestureHandlerT
@@ -159,6 +163,10 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
159
163
  fun setInteractionController(controller: GestureHandlerInteractionController?): ConcreteGestureHandlerT =
160
164
  applySelf { interactionController = controller }
161
165
 
166
+ fun setMouseButton(mouseButton: Int) = apply {
167
+ this.mouseButton = mouseButton
168
+ }
169
+
162
170
  fun prepare(view: View?, orchestrator: GestureHandlerOrchestrator?) {
163
171
  check(!(this.view != null || this.orchestrator != null)) { "Already prepared or hasn't been reset" }
164
172
  Arrays.fill(trackedPointerIDs, -1)
@@ -167,12 +175,9 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
167
175
  this.view = view
168
176
  this.orchestrator = orchestrator
169
177
 
170
- val decorView = getWindow(view?.context)?.decorView
171
- if (decorView != null) {
172
- val frame = Rect()
173
- decorView.getWindowVisibleDisplayFrame(frame)
174
- windowOffset[0] = frame.left
175
- windowOffset[1] = frame.top
178
+ val content = getActivity(view?.context)?.findViewById<View>(android.R.id.content)
179
+ if (content != null) {
180
+ content.getLocationOnScreen(windowOffset)
176
181
  } else {
177
182
  windowOffset[0] = 0
178
183
  windowOffset[1] = 0
@@ -183,13 +188,13 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
183
188
 
184
189
  protected open fun onPrepare() {}
185
190
 
186
- private fun getWindow(context: Context?): Window? {
187
- if (context == null) return null
188
- if (context is Activity) return context.window
189
- if (context is ContextWrapper) return getWindow(context.baseContext)
190
-
191
- return null
192
- }
191
+ private fun getActivity(context: Context?): Activity? =
192
+ when (context) {
193
+ is ReactContext -> context.currentActivity
194
+ is Activity -> context
195
+ is ContextWrapper -> getActivity(context.baseContext)
196
+ else -> null
197
+ }
193
198
 
194
199
  private fun findNextLocalPointerId(): Int {
195
200
  var localPointerId = 0
@@ -371,6 +376,11 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
371
376
  lastAbsolutePositionY = GestureUtils.getLastPointerY(adaptedTransformedEvent, true)
372
377
  lastEventOffsetX = adaptedTransformedEvent.rawX - adaptedTransformedEvent.x
373
378
  lastEventOffsetY = adaptedTransformedEvent.rawY - adaptedTransformedEvent.y
379
+
380
+ if (sourceEvent.action == MotionEvent.ACTION_DOWN || sourceEvent.action == MotionEvent.ACTION_HOVER_ENTER || sourceEvent.action == MotionEvent.ACTION_HOVER_MOVE) {
381
+ setPointerType(sourceEvent)
382
+ }
383
+
374
384
  if (sourceEvent.action == MotionEvent.ACTION_HOVER_ENTER ||
375
385
  sourceEvent.action == MotionEvent.ACTION_HOVER_MOVE ||
376
386
  sourceEvent.action == MotionEvent.ACTION_HOVER_EXIT
@@ -642,7 +652,7 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
642
652
  }
643
653
 
644
654
  fun cancel() {
645
- if (state == STATE_ACTIVE || state == STATE_UNDETERMINED || state == STATE_BEGAN) {
655
+ if (state == STATE_ACTIVE || state == STATE_UNDETERMINED || state == STATE_BEGAN || this.isAwaiting) {
646
656
  onCancel()
647
657
  moveToState(STATE_CANCELLED)
648
658
  }
@@ -688,6 +698,46 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
688
698
  protected open fun onReset() {}
689
699
  protected open fun onCancel() {}
690
700
 
701
+ private fun isButtonInConfig(clickedButton: Int): Boolean {
702
+ if (mouseButton == 0) {
703
+ return clickedButton == MotionEvent.BUTTON_PRIMARY
704
+ }
705
+
706
+ return clickedButton and mouseButton != 0
707
+ }
708
+
709
+ protected fun shouldActivateWithMouse(sourceEvent: MotionEvent): Boolean {
710
+ // 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.
711
+ // On API >= 23, we will use events with infix BUTTON, otherwise we use standard action events (like ACTION_DOWN).
712
+
713
+ with(sourceEvent) {
714
+ // To use actionButton, we need API >= 23.
715
+ if (getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
716
+ // While using mouse, we want to ignore default events for touch.
717
+ if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN) {
718
+ return@shouldActivateWithMouse false
719
+ }
720
+
721
+ // 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.
722
+ if (action != MotionEvent.ACTION_MOVE && !isButtonInConfig(actionButton)) {
723
+ return@shouldActivateWithMouse false
724
+ }
725
+
726
+ // When we receive ACTION_MOVE, we have to check buttonState field.
727
+ if (action == MotionEvent.ACTION_MOVE && !isButtonInConfig(buttonState)) {
728
+ return@shouldActivateWithMouse false
729
+ }
730
+ } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
731
+ // We do not fully support mouse below API 23, so we will ignore BUTTON events.
732
+ if (action == MotionEvent.ACTION_BUTTON_PRESS || action == MotionEvent.ACTION_BUTTON_RELEASE) {
733
+ return@shouldActivateWithMouse false
734
+ }
735
+ }
736
+ }
737
+
738
+ return true
739
+ }
740
+
691
741
  /**
692
742
  * Transforms a point in the coordinate space of the wrapperView (GestureHandlerRootView) to
693
743
  * coordinate space of the view the gesture is attached to.
@@ -708,7 +758,6 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
708
758
  orchestrator = null
709
759
  Arrays.fill(trackedPointerIDs, -1)
710
760
  trackedPointersIDsCount = 0
711
-
712
761
  trackedPointersCount = 0
713
762
  trackedPointers.fill(null)
714
763
  touchEventType = RNGestureHandlerTouchEvent.EVENT_UNDETERMINED
@@ -721,6 +770,17 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
721
770
  isWithinBounds = false
722
771
  }
723
772
 
773
+ private fun setPointerType(event: MotionEvent) {
774
+ val pointerIndex = event.actionIndex
775
+
776
+ pointerType = when (event.getToolType(pointerIndex)) {
777
+ MotionEvent.TOOL_TYPE_FINGER -> POINTER_TYPE_TOUCH
778
+ MotionEvent.TOOL_TYPE_STYLUS -> POINTER_TYPE_STYLUS
779
+ MotionEvent.TOOL_TYPE_MOUSE -> POINTER_TYPE_MOUSE
780
+ else -> POINTER_TYPE_OTHER
781
+ }
782
+ }
783
+
724
784
  fun setOnTouchEventListener(listener: OnTouchEventListener?): GestureHandler<*> {
725
785
  onTouchEventListener = listener
726
786
  return this
@@ -763,19 +823,23 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
763
823
  const val ACTION_TYPE_NATIVE_ANIMATED_EVENT = 2
764
824
  const val ACTION_TYPE_JS_FUNCTION_OLD_API = 3
765
825
  const val ACTION_TYPE_JS_FUNCTION_NEW_API = 4
826
+ const val POINTER_TYPE_TOUCH = 0
827
+ const val POINTER_TYPE_STYLUS = 1
828
+ const val POINTER_TYPE_MOUSE = 2
829
+ const val POINTER_TYPE_OTHER = 3
766
830
  private const val MAX_POINTERS_COUNT = 12
767
831
  private lateinit var pointerProps: Array<PointerProperties?>
768
832
  private lateinit var pointerCoords: Array<PointerCoords?>
769
833
  private fun initPointerProps(size: Int) {
770
- var size = size
834
+ var pointerPropsSize = size
771
835
  if (!Companion::pointerProps.isInitialized) {
772
836
  pointerProps = arrayOfNulls(MAX_POINTERS_COUNT)
773
837
  pointerCoords = arrayOfNulls(MAX_POINTERS_COUNT)
774
838
  }
775
- while (size > 0 && pointerProps[size - 1] == null) {
776
- pointerProps[size - 1] = PointerProperties()
777
- pointerCoords[size - 1] = PointerCoords()
778
- size--
839
+ while (pointerPropsSize > 0 && pointerProps[pointerPropsSize - 1] == null) {
840
+ pointerProps[pointerPropsSize - 1] = PointerProperties()
841
+ pointerCoords[pointerPropsSize - 1] = PointerCoords()
842
+ pointerPropsSize--
779
843
  }
780
844
  }
781
845
 
@@ -7,6 +7,7 @@ import android.view.View
7
7
  import android.view.ViewGroup
8
8
  import android.widget.EditText
9
9
  import java.util.*
10
+ import kotlin.collections.HashSet
10
11
 
11
12
  class GestureHandlerOrchestrator(
12
13
  private val wrapperView: ViewGroup,
@@ -22,6 +23,14 @@ class GestureHandlerOrchestrator(
22
23
  private val gestureHandlers = arrayListOf<GestureHandler<*>>()
23
24
  private val awaitingHandlers = arrayListOf<GestureHandler<*>>()
24
25
  private val preparedHandlers = arrayListOf<GestureHandler<*>>()
26
+
27
+ // In `onHandlerStateChange` method we iterate through `awaitingHandlers`, but calling `tryActivate` may modify this list.
28
+ // To avoid `ConcurrentModificationException` we iterate through copy. There is one more problem though - if handler was
29
+ // removed from `awaitingHandlers`, it was still present in copy of original list. This hashset helps us identify which handlers
30
+ // are really inside `awaitingHandlers`.
31
+ // `contains` method on HashSet has O(1) complexity, so calling it inside for loop won't result in O(n^2) (contrary to ArrayList)
32
+ private val awaitingHandlersTags = HashSet<Int>()
33
+
25
34
  private var isHandlingTouch = false
26
35
  private var handlingChangeSemaphore = 0
27
36
  private var finishedHandlersCleanupScheduled = false
@@ -73,16 +82,18 @@ class GestureHandlerOrchestrator(
73
82
  finishedHandlersCleanupScheduled = false
74
83
  }
75
84
 
76
- private fun hasOtherHandlerToWaitFor(handler: GestureHandler<*>): Boolean {
77
- for (otherHandler in gestureHandlers) {
78
- if (!isFinished(otherHandler.state) && shouldHandlerWaitForOther(handler, otherHandler)) {
79
- return true
80
- }
81
- }
82
- return false
83
- }
85
+ private fun hasOtherHandlerToWaitFor(handler: GestureHandler<*>) =
86
+ gestureHandlers.any { !isFinished(it.state) && shouldHandlerWaitForOther(handler, it) }
87
+
88
+ private fun shouldBeCancelledByFinishedHandler(handler: GestureHandler<*>) = gestureHandlers.any { shouldHandlerWaitForOther(handler, it) && it.state == GestureHandler.STATE_END }
84
89
 
85
90
  private fun tryActivate(handler: GestureHandler<*>) {
91
+ // If we are waiting for a gesture that has successfully finished, we should cancel handler
92
+ if (shouldBeCancelledByFinishedHandler(handler)) {
93
+ handler.cancel()
94
+ return
95
+ }
96
+
86
97
  // see if there is anyone else who we need to wait for
87
98
  if (hasOtherHandlerToWaitFor(handler)) {
88
99
  addAwaitingHandler(handler)
@@ -94,34 +105,47 @@ class GestureHandlerOrchestrator(
94
105
  }
95
106
 
96
107
  private fun cleanupAwaitingHandlers() {
97
- awaitingHandlers.removeAll { !it.isAwaiting }
108
+ val awaitingHandlersCopy = awaitingHandlers.toList()
109
+
110
+ for (handler in awaitingHandlersCopy) {
111
+ if (!handler.isAwaiting) {
112
+ awaitingHandlers.remove(handler)
113
+ awaitingHandlersTags.remove(handler.tag)
114
+ }
115
+ }
98
116
  }
99
117
 
100
118
  /*package*/
101
119
  fun onHandlerStateChange(handler: GestureHandler<*>, newState: Int, prevState: Int) {
102
120
  handlingChangeSemaphore += 1
103
121
  if (isFinished(newState)) {
122
+ // We have to loop through copy in order to avoid modifying collection
123
+ // while iterating over its elements
124
+ val currentlyAwaitingHandlers = awaitingHandlers.toList()
125
+
104
126
  // if there were handlers awaiting completion of this handler, we can trigger active state
105
- for (otherHandler in awaitingHandlers) {
106
- if (shouldHandlerWaitForOther(otherHandler, handler)) {
107
- if (newState == GestureHandler.STATE_END) {
108
- // gesture has ended, we need to kill the awaiting handler
109
- otherHandler.cancel()
110
- if (otherHandler.state == GestureHandler.STATE_END) {
111
- // Handle edge case, where discrete gestures end immediately after activation thus
112
- // their state is set to END and when the gesture they are waiting for activates they
113
- // should be cancelled, however `cancel` was never sent as gestures were already in the END state.
114
- // Send synthetic BEGAN -> CANCELLED to properly handle JS logic
115
- otherHandler.dispatchStateChange(
116
- GestureHandler.STATE_CANCELLED,
117
- GestureHandler.STATE_BEGAN
118
- )
119
- }
120
- otherHandler.isAwaiting = false
121
- } else {
122
- // gesture has failed recognition, we may try activating
123
- tryActivate(otherHandler)
127
+ for (otherHandler in currentlyAwaitingHandlers) {
128
+ if (!shouldHandlerWaitForOther(otherHandler, handler) || !awaitingHandlersTags.contains(otherHandler.tag)) {
129
+ continue
130
+ }
131
+
132
+ if (newState == GestureHandler.STATE_END) {
133
+ // gesture has ended, we need to kill the awaiting handler
134
+ otherHandler.cancel()
135
+ if (otherHandler.state == GestureHandler.STATE_END) {
136
+ // Handle edge case, where discrete gestures end immediately after activation thus
137
+ // their state is set to END and when the gesture they are waiting for activates they
138
+ // should be cancelled, however `cancel` was never sent as gestures were already in the END state.
139
+ // Send synthetic BEGAN -> CANCELLED to properly handle JS logic
140
+ otherHandler.dispatchStateChange(
141
+ GestureHandler.STATE_CANCELLED,
142
+ GestureHandler.STATE_BEGAN
143
+ )
124
144
  }
145
+ otherHandler.isAwaiting = false
146
+ } else {
147
+ // gesture has failed recognition, we may try activating
148
+ tryActivate(otherHandler)
125
149
  }
126
150
  }
127
151
  cleanupAwaitingHandlers()
@@ -168,7 +192,6 @@ class GestureHandlerOrchestrator(
168
192
  // Clear all awaiting handlers waiting for the current handler to fail
169
193
  for (otherHandler in awaitingHandlers.reversed()) {
170
194
  if (shouldHandlerBeCancelledBy(otherHandler, handler)) {
171
- otherHandler.cancel()
172
195
  otherHandler.isAwaiting = false
173
196
  }
174
197
  }
@@ -383,6 +406,8 @@ class GestureHandlerOrchestrator(
383
406
  }
384
407
 
385
408
  awaitingHandlers.add(handler)
409
+ awaitingHandlersTags.add(handler.tag)
410
+
386
411
  with(handler) {
387
412
  isAwaiting = true
388
413
  activationIndex = this@GestureHandlerOrchestrator.activationIndex++
@@ -1,6 +1,7 @@
1
1
  package com.swmansion.gesturehandler.core
2
2
 
3
3
  import android.view.MotionEvent
4
+ import kotlin.math.cos
4
5
 
5
6
  object GestureUtils {
6
7
  fun getLastPointerX(event: MotionEvent, averageTouches: Boolean): Float {
@@ -44,4 +45,6 @@ object GestureUtils {
44
45
  event.getY(lastPointerIdx)
45
46
  }
46
47
  }
48
+ fun coneToDeviation(angle: Double): Double =
49
+ cos(Math.toRadians(angle / 2.0))
47
50
  }
@@ -38,6 +38,10 @@ class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestur
38
38
  }
39
39
 
40
40
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
41
+ if (!shouldActivateWithMouse(sourceEvent)) {
42
+ return
43
+ }
44
+
41
45
  if (state == STATE_UNDETERMINED) {
42
46
  previousTime = SystemClock.uptimeMillis()
43
47
  startTime = previousTime
@@ -51,7 +55,7 @@ class LongPressGestureHandler(context: Context) : GestureHandler<LongPressGestur
51
55
  activate()
52
56
  }
53
57
  }
54
- if (sourceEvent.actionMasked == MotionEvent.ACTION_UP) {
58
+ if (sourceEvent.actionMasked == MotionEvent.ACTION_UP || sourceEvent.actionMasked == MotionEvent.ACTION_BUTTON_RELEASE) {
55
59
  handler?.let {
56
60
  it.removeCallbacksAndMessages(null)
57
61
  handler = null