basalt-core 0.0.0-rc5

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 (325) hide show
  1. package/LICENSE +21 -0
  2. package/dist/cli/basalt.d.ts +3 -0
  3. package/dist/cli/basalt.d.ts.map +1 -0
  4. package/dist/cli/basalt.js +47 -0
  5. package/dist/cli/basalt.js.map +1 -0
  6. package/dist/cli/bundle-cli.d.ts +12 -0
  7. package/dist/cli/bundle-cli.d.ts.map +1 -0
  8. package/dist/cli/bundle-cli.js +124 -0
  9. package/dist/cli/bundle-cli.js.map +1 -0
  10. package/dist/cli/bundleWithAssets.d.ts +79 -0
  11. package/dist/cli/bundleWithAssets.d.ts.map +1 -0
  12. package/dist/cli/bundleWithAssets.js +198 -0
  13. package/dist/cli/bundleWithAssets.js.map +1 -0
  14. package/dist/cli/desktop.d.ts +339 -0
  15. package/dist/cli/desktop.d.ts.map +1 -0
  16. package/dist/cli/desktop.js +1029 -0
  17. package/dist/cli/desktop.js.map +1 -0
  18. package/dist/cli/doctor.d.ts +31 -0
  19. package/dist/cli/doctor.d.ts.map +1 -0
  20. package/dist/cli/doctor.js +283 -0
  21. package/dist/cli/doctor.js.map +1 -0
  22. package/dist/cli/init.d.ts +77 -0
  23. package/dist/cli/init.d.ts.map +1 -0
  24. package/dist/cli/init.js +442 -0
  25. package/dist/cli/init.js.map +1 -0
  26. package/dist/cli/metro.d.ts +49 -0
  27. package/dist/cli/metro.d.ts.map +1 -0
  28. package/dist/cli/metro.js +148 -0
  29. package/dist/cli/metro.js.map +1 -0
  30. package/dist/cli/packageApp.d.ts +102 -0
  31. package/dist/cli/packageApp.d.ts.map +1 -0
  32. package/dist/cli/packageApp.js +319 -0
  33. package/dist/cli/packageApp.js.map +1 -0
  34. package/dist/cli/steps.d.ts +34 -0
  35. package/dist/cli/steps.d.ts.map +1 -0
  36. package/dist/cli/steps.js +53 -0
  37. package/dist/cli/steps.js.map +1 -0
  38. package/dist/metro-config.d.ts +168 -0
  39. package/dist/metro-config.d.ts.map +1 -0
  40. package/dist/metro-config.js +671 -0
  41. package/dist/metro-config.js.map +1 -0
  42. package/dist/react-native.config.d.ts +7 -0
  43. package/dist/react-native.config.d.ts.map +1 -0
  44. package/dist/react-native.config.js +80 -0
  45. package/dist/react-native.config.js.map +1 -0
  46. package/dist/src/DragSource.d.ts +52 -0
  47. package/dist/src/DragSource.d.ts.map +1 -0
  48. package/dist/src/DragSource.js +97 -0
  49. package/dist/src/DragSource.js.map +1 -0
  50. package/dist/src/DropTarget.d.ts +58 -0
  51. package/dist/src/DropTarget.d.ts.map +1 -0
  52. package/dist/src/DropTarget.js +131 -0
  53. package/dist/src/DropTarget.js.map +1 -0
  54. package/dist/src/KeyHandler.d.ts +57 -0
  55. package/dist/src/KeyHandler.d.ts.map +1 -0
  56. package/dist/src/KeyHandler.js +48 -0
  57. package/dist/src/KeyHandler.js.map +1 -0
  58. package/dist/src/Menu.d.ts +72 -0
  59. package/dist/src/Menu.d.ts.map +1 -0
  60. package/dist/src/Menu.js +179 -0
  61. package/dist/src/Menu.js.map +1 -0
  62. package/dist/src/TitleBar.d.ts +75 -0
  63. package/dist/src/TitleBar.d.ts.map +1 -0
  64. package/dist/src/TitleBar.js +236 -0
  65. package/dist/src/TitleBar.js.map +1 -0
  66. package/dist/src/Window.d.ts +87 -0
  67. package/dist/src/Window.d.ts.map +1 -0
  68. package/dist/src/Window.js +248 -0
  69. package/dist/src/Window.js.map +1 -0
  70. package/dist/src/closeRequest.d.ts +55 -0
  71. package/dist/src/closeRequest.d.ts.map +1 -0
  72. package/dist/src/closeRequest.js +134 -0
  73. package/dist/src/closeRequest.js.map +1 -0
  74. package/dist/src/index.d.ts +45 -0
  75. package/dist/src/index.d.ts.map +1 -0
  76. package/dist/src/index.js +92 -0
  77. package/dist/src/index.js.map +1 -0
  78. package/dist/src/overrides/Alert.d.ts +69 -0
  79. package/dist/src/overrides/Alert.d.ts.map +1 -0
  80. package/dist/src/overrides/Alert.js +112 -0
  81. package/dist/src/overrides/Alert.js.map +1 -0
  82. package/dist/src/overrides/BaseViewConfig.d.ts +28 -0
  83. package/dist/src/overrides/BaseViewConfig.d.ts.map +1 -0
  84. package/dist/src/overrides/BaseViewConfig.js +72 -0
  85. package/dist/src/overrides/BaseViewConfig.js.map +1 -0
  86. package/dist/src/overrides/Platform.linux.d.ts +10 -0
  87. package/dist/src/overrides/Platform.linux.d.ts.map +1 -0
  88. package/dist/src/overrides/Platform.linux.js +15 -0
  89. package/dist/src/overrides/Platform.linux.js.map +1 -0
  90. package/dist/src/overrides/Platform.macos.d.ts +10 -0
  91. package/dist/src/overrides/Platform.macos.d.ts.map +1 -0
  92. package/dist/src/overrides/Platform.macos.js +15 -0
  93. package/dist/src/overrides/Platform.macos.js.map +1 -0
  94. package/dist/src/overrides/Platform.windows.d.ts +10 -0
  95. package/dist/src/overrides/Platform.windows.d.ts.map +1 -0
  96. package/dist/src/overrides/Platform.windows.js +15 -0
  97. package/dist/src/overrides/Platform.windows.js.map +1 -0
  98. package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts +24 -0
  99. package/dist/src/overrides/ReactDevToolsSettingsManager.d.ts.map +1 -0
  100. package/dist/src/overrides/ReactDevToolsSettingsManager.js +30 -0
  101. package/dist/src/overrides/ReactDevToolsSettingsManager.js.map +1 -0
  102. package/dist/src/overrides/RefreshControl.d.ts +52 -0
  103. package/dist/src/overrides/RefreshControl.d.ts.map +1 -0
  104. package/dist/src/overrides/RefreshControl.js +92 -0
  105. package/dist/src/overrides/RefreshControl.js.map +1 -0
  106. package/dist/src/overrides/ScrollView.d.ts +39 -0
  107. package/dist/src/overrides/ScrollView.d.ts.map +1 -0
  108. package/dist/src/overrides/ScrollView.js +59 -0
  109. package/dist/src/overrides/ScrollView.js.map +1 -0
  110. package/dist/src/overrides/Share.d.ts +96 -0
  111. package/dist/src/overrides/Share.d.ts.map +1 -0
  112. package/dist/src/overrides/Share.js +97 -0
  113. package/dist/src/overrides/Share.js.map +1 -0
  114. package/dist/src/overrides/TextInput.d.ts +81 -0
  115. package/dist/src/overrides/TextInput.d.ts.map +1 -0
  116. package/dist/src/overrides/TextInput.js +213 -0
  117. package/dist/src/overrides/TextInput.js.map +1 -0
  118. package/dist/src/overrides/View.d.ts +36 -0
  119. package/dist/src/overrides/View.d.ts.map +1 -0
  120. package/dist/src/overrides/View.js +99 -0
  121. package/dist/src/overrides/View.js.map +1 -0
  122. package/dist/src/overrides/createPlatform.d.ts +32 -0
  123. package/dist/src/overrides/createPlatform.d.ts.map +1 -0
  124. package/dist/src/overrides/createPlatform.js +84 -0
  125. package/dist/src/overrides/createPlatform.js.map +1 -0
  126. package/dist/src/overrides/setUpDeveloperTools.d.ts +28 -0
  127. package/dist/src/overrides/setUpDeveloperTools.d.ts.map +1 -0
  128. package/dist/src/overrides/setUpDeveloperTools.js +84 -0
  129. package/dist/src/overrides/setUpDeveloperTools.js.map +1 -0
  130. package/dist/src/overrides/setUpXHR.d.ts +46 -0
  131. package/dist/src/overrides/setUpXHR.d.ts.map +1 -0
  132. package/dist/src/overrides/setUpXHR.js +236 -0
  133. package/dist/src/overrides/setUpXHR.js.map +1 -0
  134. package/dist/src/quitRequest.d.ts +55 -0
  135. package/dist/src/quitRequest.d.ts.map +1 -0
  136. package/dist/src/quitRequest.js +121 -0
  137. package/dist/src/quitRequest.js.map +1 -0
  138. package/dist/src/resourcePath.d.ts +18 -0
  139. package/dist/src/resourcePath.d.ts.map +1 -0
  140. package/dist/src/resourcePath.js +31 -0
  141. package/dist/src/resourcePath.js.map +1 -0
  142. package/dist/src/responseBody.d.ts +76 -0
  143. package/dist/src/responseBody.d.ts.map +1 -0
  144. package/dist/src/responseBody.js +94 -0
  145. package/dist/src/responseBody.js.map +1 -0
  146. package/dist/src/responseHeaders.d.ts +40 -0
  147. package/dist/src/responseHeaders.d.ts.map +1 -0
  148. package/dist/src/responseHeaders.js +75 -0
  149. package/dist/src/responseHeaders.js.map +1 -0
  150. package/dist/src/titleBarState.d.ts +43 -0
  151. package/dist/src/titleBarState.d.ts.map +1 -0
  152. package/dist/src/titleBarState.js +77 -0
  153. package/dist/src/titleBarState.js.map +1 -0
  154. package/dist/src/useContextMenu.d.ts +113 -0
  155. package/dist/src/useContextMenu.d.ts.map +1 -0
  156. package/dist/src/useContextMenu.js +109 -0
  157. package/dist/src/useContextMenu.js.map +1 -0
  158. package/dist/src/useDialog.d.ts +98 -0
  159. package/dist/src/useDialog.d.ts.map +1 -0
  160. package/dist/src/useDialog.js +112 -0
  161. package/dist/src/useDialog.js.map +1 -0
  162. package/dist/src/useDisplays.d.ts +70 -0
  163. package/dist/src/useDisplays.d.ts.map +1 -0
  164. package/dist/src/useDisplays.js +118 -0
  165. package/dist/src/useDisplays.js.map +1 -0
  166. package/dist/src/useHandledKeys.d.ts +38 -0
  167. package/dist/src/useHandledKeys.d.ts.map +1 -0
  168. package/dist/src/useHandledKeys.js +70 -0
  169. package/dist/src/useHandledKeys.js.map +1 -0
  170. package/dist/src/useWindow.d.ts +140 -0
  171. package/dist/src/useWindow.d.ts.map +1 -0
  172. package/dist/src/useWindow.js +233 -0
  173. package/dist/src/useWindow.js.map +1 -0
  174. package/dist/tsconfig.tsbuildinfo +1 -0
  175. package/native/CMakeLists.txt +355 -0
  176. package/native/bootstrap.sh +613 -0
  177. package/native/cmake/CompilerFlags.cmake +49 -0
  178. package/native/cmake/Expo.cmake +125 -0
  179. package/native/cmake/ReactNativeCore.cmake +612 -0
  180. package/native/cmake/Reanimated.cmake +108 -0
  181. package/native/cmake/Skia.cmake +379 -0
  182. package/native/cmake/ThirdParty.cmake +290 -0
  183. package/native/cmake/Worklets.cmake +67 -0
  184. package/native/cmake/codegen/CMakeLists.txt +32 -0
  185. package/native/core/AppIdentity.cpp +85 -0
  186. package/native/core/AppIdentity.h +59 -0
  187. package/native/core/AppPaths.cpp +96 -0
  188. package/native/core/AppPaths.h +53 -0
  189. package/native/core/AppearanceModule.cpp +60 -0
  190. package/native/core/AppearanceModule.h +40 -0
  191. package/native/core/Backface.h +59 -0
  192. package/native/core/BlobModule.cpp +283 -0
  193. package/native/core/BlobModule.h +76 -0
  194. package/native/core/BlobRegistry.cpp +75 -0
  195. package/native/core/BlobRegistry.h +44 -0
  196. package/native/core/ColorScheme.cpp +105 -0
  197. package/native/core/ColorScheme.h +59 -0
  198. package/native/core/ComponentRegistry.h +30 -0
  199. package/native/core/ControlMetrics.h +37 -0
  200. package/native/core/CoreModules.cpp +592 -0
  201. package/native/core/CoreModules.h +308 -0
  202. package/native/core/DebuggingOverlay.cpp +106 -0
  203. package/native/core/DebuggingOverlay.h +65 -0
  204. package/native/core/DesktopControls.cpp +232 -0
  205. package/native/core/DesktopControls.h +170 -0
  206. package/native/core/DevBundle.cpp +108 -0
  207. package/native/core/DevBundle.h +69 -0
  208. package/native/core/DevMenu.cpp +99 -0
  209. package/native/core/DevMenu.h +75 -0
  210. package/native/core/DialogModule.cpp +150 -0
  211. package/native/core/DialogModule.h +51 -0
  212. package/native/core/DragAndDrop.cpp +45 -0
  213. package/native/core/DragAndDrop.h +225 -0
  214. package/native/core/ExpoImageComponent.cpp +79 -0
  215. package/native/core/ExpoImageComponent.h +80 -0
  216. package/native/core/ExpoModules.cpp +415 -0
  217. package/native/core/ExpoModules.h +115 -0
  218. package/native/core/ExpoRuntime.cpp +366 -0
  219. package/native/core/ExpoRuntime.h +42 -0
  220. package/native/core/FocusRing.h +36 -0
  221. package/native/core/FontRegistry.h +51 -0
  222. package/native/core/GestureHandlerModule.cpp +136 -0
  223. package/native/core/GestureHandlerModule.h +71 -0
  224. package/native/core/Gestures.cpp +533 -0
  225. package/native/core/Gestures.h +145 -0
  226. package/native/core/HoverTracker.cpp +69 -0
  227. package/native/core/HoverTracker.h +109 -0
  228. package/native/core/HttpClient.cpp +282 -0
  229. package/native/core/ImageBytes.cpp +205 -0
  230. package/native/core/ImageBytes.h +29 -0
  231. package/native/core/ImageCache.cpp +51 -0
  232. package/native/core/ImageCache.h +89 -0
  233. package/native/core/JsRuntimeAccess.cpp +70 -0
  234. package/native/core/JsRuntimeAccess.h +60 -0
  235. package/native/core/JsiPromise.h +51 -0
  236. package/native/core/KeyEvents.cpp +116 -0
  237. package/native/core/KeyEvents.h +144 -0
  238. package/native/core/LogBoxSurface.cpp +46 -0
  239. package/native/core/LogBoxSurface.h +68 -0
  240. package/native/core/MenuModel.h +117 -0
  241. package/native/core/MenuModule.cpp +209 -0
  242. package/native/core/MenuModule.h +66 -0
  243. package/native/core/MountingWalk.h +524 -0
  244. package/native/core/PackageModules.cpp.in +25 -0
  245. package/native/core/PackageModules.h +50 -0
  246. package/native/core/PlatformConstantsModule.cpp +63 -0
  247. package/native/core/PlatformConstantsModule.h +64 -0
  248. package/native/core/PlatformServices.h +213 -0
  249. package/native/core/PointerButtons.h +63 -0
  250. package/native/core/PullToRefresh.cpp +57 -0
  251. package/native/core/PullToRefresh.h +73 -0
  252. package/native/core/ReanimatedCompat.h +47 -0
  253. package/native/core/ReanimatedModule.cpp +203 -0
  254. package/native/core/ReanimatedModule.h +55 -0
  255. package/native/core/ScrollAnimation.cpp +59 -0
  256. package/native/core/ScrollAnimation.h +70 -0
  257. package/native/core/ScrollBounds.cpp +26 -0
  258. package/native/core/ScrollBounds.h +68 -0
  259. package/native/core/ScrollIndicator.cpp +50 -0
  260. package/native/core/ScrollIndicator.h +69 -0
  261. package/native/core/ScrollMomentum.cpp +71 -0
  262. package/native/core/ScrollMomentum.h +73 -0
  263. package/native/core/ScrollSnap.cpp +123 -0
  264. package/native/core/ScrollSnap.h +80 -0
  265. package/native/core/ShareFallback.cpp +101 -0
  266. package/native/core/ShareFallback.h +45 -0
  267. package/native/core/SkiaPictureViewComponent.cpp +11 -0
  268. package/native/core/SkiaPictureViewComponent.h +47 -0
  269. package/native/core/SourceCodeModule.cpp +55 -0
  270. package/native/core/SourceCodeModule.h +53 -0
  271. package/native/core/StatusBarModule.cpp +23 -0
  272. package/native/core/StatusBarModule.h +42 -0
  273. package/native/core/TestDialog.cpp +148 -0
  274. package/native/core/TestDialog.h +96 -0
  275. package/native/core/TestKeys.cpp +78 -0
  276. package/native/core/TestKeys.h +50 -0
  277. package/native/core/TestQuitFile.cpp +33 -0
  278. package/native/core/TestQuitFile.h +60 -0
  279. package/native/core/TestSettle.h +192 -0
  280. package/native/core/TitleBarRegions.h +31 -0
  281. package/native/core/TurboModuleProxy.cpp +51 -0
  282. package/native/core/TurboModuleProxy.h +46 -0
  283. package/native/core/UIManagerAccess.cpp +43 -0
  284. package/native/core/UIManagerAccess.h +43 -0
  285. package/native/core/WindowBoundsCache.cpp +319 -0
  286. package/native/core/WindowControl.h +235 -0
  287. package/native/core/WindowHost.h +158 -0
  288. package/native/core/WindowMethods.cpp +167 -0
  289. package/native/core/WindowMethods.h +84 -0
  290. package/native/core/WindowsModule.cpp +448 -0
  291. package/native/core/WindowsModule.h +133 -0
  292. package/native/core/WorkletsModule.cpp +199 -0
  293. package/native/core/WorkletsModule.h +57 -0
  294. package/native/core/portability_probe.cpp +210 -0
  295. package/native/tests/EventRecorder.h +124 -0
  296. package/native/tests/TestHarness.cpp +109 -0
  297. package/native/tests/TestHarness.h +89 -0
  298. package/native/tests/TreeDump.h +49 -0
  299. package/native/tests/test_app_identity.cpp +114 -0
  300. package/native/tests/test_app_paths.cpp +48 -0
  301. package/native/tests/test_appearance.cpp +107 -0
  302. package/native/tests/test_backface.cpp +79 -0
  303. package/native/tests/test_blobs.cpp +157 -0
  304. package/native/tests/test_controls.cpp +185 -0
  305. package/native/tests/test_devbundle.cpp +103 -0
  306. package/native/tests/test_drag_and_drop.cpp +143 -0
  307. package/native/tests/test_gestures.cpp +331 -0
  308. package/native/tests/test_hover.cpp +92 -0
  309. package/native/tests/test_image_cache.cpp +109 -0
  310. package/native/tests/test_js_runtime_access.cpp +137 -0
  311. package/native/tests/test_key_events.cpp +235 -0
  312. package/native/tests/test_momentum.cpp +138 -0
  313. package/native/tests/test_quit_file.cpp +104 -0
  314. package/native/tests/test_scroll_animation.cpp +120 -0
  315. package/native/tests/test_scroll_bounds.cpp +66 -0
  316. package/native/tests/test_scroll_indicator.cpp +149 -0
  317. package/native/tests/test_scroll_snap.cpp +112 -0
  318. package/native/tests/test_settle.cpp +115 -0
  319. package/native/tests/test_share.cpp +75 -0
  320. package/native/tests/test_sourcecode.cpp +62 -0
  321. package/native/tests/test_window_close.cpp +119 -0
  322. package/native/tests/test_window_limits.cpp +123 -0
  323. package/package.json +43 -0
  324. package/react-native.config.js +86 -0
  325. package/supported-versions.json +66 -0
