diff --git a/android-project/src/org/libsdl/app/SDLActivity.java b/android-project/src/org/libsdl/app/SDLActivity.java index 113b91384..989abb560 100644 --- a/android-project/src/org/libsdl/app/SDLActivity.java +++ b/android-project/src/org/libsdl/app/SDLActivity.java @@ -724,6 +724,21 @@ public class SDLActivity extends Activity { } } + // Check if a given device is considered a possible SDL joystick + public static boolean isDeviceSDLJoystick(int deviceId) { + InputDevice device = InputDevice.getDevice(deviceId); + // We cannot use InputDevice.isVirtual before API 16, so let's accept + // only nonnegative device ids (VIRTUAL_KEYBOARD equals -1) + if ((device == null) || (deviceId < 0)) { + return false; + } + int sources = device.getSources(); + return (((sources & InputDevice.SOURCE_CLASS_JOYSTICK) == InputDevice.SOURCE_CLASS_JOYSTICK) || + ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) || + ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) + ); + } + // APK expansion files support /** com.android.vending.expansion.zipfile.ZipResourceFile object or null. */ @@ -1220,23 +1235,25 @@ class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, @Override public boolean onKey(View v, int keyCode, KeyEvent event) { // Dispatch the different events depending on where they come from - // Some SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD - // So, we try to process them as DPAD or GAMEPAD events first, if that fails we try them as KEYBOARD - - if ( (event.getSource() & InputDevice.SOURCE_GAMEPAD) != 0 || - (event.getSource() & InputDevice.SOURCE_DPAD) != 0 ) { + // Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD + // So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD + // + // Furthermore, it's possible a game controller has SOURCE_KEYBOARD and + // SOURCE_JOYSTICK, while its key events arrive from the keyboard source + // So, retrieve the device itself and check all of its sources + if (SDLActivity.isDeviceSDLJoystick(event.getDeviceId())) { + // Note that we always process a pressed/released button here, as an unopened + // SDL_Joystick's button press should not be processed as a keyboard's key press if (event.getAction() == KeyEvent.ACTION_DOWN) { - if (SDLActivity.onNativePadDown(event.getDeviceId(), keyCode) == 0) { - return true; - } + SDLActivity.onNativePadDown(event.getDeviceId(), keyCode); + return true; } else if (event.getAction() == KeyEvent.ACTION_UP) { - if (SDLActivity.onNativePadUp(event.getDeviceId(), keyCode) == 0) { - return true; - } + SDLActivity.onNativePadUp(event.getDeviceId(), keyCode); + return true; } } - if( (event.getSource() & InputDevice.SOURCE_KEYBOARD) != 0) { + if ((event.getSource() & InputDevice.SOURCE_KEYBOARD) != 0) { if (event.getAction() == KeyEvent.ACTION_DOWN) { //Log.v("SDL", "key down: " + keyCode); SDLActivity.onNativeKeyDown(keyCode); @@ -1586,13 +1603,7 @@ class SDLJoystickHandler_API12 extends SDLJoystickHandler { if (joystick == null) { joystick = new SDLJoystick(); InputDevice joystickDevice = InputDevice.getDevice(deviceIds[i]); - - if ( - (joystickDevice.getSources() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 - || - (joystickDevice.getSources() & InputDevice.SOURCE_CLASS_BUTTON) != 0 - ) - { + if (SDLActivity.isDeviceSDLJoystick(deviceIds[i])) { joystick.device_id = deviceIds[i]; joystick.name = joystickDevice.getName(); joystick.axes = new ArrayList(); @@ -1601,7 +1612,7 @@ class SDLJoystickHandler_API12 extends SDLJoystickHandler { List ranges = joystickDevice.getMotionRanges(); Collections.sort(ranges, new RangeComparator()); for (InputDevice.MotionRange range : ranges ) { - if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 ) { + if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { if (range.getAxis() == MotionEvent.AXIS_HAT_X || range.getAxis() == MotionEvent.AXIS_HAT_Y) { joystick.hats.add(range); @@ -1655,7 +1666,7 @@ class SDLJoystickHandler_API12 extends SDLJoystickHandler { @Override public boolean handleMotionEvent(MotionEvent event) { - if ( (event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) { + if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) { int actionPointerIndex = event.getActionIndex(); int action = event.getActionMasked(); switch(action) {