react-native-gesture-handler 2.15.0 → 2.16.0

Sign up to get free protection for your applications and to get access to all the features.
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,17 +1,19 @@
1
- import {
2
- AdaptedEvent,
3
- EventTypes,
4
- MouseButton,
5
- PointerType,
6
- } from '../interfaces';
7
1
  import EventManager from './EventManager';
8
- import { isPointerInBounds } from '../utils';
2
+ import { MouseButton } from '../../handlers/gestureHandlerCommon';
3
+ import { AdaptedEvent, EventTypes, Point } from '../interfaces';
4
+ import { PointerTypeMapping, isPointerInBounds } from '../utils';
5
+ import { PointerType } from '../../PointerType';
9
6
 
10
7
  const POINTER_CAPTURE_EXCLUDE_LIST = new Set<string>(['SELECT', 'INPUT']);
8
+ const PointerTypes = {
9
+ Touch: 'touch',
10
+ Stylus: 'pen',
11
+ };
11
12
 
12
13
  export default class PointerEventManager extends EventManager<HTMLElement> {
13
14
  private trackedPointers = new Set<number>();
14
15
  private readonly mouseButtonsMapper = new Map<number, MouseButton>();
16
+ private lastPosition: Point;
15
17
 
16
18
  constructor(view: HTMLElement) {
17
19
  super(view);
@@ -21,181 +23,213 @@ export default class PointerEventManager extends EventManager<HTMLElement> {
21
23
  this.mouseButtonsMapper.set(2, MouseButton.RIGHT);
22
24
  this.mouseButtonsMapper.set(3, MouseButton.BUTTON_4);
23
25
  this.mouseButtonsMapper.set(4, MouseButton.BUTTON_5);
26
+
27
+ this.lastPosition = {
28
+ x: -Infinity,
29
+ y: -Infinity,
30
+ };
24
31
  }
25
32
 
26
- public setListeners(): void {
27
- this.view.addEventListener('pointerdown', (event: PointerEvent): void => {
28
- if (event.pointerType === PointerType.TOUCH) {
29
- return;
30
- }
31
- if (
32
- !isPointerInBounds(this.view, { x: event.clientX, y: event.clientY })
33
- ) {
34
- return;
35
- }
33
+ private pointerDownCallback = (event: PointerEvent) => {
34
+ if (event.pointerType === PointerTypes.Touch) {
35
+ return;
36
+ }
37
+ if (!isPointerInBounds(this.view, { x: event.clientX, y: event.clientY })) {
38
+ return;
39
+ }
40
+
41
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.DOWN);
42
+ const target = event.target as HTMLElement;
43
+
44
+ if (!POINTER_CAPTURE_EXCLUDE_LIST.has(target.tagName)) {
45
+ target.setPointerCapture(adaptedEvent.pointerId);
46
+ }
47
+
48
+ this.markAsInBounds(adaptedEvent.pointerId);
49
+ this.trackedPointers.add(adaptedEvent.pointerId);
50
+
51
+ if (++this.activePointersCounter > 1) {
52
+ adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_DOWN;
53
+ this.onPointerAdd(adaptedEvent);
54
+ } else {
55
+ this.onPointerDown(adaptedEvent);
56
+ }
57
+ };
58
+
59
+ private pointerUpCallback = (event: PointerEvent) => {
60
+ if (event.pointerType === PointerTypes.Touch) {
61
+ return;
62
+ }
63
+
64
+ // When we call reset on gesture handlers, it also resets their event managers
65
+ // In some handlers (like RotationGestureHandler) reset is called before all pointers leave view
66
+ // This means, that activePointersCounter will be set to 0, while there are still remaining pointers on view
67
+ // Removing them will end in activePointersCounter going below 0, therefore handlers won't behave properly
68
+ if (this.activePointersCounter === 0) {
69
+ return;
70
+ }
71
+
72
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.UP);
73
+ const target = event.target as HTMLElement;
74
+
75
+ if (!POINTER_CAPTURE_EXCLUDE_LIST.has(target.tagName)) {
76
+ target.releasePointerCapture(adaptedEvent.pointerId);
77
+ }
78
+
79
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
80
+ this.trackedPointers.delete(adaptedEvent.pointerId);
81
+
82
+ if (--this.activePointersCounter > 0) {
83
+ adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_UP;
84
+ this.onPointerRemove(adaptedEvent);
85
+ } else {
86
+ this.onPointerUp(adaptedEvent);
87
+ }
88
+ };
89
+
90
+ private pointerMoveCallback = (event: PointerEvent) => {
91
+ if (event.pointerType === PointerTypes.Touch) {
92
+ return;
93
+ }
94
+
95
+ // Stylus triggers `pointermove` event when it detects changes in pressure. Since it is very sensitive to those changes,
96
+ // it constantly sends events, even though there was no change in position. To fix that we check whether
97
+ // pointer has actually moved and if not, we do not send event.
98
+ if (
99
+ event.pointerType === PointerTypes.Stylus &&
100
+ event.x === this.lastPosition.x &&
101
+ event.y === this.lastPosition.y
102
+ ) {
103
+ return;
104
+ }
105
+
106
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.MOVE);
107
+ const target = event.target as HTMLElement;
108
+
109
+ // You may be wondering why are we setting pointer capture here, when we
110
+ // already set it in `pointerdown` handler. Well, that's a great question,
111
+ // for which I don't have an answer. Specification (https://www.w3.org/TR/pointerevents2/#dom-element-setpointercapture)
112
+ // says that the requirement for `setPointerCapture` to work is that pointer
113
+ // must be in 'active buttons state`, otherwise it will fail silently, which
114
+ // is lovely. Obviously, when `pointerdown` is fired, one of the buttons
115
+ // (when using mouse) is pressed, but that doesn't mean that `setPointerCapture`
116
+ // will succeed, for some reason. Since it fails silently, we don't actually know
117
+ // if it worked or not (there's `gotpointercapture` event, but the complexity of
118
+ // incorporating it here seems stupid), so we just call it again here, every time
119
+ // pointer moves until it succeeds.
120
+ // God, I do love web development.
121
+ if (
122
+ !target.hasPointerCapture(event.pointerId) &&
123
+ !POINTER_CAPTURE_EXCLUDE_LIST.has(target.tagName)
124
+ ) {
125
+ target.setPointerCapture(event.pointerId);
126
+ }
127
+
128
+ const inBounds: boolean = isPointerInBounds(this.view, {
129
+ x: adaptedEvent.x,
130
+ y: adaptedEvent.y,
131
+ });
36
132
 
37
- const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.DOWN);
38
- const target = event.target as HTMLElement;
133
+ const pointerIndex: number = this.pointersInBounds.indexOf(
134
+ adaptedEvent.pointerId
135
+ );
39
136
 
40
- if (!POINTER_CAPTURE_EXCLUDE_LIST.has(target.tagName)) {
41
- target.setPointerCapture(adaptedEvent.pointerId);
137
+ if (inBounds) {
138
+ if (pointerIndex < 0) {
139
+ adaptedEvent.eventType = EventTypes.ENTER;
140
+ this.onPointerEnter(adaptedEvent);
141
+ this.markAsInBounds(adaptedEvent.pointerId);
142
+ } else {
143
+ this.onPointerMove(adaptedEvent);
42
144
  }
43
-
44
- this.markAsInBounds(adaptedEvent.pointerId);
45
- this.trackedPointers.add(adaptedEvent.pointerId);
46
-
47
- if (++this.activePointersCounter > 1) {
48
- adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_DOWN;
49
- this.onPointerAdd(adaptedEvent);
145
+ } else {
146
+ if (pointerIndex >= 0) {
147
+ adaptedEvent.eventType = EventTypes.LEAVE;
148
+ this.onPointerLeave(adaptedEvent);
149
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
50
150
  } else {
51
- this.onPointerDown(adaptedEvent);
151
+ this.onPointerOutOfBounds(adaptedEvent);
52
152
  }
53
- });
153
+ }
54
154
 
55
- this.view.addEventListener('pointerup', (event: PointerEvent): void => {
56
- if (event.pointerType === PointerType.TOUCH) {
57
- return;
58
- }
155
+ this.lastPosition.x = event.x;
156
+ this.lastPosition.y = event.y;
157
+ };
59
158
 
60
- // When we call reset on gesture handlers, it also resets their event managers
61
- // In some handlers (like RotationGestureHandler) reset is called before all pointers leave view
62
- // This means, that activePointersCounter will be set to 0, while there are still remaining pointers on view
63
- // Removing them will end in activePointersCounter going below 0, therefore handlers won't behave properly
64
- if (this.activePointersCounter === 0) {
65
- return;
66
- }
159
+ private pointerCancelCallback = (event: PointerEvent) => {
160
+ if (event.pointerType === PointerTypes.Touch) {
161
+ return;
162
+ }
67
163
 
68
- const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.UP);
69
- const target = event.target as HTMLElement;
164
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.CANCEL);
70
165
 
71
- if (!POINTER_CAPTURE_EXCLUDE_LIST.has(target.tagName)) {
72
- target.releasePointerCapture(adaptedEvent.pointerId);
73
- }
166
+ this.onPointerCancel(adaptedEvent);
167
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
168
+ this.activePointersCounter = 0;
169
+ this.trackedPointers.clear();
170
+ };
74
171
 
75
- this.markAsOutOfBounds(adaptedEvent.pointerId);
76
- this.trackedPointers.delete(adaptedEvent.pointerId);
172
+ private pointerEnterCallback = (event: PointerEvent) => {
173
+ if (event.pointerType === PointerTypes.Touch) {
174
+ return;
175
+ }
77
176
 
78
- if (--this.activePointersCounter > 0) {
79
- adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_UP;
80
- this.onPointerRemove(adaptedEvent);
81
- } else {
82
- this.onPointerUp(adaptedEvent);
83
- }
84
- });
177
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.ENTER);
85
178
 
