| package org.libsdl.app; |
| |
| import java.util.ArrayList; |
| import java.util.Collections; |
| import java.util.Comparator; |
| import java.util.List; |
| |
| import android.content.Context; |
| import android.os.*; |
| import android.view.*; |
| import android.util.Log; |
| |
| |
| public class SDLControllerManager |
| { |
| |
| public static native int nativeSetupJNI(); |
| |
| public static native int nativeAddJoystick(int device_id, String name, String desc, |
| int vendor_id, int product_id, |
| boolean is_accelerometer, int button_mask, |
| int naxes, int nhats, int nballs); |
| public static native int nativeRemoveJoystick(int device_id); |
| public static native int nativeAddHaptic(int device_id, String name); |
| public static native int nativeRemoveHaptic(int device_id); |
| public static native int onNativePadDown(int device_id, int keycode); |
| public static native int onNativePadUp(int device_id, int keycode); |
| public static native void onNativeJoy(int device_id, int axis, |
| float value); |
| public static native void onNativeHat(int device_id, int hat_id, |
| int x, int y); |
| |
| protected static SDLJoystickHandler mJoystickHandler; |
| protected static SDLHapticHandler mHapticHandler; |
| |
| private static final String TAG = "SDLControllerManager"; |
| |
| public static void initialize() { |
| if (mJoystickHandler == null) { |
| if (Build.VERSION.SDK_INT >= 19) { |
| mJoystickHandler = new SDLJoystickHandler_API19(); |
| } else { |
| mJoystickHandler = new SDLJoystickHandler_API16(); |
| } |
| } |
| |
| if (mHapticHandler == null) { |
| if (Build.VERSION.SDK_INT >= 26) { |
| mHapticHandler = new SDLHapticHandler_API26(); |
| } else { |
| mHapticHandler = new SDLHapticHandler(); |
| } |
| } |
| } |
| |
| // Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance |
| public static boolean handleJoystickMotionEvent(MotionEvent event) { |
| return mJoystickHandler.handleMotionEvent(event); |
| } |
| |
| /** |
| * This method is called by SDL using JNI. |
| */ |
| public static void pollInputDevices() { |
| mJoystickHandler.pollInputDevices(); |
| } |
| |
| /** |
| * This method is called by SDL using JNI. |
| */ |
| public static void pollHapticDevices() { |
| mHapticHandler.pollHapticDevices(); |
| } |
| |
| /** |
| * This method is called by SDL using JNI. |
| */ |
| public static void hapticRun(int device_id, float intensity, int length) { |
| mHapticHandler.run(device_id, intensity, length); |
| } |
| |
| /** |
| * This method is called by SDL using JNI. |
| */ |
| public static void hapticStop(int device_id) |
| { |
| mHapticHandler.stop(device_id); |
| } |
| |
| // 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(); |
| |
| /* This is called for every button press, so let's not spam the logs */ |
| /** |
| if ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0) { |
| Log.v(TAG, "Input device " + device.getName() + " has class joystick."); |
| } |
| if ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) { |
| Log.v(TAG, "Input device " + device.getName() + " is a dpad."); |
| } |
| if ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) { |
| Log.v(TAG, "Input device " + device.getName() + " is a gamepad."); |
| } |
| **/ |
| |
| return ((sources & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 || |
| ((sources & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD) || |
| ((sources & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD) |
| ); |
| } |
| |
| } |
| |
| class SDLJoystickHandler { |
| |
| /** |
| * Handles given MotionEvent. |
| * @param event the event to be handled. |
| * @return if given event was processed. |
| */ |
| public boolean handleMotionEvent(MotionEvent event) { |
| return false; |
| } |
| |
| /** |
| * Handles adding and removing of input devices. |
| */ |
| public void pollInputDevices() { |
| } |
| } |
| |
| /* Actual joystick functionality available for API >= 12 devices */ |
| class SDLJoystickHandler_API16 extends SDLJoystickHandler { |
| |
| static class SDLJoystick { |
| public int device_id; |
| public String name; |
| public String desc; |
| public ArrayList<InputDevice.MotionRange> axes; |
| public ArrayList<InputDevice.MotionRange> hats; |
| } |
| static class RangeComparator implements Comparator<InputDevice.MotionRange> { |
| @Override |
| public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) { |
| // 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 |
| int arg0Axis = arg0.getAxis(); |
| int arg1Axis = arg1.getAxis(); |
| if (arg0Axis == MotionEvent.AXIS_GAS) { |
| arg0Axis = MotionEvent.AXIS_BRAKE; |
| } else if (arg0Axis == MotionEvent.AXIS_BRAKE) { |
| arg0Axis = MotionEvent.AXIS_GAS; |
| } |
| if (arg1Axis == MotionEvent.AXIS_GAS) { |
| arg1Axis = MotionEvent.AXIS_BRAKE; |
| } else if (arg1Axis == MotionEvent.AXIS_BRAKE) { |
| arg1Axis = MotionEvent.AXIS_GAS; |
| } |
| |
| return arg0Axis - arg1Axis; |
| } |
| } |
| |
| private ArrayList<SDLJoystick> mJoysticks; |
| |
| public SDLJoystickHandler_API16() { |
| |
| mJoysticks = new ArrayList<SDLJoystick>(); |
| } |
| |
| @Override |
| public void pollInputDevices() { |
| int[] deviceIds = InputDevice.getDeviceIds(); |
| for(int i=0; i < deviceIds.length; ++i) { |
| SDLJoystick joystick = getJoystick(deviceIds[i]); |
| if (joystick == null) { |
| joystick = new SDLJoystick(); |
| InputDevice joystickDevice = InputDevice.getDevice(deviceIds[i]); |
| if (SDLControllerManager.isDeviceSDLJoystick(deviceIds[i])) { |
| joystick.device_id = deviceIds[i]; |
| joystick.name = joystickDevice.getName(); |
| joystick.desc = getJoystickDescriptor(joystickDevice); |
| joystick.axes = new ArrayList<InputDevice.MotionRange>(); |
| joystick.hats = new ArrayList<InputDevice.MotionRange>(); |
| |
| List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges(); |
| Collections.sort(ranges, new RangeComparator()); |
| for (InputDevice.MotionRange range : ranges ) { |
| 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); |
| } |
| else { |
| joystick.axes.add(range); |
| } |
| } |
| } |
| |
| mJoysticks.add(joystick); |
| SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc, getVendorId(joystickDevice), getProductId(joystickDevice), false, getButtonMask(joystickDevice), joystick.axes.size(), joystick.hats.size()/2, 0); |
| } |
| } |
| } |
| |
| /* Check removed devices */ |
| ArrayList<Integer> removedDevices = new ArrayList<Integer>(); |
| for(int i=0; i < mJoysticks.size(); i++) { |
| int device_id = mJoysticks.get(i).device_id; |
| int j; |
| for (j=0; j < deviceIds.length; j++) { |
| if (device_id == deviceIds[j]) break; |
| } |
| if (j == deviceIds.length) { |
| removedDevices.add(Integer.valueOf(device_id)); |
| } |
| } |
| |
| for(int i=0; i < removedDevices.size(); i++) { |
| int device_id = removedDevices.get(i).intValue(); |
| SDLControllerManager.nativeRemoveJoystick(device_id); |
| for (int j=0; j < mJoysticks.size(); j++) { |
| if (mJoysticks.get(j).device_id == device_id) { |
| mJoysticks.remove(j); |
| break; |
| } |
| } |
| } |
| } |
| |
| protected SDLJoystick getJoystick(int device_id) { |
| for(int i=0; i < mJoysticks.size(); i++) { |
| if (mJoysticks.get(i).device_id == device_id) { |
| return mJoysticks.get(i); |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean handleMotionEvent(MotionEvent event) { |
| if ((event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) { |
| int actionPointerIndex = event.getActionIndex(); |
| int action = event.getActionMasked(); |
| switch(action) { |
| case 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(); i+=2) { |
| int hatX = Math.round(event.getAxisValue( joystick.hats.get(i).getAxis(), actionPointerIndex ) ); |
| int hatY = Math.round(event.getAxisValue( joystick.hats.get(i+1).getAxis(), actionPointerIndex ) ); |
| SDLControllerManager.onNativeHat(joystick.device_id, i/2, hatX, hatY ); |
| } |
| } |
| break; |
| default: |
| break; |
| } |
| } |
| return true; |
| } |
| |
| public String getJoystickDescriptor(InputDevice joystickDevice) { |
| String desc = joystickDevice.getDescriptor(); |
| |
| if (desc != null && !desc.isEmpty()) { |
| return desc; |
| } |
| |
| return joystickDevice.getName(); |
| } |
| public int getProductId(InputDevice joystickDevice) { |
| return 0; |
| } |
| public int getVendorId(InputDevice joystickDevice) { |
| return 0; |
| } |
| public int getButtonMask(InputDevice joystickDevice) { |
| return -1; |
| } |
| } |
| |
| class SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 { |
| |
| @Override |
| public int getProductId(InputDevice joystickDevice) { |
| return joystickDevice.getProductId(); |
| } |
| |
| @Override |
| public int getVendorId(InputDevice joystickDevice) { |
| return joystickDevice.getVendorId(); |
| } |
| |
| @Override |
| public int getButtonMask(InputDevice joystickDevice) { |
| int button_mask = 0; |
| int[] keys = new int[] { |
| KeyEvent.KEYCODE_BUTTON_A, |
| KeyEvent.KEYCODE_BUTTON_B, |
| KeyEvent.KEYCODE_BUTTON_X, |
| KeyEvent.KEYCODE_BUTTON_Y, |
| KeyEvent.KEYCODE_BACK, |
| KeyEvent.KEYCODE_BUTTON_MODE, |
| KeyEvent.KEYCODE_BUTTON_START, |
| KeyEvent.KEYCODE_BUTTON_THUMBL, |
| KeyEvent.KEYCODE_BUTTON_THUMBR, |
| KeyEvent.KEYCODE_BUTTON_L1, |
| KeyEvent.KEYCODE_BUTTON_R1, |
| KeyEvent.KEYCODE_DPAD_UP, |
| KeyEvent.KEYCODE_DPAD_DOWN, |
| KeyEvent.KEYCODE_DPAD_LEFT, |
| KeyEvent.KEYCODE_DPAD_RIGHT, |
| KeyEvent.KEYCODE_BUTTON_SELECT, |
| KeyEvent.KEYCODE_DPAD_CENTER, |
| |
| // These don't map into any SDL controller buttons directly |
| KeyEvent.KEYCODE_BUTTON_L2, |
| KeyEvent.KEYCODE_BUTTON_R2, |
| KeyEvent.KEYCODE_BUTTON_C, |
| KeyEvent.KEYCODE_BUTTON_Z, |
| KeyEvent.KEYCODE_BUTTON_1, |
| KeyEvent.KEYCODE_BUTTON_2, |
| KeyEvent.KEYCODE_BUTTON_3, |
| KeyEvent.KEYCODE_BUTTON_4, |
| KeyEvent.KEYCODE_BUTTON_5, |
| KeyEvent.KEYCODE_BUTTON_6, |
| KeyEvent.KEYCODE_BUTTON_7, |
| KeyEvent.KEYCODE_BUTTON_8, |
| KeyEvent.KEYCODE_BUTTON_9, |
| KeyEvent.KEYCODE_BUTTON_10, |
| KeyEvent.KEYCODE_BUTTON_11, |
| KeyEvent.KEYCODE_BUTTON_12, |
| KeyEvent.KEYCODE_BUTTON_13, |
| KeyEvent.KEYCODE_BUTTON_14, |
| KeyEvent.KEYCODE_BUTTON_15, |
| KeyEvent.KEYCODE_BUTTON_16, |
| }; |
| int[] masks = new int[] { |
| (1 << 0), // A -> A |
| (1 << 1), // B -> B |
| (1 << 2), // X -> X |
| (1 << 3), // Y -> Y |
| (1 << 4), // BACK -> BACK |
| (1 << 5), // MODE -> GUIDE |
| (1 << 6), // START -> START |
| (1 << 7), // THUMBL -> LEFTSTICK |
| (1 << 8), // THUMBR -> RIGHTSTICK |
| (1 << 9), // L1 -> LEFTSHOULDER |
| (1 << 10), // R1 -> RIGHTSHOULDER |
| (1 << 11), // DPAD_UP -> DPAD_UP |
| (1 << 12), // DPAD_DOWN -> DPAD_DOWN |
| (1 << 13), // DPAD_LEFT -> DPAD_LEFT |
| (1 << 14), // DPAD_RIGHT -> DPAD_RIGHT |
| (1 << 4), // SELECT -> BACK |
| (1 << 0), // DPAD_CENTER -> A |
| (1 << 15), // L2 -> ?? |
| (1 << 16), // R2 -> ?? |
| (1 << 17), // C -> ?? |
| (1 << 18), // Z -> ?? |
| (1 << 20), // 1 -> ?? |
| (1 << 21), // 2 -> ?? |
| (1 << 22), // 3 -> ?? |
| (1 << 23), // 4 -> ?? |
| (1 << 24), // 5 -> ?? |
| (1 << 25), // 6 -> ?? |
| (1 << 26), // 7 -> ?? |
| (1 << 27), // 8 -> ?? |
| (1 << 28), // 9 -> ?? |
| (1 << 29), // 10 -> ?? |
| (1 << 30), // 11 -> ?? |
| (1 << 31), // 12 -> ?? |
| // We're out of room... |
| 0xFFFFFFFF, // 13 -> ?? |
| 0xFFFFFFFF, // 14 -> ?? |
| 0xFFFFFFFF, // 15 -> ?? |
| 0xFFFFFFFF, // 16 -> ?? |
| }; |
| boolean[] has_keys = joystickDevice.hasKeys(keys); |
| for (int i = 0; i < keys.length; ++i) { |
| if (has_keys[i]) { |
| button_mask |= masks[i]; |
| } |
| } |
| return button_mask; |
| } |
| } |
| |
| class SDLHapticHandler_API26 extends SDLHapticHandler { |
| @Override |
| public void run(int device_id, float intensity, int length) { |
| SDLHaptic haptic = getHaptic(device_id); |
| if (haptic != null) { |
| Log.d("SDL", "Rtest: Vibe with intensity " + intensity + " for " + length); |
| if (intensity == 0.0f) { |
| stop(device_id); |
| return; |
| } |
| |
| int vibeValue = Math.round(intensity * 255); |
| |
| if (vibeValue > 255) { |
| vibeValue = 255; |
| } |
| if (vibeValue < 1) { |
| stop(device_id); |
| return; |
| } |
| try { |
| haptic.vib.vibrate(VibrationEffect.createOneShot(length, vibeValue)); |
| } |
| catch (Exception e) { |
| // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if |
| // something went horribly wrong with the Android 8.0 APIs. |
| haptic.vib.vibrate(length); |
| } |
| } |
| } |
| } |
| |
| class SDLHapticHandler { |
| |
| class SDLHaptic { |
| public int device_id; |
| public String name; |
| public Vibrator vib; |
| } |
| |
| private ArrayList<SDLHaptic> mHaptics; |
| |
| public SDLHapticHandler() { |
| mHaptics = new ArrayList<SDLHaptic>(); |
| } |
| |
| public void run(int device_id, float intensity, int length) { |
| SDLHaptic haptic = getHaptic(device_id); |
| if (haptic != null) { |
| haptic.vib.vibrate(length); |
| } |
| } |
| |
| public void stop(int device_id) { |
| SDLHaptic haptic = getHaptic(device_id); |
| if (haptic != null) { |
| haptic.vib.cancel(); |
| } |
| } |
| |
| public void pollHapticDevices() { |
| |
| final int deviceId_VIBRATOR_SERVICE = 999999; |
| boolean hasVibratorService = false; |
| |
| int[] deviceIds = InputDevice.getDeviceIds(); |
| // It helps processing the device ids in reverse order |
| // For example, in the case of the XBox 360 wireless dongle, |
| // so the first controller seen by SDL matches what the receiver |
| // considers to be the first controller |
| |
| for (int i = deviceIds.length - 1; i > -1; i--) { |
| SDLHaptic haptic = getHaptic(deviceIds[i]); |
| if (haptic == null) { |
| InputDevice device = InputDevice.getDevice(deviceIds[i]); |
| Vibrator vib = device.getVibrator(); |
| if (vib.hasVibrator()) { |
| haptic = new SDLHaptic(); |
| haptic.device_id = deviceIds[i]; |
| haptic.name = device.getName(); |
| haptic.vib = vib; |
| mHaptics.add(haptic); |
| SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name); |
| } |
| } |
| } |
| |
| /* Check VIBRATOR_SERVICE */ |
| Vibrator vib = (Vibrator) SDL.getContext().getSystemService(Context.VIBRATOR_SERVICE); |
| if (vib != null) { |
| hasVibratorService = vib.hasVibrator(); |
| |
| if (hasVibratorService) { |
| SDLHaptic haptic = getHaptic(deviceId_VIBRATOR_SERVICE); |
| if (haptic == null) { |
| haptic = new SDLHaptic(); |
| haptic.device_id = deviceId_VIBRATOR_SERVICE; |
| haptic.name = "VIBRATOR_SERVICE"; |
| haptic.vib = vib; |
| mHaptics.add(haptic); |
| SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name); |
| } |
| } |
| } |
| |
| /* Check removed devices */ |
| ArrayList<Integer> removedDevices = new ArrayList<Integer>(); |
| for(int i=0; i < mHaptics.size(); i++) { |
| int device_id = mHaptics.get(i).device_id; |
| int j; |
| for (j=0; j < deviceIds.length; j++) { |
| if (device_id == deviceIds[j]) break; |
| } |
| |
| if (device_id == deviceId_VIBRATOR_SERVICE && hasVibratorService) { |
| // don't remove the vibrator if it is still present |
| } else if (j == deviceIds.length) { |
| removedDevices.add(device_id); |
| } |
| } |
| |
| for(int i=0; i < removedDevices.size(); i++) { |
| int device_id = removedDevices.get(i); |
| SDLControllerManager.nativeRemoveHaptic(device_id); |
| for (int j=0; j < mHaptics.size(); j++) { |
| if (mHaptics.get(j).device_id == device_id) { |
| mHaptics.remove(j); |
| break; |
| } |
| } |
| } |
| } |
| |
| protected SDLHaptic getHaptic(int device_id) { |
| for(int i=0; i < mHaptics.size(); i++) { |
| if (mHaptics.get(i).device_id == device_id) { |
| return mHaptics.get(i); |
| } |
| } |
| return null; |
| } |
| } |
| |
| class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener { |
| // Generic Motion (mouse hover, joystick...) events go here |
| @Override |
| public boolean onGenericMotion(View v, MotionEvent event) { |
| float x, y; |
| int action; |
| |
| switch ( event.getSource() ) { |
| case InputDevice.SOURCE_JOYSTICK: |
| case InputDevice.SOURCE_GAMEPAD: |
| case InputDevice.SOURCE_DPAD: |
| return SDLControllerManager.handleJoystickMotionEvent(event); |
| |
| case InputDevice.SOURCE_MOUSE: |
| if (!SDLActivity.mSeparateMouseAndTouch) { |
| break; |
| } |
| action = event.getActionMasked(); |
| switch (action) { |
| case MotionEvent.ACTION_SCROLL: |
| x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0); |
| y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0); |
| SDLActivity.onNativeMouse(0, action, x, y, false); |
| return true; |
| |
| case MotionEvent.ACTION_HOVER_MOVE: |
| x = event.getX(0); |
| y = event.getY(0); |
| |
| SDLActivity.onNativeMouse(0, action, x, y, false); |
| return true; |
| |
| default: |
| break; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| // Event was not managed |
| return false; |
| } |
| |
| public boolean supportsRelativeMouse() { |
| return false; |
| } |
| |
| public boolean inRelativeMode() { |
| return false; |
| } |
| |
| public boolean setRelativeMouseEnabled(boolean enabled) { |
| return false; |
| } |
| |
| public void reclaimRelativeMouseModeIfNeeded() |
| { |
| |
| } |
| |
| public float getEventX(MotionEvent event) { |
| return event.getX(0); |
| } |
| |
| public float getEventY(MotionEvent event) { |
| return event.getY(0); |
| } |
| |
| } |
| |
| class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API12 { |
| // Generic Motion (mouse hover, joystick...) events go here |
| |
| private boolean mRelativeModeEnabled; |
| |
| @Override |
| public boolean onGenericMotion(View v, MotionEvent event) { |
| |
| // Handle relative mouse mode |
| if (mRelativeModeEnabled) { |
| if (event.getSource() == InputDevice.SOURCE_MOUSE) { |
| if (SDLActivity.mSeparateMouseAndTouch) { |
| int action = event.getActionMasked(); |
| if (action == MotionEvent.ACTION_HOVER_MOVE) { |
| float x = event.getAxisValue(MotionEvent.AXIS_RELATIVE_X); |
| float y = event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y); |
| SDLActivity.onNativeMouse(0, action, x, y, true); |
| return true; |
| } |
| } |
| } |
| } |
| |
| // Event was not managed, call SDLGenericMotionListener_API12 method |
| return super.onGenericMotion(v, event); |
| } |
| |
| @Override |
| public boolean supportsRelativeMouse() { |
| return true; |
| } |
| |
| @Override |
| public boolean inRelativeMode() { |
| return mRelativeModeEnabled; |
| } |
| |
| @Override |
| public boolean setRelativeMouseEnabled(boolean enabled) { |
| mRelativeModeEnabled = enabled; |
| return true; |
| } |
| |
| @Override |
| public float getEventX(MotionEvent event) { |
| if (mRelativeModeEnabled) { |
| return event.getAxisValue(MotionEvent.AXIS_RELATIVE_X); |
| } |
| else { |
| return event.getX(0); |
| } |
| } |
| |
| @Override |
| public float getEventY(MotionEvent event) { |
| if (mRelativeModeEnabled) { |
| return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y); |
| } |
| else { |
| return event.getY(0); |
| } |
| } |
| } |
| |
| |
| class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 { |
| // Generic Motion (mouse hover, joystick...) events go here |
| private boolean mRelativeModeEnabled; |
| |
| @Override |
| public boolean onGenericMotion(View v, MotionEvent event) { |
| float x, y; |
| int action; |
| |
| switch ( event.getSource() ) { |
| case InputDevice.SOURCE_JOYSTICK: |
| case InputDevice.SOURCE_GAMEPAD: |
| case InputDevice.SOURCE_DPAD: |
| return SDLControllerManager.handleJoystickMotionEvent(event); |
| |
| case InputDevice.SOURCE_MOUSE: |
| // DeX desktop mouse cursor is a separate non-standard input type. |
| case InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN: |
| if (!SDLActivity.mSeparateMouseAndTouch) { |
| break; |
| } |
| |
| action = event.getActionMasked(); |
| switch (action) { |
| case MotionEvent.ACTION_SCROLL: |
| x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0); |
| y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0); |
| SDLActivity.onNativeMouse(0, action, x, y, false); |
| return true; |
| |
| case MotionEvent.ACTION_HOVER_MOVE: |
| x = event.getX(0); |
| y = event.getY(0); |
| SDLActivity.onNativeMouse(0, action, x, y, false); |
| return true; |
| |
| default: |
| break; |
| } |
| break; |
| |
| case InputDevice.SOURCE_MOUSE_RELATIVE: |
| if (!SDLActivity.mSeparateMouseAndTouch) { |
| break; |
| } |
| action = event.getActionMasked(); |
| switch (action) { |
| case MotionEvent.ACTION_SCROLL: |
| x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0); |
| y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0); |
| SDLActivity.onNativeMouse(0, action, x, y, false); |
| return true; |
| |
| case MotionEvent.ACTION_HOVER_MOVE: |
| x = event.getX(0); |
| y = event.getY(0); |
| SDLActivity.onNativeMouse(0, action, x, y, true); |
| return true; |
| |
| default: |
| break; |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| // Event was not managed |
| return false; |
| } |
| |
| @Override |
| public boolean supportsRelativeMouse() { |
| return (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27)); |
| } |
| |
| @Override |
| public boolean inRelativeMode() { |
| return mRelativeModeEnabled; |
| } |
| |
| @Override |
| public boolean setRelativeMouseEnabled(boolean enabled) { |
| if (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27)) { |
| if (enabled) { |
| SDLActivity.getContentView().requestPointerCapture(); |
| } |
| else { |
| SDLActivity.getContentView().releasePointerCapture(); |
| } |
| mRelativeModeEnabled = enabled; |
| return true; |
| } |
| else |
| { |
| return false; |
| } |
| } |
| |
| @Override |
| public void reclaimRelativeMouseModeIfNeeded() |
| { |
| if (mRelativeModeEnabled && !SDLActivity.isDeXMode()) { |
| SDLActivity.getContentView().requestPointerCapture(); |
| } |
| } |
| |
| @Override |
| public float getEventX(MotionEvent event) { |
| // Relative mouse in capture mode will only have relative for X/Y |
| return event.getX(0); |
| } |
| |
| @Override |
| public float getEventY(MotionEvent event) { |
| // Relative mouse in capture mode will only have relative for X/Y |
| return event.getY(0); |
| } |
| } |