@@ -0,0 +1,71 @@
1
+ // `RNGestureHandlerModule`, the TurboModule react-native-gesture-handler asks
2
+ // for by name.
3
+ //
4
+ // Hand-written rather than generated. Every other module in this project
5
+ // derives from one of React Native's codegenned specs, because React Native
6
+ // ships the specs; a third-party library's spec is generated during *its* build
7
+ // against *an app's* node_modules, and this project's hosts are generic
8
+ // binaries that are not built per app. So the eight methods are declared here
9
+ // against `TurboModule` directly, from the same TypeScript interface codegen
10
+ // would have read.
11
+ //
12
+ // It is registered unconditionally, like every other core module. An app
13
+ // without gesture-handler never looks the name up, and the registry behind it
14
+ // is empty and costs a branch.
15
+ //
16
+ // The module is a thin thing: it converts arguments, hops to the UI thread and
17
+ // calls core/Gestures.h. What it adds is the one piece the engine cannot have,
18
+ // which is a way to reach JavaScript -- RNGH listens on DeviceEventEmitter, and
19
+ // only a TurboModule can emit one.
20
+
21
+ #pragma once
22
+
23
+ #include <ReactCommon/TurboModule.h>
24
+
25
+ #include <folly/dynamic.h>
26
+
27
+ #include <memory>
28
+ #include <string>
29
+
30
+ namespace basalt {
31
+
32
+ class DesktopGestureHandlerModule : public facebook::react::TurboModule {
33
+ public:
34
+ static constexpr const char *kModuleName = "RNGestureHandlerModule";
35
+
36
+ explicit DesktopGestureHandlerModule(std::shared_ptr<facebook::react::CallInvoker> jsInvoker);
37
+ ~DesktopGestureHandlerModule() override;
38
+
39
+ private:
40
+ // The method table. Each is a plain function because `MethodMetadata::invoker`
41
+ // is a function pointer, not a std::function -- a TurboModule's methods are
42
+ // meant to be static dispatch.
43
+ static facebook::jsi::Value createGestureHandler(facebook::jsi::Runtime &runtime,
44
+ facebook::react::TurboModule &module,
45
+ const facebook::jsi::Value *args,
46
+ size_t count);
47
+ static facebook::jsi::Value attachGestureHandler(facebook::jsi::Runtime &runtime,
48
+ facebook::react::TurboModule &module,
49
+ const facebook::jsi::Value *args,
50
+ size_t count);
51
+ static facebook::jsi::Value updateGestureHandler(facebook::jsi::Runtime &runtime,
52
+ facebook::react::TurboModule &module,
53
+ const facebook::jsi::Value *args,
54
+ size_t count);
55
+ static facebook::jsi::Value dropGestureHandler(facebook::jsi::Runtime &runtime,
56
+ facebook::react::TurboModule &module,
57
+ const facebook::jsi::Value *args,
58
+ size_t count);
59
+ static facebook::jsi::Value install(facebook::jsi::Runtime &runtime,
60
+ facebook::react::TurboModule &module,
61
+ const facebook::jsi::Value *args,
62
+ size_t count);
63
+ static facebook::jsi::Value noop(facebook::jsi::Runtime &runtime,
64
+ facebook::react::TurboModule &module,
65
+ const facebook::jsi::Value *args,
66
+ size_t count);
67
+
68
+ void emitGestureEvent(const std::string &eventName, folly::dynamic payload);
69
+ };
70
+
71
+ } // namespace basalt
@@ -0,0 +1,533 @@
1
+ #include "Gestures.h"
2
+
3
+ #include "PlatformServices.h"
4
+
5
+ #include <glog/logging.h>
6
+
7
+ #include <algorithm>
8
+ #include <chrono>
9
+ #include <cmath>
10
+
11
+ namespace basalt {
12
+
13
+ namespace {
14
+
15
+ // RNGH's ActionType and PointerType live in its JavaScript; only the two values
16
+ // this side produces are named here.
17
+ constexpr int kPointerTypeMouse = 2;
18
+
19
+ double number(const folly::dynamic &config, const char *key, double fallback) {
20
+ if (!config.isObject()) {
21
+ return fallback;
22
+ }
23
+ const auto *value = config.get_ptr(key);
24
+ if (value == nullptr || !value->isNumber()) {
25
+ return fallback;
26
+ }
27
+ return value->asDouble();
28
+ }
29
+
30
+ bool hasKey(const folly::dynamic &config, const char *key) {
31
+ return config.isObject() && config.get_ptr(key) != nullptr &&
32
+ !config.get_ptr(key)->isNull();
33
+ }
34
+
35
+ std::vector<int> tagList(const folly::dynamic &config, const char *key) {
36
+ std::vector<int> tags;
37
+ if (!config.isObject()) {
38
+ return tags;
39
+ }
40
+ const auto *value = config.get_ptr(key);
41
+ if (value == nullptr || !value->isArray()) {
42
+ return tags;
43
+ }
44
+ for (const auto &entry : *value) {
45
+ if (entry.isNumber()) {
46
+ tags.push_back(static_cast<int>(entry.asDouble()));
47
+ }
48
+ }
49
+ return tags;
50
+ }
51
+
52
+ bool contains(const std::vector<int> &tags, int tag) {
53
+ return std::find(tags.begin(), tags.end(), tag) != tags.end();
54
+ }
55
+
56
+ } // namespace
57
+
58
+ struct GestureRegistry::Handler {
59
+ std::string name;
60
+ int tag{0};
61
+ int viewTag{0};
62
+ folly::dynamic config = folly::dynamic::object();
63
+
64
+ GestureState state{GestureState::Undetermined};
65
+ bool tracking{false};
66
+
67
+ // The attached view's origin in root coordinates, captured when the pointer
68
+ // lands: a gesture payload's `x`/`y` are relative to the view it is attached
69
+ // to, and `absoluteX`/`absoluteY` to the root.
70
+ double originX{0};
71
+ double originY{0};
72
+
73
+ double startX{0};
74
+ double startY{0};
75
+ double lastX{0};
76
+ double lastY{0};
77
+ double startTime{0};
78
+ double lastTime{0};
79
+ double velocityX{0};
80
+ double velocityY{0};
81
+
82
+ // For multi-tap. Kept between gestures, because the second tap of a double
83
+ // tap is a separate gesture as far as the pointer is concerned.
84
+ int tapCount{0};
85
+ double lastTapTime{0};
86
+
87
+ // Bumped on every pointer down, so a timer that fires after the gesture it
88
+ // belonged to can tell that it is stale. Simpler than cancelling timers, and
89
+ // right even when the timer has already begun running.
90
+ int generation{0};
91
+ };
92
+
93
+ double monotonicMilliseconds() {
94
+ using namespace std::chrono;
95
+ return duration<double, std::milli>(steady_clock::now().time_since_epoch()).count();
96
+ }
97
+
98
+ GestureRegistry &gestures() {
99
+ static GestureRegistry registry;
100
+ return registry;
101
+ }
102
+
103
+ void GestureRegistry::setEmitter(Emitter emitter) {
104
+ emit_ = std::move(emitter);
105
+ }
106
+
107
+ GestureRegistry::Handler *GestureRegistry::find(int handlerTag) {
108
+ for (auto &handler : handlers_) {
109
+ if (handler.tag == handlerTag) {
110
+ return &handler;
111
+ }
112
+ }
113
+ return nullptr;
114
+ }
115
+
116
+ void GestureRegistry::create(const std::string &handlerName,
117
+ int handlerTag,
118
+ folly::dynamic config) {
119
+ drop(handlerTag);
120
+ Handler handler;
121
+ handler.name = handlerName;
122
+ handler.tag = handlerTag;
123
+ handler.config = config.isObject() ? std::move(config) : folly::dynamic::object();
124
+ handlers_.push_back(std::move(handler));
125
+ }
126
+
127
+ void GestureRegistry::update(int handlerTag, folly::dynamic config) {
128
+ Handler *handler = find(handlerTag);
129
+ if (handler == nullptr || !config.isObject()) {
130
+ return;
131
+ }
132
+ // Merged rather than replaced: RNGH sends the properties it knows changed,
133
+ // and sends the relations in a second call of their own.
134
+ for (const auto &entry : config.items()) {
135
+ handler->config[entry.first] = entry.second;
136
+ }
137
+ }
138
+
139
+ void GestureRegistry::attach(int handlerTag, int viewTag) {
140
+ if (Handler *handler = find(handlerTag); handler != nullptr) {
141
+ handler->viewTag = viewTag;
142
+ }
143
+ }
144
+
145
+ void GestureRegistry::drop(int handlerTag) {
146
+ handlers_.erase(std::remove_if(handlers_.begin(),
147
+ handlers_.end(),
148
+ [handlerTag](const Handler &handler) {
149
+ return handler.tag == handlerTag;
150
+ }),
151
+ handlers_.end());
152
+ tracking_.erase(std::remove(tracking_.begin(), tracking_.end(), handlerTag), tracking_.end());
153
+ }
154
+
155
+ void GestureRegistry::setStateFromWorklet(int handlerTag, int state) {
156
+ Handler *handler = find(handlerTag);
157
+ if (handler == nullptr || !handler->tracking) {
158
+ return;
159
+ }
160
+ const auto next = static_cast<GestureState>(state);
161
+ if (next == GestureState::Active) {
162
+ // Through the same path a recogniser takes, so that the handlers it
163
+ // competes with are cancelled the way they would be otherwise.
164
+ tryActivate(*handler, handler->lastX, handler->lastY, handler->lastTime);
165
+ return;
166
+ }
167
+ setState(*handler, next, handler->lastX, handler->lastY, handler->lastTime);
168
+ }
169
+
170
+ bool GestureRegistry::empty() const {
171
+ return handlers_.empty();
172
+ }
173
+
174
+ bool GestureRegistry::hasActiveHandler() const {
175
+ for (int tag : tracking_) {
176
+ for (const auto &handler : handlers_) {
177
+ if (handler.tag == tag && handler.state == GestureState::Active) {
178
+ return true;
179
+ }
180
+ }
181
+ }
182
+ return false;
183
+ }
184
+
185
+ folly::dynamic GestureRegistry::payloadFor(const Handler &handler, double x, double y) const {
186
+ folly::dynamic payload = folly::dynamic::object;
187
+ payload["handlerTag"] = handler.tag;
188
+ payload["numberOfPointers"] = 1;
189
+ payload["pointerType"] = kPointerTypeMouse;
190
+ payload["state"] = static_cast<int>(handler.state);
191
+ payload["x"] = x - handler.originX;
192
+ payload["y"] = y - handler.originY;
193
+ payload["absoluteX"] = x;
194
+ payload["absoluteY"] = y;
195
+
196
+ if (handler.name == "PanGestureHandler") {
197
+ payload["translationX"] = x - handler.startX;
198
+ payload["translationY"] = y - handler.startY;
199
+ payload["velocityX"] = handler.velocityX;
200
+ payload["velocityY"] = handler.velocityY;
201
+ } else if (handler.name == "LongPressGestureHandler") {
202
+ payload["duration"] = handler.lastTime - handler.startTime;
203
+ }
204
+ return payload;
205
+ }
206
+
207
+ void GestureRegistry::setState(Handler &handler,
208
+ GestureState next,
209
+ double x,
210
+ double y,
211
+ double timestampMs) {
212
+ if (handler.state == next) {
213
+ return;
214
+ }
215
+ const GestureState previous = handler.state;
216
+ handler.state = next;
217
+ handler.lastTime = timestampMs;
218
+
219
+ if (emit_) {
220
+ folly::dynamic payload = payloadFor(handler, x, y);
221
+ payload["oldState"] = static_cast<int>(previous);
222
+ emit_("onGestureHandlerStateChange", std::move(payload));
223
+ }
224
+
225
+ // Undetermined is where a handler waits for the next gesture.
226
+ if (next == GestureState::End || next == GestureState::Failed ||
227
+ next == GestureState::Cancelled) {
228
+ handler.tracking = false;
229
+ handler.state = GestureState::Undetermined;
230
+ }
231
+ }
232
+
233
+ void GestureRegistry::emitUpdate(const Handler &handler,
234
+ double x,
235
+ double y,
236
+ double /*timestampMs*/) {
237
+ if (!emit_) {
238
+ return;
239
+ }
240
+ emit_("onGestureHandlerEvent", payloadFor(handler, x, y));
241
+ }
242
+
243
+ void GestureRegistry::cancelOthers(const Handler &activated,
244
+ double x,
245
+ double y,
246
+ double timestampMs) {
247
+ const std::vector<int> simultaneous = tagList(activated.config, "simultaneousHandlers");
248
+ const int activatedTag = activated.tag;
249
+
250
+ for (int tag : tracking_) {
251
+ if (tag == activatedTag) {
252
+ continue;
253
+ }
254
+ Handler *other = find(tag);
255
+ if (other == nullptr || !other->tracking) {
256
+ continue;
257
+ }
258
+ if (contains(simultaneous, tag) ||
259
+ contains(tagList(other->config, "simultaneousHandlers"), activatedTag)) {
260
+ continue;
261
+ }
262
+ setState(*other,
263
+ other->state == GestureState::Active ? GestureState::Cancelled
264
+ : GestureState::Failed,
265
+ x,
266
+ y,
267
+ timestampMs);
268
+ }
269
+ }
270
+
271
+ bool GestureRegistry::tryActivate(Handler &handler, double x, double y, double timestampMs) {
272
+ // `waitFor` is RNGH's requireToFail: this handler may not activate while a
273
+ // handler it waits for is still undecided. Checked at the moment of
274
+ // activation rather than tracked as a subscription, which is enough because
275
+ // the next pointer event re-asks.
276
+ for (int tag : tagList(handler.config, "waitFor")) {
277
+ const Handler *other = const_cast<GestureRegistry *>(this)->find(tag);
278
+ if (other != nullptr && other->tracking) {
279
+ return false;
280
+ }
281
+ }
282
+
283
+ setState(handler, GestureState::Active, x, y, timestampMs);
284
+ cancelOthers(handler, x, y, timestampMs);
285
+ return true;
286
+ }
287
+
288
+ void GestureRegistry::beginTracking(Handler &handler,
289
+ const HitView &view,
290
+ double x,
291
+ double y,
292
+ double timestampMs) {
293
+ handler.tracking = true;
294
+ handler.originX = view.originX;
295
+ handler.originY = view.originY;
296
+ handler.startX = x;
297
+ handler.startY = y;
298
+ handler.lastX = x;
299
+ handler.lastY = y;
300
+ handler.startTime = timestampMs;
301
+ handler.lastTime = timestampMs;
302
+ handler.velocityX = 0;
303
+ handler.velocityY = 0;
304
+ handler.generation = generation_;
305
+
306
+ setState(handler, GestureState::Began, x, y, timestampMs);
307
+
308
+ if (handler.name == "LongPressGestureHandler") {
309
+ const double minDuration = number(handler.config, "minDurationMs", 500);
310
+ const int generation = handler.generation;
311
+ const int tag = handler.tag;
312
+ postDelayed(minDuration, [this, tag, generation]() {
313
+ Handler *held = find(tag);
314
+ if (held == nullptr || held->generation != generation || !held->tracking ||
315
+ held->state != GestureState::Began) {
316
+ return;
317
+ }
318
+ tryActivate(*held, held->lastX, held->lastY, held->lastTime);
319
+ });
320
+ }
321
+
322
+ // A native handler stands for a platform control that handles its own
323
+ // gesture -- RNGH's buttons, and scroll views. Nothing here wraps one, so it
324
+ // activates on contact, which is what those controls do.
325
+ if (handler.name == "NativeViewGestureHandler") {
326
+ tryActivate(handler, x, y, timestampMs);
327
+ }
328
+ }
329
+
330
+ void GestureRegistry::pointerDown(const std::vector<HitView> &chain,
331
+ double x,
332
+ double y,
333
+ double timestampMs) {
334
+ generation_++;
335
+ pointerIsDown_ = true;
336
+ tracking_.clear();
337
+
338
+ // Innermost first, which is the order RNGH offers a gesture to handlers in:
339
+ // the closest handler to the touch gets to claim it before its ancestors.
340
+ for (const HitView &view : chain) {
341
+ for (auto &handler : handlers_) {
342
+ if (handler.viewTag != view.tag || handler.viewTag == 0) {
343
+ continue;
344
+ }
345
+ tracking_.push_back(handler.tag);
346
+ beginTracking(handler, view, x, y, timestampMs);
347
+ }
348
+ }
349
+ }
350
+
351
+ void GestureRegistry::pointerMove(double x, double y, double timestampMs) {
352
+ if (!pointerIsDown_) {
353
+ return;
354
+ }
355
+
356
+ for (int tag : tracking_) {
357
+ Handler *handler = find(tag);
358
+ if (handler == nullptr || !handler->tracking) {
359
+ continue;
360
+ }
361
+
362
+ const double elapsed = timestampMs - handler->lastTime;
363
+ if (elapsed > 0) {
364
+ // Pixels per second, which is what RNGH's velocity is in.
365
+ handler->velocityX = (x - handler->lastX) / elapsed * 1000.0;
366
+ handler->velocityY = (y - handler->lastY) / elapsed * 1000.0;
367
+ }
368
+ handler->lastX = x;
369
+ handler->lastY = y;
370
+ handler->lastTime = timestampMs;
371
+
372
+ const double dx = x - handler->startX;
373
+ const double dy = y - handler->startY;
374
+ const double distance = std::sqrt(dx * dx + dy * dy);
375
+
376
+ if (handler->state == GestureState::Active) {
377
+ emitUpdate(*handler, x, y, timestampMs);
378
+ continue;
379
+ }
380
+ if (handler->state != GestureState::Began) {
381
+ continue;
382
+ }
383
+
384
+ if (handler->name == "PanGestureHandler") {
385
+ // activeOffsetX/Y are thresholds in one direction and take precedence
386
+ // over minDist, which is RNGH's radial default.
387
+ bool activate = false;
388
+ if (hasKey(handler->config, "activeOffsetXStart") ||
389
+ hasKey(handler->config, "activeOffsetXEnd") ||
390
+ hasKey(handler->config, "activeOffsetYStart") ||
391
+ hasKey(handler->config, "activeOffsetYEnd")) {
392
+ activate = dx <= number(handler->config, "activeOffsetXStart", -1e9) ||
393
+ dx >= number(handler->config, "activeOffsetXEnd", 1e9) ||
394
+ dy <= number(handler->config, "activeOffsetYStart", -1e9) ||
395
+ dy >= number(handler->config, "activeOffsetYEnd", 1e9);
396
+ } else {
397
+ activate = distance >= number(handler->config, "minDist", 10);
398
+ }
399
+
400
+ const bool fail = dx <= number(handler->config, "failOffsetXStart", -1e9) ||
401
+ dx >= number(handler->config, "failOffsetXEnd", 1e9) ||
402
+ dy <= number(handler->config, "failOffsetYStart", -1e9) ||
403
+ dy >= number(handler->config, "failOffsetYEnd", 1e9);
404
+
405
+ if (fail) {
406
+ setState(*handler, GestureState::Failed, x, y, timestampMs);
407
+ } else if (activate && tryActivate(*handler, x, y, timestampMs)) {
408
+ emitUpdate(*handler, x, y, timestampMs);
409
+ }
410
+ continue;
411
+ }
412
+
413
+ // A tap or a long press is over as soon as the pointer wanders. maxDist is
414
+ // RNGH's name for the slop in both.
415
+ if (handler->name == "TapGestureHandler" || handler->name == "LongPressGestureHandler") {
416
+ const double slop =
417
+ number(handler->config, "maxDist", handler->name == "TapGestureHandler" ? 25 : 10);
418
+ if (distance > slop) {
419
+ setState(*handler, GestureState::Failed, x, y, timestampMs);
420
+ }
421
+ }
422
+ }
423
+ }
424
+
425
+ void GestureRegistry::pointerUp(double x, double y, double timestampMs) {
426
+ if (!pointerIsDown_) {
427
+ return;
428
+ }
429
+ pointerIsDown_ = false;
430
+
431
+ const std::vector<int> tracking = tracking_;
432
+ for (int tag : tracking) {
433
+ Handler *handler = find(tag);
434
+ if (handler == nullptr || !handler->tracking) {
435
+ continue;
436
+ }
437
+ handler->lastTime = timestampMs;
438
+
439
+ if (handler->state == GestureState::Active) {
440
+ setState(*handler, GestureState::End, x, y, timestampMs);
441
+ continue;
442
+ }
443
+ if (handler->state != GestureState::Began) {
444
+ continue;
445
+ }
446
+
447
+ if (handler->name == "TapGestureHandler") {
448
+ const double maxDuration = number(handler->config, "maxDurationMs", 500);
449
+ const double maxDelay = number(handler->config, "maxDelayMs", 500);
450
+ const int required = static_cast<int>(number(handler->config, "numberOfTaps", 1));
451
+
452
+ if (timestampMs - handler->startTime > maxDuration) {
453
+ handler->tapCount = 0;
454
+ setState(*handler, GestureState::Failed, x, y, timestampMs);
455
+ continue;
456
+ }
457
+
458
+ handler->tapCount++;
459
+ handler->lastTapTime = timestampMs;
460
+
461
+ if (handler->tapCount >= required) {
462
+ handler->tapCount = 0;
463
+ if (tryActivate(*handler, x, y, timestampMs)) {
464
+ setState(*handler, GestureState::End, x, y, timestampMs);
465
+ }
466
+ continue;
467
+ }
468
+
469
+ // More taps wanted. The handler stops tracking this pointer but keeps its
470
+ // count, and fails if the next tap does not arrive in time.
471
+ handler->tracking = false;
472
+ handler->state = GestureState::Undetermined;
473
+ const int generation = handler->generation;
474
+ const int handlerTag = handler->tag;
475
+ postDelayed(maxDelay, [this, handlerTag, generation]() {
476
+ Handler *held = find(handlerTag);
477
+ if (held == nullptr || held->generation != generation || held->tapCount == 0) {
478
+ return;
479
+ }
480
+ held->tapCount = 0;
481
+ if (emit_) {
482
+ folly::dynamic payload = payloadFor(*held, held->lastX, held->lastY);
483
+ payload["state"] = static_cast<int>(GestureState::Failed);
484
+ payload["oldState"] = static_cast<int>(GestureState::Began);
485
+ emit_("onGestureHandlerStateChange", std::move(payload));
486
+ }
487
+ });
488
+ continue;
489
+ }
490
+
491
+ if (handler->name == "FlingGestureHandler") {
492
+ const double speed =
493
+ std::sqrt(handler->velocityX * handler->velocityX +
494
+ handler->velocityY * handler->velocityY);
495
+ // RNGH has no configurable threshold for this; its platforms use their
496
+ // own recognisers. 500 px/s is the middle of what each of them treats as
497
+ // a flick.
498
+ if (speed >= 500 && tryActivate(*handler, x, y, timestampMs)) {
499
+ setState(*handler, GestureState::End, x, y, timestampMs);
500
+ } else {
501
+ setState(*handler, GestureState::Failed, x, y, timestampMs);
502
+ }
503
+ continue;
504
+ }
505
+
506
+ // Everything still at BEGAN when the pointer lifts did not happen: a long
507
+ // press that was not held, a pan that never moved, a pinch that could never
508
+ // have started.
509
+ setState(*handler, GestureState::Failed, x, y, timestampMs);
510
+ }
511
+
512
+ tracking_.clear();
513
+ }
514
+
515
+ void GestureRegistry::pointerCancel() {
516
+ const std::vector<int> tracking = tracking_;
517
+ for (int tag : tracking) {
518
+ Handler *handler = find(tag);
519
+ if (handler == nullptr || !handler->tracking) {
520
+ continue;
521
+ }
522
+ setState(*handler,
523
+ handler->state == GestureState::Active ? GestureState::Cancelled
524
+ : GestureState::Failed,
525
+ handler->lastX,
526
+ handler->lastY,
527
+ handler->lastTime);
528
+ }
529
+ tracking_.clear();
530
+ pointerIsDown_ = false;
531
+ }
532
+
533
+ } // namespace basalt