86
- this.view.addEventListener('pointermove', (event: PointerEvent): void => {
87
- if (event.pointerType === PointerType.TOUCH) {
88
- return;
89
- }
179
+ this.onPointerMoveOver(adaptedEvent);
180
+ };
90
181
 
91
- const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.MOVE);
92
- const target = event.target as HTMLElement;
93
-
94
- // You may be wondering why are we setting pointer capture here, when we
95
- // already set it in `pointerdown` handler. Well, that's a great question,
96
- // for which I don't have an answer. Specification (https://www.w3.org/TR/pointerevents2/#dom-element-setpointercapture)
97
- // says that the requirement for `setPointerCapture` to work is that pointer
98
- // must be in 'active buttons state`, otherwise it will fail silently, which
99
- // is lovely. Obviously, when `pointerdown` is fired, one of the buttons
100
- // (when using mouse) is pressed, but that doesn't mean that `setPointerCapture`
101
- // will succeed, for some reason. Since it fails silently, we don't actually know
102
- // if it worked or not (there's `gotpointercapture` event, but the complexity of
103
- // incorporating it here seems stupid), so we just call it again here, every time
104
- // pointer moves until it succeeds.
105
- // God, I do love web development.
106
- if (
107
- !target.hasPointerCapture(event.pointerId) &&
108
- !POINTER_CAPTURE_EXCLUDE_LIST.has(target.tagName)
109
- ) {
110
- target.setPointerCapture(event.pointerId);
111
- }
182
+ private pointerLeaveCallback = (event: PointerEvent) => {
183
+ if (event.pointerType === PointerTypes.Touch) {
184
+ return;
185
+ }
112
186
 
113
- const inBounds: boolean = isPointerInBounds(this.view, {
114
- x: adaptedEvent.x,
115
- y: adaptedEvent.y,
116
- });
117
-
118
- const pointerIndex: number = this.pointersInBounds.indexOf(
119
- adaptedEvent.pointerId
120
- );
121
-
122
- if (inBounds) {
123
- if (pointerIndex < 0) {
124
- adaptedEvent.eventType = EventTypes.ENTER;
125
- this.onPointerEnter(adaptedEvent);
126
- this.markAsInBounds(adaptedEvent.pointerId);
127
- } else {
128
- this.onPointerMove(adaptedEvent);
129
- }
130
- } else {
131
- if (pointerIndex >= 0) {
132
- adaptedEvent.eventType = EventTypes.LEAVE;
133
- this.onPointerLeave(adaptedEvent);
134
- this.markAsOutOfBounds(adaptedEvent.pointerId);
135
- } else {
136
- this.onPointerOutOfBounds(adaptedEvent);
137
- }
138
- }
139
- });
187
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.LEAVE);
140
188
 
