react-native-gesture-handler 2.15.0 → 2.16.0-rc.0

Sign up to get free protection for your applications and to get access to all the features.
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