From 0b66595c0fdffd0156ef9131d49c5ec09e0c6f3e Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 14 Dec 2022 23:27:17 -0500 Subject: [PATCH] update Android project template --- .../java/org/libsdl/app/HIDDeviceManager.java | 4 + .../main/java/org/libsdl/app/SDLActivity.java | 161 ++++++++++++++++-- .../org/libsdl/app/SDLControllerManager.java | 36 ++-- 3 files changed, 170 insertions(+), 31 deletions(-) diff --git a/android/app/src/main/java/org/libsdl/app/HIDDeviceManager.java b/android/app/src/main/java/org/libsdl/app/HIDDeviceManager.java index 802c7254..cf3c9267 100644 --- a/android/app/src/main/java/org/libsdl/app/HIDDeviceManager.java +++ b/android/app/src/main/java/org/libsdl/app/HIDDeviceManager.java @@ -248,7 +248,9 @@ public class HIDDeviceManager { 0x1689, // Razer Onza 0x1949, // Lab126, Inc. 0x1bad, // Harmonix + 0x20d6, // PowerA 0x24c6, // PowerA + 0x2c22, // Qanba }; if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_VENDOR_SPEC && @@ -274,7 +276,9 @@ public class HIDDeviceManager { 0x0e6f, // PDP 0x0f0d, // Hori 0x1532, // Razer Wildcat + 0x20d6, // PowerA 0x24c6, // PowerA + 0x2dc8, /* 8BitDo */ 0x2e24, // Hyperkin }; diff --git a/android/app/src/main/java/org/libsdl/app/SDLActivity.java b/android/app/src/main/java/org/libsdl/app/SDLActivity.java index 3da07209..55b961a4 100644 --- a/android/app/src/main/java/org/libsdl/app/SDLActivity.java +++ b/android/app/src/main/java/org/libsdl/app/SDLActivity.java @@ -27,7 +27,9 @@ import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Message; +import android.text.Editable; import android.text.InputType; +import android.text.Selection; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseArray; @@ -63,6 +65,112 @@ import java.util.Locale; */ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener { private static final String TAG = "SDL"; +/* + // Display InputType.SOURCE/CLASS of events and devices + // + // SDLActivity.debugSource(device.getSources(), "device[" + device.getName() + "]"); + // SDLActivity.debugSource(event.getSource(), "event"); + public static void debugSource(int sources, String prefix) { + int s = sources; + int s_copy = sources; + String cls = ""; + String src = ""; + int tst = 0; + int FLAG_TAINTED = 0x80000000; + + if ((s & InputDevice.SOURCE_CLASS_BUTTON) != 0) cls += " BUTTON"; + if ((s & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) cls += " JOYSTICK"; + if ((s & InputDevice.SOURCE_CLASS_POINTER) != 0) cls += " POINTER"; + if ((s & InputDevice.SOURCE_CLASS_POSITION) != 0) cls += " POSITION"; + if ((s & InputDevice.SOURCE_CLASS_TRACKBALL) != 0) cls += " TRACKBALL"; + + + int s2 = s_copy & ~InputDevice.SOURCE_ANY; // keep class bits + s2 &= ~( InputDevice.SOURCE_CLASS_BUTTON + | InputDevice.SOURCE_CLASS_JOYSTICK + | InputDevice.SOURCE_CLASS_POINTER + | InputDevice.SOURCE_CLASS_POSITION + | InputDevice.SOURCE_CLASS_TRACKBALL); + + if (s2 != 0) cls += "Some_Unkown"; + + s2 = s_copy & InputDevice.SOURCE_ANY; // keep source only, no class; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + tst = InputDevice.SOURCE_BLUETOOTH_STYLUS; + if ((s & tst) == tst) src += " BLUETOOTH_STYLUS"; + s2 &= ~tst; + } + + tst = InputDevice.SOURCE_DPAD; + if ((s & tst) == tst) src += " DPAD"; + s2 &= ~tst; + + tst = InputDevice.SOURCE_GAMEPAD; + if ((s & tst) == tst) src += " GAMEPAD"; + s2 &= ~tst; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + tst = InputDevice.SOURCE_HDMI; + if ((s & tst) == tst) src += " HDMI"; + s2 &= ~tst; + } + + tst = InputDevice.SOURCE_JOYSTICK; + if ((s & tst) == tst) src += " JOYSTICK"; + s2 &= ~tst; + + tst = InputDevice.SOURCE_KEYBOARD; + if ((s & tst) == tst) src += " KEYBOARD"; + s2 &= ~tst; + + tst = InputDevice.SOURCE_MOUSE; + if ((s & tst) == tst) src += " MOUSE"; + s2 &= ~tst; + + if (Build.VERSION.SDK_INT >= 26) { + tst = InputDevice.SOURCE_MOUSE_RELATIVE; + if ((s & tst) == tst) src += " MOUSE_RELATIVE"; + s2 &= ~tst; + + tst = InputDevice.SOURCE_ROTARY_ENCODER; + if ((s & tst) == tst) src += " ROTARY_ENCODER"; + s2 &= ~tst; + } + tst = InputDevice.SOURCE_STYLUS; + if ((s & tst) == tst) src += " STYLUS"; + s2 &= ~tst; + + tst = InputDevice.SOURCE_TOUCHPAD; + if ((s & tst) == tst) src += " TOUCHPAD"; + s2 &= ~tst; + + tst = InputDevice.SOURCE_TOUCHSCREEN; + if ((s & tst) == tst) src += " TOUCHSCREEN"; + s2 &= ~tst; + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { + tst = InputDevice.SOURCE_TOUCH_NAVIGATION; + if ((s & tst) == tst) src += " TOUCH_NAVIGATION"; + s2 &= ~tst; + } + + tst = InputDevice.SOURCE_TRACKBALL; + if ((s & tst) == tst) src += " TRACKBALL"; + s2 &= ~tst; + + tst = InputDevice.SOURCE_ANY; + if ((s & tst) == tst) src += " ANY"; + s2 &= ~tst; + + if (s == FLAG_TAINTED) src += " FLAG_TAINTED"; + s2 &= ~FLAG_TAINTED; + + if (s2 != 0) src += " Some_Unkown"; + + Log.v(TAG, prefix + "int=" + s_copy + " CLASS={" + cls + " } source(s):" + src); + } +*/ public static boolean mIsResumedCalled, mHasFocus; public static final boolean mHasMultiWindow = (Build.VERSION.SDK_INT >= 24); @@ -1204,8 +1312,21 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh for (int id : ids) { InputDevice device = InputDevice.getDevice(id); - if (device != null && (device.getSources() & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN) { - nativeAddTouch(device.getId(), device.getName()); + /* Allow SOURCE_TOUCHSCREEN and also Virtual InputDevices because they can send TOUCHSCREEN events */ + if (device != null && ((device.getSources() & InputDevice.SOURCE_TOUCHSCREEN) == InputDevice.SOURCE_TOUCHSCREEN + || device.isVirtual())) { + + int touchDevId = device.getId(); + /* + * Prevent id to be -1, since it's used in SDL internal for synthetic events + * Appears when using Android emulator, eg: + * adb shell input mouse tap 100 100 + * adb shell input touchscreen tap 100 100 + */ + if (touchDevId < 0) { + touchDevId -= 1; + } + nativeAddTouch(touchDevId, device.getName()); } } } @@ -1895,7 +2016,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, } } - if ((source & InputDevice.SOURCE_KEYBOARD) != 0) { + if ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) { if (event.getAction() == KeyEvent.ACTION_DOWN) { if (SDLActivity.isTextInputEvent(event)) { SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1); @@ -1908,7 +2029,7 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, } } - if ((source & InputDevice.SOURCE_MOUSE) != 0) { + if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) { // on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses // they are ignored here because sending them as mouse input to SDL is messy if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) { @@ -2195,7 +2316,7 @@ class DummyEdit extends View implements View.OnKeyListener { public InputConnection onCreateInputConnection(EditorInfo outAttrs) { ic = new SDLInputConnection(this, true); - outAttrs.inputType = InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD; + outAttrs.inputType = InputType.TYPE_CLASS_TEXT; outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */; @@ -2237,6 +2358,29 @@ class SDLInputConnection extends BaseInputConnection { @Override public boolean commitText(CharSequence text, int newCursorPosition) { + /* Generate backspaces for the text we're going to replace */ + final Editable content = getEditable(); + if (content != null) { + int a = getComposingSpanStart(content); + int b = getComposingSpanEnd(content); + if (a == -1 || b == -1) { + a = Selection.getSelectionStart(content); + b = Selection.getSelectionEnd(content); + } + if (a < 0) a = 0; + if (b < 0) b = 0; + if (b < a) { + int tmp = a; + a = b; + b = tmp; + } + int backspaces = (b - a); + + for (int i = 0; i < backspaces; i++) { + nativeGenerateScancodeForUnichar('\b'); + } + } + for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); if (c == '\n') { @@ -2271,14 +2415,11 @@ class SDLInputConnection extends BaseInputConnection { // Workaround to capture backspace key. Ref: http://stackoverflow.com/questions/14560344/android-backspace-in-webview-baseinputconnection // and https://bugzilla.libsdl.org/show_bug.cgi?id=2265 if (beforeLength > 0 && afterLength == 0) { - boolean ret = true; // backspace(s) while (beforeLength-- > 0) { - boolean ret_key = sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL)) - && sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL)); - ret = ret && ret_key; + nativeGenerateScancodeForUnichar('\b'); } - return ret; + return true; } return super.deleteSurroundingText(beforeLength, afterLength); diff --git a/android/app/src/main/java/org/libsdl/app/SDLControllerManager.java b/android/app/src/main/java/org/libsdl/app/SDLControllerManager.java index 1fa32ef3..82373d9d 100644 --- a/android/app/src/main/java/org/libsdl/app/SDLControllerManager.java +++ b/android/app/src/main/java/org/libsdl/app/SDLControllerManager.java @@ -255,23 +255,21 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler { @Override public boolean handleMotionEvent(MotionEvent event) { - if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) { - int actionPointerIndex = event.getActionIndex(); - int action = event.getActionMasked(); - if (action == MotionEvent.ACTION_MOVE) { - SDLJoystick joystick = getJoystick(event.getDeviceId()); - if (joystick != null) { - for (int i = 0; i < joystick.axes.size(); i++) { - InputDevice.MotionRange range = joystick.axes.get(i); - /* Normalize the value to -1...1 */ - float value = (event.getAxisValue(range.getAxis(), actionPointerIndex) - range.getMin()) / range.getRange() * 2.0f - 1.0f; - SDLControllerManager.onNativeJoy(joystick.device_id, i, value); - } - for (int i = 0; i < joystick.hats.size() / 2; i++) { - int hatX = Math.round(event.getAxisValue(joystick.hats.get(2 * i).getAxis(), actionPointerIndex)); - int hatY = Math.round(event.getAxisValue(joystick.hats.get(2 * i + 1).getAxis(), actionPointerIndex)); - SDLControllerManager.onNativeHat(joystick.device_id, i, hatX, hatY); - } + int actionPointerIndex = event.getActionIndex(); + int action = event.getActionMasked(); + if (action == MotionEvent.ACTION_MOVE) { + SDLJoystick joystick = getJoystick(event.getDeviceId()); + if (joystick != null) { + for (int i = 0; i < joystick.axes.size(); i++) { + InputDevice.MotionRange range = joystick.axes.get(i); + /* Normalize the value to -1...1 */ + float value = (event.getAxisValue(range.getAxis(), actionPointerIndex) - range.getMin()) / range.getRange() * 2.0f - 1.0f; + SDLControllerManager.onNativeJoy(joystick.device_id, i, value); + } + for (int i = 0; i < joystick.hats.size() / 2; i++) { + int hatX = Math.round(event.getAxisValue(joystick.hats.get(2 * i).getAxis(), actionPointerIndex)); + int hatY = Math.round(event.getAxisValue(joystick.hats.get(2 * i + 1).getAxis(), actionPointerIndex)); + SDLControllerManager.onNativeHat(joystick.device_id, i, hatX, hatY); } } } @@ -562,8 +560,6 @@ class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener { switch ( event.getSource() ) { case InputDevice.SOURCE_JOYSTICK: - case InputDevice.SOURCE_GAMEPAD: - case InputDevice.SOURCE_DPAD: return SDLControllerManager.handleJoystickMotionEvent(event); case InputDevice.SOURCE_MOUSE: @@ -693,8 +689,6 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 { switch ( event.getSource() ) { case InputDevice.SOURCE_JOYSTICK: - case InputDevice.SOURCE_GAMEPAD: - case InputDevice.SOURCE_DPAD: return SDLControllerManager.handleJoystickMotionEvent(event); case InputDevice.SOURCE_MOUSE: