kivyforge 3.0.0.dev0__py3-none-any.whl

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 (225) hide show
  1. kivyforge/__init__.py +9 -0
  2. kivyforge/artifacts/__init__.py +41 -0
  3. kivyforge/artifacts/cache.py +81 -0
  4. kivyforge/artifacts/collect.py +354 -0
  5. kivyforge/artifacts/download.py +125 -0
  6. kivyforge/artifacts/frameworks.py +240 -0
  7. kivyforge/artifacts/native_stage_util.py +346 -0
  8. kivyforge/artifacts/runtime.py +65 -0
  9. kivyforge/artifacts/verify.py +45 -0
  10. kivyforge/artifacts/wheels.py +89 -0
  11. kivyforge/bundle/__init__.py +1 -0
  12. kivyforge/bundle/pycompile.py +161 -0
  13. kivyforge/cli/__init__.py +52 -0
  14. kivyforge/cli/_common.py +62 -0
  15. kivyforge/cli/_platform.py +84 -0
  16. kivyforge/cli/build.py +111 -0
  17. kivyforge/cli/clean.py +135 -0
  18. kivyforge/cli/doctor.py +52 -0
  19. kivyforge/cli/init.py +612 -0
  20. kivyforge/cli/init_writer.py +716 -0
  21. kivyforge/cli/lock.py +261 -0
  22. kivyforge/cli/open_cmd.py +15 -0
  23. kivyforge/cli/package.py +134 -0
  24. kivyforge/cli/run.py +162 -0
  25. kivyforge/cli/status.py +20 -0
  26. kivyforge/cli/upgrade.py +314 -0
  27. kivyforge/config/__init__.py +46 -0
  28. kivyforge/config/errors.py +43 -0
  29. kivyforge/config/icons.py +60 -0
  30. kivyforge/config/loader.py +3079 -0
  31. kivyforge/config/model.py +817 -0
  32. kivyforge/doctor/__init__.py +19 -0
  33. kivyforge/doctor/checks_common.py +95 -0
  34. kivyforge/doctor/probe.py +357 -0
  35. kivyforge/doctor/result.py +41 -0
  36. kivyforge/lock/__init__.py +42 -0
  37. kivyforge/lock/_pip_shim.py +63 -0
  38. kivyforge/lock/find_links.py +182 -0
  39. kivyforge/lock/model.py +69 -0
  40. kivyforge/lock/pep751.py +111 -0
  41. kivyforge/lock/reader.py +30 -0
  42. kivyforge/lock/resolver.py +124 -0
  43. kivyforge/lock/wheelruntime/__init__.py +70 -0
  44. kivyforge/lock/wheelruntime/builder.py +280 -0
  45. kivyforge/lock/wheelruntime/model.py +94 -0
  46. kivyforge/lock/wheelruntime/native_binaries.py +127 -0
  47. kivyforge/lock/wheelruntime/pbs_github.py +133 -0
  48. kivyforge/lock/wheelruntime/profile.py +104 -0
  49. kivyforge/lock/wheelruntime/resolver.py +248 -0
  50. kivyforge/lock/wheelruntime/runtime.py +161 -0
  51. kivyforge/lock/wheelruntime/serialize.py +245 -0
  52. kivyforge/platforms/__init__.py +114 -0
  53. kivyforge/platforms/android/__init__.py +140 -0
  54. kivyforge/platforms/android/adb.py +215 -0
  55. kivyforge/platforms/android/bootstrap/__init__.py +7 -0
  56. kivyforge/platforms/android/bootstrap/contract.py +166 -0
  57. kivyforge/platforms/android/bootstrap/render.py +244 -0
  58. kivyforge/platforms/android/bootstrap/templates/androidtest/KivyforgeContractTest.java +76 -0
  59. kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivy_bootstrap.py +50 -0
  60. kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_bootstrap.py +54 -0
  61. kivyforge/platforms/android/bootstrap/templates/bootstrap_py/_kivyforge_selftest.py +97 -0
  62. kivyforge/platforms/android/bootstrap/templates/cpp/CMakeLists.txt +20 -0
  63. kivyforge/platforms/android/bootstrap/templates/cpp/main.c +150 -0
  64. kivyforge/platforms/android/bootstrap/templates/java/org/jnius/NativeInvocationHandler.java +48 -0
  65. kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonActivity.java +75 -0
  66. kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonBundle.java +132 -0
  67. kivyforge/platforms/android/bootstrap/templates/java/org/kivy/android/PythonService.java +189 -0
  68. kivyforge/platforms/android/bootstrap/templates/java/org/renpy/android/Hardware.java +276 -0
  69. kivyforge/platforms/android/bootstrap/templates/sdl2/LICENSE-SDL.txt +18 -0
  70. kivyforge/platforms/android/bootstrap/templates/sdl2/SDL_REVISION.txt +3 -0
  71. kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDevice.java +22 -0
  72. kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceBLESteamController.java +650 -0
  73. kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceManager.java +698 -0
  74. kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/HIDDeviceUSB.java +309 -0
  75. kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDL.java +90 -0
  76. kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLActivity.java +2120 -0
  77. kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLAudioManager.java +514 -0
  78. kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLControllerManager.java +856 -0
  79. kivyforge/platforms/android/bootstrap/templates/sdl2/org/libsdl/app/SDLSurface.java +405 -0
  80. kivyforge/platforms/android/bootstrap/templates/sdl3/LICENSE-SDL.txt +18 -0
  81. kivyforge/platforms/android/bootstrap/templates/sdl3/SDL_REVISION.txt +3 -0
  82. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDevice.java +21 -0
  83. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceBLESteamController.java +829 -0
  84. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceManager.java +698 -0
  85. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/HIDDeviceUSB.java +354 -0
  86. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDL.java +90 -0
  87. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLActivity.java +2240 -0
  88. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLAudioManager.java +126 -0
  89. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLControllerManager.java +1010 -0
  90. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLDummyEdit.java +66 -0
  91. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLInputConnection.java +136 -0
  92. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSensorManager.java +73 -0
  93. kivyforge/platforms/android/bootstrap/templates/sdl3/org/libsdl/app/SDLSurface.java +464 -0
  94. kivyforge/platforms/android/cli.py +1023 -0
  95. kivyforge/platforms/android/doctor.py +899 -0
  96. kivyforge/platforms/android/elf.py +148 -0
  97. kivyforge/platforms/android/generate/__init__.py +1 -0
  98. kivyforge/platforms/android/generate/manifest.py +261 -0
  99. kivyforge/platforms/android/generate/project.py +462 -0
  100. kivyforge/platforms/android/generate/services.py +187 -0
  101. kivyforge/platforms/android/gradle_wrapper/NOTICE +3 -0
  102. kivyforge/platforms/android/gradle_wrapper/SHA256SUMS +1 -0
  103. kivyforge/platforms/android/gradle_wrapper/gradle-wrapper.jar +0 -0
  104. kivyforge/platforms/android/gradle_wrapper/gradlew +164 -0
  105. kivyforge/platforms/android/gradle_wrapper/gradlew.bat +90 -0
  106. kivyforge/platforms/android/gradlew.py +60 -0
  107. kivyforge/platforms/android/icons.py +237 -0
  108. kivyforge/platforms/android/lock/__init__.py +1 -0
  109. kivyforge/platforms/android/lock/archives.py +109 -0
  110. kivyforge/platforms/android/lock/builder.py +387 -0
  111. kivyforge/platforms/android/lock/markers.py +71 -0
  112. kivyforge/platforms/android/lock/maven.py +252 -0
  113. kivyforge/platforms/android/lock/model.py +113 -0
  114. kivyforge/platforms/android/lock/python_meta.py +199 -0
  115. kivyforge/platforms/android/lock/reader.py +206 -0
  116. kivyforge/platforms/android/lock/resolver.py +276 -0
  117. kivyforge/platforms/android/lock/writer.py +121 -0
  118. kivyforge/platforms/android/policy.py +214 -0
  119. kivyforge/platforms/android/signing.py +145 -0
  120. kivyforge/platforms/android/smoke.py +43 -0
  121. kivyforge/platforms/android/splash.py +293 -0
  122. kivyforge/platforms/android/stage/__init__.py +1 -0
  123. kivyforge/platforms/android/stage/bundle.py +295 -0
  124. kivyforge/platforms/android/stage/jnilibs.py +186 -0
  125. kivyforge/platforms/android/stage/runtime.py +61 -0
  126. kivyforge/platforms/android/stage/wheels.py +106 -0
  127. kivyforge/platforms/android/toolchain.py +29 -0
  128. kivyforge/platforms/base.py +157 -0
  129. kivyforge/platforms/ios/__init__.py +129 -0
  130. kivyforge/platforms/ios/assets.py +193 -0
  131. kivyforge/platforms/ios/buildsettings.py +128 -0
  132. kivyforge/platforms/ios/cli.py +543 -0
  133. kivyforge/platforms/ios/doctor.py +410 -0
  134. kivyforge/platforms/ios/entitlements.py +34 -0
  135. kivyforge/platforms/ios/generator.py +318 -0
  136. kivyforge/platforms/ios/lock/__init__.py +71 -0
  137. kivyforge/platforms/ios/lock/builder.py +393 -0
  138. kivyforge/platforms/ios/lock/markers.py +69 -0
  139. kivyforge/platforms/ios/lock/model.py +95 -0
  140. kivyforge/platforms/ios/lock/python_meta.py +187 -0
  141. kivyforge/platforms/ios/lock/reader.py +191 -0
  142. kivyforge/platforms/ios/lock/resolver.py +304 -0
  143. kivyforge/platforms/ios/lock/spm.py +217 -0
  144. kivyforge/platforms/ios/lock/writer.py +114 -0
  145. kivyforge/platforms/ios/lock/xcframework.py +188 -0
  146. kivyforge/platforms/ios/materialize.py +59 -0
  147. kivyforge/platforms/ios/plist.py +91 -0
  148. kivyforge/platforms/ios/privacy.py +39 -0
  149. kivyforge/platforms/ios/skeleton.py +165 -0
  150. kivyforge/platforms/ios/sources.py +63 -0
  151. kivyforge/platforms/ios/staging.py +225 -0
  152. kivyforge/platforms/ios/swift_packages.py +324 -0
  153. kivyforge/platforms/ios/templates/kivyforge_bootstrap.h +34 -0
  154. kivyforge/platforms/ios/templates/kivyforge_bootstrap.m +146 -0
  155. kivyforge/platforms/ios/templates/main.m +15 -0
  156. kivyforge/platforms/ios/templates/main_config.h.in +12 -0
  157. kivyforge/platforms/ios/xcframeworks.py +194 -0
  158. kivyforge/platforms/ios/xcode/__init__.py +76 -0
  159. kivyforge/platforms/ios/xcode/commands.py +296 -0
  160. kivyforge/platforms/ios/xcode/runner.py +316 -0
  161. kivyforge/platforms/linux/__init__.py +120 -0
  162. kivyforge/platforms/linux/appimage.py +169 -0
  163. kivyforge/platforms/linux/bundle.py +235 -0
  164. kivyforge/platforms/linux/cli.py +232 -0
  165. kivyforge/platforms/linux/desktop.py +71 -0
  166. kivyforge/platforms/linux/doctor.py +438 -0
  167. kivyforge/platforms/linux/elftools.py +95 -0
  168. kivyforge/platforms/linux/icons.py +129 -0
  169. kivyforge/platforms/linux/launcher.py +107 -0
  170. kivyforge/platforms/linux/lock/__init__.py +126 -0
  171. kivyforge/platforms/linux/lock/profile.py +254 -0
  172. kivyforge/platforms/linux/lock/runtime.py +75 -0
  173. kivyforge/platforms/linux/native_stage.py +47 -0
  174. kivyforge/platforms/linux/runtime_stage.py +107 -0
  175. kivyforge/platforms/linux/wheels_stage.py +103 -0
  176. kivyforge/platforms/macos/__init__.py +121 -0
  177. kivyforge/platforms/macos/bundle.py +255 -0
  178. kivyforge/platforms/macos/cli.py +269 -0
  179. kivyforge/platforms/macos/doctor.py +480 -0
  180. kivyforge/platforms/macos/icns.py +75 -0
  181. kivyforge/platforms/macos/launcher.py +118 -0
  182. kivyforge/platforms/macos/lock/__init__.py +112 -0
  183. kivyforge/platforms/macos/lock/profile.py +119 -0
  184. kivyforge/platforms/macos/lock/runtime.py +58 -0
  185. kivyforge/platforms/macos/machotools.py +138 -0
  186. kivyforge/platforms/macos/native_stage.py +47 -0
  187. kivyforge/platforms/macos/notarize.py +143 -0
  188. kivyforge/platforms/macos/plist.py +37 -0
  189. kivyforge/platforms/macos/runtime_stage.py +110 -0
  190. kivyforge/platforms/macos/signing.py +78 -0
  191. kivyforge/platforms/macos/wheels_stage.py +108 -0
  192. kivyforge/platforms/windows/__init__.py +133 -0
  193. kivyforge/platforms/windows/assets.py +76 -0
  194. kivyforge/platforms/windows/bundle.py +298 -0
  195. kivyforge/platforms/windows/cli.py +314 -0
  196. kivyforge/platforms/windows/doctor.py +563 -0
  197. kivyforge/platforms/windows/fsswap.py +87 -0
  198. kivyforge/platforms/windows/icons.py +64 -0
  199. kivyforge/platforms/windows/launcher/__init__.py +193 -0
  200. kivyforge/platforms/windows/launcher/build_launcher.py +507 -0
  201. kivyforge/platforms/windows/launcher/launcher.c +379 -0
  202. kivyforge/platforms/windows/lock/__init__.py +112 -0
  203. kivyforge/platforms/windows/lock/profile.py +101 -0
  204. kivyforge/platforms/windows/lock/runtime.py +64 -0
  205. kivyforge/platforms/windows/naming.py +52 -0
  206. kivyforge/platforms/windows/native_stage.py +66 -0
  207. kivyforge/platforms/windows/petools.py +98 -0
  208. kivyforge/platforms/windows/rcedit.py +116 -0
  209. kivyforge/platforms/windows/runtime_stage.py +221 -0
  210. kivyforge/platforms/windows/signing.py +168 -0
  211. kivyforge/platforms/windows/vendor/LICENSE.rcedit +29 -0
  212. kivyforge/platforms/windows/vendor/NOTICE +17 -0
  213. kivyforge/platforms/windows/vendor/SHA256SUMS +4 -0
  214. kivyforge/platforms/windows/vendor/TOOLSET.txt +4 -0
  215. kivyforge/platforms/windows/vendor/__init__.py +12 -0
  216. kivyforge/platforms/windows/vendor/fetch_rcedit.py +97 -0
  217. kivyforge/platforms/windows/vendor/launcher-amd64.exe +0 -0
  218. kivyforge/platforms/windows/vendor/rcedit-x64.exe +0 -0
  219. kivyforge/platforms/windows/wheels_stage.py +139 -0
  220. kivyforge-3.0.0.dev0.dist-info/METADATA +609 -0
  221. kivyforge-3.0.0.dev0.dist-info/RECORD +225 -0
  222. kivyforge-3.0.0.dev0.dist-info/WHEEL +5 -0
  223. kivyforge-3.0.0.dev0.dist-info/entry_points.txt +3 -0
  224. kivyforge-3.0.0.dev0.dist-info/licenses/LICENSE +21 -0
  225. kivyforge-3.0.0.dev0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,1010 @@
1
+ package org.libsdl.app;
2
+
3
+ import java.util.ArrayList;
4
+ import java.util.Collections;
5
+ import java.util.Comparator;
6
+ import java.util.List;
7
+
8
+ import android.content.Context;
9
+ import android.hardware.lights.Light;
10
+ import android.hardware.lights.LightsRequest;
11
+ import android.hardware.lights.LightsManager;
12
+ import android.hardware.lights.LightState;
13
+ import android.hardware.Sensor;
14
+ import android.hardware.SensorEvent;
15
+ import android.hardware.SensorEventListener;
16
+ import android.hardware.SensorManager;
17
+ import android.graphics.Color;
18
+ import android.os.Build;
19
+ import android.os.VibrationEffect;
20
+ import android.os.Vibrator;
21
+ import android.os.VibratorManager;
22
+ import android.util.Log;
23
+ import android.view.InputDevice;
24
+ import android.view.KeyEvent;
25
+ import android.view.MotionEvent;
26
+ import android.view.View;
27
+
28
+
29
+ public class SDLControllerManager
30
+ {
31
+
32
+ static native void nativeSetupJNI();
33
+
34
+ static native void nativeAddJoystick(int device_id, String name, String desc,
35
+ int vendor_id, int product_id,
36
+ int button_mask,
37
+ int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led,
38
+ boolean has_accelerometer, boolean has_gyroscope);
39
+ static native void nativeRemoveJoystick(int device_id);
40
+ static native void nativeAddHaptic(int device_id, String name);
41
+ static native void nativeRemoveHaptic(int device_id);
42
+ static public native boolean onNativePadDown(int device_id, int keycode, int scancode);
43
+ static public native boolean onNativePadUp(int device_id, int keycode, int scancode);
44
+ static native void onNativeJoy(int device_id, int axis,
45
+ float value);
46
+ static native void onNativeHat(int device_id, int hat_id,
47
+ int x, int y);
48
+ static native void onNativeJoySensor(int device_id, int sensor_type, long sensor_timestamp, float x, float y, float z);
49
+
50
+ protected static SDLJoystickHandler mJoystickHandler;
51
+ protected static SDLHapticHandler mHapticHandler;
52
+
53
+ private static final String TAG = "SDLControllerManager";
54
+
55
+ static void initialize() {
56
+ if (mJoystickHandler == null) {
57
+ mJoystickHandler = new SDLJoystickHandler();
58
+ }
59
+
60
+ if (mHapticHandler == null) {
61
+ if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
62
+ mHapticHandler = new SDLHapticHandler_API31();
63
+ } else if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
64
+ mHapticHandler = new SDLHapticHandler_API26();
65
+ } else {
66
+ mHapticHandler = new SDLHapticHandler();
67
+ }
68
+ }
69
+ }
70
+
71
+ // Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
72
+ static public boolean handleJoystickMotionEvent(MotionEvent event) {
73
+ return mJoystickHandler.handleMotionEvent(event);
74
+ }
75
+
76
+ /**
77
+ * This method is called by SDL using JNI.
78
+ */
79
+ static void pollInputDevices() {
80
+ mJoystickHandler.pollInputDevices();
81
+ }
82
+
83
+ /**
84
+ * This method is called by SDL using JNI.
85
+ */
86
+ static void joystickSetLED(int device_id, int red, int green, int blue) {
87
+ mJoystickHandler.setLED(device_id, red, green, blue);
88
+ }
89
+
90
+ /**
91
+ * This method is called by SDL using JNI.
92
+ */
93
+ static void joystickSetSensorsEnabled(int device_id, boolean enabled) {
94
+ mJoystickHandler.setSensorsEnabled(device_id, enabled);
95
+ }
96
+
97
+ /**
98
+ * This method is called by SDL using JNI.
99
+ */
100
+ static void pollHapticDevices() {
101
+ mHapticHandler.pollHapticDevices();
102
+ }
103
+
104
+ /**
105
+ * This method is called by SDL using JNI.
106
+ */
107
+ static void hapticRun(int device_id, float intensity, int length) {
108
+ mHapticHandler.run(device_id, intensity, length);
109
+ }
110
+
111
+ /**
112
+ * This method is called by SDL using JNI.
113
+ */
114
+ static void hapticRumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
115
+ mHapticHandler.rumble(device_id, low_frequency_intensity, high_frequency_intensity, length);
116
+ }
117
+
118
+ /**
119
+ * This method is called by SDL using JNI.
120
+ */
121
+ static void hapticStop(int device_id)
122
+ {
123
+ mHapticHandler.stop(device_id);
124
+ }
125
+
126
+ // Check if a given device is considered a possible SDL joystick
127
+ static public boolean isDeviceSDLJoystick(int deviceId) {
128
+ InputDevice device = InputDevice.getDevice(deviceId);
129
+ // We cannot use InputDevice.isVirtual before API 16, so let's accept
130
+ // only nonnegative device ids (VIRTUAL_KEYBOARD equals -1)
131
+ if ((device == null) || (deviceId < 0)) {
132
+ return false;
133
+ }
134
+ int sources = device.getSources();
135
+
136
+ /* This is called for every button press, so let's not spam the logs */
137
+ /*
138
+ if ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) {
139
+ Log.v(TAG, "Input device " + device.getName() + " has class joystick.");
140
+ }
141
+ if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) {
142
+ Log.v(TAG, "Input device " + device.getName() + " is a dpad.");
143
+ }
144
+ if ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) {
145
+ Log.v(TAG, "Input device " + device.getName() + " is a gamepad.");
146
+ }
147
+ */
148
+
149
+ return ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 ||
150
+ ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) ||
151
+ ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD)
152
+ );
153
+ }
154
+
155
+ }
156
+
157
+
158
+ /* Actual joystick functionality available for API >= 19 devices */
159
+ class SDLJoystickHandler {
160
+
161
+ static class SDLJoystick {
162
+ int device_id;
163
+ String name;
164
+ String desc;
165
+ ArrayList<InputDevice.MotionRange> axes;
166
+ ArrayList<InputDevice.MotionRange> hats;
167
+ ArrayList<Light> lights;
168
+ LightsManager.LightsSession lightsSession;
169
+ SensorManager sensorManager;
170
+ SDLJoySensorListener sensorListener;
171
+ Sensor accelerometerSensor;
172
+ Sensor gyroscopeSensor;
173
+ }
174
+ static class RangeComparator implements Comparator<InputDevice.MotionRange> {
175
+ @Override
176
+ public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) {
177
+ // Some controllers, like the Moga Pro 2, return AXIS_GAS (22) for right trigger and AXIS_BRAKE (23) for left trigger - swap them so they're sorted in the right order for SDL
178
+ int arg0Axis = arg0.getAxis();
179
+ int arg1Axis = arg1.getAxis();
180
+ if (arg0Axis == MotionEvent.AXIS_GAS) {
181
+ arg0Axis = MotionEvent.AXIS_BRAKE;
182
+ } else if (arg0Axis == MotionEvent.AXIS_BRAKE) {
183
+ arg0Axis = MotionEvent.AXIS_GAS;
184
+ }
185
+ if (arg1Axis == MotionEvent.AXIS_GAS) {
186
+ arg1Axis = MotionEvent.AXIS_BRAKE;
187
+ } else if (arg1Axis == MotionEvent.AXIS_BRAKE) {
188
+ arg1Axis = MotionEvent.AXIS_GAS;
189
+ }
190
+
191
+ // Make sure the AXIS_Z is sorted between AXIS_RY and AXIS_RZ.
192
+ // This is because the usual pairing are:
193
+ // - AXIS_X + AXIS_Y (left stick).
194
+ // - AXIS_RX, AXIS_RY (sometimes the right stick, sometimes triggers).
195
+ // - AXIS_Z, AXIS_RZ (sometimes the right stick, sometimes triggers).
196
+ // This sorts the axes in the above order, which tends to be correct
197
+ // for Xbox-ish game pads that have the right stick on RX/RY and the
198
+ // triggers on Z/RZ.
199
+ //
200
+ // Gamepads that don't have AXIS_Z/AXIS_RZ but use
201
+ // AXIS_LTRIGGER/AXIS_RTRIGGER are unaffected by this.
202
+ //
203
+ // References:
204
+ // - https://developer.android.com/develop/ui/views/touch-and-input/game-controllers/controller-input
205
+ // - https://www.kernel.org/doc/html/latest/input/gamepad.html
206
+ if (arg0Axis == MotionEvent.AXIS_Z) {
207
+ arg0Axis = MotionEvent.AXIS_RZ - 1;
208
+ } else if (arg0Axis > MotionEvent.AXIS_Z && arg0Axis < MotionEvent.AXIS_RZ) {
209
+ --arg0Axis;
210
+ }
211
+ if (arg1Axis == MotionEvent.AXIS_Z) {
212
+ arg1Axis = MotionEvent.AXIS_RZ - 1;
213
+ } else if (arg1Axis > MotionEvent.AXIS_Z && arg1Axis < MotionEvent.AXIS_RZ) {
214
+ --arg1Axis;
215
+ }
216
+
217
+ return arg0Axis - arg1Axis;
218
+ }
219
+ }
220
+
221
+ private final ArrayList<SDLJoystick> mJoysticks;
222
+
223
+ SDLJoystickHandler() {
224
+
225
+ mJoysticks = new ArrayList<SDLJoystick>();
226
+ }
227
+
228
+ /**
229
+ * Handles adding and removing of input devices.
230
+ */
231
+ synchronized void pollInputDevices() {
232
+ int[] deviceIds = InputDevice.getDeviceIds();
233
+
234
+ for (int device_id : deviceIds) {
235
+ if (SDLControllerManager.isDeviceSDLJoystick(device_id)) {
236
+ SDLJoystick joystick = getJoystick(device_id);
237
+ if (joystick == null) {
238
+ InputDevice joystickDevice = InputDevice.getDevice(device_id);
239
+ joystick = new SDLJoystick();
240
+ joystick.device_id = device_id;
241
+ joystick.name = joystickDevice.getName();
242
+ joystick.desc = getJoystickDescriptor(joystickDevice);
243
+ joystick.axes = new ArrayList<InputDevice.MotionRange>();
244
+ joystick.hats = new ArrayList<InputDevice.MotionRange>();
245
+ java.util.Set<Integer> axisStrsSet = new java.util.HashSet<Integer>();
246
+ joystick.lights = new ArrayList<Light>();
247
+
248
+ List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
249
+ Collections.sort(ranges, new RangeComparator());
250
+ for (InputDevice.MotionRange range : ranges) {
251
+ if (((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) && axisStrsSet.add(range.getAxis())) {
252
+ if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) {
253
+ joystick.hats.add(range);
254
+ } else {
255
+ joystick.axes.add(range);
256
+ }
257
+ }
258
+ }
259
+
260
+ boolean can_rumble = false;
261
+ boolean has_rgb_led = false;
262
+ boolean has_accelerometer = false;
263
+ boolean has_gyroscope = false;
264
+ if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
265
+ VibratorManager vibratorManager = joystickDevice.getVibratorManager();
266
+ int[] vibrators = vibratorManager.getVibratorIds();
267
+ if (vibrators.length > 0) {
268
+ can_rumble = true;
269
+ }
270
+ LightsManager lightsManager = joystickDevice.getLightsManager();
271
+ List<Light> lights = lightsManager.getLights();
272
+ for (Light light : lights) {
273
+ if (light.hasRgbControl()) {
274
+ joystick.lights.add(light);
275
+ }
276
+ }
277
+ if (!joystick.lights.isEmpty()) {
278
+ joystick.lightsSession = lightsManager.openSession();
279
+ has_rgb_led = true;
280
+ }
281
+ SensorManager sensorManager = joystickDevice.getSensorManager();
282
+ if (sensorManager != null) {
283
+ joystick.sensorManager = sensorManager;
284
+ joystick.sensorListener = new SDLJoySensorListener(joystick.device_id);
285
+ joystick.accelerometerSensor = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
286
+ if (joystick.accelerometerSensor != null) {
287
+ has_accelerometer = true;
288
+ }
289
+ joystick.gyroscopeSensor = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
290
+ if (joystick.gyroscopeSensor != null) {
291
+ has_gyroscope = true;
292
+ }
293
+ }
294
+ }
295
+
296
+ mJoysticks.add(joystick);
297
+ SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
298
+ getVendorId(joystickDevice), getProductId(joystickDevice),
299
+ getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led,
300
+ has_accelerometer, has_gyroscope);
301
+ }
302
+ }
303
+ }
304
+
305
+ /* Check removed devices */
306
+ ArrayList<Integer> removedDevices = null;
307
+ for (SDLJoystick joystick : mJoysticks) {
308
+ int device_id = joystick.device_id;
309
+ int i;
310
+ for (i = 0; i < deviceIds.length; i++) {
311
+ if (device_id == deviceIds[i]) break;
312
+ }
313
+ if (i == deviceIds.length) {
314
+ if (removedDevices == null) {
315
+ removedDevices = new ArrayList<Integer>();
316
+ }
317
+ removedDevices.add(device_id);
318
+ }
319
+ }
320
+
321
+ if (removedDevices != null) {
322
+ for (int device_id : removedDevices) {
323
+ SDLControllerManager.nativeRemoveJoystick(device_id);
324
+ for (int i = 0; i < mJoysticks.size(); i++) {
325
+ if (mJoysticks.get(i).device_id == device_id) {
326
+ if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
327
+ if (mJoysticks.get(i).lightsSession != null) {
328
+ try {
329
+ mJoysticks.get(i).lightsSession.close();
330
+ } catch (Exception e) {
331
+ // Session may already be unregistered when device disconnects
332
+ }
333
+ mJoysticks.get(i).lightsSession = null;
334
+ }
335
+ }
336
+ mJoysticks.remove(i);
337
+ break;
338
+ }
339
+ }
340
+ }
341
+ }
342
+ }
343
+
344
+ synchronized protected SDLJoystick getJoystick(int device_id) {
345
+ for (SDLJoystick joystick : mJoysticks) {
346
+ if (joystick.device_id == device_id) {
347
+ return joystick;
348
+ }
349
+ }
350
+ return null;
351
+ }
352
+
353
+ /**
354
+ * Handles given MotionEvent.
355
+ * @param event the event to be handled.
356
+ * @return if given event was processed.
357
+ */
358
+ boolean handleMotionEvent(MotionEvent event) {
359
+ int actionPointerIndex = event.getActionIndex();
360
+ int action = event.getActionMasked();
361
+ if (action == MotionEvent.ACTION_MOVE) {
362
+ SDLJoystick joystick = getJoystick(event.getDeviceId());
363
+ if (joystick != null) {
364
+ for (int i = 0; i < joystick.axes.size(); i++) {
365
+ InputDevice.MotionRange range = joystick.axes.get(i);
366
+ /* Normalize the value to -1...1 */
367
+ float value = (event.getAxisValue(range.getAxis(), actionPointerIndex) - range.getMin()) / range.getRange() * 2.0f - 1.0f;
368
+ SDLControllerManager.onNativeJoy(joystick.device_id, i, value);
369
+ }
370
+ for (int i = 0; i < joystick.hats.size() / 2; i++) {
371
+ int hatX = Math.round(event.getAxisValue(joystick.hats.get(2 * i).getAxis(), actionPointerIndex));
372
+ int hatY = Math.round(event.getAxisValue(joystick.hats.get(2 * i + 1).getAxis(), actionPointerIndex));
373
+ SDLControllerManager.onNativeHat(joystick.device_id, i, hatX, hatY);
374
+ }
375
+ }
376
+ }
377
+ return true;
378
+ }
379
+
380
+ String getJoystickDescriptor(InputDevice joystickDevice) {
381
+ String desc = joystickDevice.getDescriptor();
382
+
383
+ if (desc != null && !desc.isEmpty()) {
384
+ return desc;
385
+ }
386
+
387
+ return joystickDevice.getName();
388
+ }
389
+
390
+ int getProductId(InputDevice joystickDevice) {
391
+ return joystickDevice.getProductId();
392
+ }
393
+
394
+ int getVendorId(InputDevice joystickDevice) {
395
+ return joystickDevice.getVendorId();
396
+ }
397
+
398
+ int getAxisMask(List<InputDevice.MotionRange> ranges) {
399
+ // For compatibility, keep computing the axis mask like before,
400
+ // only really distinguishing 2, 4 and 6 axes.
401
+ int axis_mask = 0;
402
+ if (ranges.size() >= 2) {
403
+ // ((1 << SDL_GAMEPAD_AXIS_LEFTX) | (1 << SDL_GAMEPAD_AXIS_LEFTY))
404
+ axis_mask |= 0x0003;
405
+ }
406
+ if (ranges.size() >= 4) {
407
+ // ((1 << SDL_GAMEPAD_AXIS_RIGHTX) | (1 << SDL_GAMEPAD_AXIS_RIGHTY))
408
+ axis_mask |= 0x000c;
409
+ }
410
+ if (ranges.size() >= 6) {
411
+ // ((1 << SDL_GAMEPAD_AXIS_LEFT_TRIGGER) | (1 << SDL_GAMEPAD_AXIS_RIGHT_TRIGGER))
412
+ axis_mask |= 0x0030;
413
+ }
414
+ // Also add an indicator bit for whether the sorting order has changed.
415
+ // This serves to disable outdated gamecontrollerdb.txt mappings.
416
+ boolean have_z = false;
417
+ boolean have_past_z_before_rz = false;
418
+ for (InputDevice.MotionRange range : ranges) {
419
+ int axis = range.getAxis();
420
+ if (axis == MotionEvent.AXIS_Z) {
421
+ have_z = true;
422
+ } else if (axis > MotionEvent.AXIS_Z && axis < MotionEvent.AXIS_RZ) {
423
+ have_past_z_before_rz = true;
424
+ }
425
+ }
426
+ if (have_z && have_past_z_before_rz) {
427
+ // If both these exist, the compare() function changed sorting order.
428
+ // Set a bit to indicate this fact.
429
+ axis_mask |= 0x8000;
430
+ }
431
+ return axis_mask;
432
+ }
433
+
434
+ int getButtonMask(InputDevice joystickDevice) {
435
+ int button_mask = 0;
436
+ int[] keys = new int[] {
437
+ KeyEvent.KEYCODE_BUTTON_A,
438
+ KeyEvent.KEYCODE_BUTTON_B,
439
+ KeyEvent.KEYCODE_BUTTON_X,
440
+ KeyEvent.KEYCODE_BUTTON_Y,
441
+ KeyEvent.KEYCODE_BACK,
442
+ KeyEvent.KEYCODE_MENU,
443
+ KeyEvent.KEYCODE_BUTTON_MODE,
444
+ KeyEvent.KEYCODE_BUTTON_START,
445
+ KeyEvent.KEYCODE_BUTTON_THUMBL,
446
+ KeyEvent.KEYCODE_BUTTON_THUMBR,
447
+ KeyEvent.KEYCODE_BUTTON_L1,
448
+ KeyEvent.KEYCODE_BUTTON_R1,
449
+ KeyEvent.KEYCODE_DPAD_UP,
450
+ KeyEvent.KEYCODE_DPAD_DOWN,
451
+ KeyEvent.KEYCODE_DPAD_LEFT,
452
+ KeyEvent.KEYCODE_DPAD_RIGHT,
453
+ KeyEvent.KEYCODE_BUTTON_SELECT,
454
+ KeyEvent.KEYCODE_DPAD_CENTER,
455
+
456
+ // These don't map into any SDL controller buttons directly
457
+ KeyEvent.KEYCODE_BUTTON_L2,
458
+ KeyEvent.KEYCODE_BUTTON_R2,
459
+ KeyEvent.KEYCODE_BUTTON_C,
460
+ KeyEvent.KEYCODE_BUTTON_Z,
461
+ KeyEvent.KEYCODE_BUTTON_1,
462
+ KeyEvent.KEYCODE_BUTTON_2,
463
+ KeyEvent.KEYCODE_BUTTON_3,
464
+ KeyEvent.KEYCODE_BUTTON_4,
465
+ KeyEvent.KEYCODE_BUTTON_5,
466
+ KeyEvent.KEYCODE_BUTTON_6,
467
+ KeyEvent.KEYCODE_BUTTON_7,
468
+ KeyEvent.KEYCODE_BUTTON_8,
469
+ KeyEvent.KEYCODE_BUTTON_9,
470
+ KeyEvent.KEYCODE_BUTTON_10,
471
+ KeyEvent.KEYCODE_BUTTON_11,
472
+ KeyEvent.KEYCODE_BUTTON_12,
473
+ KeyEvent.KEYCODE_BUTTON_13,
474
+ KeyEvent.KEYCODE_BUTTON_14,
475
+ KeyEvent.KEYCODE_BUTTON_15,
476
+ KeyEvent.KEYCODE_BUTTON_16,
477
+ };
478
+ int[] masks = new int[] {
479
+ (1 << 0), // A -> A
480
+ (1 << 1), // B -> B
481
+ (1 << 2), // X -> X
482
+ (1 << 3), // Y -> Y
483
+ (1 << 4), // BACK -> BACK
484
+ (1 << 6), // MENU -> START
485
+ (1 << 5), // MODE -> GUIDE
486
+ (1 << 6), // START -> START
487
+ (1 << 7), // THUMBL -> LEFTSTICK
488
+ (1 << 8), // THUMBR -> RIGHTSTICK
489
+ (1 << 9), // L1 -> LEFTSHOULDER
490
+ (1 << 10), // R1 -> RIGHTSHOULDER
491
+ (1 << 11), // DPAD_UP -> DPAD_UP
492
+ (1 << 12), // DPAD_DOWN -> DPAD_DOWN
493
+ (1 << 13), // DPAD_LEFT -> DPAD_LEFT
494
+ (1 << 14), // DPAD_RIGHT -> DPAD_RIGHT
495
+ (1 << 4), // SELECT -> BACK
496
+ (1 << 0), // DPAD_CENTER -> A
497
+ (1 << 15), // L2 -> ??
498
+ (1 << 16), // R2 -> ??
499
+ (1 << 17), // C -> ??
500
+ (1 << 18), // Z -> ??
501
+ (1 << 20), // 1 -> ??
502
+ (1 << 21), // 2 -> ??
503
+ (1 << 22), // 3 -> ??
504
+ (1 << 23), // 4 -> ??
505
+ (1 << 24), // 5 -> ??
506
+ (1 << 25), // 6 -> ??
507
+ (1 << 26), // 7 -> ??
508
+ (1 << 27), // 8 -> ??
509
+ (1 << 28), // 9 -> ??
510
+ (1 << 29), // 10 -> ??
511
+ (1 << 30), // 11 -> ??
512
+ (1 << 31), // 12 -> ??
513
+ // We're out of room...
514
+ 0xFFFFFFFF, // 13 -> ??
515
+ 0xFFFFFFFF, // 14 -> ??
516
+ 0xFFFFFFFF, // 15 -> ??
517
+ 0xFFFFFFFF, // 16 -> ??
518
+ };
519
+ boolean[] has_keys = joystickDevice.hasKeys(keys);
520
+ for (int i = 0; i < keys.length; ++i) {
521
+ if (has_keys[i]) {
522
+ button_mask |= masks[i];
523
+ }
524
+ }
525
+ return button_mask;
526
+ }
527
+
528
+ void setLED(int device_id, int red, int green, int blue) {
529
+ if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
530
+ return;
531
+ }
532
+ SDLJoystick joystick = getJoystick(device_id);
533
+ if (joystick == null || joystick.lights.isEmpty()) {
534
+ return;
535
+ }
536
+ LightsRequest.Builder lightsRequest = new LightsRequest.Builder();
537
+ LightState lightState = new LightState.Builder().setColor(Color.rgb(red, green, blue)).build();
538
+ for (Light light : joystick.lights) {
539
+ if (light.hasRgbControl()) {
540
+ lightsRequest.addLight(light, lightState);
541
+ }
542
+ }
543
+ joystick.lightsSession.requestLights(lightsRequest.build());
544
+ }
545
+
546
+ void setSensorsEnabled(int device_id, boolean enabled) {
547
+ if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
548
+ return;
549
+ }
550
+ SDLJoystick joystick = getJoystick(device_id);
551
+ if (joystick == null || joystick.sensorManager == null) {
552
+ return;
553
+ }
554
+ if (enabled) {
555
+ if (joystick.accelerometerSensor != null) {
556
+ SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor, SensorManager.SENSOR_DELAY_GAME);
557
+ }
558
+ if (joystick.gyroscopeSensor != null) {
559
+ SDLSensorManager.registerListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor, SensorManager.SENSOR_DELAY_GAME);
560
+ }
561
+ } else {
562
+ if (joystick.accelerometerSensor != null) {
563
+ SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.accelerometerSensor);
564
+ }
565
+ if (joystick.gyroscopeSensor != null) {
566
+ SDLSensorManager.unregisterListener(joystick.sensorManager, joystick.sensorListener, joystick.gyroscopeSensor);
567
+ }
568
+ }
569
+ }
570
+ }
571
+
572
+ class SDLHapticHandler_API31 extends SDLHapticHandler {
573
+ @Override
574
+ void run(int device_id, float intensity, int length) {
575
+ SDLHaptic haptic = getHaptic(device_id);
576
+ if (haptic != null) {
577
+ vibrate(haptic.vib, intensity, length);
578
+ }
579
+ }
580
+
581
+ @Override
582
+ void rumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
583
+ InputDevice device = InputDevice.getDevice(device_id);
584
+ if (device == null) {
585
+ return;
586
+ }
587
+
588
+ if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
589
+ /* Silence 'lint' warning */
590
+ return;
591
+ }
592
+
593
+ VibratorManager manager = device.getVibratorManager();
594
+ int[] vibrators = manager.getVibratorIds();
595
+ if (vibrators.length >= 2) {
596
+ vibrate(manager.getVibrator(vibrators[0]), low_frequency_intensity, length);
597
+ vibrate(manager.getVibrator(vibrators[1]), high_frequency_intensity, length);
598
+ } else if (vibrators.length == 1) {
599
+ float intensity = (low_frequency_intensity * 0.6f) + (high_frequency_intensity * 0.4f);
600
+ vibrate(manager.getVibrator(vibrators[0]), intensity, length);
601
+ }
602
+ }
603
+
604
+ private void vibrate(Vibrator vibrator, float intensity, int length) {
605
+
606
+ if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
607
+ /* Silence 'lint' warning */
608
+ return;
609
+ }
610
+
611
+ if (intensity == 0.0f) {
612
+ vibrator.cancel();
613
+ return;
614
+ }
615
+
616
+ int value = Math.round(intensity * 255);
617
+ if (value > 255) {
618
+ value = 255;
619
+ }
620
+ if (value < 1) {
621
+ vibrator.cancel();
622
+ return;
623
+ }
624
+ try {
625
+ vibrator.vibrate(VibrationEffect.createOneShot(length, value));
626
+ }
627
+ catch (Exception e) {
628
+ // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if
629
+ // something went horribly wrong with the Android 8.0 APIs.
630
+ vibrator.vibrate(length);
631
+ }
632
+ }
633
+ }
634
+
635
+ class SDLHapticHandler_API26 extends SDLHapticHandler {
636
+ @Override
637
+ void run(int device_id, float intensity, int length) {
638
+
639
+ if (Build.VERSION.SDK_INT < 26 /* Android 8.0 (O) */) {
640
+ /* Silence 'lint' warning */
641
+ return;
642
+ }
643
+
644
+ SDLHaptic haptic = getHaptic(device_id);
645
+ if (haptic != null) {
646
+ if (intensity == 0.0f) {
647
+ stop(device_id);
648
+ return;
649
+ }
650
+
651
+ int vibeValue = Math.round(intensity * 255);
652
+
653
+ if (vibeValue > 255) {
654
+ vibeValue = 255;
655
+ }
656
+ if (vibeValue < 1) {
657
+ stop(device_id);
658
+ return;
659
+ }
660
+ try {
661
+ haptic.vib.vibrate(VibrationEffect.createOneShot(length, vibeValue));
662
+ }
663
+ catch (Exception e) {
664
+ // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if
665
+ // something went horribly wrong with the Android 8.0 APIs.
666
+ haptic.vib.vibrate(length);
667
+ }
668
+ }
669
+ }
670
+ }
671
+
672
+ class SDLHapticHandler {
673
+
674
+ static class SDLHaptic {
675
+ int device_id;
676
+ String name;
677
+ Vibrator vib;
678
+ }
679
+
680
+ private final ArrayList<SDLHaptic> mHaptics;
681
+
682
+ SDLHapticHandler() {
683
+ mHaptics = new ArrayList<SDLHaptic>();
684
+ }
685
+
686
+ void run(int device_id, float intensity, int length) {
687
+ SDLHaptic haptic = getHaptic(device_id);
688
+ if (haptic != null) {
689
+ haptic.vib.vibrate(length);
690
+ }
691
+ }
692
+
693
+ void rumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
694
+ // Not supported in older APIs
695
+ }
696
+
697
+ void stop(int device_id) {
698
+ SDLHaptic haptic = getHaptic(device_id);
699
+ if (haptic != null) {
700
+ haptic.vib.cancel();
701
+ }
702
+ }
703
+
704
+ synchronized void pollHapticDevices() {
705
+
706
+ final int deviceId_VIBRATOR_SERVICE = 999999;
707
+ boolean hasVibratorService = false;
708
+
709
+ /* Check VIBRATOR_SERVICE */
710
+ Vibrator vib = (Vibrator) SDL.getContext().getSystemService(Context.VIBRATOR_SERVICE);
711
+ if (vib != null) {
712
+ hasVibratorService = vib.hasVibrator();
713
+
714
+ if (hasVibratorService) {
715
+ SDLHaptic haptic = getHaptic(deviceId_VIBRATOR_SERVICE);
716
+ if (haptic == null) {
717
+ haptic = new SDLHaptic();
718
+ haptic.device_id = deviceId_VIBRATOR_SERVICE;
719
+ haptic.name = "VIBRATOR_SERVICE";
720
+ haptic.vib = vib;
721
+ mHaptics.add(haptic);
722
+ SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
723
+ }
724
+ }
725
+ }
726
+
727
+ /* Check removed devices */
728
+ ArrayList<Integer> removedDevices = null;
729
+ for (SDLHaptic haptic : mHaptics) {
730
+ int device_id = haptic.device_id;
731
+ if (device_id != deviceId_VIBRATOR_SERVICE || !hasVibratorService) {
732
+ if (removedDevices == null) {
733
+ removedDevices = new ArrayList<Integer>();
734
+ }
735
+ removedDevices.add(device_id);
736
+ } // else: don't remove the vibrator if it is still present
737
+ }
738
+
739
+ if (removedDevices != null) {
740
+ for (int device_id : removedDevices) {
741
+ SDLControllerManager.nativeRemoveHaptic(device_id);
742
+ for (int i = 0; i < mHaptics.size(); i++) {
743
+ if (mHaptics.get(i).device_id == device_id) {
744
+ mHaptics.remove(i);
745
+ break;
746
+ }
747
+ }
748
+ }
749
+ }
750
+ }
751
+
752
+ synchronized protected SDLHaptic getHaptic(int device_id) {
753
+ for (SDLHaptic haptic : mHaptics) {
754
+ if (haptic.device_id == device_id) {
755
+ return haptic;
756
+ }
757
+ }
758
+ return null;
759
+ }
760
+ }
761
+
762
+ class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
763
+ protected static final int SDL_PEN_DEVICE_TYPE_UNKNOWN = 0;
764
+ protected static final int SDL_PEN_DEVICE_TYPE_DIRECT = 1;
765
+ protected static final int SDL_PEN_DEVICE_TYPE_INDIRECT = 2;
766
+
767
+ // Generic Motion (mouse hover, joystick...) events go here
768
+ @Override
769
+ public boolean onGenericMotion(View v, MotionEvent event) {
770
+ if (event.getSource() == InputDevice.SOURCE_JOYSTICK)
771
+ return SDLControllerManager.handleJoystickMotionEvent(event);
772
+
773
+ float x, y;
774
+ int action = event.getActionMasked();
775
+ int pointerCount = event.getPointerCount();
776
+ boolean consumed = false;
777
+
778
+ for (int i = 0; i < pointerCount; i++) {
779
+ int toolType = event.getToolType(i);
780
+
781
+ if (toolType == MotionEvent.TOOL_TYPE_MOUSE) {
782
+ switch (action) {
783
+ case MotionEvent.ACTION_SCROLL:
784
+ x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, i);
785
+ y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, i);
786
+ SDLActivity.onNativeMouse(0, action, x, y, false);
787
+ consumed = true;
788
+ break;
789
+
790
+ case MotionEvent.ACTION_HOVER_MOVE:
791
+ x = getEventX(event, i);
792
+ y = getEventY(event, i);
793
+
794
+ SDLActivity.onNativeMouse(0, action, x, y, checkRelativeEvent(event));
795
+ consumed = true;
796
+ break;
797
+
798
+ default:
799
+ break;
800
+ }
801
+ } else if (toolType == MotionEvent.TOOL_TYPE_STYLUS || toolType == MotionEvent.TOOL_TYPE_ERASER) {
802
+ switch (action) {
803
+ case MotionEvent.ACTION_HOVER_ENTER:
804
+ case MotionEvent.ACTION_HOVER_MOVE:
805
+ case MotionEvent.ACTION_HOVER_EXIT:
806
+ x = event.getX(i);
807
+ y = event.getY(i);
808
+ float p = event.getPressure(i);
809
+ if (p > 1.0f) {
810
+ // may be larger than 1.0f on some devices
811
+ // see the documentation of getPressure(i)
812
+ p = 1.0f;
813
+ }
814
+
815
+ // BUTTON_STYLUS_PRIMARY is 2^5, so shift by 4, and apply SDL_PEN_INPUT_DOWN/SDL_PEN_INPUT_ERASER_TIP
816
+ int buttons = (event.getButtonState() >> 4) | (1 << (toolType == MotionEvent.TOOL_TYPE_STYLUS ? 0 : 30));
817
+ if ((event.getButtonState() & MotionEvent.BUTTON_TERTIARY) != 0) {
818
+ buttons |= 0x08;
819
+ }
820
+
821
+ SDLActivity.onNativePen(event.getPointerId(i), getPenDeviceType(event.getDevice()), buttons, action, x, y, p);
822
+ consumed = true;
823
+ break;
824
+ }
825
+ }
826
+ }
827
+
828
+ return consumed;
829
+ }
830
+
831
+ boolean supportsRelativeMouse() {
832
+ return false;
833
+ }
834
+
835
+ boolean inRelativeMode() {
836
+ return false;
837
+ }
838
+
839
+ boolean setRelativeMouseEnabled(boolean enabled) {
840
+ return false;
841
+ }
842
+
843
+ void reclaimRelativeMouseModeIfNeeded() {
844
+
845
+ }
846
+
847
+ boolean checkRelativeEvent(MotionEvent event) {
848
+ return inRelativeMode();
849
+ }
850
+
851
+ float getEventX(MotionEvent event, int pointerIndex) {
852
+ return event.getX(pointerIndex);
853
+ }
854
+
855
+ float getEventY(MotionEvent event, int pointerIndex) {
856
+ return event.getY(pointerIndex);
857
+ }
858
+
859
+ int getPenDeviceType(InputDevice penDevice) {
860
+ return SDL_PEN_DEVICE_TYPE_UNKNOWN;
861
+ }
862
+ }
863
+
864
+ class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API14 {
865
+ // Generic Motion (mouse hover, joystick...) events go here
866
+
867
+ private boolean mRelativeModeEnabled;
868
+
869
+ @Override
870
+ boolean supportsRelativeMouse() {
871
+ return true;
872
+ }
873
+
874
+ @Override
875
+ boolean inRelativeMode() {
876
+ return mRelativeModeEnabled;
877
+ }
878
+
879
+ @Override
880
+ boolean setRelativeMouseEnabled(boolean enabled) {
881
+ mRelativeModeEnabled = enabled;
882
+ return true;
883
+ }
884
+
885
+ @Override
886
+ float getEventX(MotionEvent event, int pointerIndex) {
887
+ if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {
888
+ /* Silence 'lint' warning */
889
+ return 0;
890
+ }
891
+
892
+ if (mRelativeModeEnabled && event.getToolType(pointerIndex) == MotionEvent.TOOL_TYPE_MOUSE) {
893
+ return event.getAxisValue(MotionEvent.AXIS_RELATIVE_X, pointerIndex);
894
+ } else {
895
+ return event.getX(pointerIndex);
896
+ }
897
+ }
898
+
899
+ @Override
900
+ float getEventY(MotionEvent event, int pointerIndex) {
901
+ if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {
902
+ /* Silence 'lint' warning */
903
+ return 0;
904
+ }
905
+
906
+ if (mRelativeModeEnabled && event.getToolType(pointerIndex) == MotionEvent.TOOL_TYPE_MOUSE) {
907
+ return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y, pointerIndex);
908
+ } else {
909
+ return event.getY(pointerIndex);
910
+ }
911
+ }
912
+ }
913
+
914
+ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
915
+ // Generic Motion (mouse hover, joystick...) events go here
916
+ private boolean mRelativeModeEnabled;
917
+
918
+ @Override
919
+ boolean supportsRelativeMouse() {
920
+ return (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */);
921
+ }
922
+
923
+ @Override
924
+ boolean inRelativeMode() {
925
+ return mRelativeModeEnabled;
926
+ }
927
+
928
+ @Override
929
+ boolean setRelativeMouseEnabled(boolean enabled) {
930
+
931
+ if (Build.VERSION.SDK_INT < 26 /* Android 8.0 (O) */) {
932
+ /* Silence 'lint' warning */
933
+ return false;
934
+ }
935
+
936
+ if (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */) {
937
+ if (enabled) {
938
+ SDLActivity.getContentView().requestPointerCapture();
939
+ } else {
940
+ SDLActivity.getContentView().releasePointerCapture();
941
+ }
942
+ mRelativeModeEnabled = enabled;
943
+ return true;
944
+ } else {
945
+ return false;
946
+ }
947
+ }
948
+
949
+ @Override
950
+ void reclaimRelativeMouseModeIfNeeded() {
951
+
952
+ if (Build.VERSION.SDK_INT < 26 /* Android 8.0 (O) */) {
953
+ /* Silence 'lint' warning */
954
+ return;
955
+ }
956
+
957
+ if (mRelativeModeEnabled && !SDLActivity.isDeXMode()) {
958
+ SDLActivity.getContentView().requestPointerCapture();
959
+ }
960
+ }
961
+
962
+ @Override
963
+ boolean checkRelativeEvent(MotionEvent event) {
964
+ if (Build.VERSION.SDK_INT < 26 /* Android 8.0 (O) */) {
965
+ /* Silence 'lint' warning */
966
+ return false;
967
+ }
968
+ return event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE;
969
+ }
970
+
971
+ @Override
972
+ float getEventX(MotionEvent event, int pointerIndex) {
973
+ // Relative mouse in capture mode will only have relative for X/Y
974
+ return event.getX(pointerIndex);
975
+ }
976
+
977
+ @Override
978
+ float getEventY(MotionEvent event, int pointerIndex) {
979
+ // Relative mouse in capture mode will only have relative for X/Y
980
+ return event.getY(pointerIndex);
981
+ }
982
+ }
983
+
984
+ class SDLGenericMotionListener_API29 extends SDLGenericMotionListener_API26 {
985
+ @Override
986
+ int getPenDeviceType(InputDevice penDevice)
987
+ {
988
+ if (penDevice == null) {
989
+ return SDL_PEN_DEVICE_TYPE_UNKNOWN;
990
+ }
991
+
992
+ return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
993
+ }
994
+ }
995
+
996
+ class SDLJoySensorListener implements SensorEventListener {
997
+ int device_id;
998
+
999
+ public SDLJoySensorListener(int device_id) {
1000
+ this.device_id = device_id;
1001
+ }
1002
+
1003
+ @Override
1004
+ public void onAccuracyChanged(Sensor sensor, int accuracy) {}
1005
+
1006
+ @Override
1007
+ public void onSensorChanged(SensorEvent event) {
1008
+ SDLControllerManager.onNativeJoySensor(device_id, event.sensor.getType(), event.timestamp, event.values[0], event.values[1], event.values[2]);
1009
+ }
1010
+ }