Advertisement
Guest User

Untitled

a guest
Aug 26th, 2015
59
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 52.02 KB | None | 0 0
  1. import android.annotation.TargetApi;
  2. import android.app.Activity;
  3. import android.content.Context;
  4. import android.graphics.Canvas;
  5. import android.graphics.PixelFormat;
  6. import android.hardware.Sensor;
  7. import android.hardware.SensorEvent;
  8. import android.hardware.SensorEventListener;
  9. import android.hardware.SensorManager;
  10. import android.media.AudioFormat;
  11. import android.media.AudioManager;
  12. import android.media.AudioTrack;
  13. import android.os.Build;
  14. import android.os.Handler;
  15. import android.os.Message;
  16. import android.service.wallpaper.WallpaperService;
  17. import android.util.Log;
  18. import android.view.Display;
  19. import android.view.InputDevice;
  20. import android.view.KeyEvent;
  21. import android.view.MotionEvent;
  22. import android.view.Surface;
  23. import android.view.SurfaceHolder;
  24. import android.view.SurfaceView;
  25. import android.view.View;
  26. import android.view.View.OnGenericMotionListener;
  27. import android.view.Window;
  28. import android.view.WindowManager;
  29. import android.view.inputmethod.BaseInputConnection;
  30. import android.view.inputmethod.EditorInfo;
  31. import android.view.inputmethod.InputConnection;
  32.  
  33. import java.io.IOException;
  34. import java.io.InputStream;
  35. import java.lang.reflect.Method;
  36. import java.util.ArrayList;
  37. import java.util.Arrays;
  38. import java.util.Collections;
  39. import java.util.Comparator;
  40. import java.util.List;
  41.  
  42.  
  43. public class SDLActivity extends WallpaperService
  44. {
  45.     private String TAG = "bb ----------- SDL Wallpaper Activity --------------";
  46.  
  47.     // Keep track of the paused state
  48.     public static boolean mIsPaused, mIsSurfaceReady, mHasFocus;
  49.     public static boolean mExitCalledFromJava;
  50.  
  51.     /** If shared libraries (e.g. SDL or the native application) could not be loaded. */
  52.     public static boolean mBrokenLibraries;
  53.  
  54.     // If we want to separate mouse and touch events.
  55.     //  This is only toggled in native code when a hint is set!
  56.     public static boolean mSeparateMouseAndTouch;
  57.  
  58.     // Main components
  59.     protected static SDLActivity mSingleton;
  60.     protected static SDLSurface mSurface;
  61.     protected static SDLJoystickHandler mJoystickHandler;
  62.  
  63.     // This is what SDL runs in. It invokes SDL_main(), eventually
  64.     protected static Thread mSDLThread;
  65.  
  66.     // Audio
  67.     protected static AudioTrack mAudioTrack;
  68.  
  69.  
  70.     protected String[] getLibraries()
  71.     {
  72.         return new String[] {
  73.                 "SDL2",
  74.                 // "SDL2_image",
  75.                 // "SDL2_mixer",
  76.                 // "SDL2_net",
  77.                 // "SDL2_ttf",
  78.                 "main"
  79.         };
  80.     }
  81.  
  82.     // Load the .so
  83.     public void loadLibraries()
  84.     {
  85.         for (String lib : getLibraries())
  86.         {
  87.             System.loadLibrary(lib);
  88.         }
  89.     }
  90.  
  91.     /**
  92.      * This method is called by SDL before starting the native application thread.
  93.      * It can be overridden to provide the arguments after the application name.
  94.      * The default implementation returns an empty array. It never returns null.
  95.      * @return arguments for the native application.
  96.      */
  97.     protected String[] getArguments()
  98.     {
  99.         //
  100.         //
  101.         return new String[0];
  102.     }
  103.  
  104.     public static void initialize()
  105.     {
  106.         // The static nature of the singleton and Android quirkyness force us to initialize everything here
  107.         // Otherwise, when exiting the app and returning to it, these variables *keep* their pre exit values
  108.         mSingleton = null;
  109.         mSurface = null;
  110.         mJoystickHandler = null;
  111.         mSDLThread = null;
  112.         mAudioTrack = null;
  113.         mExitCalledFromJava = false;
  114.         mBrokenLibraries = false;
  115.         mIsPaused = false;
  116.         mIsSurfaceReady = false;
  117.         mHasFocus = true;
  118.     }
  119.  
  120.     @Override
  121.     public void onCreate()
  122.     {
  123.         //
  124.         Log.d(TAG, "-----------SDLEngine onCreate----------");
  125.         super.onCreate();
  126.         create();
  127.     }
  128.  
  129.     // Setup
  130.     public void create()
  131.     {
  132.             Log.v(TAG, "Device: " + android.os.Build.DEVICE);
  133.             Log.v(TAG, "Model: " + android.os.Build.MODEL);
  134.             Log.v(TAG, "1st onCreate(): " + mSingleton);
  135.  
  136.             SDLActivity.initialize();
  137.             // So we can call stuff from static callbacks
  138.             mSingleton = this;
  139.             Log.v(TAG, "2nd onCreate(): " + mSingleton);
  140.  
  141.             // Load shared libraries
  142.             String errorMsgBrokenLib = "";
  143.             try {
  144.                 loadLibraries();
  145.             } catch(UnsatisfiedLinkError e) {
  146.                 System.err.println(e.getMessage());
  147.                 mBrokenLibraries = true;
  148.                 errorMsgBrokenLib = e.getMessage();
  149.             } catch(Exception e) {
  150.                 System.err.println(e.getMessage());
  151.                 mBrokenLibraries = true;
  152.                 errorMsgBrokenLib = e.getMessage();
  153.             }
  154.  
  155.             if (mBrokenLibraries)
  156.             {
  157.                 Log.e(TAG, "failed to load .so " + errorMsgBrokenLib);
  158.                 return;
  159.             }
  160.  
  161.             // Set up the surface
  162.             mSurface = new SDLSurface(getApplication());
  163.  
  164.             if(Build.VERSION.SDK_INT >= 12) {
  165.                 mJoystickHandler = new SDLJoystickHandler_API12();
  166.             }
  167.             else {
  168.                 mJoystickHandler = new SDLJoystickHandler();
  169.             }
  170.         }
  171.  
  172.  
  173. //    //---------------------------- beginina
  174. //
  175. //    public class SDLActivityqa extends Activity
  176. //    {
  177. //
  178. //        @Override
  179. //        public boolean dispatchKeyEvent(KeyEvent event)
  180. //        {
  181. //
  182. //            if (SDLActivity.mBrokenLibraries) {
  183. //                return false;
  184. //            }
  185. //
  186. //            int keyCode = event.getKeyCode();
  187. //            // Ignore certain special keys so they're handled by Android
  188. //            if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
  189. //                    keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
  190. //                    keyCode == KeyEvent.KEYCODE_CAMERA ||
  191. //                    keyCode == 168 || /* API 11: KeyEvent.KEYCODE_ZOOM_IN */
  192. //                    keyCode == 169 /* API 11: KeyEvent.KEYCODE_ZOOM_OUT */
  193. //                    ) {
  194. //                return false;
  195. //            }
  196. //            return super.dispatchKeyEvent(event);
  197. //        }
  198. //
  199. //
  200. //    }
  201. //
  202. //    //---------------------------- begininb
  203.  
  204.  
  205.     /** Called by onPause or surfaceDestroyed. Even if surfaceDestroyed
  206.      *  is the first to be called, mIsSurfaceReady should still be set
  207.      *  to 'true' during the call to onPause (in a usual scenario).
  208.      */
  209.     public static void handlePause()
  210.     {
  211.         if (!SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady)
  212.         {
  213.             SDLActivity.mIsPaused = true;
  214.             SDLActivity.nativePause();
  215.             mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, false);
  216.         }
  217.     }
  218.  
  219.     /** Called by onResume or surfaceCreated. An actual resume should be done only when the surface is ready.
  220.      * Note: Some Android variants may send multiple surfaceChanged events, so we don't need to resume
  221.      * every time we get one of those events, only if it comes after surfaceDestroyed
  222.      */
  223.     public static void handleResume()
  224.     {
  225.         if (SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady && SDLActivity.mHasFocus)
  226.         {
  227.             SDLActivity.mIsPaused = false;
  228.             SDLActivity.nativeResume();
  229.             mSurface.handleResume();
  230.         }
  231.     }
  232.  
  233.     /* The native thread has finished */
  234.     public static void handleNativeExit()
  235.     {
  236.         //
  237.         SDLActivity.mSDLThread = null;
  238.         //mSingleton.finish();
  239.     }
  240.  
  241.  
  242.     // Messages from the SDLMain thread
  243.     static final int COMMAND_CHANGE_TITLE = 1;
  244.     static final int COMMAND_UNUSED = 2;
  245.     static final int COMMAND_TEXTEDIT_HIDE = 3;
  246.     static final int COMMAND_SET_KEEP_SCREEN_ON = 5;
  247.  
  248.     protected static final int COMMAND_USER = 0x8000;
  249.  
  250.     /**
  251.      * This method is called by SDL if SDL did not handle a message itself.
  252.      * This happens if a received message contains an unsupported command.
  253.      * Method can be overwritten to handle Messages in a different class.
  254.      * @param command the command of the message.
  255.      * @param param the parameter of the message. May be null.
  256.      * @return if the message was handled in overridden method.
  257.      */
  258.     protected boolean onUnhandledMessage(int command, Object param)
  259.     {
  260.         //
  261.         //
  262.         return false;
  263.     }
  264.  
  265.     /**
  266.      * A Handler class for Messages from native SDL applications.
  267.      * It uses current Activities as target (e.g. for the title).
  268.      * static to prevent implicit references to enclosing object.
  269.      */
  270.     protected static class SDLCommandHandler extends Handler
  271.     {
  272.         private String TAG = "bb ---- SDLCommandHandler ----";
  273.         //
  274.         @Override
  275.         public void handleMessage(Message msg)
  276.         {
  277.             Context context = getContext();
  278.             if (context == null) {
  279.                 Log.e(TAG, "error handling message, getContext() returned null");
  280.                 return;
  281.             }
  282.             switch (msg.arg1) {
  283.                 case COMMAND_CHANGE_TITLE:
  284.                     if (context instanceof Activity) {
  285.                         ((Activity) context).setTitle((String)msg.obj);
  286.                     } else {
  287.                         Log.e(TAG, "error handling message, getContext() returned no Activity");
  288.                     }
  289.                     break;
  290.                 case COMMAND_SET_KEEP_SCREEN_ON:
  291.                 {
  292.                     Window window = ((Activity) context).getWindow();
  293.                     if (window != null) {
  294.                         if ((msg.obj instanceof Integer) && (((Integer) msg.obj).intValue() != 0)) {
  295.                             window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  296.                         } else {
  297.                             window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
  298.                         }
  299.                     }
  300.                     break;
  301.                 }
  302.                 default:
  303.                     if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) {
  304.                         Log.e(TAG, "error handling message, command is " + msg.arg1);
  305.                     }
  306.             }
  307.         }
  308.     }
  309.  
  310.     // Handler for the messages
  311.     Handler commandHandler = new SDLCommandHandler();
  312.  
  313.     // Send a message from the SDLMain thread
  314.     boolean sendCommand(int command, Object data)
  315.     {
  316.         Message msg = commandHandler.obtainMessage();
  317.         msg.arg1 = command;
  318.         msg.obj = data;
  319.         return commandHandler.sendMessage(msg);
  320.     }
  321.  
  322.     // C functions we call
  323.     public static native int nativeInit(Object arguments);
  324.     public static native void nativeLowMemory();
  325.     public static native void nativeQuit();
  326.     public static native void nativePause();
  327.     public static native void nativeResume();
  328.     public static native void onNativeDropFile(String filename);
  329.     public static native void onNativeResize(int x, int y, int format, float rate);
  330.     public static native int onNativePadDown(int device_id, int keycode);
  331.     public static native int onNativePadUp(int device_id, int keycode);
  332.     public static native void onNativeJoy(int device_id, int axis, float value);
  333.     public static native void onNativeHat(int device_id, int hat_id, int x, int y);
  334.     public static native void onNativeKeyDown(int keycode);
  335.     public static native void onNativeKeyUp(int keycode);
  336.     public static native void onNativeKeyboardFocusLost();
  337.     public static native void onNativeMouse(int button, int action, float x, float y);
  338.     public static native void onNativeTouch(int touchDevId, int pointerFingerId, int action, float x, float y, float p);
  339.     public static native void onNativeAccel(float x, float y, float z);
  340.     public static native void onNativeSurfaceChanged();
  341.     public static native void onNativeSurfaceDestroyed();
  342.     public static native void nativeFlipBuffers();
  343.     public static native int nativeAddJoystick(int device_id, String name, int is_accelerometer, int nbuttons, int naxes, int nhats, int nballs);
  344.     public static native int nativeRemoveJoystick(int device_id);
  345.     public static native String nativeGetHint(String name);
  346.  
  347.     /**
  348.      * This method is called by SDL using JNI.
  349.      */
  350.     public static void flipBuffers()
  351.     {
  352.         //
  353.         //
  354.         SDLActivity.nativeFlipBuffers();
  355.     }
  356.  
  357.     /**
  358.      * This method is called by SDL using JNI.
  359.      */
  360.     public static boolean setActivityTitle(String title)
  361.     {
  362.         //
  363.         // Called from SDLMain() thread and can't directly affect the view
  364.         return mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);
  365.     }
  366.  
  367.     /**
  368.      * This method is called by SDL using JNI.
  369.      */
  370.     public static boolean sendMessage(int command, int param)
  371.     {
  372.         //
  373.         //
  374.         return mSingleton.sendCommand(command, Integer.valueOf(param));
  375.     }
  376.  
  377.     /**
  378.      * This method is called by SDL using JNI.
  379.      */
  380.     public static Context getContext()
  381.     {
  382.         //
  383.         //
  384.         return mSingleton;
  385.     }
  386.  
  387.     /**
  388.      * This method is called by SDL using JNI.
  389.      * @return result of getSystemService(name) but executed on UI thread.
  390.      */
  391.     public Object getSystemServiceFromUiThread(final String name)
  392.     {
  393.         //
  394.         return getSystemService(name);
  395.     }
  396.  
  397.     /**
  398.      * This method is called by SDL using JNI.
  399.      */
  400.     public static Surface getNativeSurface()
  401.     {
  402.         //
  403.         //
  404.         return SDLActivity.mSurface.getNativeSurface();
  405.     }
  406.  
  407.     // Audio
  408.     /**
  409.      * This method is called by SDL using JNI.
  410.      */
  411.     public static int audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames)
  412.     {
  413.         String TAG = "bb ---- audioInit ----";
  414.         int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
  415.         int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
  416.         int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
  417.  
  418.         Log.v(TAG, "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + (sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
  419.  
  420.         // Let the user pick a larger buffer if they really want -- but ye
  421.         // gods they probably shouldn't, the minimums are horrifyingly high
  422.         // latency already
  423.         desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
  424.  
  425.         if (mAudioTrack == null) {
  426.             mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
  427.                     channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
  428.  
  429.             // Instantiating AudioTrack can "succeed" without an exception and the track may still be invalid
  430.             // Ref: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/AudioTrack.java
  431.             // Ref: http://developer.android.com/reference/android/media/AudioTrack.html#getState()
  432.  
  433.             if (mAudioTrack.getState() != AudioTrack.STATE_INITIALIZED) {
  434.                 Log.e(TAG, "Failed during initialization of Audio Track");
  435.                 mAudioTrack = null;
  436.                 return -1;
  437.             }
  438.  
  439.             mAudioTrack.play();
  440.         }
  441.  
  442.         Log.v(TAG, "SDL audio: got " + ((mAudioTrack.getChannelCount() >= 2) ? "stereo" : "mono") + " " + ((mAudioTrack.getAudioFormat() == AudioFormat.ENCODING_PCM_16BIT) ? "16-bit" : "8-bit") + " " + (mAudioTrack.getSampleRate() / 1000f) + "kHz, " + desiredFrames + " frames buffer");
  443.  
  444.         return 0;
  445.     }
  446.  
  447.     /**
  448.      * This method is called by SDL using JNI.
  449.      */
  450.     public static void audioWriteShortBuffer(short[] buffer)
  451.     {
  452.         String TAG = "bb ---- audioWriteShortBuffer ----";
  453.         for (int i = 0; i < buffer.length; ) {
  454.             int result = mAudioTrack.write(buffer, i, buffer.length - i);
  455.             if (result > 0) {
  456.                 i += result;
  457.             } else if (result == 0) {
  458.                 try {
  459.                     Thread.sleep(1);
  460.                 } catch(InterruptedException e) {
  461.                     // Nom nom
  462.                 }
  463.             } else {
  464.                 Log.w(TAG, "SDL audio: error return from write(short)");
  465.                 return;
  466.             }
  467.         }
  468.     }
  469.  
  470.     /**
  471.      * This method is called by SDL using JNI.
  472.      */
  473.     public static void audioWriteByteBuffer(byte[] buffer)
  474.     {
  475.         String TAG = "bb ---- audioWriteByteBuffer ----";
  476.         for (int i = 0; i < buffer.length; ) {
  477.             int result = mAudioTrack.write(buffer, i, buffer.length - i);
  478.             if (result > 0) {
  479.                 i += result;
  480.             } else if (result == 0) {
  481.                 try {
  482.                     Thread.sleep(1);
  483.                 } catch(InterruptedException e) {
  484.                     // Nom nom
  485.                 }
  486.             } else {
  487.                 Log.w(TAG, "SDL audio: error return from write(byte)");
  488.                 return;
  489.             }
  490.         }
  491.     }
  492.  
  493.     /**
  494.      * This method is called by SDL using JNI.
  495.      */
  496.     public static void audioQuit()
  497.     {
  498.         if (mAudioTrack != null) {
  499.             mAudioTrack.stop();
  500.             mAudioTrack = null;
  501.         }
  502.     }
  503.  
  504.     // Input
  505.  
  506.     /**
  507.      * This method is called by SDL using JNI.
  508.      * @return an array which may be empty but is never null.
  509.      */
  510.     public static int[] inputGetInputDeviceIds(int sources)
  511.     {
  512.         int[] ids = InputDevice.getDeviceIds();
  513.         int[] filtered = new int[ids.length];
  514.         int used = 0;
  515.         for (int i = 0; i < ids.length; ++i) {
  516.             InputDevice device = InputDevice.getDevice(ids[i]);
  517.             if ((device != null) && ((device.getSources() & sources) != 0)) {
  518.                 filtered[used++] = device.getId();
  519.             }
  520.         }
  521.         return Arrays.copyOf(filtered, used);
  522.     }
  523.  
  524.     // Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
  525.     public static boolean handleJoystickMotionEvent(MotionEvent event)
  526.     {
  527.         //
  528.         return mJoystickHandler.handleMotionEvent(event);
  529.     }
  530.  
  531.     /**
  532.      * This method is called by SDL using JNI.
  533.      */
  534.     public static void pollInputDevices()
  535.     {
  536.         if (SDLActivity.mSDLThread != null)
  537.         {
  538.             mJoystickHandler.pollInputDevices();
  539.         }
  540.     }
  541.  
  542.     // APK extension files support
  543.  
  544.     /** com.android.vending.expansion.zipfile.ZipResourceFile object or null. */
  545.     private Object expansionFile;
  546.  
  547.     /** com.android.vending.expansion.zipfile.ZipResourceFile's getInputStream() or null. */
  548.     private Method expansionFileMethod;
  549.  
  550.     /**
  551.      * This method is called by SDL using JNI.
  552.      */
  553.     public InputStream openAPKExtensionInputStream(String fileName) throws IOException
  554.     {
  555.         // Get a ZipResourceFile representing a merger of both the main and patch files
  556.         if (expansionFile == null) {
  557.             Integer mainVersion = Integer.valueOf(nativeGetHint("SDL_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION"));
  558.             Integer patchVersion = Integer.valueOf(nativeGetHint("SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION"));
  559.  
  560.             try {
  561.                 // To avoid direct dependency on Google APK extension library that is
  562.                 // not a part of Android SDK we access it using reflection
  563.                 expansionFile = Class.forName("com.android.vending.expansion.zipfile.APKExpansionSupport")
  564.                         .getMethod("getAPKExpansionZipFile", Context.class, int.class, int.class)
  565.                         .invoke(null, this, mainVersion, patchVersion);
  566.  
  567.                 expansionFileMethod = expansionFile.getClass()
  568.                         .getMethod("getInputStream", String.class);
  569.             } catch (Exception ex) {
  570.                 ex.printStackTrace();
  571.                 expansionFile = null;
  572.                 expansionFileMethod = null;
  573.             }
  574.         }
  575.  
  576.         // Get an input stream for a known file inside the expansion file ZIPs
  577.         InputStream fileStream;
  578.         try {
  579.             fileStream = (InputStream)expansionFileMethod.invoke(expansionFile, fileName);
  580.         } catch (Exception ex) {
  581.             ex.printStackTrace();
  582.             fileStream = null;
  583.         }
  584.  
  585.         if (fileStream == null) {
  586.             throw new IOException();
  587.         }
  588.  
  589.         return fileStream;
  590.     }
  591.  
  592.  
  593.  
  594.     @Override
  595.     public void onDestroy()
  596.     {
  597.         //
  598.         Log.d(TAG, "onDestroy()");
  599.         super.onDestroy();
  600.     }
  601.  
  602.  
  603.     @Override
  604.     public Engine onCreateEngine()
  605.     {
  606.         //
  607.         Log.d(TAG, "onCreateEngine()");
  608.         SDLEngine mEngine;
  609.         //return new SDLEngine(this, getApplicationContext());
  610.  
  611.         if (mSurface != null)
  612.         {
  613.             Log.v(TAG, "Waiting for SDL thread");
  614.             if (SDLActivity.mSDLThread != null)
  615.             {
  616.                 SDLActivity.nativeQuit();
  617.                 try
  618.                 {
  619.                     SDLActivity.mSDLThread.join();
  620.                 }
  621.                 catch(Exception e)
  622.                 {
  623.                     Log.v(TAG, "Problem stopping thread: " + e);
  624.                 }
  625.             }
  626.             Log.v(TAG, "SDL thread finished");
  627.         }
  628.         Log.v(TAG, "Creating SDL Engine");
  629.         mEngine = new SDLEngine(this, getApplicationContext());
  630.         return mEngine;
  631.     }
  632.  
  633.     class SDLEngine extends Engine
  634.     {
  635.         private String TAG = "bb ----- SDLEngine -----";
  636.  
  637.         public SDLEngine(SDLActivity atv, Context ctx)
  638.         {
  639.             //
  640.             Log.d(TAG, "constructor");
  641.         }
  642.  
  643.         @Override
  644.         public void onSurfaceChanged(SurfaceHolder holder, int format, int width, int height)
  645.         {
  646.             //
  647.             Log.d(TAG, "pre onSurfaceChanged()");
  648.             mSurface.surfaceChanged(holder, format, width, height);
  649.             Log.d(TAG, "post onSurfaceChanged()");
  650.         }
  651.  
  652.         @Override
  653.         public void onVisibilityChanged(boolean visible)
  654.         {
  655.             //
  656.             Log.d(TAG, "onVisibilityChanged()" + visible);
  657.             if (visible)
  658.             {
  659.                 //resume
  660.                 Log.v(TAG, "onPause()");
  661.                 if (SDLActivity.mBrokenLibraries)
  662.                 {
  663.                     return;
  664.                 }
  665.                 SDLActivity.handleResume();
  666.             }
  667.             else
  668.             {
  669.                 //pause
  670.                 Log.v(TAG, "onPause()");
  671.                 if (SDLActivity.mBrokenLibraries)
  672.                 {
  673.                     return;
  674.                 }
  675.                 SDLActivity.handlePause();
  676.             }
  677.         }
  678.  
  679.         @Override
  680.         public void onDestroy()
  681.         {
  682.             Log.v(TAG, "onDestroy()");
  683.  
  684.             if (SDLActivity.mBrokenLibraries)
  685.             {
  686.                 super.onDestroy();
  687.                 // Reset everything in case the user re opens the app
  688.                 SDLActivity.initialize();
  689.                 return;
  690.             }
  691.  
  692.             // Send a quit message to the application
  693.             SDLActivity.mExitCalledFromJava = true;
  694.             SDLActivity.nativeQuit();
  695.  
  696.             // Now wait for the SDL thread to quit
  697.             if (SDLActivity.mSDLThread != null)
  698.             {
  699.                 try
  700.                 {
  701.                     SDLActivity.mSDLThread.join();
  702.                 }
  703.                 catch(Exception e)
  704.                 {
  705.                     Log.v(TAG, "Problem stopping thread: " + e);
  706.                 }
  707.                 SDLActivity.mSDLThread = null;
  708.                 Log.v(TAG, "Finished waiting for SDL thread");
  709.             }
  710.  
  711.             super.onDestroy();
  712.             Log.v(TAG, "Reset everything in case the user re opens the app");
  713.             SDLActivity.initialize();
  714.         }
  715.     }
  716. }
  717.     /* This is a fake invisible editor view that receives the input and defines the
  718.  * pan&scan region
  719.  */
  720.  
  721.  
  722. class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, View.OnKeyListener, View.OnTouchListener, SensorEventListener
  723. {
  724.     String TAG = "bb ---- SDLSurface ----";
  725.     // Sensors
  726.     protected static SensorManager mSensorManager;
  727.     protected static Display mDisplay;
  728.  
  729.     // Keep track of the surface size to normalize touch events
  730.     protected static float mWidth, mHeight;
  731.  
  732.     // Startup
  733.     public SDLSurface(Context context) {
  734.         super(context);
  735.         getHolder().addCallback(this);
  736.  
  737.         setFocusable(true);
  738.         setFocusableInTouchMode(true);
  739.         requestFocus();
  740.         setOnKeyListener(this);
  741.         setOnTouchListener(this);
  742.  
  743.         mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
  744.         mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
  745.  
  746.         if(Build.VERSION.SDK_INT >= 12) {
  747.             setOnGenericMotionListener(new SDLGenericMotionListener_API12());
  748.         }
  749.  
  750.         // Some arbitrary defaults to avoid a potential division by zero
  751.         mWidth = 1.0f;
  752.         mHeight = 1.0f;
  753.     }
  754.  
  755.     public void handleResume() {
  756.         setFocusable(true);
  757.         setFocusableInTouchMode(true);
  758.         requestFocus();
  759.         setOnKeyListener(this);
  760.         setOnTouchListener(this);
  761.         enableSensor(Sensor.TYPE_ACCELEROMETER, true);
  762.     }
  763.  
  764.     public Surface getNativeSurface() {
  765.         return getHolder().getSurface();
  766.     }
  767.  
  768.     // Called when we have a valid drawing surface
  769.     @Override
  770.     public void surfaceCreated(SurfaceHolder holder) {
  771.         Log.v(TAG, "surfaceCreated()");
  772.         holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
  773.     }
  774.  
  775.     // Called when we lose the surface
  776.     @Override
  777.     public void surfaceDestroyed(SurfaceHolder holder) {
  778.         Log.v(TAG, "surfaceDestroyed()");
  779.         // Call this *before* setting mIsSurfaceReady to 'false'
  780.         SDLActivity.handlePause();
  781.         SDLActivity.mIsSurfaceReady = false;
  782.         SDLActivity.onNativeSurfaceDestroyed();
  783.     }
  784.  
  785.     // Called when the surface is resized
  786.     @Override
  787.     public void surfaceChanged(SurfaceHolder holder,
  788.                                int format, int width, int height) {
  789.         Log.v(TAG, "surfaceChanged()");
  790.  
  791.         int sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565 by default
  792.         switch (format) {
  793.             case PixelFormat.A_8:
  794.                 Log.v(TAG, "pixel format A_8");
  795.                 break;
  796.             case PixelFormat.LA_88:
  797.                 Log.v(TAG, "pixel format LA_88");
  798.                 break;
  799.             case PixelFormat.L_8:
  800.                 Log.v(TAG, "pixel format L_8");
  801.                 break;
  802.             case PixelFormat.RGBA_4444:
  803.                 Log.v(TAG, "pixel format RGBA_4444");
  804.                 sdlFormat = 0x15421002; // SDL_PIXELFORMAT_RGBA4444
  805.                 break;
  806.             case PixelFormat.RGBA_5551:
  807.                 Log.v(TAG, "pixel format RGBA_5551");
  808.                 sdlFormat = 0x15441002; // SDL_PIXELFORMAT_RGBA5551
  809.                 break;
  810.             case PixelFormat.RGBA_8888:
  811.                 Log.v(TAG, "pixel format RGBA_8888");
  812.                 sdlFormat = 0x16462004; // SDL_PIXELFORMAT_RGBA8888
  813.                 break;
  814.             case PixelFormat.RGBX_8888:
  815.                 Log.v(TAG, "pixel format RGBX_8888");
  816.                 sdlFormat = 0x16261804; // SDL_PIXELFORMAT_RGBX8888
  817.                 break;
  818.             case PixelFormat.RGB_332:
  819.                 Log.v(TAG, "pixel format RGB_332");
  820.                 sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
  821.                 break;
  822.             case PixelFormat.RGB_565:
  823.                 Log.v(TAG, "pixel format RGB_565");
  824.                 sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565
  825.                 break;
  826.             case PixelFormat.RGB_888:
  827.                 Log.v(TAG, "pixel format RGB_888");
  828.                 // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
  829.                 sdlFormat = 0x16161804; // SDL_PIXELFORMAT_RGB888
  830.                 break;
  831.             default:
  832.                 Log.v(TAG, "pixel format unknown " + format);
  833.                 break;
  834.         }
  835.  
  836.         mWidth = width;
  837.         mHeight = height;
  838.         SDLActivity.onNativeResize(width, height, sdlFormat, mDisplay.getRefreshRate());
  839.         Log.v(TAG, "Window size: " + width + "x" + height);
  840.  
  841.  
  842.         // Set mIsSurfaceReady to 'true' *before* making a call to handleResume
  843.         SDLActivity.mIsSurfaceReady = true;
  844.         SDLActivity.onNativeSurfaceChanged();
  845.         Log.v(TAG, "SDLActivity.mIsSurfaceReady: " + SDLActivity.mIsSurfaceReady);
  846.  
  847.         if (SDLActivity.mSDLThread == null)
  848.         {
  849.             Log.v(TAG, "This is the entry point to the C app. mDSLThread is null");
  850.             // This is the entry point to the C app.
  851.             // Start up the C app thread and enable sensor input for the first time
  852.  
  853.             final Thread sdlThread = new Thread(new SDLMain(), "SDLThread");
  854.             enableSensor(Sensor.TYPE_ACCELEROMETER, true);
  855.             sdlThread.start();
  856.  
  857.             // Set up a listener thread to catch when the native thread ends
  858.             SDLActivity.mSDLThread = new Thread(new Runnable(){
  859.                 @Override
  860.                 public void run()
  861.                 {
  862.                     try
  863.                     {
  864.                         Log.v(TAG, "mSDLThread run try block");
  865.                         sdlThread.join();
  866.                     }
  867.                     catch(Exception e)
  868.                     {
  869.                         Log.v(TAG, " SDL thread exception: "+e.getMessage());
  870.                     }
  871.                     finally
  872.                     {
  873.                         // Native thread has finished
  874.                         Log.v(TAG, "Native thread has finished");
  875.                         if (!SDLActivity.mExitCalledFromJava)
  876.                         {
  877.                             Log.v(TAG, "handle native exit? " + !SDLActivity.mExitCalledFromJava);
  878.                             SDLActivity.handleNativeExit();
  879.                         }
  880.                     }
  881.                 }
  882.             }, "SDLThreadListener");
  883.             Log.v(TAG, "pre thread start");
  884.             SDLActivity.mSDLThread.start();
  885.             Log.v(TAG, "post thread start");
  886.         }
  887.  
  888.         if (SDLActivity.mHasFocus)
  889.         {
  890.             Log.v(TAG, "SDLActivity mHasFocus " + SDLActivity.mHasFocus);
  891.             SDLActivity.handleResume();
  892.         }
  893.     }
  894.  
  895.     // unused
  896.     @Override
  897.     public void onDraw(Canvas canvas) {}
  898.  
  899.  
  900.     // Key events
  901.     @Override
  902.     public boolean onKey(View  v, int keyCode, KeyEvent event) {
  903.         // Dispatch the different events depending on where they come from
  904.         // Some SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
  905.         // So, we try to process them as DPAD or GAMEPAD events first, if that fails we try them as KEYBOARD
  906.  
  907.         if ( (event.getSource() & InputDevice.SOURCE_GAMEPAD) != 0 ||
  908.                 (event.getSource() & InputDevice.SOURCE_DPAD) != 0 ) {
  909.             if (event.getAction() == KeyEvent.ACTION_DOWN) {
  910.                 if (SDLActivity.onNativePadDown(event.getDeviceId(), keyCode) == 0) {
  911.                     return true;
  912.                 }
  913.             } else if (event.getAction() == KeyEvent.ACTION_UP) {
  914.                 if (SDLActivity.onNativePadUp(event.getDeviceId(), keyCode) == 0) {
  915.                     return true;
  916.                 }
  917.             }
  918.         }
  919.  
  920.         if( (event.getSource() & InputDevice.SOURCE_KEYBOARD) != 0) {
  921.             if (event.getAction() == KeyEvent.ACTION_DOWN) {
  922.                 //Log.v(TAG, "key down: " + keyCode);
  923.                 SDLActivity.onNativeKeyDown(keyCode);
  924.                 return true;
  925.             }
  926.             else if (event.getAction() == KeyEvent.ACTION_UP) {
  927.                 //Log.v(TAG, "key up: " + keyCode);
  928.                 SDLActivity.onNativeKeyUp(keyCode);
  929.                 return true;
  930.             }
  931.         }
  932.  
  933.         return false;
  934.     }
  935.  
  936.     // Touch events
  937.     @Override
  938.     public boolean onTouch(View v, MotionEvent event) {
  939.         /* Ref: http://developer.android.com/training/gestures/multi.html */
  940.         final int touchDevId = event.getDeviceId();
  941.         final int pointerCount = event.getPointerCount();
  942.         int action = event.getActionMasked();
  943.         int pointerFingerId;
  944.         int mouseButton;
  945.         int i = -1;
  946.         float x,y,p;
  947.  
  948.         // !!! FIXME: dump this SDK check after 2.0.4 ships and require API14.
  949.         if (event.getSource() == InputDevice.SOURCE_MOUSE && SDLActivity.mSeparateMouseAndTouch) {
  950.             if (Build.VERSION.SDK_INT < 14) {
  951.                 mouseButton = 1;    // For Android==12 all mouse buttons are the left button
  952.             } else {
  953.                 try {
  954.                     mouseButton = (Integer) event.getClass().getMethod("getButtonState").invoke(event);
  955.                 } catch(Exception e) {
  956.                     mouseButton = 1;    // oh well.
  957.                 }
  958.             }
  959.             SDLActivity.onNativeMouse(mouseButton, action, event.getX(0), event.getY(0));
  960.         } else {
  961.             switch(action) {
  962.                 case MotionEvent.ACTION_MOVE:
  963.                     for (i = 0; i < pointerCount; i++) {
  964.                         pointerFingerId = event.getPointerId(i);
  965.                         x = event.getX(i) / mWidth;
  966.                         y = event.getY(i) / mHeight;
  967.                         p = event.getPressure(i);
  968.                         if (p > 1.0f) {
  969.                             // may be larger than 1.0f on some devices
  970.                             // see the documentation of getPressure(i)
  971.                             p = 1.0f;
  972.                         }
  973.                         SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
  974.                     }
  975.                     break;
  976.  
  977.                 case MotionEvent.ACTION_UP:
  978.                 case MotionEvent.ACTION_DOWN:
  979.                     // Primary pointer up/down, the index is always zero
  980.                     i = 0;
  981.                 case MotionEvent.ACTION_POINTER_UP:
  982.                 case MotionEvent.ACTION_POINTER_DOWN:
  983.                     // Non primary pointer up/down
  984.                     if (i == -1) {
  985.                         i = event.getActionIndex();
  986.                     }
  987.  
  988.                     pointerFingerId = event.getPointerId(i);
  989.                     x = event.getX(i) / mWidth;
  990.                     y = event.getY(i) / mHeight;
  991.                     p = event.getPressure(i);
  992.                     if (p > 1.0f) {
  993.                         // may be larger than 1.0f on some devices
  994.                         // see the documentation of getPressure(i)
  995.                         p = 1.0f;
  996.                     }
  997.                     SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
  998.                     break;
  999.  
  1000.                 case MotionEvent.ACTION_CANCEL:
  1001.                     for (i = 0; i < pointerCount; i++) {
  1002.                         pointerFingerId = event.getPointerId(i);
  1003.                         x = event.getX(i) / mWidth;
  1004.                         y = event.getY(i) / mHeight;
  1005.                         p = event.getPressure(i);
  1006.                         if (p > 1.0f) {
  1007.                             // may be larger than 1.0f on some devices
  1008.                             // see the documentation of getPressure(i)
  1009.                             p = 1.0f;
  1010.                         }
  1011.                         SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
  1012.                     }
  1013.                     break;
  1014.  
  1015.                 default:
  1016.                     break;
  1017.             }
  1018.         }
  1019.  
  1020.         return true;
  1021.     }
  1022.  
  1023.     // Sensor events
  1024.     public void enableSensor(int sensortype, boolean enabled) {
  1025.         // TODO: This uses getDefaultSensor - what if we have >1 accels?
  1026.         if (enabled) {
  1027.             mSensorManager.registerListener(this,
  1028.                     mSensorManager.getDefaultSensor(sensortype),
  1029.                     SensorManager.SENSOR_DELAY_GAME, null);
  1030.         } else {
  1031.             mSensorManager.unregisterListener(this,
  1032.                     mSensorManager.getDefaultSensor(sensortype));
  1033.         }
  1034.     }
  1035.  
  1036.     @Override
  1037.     public void onAccuracyChanged(Sensor sensor, int accuracy) {
  1038.         // TODO
  1039.     }
  1040.  
  1041.     @Override
  1042.     public void onSensorChanged(SensorEvent event) {
  1043.         if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
  1044.             float x, y;
  1045.             switch (mDisplay.getRotation()) {
  1046.                 case Surface.ROTATION_90:
  1047.                     x = -event.values[1];
  1048.                     y = event.values[0];
  1049.                     break;
  1050.                 case Surface.ROTATION_270:
  1051.                     x = event.values[1];
  1052.                     y = -event.values[0];
  1053.                     break;
  1054.                 case Surface.ROTATION_180:
  1055.                     x = -event.values[1];
  1056.                     y = -event.values[0];
  1057.                     break;
  1058.                 default:
  1059.                     x = event.values[0];
  1060.                     y = event.values[1];
  1061.                     break;
  1062.             }
  1063.             SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
  1064.                     y / SensorManager.GRAVITY_EARTH,
  1065.                     event.values[2] / SensorManager.GRAVITY_EARTH - 1);
  1066.         }
  1067.     }
  1068. }
  1069.  
  1070. /* This is a fake invisible editor view that receives the input and defines the
  1071.  * pan&scan region
  1072.  */
  1073. class DummyEdit extends View implements View.OnKeyListener
  1074. {
  1075.     InputConnection ic;
  1076.  
  1077.     public DummyEdit(Context context) {
  1078.         super(context);
  1079.         setFocusableInTouchMode(true);
  1080.         setFocusable(true);
  1081.         setOnKeyListener(this);
  1082.     }
  1083.  
  1084.     @Override
  1085.     public boolean onCheckIsTextEditor() {
  1086.         return true;
  1087.     }
  1088.  
  1089.     @Override
  1090.     public boolean onKey(View v, int keyCode, KeyEvent event) {
  1091.  
  1092.         // This handles the hardware keyboard input
  1093.         if (event.isPrintingKey()) {
  1094.             if (event.getAction() == KeyEvent.ACTION_DOWN) {
  1095.                 ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
  1096.             }
  1097.             return true;
  1098.         }
  1099.  
  1100.         if (event.getAction() == KeyEvent.ACTION_DOWN) {
  1101.             SDLActivity.onNativeKeyDown(keyCode);
  1102.             return true;
  1103.         } else if (event.getAction() == KeyEvent.ACTION_UP) {
  1104.             SDLActivity.onNativeKeyUp(keyCode);
  1105.             return true;
  1106.         }
  1107.  
  1108.         return false;
  1109.     }
  1110.  
  1111.     @Override
  1112.     public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
  1113.         ic = new SDLInputConnection(this, true);
  1114.  
  1115.         outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
  1116.                 | 33554432 /* API 11: EditorInfo.IME_FLAG_NO_FULLSCREEN */;
  1117.  
  1118.         return ic;
  1119.     }
  1120. }
  1121.  
  1122. class SDLInputConnection extends BaseInputConnection
  1123. {
  1124.  
  1125.     public SDLInputConnection(View targetView, boolean fullEditor) {
  1126.         super(targetView, fullEditor);
  1127.  
  1128.     }
  1129.  
  1130.     @Override
  1131.     public boolean sendKeyEvent(KeyEvent event) {
  1132.  
  1133.         /*
  1134.          * This handles the keycodes from soft keyboard (and IME-translated
  1135.          * input from hardkeyboard)
  1136.          */
  1137.         int keyCode = event.getKeyCode();
  1138.         if (event.getAction() == KeyEvent.ACTION_DOWN) {
  1139.             if (event.isPrintingKey()) {
  1140.                 commitText(String.valueOf((char) event.getUnicodeChar()), 1);
  1141.             }
  1142.             SDLActivity.onNativeKeyDown(keyCode);
  1143.             return true;
  1144.         } else if (event.getAction() == KeyEvent.ACTION_UP) {
  1145.  
  1146.             SDLActivity.onNativeKeyUp(keyCode);
  1147.             return true;
  1148.         }
  1149.         return super.sendKeyEvent(event);
  1150.     }
  1151.  
  1152.     @Override
  1153.     public boolean commitText(CharSequence text, int newCursorPosition) {
  1154.  
  1155.         nativeCommitText(text.toString(), newCursorPosition);
  1156.  
  1157.         return super.commitText(text, newCursorPosition);
  1158.     }
  1159.  
  1160.     @Override
  1161.     public boolean setComposingText(CharSequence text, int newCursorPosition) {
  1162.  
  1163.         nativeSetComposingText(text.toString(), newCursorPosition);
  1164.  
  1165.         return super.setComposingText(text, newCursorPosition);
  1166.     }
  1167.  
  1168.     public native void nativeCommitText(String text, int newCursorPosition);
  1169.  
  1170.     public native void nativeSetComposingText(String text, int newCursorPosition);
  1171.  
  1172.     @Override
  1173.     public boolean deleteSurroundingText(int beforeLength, int afterLength) {
  1174.         // Workaround to capture backspace key. Ref: http://stackoverflow.com/questions/14560344/android-backspace-in-webview-baseinputconnection
  1175.         if (beforeLength == 1 && afterLength == 0) {
  1176.             // backspace
  1177.             return super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL))
  1178.                     && super.sendKeyEvent(new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL));
  1179.         }
  1180.  
  1181.         return super.deleteSurroundingText(beforeLength, afterLength);
  1182.     }
  1183. }
  1184.  
  1185. /* A null joystick handler for API level < 12 devices (the accelerometer is handled separately) */
  1186. class SDLJoystickHandler
  1187. {
  1188.  
  1189.     /**
  1190.      * Handles given MotionEvent.
  1191.      * @param event the event to be handled.
  1192.      * @return if given event was processed.
  1193.      */
  1194.     public boolean handleMotionEvent(MotionEvent event) {
  1195.         return false;
  1196.     }
  1197.  
  1198.     /**
  1199.      * Handles adding and removing of input devices.
  1200.      */
  1201.     public void pollInputDevices() {
  1202.     }
  1203. }
  1204.  
  1205. /* Actual joystick functionality available for API >= 12 devices */
  1206. class SDLJoystickHandler_API12 extends SDLJoystickHandler
  1207. {
  1208.  
  1209.     static class SDLJoystick {
  1210.         public int device_id;
  1211.         public String name;
  1212.         public ArrayList<InputDevice.MotionRange> axes;
  1213.         public ArrayList<InputDevice.MotionRange> hats;
  1214.     }
  1215.     static class RangeComparator implements Comparator<InputDevice.MotionRange> {
  1216.         @Override
  1217.         public int compare(InputDevice.MotionRange arg0, InputDevice.MotionRange arg1) {
  1218.             return arg0.getAxis() - arg1.getAxis();
  1219.         }
  1220.     }
  1221.  
  1222.     private ArrayList<SDLJoystick> mJoysticks;
  1223.  
  1224.     public SDLJoystickHandler_API12() {
  1225.  
  1226.         mJoysticks = new ArrayList<SDLJoystick>();
  1227.     }
  1228.  
  1229.     @Override
  1230.     public void pollInputDevices() {
  1231.         int[] deviceIds = InputDevice.getDeviceIds();
  1232.         // It helps processing the device ids in reverse order
  1233.         // For example, in the case of the XBox 360 wireless dongle,
  1234.         // so the first controller seen by SDL matches what the receiver
  1235.         // considers to be the first controller
  1236.  
  1237.         for(int i=deviceIds.length-1; i>-1; i--) {
  1238.             SDLJoystick joystick = getJoystick(deviceIds[i]);
  1239.             if (joystick == null) {
  1240.                 joystick = new SDLJoystick();
  1241.                 InputDevice joystickDevice = InputDevice.getDevice(deviceIds[i]);
  1242.  
  1243.                 if (
  1244.                         (joystickDevice.getSources() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0
  1245.                                 ||
  1246.                                 (joystickDevice.getSources() & InputDevice.SOURCE_CLASS_BUTTON) != 0
  1247.                         )
  1248.                 {
  1249.                     joystick.device_id = deviceIds[i];
  1250.                     joystick.name = joystickDevice.getName();
  1251.                     joystick.axes = new ArrayList<InputDevice.MotionRange>();
  1252.                     joystick.hats = new ArrayList<InputDevice.MotionRange>();
  1253.  
  1254.                     List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
  1255.                     Collections.sort(ranges, new RangeComparator());
  1256.                     for (InputDevice.MotionRange range : ranges ) {
  1257.                         if ((range.getSource() & InputDevice.SOURCE_CLASS_JOYSTICK) != 0 ) {
  1258.                             if (range.getAxis() == MotionEvent.AXIS_HAT_X ||
  1259.                                     range.getAxis() == MotionEvent.AXIS_HAT_Y) {
  1260.                                 joystick.hats.add(range);
  1261.                             }
  1262.                             else {
  1263.                                 joystick.axes.add(range);
  1264.                             }
  1265.                         }
  1266.                     }
  1267.  
  1268.                     mJoysticks.add(joystick);
  1269.                     SDLActivity.nativeAddJoystick(joystick.device_id, joystick.name, 0, -1,
  1270.                             joystick.axes.size(), joystick.hats.size()/2, 0);
  1271.                 }
  1272.             }
  1273.         }
  1274.  
  1275.         /* Check removed devices */
  1276.         ArrayList<Integer> removedDevices = new ArrayList<Integer>();
  1277.         for(int i=0; i < mJoysticks.size(); i++) {
  1278.             int device_id = mJoysticks.get(i).device_id;
  1279.             int j;
  1280.             for (j=0; j < deviceIds.length; j++) {
  1281.                 if (device_id == deviceIds[j]) break;
  1282.             }
  1283.             if (j == deviceIds.length) {
  1284.                 removedDevices.add(Integer.valueOf(device_id));
  1285.             }
  1286.         }
  1287.  
  1288.         for(int i=0; i < removedDevices.size(); i++) {
  1289.             int device_id = removedDevices.get(i).intValue();
  1290.             SDLActivity.nativeRemoveJoystick(device_id);
  1291.             for (int j=0; j < mJoysticks.size(); j++) {
  1292.                 if (mJoysticks.get(j).device_id == device_id) {
  1293.                     mJoysticks.remove(j);
  1294.                     break;
  1295.                 }
  1296.             }
  1297.         }
  1298.     }
  1299.  
  1300.     protected SDLJoystick getJoystick(int device_id) {
  1301.         for(int i=0; i < mJoysticks.size(); i++) {
  1302.             if (mJoysticks.get(i).device_id == device_id) {
  1303.                 return mJoysticks.get(i);
  1304.             }
  1305.         }
  1306.         return null;
  1307.     }
  1308.  
  1309.     @Override
  1310.     public boolean handleMotionEvent(MotionEvent event) {
  1311.         if ( (event.getSource() & InputDevice.SOURCE_JOYSTICK) != 0) {
  1312.             int actionPointerIndex = event.getActionIndex();
  1313.             int action = event.getActionMasked();
  1314.             switch(action) {
  1315.                 case MotionEvent.ACTION_MOVE:
  1316.                     SDLJoystick joystick = getJoystick(event.getDeviceId());
  1317.                     if ( joystick != null ) {
  1318.                         for (int i = 0; i < joystick.axes.size(); i++) {
  1319.                             InputDevice.MotionRange range = joystick.axes.get(i);
  1320.                             /* Normalize the value to -1...1 */
  1321.                             float value = ( event.getAxisValue( range.getAxis(), actionPointerIndex) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
  1322.                             SDLActivity.onNativeJoy(joystick.device_id, i, value );
  1323.                         }
  1324.                         for (int i = 0; i < joystick.hats.size(); i+=2) {
  1325.                             int hatX = Math.round(event.getAxisValue( joystick.hats.get(i).getAxis(), actionPointerIndex ) );
  1326.                             int hatY = Math.round(event.getAxisValue( joystick.hats.get(i+1).getAxis(), actionPointerIndex ) );
  1327.                             SDLActivity.onNativeHat(joystick.device_id, i/2, hatX, hatY );
  1328.                         }
  1329.                     }
  1330.                     break;
  1331.                 default:
  1332.                     break;
  1333.             }
  1334.         }
  1335.         return true;
  1336.     }
  1337. }
  1338.  
  1339. @TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
  1340. class SDLGenericMotionListener_API12 implements OnGenericMotionListener
  1341. {
  1342.     // Generic Motion (mouse hover, joystick...) events go here
  1343.     @Override
  1344.     public boolean onGenericMotion(View v, MotionEvent event) {
  1345.         float x, y;
  1346.         int mouseButton;
  1347.         int action;
  1348.  
  1349.         switch ( event.getSource() ) {
  1350.             case InputDevice.SOURCE_JOYSTICK:
  1351.             case InputDevice.SOURCE_GAMEPAD:
  1352.             case InputDevice.SOURCE_DPAD:
  1353.                 SDLActivity.handleJoystickMotionEvent(event);
  1354.                 return true;
  1355.  
  1356.             case InputDevice.SOURCE_MOUSE:
  1357.                 action = event.getActionMasked();
  1358.                 switch (action) {
  1359.                     case MotionEvent.ACTION_SCROLL:
  1360.                         x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
  1361.                         y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
  1362.                         SDLActivity.onNativeMouse(0, action, x, y);
  1363.                         return true;
  1364.  
  1365.                     case MotionEvent.ACTION_HOVER_MOVE:
  1366.                         x = event.getX(0);
  1367.                         y = event.getY(0);
  1368.  
  1369.                         SDLActivity.onNativeMouse(0, action, x, y);
  1370.                         return true;
  1371.  
  1372.                     default:
  1373.                         break;
  1374.                 }
  1375.  
  1376.             default:
  1377.                 break;
  1378.         }
  1379.  
  1380.         // Event was not managed
  1381.         return false;
  1382.     }
  1383. }
  1384.  
  1385. class SDLMain implements Runnable
  1386. {
  1387.     @Override
  1388.     public void run()
  1389.     {
  1390.         Log.v("bb -----------SDL Main -----------", "pre SDL thread");
  1391.         SDLActivity.nativeInit(SDLActivity.mSingleton.getArguments());
  1392.         Log.v("bb -----------SDL Main -----------", "post SDL thread");
  1393.     }
  1394. }
  1395.  
  1396.  
  1397. ======================
  1398. logcat output
  1399.  
  1400. D/bb ----- SDLEngine -----(21706): constructor
  1401. D/bb ----- SDLEngine -----(21706): pre onSurfaceChanged()
  1402. V/bb ---- SDLSurface ----(21706): surfaceChanged()
  1403. V/bb ---- SDLSurface ----(21706): pixel format RGBX_8888
  1404. V/bb ---- SDLSurface ----(21706): Window size: 720x1280
  1405. V/bb ---- SDLSurface ----(21706): SDLActivity.mIsSurfaceReady: true
  1406. V/bb ---- SDLSurface ----(21706): This is the entry point to the C app. mDSLThread is null
  1407. V/bb -----------SDL Main -----------(21706): pre SDL thread
  1408. V/bb ---- SDLSurface ----(21706): pre thread start
  1409. V/bb ---- SDLSurface ----(21706): post thread start
  1410. V/bb ---- SDLSurface ----(21706): SDLActivity mHasFocus true
  1411. D/bb ----- SDLEngine -----(21706): post onSurfaceChanged()
  1412. D/bb ----- SDLEngine -----(21706): onVisibilityChanged()true
  1413. V/bb ----- SDLEngine -----(21706): onPause()
  1414. D/bb ----- SDLEngine -----(21706): onVisibilityChanged()false
  1415. V/bb ----- SDLEngine -----(21706): onPause()
  1416. V/bb ---- SDLSurface ----(21706): mSDLThread run try block
  1417. D/bb ----- SDLEngine -----(21706): onVisibilityChanged()true
  1418. V/bb ----- SDLEngine -----(21706): onPause()
  1419. V/bb -----------SDL Main -----------(21706): post SDL thread
  1420. V/bb ---- SDLSurface ----(21706): Native thread has finished
  1421. V/bb ---- SDLSurface ----(21706): handle native exit? true
  1422. D/bb ----------- SDL Wallpaper Activity --------------(21778): -----------SDLEngine onCreate----------
  1423. D/bb ----------- SDL Wallpaper Activity --------------(21778): onCreateEngine()
  1424. V/bb ----------- SDL Wallpaper Activity --------------(21778): Creating SDL Engine
  1425. V/bb ----------- SDL Wallpaper Activity --------------(21778): Device: m0
  1426. V/bb ----------- SDL Wallpaper Activity --------------(21778): Model: GT-I9300
  1427. V/bb ----------- SDL Wallpaper Activity --------------(21778): 1st onCreate(): null
  1428. V/bb ----------- SDL Wallpaper Activity --------------(21778): 2nd onCreate(): org.libsdl.app.SDLActivity@426b8a90
  1429. D/bb ----- SDLEngine -----(21778): constructor
  1430. D/bb ----- SDLEngine -----(21778): pre onSurfaceChanged()
  1431. V/bb ---- SDLSurface ----(21778): surfaceChanged()
  1432. V/bb ---- SDLSurface ----(21778): pixel format RGBX_8888
  1433. V/bb ---- SDLSurface ----(21778): Window size: 720x1280
  1434. V/bb ---- SDLSurface ----(21778): SDLActivity.mIsSurfaceReady: true
  1435. V/bb ---- SDLSurface ----(21778): This is the entry point to the C app. mDSLThread is null
  1436. V/bb -----------SDL Main -----------(21778): pre SDL thread
  1437. V/bb ---- SDLSurface ----(21778): pre thread start
  1438. V/bb ---- SDLSurface ----(21778): post thread start
  1439. V/bb ---- SDLSurface ----(21778): mSDLThread run try block
  1440. V/bb ---- SDLSurface ----(21778): SDLActivity mHasFocus true
  1441. D/bb ----- SDLEngine -----(21778): post onSurfaceChanged()
  1442. D/bb ----- SDLEngine -----(21778): onVisibilityChanged()true
  1443. V/bb ----- SDLEngine -----(21778): onPause()
  1444. D/bb ----- SDLEngine -----(21778): onVisibilityChanged()false
  1445. V/bb ----- SDLEngine -----(21778): onPause()
  1446. D/bb ----- SDLEngine -----(21778): onVisibilityChanged()true
  1447. V/bb ----- SDLEngine -----(21778): onPause()
  1448. V/bb -----------SDL Main -----------(21778): post SDL thread
  1449. V/bb ---- SDLSurface ----(21778): Native thread has finished
  1450. V/bb ---- SDLSurface ----(21778): handle native exit? true
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement