react-native-gesture-handler 2.15.0 → 2.16.0-rc.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 (115) hide show
  1. package/RNGestureHandler.podspec +2 -23
  2. package/android/build.gradle +1 -1
  3. package/android/src/main/java/com/swmansion/gesturehandler/RNGestureHandlerPackage.kt +9 -4
  4. package/android/src/main/java/com/swmansion/gesturehandler/core/FlingGestureHandler.kt +4 -0
  5. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandler.kt +69 -0
  6. package/android/src/main/java/com/swmansion/gesturehandler/core/GestureHandlerOrchestrator.kt +25 -19
  7. package/android/src/main/java/com/swmansion/gesturehandler/core/LongPressGestureHandler.kt +5 -1
  8. package/android/src/main/java/com/swmansion/gesturehandler/core/PanGestureHandler.kt +5 -1
  9. package/android/src/main/java/com/swmansion/gesturehandler/core/TapGestureHandler.kt +7 -3
  10. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerModule.kt +8 -5
  11. package/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRootHelper.kt +3 -2
  12. package/android/src/main/java/com/swmansion/gesturehandler/react/eventbuilders/GestureHandlerEventDataBuilder.kt +3 -0
  13. package/android/src/main/jni/cpp-adapter.cpp +18 -22
  14. package/apple/Handlers/RNFlingHandler.m +5 -4
  15. package/apple/Handlers/RNForceTouchHandler.m +3 -1
  16. package/apple/Handlers/RNHoverHandler.m +2 -1
  17. package/apple/Handlers/RNLongPressHandler.m +3 -1
  18. package/apple/Handlers/RNManualHandler.m +1 -0
  19. package/apple/Handlers/RNNativeViewHandler.mm +9 -7
  20. package/apple/Handlers/RNPanHandler.m +7 -2
  21. package/apple/Handlers/RNPinchHandler.m +38 -25
  22. package/apple/Handlers/RNRotationHandler.m +43 -29
  23. package/apple/Handlers/RNTapHandler.m +6 -4
  24. package/apple/RNGestureHandler.h +9 -0
  25. package/apple/RNGestureHandler.m +38 -3
  26. package/apple/RNGestureHandlerEvents.h +18 -9
  27. package/apple/RNGestureHandlerEvents.m +29 -11
  28. package/apple/RNGestureHandlerManager.h +5 -0
  29. package/apple/RNGestureHandlerManager.mm +32 -6
  30. package/apple/RNGestureHandlerModule.h +5 -3
  31. package/apple/RNGestureHandlerModule.mm +33 -19
  32. package/apple/RNGestureHandlerPointerType.h +8 -0
  33. package/lib/commonjs/PointerType.js +16 -0
  34. package/lib/commonjs/PointerType.js.map +1 -0
  35. package/lib/commonjs/components/GestureHandlerRootView.android.js +17 -2
  36. package/lib/commonjs/components/GestureHandlerRootView.android.js.map +1 -1
  37. package/lib/commonjs/components/GestureHandlerRootView.js +15 -2
  38. package/lib/commonjs/components/GestureHandlerRootView.js.map +1 -1
  39. package/lib/commonjs/components/GestureHandlerRootView.web.js +15 -2
  40. package/lib/commonjs/components/GestureHandlerRootView.web.js.map +1 -1
  41. package/lib/commonjs/getShadowNodeFromRef.js +19 -2
  42. package/lib/commonjs/getShadowNodeFromRef.js.map +1 -1
  43. package/lib/commonjs/handlers/createHandler.js +5 -0
  44. package/lib/commonjs/handlers/createHandler.js.map +1 -1
  45. package/lib/commonjs/handlers/gestureHandlerCommon.js.map +1 -1
  46. package/lib/commonjs/index.js +8 -0
  47. package/lib/commonjs/index.js.map +1 -1
  48. package/lib/commonjs/specs/NativeRNGestureHandlerModule.js.map +1 -1
  49. package/lib/commonjs/web/handlers/GestureHandler.js +6 -3
  50. package/lib/commonjs/web/handlers/GestureHandler.js.map +1 -1
  51. package/lib/commonjs/web/interfaces.js +3 -13
  52. package/lib/commonjs/web/interfaces.js.map +1 -1
  53. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js +3 -3
  54. package/lib/commonjs/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  55. package/lib/commonjs/web/tools/PointerEventManager.js +29 -7
  56. package/lib/commonjs/web/tools/PointerEventManager.js.map +1 -1
  57. package/lib/commonjs/web/tools/TouchEventManager.js +3 -1
  58. package/lib/commonjs/web/tools/TouchEventManager.js.map +1 -1
  59. package/lib/commonjs/web/utils.js +6 -0
  60. package/lib/commonjs/web/utils.js.map +1 -1
  61. package/lib/module/PointerType.js +9 -0
  62. package/lib/module/PointerType.js.map +1 -0
  63. package/lib/module/components/GestureHandlerRootView.android.js +15 -2
  64. package/lib/module/components/GestureHandlerRootView.android.js.map +1 -1
  65. package/lib/module/components/GestureHandlerRootView.js +15 -3
  66. package/lib/module/components/GestureHandlerRootView.js.map +1 -1
  67. package/lib/module/components/GestureHandlerRootView.web.js +15 -3
  68. package/lib/module/components/GestureHandlerRootView.web.js.map +1 -1
  69. package/lib/module/getShadowNodeFromRef.js +19 -2
  70. package/lib/module/getShadowNodeFromRef.js.map +1 -1
  71. package/lib/module/handlers/createHandler.js +6 -1
  72. package/lib/module/handlers/createHandler.js.map +1 -1
  73. package/lib/module/handlers/gestureHandlerCommon.js.map +1 -1
  74. package/lib/module/index.js +1 -0
  75. package/lib/module/index.js.map +1 -1
  76. package/lib/module/specs/NativeRNGestureHandlerModule.js.map +1 -1
  77. package/lib/module/web/handlers/GestureHandler.js +5 -3
  78. package/lib/module/web/handlers/GestureHandler.js.map +1 -1
  79. package/lib/module/web/interfaces.js +2 -11
  80. package/lib/module/web/interfaces.js.map +1 -1
  81. package/lib/module/web/tools/GestureHandlerOrchestrator.js +2 -2
  82. package/lib/module/web/tools/GestureHandlerOrchestrator.js.map +1 -1
  83. package/lib/module/web/tools/PointerEventManager.js +30 -9
  84. package/lib/module/web/tools/PointerEventManager.js.map +1 -1
  85. package/lib/module/web/tools/TouchEventManager.js +2 -1
  86. package/lib/module/web/tools/TouchEventManager.js.map +1 -1
  87. package/lib/module/web/utils.js +2 -0
  88. package/lib/module/web/utils.js.map +1 -1
  89. package/lib/typescript/PointerType.d.ts +6 -0
  90. package/lib/typescript/components/GestureHandlerRootView.android.d.ts +1 -1
  91. package/lib/typescript/components/GestureHandlerRootView.d.ts +1 -1
  92. package/lib/typescript/components/GestureHandlerRootView.web.d.ts +1 -1
  93. package/lib/typescript/getShadowNodeFromRef.d.ts +1 -1
  94. package/lib/typescript/handlers/gestureHandlerCommon.d.ts +2 -0
  95. package/lib/typescript/index.d.ts +1 -0
  96. package/lib/typescript/specs/NativeRNGestureHandlerModule.d.ts +6 -6
  97. package/lib/typescript/web/handlers/GestureHandler.d.ts +2 -1
  98. package/lib/typescript/web/interfaces.d.ts +4 -8
  99. package/lib/typescript/web/utils.d.ts +2 -0
  100. package/package.json +1 -1
  101. package/src/PointerType.ts +6 -0
  102. package/src/components/GestureHandlerRootView.android.tsx +13 -5
  103. package/src/components/GestureHandlerRootView.tsx +10 -5
  104. package/src/components/GestureHandlerRootView.web.tsx +10 -5
  105. package/src/getShadowNodeFromRef.ts +28 -6
  106. package/src/handlers/createHandler.tsx +6 -0
  107. package/src/handlers/gestureHandlerCommon.ts +2 -0
  108. package/src/index.ts +1 -0
  109. package/src/specs/NativeRNGestureHandlerModule.ts +8 -8
  110. package/src/web/handlers/GestureHandler.ts +3 -2
  111. package/src/web/interfaces.ts +4 -9
  112. package/src/web/tools/GestureHandlerOrchestrator.ts +2 -2
  113. package/src/web/tools/PointerEventManager.ts +34 -14
  114. package/src/web/tools/TouchEventManager.ts +2 -6
  115. package/src/web/utils.ts +9 -0
@@ -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}",
@@ -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
@@ -61,14 +66,14 @@ class RNGestureHandlerPackage : TurboReactPackage(), ViewManagerOnDemandReactPac
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
74
  reactModule.hasConstants,
70
75
  reactModule.isCxxModule,
71
- TurboModule::class.java.isAssignableFrom(RNGestureHandlerModule::class.java)
76
+ true
72
77
  )
73
78
  )
74
79
  }
@@ -67,6 +67,10 @@ class FlingGestureHandler : GestureHandler<FlingGestureHandler>() {
67
67
  }
68
68
 
69
69
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
70
+ if (!shouldActivateWithMouse(sourceEvent)) {
71
+ return
72
+ }
73
+
70
74
  val state = state
71
75
  if (state == STATE_UNDETERMINED) {
72
76
  startFling(sourceEvent)
@@ -5,6 +5,7 @@ import android.content.Context
5
5
  import android.content.ContextWrapper
6
6
  import android.graphics.PointF
7
7
  import android.graphics.Rect
8
+ import android.os.Build
8
9
  import android.view.MotionEvent
9
10
  import android.view.MotionEvent.PointerCoords
10
11
  import android.view.MotionEvent.PointerProperties
@@ -67,6 +68,10 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
67
68
  protected var orchestrator: GestureHandlerOrchestrator? = null
68
69
  private var onTouchEventListener: OnTouchEventListener? = null
69
70
  private var interactionController: GestureHandlerInteractionController? = null
71
+ var pointerType: Int = POINTER_TYPE_OTHER
72
+ private set
73
+
74
+ protected var mouseButton = 0
70
75
 
71
76
  @Suppress("UNCHECKED_CAST")
72
77
  protected fun self(): ConcreteGestureHandlerT = this as ConcreteGestureHandlerT
@@ -159,6 +164,10 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
159
164
  fun setInteractionController(controller: GestureHandlerInteractionController?): ConcreteGestureHandlerT =
160
165
  applySelf { interactionController = controller }
161
166
 
167
+ fun setMouseButton(mouseButton: Int) = apply {
168
+ this.mouseButton = mouseButton
169
+ }
170
+
162
171
  fun prepare(view: View?, orchestrator: GestureHandlerOrchestrator?) {
163
172
  check(!(this.view != null || this.orchestrator != null)) { "Already prepared or hasn't been reset" }
164
173
  Arrays.fill(trackedPointerIDs, -1)
@@ -371,6 +380,11 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
371
380
  lastAbsolutePositionY = GestureUtils.getLastPointerY(adaptedTransformedEvent, true)
372
381
  lastEventOffsetX = adaptedTransformedEvent.rawX - adaptedTransformedEvent.x
373
382
  lastEventOffsetY = adaptedTransformedEvent.rawY - adaptedTransformedEvent.y
383
+
384
+ if (sourceEvent.action == MotionEvent.ACTION_DOWN || sourceEvent.action == MotionEvent.ACTION_HOVER_ENTER || sourceEvent.action == MotionEvent.ACTION_HOVER_MOVE) {
385
+ setPointerType(sourceEvent)
386
+ }
387
+
374
388
  if (sourceEvent.action == MotionEvent.ACTION_HOVER_ENTER ||
375
389
  sourceEvent.action == MotionEvent.ACTION_HOVER_MOVE ||
376
390
  sourceEvent.action == MotionEvent.ACTION_HOVER_EXIT
@@ -688,6 +702,46 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
688
702
  protected open fun onReset() {}
689
703
  protected open fun onCancel() {}
690
704
 
705
+ private fun isButtonInConfig(clickedButton: Int): Boolean {
706
+ if (mouseButton == 0) {
707
+ return clickedButton == MotionEvent.BUTTON_PRIMARY
708
+ }
709
+
710
+ return clickedButton and mouseButton != 0
711
+ }
712
+
713
+ protected fun shouldActivateWithMouse(sourceEvent: MotionEvent): Boolean {
714
+ // 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.
715
+ // On API >= 23, we will use events with infix BUTTON, otherwise we use standard action events (like ACTION_DOWN).
716
+
717
+ with(sourceEvent) {
718
+ // To use actionButton, we need API >= 23.
719
+ if (getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
720
+ // While using mouse, we want to ignore default events for touch.
721
+ if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN) {
722
+ return@shouldActivateWithMouse false
723
+ }
724
+
725
+ // 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.
726
+ if (action != MotionEvent.ACTION_MOVE && !isButtonInConfig(actionButton)) {
727
+ return@shouldActivateWithMouse false
728
+ }
729
+
730
+ // When we receive ACTION_MOVE, we have to check buttonState field.
731
+ if (action == MotionEvent.ACTION_MOVE && !isButtonInConfig(buttonState)) {
732
+ return@shouldActivateWithMouse false
733
+ }
734
+ } else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
735
+ // We do not fully support mouse below API 23, so we will ignore BUTTON events.
736
+ if (action == MotionEvent.ACTION_BUTTON_PRESS || action == MotionEvent.ACTION_BUTTON_RELEASE) {
737
+ return@shouldActivateWithMouse false
738
+ }
739
+ }
740
+ }
741
+
742
+ return true
743
+ }
744
+
691
745
  /**
692
746
  * Transforms a point in the coordinate space of the wrapperView (GestureHandlerRootView) to
693
747
  * coordinate space of the view the gesture is attached to.
@@ -721,6 +775,17 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
721
775
  isWithinBounds = false
722
776
  }
723
777
 
778
+ private fun setPointerType(event: MotionEvent) {
779
+ val pointerIndex = event.actionIndex
780
+
781
+ pointerType = when (event.getToolType(pointerIndex)) {
782
+ MotionEvent.TOOL_TYPE_FINGER -> POINTER_TYPE_TOUCH
783
+ MotionEvent.TOOL_TYPE_STYLUS -> POINTER_TYPE_STYLUS
784
+ MotionEvent.TOOL_TYPE_MOUSE -> POINTER_TYPE_MOUSE
785
+ else -> POINTER_TYPE_OTHER
786
+ }
787
+ }
788
+
724
789
  fun setOnTouchEventListener(listener: OnTouchEventListener?): GestureHandler<*> {
725
790
  onTouchEventListener = listener
726
791
  return this
@@ -763,6 +828,10 @@ open class GestureHandler<ConcreteGestureHandlerT : GestureHandler<ConcreteGestu
763
828
  const val ACTION_TYPE_NATIVE_ANIMATED_EVENT = 2
764
829
  const val ACTION_TYPE_JS_FUNCTION_OLD_API = 3
765
830
  const val ACTION_TYPE_JS_FUNCTION_NEW_API = 4
831
+ const val POINTER_TYPE_TOUCH = 0
832
+ const val POINTER_TYPE_STYLUS = 1
833
+ const val POINTER_TYPE_MOUSE = 2
834
+ const val POINTER_TYPE_OTHER = 3
766
835
  private const val MAX_POINTERS_COUNT = 12
767
836
  private lateinit var pointerProps: Array<PointerProperties?>
768
837
  private lateinit var pointerCoords: Array<PointerCoords?>
@@ -101,27 +101,33 @@ class GestureHandlerOrchestrator(
101
101
  fun onHandlerStateChange(handler: GestureHandler<*>, newState: Int, prevState: Int) {
102
102
  handlingChangeSemaphore += 1
103
103
  if (isFinished(newState)) {
104
+ // We have to loop through copy in order to avoid modifying collection
105
+ // while iterating over its elements
106
+ val currentlyAwaitingHandlers = awaitingHandlers.toList()
107
+
104
108
  // 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)
109
+ for (otherHandler in currentlyAwaitingHandlers) {
110
+ if (!shouldHandlerWaitForOther(otherHandler, handler)) {
111
+ continue
112
+ }
113
+
114
+ if (newState == GestureHandler.STATE_END) {
115
+ // gesture has ended, we need to kill the awaiting handler
116
+ otherHandler.cancel()
117
+ if (otherHandler.state == GestureHandler.STATE_END) {
118
+ // Handle edge case, where discrete gestures end immediately after activation thus
119
+ // their state is set to END and when the gesture they are waiting for activates they
120
+ // should be cancelled, however `cancel` was never sent as gestures were already in the END state.
121
+ // Send synthetic BEGAN -> CANCELLED to properly handle JS logic
122
+ otherHandler.dispatchStateChange(
123
+ GestureHandler.STATE_CANCELLED,
124
+ GestureHandler.STATE_BEGAN
125
+ )
124
126
  }
127
+ otherHandler.isAwaiting = false
128
+ } else {
129
+ // gesture has failed recognition, we may try activating
130
+ tryActivate(otherHandler)
125
131
  }
126
132
  }
127
133
  cleanupAwaitingHandlers()
@@ -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
@@ -208,6 +208,10 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
208
208
  }
209
209
 
210
210
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
211
+ if (!shouldActivateWithMouse(sourceEvent)) {
212
+ return
213
+ }
214
+
211
215
  val state = state
212
216
  val action = sourceEvent.actionMasked
213
217
  if (action == MotionEvent.ACTION_POINTER_UP || action == MotionEvent.ACTION_POINTER_DOWN) {
@@ -246,7 +250,7 @@ class PanGestureHandler(context: Context?) : GestureHandler<PanGestureHandler>()
246
250
  velocityX = velocityTracker!!.xVelocity
247
251
  velocityY = velocityTracker!!.yVelocity
248
252
  }
249
- if (action == MotionEvent.ACTION_UP) {
253
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_BUTTON_RELEASE) {
250
254
  if (state == STATE_ACTIVE) {
251
255
  end()
252
256
  } else {
@@ -105,6 +105,10 @@ class TapGestureHandler : GestureHandler<TapGestureHandler>() {
105
105
  }
106
106
 
107
107
  override fun onHandle(event: MotionEvent, sourceEvent: MotionEvent) {
108
+ if (!shouldActivateWithMouse(sourceEvent)) {
109
+ return
110
+ }
111
+
108
112
  val state = state
109
113
  val action = sourceEvent.actionMasked
110
114
  if (state == STATE_UNDETERMINED) {
@@ -130,14 +134,14 @@ class TapGestureHandler : GestureHandler<TapGestureHandler>() {
130
134
  if (shouldFail()) {
131
135
  fail()
132
136
  } else if (state == STATE_UNDETERMINED) {
133
- if (action == MotionEvent.ACTION_DOWN) {
137
+ if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_BUTTON_PRESS) {
134
138
  begin()
135
139
  }
136
140
  startTap()
137
141
  } else if (state == STATE_BEGAN) {
138
- if (action == MotionEvent.ACTION_UP) {
142
+ if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_BUTTON_RELEASE) {
139
143
  endTap()
140
- } else if (action == MotionEvent.ACTION_DOWN) {
144
+ } else if (action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_BUTTON_PRESS) {
141
145
  startTap()
142
146
  }
143
147
  }
@@ -47,7 +47,7 @@ import com.swmansion.gesturehandler.react.eventbuilders.TapGestureHandlerEventDa
47
47
  // UIManagerModule.resolveRootTagFromReactTag() was deprecated and will be removed in the next RN release
48
48
  // ref: https://github.com/facebook/react-native/commit/acbf9e18ea666b07c1224a324602a41d0a66985e
49
49
  @Suppress("DEPRECATION")
50
- @ReactModule(name = RNGestureHandlerModule.MODULE_NAME)
50
+ @ReactModule(name = RNGestureHandlerModule.NAME)
51
51
  class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
52
52
  NativeRNGestureHandlerModuleSpec(reactContext), GestureHandlerStateManager {
53
53
  private abstract class HandlerFactory<T : GestureHandler<T>> {
@@ -71,6 +71,9 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
71
71
  if (config.hasKey(KEY_MANUAL_ACTIVATION)) {
72
72
  handler.setManualActivation(config.getBoolean(KEY_MANUAL_ACTIVATION))
73
73
  }
74
+ if (config.hasKey("mouseButton")) {
75
+ handler.setMouseButton(config.getInt("mouseButton"))
76
+ }
74
77
  }
75
78
 
76
79
  abstract fun createEventBuilder(handler: T): GestureHandlerEventDataBuilder<T>
@@ -331,7 +334,7 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
331
334
  private val interactionManager = RNGestureHandlerInteractionManager()
332
335
  private val roots: MutableList<RNGestureHandlerRootHelper> = ArrayList()
333
336
  private val reanimatedEventDispatcher = ReanimatedEventDispatcher()
334
- override fun getName() = MODULE_NAME
337
+ override fun getName() = NAME
335
338
 
336
339
  @Suppress("UNCHECKED_CAST")
337
340
  private fun <T : GestureHandler<T>> createGestureHandlerHelper(
@@ -476,7 +479,7 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
476
479
  )
477
480
  }
478
481
 
479
- override fun onCatalystInstanceDestroy() {
482
+ override fun invalidate() {
480
483
  registry.dropAllHandlers()
481
484
  interactionManager.reset()
482
485
  synchronized(roots) {
@@ -489,7 +492,7 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
489
492
  }
490
493
  }
491
494
  }
492
- super.onCatalystInstanceDestroy()
495
+ super.invalidate()
493
496
  }
494
497
 
495
498
  fun registerRootHelper(root: RNGestureHandlerRootHelper) {
@@ -645,7 +648,7 @@ class RNGestureHandlerModule(reactContext: ReactApplicationContext?) :
645
648
  }
646
649
 
647
650
  companion object {
648
- const val MODULE_NAME = "RNGestureHandlerModule"
651
+ const val NAME = "RNGestureHandlerModule"
649
652
  private const val KEY_SHOULD_CANCEL_WHEN_OUTSIDE = "shouldCancelWhenOutside"
650
653
  private const val KEY_ENABLED = "enabled"
651
654
  private const val KEY_NEEDS_POINTER_DATA = "needsPointerData"
@@ -10,6 +10,7 @@ import com.facebook.react.bridge.ReactContext
10
10
  import com.facebook.react.bridge.UiThreadUtil
11
11
  import com.facebook.react.common.ReactConstants
12
12
  import com.facebook.react.uimanager.RootView
13
+ import com.facebook.react.uimanager.ThemedReactContext
13
14
  import com.swmansion.gesturehandler.core.GestureHandler
14
15
  import com.swmansion.gesturehandler.core.GestureHandlerOrchestrator
15
16
 
@@ -24,7 +25,7 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
24
25
  UiThreadUtil.assertOnUiThread()
25
26
  val wrappedViewTag = wrappedView.id
26
27
  check(wrappedViewTag >= 1) { "Expect view tag to be set for $wrappedView" }
27
- val module = context.getNativeModule(RNGestureHandlerModule::class.java)!!
28
+ val module = (context as ThemedReactContext).reactApplicationContext.getNativeModule(RNGestureHandlerModule::class.java)!!
28
29
  val registry = module.registry
29
30
  rootView = findRootViewTag(wrappedView)
30
31
  Log.i(
@@ -49,7 +50,7 @@ class RNGestureHandlerRootHelper(private val context: ReactContext, wrappedView:
49
50
  ReactConstants.TAG,
50
51
  "[GESTURE HANDLER] Tearing down gesture handler registered for root view $rootView"
51
52
  )
52
- val module = context.getNativeModule(RNGestureHandlerModule::class.java)!!
53
+ val module = (context as ThemedReactContext).reactApplicationContext.getNativeModule(RNGestureHandlerModule::class.java)!!
53
54
  with(module) {
54
55
  registry.dropHandler(jsGestureHandler!!.tag)
55
56
  unregisterRootHelper(this@RNGestureHandlerRootHelper)
@@ -7,16 +7,19 @@ abstract class GestureHandlerEventDataBuilder<T : GestureHandler<T>>(handler: T)
7
7
  private val numberOfPointers: Int
8
8
  private val handlerTag: Int
9
9
  private val state: Int
10
+ private val pointerType: Int
10
11
 
11
12
  init {
12
13
  numberOfPointers = handler.numberOfPointers
13
14
  handlerTag = handler.tag
14
15
  state = handler.state
16
+ pointerType = handler.pointerType
15
17
  }
16
18
 
17
19
  open fun buildEventData(eventData: WritableMap) {
18
20
  eventData.putInt("numberOfPointers", numberOfPointers)
19
21
  eventData.putInt("handlerTag", handlerTag)
20
22
  eventData.putInt("state", state)
23
+ eventData.putInt("pointerType", pointerType)
21
24
  }
22
25
  }
@@ -7,29 +7,25 @@ using namespace facebook;
7
7
  using namespace react;
8
8
 
9
9
  void decorateRuntime(jsi::Runtime &runtime) {
10
- auto isFormsStackingContext = jsi::Function::createFromHostFunction(
11
- runtime,
12
- jsi::PropNameID::forAscii(runtime, "isFormsStackingContext"),
13
- 1,
14
- [](jsi::Runtime &runtime,
15
- const jsi::Value &thisValue,
16
- const jsi::Value *arguments,
17
- size_t count) -> jsi::Value {
18
- if (!arguments[0].isObject()) {
19
- return jsi::Value::null();
20
- }
10
+ auto isFormsStackingContext = jsi::Function::createFromHostFunction(
11
+ runtime,
12
+ jsi::PropNameID::forAscii(runtime, "isFormsStackingContext"),
13
+ 1,
14
+ [](jsi::Runtime &runtime,
15
+ const jsi::Value &thisValue,
16
+ const jsi::Value *arguments,
17
+ size_t count) -> jsi::Value {
18
+ if (!arguments[0].isObject()) {
19
+ return jsi::Value::null();
20
+ }
21
+ auto shadowNode = arguments[0]
22
+ .asObject(runtime).getNativeState<ShadowNode>(runtime);
23
+ bool isFormsStackingContext = shadowNode->getTraits().check(ShadowNodeTraits::FormsStackingContext);
21
24
 
22
- auto shadowNode = arguments[0]
23
- .asObject(runtime)
24
- .getHostObject<ShadowNodeWrapper>(runtime)
25
- ->shadowNode;
26
- bool isFormsStackingContext = shadowNode->getTraits().check(
27
- ShadowNodeTraits::FormsStackingContext);
28
-
29
- return jsi::Value(isFormsStackingContext);
30
- });
31
- runtime.global().setProperty(
32
- runtime, "isFormsStackingContext", std::move(isFormsStackingContext));
25
+ return jsi::Value(isFormsStackingContext);
26
+ });
27
+ runtime.global().setProperty(
28
+ runtime, "isFormsStackingContext", std::move(isFormsStackingContext));
33
29
  }
34
30
 
35
31
  extern "C" JNIEXPORT void JNICALL
@@ -26,6 +26,7 @@
26
26
 
27
27
  - (void)touchesBegan:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
28
28
  {
29
+ [_gestureHandler setCurrentPointerType:event];
29
30
  _lastPoint = [[[touches allObjects] objectAtIndex:0] locationInView:_gestureHandler.recognizer.view];
30
31
  [_gestureHandler reset];
31
32
  [super touchesBegan:touches withEvent:event];
@@ -141,16 +142,16 @@
141
142
 
142
143
  RNBetterSwipeGestureRecognizer *recognizer = (RNBetterSwipeGestureRecognizer *)_recognizer;
143
144
 
144
- CGPoint viewAbsolutePosition =
145
- [recognizer.view convertPoint:recognizer.view.bounds.origin
146
- toView:RCTKeyWindow().rootViewController.view];
145
+ CGPoint viewAbsolutePosition = [recognizer.view convertPoint:recognizer.view.bounds.origin
146
+ toView:RCTKeyWindow().rootViewController.view];
147
147
  CGPoint locationInView = [recognizer getLastLocation];
148
148
 
149
149
  return [RNGestureHandlerEventExtraData
150
150
  forPosition:locationInView
151
151
  withAbsolutePosition:CGPointMake(
152
152
  viewAbsolutePosition.x + locationInView.x, viewAbsolutePosition.y + locationInView.y)
153
- withNumberOfTouches:recognizer.numberOfTouches];
153
+ withNumberOfTouches:recognizer.numberOfTouches
154
+ withPointerType:_pointerType];
154
155
  }
155
156
  @end
156
157
 
@@ -40,6 +40,7 @@ static const BOOL defaultFeedbackOnActivation = NO;
40
40
 
41
41
  - (void)touchesBegan:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
42
42
  {
43
+ [_gestureHandler setCurrentPointerType:event];
43
44
  if (_firstTouch) {
44
45
  // ignore rest of fingers
45
46
  return;
@@ -171,7 +172,8 @@ static const BOOL defaultFeedbackOnActivation = NO;
171
172
  return [RNGestureHandlerEventExtraData forForce:recognizer.force
172
173
  forPosition:[recognizer locationInView:recognizer.view]
173
174
  withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
174
- withNumberOfTouches:recognizer.numberOfTouches];
175
+ withNumberOfTouches:recognizer.numberOfTouches
176
+ withPointerType:_pointerType];
175
177
  }
176
178
 
177
179
  @end
@@ -155,7 +155,8 @@ API_AVAILABLE(ios(13.4))
155
155
  - (RNGestureHandlerEventExtraData *)eventExtraData:(UIGestureRecognizer *)recognizer
156
156
  {
157
157
  return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:recognizer.view]
158
- withAbsolutePosition:[recognizer locationInView:recognizer.view.window]];
158
+ withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
159
+ withPointerType:UITouchTypePencil];
159
160
  }
160
161
 
161
162
  @end
@@ -59,6 +59,7 @@
59
59
 
60
60
  - (void)touchesBegan:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
61
61
  {
62
+ [_gestureHandler setCurrentPointerType:event];
62
63
  [super touchesBegan:touches withEvent:event];
63
64
  [_gestureHandler.pointerTracker touchesBegan:touches withEvent:event];
64
65
 
@@ -181,7 +182,8 @@
181
182
  return [RNGestureHandlerEventExtraData forPosition:[recognizer locationInView:recognizer.view]
182
183
  withAbsolutePosition:[recognizer locationInView:recognizer.view.window]
183
184
  withNumberOfTouches:recognizer.numberOfTouches
184
- withDuration:[(RNBetterLongPressGestureRecognizer *)recognizer getDuration]];
185
+ withDuration:[(RNBetterLongPressGestureRecognizer *)recognizer getDuration]
186
+ withPointerType:_pointerType];
185
187
  }
186
188
  @end
187
189
 
@@ -24,6 +24,7 @@
24
24
 
25
25
  - (void)touchesBegan:(NSSet<RNGHUITouch *> *)touches withEvent:(UIEvent *)event
26
26
  {
27
+ [_gestureHandler setCurrentPointerType:event];
27
28
  [super touchesBegan:touches withEvent:event];
28
29
  [_gestureHandler.pointerTracker touchesBegan:touches withEvent:event];
29
30