android-project/app/src/main/java/org/libsdl/app/SDLControllerManager.java
changeset 12334 0789a425e8d7
parent 12332 c80f702e4b8b
child 12354 7846ac86d46e
equal deleted inserted replaced
12333:898f03b00670 12334:0789a425e8d7
     1 package org.libsdl.app;
     1 package org.libsdl.app;
     2 
     2 
     3 import java.lang.reflect.Method;
       
     4 import java.util.ArrayList;
     3 import java.util.ArrayList;
     5 import java.util.Collections;
     4 import java.util.Collections;
     6 import java.util.Comparator;
     5 import java.util.Comparator;
     7 import java.util.List;
     6 import java.util.List;
     8 
     7 
    10 import android.os.*;
     9 import android.os.*;
    11 import android.view.*;
    10 import android.view.*;
    12 import android.util.Log;
    11 import android.util.Log;
    13 
    12 
    14 
    13 
    15 public class SDLControllerManager 
    14 public class SDLControllerManager
    16 {
    15 {
    17 
    16 
    18     public static native int nativeSetupJNI();
    17     public static native int nativeSetupJNI();
    19 
    18 
    20     public static native int nativeAddJoystick(int device_id, String name, String desc,
    19     public static native int nativeAddJoystick(int device_id, String name, String desc,
    51         } else if (Build.VERSION.SDK_INT >= 12) {
    50         } else if (Build.VERSION.SDK_INT >= 12) {
    52             mJoystickHandler = new SDLJoystickHandler_API12();
    51             mJoystickHandler = new SDLJoystickHandler_API12();
    53         } else {
    52         } else {
    54             mJoystickHandler = new SDLJoystickHandler();
    53             mJoystickHandler = new SDLJoystickHandler();
    55         }
    54         }
    56         mHapticHandler = new SDLHapticHandler();
    55 
       
    56         if (Build.VERSION.SDK_INT >= 26) {
       
    57             mHapticHandler = new SDLHapticHandler_API26();
       
    58         } else {
       
    59             mHapticHandler = new SDLHapticHandler();
       
    60         }
    57     }
    61     }
    58 
    62 
    59     // Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
    63     // Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
    60     public static boolean handleJoystickMotionEvent(MotionEvent event) {
    64     public static boolean handleJoystickMotionEvent(MotionEvent event) {
    61         return mJoystickHandler.handleMotionEvent(event);
    65         return mJoystickHandler.handleMotionEvent(event);
   408         }
   412         }
   409         return button_mask;
   413         return button_mask;
   410     }
   414     }
   411 }
   415 }
   412 
   416 
       
   417 class SDLHapticHandler_API26 extends SDLHapticHandler {
       
   418     @Override
       
   419     public void run(int device_id, float intensity, int length) {
       
   420         SDLHaptic haptic = getHaptic(device_id);
       
   421         if (haptic != null) {
       
   422             Log.d("SDL", "Rtest: Vibe with intensity " + intensity + " for " + length);
       
   423             if (intensity == 0.0f) {
       
   424                 stop(device_id);
       
   425                 return;
       
   426             }
       
   427 
       
   428             int vibeValue = Math.round(intensity * 255);
       
   429 
       
   430             if (vibeValue > 255) {
       
   431                 vibeValue = 255;
       
   432             }
       
   433             if (vibeValue < 1) {
       
   434                 stop(device_id);
       
   435                 return;
       
   436             }
       
   437             try {
       
   438                 haptic.vib.vibrate(VibrationEffect.createOneShot(length, vibeValue));
       
   439             }
       
   440             catch (Exception e) {
       
   441                 // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if
       
   442                 // something went horribly wrong with the Android 8.0 APIs.
       
   443                 haptic.vib.vibrate(length);
       
   444             }
       
   445         }
       
   446     }
       
   447 }
       
   448 
   413 class SDLHapticHandler {
   449 class SDLHapticHandler {
   414 
   450 
   415     class SDLHaptic {
   451     class SDLHaptic {
   416         public int device_id;
   452         public int device_id;
   417         public String name;
   453         public String name;
   418         public Vibrator vib;
   454         public Vibrator vib;
   419     }
   455     }
   420 
   456 
   421     private ArrayList<SDLHaptic> mHaptics;
   457     private ArrayList<SDLHaptic> mHaptics;
   422     
   458 
   423     public SDLHapticHandler() {
   459     public SDLHapticHandler() {
   424         mHaptics = new ArrayList<SDLHaptic>();
   460         mHaptics = new ArrayList<SDLHaptic>();
   425     }
   461     }
   426 
   462 
   427     public void run(int device_id, float intensity, int length) {
   463     public void run(int device_id, float intensity, int length) {
   428         SDLHaptic haptic = getHaptic(device_id);
   464         SDLHaptic haptic = getHaptic(device_id);
   429         if (haptic != null) {
   465         if (haptic != null) {
   430 
   466             haptic.vib.vibrate(length);
   431             Log.d("SDL", "Rtest: Vibe with intensity " + intensity + " for " + length);
       
   432             if (intensity == 0.0f) {
       
   433                 stop(device_id);
       
   434                 return;
       
   435             }
       
   436 
       
   437             if (Build.VERSION.SDK_INT >= 26) {
       
   438                 // We have to do this dynamically to avoid issues on earlier SDKs.
       
   439                 // But we want to use the VibrationEffect so we can set amplitude.
       
   440 
       
   441                 try {
       
   442                     int vibeValue = Math.round(intensity * 255);
       
   443 
       
   444                     if (vibeValue > 255) {
       
   445                         vibeValue = 255;
       
   446                     }
       
   447                     if (vibeValue < 1) {
       
   448                         stop(device_id);
       
   449                         return;
       
   450                     }
       
   451 
       
   452                     long longLength = length;
       
   453                     Class vibrationEffectClass = Class.forName("android.os.VibrationEffect");
       
   454                     Method oneShotMethod = vibrationEffectClass.getMethod("createOneShot", long.class, int.class);
       
   455                     Object effect = oneShotMethod.invoke(null, longLength, vibeValue);
       
   456                     Method vibeEffect = android.os.Vibrator.class.getMethod("vibrate", vibrationEffectClass);
       
   457                     vibeEffect.invoke(haptic.vib, vibrationEffectClass.cast(effect));
       
   458                 }
       
   459                 catch (Exception e) {
       
   460                     // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but works even if
       
   461                     // something went horribly wrong with the Android 8.0 APIs.
       
   462                     haptic.vib.vibrate(length);
       
   463                 }
       
   464             }
       
   465             else {
       
   466                 // Fall back to the generic method, which uses DEFAULT_AMPLITUDE, but exists
       
   467                 // on earlier SDKs.
       
   468 
       
   469                 haptic.vib.vibrate (length);
       
   470             }
       
   471         }
   467         }
   472     }
   468     }
   473 
   469 
   474     public void stop(int device_id) {
   470     public void stop(int device_id) {
   475         SDLHaptic haptic = getHaptic(device_id);
   471         SDLHaptic haptic = getHaptic(device_id);
   477             haptic.vib.cancel();
   473             haptic.vib.cancel();
   478         }
   474         }
   479     }
   475     }
   480 
   476 
   481     public void pollHapticDevices() {
   477     public void pollHapticDevices() {
   482         
   478 
   483         final int deviceId_VIBRATOR_SERVICE = 999999;
   479         final int deviceId_VIBRATOR_SERVICE = 999999;
   484         boolean hasVibratorService = false;
   480         boolean hasVibratorService = false;
   485 
   481 
   486         int[] deviceIds = InputDevice.getDeviceIds();
   482         int[] deviceIds = InputDevice.getDeviceIds();
   487         // It helps processing the device ids in reverse order
   483         // It helps processing the device ids in reverse order
   521                 SDLHaptic haptic = getHaptic(deviceId_VIBRATOR_SERVICE);
   517                 SDLHaptic haptic = getHaptic(deviceId_VIBRATOR_SERVICE);
   522                 if (haptic == null) {
   518                 if (haptic == null) {
   523                     haptic = new SDLHaptic();
   519                     haptic = new SDLHaptic();
   524                     haptic.device_id = deviceId_VIBRATOR_SERVICE;
   520                     haptic.device_id = deviceId_VIBRATOR_SERVICE;
   525                     haptic.name = "VIBRATOR_SERVICE";
   521                     haptic.name = "VIBRATOR_SERVICE";
   526                     haptic.vib = vib; 
   522                     haptic.vib = vib;
   527                     mHaptics.add(haptic);
   523                     mHaptics.add(haptic);
   528                     SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
   524                     SDLControllerManager.nativeAddHaptic(haptic.device_id, haptic.name);
   529                 }
   525                 }
   530             }
   526             }
   531         }
   527         }
   563             if (mHaptics.get(i).device_id == device_id) {
   559             if (mHaptics.get(i).device_id == device_id) {
   564                 return mHaptics.get(i);
   560                 return mHaptics.get(i);
   565             }
   561             }
   566         }
   562         }
   567         return null;
   563         return null;
   568     }   
   564     }
   569 }
   565 }
   570 
   566 
   571 class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {
   567 class SDLGenericMotionListener_API12 implements View.OnGenericMotionListener {
   572     // Generic Motion (mouse hover, joystick...) events go here
   568     // Generic Motion (mouse hover, joystick...) events go here
   573     @Override
   569     @Override
   653         switch ( event.getSource() ) {
   649         switch ( event.getSource() ) {
   654             case InputDevice.SOURCE_JOYSTICK:
   650             case InputDevice.SOURCE_JOYSTICK:
   655             case InputDevice.SOURCE_GAMEPAD:
   651             case InputDevice.SOURCE_GAMEPAD:
   656             case InputDevice.SOURCE_DPAD:
   652             case InputDevice.SOURCE_DPAD:
   657                 return SDLControllerManager.handleJoystickMotionEvent(event);
   653                 return SDLControllerManager.handleJoystickMotionEvent(event);
   658                 
   654 
   659             case InputDevice.SOURCE_MOUSE:
   655             case InputDevice.SOURCE_MOUSE:
   660                 if (!SDLActivity.mSeparateMouseAndTouch) {
   656                 if (!SDLActivity.mSeparateMouseAndTouch) {
   661                     break;
   657                     break;
   662                 }
   658                 }
   663                 action = event.getActionMasked();
   659                 action = event.getActionMasked();
   744         switch ( event.getSource() ) {
   740         switch ( event.getSource() ) {
   745             case InputDevice.SOURCE_JOYSTICK:
   741             case InputDevice.SOURCE_JOYSTICK:
   746             case InputDevice.SOURCE_GAMEPAD:
   742             case InputDevice.SOURCE_GAMEPAD:
   747             case InputDevice.SOURCE_DPAD:
   743             case InputDevice.SOURCE_DPAD:
   748                 return SDLControllerManager.handleJoystickMotionEvent(event);
   744                 return SDLControllerManager.handleJoystickMotionEvent(event);
   749                 
   745 
   750             case InputDevice.SOURCE_MOUSE:
   746             case InputDevice.SOURCE_MOUSE:
   751             case 12290: // DeX desktop mouse cursor is a separate non-standard input type.
   747             case 12290: // DeX desktop mouse cursor is a separate non-standard input type.
   752                 if (!SDLActivity.mSeparateMouseAndTouch) {
   748                 if (!SDLActivity.mSeparateMouseAndTouch) {
   753                     break;
   749                     break;
   754                 }
   750                 }
   818         if (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27)) {
   814         if (!SDLActivity.isDeXMode() || (Build.VERSION.SDK_INT >= 27)) {
   819             if (enabled) {
   815             if (enabled) {
   820                 SDLActivity.getContentView().requestPointerCapture();
   816                 SDLActivity.getContentView().requestPointerCapture();
   821             }
   817             }
   822             else {
   818             else {
   823                 SDLActivity.getContentView().releasePointerCapture();            
   819                 SDLActivity.getContentView().releasePointerCapture();
   824             }
   820             }
   825             mRelativeModeEnabled = enabled;
   821             mRelativeModeEnabled = enabled;
   826             return true;
   822             return true;
   827         }
   823         }
   828         else 
   824         else
   829         {
   825         {
   830             return false;
   826             return false;
   831         }
   827         }
   832     }
   828     }
   833 
   829