141
- this.view.addEventListener('pointercancel', (event: PointerEvent): void => {
142
- if (event.pointerType === PointerType.TOUCH) {
143
- return;
144
- }
189
+ this.onPointerMoveOut(adaptedEvent);
190
+ };
145
191
 
146
- const adaptedEvent: AdaptedEvent = this.mapEvent(
147
- event,
148
- EventTypes.CANCEL
149
- );
192
+ private lostPointerCaptureCallback = (event: PointerEvent) => {
193
+ const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.CANCEL);
150
194
 
195
+ if (this.trackedPointers.has(adaptedEvent.pointerId)) {
196
+ // in some cases the `pointerup` event is not fired, but `lostpointercapture` is
197
+ // we simulate the `pointercancel` event here to make sure the gesture handler stops tracking it
151
198
  this.onPointerCancel(adaptedEvent);
152
- this.markAsOutOfBounds(adaptedEvent.pointerId);
199
+
153
200
  this.activePointersCounter = 0;
154
201
  this.trackedPointers.clear();
155
- });
202
+ }
203
+ };
204
+
205
+ public registerListeners(): void {
206
+ this.view.addEventListener('pointerdown', this.pointerDownCallback);
207
+ this.view.addEventListener('pointerup', this.pointerUpCallback);
208
+ this.view.addEventListener('pointermove', this.pointerMoveCallback);
209
+ this.view.addEventListener('pointercancel', this.pointerCancelCallback);
156
210
 
157
211
  // onPointerEnter and onPointerLeave are triggered by a custom logic responsible for
158
212
  // handling shouldCancelWhenOutside flag, and are unreliable unless the pointer is down.
159
213
  // We therefore use pointerenter and pointerleave events to handle the hover gesture,
160
214
  // mapping them to onPointerMoveOver and onPointerMoveOut respectively.
161
-
162
- this.view.addEventListener('pointerenter', (event: PointerEvent): void => {
163
- if (event.pointerType === PointerType.TOUCH) {
164
- return;
165
- }
166
-
167
- const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.ENTER);
168
-
169
- this.onPointerMoveOver(adaptedEvent);
170
- });
171
-
172
- this.view.addEventListener('pointerleave', (event: PointerEvent): void => {
173
- if (event.pointerType === PointerType.TOUCH) {
174
- return;
175
- }
176
-
177
- const adaptedEvent: AdaptedEvent = this.mapEvent(event, EventTypes.LEAVE);
178
-
179
- this.onPointerMoveOut(adaptedEvent);
180
- });
181
-
215
+ this.view.addEventListener('pointerenter', this.pointerEnterCallback);
216
+ this.view.addEventListener('pointerleave', this.pointerLeaveCallback);
182
217
  this.view.addEventListener(
183
218
  'lostpointercapture',
184
- (event: PointerEvent): void => {
185
- const adaptedEvent: AdaptedEvent = this.mapEvent(
186
- event,
187
- EventTypes.CANCEL
188
- );
189
-
190
- if (this.trackedPointers.has(adaptedEvent.pointerId)) {
191
- // in some cases the `pointerup` event is not fired, but `lostpointercapture` is
192
- // we simulate the `pointercancel` event here to make sure the gesture handler stops tracking it
193
- this.onPointerCancel(adaptedEvent);
194
-
195
- this.activePointersCounter = 0;
196
- this.trackedPointers.clear();
197
- }
198
- }
219
+ this.lostPointerCaptureCallback
220
+ );
221
+ }
222
+
223
+ public unregisterListeners(): void {
224
+ this.view.removeEventListener('pointerdown', this.pointerDownCallback);
225
+ this.view.removeEventListener('pointerup', this.pointerUpCallback);
226
+ this.view.removeEventListener('pointermove', this.pointerMoveCallback);
227
+ this.view.removeEventListener('pointercancel', this.pointerCancelCallback);
228
+ this.view.removeEventListener('pointerenter', this.pointerEnterCallback);
229
+ this.view.removeEventListener('pointerleave', this.pointerLeaveCallback);
230
+ this.view.removeEventListener(
231
+ 'lostpointercapture',
232
+ this.lostPointerCaptureCallback
199
233
  );
200
234
  }
201
235
 
@@ -207,7 +241,8 @@ export default class PointerEventManager extends EventManager<HTMLElement> {
207
241
  offsetY: event.offsetY,
208
242
  pointerId: event.pointerId,
209
243
  eventType: eventType,
210
- pointerType: event.pointerType as PointerType,
244
+ pointerType:
245
+ PointerTypeMapping.get(event.pointerType) ?? PointerType.OTHER,
211
246
  button: this.mouseButtonsMapper.get(event.button),
212
247
  time: event.timeStamp,
213
248
  };
@@ -1,141 +1,149 @@
1
- import {
2
- AdaptedEvent,
3
- EventTypes,
4
- PointerType,
5
- TouchEventType,
6
- } from '../interfaces';
1
+ import { AdaptedEvent, EventTypes, TouchEventType } from '../interfaces';
7
2
  import EventManager from './EventManager';
8
3
  import { isPointerInBounds } from '../utils';
4
+ import { PointerType } from '../../PointerType';
9
5
 
10
6
  export default class TouchEventManager extends EventManager<HTMLElement> {
11
- public setListeners(): void {
12
- this.view.addEventListener('touchstart', (event: TouchEvent) => {
13
- for (let i = 0; i < event.changedTouches.length; ++i) {
14
- const adaptedEvent: AdaptedEvent = this.mapEvent(
15
- event,
16
- EventTypes.DOWN,
17
- i,
18
- TouchEventType.DOWN
19
- );
20
-
21
- // Here we skip stylus, because in case of anything different than touch we want to handle it by using PointerEvents
22
- // If we leave stylus to send touch events, handlers will receive every action twice
23
- if (
24
- !isPointerInBounds(this.view, {
25
- x: adaptedEvent.x,
26
- y: adaptedEvent.y,
27
- }) ||
28
- //@ts-ignore touchType field does exist
29
- event.changedTouches[i].touchType === 'stylus'
30
- ) {
31
- continue;
32
- }
33
-
34
- this.markAsInBounds(adaptedEvent.pointerId);
35
-
36
- if (++this.activePointersCounter > 1) {
37
- adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_DOWN;
38
- this.onPointerAdd(adaptedEvent);
39
- } else {
40
- this.onPointerDown(adaptedEvent);
41
- }
42
- }
43
- });
44
-
45
- this.view.addEventListener('touchmove', (event: TouchEvent) => {
46
- for (let i = 0; i < event.changedTouches.length; ++i) {
47
- const adaptedEvent: AdaptedEvent = this.mapEvent(
48
- event,
49
- EventTypes.MOVE,
50
- i,
51
- TouchEventType.MOVE
52
- );
53
- //@ts-ignore touchType field does exist
54
- if (event.changedTouches[i].touchType === 'stylus') {
55
- continue;
56
- }
57
-
58
- const inBounds: boolean = isPointerInBounds(this.view, {
7
+ private touchStartCallback = (event: TouchEvent): void => {
8
+ for (let i = 0; i < event.changedTouches.length; ++i) {
9
+ const adaptedEvent: AdaptedEvent = this.mapEvent(
10
+ event,
11
+ EventTypes.DOWN,
12
+ i,
13
+ TouchEventType.DOWN
14
+ );
15
+
16
+ // Here we skip stylus, because in case of anything different than touch we want to handle it by using PointerEvents
17
+ // If we leave stylus to send touch events, handlers will receive every action twice
18
+ if (
19
+ !isPointerInBounds(this.view, {
59
20
  x: adaptedEvent.x,
60
21
  y: adaptedEvent.y,
61
- });
62
-
63
- const pointerIndex: number = this.pointersInBounds.indexOf(
64
- adaptedEvent.pointerId
65
- );
66
-
67
- if (inBounds) {
68
- if (pointerIndex < 0) {
69
- adaptedEvent.eventType = EventTypes.ENTER;
70
- this.onPointerEnter(adaptedEvent);
71
- this.markAsInBounds(adaptedEvent.pointerId);
72
- } else {
73
- this.onPointerMove(adaptedEvent);
74
- }
75
- } else {
76
- if (pointerIndex >= 0) {
77
- adaptedEvent.eventType = EventTypes.LEAVE;
78
- this.onPointerLeave(adaptedEvent);
79
- this.markAsOutOfBounds(adaptedEvent.pointerId);
80
- } else {
81
- this.onPointerOutOfBounds(adaptedEvent);
82
- }
83
- }
22
+ }) ||
23
+ //@ts-ignore touchType field does exist
24
+ event.changedTouches[i].touchType === 'stylus'
25
+ ) {
26
+ continue;
84
27
  }
85
- });
86
-
87
- this.view.addEventListener('touchend', (event: TouchEvent) => {
88
- for (let i = 0; i < event.changedTouches.length; ++i) {
89
- // When we call reset on gesture handlers, it also resets their event managers
90
- // In some handlers (like RotationGestureHandler) reset is called before all pointers leave view
91
- // This means, that activePointersCounter will be set to 0, while there are still remaining pointers on view
92
- // Removing them will end in activePointersCounter going below 0, therefore handlers won't behave properly
93
- if (this.activePointersCounter === 0) {
94
- break;
95
- }
96
28
 
97
- //@ts-ignore touchType field does exist
98
- if (event.changedTouches[i].touchType === 'stylus') {
99
- continue;
100
- }
29
+ this.markAsInBounds(adaptedEvent.pointerId);
101
30
 
102
- const adaptedEvent: AdaptedEvent = this.mapEvent(
103
- event,
104
- EventTypes.UP,
105
- i,
106
- TouchEventType.UP
107
- );
31
+ if (++this.activePointersCounter > 1) {
32
+ adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_DOWN;
33
+ this.onPointerAdd(adaptedEvent);
34
+ } else {
35
+ this.onPointerDown(adaptedEvent);
36
+ }
37
+ }
38
+ };
39
+
40
+ private touchMoveCallback = (event: TouchEvent): void => {
41
+ for (let i = 0; i < event.changedTouches.length; ++i) {
42
+ const adaptedEvent: AdaptedEvent = this.mapEvent(
43
+ event,
44
+ EventTypes.MOVE,
45
+ i,
46
+ TouchEventType.MOVE
47
+ );
48
+ //@ts-ignore touchType field does exist
49
+ if (event.changedTouches[i].touchType === 'stylus') {
50
+ continue;
51
+ }
108
52
 
109
- this.markAsOutOfBounds(adaptedEvent.pointerId);
53
+ const inBounds: boolean = isPointerInBounds(this.view, {
54
+ x: adaptedEvent.x,
55
+ y: adaptedEvent.y,
56
+ });
110
57
 
111
- if (--this.activePointersCounter > 0) {
112
- adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_UP;
113
- this.onPointerRemove(adaptedEvent);
58
+ const pointerIndex: number = this.pointersInBounds.indexOf(
59
+ adaptedEvent.pointerId
60
+ );
61
+
62
+ if (inBounds) {
63
+ if (pointerIndex < 0) {
64
+ adaptedEvent.eventType = EventTypes.ENTER;
65
+ this.onPointerEnter(adaptedEvent);
66
+ this.markAsInBounds(adaptedEvent.pointerId);
114
67
  } else {
115
- this.onPointerUp(adaptedEvent);
68
+ this.onPointerMove(adaptedEvent);
116
69
  }
70
+ } else {
71
+ if (pointerIndex >= 0) {
72
+ adaptedEvent.eventType = EventTypes.LEAVE;
73
+ this.onPointerLeave(adaptedEvent);
74
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
75
+ } else {
76
+ this.onPointerOutOfBounds(adaptedEvent);
77
+ }
78
+ }
79
+ }
80
+ };
81
+
82
+ private touchEndCallback = (event: TouchEvent): void => {
83
+ for (let i = 0; i < event.changedTouches.length; ++i) {
84
+ // When we call reset on gesture handlers, it also resets their event managers
85
+ // In some handlers (like RotationGestureHandler) reset is called before all pointers leave view
86
+ // This means, that activePointersCounter will be set to 0, while there are still remaining pointers on view
87
+ // Removing them will end in activePointersCounter going below 0, therefore handlers won't behave properly
88
+ if (this.activePointersCounter === 0) {
89
+ break;
90
+ }
91
+
92
+ //@ts-ignore touchType field does exist
93
+ if (event.changedTouches[i].touchType === 'stylus') {
94
+ continue;
117
95
  }
118
- });
119
96
 
120
- this.view.addEventListener('touchcancel', (event: TouchEvent) => {
121
- for (let i = 0; i < event.changedTouches.length; ++i) {
122
- const adaptedEvent: AdaptedEvent = this.mapEvent(
123
- event,
124
- EventTypes.CANCEL,
125
- i,
126
- TouchEventType.CANCELLED
127
- );
97
+ const adaptedEvent: AdaptedEvent = this.mapEvent(
98
+ event,
99
+ EventTypes.UP,
100
+ i,
101
+ TouchEventType.UP
102
+ );
128
103
 
129
- //@ts-ignore touchType field does exist
130
- if (event.changedTouches[i].touchType === 'stylus') {
131
- continue;
132
- }
104
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
133
105
 
134
- this.onPointerCancel(adaptedEvent);
135
- this.markAsOutOfBounds(adaptedEvent.pointerId);
136
- this.activePointersCounter = 0;
106
+ if (--this.activePointersCounter > 0) {
107
+ adaptedEvent.eventType = EventTypes.ADDITIONAL_POINTER_UP;
108
+ this.onPointerRemove(adaptedEvent);
109
+ } else {
110
+ this.onPointerUp(adaptedEvent);
111
+ }
112
+ }
113
+ };
114
+
115
+ private touchCancelCallback = (event: TouchEvent): void => {
116
+ for (let i = 0; i < event.changedTouches.length; ++i) {
117
+ const adaptedEvent: AdaptedEvent = this.mapEvent(
118
+ event,
119
+ EventTypes.CANCEL,
120
+ i,
121
+ TouchEventType.CANCELLED
122
+ );
123
+
124
+ //@ts-ignore touchType field does exist
125
+ if (event.changedTouches[i].touchType === 'stylus') {
126
+ continue;
137
127
  }
138
- });
128
+
129
+ this.onPointerCancel(adaptedEvent);
130
+ this.markAsOutOfBounds(adaptedEvent.pointerId);
131
+ this.activePointersCounter = 0;
132
+ }
133
+ };
134
+
135
+ public registerListeners(): void {
136
+ this.view.addEventListener('touchstart', this.touchStartCallback);
137
+ this.view.addEventListener('touchmove', this.touchMoveCallback);
138
+ this.view.addEventListener('touchend', this.touchEndCallback);
139
+ this.view.addEventListener('touchcancel', this.touchCancelCallback);
140
+ }
141
+
142
+ public unregisterListeners(): void {
143
+ this.view.removeEventListener('touchstart', this.touchStartCallback);
144
+ this.view.removeEventListener('touchmove', this.touchMoveCallback);
145
+ this.view.removeEventListener('touchend', this.touchEndCallback);
146
+ this.view.removeEventListener('touchcancel', this.touchCancelCallback);
139
147
  }
140
148
 
141
149
  protected mapEvent(