Browse Source

Merge branch 'sdl-update'

Lasse Öörni 12 years ago
parent
commit
8ca86afbe7
100 changed files with 3692 additions and 2926 deletions
  1. 5 0
      .gitignore
  2. 3 3
      Docs/GettingStarted.dox
  3. 1 1
      Docs/Urho3D.dox
  4. 9 8
      Readme.txt
  5. 1 1
      Source/Android/AndroidManifest.xml
  6. 0 14
      Source/Android/project.properties
  7. 805 952
      Source/Android/src/org/libsdl/app/SDLActivity.java
  8. 1 1
      Source/CMake/Modules/Urho3D-CMake-magic.cmake
  9. 1 1
      Source/CMake/Toolchains/android.toolchain.cmake
  10. 16 5
      Source/Engine/Graphics/OpenGL/OGLGraphics.cpp
  11. 1 1
      Source/Engine/Graphics/OpenGL/OGLGraphics.h
  12. 8 4
      Source/Engine/Graphics/OpenGL/OGLIndexBuffer.cpp
  13. 16 14
      Source/Engine/Graphics/OpenGL/OGLRenderSurface.cpp
  14. 11 7
      Source/Engine/Graphics/OpenGL/OGLShaderProgram.cpp
  15. 13 9
      Source/Engine/Graphics/OpenGL/OGLShaderVariation.cpp
  16. 9 5
      Source/Engine/Graphics/OpenGL/OGLTexture2D.cpp
  17. 9 5
      Source/Engine/Graphics/OpenGL/OGLTextureCube.cpp
  18. 9 5
      Source/Engine/Graphics/OpenGL/OGLVertexBuffer.cpp
  19. 14 16
      Source/Engine/Input/Input.cpp
  20. 17 18
      Source/Engine/UI/Cursor.cpp
  21. 6 4
      Source/ThirdParty/SDL/CMakeLists.txt
  22. 2 0
      Source/ThirdParty/SDL/CREDITS.txt
  23. 0 5
      Source/ThirdParty/SDL/TODO.txt
  24. 57 0
      Source/ThirdParty/SDL/WhatsNew.txt
  25. 15 12
      Source/ThirdParty/SDL/include/SDL.h
  26. 11 2
      Source/ThirdParty/SDL/include/SDL_assert.h
  27. 2 2
      Source/ThirdParty/SDL/include/SDL_atomic.h
  28. 22 22
      Source/ThirdParty/SDL/include/SDL_audio.h
  29. 4 0
      Source/ThirdParty/SDL/include/SDL_config_android.h
  30. 3 0
      Source/ThirdParty/SDL/include/SDL_config_iphoneos.h
  31. 8 2
      Source/ThirdParty/SDL/include/SDL_config_linux.h
  32. 3 0
      Source/ThirdParty/SDL/include/SDL_config_macosx.h
  33. 3 0
      Source/ThirdParty/SDL/include/SDL_config_minimal.h
  34. 1 0
      Source/ThirdParty/SDL/include/SDL_config_pandora.h
  35. 5 2
      Source/ThirdParty/SDL/include/SDL_config_psp.h
  36. 12 7
      Source/ThirdParty/SDL/include/SDL_config_windows.h
  37. 5 0
      Source/ThirdParty/SDL/include/SDL_cpuinfo.h
  38. 4 4
      Source/ThirdParty/SDL/include/SDL_endian.h
  39. 2 2
      Source/ThirdParty/SDL/include/SDL_error.h
  40. 4 4
      Source/ThirdParty/SDL/include/SDL_events.h
  41. 136 0
      Source/ThirdParty/SDL/include/SDL_filesystem.h
  42. 7 7
      Source/ThirdParty/SDL/include/SDL_haptic.h
  43. 16 0
      Source/ThirdParty/SDL/include/SDL_hints.h
  44. 2 2
      Source/ThirdParty/SDL/include/SDL_joystick.h
  45. 1 1
      Source/ThirdParty/SDL/include/SDL_main.h
  46. 9 9
      Source/ThirdParty/SDL/include/SDL_mutex.h
  47. 2 2
      Source/ThirdParty/SDL/include/SDL_pixels.h
  48. 6 2
      Source/ThirdParty/SDL/include/SDL_platform.h
  49. 1 1
      Source/ThirdParty/SDL/include/SDL_rect.h
  50. 25 0
      Source/ThirdParty/SDL/include/SDL_render.h
  51. 2 2
      Source/ThirdParty/SDL/include/SDL_revision.h
  52. 8 8
      Source/ThirdParty/SDL/include/SDL_rwops.h
  53. 6 6
      Source/ThirdParty/SDL/include/SDL_scancode.h
  54. 4 4
      Source/ThirdParty/SDL/include/SDL_stdinc.h
  55. 3 3
      Source/ThirdParty/SDL/include/SDL_surface.h
  56. 21 5
      Source/ThirdParty/SDL/include/SDL_system.h
  57. 1 0
      Source/ThirdParty/SDL/include/SDL_test_common.h
  58. 14 14
      Source/ThirdParty/SDL/include/SDL_test_harness.h
  59. 6 4
      Source/ThirdParty/SDL/include/SDL_thread.h
  60. 11 0
      Source/ThirdParty/SDL/include/SDL_timer.h
  61. 1 1
      Source/ThirdParty/SDL/include/SDL_version.h
  62. 30 9
      Source/ThirdParty/SDL/include/SDL_video.h
  63. 25 35
      Source/ThirdParty/SDL/include/begin_code.h
  64. 4 0
      Source/ThirdParty/SDL/src/SDL.c
  65. 4 2
      Source/ThirdParty/SDL/src/SDL_assert.c
  66. 3 11
      Source/ThirdParty/SDL/src/SDL_hints.c
  67. 13 10
      Source/ThirdParty/SDL/src/SDL_log.c
  68. 2 2
      Source/ThirdParty/SDL/src/atomic/SDL_atomic.c
  69. 4 4
      Source/ThirdParty/SDL/src/atomic/SDL_spinlock.c
  70. 4 10
      Source/ThirdParty/SDL/src/audio/SDL_audio.c
  71. 1 1
      Source/ThirdParty/SDL/src/audio/SDL_audiodev.c
  72. 8 16
      Source/ThirdParty/SDL/src/audio/SDL_wave.c
  73. 8 10
      Source/ThirdParty/SDL/src/audio/alsa/SDL_alsa_audio.c
  74. 3 5
      Source/ThirdParty/SDL/src/audio/arts/SDL_artsaudio.c
  75. 3 7
      Source/ThirdParty/SDL/src/audio/bsd/SDL_bsdaudio.c
  76. 3 11
      Source/ThirdParty/SDL/src/audio/directsound/SDL_directsound.c
  77. 2 4
      Source/ThirdParty/SDL/src/audio/disk/SDL_diskaudio.c
  78. 2 4
      Source/ThirdParty/SDL/src/audio/dsp/SDL_dspaudio.c
  79. 3 6
      Source/ThirdParty/SDL/src/audio/esd/SDL_esdaudio.c
  80. 2 4
      Source/ThirdParty/SDL/src/audio/fusionsound/SDL_fsaudio.c
  81. 2 4
      Source/ThirdParty/SDL/src/audio/nas/SDL_nasaudio.c
  82. 3 7
      Source/ThirdParty/SDL/src/audio/paudio/SDL_paudio.c
  83. 5 5
      Source/ThirdParty/SDL/src/audio/psp/SDL_pspaudio.c
  84. 5 7
      Source/ThirdParty/SDL/src/audio/pulseaudio/SDL_pulseaudio.c
  85. 3 5
      Source/ThirdParty/SDL/src/audio/qsa/SDL_qsa_audio.c
  86. 2 4
      Source/ThirdParty/SDL/src/audio/sndio/SDL_sndioaudio.c
  87. 4 8
      Source/ThirdParty/SDL/src/audio/sun/SDL_sunaudio.c
  88. 3 5
      Source/ThirdParty/SDL/src/audio/winmm/SDL_winmm.c
  89. 15 13
      Source/ThirdParty/SDL/src/audio/xaudio2/SDL_xaudio2.c
  90. 1464 1420
      Source/ThirdParty/SDL/src/core/android/SDL_android.c
  91. 13 2
      Source/ThirdParty/SDL/src/core/android/SDL_android.h
  92. 398 0
      Source/ThirdParty/SDL/src/core/linux/SDL_udev.c
  93. 115 0
      Source/ThirdParty/SDL/src/core/linux/SDL_udev.h
  94. 1 1
      Source/ThirdParty/SDL/src/core/windows/SDL_windows.c
  95. 3 2
      Source/ThirdParty/SDL/src/core/windows/SDL_windows.h
  96. 61 14
      Source/ThirdParty/SDL/src/cpuinfo/SDL_cpuinfo.c
  97. 4 6
      Source/ThirdParty/SDL/src/events/SDL_events.c
  98. 62 61
      Source/ThirdParty/SDL/src/events/SDL_gesture.c
  99. 2 2
      Source/ThirdParty/SDL/src/events/SDL_keyboard.c
  100. 3 0
      Source/ThirdParty/SDL/src/events/SDL_keyboard_c.h

+ 5 - 0
.gitignore

@@ -31,6 +31,11 @@ Docs/html/
 Source/.*project
 Source/.settings
 
+# Android project settings for non out-of-source build
+Source/Android/project.properties
+Source/Android/local.properties
+Source/Android/proguard-project.txt
+
 # CMake files for non out-of-source build
 CMakeCache.txt
 CMakeFiles

+ 3 - 3
Docs/GettingStarted.dox

@@ -12,11 +12,11 @@ Although all required third-party libraries are included as source code, there a
 
 - For Linux, the following development packages need to be installed: libx11-dev, libxrandr-dev, libasound2-dev on Debian-based distros; libX11-devel, libXrandr-devel, alsa-lib-devel on RedHat-based distros. Also install the package libgl1-mesa-dev (Debian) or mesa-libGL-devel (RH) if your GPU driver does not include OpenGL headers & libs.  Building as 32-bit on a 64-bit system requires installing also the 32-bit versions of the development libraries.
 
-- For Raspberry Pi, the following development packages need to be installed: libraspberrypi0, libraspberrypi-dev, libasound2-dev on Raspbian; raspberrypi-vc-libs, raspberrypi-vc-libs-devel, alsa-lib-devel on Pidora. The first two packages which contain the Broadcom VideoCore IV libraries and development headers should normally come preinstalled.
+- For Raspberry Pi, the following development packages need to be installed: libraspberrypi0, libraspberrypi-dev, libasound2-dev, libudev-dev on Raspbian; raspberrypi-vc-libs, raspberrypi-vc-libs-devel, alsa-lib-devel, systemd-devel on Pidora. The first two packages which contain the Broadcom VideoCore IV libraries and development headers should normally come preinstalled.
 
 - For Mac OS X, the Xcode developer tools package should include everything necessary.
 
-- For Android, the Android SDK and Android NDK need to be installed. Optionally, also install Eclipse ADT plugin for building and deployment via Eclipse.
+- For Android, the Android SDK and Android NDK (minimum API level 9) need to be installed. Optionally, also install Eclipse ADT plugin for building and deployment via Eclipse.
 
 To run Urho3D, the minimum system requirements are:
 
@@ -26,7 +26,7 @@ To run Urho3D, the minimum system requirements are:
 
 - Raspberry Pi: %Model B revision 2.0 with at least 128 MB of 512 MB SDRAM allocated for GPU. OpenGL ES 2.0 capable GPU.
 
-- Android: OS version 2.2 or newer, OpenGL ES 2.0 capable GPU.
+- Android: OS version 2.3 or newer, OpenGL ES 2.0 capable GPU.
 
 - iOS: OpenGL ES 2.0 capable GPU.
 

+ 1 - 1
Docs/Urho3D.dox

@@ -103,7 +103,7 @@ Urho3D uses the following third-party libraries:
 - Open Asset Import Library (http://assimp.sourceforge.net/)
 - pugixml 1.0 (http://pugixml.org/)
 - Recast/Detour (http://code.google.com/p/recastnavigation/)
-- SDL 2.0.0 (http://www.libsdl.org/)
+- SDL 2.0.1 (http://www.libsdl.org/)
 - StanHull (http://codesuppository.blogspot.com/2006/03/john-ratcliffs-code-suppository-blog.html)
 - stb_image 1.29 (http://nothings.org/)
 - stb_vorbis 0.99996 (http://nothings.org/)

+ 9 - 8
Readme.txt

@@ -73,7 +73,7 @@ Urho3D uses the following third-party libraries:
 - Open Asset Import Library (http://assimp.sourceforge.net/)
 - pugixml 1.0 (http://pugixml.org/)
 - Recast/Detour (http://code.google.com/p/recastnavigation/)
-- SDL 2.0.0 (http://www.libsdl.org/)
+- SDL 2.0.1 (http://www.libsdl.org/)
 - StanHull (http://codesuppository.blogspot.com/2006/03/
   john-ratcliffs-code-suppository-blog.html)
 - stb_image 1.29 (http://nothings.org/)
@@ -125,16 +125,17 @@ successfully:
   development libraries.
 
 - For Raspberry Pi, the following development packages need to be installed:
-  libraspberrypi0, libraspberrypi-dev, libasound2-dev on Raspbian;
-  raspberrypi-vc-libs, raspberrypi-vc-libs-devel, alsa-lib-devel on Pidora.
-  The first two packages which contain the Broadcom VideoCore IV libraries and
-  development headers should normally come preinstalled.
+  libraspberrypi0, libraspberrypi-dev, libasound2-dev, libudev-dev on Raspbian;
+  raspberrypi-vc-libs, raspberrypi-vc-libs-devel, alsa-lib-devel, systemd-devel
+  on Pidora. The first two packages which contain the Broadcom VideoCore IV
+  libraries and development headers should normally come preinstalled.
 
 - For Mac OS X, the Xcode developer tools package should include everything
   necessary.
 
-- For Android, the Android SDK and Android NDK need to be installed. Optionally,
-  also install Eclipse ADT plugin for building and deployment via Eclipse.
+- For Android, the Android SDK and Android NDK (minimum API level 9) need to be
+  installed. Optionally, also install Eclipse ADT plugin for building and 
+  deployment via Eclipse.
 
 To run Urho3D, the minimum system requirements are:
 
@@ -147,7 +148,7 @@ To run Urho3D, the minimum system requirements are:
 - Raspberry Pi: Model B revision 2.0 with at least 128 MB of 512 MB SDRAM
   allocated for GPU. OpenGL ES 2.0 capable GPU.
 
-- Android: OS version 2.2 or newer, OpenGL ES 2.0 capable GPU.
+- Android: OS version 2.3 or newer, OpenGL ES 2.0 capable GPU.
 
 - iOS: OpenGL ES 2.0 capable GPU.
 

+ 1 - 1
Source/Android/AndroidManifest.xml

@@ -5,7 +5,7 @@
     android:versionName="1.0">
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-feature android:glEsVersion="0x00020000" />
-    <uses-sdk android:targetSdkVersion="8" android:minSdkVersion="8" />
+    <uses-sdk android:targetSdkVersion="9" android:minSdkVersion="9" />
     <application android:label="@string/app_name" android:icon="@drawable/icon">
         <activity android:name="Urho3D"
                   android:label="@string/app_name"

+ 0 - 14
Source/Android/project.properties

@@ -1,14 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}\tools\proguard\proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-8

+ 805 - 952
Source/Android/src/org/libsdl/app/SDLActivity.java

@@ -1,952 +1,805 @@
-// Modified by Lasse Oorni and Yao Wei Tjong for Urho3D
-
-package org.libsdl.app;
-
-import java.io.File;
-import java.util.Arrays;
-import java.util.Comparator;
-
-import javax.microedition.khronos.egl.EGL10;
-import javax.microedition.khronos.egl.EGLConfig;
-import javax.microedition.khronos.egl.EGLContext;
-import javax.microedition.khronos.egl.EGLDisplay;
-import javax.microedition.khronos.egl.EGLSurface;
-
-import android.app.*;
-import android.content.*;
-import android.view.*;
-import android.view.inputmethod.BaseInputConnection;
-import android.view.inputmethod.EditorInfo;
-import android.view.inputmethod.InputConnection;
-import android.view.inputmethod.InputMethodManager;
-import android.widget.AbsoluteLayout;
-import android.os.*;
-import android.util.Log;
-import android.graphics.*;
-import android.media.*;
-import android.hardware.*;
-
-
-/**
-    SDL Activity
-*/
-public class SDLActivity extends Activity {
-    // Urho3D: adjust log level, no verbose in production code, first check log level for non-trivial message construction
-    private static final String TAG = "SDL";
-
-    // Keep track of the paused state
-    public static boolean mIsPaused = false, mIsSurfaceReady = false, mHasFocus = true;
-
-    // Main components
-    protected static SDLActivity mSingleton;
-    protected static SDLSurface mSurface;
-    protected static View mTextEdit;
-    protected static ViewGroup mLayout;
-
-    // This is what SDL runs in. It invokes SDL_main(), eventually
-    protected static Thread mSDLThread;
-
-    // Audio
-    protected static Thread mAudioThread;
-    protected static AudioTrack mAudioTrack;
-
-    // EGL objects
-    protected static EGLContext  mEGLContext;
-    protected static EGLSurface  mEGLSurface;
-    protected static EGLDisplay  mEGLDisplay;
-    protected static EGLConfig   mEGLConfig;
-    protected static int mGLMajor, mGLMinor;
-
-    // Urho3D: flag to load the .so
-    private static boolean mIsSharedLibraryLoaded = false;
-
-    // Setup
-    @Override
-    protected void onCreate(Bundle savedInstanceState) {
-        //Log.v(TAG, "onCreate()");
-        super.onCreate(savedInstanceState);
-        
-        // So we can call stuff from static callbacks
-        mSingleton = this;
-        
-        // Urho3D: auto load all the shared libraries available in the library path
-        // FIXME: use getApplicationInfo().nativeLibraryDir directly when min target API is 9 or above
-        String libraryPath = getApplicationInfo().dataDir + "/lib";
-        //Log.v(TAG, "library path: " + libraryPath);
-        if (!mIsSharedLibraryLoaded) {
-            File[] files = new File(libraryPath).listFiles();
-            Arrays.sort(files, new Comparator<File>() {
-                @Override
-                public int compare(File lhs, File rhs) {
-                    return Long.valueOf(lhs.lastModified()).compareTo(rhs.lastModified());
-                }
-            });
-            for (final File libraryFilename : files) {
-                String name = libraryFilename.getName().replaceAll("^lib(.*)\\.so$", "$1");
-                //Log.v(TAG, "library name: " + name);
-                System.loadLibrary(name);
-            }            
-            mIsSharedLibraryLoaded = true;
-        }
-
-        // Set up the surface
-        mEGLSurface = EGL10.EGL_NO_SURFACE;
-        mSurface = new SDLSurface(getApplication());
-        mEGLContext = EGL10.EGL_NO_CONTEXT;
-
-        mLayout = new AbsoluteLayout(this);
-        mLayout.addView(mSurface);
-
-        setContentView(mLayout);
-    }
-
-    // Events
-    @Override
-    protected void onPause() {
-        //Log.v(TAG, "onPause()");
-        super.onPause();
-        SDLActivity.handlePause();
-    }
-
-    @Override
-    protected void onResume() {
-        //Log.v(TAG, "onResume()");
-        super.onResume();
-        SDLActivity.handleResume();
-    }
-
-
-    @Override
-    public void onWindowFocusChanged(boolean hasFocus) {
-        //Log.v(TAG, "onWindowFocusChanged(): " + hasFocus);
-        super.onWindowFocusChanged(hasFocus);
-
-        SDLActivity.mHasFocus = hasFocus;
-        if (hasFocus) {
-            SDLActivity.handleResume();
-        }
-    }
-
-    @Override
-    public void onLowMemory() {
-        //Log.v(TAG, "onLowMemory()");
-        super.onLowMemory();
-        SDLActivity.nativeLowMemory();
-    }
-
-    @Override
-    protected void onDestroy() {
-        //Log.v(TAG, "onDestroy()");
-        super.onDestroy();
-        
-        // Send a quit message to the application
-        SDLActivity.nativeQuit();
-
-        // Now wait for the SDL thread to quit
-        if (mSDLThread != null) {
-            try {
-                mSDLThread.join();
-            } catch(Exception e) {
-                if (Log.isLoggable(TAG, Log.ERROR))
-                    Log.e(TAG, "Problem stopping thread: " + e);
-            }
-            mSDLThread = null;
-
-            //Log.v(TAG, "Finished waiting for SDL thread");
-        }
-    }
-
-    @Override
-    public boolean dispatchKeyEvent(KeyEvent event) {
-        int keyCode = event.getKeyCode();
-        // Ignore volume keys so they're handled by Android
-        // Urho3D: also ignore the Home key
-        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
-            keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
-            keyCode == KeyEvent.KEYCODE_HOME) {
-            return false;
-        }
-        return super.dispatchKeyEvent(event);
-    }
-
-    /** Called by onPause or surfaceDestroyed. Even if surfaceDestroyed
-     *  is the first to be called, mIsSurfaceReady should still be set
-     *  to 'true' during the call to onPause (in a usual scenario).
-     */
-    public static void handlePause() {
-        if (!SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady) {
-            SDLActivity.mIsPaused = true;
-            SDLActivity.nativePause();
-            mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, false);
-        }
-    }
-
-    /** Called by onResume or surfaceCreated. An actual resume should be done only when the surface is ready.
-     * Note: Some Android variants may send multiple surfaceChanged events, so we don't need to resume
-     * every time we get one of those events, only if it comes after surfaceDestroyed
-     */
-    public static void handleResume() {
-        if (SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady && SDLActivity.mHasFocus) {
-            SDLActivity.mIsPaused = false;
-            SDLActivity.nativeResume();
-            mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);
-        }
-    }
-
-
-    // Messages from the SDLMain thread
-    static final int COMMAND_CHANGE_TITLE = 1;
-    static final int COMMAND_UNUSED = 2;
-    static final int COMMAND_TEXTEDIT_HIDE = 3;
-    // Urho3D: added
-    static final int COMMAND_FINISH = 4;
-
-    protected static final int COMMAND_USER = 0x8000;
-
-    /**
-     * This method is called by SDL if SDL did not handle a message itself.
-     * This happens if a received message contains an unsupported command.
-     * Method can be overwritten to handle Messages in a different class.
-     * @param command the command of the message.
-     * @param param the parameter of the message. May be null.
-     * @return if the message was handled in overridden method.
-     */
-    protected boolean onUnhandledMessage(int command, Object param) {
-        return false;
-    }
-
-    /**
-     * A Handler class for Messages from native SDL applications.
-     * It uses current Activities as target (e.g. for the title).
-     * static to prevent implicit references to enclosing object.
-     */
-    protected static class SDLCommandHandler extends Handler {
-        @Override
-        public void handleMessage(Message msg) {
-            Context context = getContext();
-            if (context == null) {
-                Log.e(TAG, "error handling message, getContext() returned null");
-                return;
-            }
-            switch (msg.arg1) {
-            case COMMAND_CHANGE_TITLE:
-                if (context instanceof Activity) {
-                    ((Activity) context).setTitle((String)msg.obj);
-                } else {
-                    Log.e(TAG, "error handling message, getContext() returned no Activity");
-                }
-                break;
-            case COMMAND_TEXTEDIT_HIDE:
-                if (mTextEdit != null) {
-                    mTextEdit.setVisibility(View.GONE);
-
-                    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
-                    imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0);
-                }
-                break;
-            // Urho3D: added
-            case COMMAND_FINISH:
-                if (context instanceof Activity)
-                    ((Activity) context).finish();
-                break;
-
-            default:
-                if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) {
-                    if (Log.isLoggable(TAG, Log.ERROR))
-                        Log.e(TAG, "error handling message, command is " + msg.arg1);
-                }
-            }
-        }
-    }
-
-    // Handler for the messages
-    Handler commandHandler = new SDLCommandHandler();
-
-    // Send a message from the SDLMain thread
-    boolean sendCommand(int command, Object data) {
-        Message msg = commandHandler.obtainMessage();
-        msg.arg1 = command;
-        msg.obj = data;
-        return commandHandler.sendMessage(msg);
-    }
-
-    // C functions we call
-    public static native void nativeInit(String filesDir);
-    public static native void nativeLowMemory();
-    public static native void nativeQuit();
-    public static native void nativePause();
-    public static native void nativeResume();
-    public static native void onNativeResize(int x, int y, int format);
-    public static native void onNativeKeyDown(int keycode);
-    public static native void onNativeKeyUp(int keycode);
-    public static native void onNativeKeyboardFocusLost();
-    public static native void onNativeTouch(int touchDevId, int pointerFingerId,
-                                            int action, float x, 
-                                            float y, float p);
-    public static native void onNativeAccel(float x, float y, float z);
-
-    // Java functions called from C
-
-    public static boolean createGLContext(int majorVersion, int minorVersion, int[] attribs) {
-        return initEGL(majorVersion, minorVersion, attribs);
-    }
-    
-    public static void deleteGLContext() {
-        if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLContext != EGL10.EGL_NO_CONTEXT) {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-            egl.eglMakeCurrent(SDLActivity.mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
-            egl.eglDestroyContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLContext);
-            SDLActivity.mEGLContext = EGL10.EGL_NO_CONTEXT;
-
-            if (SDLActivity.mEGLSurface != EGL10.EGL_NO_SURFACE) {
-                egl.eglDestroySurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
-                SDLActivity.mEGLSurface = EGL10.EGL_NO_SURFACE;
-            }
-        }
-    }
-
-    public static void flipBuffers() {
-        flipEGL();
-    }
-
-    public static boolean setActivityTitle(String title) {
-        // Called from SDLMain() thread and can't directly affect the view
-        return mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);
-    }
-
-    public static void finishActivity()
-    {
-        mSingleton.sendCommand(COMMAND_FINISH, null);
-    }
-
-    public static boolean sendMessage(int command, int param) {
-        return mSingleton.sendCommand(command, Integer.valueOf(param));
-    }
-
-    public static Context getContext() {
-        return mSingleton;
-    }
-
-    static class ShowTextInputTask implements Runnable {
-        /*
-         * This is used to regulate the pan&scan method to have some offset from
-         * the bottom edge of the input region and the top edge of an input
-         * method (soft keyboard)
-         */
-        static final int HEIGHT_PADDING = 15;
-
-        public int x, y, w, h;
-
-        public ShowTextInputTask(int x, int y, int w, int h) {
-            this.x = x;
-            this.y = y;
-            this.w = w;
-            this.h = h;
-        }
-
-        @Override
-        public void run() {
-            AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(
-                    w, h + HEIGHT_PADDING, x, y);
-
-            if (mTextEdit == null) {
-                mTextEdit = new DummyEdit(getContext());
-
-                mLayout.addView(mTextEdit, params);
-            } else {
-                mTextEdit.setLayoutParams(params);
-            }
-
-            mTextEdit.setVisibility(View.VISIBLE);
-            mTextEdit.requestFocus();
-
-            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
-            imm.showSoftInput(mTextEdit, 0);
-        }
-    }
-
-    public static boolean showTextInput(int x, int y, int w, int h) {
-        // Transfer the task to the main thread as a Runnable
-        return mSingleton.commandHandler.post(new ShowTextInputTask(x, y, w, h));
-    }
-
-
-    // EGL functions
-    public static boolean initEGL(int majorVersion, int minorVersion, int[] attribs) {
-        try {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-            
-            if (SDLActivity.mEGLDisplay == null) {
-                SDLActivity.mEGLDisplay = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
-                int[] version = new int[2];
-                egl.eglInitialize(SDLActivity.mEGLDisplay, version);
-            }
-            
-            if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) {
-                // No current GL context exists, we will create a new one.
-                if (Log.isLoggable(TAG, Log.DEBUG))
-                    Log.d(TAG, "Starting up OpenGL ES " + majorVersion + "." + minorVersion);
-                EGLConfig[] configs = new EGLConfig[128];
-                int[] num_config = new int[1];
-                if (!egl.eglChooseConfig(SDLActivity.mEGLDisplay, attribs, configs, 1, num_config) || num_config[0] == 0) {
-                    Log.e("SDL", "No EGL config available");
-                    return false;
-                }
-                EGLConfig config = null;
-                int bestdiff = -1, bitdiff;
-                int[] value = new int[1];
-                
-                // eglChooseConfig returns a number of configurations that match or exceed the requested attribs.
-                // From those, we select the one that matches our requirements more closely
-                if (Log.isLoggable(TAG, Log.DEBUG))
-                    Log.d(TAG, "Got " + num_config[0] + " valid modes from egl");
-                for(int i = 0; i < num_config[0]; i++) {
-                    bitdiff = 0;
-                    // Go through some of the attributes and compute the bit difference between what we want and what we get.
-                    for (int j = 0; ; j += 2) {
-                        if (attribs[j] == EGL10.EGL_NONE)
-                            break;
-
-                        if (attribs[j+1] != EGL10.EGL_DONT_CARE && (attribs[j] == EGL10.EGL_RED_SIZE ||
-                            attribs[j] == EGL10.EGL_GREEN_SIZE ||
-                            attribs[j] == EGL10.EGL_BLUE_SIZE ||
-                            attribs[j] == EGL10.EGL_ALPHA_SIZE ||
-                            attribs[j] == EGL10.EGL_DEPTH_SIZE ||
-                            attribs[j] == EGL10.EGL_STENCIL_SIZE)) {
-                            egl.eglGetConfigAttrib(SDLActivity.mEGLDisplay, configs[i], attribs[j], value);
-                            bitdiff += value[0] - attribs[j + 1]; // value is always >= attrib
-                        }
-                    }
-                    
-                    if (bitdiff < bestdiff || bestdiff == -1) {
-                        config = configs[i];
-                        bestdiff = bitdiff;
-                    }
-                    
-                    if (bitdiff == 0) break; // we found an exact match!
-                }
-                
-                if (Log.isLoggable(TAG, Log.DEBUG))
-                    Log.d("SDL", "Selected mode with a total bit difference of " + bestdiff);
-
-                SDLActivity.mEGLConfig = config;
-                SDLActivity.mGLMajor = majorVersion;
-                SDLActivity.mGLMinor = minorVersion;
-            }
-            
-            return SDLActivity.createEGLSurface();
-
-        } catch(Exception e) {
-            if (Log.isLoggable(TAG, Log.ERROR))
-                Log.e(TAG, "initEGL(): " + e);
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                for (StackTraceElement s : e.getStackTrace()) {
-                    Log.d(TAG, s.toString());
-                }
-            }
-            return false;
-        }
-    }
-
-    public static boolean createEGLContext() {
-        EGL10 egl = (EGL10)EGLContext.getEGL();
-        int EGL_CONTEXT_CLIENT_VERSION=0x3098;
-        int contextAttrs[] = new int[] { EGL_CONTEXT_CLIENT_VERSION, SDLActivity.mGLMajor, EGL10.EGL_NONE };
-        SDLActivity.mEGLContext = egl.eglCreateContext(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, EGL10.EGL_NO_CONTEXT, contextAttrs);
-        if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) {
-            Log.e("SDL", "Couldn't create context");
-            return false;
-        }
-        return true;
-    }
-
-    public static boolean createEGLSurface() {
-        if (SDLActivity.mEGLDisplay != null && SDLActivity.mEGLConfig != null) {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-            if (SDLActivity.mEGLContext == EGL10.EGL_NO_CONTEXT) createEGLContext();
-
-            if (SDLActivity.mEGLSurface == EGL10.EGL_NO_SURFACE) {
-                Log.d(TAG, "Creating new EGL Surface");
-                SDLActivity.mEGLSurface = egl.eglCreateWindowSurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLConfig, SDLActivity.mSurface, null);
-                if (SDLActivity.mEGLSurface == EGL10.EGL_NO_SURFACE) {
-                    Log.e("SDL", "Couldn't create surface");
-                    return false;
-                }
-            }
-            else Log.d(TAG, "EGL Surface remains valid");
-
-            if (egl.eglGetCurrentContext() != SDLActivity.mEGLContext) {
-                if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface, SDLActivity.mEGLSurface, SDLActivity.mEGLContext)) {
-                    Log.e("SDL", "Old EGL Context doesnt work, trying with a new one");
-                    // TODO: Notify the user via a message that the old context could not be restored, and that textures need to be manually restored.
-                    createEGLContext();
-                    if (!egl.eglMakeCurrent(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface, SDLActivity.mEGLSurface, SDLActivity.mEGLContext)) {
-                        Log.e("SDL", "Failed making EGL Context current");
-                        return false;
-                    }
-                }
-                else Log.d(TAG, "EGL Context made current");
-            }
-            else Log.d(TAG, "EGL Context remains current");
-
-            return true;
-        } else {
-            if (Log.isLoggable(TAG, Log.ERROR))
-                Log.e("SDL", "Surface creation failed, display = " + SDLActivity.mEGLDisplay + ", config = " + SDLActivity.mEGLConfig);
-            return false;
-        }
-    }
-
-    // EGL buffer flip
-    public static void flipEGL() {
-        try {
-            EGL10 egl = (EGL10)EGLContext.getEGL();
-
-            egl.eglWaitNative(EGL10.EGL_CORE_NATIVE_ENGINE, null);
-
-            // drawing here
-
-            egl.eglWaitGL();
-
-            egl.eglSwapBuffers(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
-
-
-        } catch(Exception e) {
-            if (Log.isLoggable(TAG, Log.ERROR))
-                Log.e(TAG, "flipEGL(): " + e);
-            if (Log.isLoggable(TAG, Log.DEBUG)) {
-                for (StackTraceElement s : e.getStackTrace()) {
-                    Log.d(TAG, s.toString());
-                }
-            }
-        }
-    }
-
-    // Audio
-    public static int audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
-        int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
-        int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
-        int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
-        
-        if (Log.isLoggable(TAG, Log.DEBUG))
-            Log.d(TAG, "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + (sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
-        
-        // Let the user pick a larger buffer if they really want -- but ye
-        // gods they probably shouldn't, the minimums are horrifyingly high
-        // latency already
-        desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
-        
-        if (mAudioTrack == null) {
-            mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
-                    channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
-            
-            // Instantiating AudioTrack can "succeed" without an exception and the track may still be invalid
-            // Ref: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/AudioTrack.java
-            // Ref: http://developer.android.com/reference/android/media/AudioTrack.html#getState()
-            
-            if (mAudioTrack.getState() != AudioTrack.STATE_INITIALIZED) {
-                Log.e("SDL", "Failed during initialization of Audio Track");
-                mAudioTrack = null;
-                return -1;
-            }
-            
-            mAudioTrack.play();
-        }
-
-        if (Log.isLoggable(TAG, Log.DEBUG))
-            Log.d(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");
-        
-        return 0;
-    }
-    
-    public static void audioWriteShortBuffer(short[] buffer) {
-        for (int i = 0; i < buffer.length; ) {
-            int result = mAudioTrack.write(buffer, i, buffer.length - i);
-            if (result > 0) {
-                i += result;
-            } else if (result == 0) {
-                try {
-                    Thread.sleep(1);
-                } catch(InterruptedException e) {
-                    // Nom nom
-                }
-            } else {
-                Log.w("SDL", "SDL audio: error return from write(short)");
-                return;
-            }
-        }
-    }
-    
-    public static void audioWriteByteBuffer(byte[] buffer) {
-        for (int i = 0; i < buffer.length; ) {
-            int result = mAudioTrack.write(buffer, i, buffer.length - i);
-            if (result > 0) {
-                i += result;
-            } else if (result == 0) {
-                try {
-                    Thread.sleep(1);
-                } catch(InterruptedException e) {
-                    // Nom nom
-                }
-            } else {
-                Log.w("SDL", "SDL audio: error return from write(byte)");
-                return;
-            }
-        }
-    }
-
-    public static void audioQuit() {
-        if (mAudioTrack != null) {
-            mAudioTrack.stop();
-            mAudioTrack = null;
-        }
-    }
-}
-
-/**
-    Simple nativeInit() runnable
-*/
-class SDLMain implements Runnable {
-    @Override
-    public void run() {
-        // Runs SDL_main()
-        // Urho3D: pass filesDir
-        SDLActivity.nativeInit(((Activity)SDLActivity.getContext()).getFilesDir().getAbsolutePath());
-        //Log.v("SDL", "SDL thread terminated");
-    }
-}
-
-
-/**
-    SDLSurface. This is what we draw on, so we need to know when it's created
-    in order to do anything useful. 
-
-    Because of this, that's where we set up the SDL thread
-*/
-class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, 
-    View.OnKeyListener, View.OnTouchListener, SensorEventListener  {
-
-    private static final String TAG = "SDL";
-    
-    // Sensors
-    protected static SensorManager mSensorManager;
-
-    // Keep track of the surface size to normalize touch events
-    protected static float mWidth, mHeight;
-
-    // Startup    
-    public SDLSurface(Context context) {
-        super(context);
-        getHolder().addCallback(this); 
-    
-        setFocusable(true);
-        setFocusableInTouchMode(true);
-        requestFocus();
-        setOnKeyListener(this); 
-        setOnTouchListener(this);   
-
-        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
-
-        // Some arbitrary defaults to avoid a potential division by zero
-        mWidth = 1.0f;
-        mHeight = 1.0f;
-    }
-
-    // Called when we have a valid drawing surface
-    @Override
-    public void surfaceCreated(SurfaceHolder holder) {
-        //Log.v(TAG, "surfaceCreated()");
-        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
-        // Set mIsSurfaceReady to 'true' *before* any call to handleResume
-        SDLActivity.mIsSurfaceReady = true;
-    }
-
-    // Called when we lose the surface
-    @Override
-    public void surfaceDestroyed(SurfaceHolder holder) {
-        //Log.v(TAG, "surfaceDestroyed()");
-        // Call this *before* setting mIsSurfaceReady to 'false'
-        SDLActivity.handlePause();
-        SDLActivity.mIsSurfaceReady = false;
-
-        /* We have to clear the current context and destroy the egl surface here
-         * Otherwise there's BAD_NATIVE_WINDOW errors coming from eglCreateWindowSurface on resume
-         * Ref: http://stackoverflow.com/questions/8762589/eglcreatewindowsurface-on-ics-and-switching-from-2d-to-3d
-         */
-        
-        EGL10 egl = (EGL10)EGLContext.getEGL();
-        egl.eglMakeCurrent(SDLActivity.mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
-        egl.eglDestroySurface(SDLActivity.mEGLDisplay, SDLActivity.mEGLSurface);
-        SDLActivity.mEGLSurface = EGL10.EGL_NO_SURFACE;
-    }
-
-    // Called when the surface is resized
-    @Override
-    public void surfaceChanged(SurfaceHolder holder,
-                               int format, int width, int height) {
-        //Log.v(TAG, "surfaceChanged()");
-
-        int sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565 by default
-        switch (format) {
-        case PixelFormat.A_8:
-            Log.d(TAG, "pixel format A_8");
-            break;
-        case PixelFormat.LA_88:
-            Log.d(TAG, "pixel format LA_88");
-            break;
-        case PixelFormat.L_8:
-            Log.d(TAG, "pixel format L_8");
-            break;
-        case PixelFormat.RGBA_4444:
-            Log.d(TAG, "pixel format RGBA_4444");
-            sdlFormat = 0x15421002; // SDL_PIXELFORMAT_RGBA4444
-            break;
-        case PixelFormat.RGBA_5551:
-            Log.d(TAG, "pixel format RGBA_5551");
-            sdlFormat = 0x15441002; // SDL_PIXELFORMAT_RGBA5551
-            break;
-        case PixelFormat.RGBA_8888:
-            Log.d(TAG, "pixel format RGBA_8888");
-            sdlFormat = 0x16462004; // SDL_PIXELFORMAT_RGBA8888
-            break;
-        case PixelFormat.RGBX_8888:
-            Log.d(TAG, "pixel format RGBX_8888");
-            sdlFormat = 0x16261804; // SDL_PIXELFORMAT_RGBX8888
-            break;
-        case PixelFormat.RGB_332:
-            Log.d(TAG, "pixel format RGB_332");
-            sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
-            break;
-        case PixelFormat.RGB_565:
-            Log.d(TAG, "pixel format RGB_565");
-            sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565
-            break;
-        case PixelFormat.RGB_888:
-            Log.d(TAG, "pixel format RGB_888");
-            // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
-            sdlFormat = 0x16161804; // SDL_PIXELFORMAT_RGB888
-            break;
-        default:
-            if (Log.isLoggable(TAG, Log.DEBUG))
-                Log.d(TAG, "pixel format unknown " + format);
-            break;
-        }
-
-        mWidth = width;
-        mHeight = height;
-        SDLActivity.onNativeResize(width, height, sdlFormat);
-        if (Log.isLoggable(TAG, Log.DEBUG))
-            Log.d(TAG, "Window size: " + width + "x" + height);
-
-        // Set mIsSurfaceReady to 'true' *before* making a call to handleResume
-        SDLActivity.mIsSurfaceReady = true;
-
-        if (SDLActivity.mSDLThread == null) {
-            // This is the entry point to the C app.
-            // Start up the C app thread and enable sensor input for the first time
-
-            SDLActivity.mSDLThread = new Thread(new SDLMain(), "SDLThread");
-            enableSensor(Sensor.TYPE_ACCELEROMETER, true);
-            SDLActivity.mSDLThread.start();
-        }
-    }
-
-    // unused
-    @Override
-    public void onDraw(Canvas canvas) {}
-
-
-    // Key events
-    @Override
-    public boolean onKey(View  v, int keyCode, KeyEvent event) {
-        
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            //Log.v(TAG, "key down: " + keyCode);
-            SDLActivity.onNativeKeyDown(keyCode);
-            return true;
-        }
-        else if (event.getAction() == KeyEvent.ACTION_UP) {
-            //Log.v(TAG, "key up: " + keyCode);
-            SDLActivity.onNativeKeyUp(keyCode);
-            return true;
-        }
-        
-        return false;
-    }
-
-    // Touch events
-    @Override
-    public boolean onTouch(View v, MotionEvent event) {
-             final int touchDevId = event.getDeviceId();
-             final int pointerCount = event.getPointerCount();
-             // touchId, pointerId, action, x, y, pressure
-             int actionPointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; /* API 8: event.getActionIndex(); */
-             int pointerFingerId = event.getPointerId(actionPointerIndex);
-             int action = (event.getAction() & MotionEvent.ACTION_MASK); /* API 8: event.getActionMasked(); */
-
-             float x = event.getX(actionPointerIndex) / mWidth;
-             float y = event.getY(actionPointerIndex) / mHeight;
-             float p = event.getPressure(actionPointerIndex);
-
-             if (action == MotionEvent.ACTION_MOVE && pointerCount > 1) {
-                // TODO send motion to every pointer if its position has
-                // changed since prev event.
-                for (int i = 0; i < pointerCount; i++) {
-                    pointerFingerId = event.getPointerId(i);
-                    x = event.getX(i) / mWidth;
-                    y = event.getY(i) / mHeight;
-                    p = event.getPressure(i);
-                    SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
-                }
-             } else {
-                SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
-             }
-      return true;
-   } 
-
-    // Sensor events
-    public void enableSensor(int sensortype, boolean enabled) {
-        // TODO: This uses getDefaultSensor - what if we have >1 accels?
-        if (enabled) {
-            mSensorManager.registerListener(this, 
-                            mSensorManager.getDefaultSensor(sensortype), 
-                            SensorManager.SENSOR_DELAY_GAME, null);
-        } else {
-            mSensorManager.unregisterListener(this, 
-                            mSensorManager.getDefaultSensor(sensortype));
-        }
-    }
-    
-    @Override
-    public void onAccuracyChanged(Sensor sensor, int accuracy) {
-        // TODO
-    }
-
-    @Override
-    public void onSensorChanged(SensorEvent event) {
-        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
-            SDLActivity.onNativeAccel(event.values[0] / SensorManager.GRAVITY_EARTH,
-                                      event.values[1] / SensorManager.GRAVITY_EARTH,
-                                      event.values[2] / SensorManager.GRAVITY_EARTH);
-        }
-    }
-    
-}
-
-/* This is a fake invisible editor view that receives the input and defines the
- * pan&scan region
- */
-class DummyEdit extends View implements View.OnKeyListener {
-    InputConnection ic;
-
-    public DummyEdit(Context context) {
-        super(context);
-        setFocusableInTouchMode(true);
-        setFocusable(true);
-        setOnKeyListener(this);
-    }
-
-    @Override
-    public boolean onCheckIsTextEditor() {
-        return true;
-    }
-
-    @Override
-    public boolean onKey(View v, int keyCode, KeyEvent event) {
-
-        // This handles the hardware keyboard input
-        if (event.isPrintingKey()) {
-            if (event.getAction() == KeyEvent.ACTION_DOWN) {
-                ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
-            }
-            return true;
-        }
-
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            SDLActivity.onNativeKeyDown(keyCode);
-            return true;
-        } else if (event.getAction() == KeyEvent.ACTION_UP) {
-            SDLActivity.onNativeKeyUp(keyCode);
-            return true;
-        }
-
-        return false;
-    }
-        
-    //
-    @Override
-    public boolean onKeyPreIme (int keyCode, KeyEvent event) {
-        // As seen on StackOverflow: http://stackoverflow.com/questions/7634346/keyboard-hide-event
-        // FIXME: Discussion at http://bugzilla.libsdl.org/show_bug.cgi?id=1639
-        // FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not
-        // FIXME: A more effective solution would be to change our Layout from AbsoluteLayout to Relative or Linear
-        // FIXME: And determine the keyboard presence doing this: http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android
-        // FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :)
-        if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
-            if (SDLActivity.mTextEdit != null && SDLActivity.mTextEdit.getVisibility() == View.VISIBLE) {
-                SDLActivity.onNativeKeyboardFocusLost();
-            }
-        }
-        return super.onKeyPreIme(keyCode, event);
-    }
-
-    @Override
-    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
-        ic = new SDLInputConnection(this, true);
-
-        outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
-                | 33554432 /* API 11: EditorInfo.IME_FLAG_NO_FULLSCREEN */;
-
-        return ic;
-    }
-}
-
-class SDLInputConnection extends BaseInputConnection {
-
-    public SDLInputConnection(View targetView, boolean fullEditor) {
-        super(targetView, fullEditor);
-    }
-
-    @Override
-    public boolean sendKeyEvent(KeyEvent event) {
-
-        /*
-         * This handles the keycodes from soft keyboard (and IME-translated
-         * input from hardkeyboard)
-         */
-        int keyCode = event.getKeyCode();
-        if (event.getAction() == KeyEvent.ACTION_DOWN) {
-            if (event.isPrintingKey()) {
-                commitText(String.valueOf((char) event.getUnicodeChar()), 1);
-            }
-            SDLActivity.onNativeKeyDown(keyCode);
-            return true;
-        } else if (event.getAction() == KeyEvent.ACTION_UP) {
-
-            SDLActivity.onNativeKeyUp(keyCode);
-            return true;
-        }
-        return super.sendKeyEvent(event);
-    }
-
-    @Override
-    public boolean commitText(CharSequence text, int newCursorPosition) {
-
-        nativeCommitText(text.toString(), newCursorPosition);
-
-        return super.commitText(text, newCursorPosition);
-    }
-
-    @Override
-    public boolean setComposingText(CharSequence text, int newCursorPosition) {
-
-        nativeSetComposingText(text.toString(), newCursorPosition);
-
-        return super.setComposingText(text, newCursorPosition);
-    }
-
-    public native void nativeCommitText(String text, int newCursorPosition);
-
-    public native void nativeSetComposingText(String text, int newCursorPosition);
-
-}
+// Modified by Lasse Oorni and Yao Wei Tjong for Urho3D
+
+package org.libsdl.app;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.Comparator;
+
+import android.app.*;
+import android.content.*;
+import android.view.*;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.AbsoluteLayout;
+import android.os.*;
+import android.util.Log;
+import android.graphics.*;
+import android.media.*;
+import android.hardware.*;
+
+
+/**
+    SDL Activity
+*/
+public class SDLActivity extends Activity {
+    // Urho3D: adjust log level, no verbose in production code, first check log level for non-trivial message construction
+    private static final String TAG = "SDL";
+
+    // Keep track of the paused state
+    public static boolean mIsPaused = false, mIsSurfaceReady = false, mHasFocus = true;
+
+    // Main components
+    protected static SDLActivity mSingleton;
+    protected static SDLSurface mSurface;
+    protected static View mTextEdit;
+    protected static ViewGroup mLayout;
+
+    // This is what SDL runs in. It invokes SDL_main(), eventually
+    protected static Thread mSDLThread;
+
+    // Audio
+    protected static Thread mAudioThread;
+    protected static AudioTrack mAudioTrack;
+
+
+    // Urho3D: flag to load the .so
+    private static boolean mIsSharedLibraryLoaded = false;
+
+    // Setup
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        //Log.v("SDL", "onCreate()");
+        super.onCreate(savedInstanceState);
+        
+        // So we can call stuff from static callbacks
+        mSingleton = this;
+        
+        // Urho3D: auto load all the shared libraries available in the library path
+        String libraryPath = getApplicationInfo().nativeLibraryDir;
+        //Log.v(TAG, "library path: " + libraryPath);
+        if (!mIsSharedLibraryLoaded) {
+            File[] files = new File(libraryPath).listFiles();
+            Arrays.sort(files, new Comparator<File>() {
+                @Override
+                public int compare(File lhs, File rhs) {
+                    return Long.valueOf(lhs.lastModified()).compareTo(rhs.lastModified());
+                }
+            });
+            for (final File libraryFilename : files) {
+                String name = libraryFilename.getName().replaceAll("^lib(.*)\\.so$", "$1");
+                //Log.v(TAG, "library name: " + name);
+                System.loadLibrary(name);
+            }            
+            mIsSharedLibraryLoaded = true;
+        }
+
+        // Set up the surface
+        mSurface = new SDLSurface(getApplication());
+
+        mLayout = new AbsoluteLayout(this);
+        mLayout.addView(mSurface);
+
+        setContentView(mLayout);
+    }
+
+    // Events
+    @Override
+    protected void onPause() {
+        Log.v("SDL", "onPause()");
+        super.onPause();
+        SDLActivity.handlePause();
+    }
+
+    @Override
+    protected void onResume() {
+        Log.v("SDL", "onResume()");
+        super.onResume();
+        SDLActivity.handleResume();
+    }
+
+
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        Log.v("SDL", "onWindowFocusChanged(): " + hasFocus);
+
+        SDLActivity.mHasFocus = hasFocus;
+        if (hasFocus) {
+            SDLActivity.handleResume();
+        }
+    }
+
+    @Override
+    public void onLowMemory() {
+        Log.v("SDL", "onLowMemory()");
+        super.onLowMemory();
+        SDLActivity.nativeLowMemory();
+    }
+
+    @Override
+    protected void onDestroy() {
+        super.onDestroy();
+        Log.v("SDL", "onDestroy()");
+        // Send a quit message to the application
+        SDLActivity.nativeQuit();
+
+        // Now wait for the SDL thread to quit
+        if (mSDLThread != null) {
+            try {
+                mSDLThread.join();
+            } catch(Exception e) {
+                Log.v("SDL", "Problem stopping thread: " + e);
+            }
+            mSDLThread = null;
+
+            //Log.v("SDL", "Finished waiting for SDL thread");
+        }
+    }
+
+    @Override
+    public boolean dispatchKeyEvent(KeyEvent event) {
+        int keyCode = event.getKeyCode();
+        // Ignore certain special keys so they're handled by Android
+        // Urho3D: also ignore the Home key
+        if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
+            keyCode == KeyEvent.KEYCODE_VOLUME_UP ||
+            keyCode == KeyEvent.KEYCODE_HOME ||
+            keyCode == KeyEvent.KEYCODE_CAMERA ||
+            keyCode == 168 || /* API 11: KeyEvent.KEYCODE_ZOOM_IN */
+            keyCode == 169 /* API 11: KeyEvent.KEYCODE_ZOOM_OUT */
+            ) {
+            return false;
+        }
+        return super.dispatchKeyEvent(event);
+    }
+
+    /** Called by onPause or surfaceDestroyed. Even if surfaceDestroyed
+     *  is the first to be called, mIsSurfaceReady should still be set
+     *  to 'true' during the call to onPause (in a usual scenario).
+     */
+    public static void handlePause() {
+        if (!SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady) {
+            SDLActivity.mIsPaused = true;
+            SDLActivity.nativePause();
+            mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, false);
+        }
+    }
+
+    /** Called by onResume or surfaceCreated. An actual resume should be done only when the surface is ready.
+     * Note: Some Android variants may send multiple surfaceChanged events, so we don't need to resume
+     * every time we get one of those events, only if it comes after surfaceDestroyed
+     */
+    public static void handleResume() {
+        if (SDLActivity.mIsPaused && SDLActivity.mIsSurfaceReady && SDLActivity.mHasFocus) {
+            SDLActivity.mIsPaused = false;
+            SDLActivity.nativeResume();
+            mSurface.enableSensor(Sensor.TYPE_ACCELEROMETER, true);
+        }
+    }
+
+
+    // Messages from the SDLMain thread
+    static final int COMMAND_CHANGE_TITLE = 1;
+    static final int COMMAND_UNUSED = 2;
+    static final int COMMAND_TEXTEDIT_HIDE = 3;
+    // Urho3D: added
+    static final int COMMAND_FINISH = 4;
+
+    protected static final int COMMAND_USER = 0x8000;
+
+    /**
+     * This method is called by SDL if SDL did not handle a message itself.
+     * This happens if a received message contains an unsupported command.
+     * Method can be overwritten to handle Messages in a different class.
+     * @param command the command of the message.
+     * @param param the parameter of the message. May be null.
+     * @return if the message was handled in overridden method.
+     */
+    protected boolean onUnhandledMessage(int command, Object param) {
+        return false;
+    }
+
+    /**
+     * A Handler class for Messages from native SDL applications.
+     * It uses current Activities as target (e.g. for the title).
+     * static to prevent implicit references to enclosing object.
+     */
+    protected static class SDLCommandHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+            Context context = getContext();
+            if (context == null) {
+                Log.e(TAG, "error handling message, getContext() returned null");
+                return;
+            }
+            switch (msg.arg1) {
+            case COMMAND_CHANGE_TITLE:
+                if (context instanceof Activity) {
+                    ((Activity) context).setTitle((String)msg.obj);
+                } else {
+                    Log.e(TAG, "error handling message, getContext() returned no Activity");
+                }
+                break;
+            case COMMAND_TEXTEDIT_HIDE:
+                if (mTextEdit != null) {
+                    mTextEdit.setVisibility(View.GONE);
+
+                    InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
+                    imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0);
+                }
+                break;
+            // Urho3D: added
+            case COMMAND_FINISH:
+                if (context instanceof Activity)
+                    ((Activity) context).finish();
+                break;
+
+            default:
+                if ((context instanceof SDLActivity) && !((SDLActivity) context).onUnhandledMessage(msg.arg1, msg.obj)) {
+                    Log.e(TAG, "error handling message, command is " + msg.arg1);
+                }
+            }
+        }
+    }
+
+    // Handler for the messages
+    Handler commandHandler = new SDLCommandHandler();
+
+    // Send a message from the SDLMain thread
+    boolean sendCommand(int command, Object data) {
+        Message msg = commandHandler.obtainMessage();
+        msg.arg1 = command;
+        msg.obj = data;
+        return commandHandler.sendMessage(msg);
+    }
+
+    // C functions we call
+    // Urho3D: added parameter
+    public static native void nativeInit(String filesDir);
+    public static native void nativeLowMemory();
+    public static native void nativeQuit();
+    public static native void nativePause();
+    public static native void nativeResume();
+    public static native void onNativeResize(int x, int y, int format);
+    public static native void onNativeKeyDown(int keycode);
+    public static native void onNativeKeyUp(int keycode);
+    public static native void onNativeKeyboardFocusLost();
+    public static native void onNativeTouch(int touchDevId, int pointerFingerId,
+                                            int action, float x, 
+                                            float y, float p);
+    public static native void onNativeAccel(float x, float y, float z);
+    public static native void onNativeSurfaceChanged();
+    public static native void onNativeSurfaceDestroyed();
+    public static native void nativeFlipBuffers();
+
+    public static void flipBuffers() {
+        SDLActivity.nativeFlipBuffers();
+    }
+
+    public static boolean setActivityTitle(String title) {
+        // Called from SDLMain() thread and can't directly affect the view
+        return mSingleton.sendCommand(COMMAND_CHANGE_TITLE, title);
+    }
+
+    // Urho3D: added function
+    public static void finishActivity()
+    {
+        mSingleton.sendCommand(COMMAND_FINISH, null);
+    }
+
+    public static boolean sendMessage(int command, int param) {
+        return mSingleton.sendCommand(command, Integer.valueOf(param));
+    }
+
+    public static Context getContext() {
+        return mSingleton;
+    }
+
+    static class ShowTextInputTask implements Runnable {
+        /*
+         * This is used to regulate the pan&scan method to have some offset from
+         * the bottom edge of the input region and the top edge of an input
+         * method (soft keyboard)
+         */
+        static final int HEIGHT_PADDING = 15;
+
+        public int x, y, w, h;
+
+        public ShowTextInputTask(int x, int y, int w, int h) {
+            this.x = x;
+            this.y = y;
+            this.w = w;
+            this.h = h;
+        }
+
+        @Override
+        public void run() {
+            AbsoluteLayout.LayoutParams params = new AbsoluteLayout.LayoutParams(
+                    w, h + HEIGHT_PADDING, x, y);
+
+            if (mTextEdit == null) {
+                mTextEdit = new DummyEdit(getContext());
+
+                mLayout.addView(mTextEdit, params);
+            } else {
+                mTextEdit.setLayoutParams(params);
+            }
+
+            mTextEdit.setVisibility(View.VISIBLE);
+            mTextEdit.requestFocus();
+
+            InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+            imm.showSoftInput(mTextEdit, 0);
+        }
+    }
+
+    public static boolean showTextInput(int x, int y, int w, int h) {
+        // Transfer the task to the main thread as a Runnable
+        return mSingleton.commandHandler.post(new ShowTextInputTask(x, y, w, h));
+    }
+            
+    public static Surface getNativeSurface() {
+        return SDLActivity.mSurface.getNativeSurface();
+    }
+
+    // Audio
+    public static int audioInit(int sampleRate, boolean is16Bit, boolean isStereo, int desiredFrames) {
+        int channelConfig = isStereo ? AudioFormat.CHANNEL_CONFIGURATION_STEREO : AudioFormat.CHANNEL_CONFIGURATION_MONO;
+        int audioFormat = is16Bit ? AudioFormat.ENCODING_PCM_16BIT : AudioFormat.ENCODING_PCM_8BIT;
+        int frameSize = (isStereo ? 2 : 1) * (is16Bit ? 2 : 1);
+        
+        Log.v("SDL", "SDL audio: wanted " + (isStereo ? "stereo" : "mono") + " " + (is16Bit ? "16-bit" : "8-bit") + " " + (sampleRate / 1000f) + "kHz, " + desiredFrames + " frames buffer");
+        
+        // Let the user pick a larger buffer if they really want -- but ye
+        // gods they probably shouldn't, the minimums are horrifyingly high
+        // latency already
+        desiredFrames = Math.max(desiredFrames, (AudioTrack.getMinBufferSize(sampleRate, channelConfig, audioFormat) + frameSize - 1) / frameSize);
+        
+        if (mAudioTrack == null) {
+            mAudioTrack = new AudioTrack(AudioManager.STREAM_MUSIC, sampleRate,
+                    channelConfig, audioFormat, desiredFrames * frameSize, AudioTrack.MODE_STREAM);
+            
+            // Instantiating AudioTrack can "succeed" without an exception and the track may still be invalid
+            // Ref: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/media/java/android/media/AudioTrack.java
+            // Ref: http://developer.android.com/reference/android/media/AudioTrack.html#getState()
+            
+            if (mAudioTrack.getState() != AudioTrack.STATE_INITIALIZED) {
+                Log.e("SDL", "Failed during initialization of Audio Track");
+                mAudioTrack = null;
+                return -1;
+            }
+            
+            mAudioTrack.play();
+        }
+       
+        Log.v("SDL", "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");
+        
+        return 0;
+    }
+    
+    public static void audioWriteShortBuffer(short[] buffer) {
+        for (int i = 0; i < buffer.length; ) {
+            int result = mAudioTrack.write(buffer, i, buffer.length - i);
+            if (result > 0) {
+                i += result;
+            } else if (result == 0) {
+                try {
+                    Thread.sleep(1);
+                } catch(InterruptedException e) {
+                    // Nom nom
+                }
+            } else {
+                Log.w("SDL", "SDL audio: error return from write(short)");
+                return;
+            }
+        }
+    }
+    
+    public static void audioWriteByteBuffer(byte[] buffer) {
+        for (int i = 0; i < buffer.length; ) {
+            int result = mAudioTrack.write(buffer, i, buffer.length - i);
+            if (result > 0) {
+                i += result;
+            } else if (result == 0) {
+                try {
+                    Thread.sleep(1);
+                } catch(InterruptedException e) {
+                    // Nom nom
+                }
+            } else {
+                Log.w("SDL", "SDL audio: error return from write(byte)");
+                return;
+            }
+        }
+    }
+
+    public static void audioQuit() {
+        if (mAudioTrack != null) {
+            mAudioTrack.stop();
+            mAudioTrack = null;
+        }
+    }
+
+    // Input
+
+    /**
+     * @return an array which may be empty but is never null.
+     */
+    public static int[] inputGetInputDeviceIds(int sources) {
+        int[] ids = InputDevice.getDeviceIds();
+        int[] filtered = new int[ids.length];
+        int used = 0;
+        for (int i = 0; i < ids.length; ++i) {
+            InputDevice device = InputDevice.getDevice(ids[i]);
+            if ((device != null) && ((device.getSources() & sources) != 0)) {
+                filtered[used++] = device.getId();
+            }
+        }
+        return Arrays.copyOf(filtered, used);
+    }
+}
+
+/**
+    Simple nativeInit() runnable
+*/
+class SDLMain implements Runnable {
+    @Override
+    public void run() {
+        // Runs SDL_main()
+        // Urho3D: pass filesDir
+        SDLActivity.nativeInit(((Activity)SDLActivity.getContext()).getFilesDir().getAbsolutePath());
+        //Log.v("SDL", "SDL thread terminated");
+    }
+}
+
+
+/**
+    SDLSurface. This is what we draw on, so we need to know when it's created
+    in order to do anything useful. 
+
+    Because of this, that's where we set up the SDL thread
+*/
+class SDLSurface extends SurfaceView implements SurfaceHolder.Callback, 
+    View.OnKeyListener, View.OnTouchListener, SensorEventListener  {
+
+    // Sensors
+    protected static SensorManager mSensorManager;
+    protected static Display mDisplay;
+
+    // Keep track of the surface size to normalize touch events
+    protected static float mWidth, mHeight;
+
+    // Startup    
+    public SDLSurface(Context context) {
+        super(context);
+        getHolder().addCallback(this); 
+    
+        setFocusable(true);
+        setFocusableInTouchMode(true);
+        requestFocus();
+        setOnKeyListener(this); 
+        setOnTouchListener(this);   
+
+        mDisplay = ((WindowManager)context.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
+        mSensorManager = (SensorManager)context.getSystemService(Context.SENSOR_SERVICE);
+
+        // Some arbitrary defaults to avoid a potential division by zero
+        mWidth = 1.0f;
+        mHeight = 1.0f;
+    }
+    
+    public Surface getNativeSurface() {
+        return getHolder().getSurface();
+    }
+
+    // Called when we have a valid drawing surface
+    @Override
+    public void surfaceCreated(SurfaceHolder holder) {
+        Log.v("SDL", "surfaceCreated()");
+        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
+    }
+
+    // Called when we lose the surface
+    @Override
+    public void surfaceDestroyed(SurfaceHolder holder) {
+        Log.v("SDL", "surfaceDestroyed()");
+        // Call this *before* setting mIsSurfaceReady to 'false'
+        SDLActivity.handlePause();
+        SDLActivity.mIsSurfaceReady = false;
+        SDLActivity.onNativeSurfaceDestroyed();
+    }
+
+    // Called when the surface is resized
+    @Override
+    public void surfaceChanged(SurfaceHolder holder,
+                               int format, int width, int height) {
+        Log.v("SDL", "surfaceChanged()");
+
+        int sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565 by default
+        switch (format) {
+        case PixelFormat.A_8:
+            Log.v("SDL", "pixel format A_8");
+            break;
+        case PixelFormat.LA_88:
+            Log.v("SDL", "pixel format LA_88");
+            break;
+        case PixelFormat.L_8:
+            Log.v("SDL", "pixel format L_8");
+            break;
+        case PixelFormat.RGBA_4444:
+            Log.v("SDL", "pixel format RGBA_4444");
+            sdlFormat = 0x15421002; // SDL_PIXELFORMAT_RGBA4444
+            break;
+        case PixelFormat.RGBA_5551:
+            Log.v("SDL", "pixel format RGBA_5551");
+            sdlFormat = 0x15441002; // SDL_PIXELFORMAT_RGBA5551
+            break;
+        case PixelFormat.RGBA_8888:
+            Log.v("SDL", "pixel format RGBA_8888");
+            sdlFormat = 0x16462004; // SDL_PIXELFORMAT_RGBA8888
+            break;
+        case PixelFormat.RGBX_8888:
+            Log.v("SDL", "pixel format RGBX_8888");
+            sdlFormat = 0x16261804; // SDL_PIXELFORMAT_RGBX8888
+            break;
+        case PixelFormat.RGB_332:
+            Log.v("SDL", "pixel format RGB_332");
+            sdlFormat = 0x14110801; // SDL_PIXELFORMAT_RGB332
+            break;
+        case PixelFormat.RGB_565:
+            Log.v("SDL", "pixel format RGB_565");
+            sdlFormat = 0x15151002; // SDL_PIXELFORMAT_RGB565
+            break;
+        case PixelFormat.RGB_888:
+            Log.v("SDL", "pixel format RGB_888");
+            // Not sure this is right, maybe SDL_PIXELFORMAT_RGB24 instead?
+            sdlFormat = 0x16161804; // SDL_PIXELFORMAT_RGB888
+            break;
+        default:
+            Log.v("SDL", "pixel format unknown " + format);
+            break;
+        }
+
+        mWidth = width;
+        mHeight = height;
+        SDLActivity.onNativeResize(width, height, sdlFormat);
+        Log.v("SDL", "Window size:" + width + "x"+height);
+
+        // Set mIsSurfaceReady to 'true' *before* making a call to handleResume
+        SDLActivity.mIsSurfaceReady = true;
+        SDLActivity.onNativeSurfaceChanged();
+
+
+        if (SDLActivity.mSDLThread == null) {
+            // This is the entry point to the C app.
+            // Start up the C app thread and enable sensor input for the first time
+
+            SDLActivity.mSDLThread = new Thread(new SDLMain(), "SDLThread");
+            enableSensor(Sensor.TYPE_ACCELEROMETER, true);
+            SDLActivity.mSDLThread.start();
+        }
+    }
+
+    // unused
+    @Override
+    public void onDraw(Canvas canvas) {}
+
+
+    // Key events
+    @Override
+    public boolean onKey(View  v, int keyCode, KeyEvent event) {
+        
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            //Log.v("SDL", "key down: " + keyCode);
+            SDLActivity.onNativeKeyDown(keyCode);
+            return true;
+        }
+        else if (event.getAction() == KeyEvent.ACTION_UP) {
+            //Log.v("SDL", "key up: " + keyCode);
+            SDLActivity.onNativeKeyUp(keyCode);
+            return true;
+        }
+        
+        return false;
+    }
+
+    // Touch events
+    @Override
+    public boolean onTouch(View v, MotionEvent event) {
+             final int touchDevId = event.getDeviceId();
+             final int pointerCount = event.getPointerCount();
+             // touchId, pointerId, action, x, y, pressure
+             int actionPointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_ID_MASK) >> MotionEvent.ACTION_POINTER_ID_SHIFT; /* API 8: event.getActionIndex(); */
+             int pointerFingerId = event.getPointerId(actionPointerIndex);
+             int action = (event.getAction() & MotionEvent.ACTION_MASK); /* API 8: event.getActionMasked(); */
+
+             float x = event.getX(actionPointerIndex) / mWidth;
+             float y = event.getY(actionPointerIndex) / mHeight;
+             float p = event.getPressure(actionPointerIndex);
+
+             if (action == MotionEvent.ACTION_MOVE && pointerCount > 1) {
+                // TODO send motion to every pointer if its position has
+                // changed since prev event.
+                for (int i = 0; i < pointerCount; i++) {
+                    pointerFingerId = event.getPointerId(i);
+                    x = event.getX(i) / mWidth;
+                    y = event.getY(i) / mHeight;
+                    p = event.getPressure(i);
+                    SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
+                }
+             } else {
+                SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
+             }
+      return true;
+   } 
+
+    // Sensor events
+    public void enableSensor(int sensortype, boolean enabled) {
+        // TODO: This uses getDefaultSensor - what if we have >1 accels?
+        if (enabled) {
+            mSensorManager.registerListener(this, 
+                            mSensorManager.getDefaultSensor(sensortype), 
+                            SensorManager.SENSOR_DELAY_GAME, null);
+        } else {
+            mSensorManager.unregisterListener(this, 
+                            mSensorManager.getDefaultSensor(sensortype));
+        }
+    }
+    
+    @Override
+    public void onAccuracyChanged(Sensor sensor, int accuracy) {
+        // TODO
+    }
+
+    @Override
+    public void onSensorChanged(SensorEvent event) {
+        if (event.sensor.getType() == Sensor.TYPE_ACCELEROMETER) {
+            float x, y;
+            switch (mDisplay.getRotation()) {
+                case Surface.ROTATION_90:
+                    x = -event.values[1];
+                    y = event.values[0];
+                    break;
+                case Surface.ROTATION_270:
+                    x = event.values[1];
+                    y = -event.values[0];
+                    break;
+                case Surface.ROTATION_180:
+                    x = -event.values[1];
+                    y = -event.values[0];
+                    break;
+                default:
+                    x = event.values[0];
+                    y = event.values[1];
+                    break;
+            }
+            SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
+                                      y / SensorManager.GRAVITY_EARTH,
+                                      event.values[2] / SensorManager.GRAVITY_EARTH - 1);
+        }
+    }
+    
+}
+
+/* This is a fake invisible editor view that receives the input and defines the
+ * pan&scan region
+ */
+class DummyEdit extends View implements View.OnKeyListener {
+    InputConnection ic;
+
+    public DummyEdit(Context context) {
+        super(context);
+        setFocusableInTouchMode(true);
+        setFocusable(true);
+        setOnKeyListener(this);
+    }
+
+    @Override
+    public boolean onCheckIsTextEditor() {
+        return true;
+    }
+
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+
+        // This handles the hardware keyboard input
+        if (event.isPrintingKey()) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
+            }
+            return true;
+        }
+
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            SDLActivity.onNativeKeyDown(keyCode);
+            return true;
+        } else if (event.getAction() == KeyEvent.ACTION_UP) {
+            SDLActivity.onNativeKeyUp(keyCode);
+            return true;
+        }
+
+        return false;
+    }
+        
+    //
+    @Override
+    public boolean onKeyPreIme (int keyCode, KeyEvent event) {
+        // As seen on StackOverflow: http://stackoverflow.com/questions/7634346/keyboard-hide-event
+        // FIXME: Discussion at http://bugzilla.libsdl.org/show_bug.cgi?id=1639
+        // FIXME: This is not a 100% effective solution to the problem of detecting if the keyboard is showing or not
+        // FIXME: A more effective solution would be to change our Layout from AbsoluteLayout to Relative or Linear
+        // FIXME: And determine the keyboard presence doing this: http://stackoverflow.com/questions/2150078/how-to-check-visibility-of-software-keyboard-in-android
+        // FIXME: An even more effective way would be if Android provided this out of the box, but where would the fun be in that :)
+        if (event.getAction()==KeyEvent.ACTION_UP && keyCode == KeyEvent.KEYCODE_BACK) {
+            if (SDLActivity.mTextEdit != null && SDLActivity.mTextEdit.getVisibility() == View.VISIBLE) {
+                SDLActivity.onNativeKeyboardFocusLost();
+            }
+        }
+        return super.onKeyPreIme(keyCode, event);
+    }
+
+    @Override
+    public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+        ic = new SDLInputConnection(this, true);
+
+        outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
+                | 33554432 /* API 11: EditorInfo.IME_FLAG_NO_FULLSCREEN */;
+
+        return ic;
+    }
+}
+
+class SDLInputConnection extends BaseInputConnection {
+
+    public SDLInputConnection(View targetView, boolean fullEditor) {
+        super(targetView, fullEditor);
+
+    }
+
+    @Override
+    public boolean sendKeyEvent(KeyEvent event) {
+
+        /*
+         * This handles the keycodes from soft keyboard (and IME-translated
+         * input from hardkeyboard)
+         */
+        int keyCode = event.getKeyCode();
+        if (event.getAction() == KeyEvent.ACTION_DOWN) {
+            if (event.isPrintingKey()) {
+                commitText(String.valueOf((char) event.getUnicodeChar()), 1);
+            }
+            SDLActivity.onNativeKeyDown(keyCode);
+            return true;
+        } else if (event.getAction() == KeyEvent.ACTION_UP) {
+
+            SDLActivity.onNativeKeyUp(keyCode);
+            return true;
+        }
+        return super.sendKeyEvent(event);
+    }
+
+    @Override
+    public boolean commitText(CharSequence text, int newCursorPosition) {
+
+        nativeCommitText(text.toString(), newCursorPosition);
+
+        return super.commitText(text, newCursorPosition);
+    }
+
+    @Override
+    public boolean setComposingText(CharSequence text, int newCursorPosition) {
+
+        nativeSetComposingText(text.toString(), newCursorPosition);
+
+        return super.setComposingText(text, newCursorPosition);
+    }
+
+    public native void nativeCommitText(String text, int newCursorPosition);
+
+    public native void nativeSetComposingText(String text, int newCursorPosition);
+
+}
+

+ 1 - 1
Source/CMake/Modules/Urho3D-CMake-magic.cmake

@@ -477,7 +477,7 @@ macro (define_dependency_libs TARGET)
         elseif (APPLE)
             list (APPEND LINK_LIBS_ONLY dl pthread)
         elseif (ANDROID)
-            list (APPEND LINK_LIBS_ONLY dl log)
+            list (APPEND LINK_LIBS_ONLY dl log android)
         else ()
             # Linux
             list (APPEND LINK_LIBS_ONLY dl pthread rt)

+ 1 - 1
Source/CMake/Toolchains/android.toolchain.cmake

@@ -340,7 +340,7 @@ set( ANDROID_SUPPORTED_ABIS_arm "armeabi-v7a;armeabi;armeabi-v7a with NEON;armea
 set( ANDROID_SUPPORTED_ABIS_x86 "x86" )
 set( ANDROID_SUPPORTED_ABIS_mipsel "mips" )
 
-set( ANDROID_DEFAULT_NDK_API_LEVEL 8 )
+set( ANDROID_DEFAULT_NDK_API_LEVEL 9 )
 set( ANDROID_DEFAULT_NDK_API_LEVEL_x86 9 )
 set( ANDROID_DEFAULT_NDK_API_LEVEL_mips 9 )
 

+ 16 - 5
Source/Engine/Graphics/OpenGL/OGLGraphics.cpp

@@ -533,7 +533,7 @@ void Graphics::EndFrame()
     SDL_GL_SwapWindow(impl_->window_);
     
     // Clean up FBO's that have not been used for a long time, and too large scratch buffers
-    CleanupFramebuffers(false);
+    CleanupFramebuffers();
     CleanupScratchBuffers();
 }
 
@@ -2146,6 +2146,17 @@ void Graphics::Restore()
     if (!impl_->window_)
         return;
     
+    #ifdef ANDROID
+    // On Android the context may be lost behind the scenes as the application is minimized
+    if (impl_->context_ && !SDL_GL_GetCurrentContext())
+    {
+        impl_->context_ = 0;
+        // Mark GPU objects lost without a current context. In this case they just mark their internal state lost
+        // but do not perform OpenGL commands to delete the GL objects
+        Release(false, false);
+    }
+    #endif
+    
     // Ensure first that the context exists
     if (!impl_->context_)
     {
@@ -2621,15 +2632,15 @@ bool Graphics::CheckFramebuffer()
     return glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT) == GL_FRAMEBUFFER_COMPLETE_EXT;
 }
 
-void Graphics::CleanupFramebuffers(bool contextLost)
+void Graphics::CleanupFramebuffers(bool force)
 {
-    if (!contextLost)
+    if (!IsDeviceLost())
     {
         for (HashMap<unsigned long long, FrameBufferObject>::Iterator i = impl_->frameBuffers_.Begin();
             i != impl_->frameBuffers_.End();)
         {
-            if (i->second_.fbo_ != impl_->boundFbo_ && i->second_.useTimer_.GetMSec(false) >
-                MAX_FRAMEBUFFER_AGE)
+            if (i->second_.fbo_ != impl_->boundFbo_ && (force || i->second_.useTimer_.GetMSec(false) >
+                MAX_FRAMEBUFFER_AGE))
             {
                 glDeleteFramebuffersEXT(1, &i->second_.fbo_);
                 i = impl_->frameBuffers_.Erase(i);

+ 1 - 1
Source/Engine/Graphics/OpenGL/OGLGraphics.h

@@ -418,7 +418,7 @@ private:
     /// Check FBO completeness.
     bool CheckFramebuffer();
     /// Cleanup unused and unbound FBO's.
-    void CleanupFramebuffers(bool contextLost);
+    void CleanupFramebuffers(bool force = false);
     /// Reset cached rendering state.
     void ResetCachedState();
     /// Initialize texture unit mappings.

+ 8 - 4
Source/Engine/Graphics/OpenGL/OGLIndexBuffer.cpp

@@ -75,13 +75,17 @@ void IndexBuffer::Release()
     
     if (object_)
     {
-        if (!graphics_ || graphics_->IsDeviceLost())
+        if (!graphics_)
             return;
         
-        if (graphics_->GetIndexBuffer() == this)
-            graphics_->SetIndexBuffer(0);
+        if (!graphics_->IsDeviceLost())
+        {
+            if (graphics_->GetIndexBuffer() == this)
+                graphics_->SetIndexBuffer(0);
+            
+            glDeleteBuffers(1, &object_);
+        }
         
-        glDeleteBuffers(1, &object_);
         object_ = 0;
     }
 }

+ 16 - 14
Source/Engine/Graphics/OpenGL/OGLRenderSurface.cpp

@@ -157,23 +157,25 @@ void RenderSurface::Release()
     if (!graphics)
         return;
     
-    for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
+    if (!graphics->IsDeviceLost())
     {
-        if (graphics->GetRenderTarget(i) == this)
-            graphics->ResetRenderTarget(i);
+        for (unsigned i = 0; i < MAX_RENDERTARGETS; ++i)
+        {
+            if (graphics->GetRenderTarget(i) == this)
+                graphics->ResetRenderTarget(i);
+        }
+        
+        if (graphics->GetDepthStencil() == this)
+            graphics->ResetDepthStencil();
+        
+        // Clean up also from non-active FBOs
+        graphics->CleanupRenderSurface(this);
+        
+        if (renderBuffer_)
+            glDeleteRenderbuffersEXT(1, &renderBuffer_);
     }
     
-    if (graphics->GetDepthStencil() == this)
-        graphics->ResetDepthStencil();
-    
-    // Clean up also from non-active FBOs
-    graphics->CleanupRenderSurface(this);
-    
-    if (renderBuffer_)
-    {
-        glDeleteRenderbuffersEXT(1, &renderBuffer_);
-        renderBuffer_ = 0;
-    }
+    renderBuffer_ = 0;
 }
 
 int RenderSurface::GetWidth() const

+ 11 - 7
Source/Engine/Graphics/OpenGL/OGLShaderProgram.cpp

@@ -64,17 +64,21 @@ void ShaderProgram::Release()
         if (!graphics_)
             return;
         
-        for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
-            useTextureUnit_[i] = false;
-        shaderParameters_.Clear();
-        
-        if (graphics_->GetShaderProgram() == this)
-            graphics_->SetShaders(0, 0);
+        if (!graphics_->IsDeviceLost())
+        {
+            if (graphics_->GetShaderProgram() == this)
+                graphics_->SetShaders(0, 0);
+            
+            glDeleteProgram(object_);
+        }
         
-        glDeleteProgram(object_);
         object_ = 0;
         linked_ = false;
         linkerOutput_.Clear();
+        shaderParameters_.Clear();
+        
+        for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
+            useTextureUnit_[i] = false;
     }
 }
 

+ 13 - 9
Source/Engine/Graphics/OpenGL/OGLShaderVariation.cpp

@@ -63,18 +63,22 @@ void ShaderVariation::Release()
         if (!graphics_)
             return;
         
-        if (shaderType_ == VS)
+        if (!graphics_->IsDeviceLost())
         {
-            if (graphics_->GetVertexShader() == this)
-                graphics_->SetShaders(0, 0);
-        }
-        else
-        {
-            if (graphics_->GetPixelShader() == this)
-                graphics_->SetShaders(0, 0);
+            if (shaderType_ == VS)
+            {
+                if (graphics_->GetVertexShader() == this)
+                    graphics_->SetShaders(0, 0);
+            }
+            else
+            {
+                if (graphics_->GetPixelShader() == this)
+                    graphics_->SetShaders(0, 0);
+            }
+            
+            glDeleteShader(object_);
         }
         
-        glDeleteShader(object_);
         object_ = 0;
         compiled_ = false;
         compilerOutput_.Clear();

+ 9 - 5
Source/Engine/Graphics/OpenGL/OGLTexture2D.cpp

@@ -117,19 +117,23 @@ void Texture2D::Release()
 {
     if (object_)
     {
-        if (!graphics_ || graphics_->IsDeviceLost())
+        if (!graphics_)
             return;
         
-        for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
+        if (!graphics_->IsDeviceLost())
         {
-            if (graphics_->GetTexture(i) == this)
-                graphics_->SetTexture(i, 0);
+            for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
+            {
+                if (graphics_->GetTexture(i) == this)
+                    graphics_->SetTexture(i, 0);
+            }
+            
+            glDeleteTextures(1, &object_);
         }
         
         if (renderSurface_)
             renderSurface_->Release();
         
-        glDeleteTextures(1, &object_);
         object_ = 0;
     }
     else

+ 9 - 5
Source/Engine/Graphics/OpenGL/OGLTextureCube.cpp

@@ -105,13 +105,18 @@ void TextureCube::Release()
 {
     if (object_)
     {
-        if (!graphics_ || graphics_->IsDeviceLost())
+        if (!graphics_)
             return;
         
-        for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
+        if (!graphics_->IsDeviceLost())
         {
-            if (graphics_->GetTexture(i) == this)
-                graphics_->SetTexture(i, 0);
+            for (unsigned i = 0; i < MAX_TEXTURE_UNITS; ++i)
+            {
+                if (graphics_->GetTexture(i) == this)
+                    graphics_->SetTexture(i, 0);
+            }
+            
+            glDeleteTextures(1, &object_);
         }
         
         for (unsigned i = 0; i < MAX_CUBEMAP_FACES; ++i)
@@ -120,7 +125,6 @@ void TextureCube::Release()
                 renderSurfaces_[i]->Release();
         }
         
-        glDeleteTextures(1, &object_);
         object_ = 0;
     }
 }

+ 9 - 5
Source/Engine/Graphics/OpenGL/OGLVertexBuffer.cpp

@@ -144,16 +144,20 @@ void VertexBuffer::Release()
     
     if (object_)
     {
-        if (!graphics_ || graphics_->IsDeviceLost())
+        if (!graphics_)
             return;
         
-        for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
+        if (!graphics_->IsDeviceLost())
         {
-            if (graphics_->GetVertexBuffer(i) == this)
-                graphics_->SetVertexBuffer(0);
+            for (unsigned i = 0; i < MAX_VERTEX_STREAMS; ++i)
+            {
+                if (graphics_->GetVertexBuffer(i) == this)
+                    graphics_->SetVertexBuffer(0);
+            }
+            
+            glDeleteBuffers(1, &object_);
         }
         
-        glDeleteBuffers(1, &object_);
         object_ = 0;
     }
 }

+ 14 - 16
Source/Engine/Input/Input.cpp

@@ -180,7 +180,7 @@ void Input::Update()
 
 void Input::SetMouseVisible(bool enable)
 {
-    // Urho3D implementation of SDL Raspberry Pi "video driver" does not have OS mouse support, so no-op
+    // SDL Raspberry Pi "video driver" does not have proper OS mouse support yet, so no-op for now
     #ifndef RASPI
     if (enable != mouseVisible_)
     {
@@ -238,7 +238,7 @@ bool Input::OpenJoystick(unsigned index)
         // Map SDL joystick index to internal index (which starts at 0)
         int sdl_joy_instance_id = SDL_JoystickInstanceID(joystick);
         joystickIDMap_[sdl_joy_instance_id] = index;
-        
+
         JoystickState& state = joysticks_[index];
         state.joystick_ = joystick;
         state.buttons_.Resize(SDL_JoystickNumButtons(joystick));
@@ -671,6 +671,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
         break;
 
     case SDL_FINGERDOWN:
+        if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
         {
             int touchID = evt.tfinger.fingerId & 0x7ffffff;
             TouchState& state = touches_[touchID];
@@ -693,6 +694,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
         break;
 
     case SDL_FINGERUP:
+        if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
         {
             int touchID = evt.tfinger.fingerId & 0x7ffffff;
             TouchState& state = touches_[touchID];
@@ -713,6 +715,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
         break;
 
     case SDL_FINGERMOTION:
+        if (evt.tfinger.touchId != SDL_TOUCH_MOUSEID)
         {
             int touchID = evt.tfinger.fingerId & 0x7ffffff;
             TouchState& state = touches_[touchID];
@@ -742,11 +745,11 @@ void Input::HandleSDLEvent(void* sdlEvent)
 
             unsigned button = evt.jbutton.button;
             unsigned joystickIndex = joystickIDMap_[evt.jbutton.which];
-            
+
             VariantMap eventData;
             eventData[P_JOYSTICK] = joystickIndex;
             eventData[P_BUTTON] = button;
-            
+
             if (joystickIndex < joysticks_.Size() && button < joysticks_[joystickIndex].buttons_.Size()) {
                 joysticks_[joystickIndex].buttons_[button] = true;
                 joysticks_[joystickIndex].buttonPress_[button] = true;
@@ -761,7 +764,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
 
             unsigned button = evt.jbutton.button;
             unsigned joystickIndex = joystickIDMap_[evt.jbutton.which];
-            
+
             VariantMap eventData;
             eventData[P_JOYSTICK] = joystickIndex;
             eventData[P_BUTTON] = button;
@@ -776,7 +779,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
     case SDL_JOYAXISMOTION:
         {
             using namespace JoystickAxisMove;
-            
+
             unsigned joystickIndex = joystickIDMap_[evt.jaxis.which];
 
             VariantMap eventData;
@@ -796,7 +799,7 @@ void Input::HandleSDLEvent(void* sdlEvent)
     case SDL_JOYHATMOTION:
         {
             using namespace JoystickHatMove;
-            
+
             unsigned joystickIndex = joystickIDMap_[evt.jaxis.which];
 
             VariantMap eventData;
@@ -834,13 +837,8 @@ void Input::HandleSDLEvent(void* sdlEvent)
                 break;
 
             #ifdef ANDROID
-            case SDL_WINDOWEVENT_FOCUS_LOST:
-                // Mark GPU objects lost
-                graphics_->Release(false, false);
-                break;
-
             case SDL_WINDOWEVENT_FOCUS_GAINED:
-                // Restore GPU objects
+                // Restore GPU objects to the new GL context
                 graphics_->Restore();
                 break;
             #endif
@@ -855,15 +853,15 @@ void Input::HandleSDLEvent(void* sdlEvent)
     case SDL_DROPFILE:
         {
             using namespace DropFile;
-            
+
             VariantMap eventData;
             eventData[P_FILENAME] = GetInternalPath(String(evt.drop.file));
             SDL_free(evt.drop.file);
-            
+
             SendEvent(E_DROPFILE, eventData);
         }
         break;
-        
+
     case SDL_QUIT:
         SendEvent(E_EXITREQUESTED);
         break;

+ 17 - 18
Source/Engine/UI/Cursor.cpp

@@ -102,7 +102,7 @@ void Cursor::SetUseSystemShapes(bool enable)
     if (enable != useSystemShapes_)
     {
         useSystemShapes_ = enable;
-        
+
         // Reapply current shape
         ApplyShape();
     }
@@ -115,13 +115,13 @@ void Cursor::DefineShape(CursorShape shape, Image* image, const IntRect& imageRe
         LOGERROR("Shape index out of bounds, can not define cursor shape");
         return;
     }
-    
+
     if (!image)
         return;
-    
+
     ResourceCache* cache = GetSubsystem<ResourceCache>();
     CursorShapeInfo& info = shapeInfos_[shape];
-    
+
     // Prefer to get the texture with same name from cache to prevent creating several copies of the texture
     if (cache->Exists(image->GetName()))
         info.texture_ = cache->GetResource<Texture2D>(image->GetName());
@@ -131,11 +131,11 @@ void Cursor::DefineShape(CursorShape shape, Image* image, const IntRect& imageRe
         texture->Load(SharedPtr<Image>(image));
         info.texture_ = texture;
     }
-    
+
     info.image_ = image;
     info.imageRect_ = imageRect;
     info.hotSpot_ = hotSpot;
-    
+
     // Remove existing SDL cursor
     if (info.osCursor_)
     {
@@ -236,12 +236,20 @@ void Cursor::ApplyShape()
             SDL_FreeCursor(info.osCursor_);
             info.osCursor_ = 0;
         }
-        
+
         // Create SDL cursor now if necessary
         if (!info.osCursor_)
         {
+            // Create a system default shape
+            if (useSystemShapes_)
+            {
+                info.osCursor_ = SDL_CreateSystemCursor((SDL_SystemCursor)osCursorLookup[shape_]);
+                info.systemDefined_ = true;
+                if (!info.osCursor_)
+                    LOGERROR("Could not create system cursor");
+            }
             // Create from image
-            if (!useSystemShapes_ && info.image_)
+            else if (info.image_)
             {
                 unsigned comp = info.image_->GetComponents();
                 int imageWidth = info.image_->GetWidth();
@@ -272,17 +280,8 @@ void Cursor::ApplyShape()
                     SDL_FreeSurface(surface);
                 }
             }
-            
-            // Create a system default shape
-            if (useSystemShapes_)
-            {
-                info.osCursor_ = SDL_CreateSystemCursor((SDL_SystemCursor)osCursorLookup[shape_]);
-                info.systemDefined_ = true;
-                if (!info.osCursor_)
-                    LOGERROR("Could not create system cursor");
-            }
         }
-        
+
         if (info.osCursor_)
             SDL_SetCursor(info.osCursor_);
     }

+ 6 - 4
Source/ThirdParty/SDL/CMakeLists.txt

@@ -29,26 +29,28 @@ if (WIN32)
     file (GLOB SYS_C_FILES
         src/audio/directsound/*.c src/haptic/${HAPTIC_DRIVER}/*.c src/joystick/windows/*.c src/core/windows/*.c src/loadso/windows/*.c
         src/power/windows/*.c src/thread/windows/*.c src/thread/generic/SDL_syscond.c src/timer/windows/*.c src/video/windows/*.c src/joystick/dummy/*.c
+        src/filesystem/windows/*.c
     )
 elseif (IOS)
     file (GLOB SYS_C_FILES
         src/audio/coreaudio/*.c src/file/cocoa/*.m src/joystick/iphoneos/*.m src/loadso/dlopen/*.c src/power/uikit/*.m
         src/thread/pthread/*.c src/timer/unix/*.c src/video/uikit/*.m src/video/uikit/*.c src/haptic/dummy/*.c
+        src/filesystem/cocoa/*.m
     )
 elseif (APPLE)
     file (GLOB SYS_C_FILES
         src/audio/coreaudio/*.c src/file/cocoa/*.m src/haptic/darwin/*.c src/joystick/darwin/*.c src/loadso/dlopen/*.c
-        src/power/macosx/*.c src/thread/pthread/*.c src/timer/unix/*.c src/video/cocoa/*.m
+        src/power/macosx/*.c src/thread/pthread/*.c src/timer/unix/*.c src/video/cocoa/*.m src/filesystem/cocoa/*.m
     )
 elseif (ANDROID)
     file (GLOB SYS_C_FILES
         src/audio/android/*.c src/core/android/*.c src/joystick/android/*.c src/loadso/dlopen/*.c src/power/android/*.c
-        src/thread/pthread/*.c src/timer/unix/*.c src/video/android/*.c src/haptic/dummy/*.c
+        src/thread/pthread/*.c src/timer/unix/*.c src/video/android/*.c src/haptic/dummy/*.c src/filesystem/dummy/*.c
     )
 else ()
     # On Linux, make sure development libraries exist, and use their include file directories  
     if (RASPI)
-        file (GLOB VIDEO_DRIVER_C_FILES src/video/raspi/*.c)
+        file (GLOB VIDEO_DRIVER_C_FILES src/video/raspberry/*.c src/core/linux/*.c src/input/evdev/*.c)
     else ()
         find_package (OpenGL REQUIRED)
         include_directories (${OpenGL_INCLUDE_DIRS})
@@ -92,7 +94,7 @@ else ()
 
     file (GLOB SYS_C_FILES
         src/audio/alsa/*.c src/audio/dma/*.c src/audio/dsp/*.c src/haptic/linux/*.c src/joystick/linux/*.c src/loadso/dlopen/*.c
-        src/power/linux/*.c src/thread/pthread/*.c src/timer/unix/*.c
+        src/power/linux/*.c src/thread/pthread/*.c src/timer/unix/*.c src/filesystem/unix/*.c
     )
     set (SYS_C_FILES ${SYS_C_FILES} ${VIDEO_DRIVER_C_FILES})
 endif ()

+ 2 - 0
Source/ThirdParty/SDL/CREDITS.txt

@@ -21,6 +21,8 @@ Thanks to everyone who made this possible, including:
 
 * Pierre-Loup Griffais for his deep knowledge of OpenGL drivers.
  
+* Julian Winter for the SDL 2.0 website.
+
 * Sheena Smith for many months of great work on the SDL wiki creating the API documentation and style guides.
 
 * Paul Hunkin for his port of SDL to Android during the Google Summer of Code 2010.

+ 0 - 5
Source/ThirdParty/SDL/TODO.txt

@@ -1,15 +1,10 @@
 Future work roadmap:
  * http://wiki.libsdl.org/moin.cgi/Roadmap
 
- * See why windows are being rearranged.  Is the shield window not up?
- * Add __WINDOWS__ in addition to __WIN32__
- * Write test for fullscreen gamma to check X11 colormap handling
-
  * Check 1.2 revisions:
 	3554 - Need to resolve semantics for locking keys on different platforms
 	4874 - Do we want screen rotation?  At what level?
 	4974 - Windows file code needs to convert UTF-8 to Unicode, but we don't need to tap dance for Windows 95/98
-	4484, 4485 - Verify that SDL's Windows keyboard handling works correctly
 	4865 - See if this is still needed (mouse coordinate clamping)
 	4866 - See if this is still needed (blocking window repositioning)
 

+ 57 - 0
Source/ThirdParty/SDL/WhatsNew.txt

@@ -0,0 +1,57 @@
+
+This is a list of major changes in SDL's version history.
+
+---------------------------------------------------------------------------
+2.0.1:
+---------------------------------------------------------------------------
+
+General:
+* Added an API to get common filesystem paths in SDL_filesystem.h:
+    SDL_GetBasePath(), SDL_GetPrefPath()
+* Added an API to do optimized YV12 and IYUV texture updates:
+    SDL_UpdateYUVTexture()
+* Added an API to get the amount of RAM on the system:
+    SDL_GetSystemRAM()
+* Added a macro to perform timestamp comparisons with SDL_GetTicks():
+    SDL_TICKS_PASSED()
+* Dramatically improved OpenGL ES 2.0 rendering performance
+* Added OpenGL attribute SDL_GL_FRAMEBUFFER_SRGB_CAPABLE
+
+Windows:
+* Created a static library configuration for the Visual Studio 2010 project
+* Added a hint to create the Direct3D device with support for multi-threading:
+    SDL_HINT_RENDER_DIRECT3D_THREADSAFE
+* Added a function to get the D3D9 adapter index for a display:
+    SDL_Direct3D9GetAdapterIndex()
+* Added a function to get the D3D9 device for a D3D9 renderer:
+    SDL_RenderGetD3D9Device()
+* Fixed building SDL with the mingw32 toolchain (mingw-w64 is preferred)
+* Fixed crash when using two XInput controllers at the same time
+* Fixed detecting a mixture of XInput and DirectInput controllers
+* Fixed clearing a D3D render target larger than the window
+* Improved support for format specifiers in SDL_snprintf()
+
+Mac OS X:
+* Added support for retina displays:
+  Create your window with the SDL_WINDOW_ALLOW_HIGHDPI flag, and then use SDL_GL_GetDrawableSize() to find the actual drawable size. You are responsible for scaling mouse and drawing coordinates appropriately.
+* Fixed mouse warping in fullscreen mode
+* Right mouse click is emulated by holding the Ctrl key while left clicking
+
+Linux:
+* Fixed float audio support with the PulseAudio driver
+* Fixed missing line endpoints in the OpenGL renderer on some drivers
+* X11 symbols are no longer defined to avoid collisions when linking statically
+
+iOS:
+* Fixed status bar visibility on iOS 7
+* Flipped the accelerometer Y axis to match expected values
+
+Android:
+IMPORTANT: You MUST get the updated SDLActivity.java to match C code
+* Moved EGL initialization to native code 
+* Fixed the accelerometer axis rotation relative to the device rotation
+* Fixed race conditions when handling the EGL context on pause/resume
+* Touch devices are available for enumeration immediately after init
+
+Raspberry Pi:
+* Added support for the Raspberry Pi, see README-raspberrypi.txt for details

+ 15 - 12
Source/ThirdParty/SDL/include/SDL.h

@@ -32,18 +32,20 @@
  *
  *  \section intro_sec Introduction
  *
- *  This is the Simple DirectMedia Layer, a general API that provides low
- *  level access to audio, keyboard, mouse, joystick, 3D hardware via OpenGL,
- *  and 2D framebuffer across multiple platforms.
+ *  Simple DirectMedia Layer is a cross-platform development library designed
+ *  to provide low level access to audio, keyboard, mouse, joystick, and
+ *  graphics hardware via OpenGL and Direct3D. It is used by video playback
+ *  software, emulators, and popular games including Valve's award winning
+ *  catalog and many Humble Bundle games.
  *
- *  SDL is written in C, but works with C++ natively, and has bindings to
- *  several other languages, including Ada, C#, Eiffel, Erlang, Euphoria,
- *  Guile, Haskell, Java, Lisp, Lua, ML, Objective C, Pascal, Perl, PHP,
- *  Pike, Pliant, Python, Ruby, and Smalltalk.
+ *  SDL officially supports Windows, Mac OS X, Linux, iOS, and Android.
+ *  Support for other platforms may be found in the source code.
  *
- *  This library is distributed under the zlib license, which can be
- *  found in the file  "COPYING".  This license allows you to use SDL
- *  freely for any purpose as long as you retain the copyright notice.
+ *  SDL is written in C, works natively with C++, and there are bindings 
+ *  available for several other languages, including C# and Python.
+ *
+ *  This library is distributed under the zlib license, which can be found
+ *  in the file "COPYING.txt".
  *
  *  The best way to learn how to use SDL is to check out the header files in
  *  the "include" subdirectory and the programs in the "test" subdirectory.
@@ -72,6 +74,7 @@
 #include "SDL_endian.h"
 #include "SDL_error.h"
 #include "SDL_events.h"
+#include "SDL_filesystem.h"
 #include "SDL_joystick.h"
 #include "SDL_gamecontroller.h"
 #include "SDL_haptic.h"
@@ -103,7 +106,7 @@ extern "C" {
  *  These are the flags which may be passed to SDL_Init().  You should
  *  specify the subsystems which you will be using in your application.
  */
-/*@{*/
+/* @{ */
 #define SDL_INIT_TIMER          0x00000001
 #define SDL_INIT_AUDIO          0x00000010
 #define SDL_INIT_VIDEO          0x00000020  /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
@@ -116,7 +119,7 @@ extern "C" {
                 SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
                 SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER \
             )
-/*@}*/
+/* @} */
 
 /**
  *  This function initializes  the subsystems specified by \c flags

+ 11 - 2
Source/ThirdParty/SDL/include/SDL_assert.h

@@ -86,8 +86,14 @@ This also solves the problem of...
 disable assertions.
 */
 
+#ifdef _MSC_VER  /* stupid /W4 warnings. */
+#define SDL_NULL_WHILE_LOOP_CONDITION (-1 == __LINE__)
+#else
+#define SDL_NULL_WHILE_LOOP_CONDITION (0)
+#endif
+
 #define SDL_disabled_assert(condition) \
-    do { (void) sizeof ((condition)); } while (0)
+    do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION)
 
 typedef enum
 {
@@ -140,7 +146,7 @@ extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,
             } \
             break; /* not retrying. */ \
         } \
-    } while (0)
+    } while (SDL_NULL_WHILE_LOOP_CONDITION)
 
 #endif  /* enabled assertions support code */
 
@@ -165,6 +171,9 @@ extern DECLSPEC SDL_assert_state SDLCALL SDL_ReportAssertion(SDL_assert_data *,
 #   error Unknown assertion level.
 #endif
 
+/* this assertion is never disabled at any level. */
+#define SDL_assert_always(condition) SDL_enabled_assert(condition)
+
 
 typedef SDL_assert_state (SDLCALL *SDL_AssertionHandler)(
                                  const SDL_assert_data* data, void* userdata);

+ 2 - 2
Source/ThirdParty/SDL/include/SDL_atomic.h

@@ -91,7 +91,7 @@ extern "C" {
  * The spin lock functions and type are required and can not be
  * emulated because they are used in the atomic emulation code.
  */
-/*@{*/
+/* @{ */
 
 typedef int SDL_SpinLock;
 
@@ -118,7 +118,7 @@ extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock);
  */
 extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
 
-/*@}*//*SDL AtomicLock*/
+/* @} *//* SDL AtomicLock */
 
 
 /**

+ 22 - 22
Source/ThirdParty/SDL/include/SDL_audio.h

@@ -66,7 +66,7 @@ typedef Uint16 SDL_AudioFormat;
 /**
  *  \name Audio flags
  */
-/*@{*/
+/* @{ */
 
 #define SDL_AUDIO_MASK_BITSIZE       (0xFF)
 #define SDL_AUDIO_MASK_DATATYPE      (1<<8)
@@ -85,7 +85,7 @@ typedef Uint16 SDL_AudioFormat;
  *
  *  Defaults to LSB byte order.
  */
-/*@{*/
+/* @{ */
 #define AUDIO_U8        0x0008  /**< Unsigned 8-bit samples */
 #define AUDIO_S8        0x8008  /**< Signed 8-bit samples */
 #define AUDIO_U16LSB    0x0010  /**< Unsigned 16-bit samples */
@@ -94,30 +94,30 @@ typedef Uint16 SDL_AudioFormat;
 #define AUDIO_S16MSB    0x9010  /**< As above, but big-endian byte order */
 #define AUDIO_U16       AUDIO_U16LSB
 #define AUDIO_S16       AUDIO_S16LSB
-/*@}*/
+/* @} */
 
 /**
  *  \name int32 support
  */
-/*@{*/
+/* @{ */
 #define AUDIO_S32LSB    0x8020  /**< 32-bit integer samples */
 #define AUDIO_S32MSB    0x9020  /**< As above, but big-endian byte order */
 #define AUDIO_S32       AUDIO_S32LSB
-/*@}*/
+/* @} */
 
 /**
  *  \name float32 support
  */
-/*@{*/
+/* @{ */
 #define AUDIO_F32LSB    0x8120  /**< 32-bit floating point samples */
 #define AUDIO_F32MSB    0x9120  /**< As above, but big-endian byte order */
 #define AUDIO_F32       AUDIO_F32LSB
-/*@}*/
+/* @} */
 
 /**
  *  \name Native audio byte ordering
  */
-/*@{*/
+/* @{ */
 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
 #define AUDIO_U16SYS    AUDIO_U16LSB
 #define AUDIO_S16SYS    AUDIO_S16LSB
@@ -129,21 +129,21 @@ typedef Uint16 SDL_AudioFormat;
 #define AUDIO_S32SYS    AUDIO_S32MSB
 #define AUDIO_F32SYS    AUDIO_F32MSB
 #endif
-/*@}*/
+/* @} */
 
 /**
  *  \name Allow change flags
  *
  *  Which audio format changes are allowed when opening a device.
  */
-/*@{*/
+/* @{ */
 #define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE    0x00000001
 #define SDL_AUDIO_ALLOW_FORMAT_CHANGE       0x00000002
 #define SDL_AUDIO_ALLOW_CHANNELS_CHANGE     0x00000004
 #define SDL_AUDIO_ALLOW_ANY_CHANGE          (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE)
-/*@}*/
+/* @} */
 
-/*@}*//*Audio flags*/
+/* @} *//* Audio flags */
 
 /**
  *  This function is called when the audio device needs more data.
@@ -218,10 +218,10 @@ typedef struct SDL_AudioCVT
  *  These functions return the list of built in audio drivers, in the
  *  order that they are normally initialized by default.
  */
-/*@{*/
+/* @{ */
 extern DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void);
 extern DECLSPEC const char *SDLCALL SDL_GetAudioDriver(int index);
-/*@}*/
+/* @} */
 
 /**
  *  \name Initialization and cleanup
@@ -230,10 +230,10 @@ extern DECLSPEC const char *SDLCALL SDL_GetAudioDriver(int index);
  *            you have a specific need to specify the audio driver you want to
  *            use.  You should normally use SDL_Init() or SDL_InitSubSystem().
  */
-/*@{*/
+/* @{ */
 extern DECLSPEC int SDLCALL SDL_AudioInit(const char *driver_name);
 extern DECLSPEC void SDLCALL SDL_AudioQuit(void);
-/*@}*/
+/* @} */
 
 /**
  *  This function returns the name of the current audio driver, or NULL
@@ -359,7 +359,7 @@ extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(const char
  *
  *  Get the current audio state.
  */
-/*@{*/
+/* @{ */
 typedef enum
 {
     SDL_AUDIO_STOPPED = 0,
@@ -370,7 +370,7 @@ extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioStatus(void);
 
 extern DECLSPEC SDL_AudioStatus SDLCALL
 SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev);
-/*@}*//*Audio State*/
+/* @} *//* Audio State */
 
 /**
  *  \name Pause audio functions
@@ -381,11 +381,11 @@ SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev);
  *  data for your callback function after opening the audio device.
  *  Silence will be written to the audio device during the pause.
  */
-/*@{*/
+/* @{ */
 extern DECLSPEC void SDLCALL SDL_PauseAudio(int pause_on);
 extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev,
                                                   int pause_on);
-/*@}*//*Pause audio functions*/
+/* @} *//* Pause audio functions */
 
 /**
  *  This function loads a WAVE from the data source, automatically freeing
@@ -482,12 +482,12 @@ extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst,
  *  the callback function is not running.  Do not call these from the callback
  *  function or you will cause deadlock.
  */
-/*@{*/
+/* @{ */
 extern DECLSPEC void SDLCALL SDL_LockAudio(void);
 extern DECLSPEC void SDLCALL SDL_LockAudioDevice(SDL_AudioDeviceID dev);
 extern DECLSPEC void SDLCALL SDL_UnlockAudio(void);
 extern DECLSPEC void SDLCALL SDL_UnlockAudioDevice(SDL_AudioDeviceID dev);
-/*@}*//*Audio lock functions*/
+/* @} *//* Audio lock functions */
 
 /**
  *  This function shuts down audio processing and closes the audio device.

+ 4 - 0
Source/ThirdParty/SDL/include/SDL_config_android.h

@@ -129,10 +129,14 @@
 
 /* Enable OpenGL ES */
 #define SDL_VIDEO_OPENGL_ES 1
+#define SDL_VIDEO_OPENGL_EGL 1
 #define SDL_VIDEO_RENDER_OGL_ES 1
 #define SDL_VIDEO_RENDER_OGL_ES2    1
 
 /* Enable system power support */
 #define SDL_POWER_ANDROID 1
 
+/* !!! FIXME: what does Android do for filesystem stuff? */
+#define SDL_FILESYSTEM_DUMMY   1
+
 #endif /* _SDL_config_android_h */

+ 3 - 0
Source/ThirdParty/SDL/include/SDL_config_iphoneos.h

@@ -148,4 +148,7 @@
  */
 #define SDL_IPHONE_MAX_GFORCE 5.0
 
+/* enable filesystem support */
+#define SDL_FILESYSTEM_COCOA   1
+
 #endif /* _SDL_config_iphoneos_h */

+ 8 - 2
Source/ThirdParty/SDL/include/SDL_config_linux.h

@@ -36,7 +36,7 @@
 
 /* Make sure that this isn't included by Visual C++ */
 #ifdef _MSC_VER
-#error You should run hg revert SDL_config.h 
+#error You should run hg revert SDL_config.h
 #endif
 
 /* C language features */
@@ -277,13 +277,19 @@
 // Urho3D: Use OpenGL ES 2 implementation from Broadcom VideoCore for Raspberry Pi
 #ifdef RASPI
 #undef SDL_VIDEO_DRIVER_X11			/* No X */
-#define SDL_VIDEO_DRIVER_RASPI 1
+#define SDL_VIDEO_DRIVER_RPI 1
 
 /* Enable OpenGL ES 2 */
 #define SDL_VIDEO_OPENGL_ES2 1
+#define SDL_VIDEO_OPENGL_EGL 1
 #define SDL_VIDEO_RENDER_OGL_ES 1
 #define SDL_VIDEO_RENDER_OGL_ES2 1
 
+/* Linux device manager */
+#define HAVE_LIBUDEV_H 1
+/* Linux keyboard */
+#define SDL_INPUT_LINUXKD 1
+
 #else
 
 /* #undef SDL_VIDEO_RENDER_D3D */

+ 3 - 0
Source/ThirdParty/SDL/include/SDL_config_macosx.h

@@ -171,6 +171,9 @@
 /* Enable system power support */
 #define SDL_POWER_MACOSX 1
 
+/* enable filesystem support */
+#define SDL_FILESYSTEM_COCOA   1
+
 /* Enable assembly routines */
 #define SDL_ASSEMBLY_ROUTINES   1
 #ifdef __ppc__

+ 3 - 0
Source/ThirdParty/SDL/include/SDL_config_minimal.h

@@ -75,4 +75,7 @@ typedef unsigned long uintptr_t;
 /* Enable the dummy video driver (src/video/dummy/\*.c) */
 #define SDL_VIDEO_DRIVER_DUMMY  1
 
+/* Enable the dummy filesystem driver (src/filesystem/dummy/\*.c) */
+#define SDL_FILESYSTEM_DUMMY  1
+
 #endif /* _SDL_config_minimal_h */

+ 1 - 0
Source/ThirdParty/SDL/include/SDL_config_pandora.h

@@ -114,6 +114,7 @@
 #define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX_NP 1
 
 #define SDL_TIMER_UNIX 1
+#define SDL_FILESYSTEM_UNIX 1
 
 #define SDL_VIDEO_DRIVER_DUMMY 1
 #define SDL_VIDEO_DRIVER_X11 1

+ 5 - 2
Source/ThirdParty/SDL/include/SDL_config_psp.h

@@ -99,8 +99,8 @@
 #define HAVE_SQRT   1
 #define HAVE_SETJMP 1
 #define HAVE_NANOSLEEP  1
-//#define HAVE_SYSCONF  1
-//#define HAVE_SIGACTION    1
+/* #define HAVE_SYSCONF  1 */
+/* #define HAVE_SIGACTION    1 */
 
 
 /* PSP isn't that sophisticated */
@@ -126,6 +126,9 @@
 
 #define SDL_POWER_PSP          1
 
+/* !!! FIXME: what does PSP do for filesystem stuff? */
+#define SDL_FILESYSTEM_DUMMY   1
+
 /* PSP doesn't have haptic device (src/haptic/dummy/\*.c) */
 #define SDL_HAPTIC_DISABLED    1
 

+ 12 - 7
Source/ThirdParty/SDL/include/SDL_config_windows.h

@@ -79,7 +79,6 @@ typedef unsigned int uintptr_t;
 #endif
 
 /* This is disabled by default to avoid C runtime dependencies and manifest requirements */
-//#define HAVE_LIBC     1
 #ifdef HAVE_LIBC
 /* Useful headers */
 #define HAVE_STDIO_H 1
@@ -108,12 +107,10 @@ typedef unsigned int uintptr_t;
 #define HAVE_STRCHR 1
 #define HAVE_STRRCHR 1
 #define HAVE_STRSTR 1
-#define HAVE_ITOA 1
 #define HAVE__LTOA 1
 #define HAVE__ULTOA 1
 #define HAVE_STRTOL 1
 #define HAVE_STRTOUL 1
-#define HAVE_STRTOLL 1
 #define HAVE_STRTOD 1
 #define HAVE_ATOI 1
 #define HAVE_ATOF 1
@@ -121,22 +118,27 @@ typedef unsigned int uintptr_t;
 #define HAVE_STRNCMP 1
 #define HAVE__STRICMP 1
 #define HAVE__STRNICMP 1
-#define HAVE_SSCANF 1
-#define HAVE_M_PI 1
 #define HAVE_ATAN 1
 #define HAVE_ATAN2 1
 #define HAVE_CEIL 1
-#define HAVE_COPYSIGN 1
 #define HAVE_COS 1
 #define HAVE_COSF 1
 #define HAVE_FABS 1
 #define HAVE_FLOOR 1
 #define HAVE_LOG 1
 #define HAVE_POW 1
-#define HAVE_SCALBN 1
 #define HAVE_SIN 1
 #define HAVE_SINF 1
 #define HAVE_SQRT 1
+#if _MSC_VER >= 1800
+#define HAVE_STRTOLL 1
+#define HAVE_SSCANF 1
+#define HAVE_COPYSIGN 1
+#define HAVE_SCALBN 1
+#endif
+#if !defined(_MSC_VER) || defined(_USE_MATH_DEFINES)
+#define HAVE_M_PI 1
+#endif
 #else
 #define HAVE_STDARG_H   1
 #define HAVE_STDDEF_H   1
@@ -186,6 +188,9 @@ typedef unsigned int uintptr_t;
 /* Enable system power support */
 #define SDL_POWER_WINDOWS 1
 
+/* Enable filesystem support */
+#define SDL_FILESYSTEM_WINDOWS  1
+
 /* Enable assembly routines (Win64 doesn't have inline asm) */
 #ifndef _WIN64
 #define SDL_ASSEMBLY_ROUTINES   1

+ 5 - 0
Source/ThirdParty/SDL/include/SDL_cpuinfo.h

@@ -134,6 +134,11 @@ extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE41(void);
  */
 extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE42(void);
 
+/**
+ *  This function returns the amount of RAM configured in the system, in MB.
+ */
+extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void);
+
 
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus

+ 4 - 4
Source/ThirdParty/SDL/include/SDL_endian.h

@@ -33,10 +33,10 @@
 /**
  *  \name The two types of endianness
  */
-/*@{*/
+/* @{ */
 #define SDL_LIL_ENDIAN  1234
 #define SDL_BIG_ENDIAN  4321
-/*@}*/
+/* @} */
 
 #ifndef SDL_BYTEORDER           /* Not defined in SDL_config.h? */
 #ifdef __linux__
@@ -206,7 +206,7 @@ SDL_SwapFloat(float x)
  *  \name Swap to native
  *  Byteswap item from the specified endianness to the native endianness.
  */
-/*@{*/
+/* @{ */
 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
 #define SDL_SwapLE16(X) (X)
 #define SDL_SwapLE32(X) (X)
@@ -226,7 +226,7 @@ SDL_SwapFloat(float x)
 #define SDL_SwapBE64(X) (X)
 #define SDL_SwapFloatBE(X)  (X)
 #endif
-/*@}*//*Swap to native*/
+/* @} *//* Swap to native */
 
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus

+ 2 - 2
Source/ThirdParty/SDL/include/SDL_error.h

@@ -48,7 +48,7 @@ extern DECLSPEC void SDLCALL SDL_ClearError(void);
  *  \internal
  *  Private error reporting function - used internally.
  */
-/*@{*/
+/* @{ */
 #define SDL_OutOfMemory()   SDL_Error(SDL_ENOMEM)
 #define SDL_Unsupported()   SDL_Error(SDL_UNSUPPORTED)
 #define SDL_InvalidParamError(param)    SDL_SetError("Parameter '%s' is invalid", (param))
@@ -63,7 +63,7 @@ typedef enum
 } SDL_errorcode;
 /* SDL_Error() unconditionally returns -1. */
 extern DECLSPEC int SDLCALL SDL_Error(SDL_errorcode code);
-/*@}*//*Internal error functions*/
+/* @} *//* Internal error functions */
 
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus

+ 4 - 4
Source/ThirdParty/SDL/include/SDL_events.h

@@ -541,7 +541,7 @@ typedef union SDL_Event
  */
 extern DECLSPEC void SDLCALL SDL_PumpEvents(void);
 
-/*@{*/
+/* @{ */
 typedef enum
 {
     SDL_ADDEVENT,
@@ -570,7 +570,7 @@ typedef enum
 extern DECLSPEC int SDLCALL SDL_PeepEvents(SDL_Event * events, int numevents,
                                            SDL_eventaction action,
                                            Uint32 minType, Uint32 maxType);
-/*@}*/
+/* @} */
 
 /**
  *  Checks to see if certain event types are in the event queue.
@@ -681,7 +681,7 @@ extern DECLSPEC void SDLCALL SDL_DelEventWatch(SDL_EventFilter filter,
 extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter,
                                               void *userdata);
 
-/*@{*/
+/* @{ */
 #define SDL_QUERY   -1
 #define SDL_IGNORE   0
 #define SDL_DISABLE  0
@@ -697,7 +697,7 @@ extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter,
  *     current processing state of the specified event.
  */
 extern DECLSPEC Uint8 SDLCALL SDL_EventState(Uint32 type, int state);
-/*@}*/
+/* @} */
 #define SDL_GetEventState(type) SDL_EventState(type, SDL_QUERY)
 
 /**

+ 136 - 0
Source/ThirdParty/SDL/include/SDL_filesystem.h

@@ -0,0 +1,136 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ *  \file SDL_filesystem.h
+ *
+ *  \brief Include file for filesystem SDL API functions
+ */
+
+#ifndef _SDL_filesystem_h
+#define _SDL_filesystem_h
+
+#include "SDL_stdinc.h"
+
+#include "begin_code.h"
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Get the path where the application resides.
+ *
+ * Get the "base path". This is the directory where the application was run
+ *  from, which is probably the installation directory, and may or may not
+ *  be the process's current working directory.
+ *
+ * This returns an absolute path in UTF-8 encoding, and is guaranteed to
+ *  end with a path separator ('\\' on Windows, '/' most other places).
+ *
+ * The pointer returned by this function is owned by you. Please call
+ *  SDL_free() on the pointer when you are done with it, or it will be a
+ *  memory leak. This is not necessarily a fast call, though, so you should
+ *  call this once near startup and save the string if you need it.
+ *
+ * Some platforms can't determine the application's path, and on other
+ *  platforms, this might be meaningless. In such cases, this function will
+ *  return NULL.
+ *
+ *  \return String of base dir in UTF-8 encoding, or NULL on error.
+ *
+ * \sa SDL_GetPrefPath
+ */
+extern DECLSPEC char *SDLCALL SDL_GetBasePath(void);
+
+/**
+ * \brief Get the user-and-app-specific path where files can be written.
+ *
+ * Get the "pref dir". This is meant to be where users can write personal
+ *  files (preferences and save games, etc) that are specific to your
+ *  application. This directory is unique per user, per application.
+ *
+ * This function will decide the appropriate location in the native filesystem,
+ *  create the directory if necessary, and return a string of the absolute
+ *  path to the directory in UTF-8 encoding.
+ *
+ * On Windows, the string might look like:
+ *  "C:\\Users\\bob\\AppData\\Roaming\\My Company\\My Program Name\\"
+ *
+ * On Linux, the string might look like:
+ *  "/home/bob/.local/share/My Program Name/"
+ *
+ * On Mac OS X, the string might look like:
+ *  "/Users/bob/Library/Application Support/My Program Name/"
+ *
+ * (etc.)
+ *
+ * You specify the name of your organization (if it's not a real organization,
+ *  your name or an Internet domain you own might do) and the name of your
+ *  application. These should be untranslated proper names.
+ *
+ * Both the org and app strings may become part of a directory name, so
+ *  please follow these rules:
+ *
+ *    - Try to use the same org string (including case-sensitivity) for
+ *      all your applications that use this function.
+ *    - Always use a unique app string for each one, and make sure it never
+ *      changes for an app once you've decided on it.
+ *    - Unicode characters are legal, as long as it's UTF-8 encoded, but...
+ *    - ...only use letters, numbers, and spaces. Avoid punctuation like
+ *      "Game Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient.
+ *
+ * This returns an absolute path in UTF-8 encoding, and is guaranteed to
+ *  end with a path separator ('\\' on Windows, '/' most other places).
+ *
+ * The pointer returned by this function is owned by you. Please call
+ *  SDL_free() on the pointer when you are done with it, or it will be a
+ *  memory leak. This is not necessarily a fast call, though, so you should
+ *  call this once near startup and save the string if you need it.
+ *
+ * You should assume the path returned by this function is the only safe
+ *  place to write files (and that SDL_GetBasePath(), while it might be
+ *  writable, or even the parent of the returned path, aren't where you
+ *  should be writing things).
+ *
+ * Some platforms can't determine the pref path, and on other
+ *  platforms, this might be meaningless. In such cases, this function will
+ *  return NULL.
+ *
+ *   \param org The name of your organization.
+ *   \param app The name of your application.
+ *  \return UTF-8 string of user dir in platform-dependent notation. NULL
+ *          if there's a problem (creating directory failed, etc).
+ *
+ * \sa SDL_GetBasePath
+ */
+extern DECLSPEC char *SDLCALL SDL_GetPrefPath(const char *org, const char *app);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include "close_code.h"
+
+#endif /* _SDL_system_h */
+
+/* vi: set ts=4 sw=4 expandtab: */

+ 7 - 7
Source/ThirdParty/SDL/include/SDL_haptic.h

@@ -140,12 +140,12 @@ typedef struct _SDL_Haptic SDL_Haptic;
  *
  *  Different haptic features a device can have.
  */
-/*@{*/
+/* @{ */
 
 /**
  *  \name Haptic effects
  */
-/*@{*/
+/* @{ */
 
 /**
  *  \brief Constant effect supported.
@@ -177,7 +177,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
 #define SDL_HAPTIC_LEFTRIGHT     (1<<2)
 
 /* !!! FIXME: put this back when we have more bits in 2.1 */
-/*#define SDL_HAPTIC_SQUARE     (1<<2)*/
+/* #define SDL_HAPTIC_SQUARE     (1<<2) */
 
 /**
  *  \brief Triangle wave effect supported.
@@ -262,7 +262,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
  */
 #define SDL_HAPTIC_CUSTOM     (1<<11)
 
-/*@}*//*Haptic effects*/
+/* @} *//* Haptic effects */
 
 /* These last few are features the device has, not effects */
 
@@ -305,7 +305,7 @@ typedef struct _SDL_Haptic SDL_Haptic;
 /**
  * \name Direction encodings
  */
-/*@{*/
+/* @{ */
 
 /**
  *  \brief Uses polar coordinates for the direction.
@@ -328,9 +328,9 @@ typedef struct _SDL_Haptic SDL_Haptic;
  */
 #define SDL_HAPTIC_SPHERICAL  2
 
-/*@}*//*Direction encodings*/
+/* @} *//* Direction encodings */
 
-/*@}*//*Haptic features*/
+/* @} *//* Haptic features */
 
 /*
  * Misc defines.

+ 16 - 0
Source/ThirdParty/SDL/include/SDL_hints.h

@@ -94,6 +94,17 @@ extern "C" {
  */
 #define SDL_HINT_RENDER_OPENGL_SHADERS      "SDL_RENDER_OPENGL_SHADERS"
 
+/**
+ *  \brief  A variable controlling whether the Direct3D device is initialized for thread-safe operations.
+ *
+ *  This variable can be set to the following values:
+ *    "0"       - Thread-safety is not enabled (faster)
+ *    "1"       - Thread-safety is enabled
+ *
+ *  By default the Direct3D device is created with thread-safety disabled.
+ */
+#define SDL_HINT_RENDER_DIRECT3D_THREADSAFE "SDL_RENDER_DIRECT3D_THREADSAFE"
+
 /**
  *  \brief  A variable controlling the scaling quality
  *
@@ -257,6 +268,11 @@ extern "C" {
 #define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION"
 
 
+/**
+ *  \brief If set to 1, then do not allow high-DPI windows. ("Retina" on Mac)
+ */
+#define SDL_HINT_VIDEO_HIGHDPI_DISABLED "SDL_VIDEO_HIGHDPI_DISABLED"
+
 
 /**
  *  \brief  An enumeration of hint priorities

+ 2 - 2
Source/ThirdParty/SDL/include/SDL_joystick.h

@@ -187,7 +187,7 @@ extern DECLSPEC Sint16 SDLCALL SDL_JoystickGetAxis(SDL_Joystick * joystick,
 /**
  *  \name Hat positions
  */
-/*@{*/
+/* @{ */
 #define SDL_HAT_CENTERED    0x00
 #define SDL_HAT_UP      0x01
 #define SDL_HAT_RIGHT       0x02
@@ -197,7 +197,7 @@ extern DECLSPEC Sint16 SDLCALL SDL_JoystickGetAxis(SDL_Joystick * joystick,
 #define SDL_HAT_RIGHTDOWN   (SDL_HAT_RIGHT|SDL_HAT_DOWN)
 #define SDL_HAT_LEFTUP      (SDL_HAT_LEFT|SDL_HAT_UP)
 #define SDL_HAT_LEFTDOWN    (SDL_HAT_LEFT|SDL_HAT_DOWN)
-/*@}*/
+/* @} */
 
 /**
  *  Get the current state of a POV hat on a joystick.

+ 1 - 1
Source/ThirdParty/SDL/include/SDL_main.h

@@ -94,7 +94,7 @@ extern C_LINKAGE int SDL_main(int argc, char *argv[]);
 extern "C" {
 #endif
 
-/*
+/**
  *  This is called by the real SDL main function to let the rest of the
  *  library know that initialization was done properly.
  *

+ 9 - 9
Source/ThirdParty/SDL/include/SDL_mutex.h

@@ -52,9 +52,9 @@ extern "C" {
 /**
  *  \name Mutex functions
  */
-/*@{*/
+/* @{ */
 
-/* The SDL mutex structure, defined in SDL_mutex.c */
+/* The SDL mutex structure, defined in SDL_sysmutex.c */
 struct SDL_mutex;
 typedef struct SDL_mutex SDL_mutex;
 
@@ -94,15 +94,15 @@ extern DECLSPEC int SDLCALL SDL_UnlockMutex(SDL_mutex * mutex);
  */
 extern DECLSPEC void SDLCALL SDL_DestroyMutex(SDL_mutex * mutex);
 
-/*@}*//*Mutex functions*/
+/* @} *//* Mutex functions */
 
 
 /**
  *  \name Semaphore functions
  */
-/*@{*/
+/* @{ */
 
-/* The SDL semaphore structure, defined in SDL_sem.c */
+/* The SDL semaphore structure, defined in SDL_syssem.c */
 struct SDL_semaphore;
 typedef struct SDL_semaphore SDL_sem;
 
@@ -154,15 +154,15 @@ extern DECLSPEC int SDLCALL SDL_SemPost(SDL_sem * sem);
  */
 extern DECLSPEC Uint32 SDLCALL SDL_SemValue(SDL_sem * sem);
 
-/*@}*//*Semaphore functions*/
+/* @} *//* Semaphore functions */
 
 
 /**
  *  \name Condition variable functions
  */
-/*@{*/
+/* @{ */
 
-/* The SDL condition variable structure, defined in SDL_cond.c */
+/* The SDL condition variable structure, defined in SDL_syscond.c */
 struct SDL_cond;
 typedef struct SDL_cond SDL_cond;
 
@@ -237,7 +237,7 @@ extern DECLSPEC int SDLCALL SDL_CondWait(SDL_cond * cond, SDL_mutex * mutex);
 extern DECLSPEC int SDLCALL SDL_CondWaitTimeout(SDL_cond * cond,
                                                 SDL_mutex * mutex, Uint32 ms);
 
-/*@}*//*Condition variable functions*/
+/* @} *//* Condition variable functions */
 
 
 /* Ends C function definitions when using C++ */

+ 2 - 2
Source/ThirdParty/SDL/include/SDL_pixels.h

@@ -39,10 +39,10 @@ extern "C" {
  *
  *  These define alpha as the opacity of a surface.
  */
-/*@{*/
+/* @{ */
 #define SDL_ALPHA_OPAQUE 255
 #define SDL_ALPHA_TRANSPARENT 0
-/*@}*/
+/* @} */
 
 /** Pixel type. */
 enum

+ 6 - 2
Source/ThirdParty/SDL/include/SDL_platform.h

@@ -66,7 +66,7 @@
 #endif
 #if defined(ANDROID)
 #undef __ANDROID__
-#undef __LINUX__ /*do we need to do this?*/
+#undef __LINUX__ /* do we need to do this? */
 #define __ANDROID__ 1
 #endif
 
@@ -121,8 +121,12 @@
 #define __SOLARIS__ 1
 #endif
 #if defined(WIN32) || defined(_WIN32) || defined(__CYGWIN__)
+#undef __WINDOWS__
+#define __WINDOWS__   1
+#endif
+#if defined(__WINDOWS__)
 #undef __WIN32__
-#define __WIN32__   1
+#define __WIN32__ 1
 #endif
 #if defined(__PSP__)
 #undef __PSP__

+ 1 - 1
Source/ThirdParty/SDL/include/SDL_rect.h

@@ -44,7 +44,7 @@ extern "C" {
  *
  *  \sa SDL_EnclosePoints
  */
-typedef struct
+typedef struct SDL_Point
 {
     int x;
     int y;

+ 25 - 0
Source/ThirdParty/SDL/include/SDL_render.h

@@ -381,6 +381,31 @@ extern DECLSPEC int SDLCALL SDL_UpdateTexture(SDL_Texture * texture,
                                               const SDL_Rect * rect,
                                               const void *pixels, int pitch);
 
+/**
+ *  \brief Update a rectangle within a planar YV12 or IYUV texture with new pixel data.
+ *
+ *  \param texture   The texture to update
+ *  \param rect      A pointer to the rectangle of pixels to update, or NULL to
+ *                   update the entire texture.
+ *  \param Yplane    The raw pixel data for the Y plane.
+ *  \param Ypitch    The number of bytes between rows of pixel data for the Y plane.
+ *  \param Uplane    The raw pixel data for the U plane.
+ *  \param Upitch    The number of bytes between rows of pixel data for the U plane.
+ *  \param Vplane    The raw pixel data for the V plane.
+ *  \param Vpitch    The number of bytes between rows of pixel data for the V plane.
+ *
+ *  \return 0 on success, or -1 if the texture is not valid.
+ *
+ *  \note You can use SDL_UpdateTexture() as long as your pixel data is
+ *        a contiguous block of Y and U/V planes in the proper order, but
+ *        this function is available if your pixel data is not contiguous.
+ */
+extern DECLSPEC int SDLCALL SDL_UpdateYUVTexture(SDL_Texture * texture,
+                                                 const SDL_Rect * rect,
+                                                 const Uint8 *Yplane, int Ypitch,
+                                                 const Uint8 *Uplane, int Upitch,
+                                                 const Uint8 *Vplane, int Vpitch);
+
 /**
  *  \brief Lock a portion of the texture for write-only pixel access.
  *

+ 2 - 2
Source/ThirdParty/SDL/include/SDL_revision.h

@@ -1,2 +1,2 @@
-#define SDL_REVISION "hg-7633:d6a8fa507a45"
-#define SDL_REVISION_NUMBER 7633
+#define SDL_REVISION "hg-0:aaaaaaaaaaah"
+#define SDL_REVISION_NUMBER 0

+ 8 - 8
Source/ThirdParty/SDL/include/SDL_rwops.h

@@ -148,7 +148,7 @@ typedef struct SDL_RWops
  *
  *  Functions to create SDL_RWops structures from various data streams.
  */
-/*@{*/
+/* @{ */
 
 extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromFile(const char *file,
                                                   const char *mode);
@@ -165,7 +165,7 @@ extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromMem(void *mem, int size);
 extern DECLSPEC SDL_RWops *SDLCALL SDL_RWFromConstMem(const void *mem,
                                                       int size);
 
-/*@}*//*RWFrom functions*/
+/* @} *//* RWFrom functions */
 
 
 extern DECLSPEC SDL_RWops *SDLCALL SDL_AllocRW(void);
@@ -180,14 +180,14 @@ extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area);
  *
  *  Macros to easily read and write from an SDL_RWops structure.
  */
-/*@{*/
+/* @{ */
 #define SDL_RWsize(ctx)         (ctx)->size(ctx)
 #define SDL_RWseek(ctx, offset, whence) (ctx)->seek(ctx, offset, whence)
 #define SDL_RWtell(ctx)         (ctx)->seek(ctx, 0, RW_SEEK_CUR)
 #define SDL_RWread(ctx, ptr, size, n)   (ctx)->read(ctx, ptr, size, n)
 #define SDL_RWwrite(ctx, ptr, size, n)  (ctx)->write(ctx, ptr, size, n)
 #define SDL_RWclose(ctx)        (ctx)->close(ctx)
-/*@}*//*Read/write macros*/
+/* @} *//* Read/write macros */
 
 
 /**
@@ -195,7 +195,7 @@ extern DECLSPEC void SDLCALL SDL_FreeRW(SDL_RWops * area);
  *
  *  Read an item of the specified endianness and return in native format.
  */
-/*@{*/
+/* @{ */
 extern DECLSPEC Uint8 SDLCALL SDL_ReadU8(SDL_RWops * src);
 extern DECLSPEC Uint16 SDLCALL SDL_ReadLE16(SDL_RWops * src);
 extern DECLSPEC Uint16 SDLCALL SDL_ReadBE16(SDL_RWops * src);
@@ -203,14 +203,14 @@ extern DECLSPEC Uint32 SDLCALL SDL_ReadLE32(SDL_RWops * src);
 extern DECLSPEC Uint32 SDLCALL SDL_ReadBE32(SDL_RWops * src);
 extern DECLSPEC Uint64 SDLCALL SDL_ReadLE64(SDL_RWops * src);
 extern DECLSPEC Uint64 SDLCALL SDL_ReadBE64(SDL_RWops * src);
-/*@}*//*Read endian functions*/
+/* @} *//* Read endian functions */
 
 /**
  *  \name Write endian functions
  *
  *  Write an item of native format to the specified endianness.
  */
-/*@{*/
+/* @{ */
 extern DECLSPEC size_t SDLCALL SDL_WriteU8(SDL_RWops * dst, Uint8 value);
 extern DECLSPEC size_t SDLCALL SDL_WriteLE16(SDL_RWops * dst, Uint16 value);
 extern DECLSPEC size_t SDLCALL SDL_WriteBE16(SDL_RWops * dst, Uint16 value);
@@ -218,7 +218,7 @@ extern DECLSPEC size_t SDLCALL SDL_WriteLE32(SDL_RWops * dst, Uint32 value);
 extern DECLSPEC size_t SDLCALL SDL_WriteBE32(SDL_RWops * dst, Uint32 value);
 extern DECLSPEC size_t SDLCALL SDL_WriteLE64(SDL_RWops * dst, Uint64 value);
 extern DECLSPEC size_t SDLCALL SDL_WriteBE64(SDL_RWops * dst, Uint64 value);
-/*@}*//*Write endian functions*/
+/* @} *//* Write endian functions */
 
 
 /* Ends C function definitions when using C++ */

+ 6 - 6
Source/ThirdParty/SDL/include/SDL_scancode.h

@@ -49,7 +49,7 @@ typedef enum
      *
      *  These values are from usage page 0x07 (USB keyboard page).
      */
-    /*@{*/
+    /* @{ */
 
     SDL_SCANCODE_A = 4,
     SDL_SCANCODE_B = 5,
@@ -339,14 +339,14 @@ typedef enum
                                  *   special KMOD_MODE for it I'm adding it here
                                  */
 
-    /*@}*//*Usage page 0x07*/
+    /* @} *//* Usage page 0x07 */
 
     /**
      *  \name Usage page 0x0C
      *
      *  These values are mapped from usage page 0x0C (USB consumer page).
      */
-    /*@{*/
+    /* @{ */
 
     SDL_SCANCODE_AUDIONEXT = 258,
     SDL_SCANCODE_AUDIOPREV = 259,
@@ -366,14 +366,14 @@ typedef enum
     SDL_SCANCODE_AC_REFRESH = 273,
     SDL_SCANCODE_AC_BOOKMARKS = 274,
 
-    /*@}*//*Usage page 0x0C*/
+    /* @} *//* Usage page 0x0C */
 
     /**
      *  \name Walther keys
      *
      *  These are values that Christian Walther added (for mac keyboard?).
      */
-    /*@{*/
+    /* @{ */
 
     SDL_SCANCODE_BRIGHTNESSDOWN = 275,
     SDL_SCANCODE_BRIGHTNESSUP = 276,
@@ -388,7 +388,7 @@ typedef enum
     SDL_SCANCODE_APP1 = 283,
     SDL_SCANCODE_APP2 = 284,
 
-    /*@}*//*Walther keys*/
+    /* @} *//* Walther keys */
 
     /* Add any other keys here. */
 

+ 4 - 4
Source/ThirdParty/SDL/include/SDL_stdinc.h

@@ -89,7 +89,7 @@
  *  Use proper C++ casts when compiled as C++ to be compatible with the option
  *  -Wold-style-cast of GCC (and -Werror=old-style-cast in GCC 4.2 and above).
  */
-/*@{*/
+/* @{ */
 #ifdef __cplusplus
 #define SDL_reinterpret_cast(type, expression) reinterpret_cast<type>(expression)
 #define SDL_static_cast(type, expression) static_cast<type>(expression)
@@ -99,7 +99,7 @@
 #define SDL_static_cast(type, expression) ((type)(expression))
 #define SDL_const_cast(type, expression) ((type)(expression))
 #endif
-/*@}*//*Cast operators*/
+/* @} *//* Cast operators */
 
 /* Define a four character code as a Uint32 */
 #define SDL_FOURCC(A, B, C, D) \
@@ -111,7 +111,7 @@
 /**
  *  \name Basic data types
  */
-/*@{*/
+/* @{ */
 
 typedef enum
 {
@@ -153,7 +153,7 @@ typedef int64_t Sint64;
  */
 typedef uint64_t Uint64;
 
-/*@}*//*Basic data types*/
+/* @} *//* Basic data types */
 
 
 #define SDL_COMPILE_TIME_ASSERT(name, x)               \

+ 3 - 3
Source/ThirdParty/SDL/include/SDL_surface.h

@@ -48,12 +48,12 @@ extern "C" {
  *  \internal
  *  Used internally (read-only).
  */
-/*@{*/
+/* @{ */
 #define SDL_SWSURFACE       0           /**< Just here for compatibility */
 #define SDL_PREALLOC        0x00000001  /**< Surface uses preallocated memory */
 #define SDL_RLEACCEL        0x00000002  /**< Surface is RLE encoded */
 #define SDL_DONTFREE        0x00000004  /**< Surface is referenced internally */
-/*@}*//*Surface flags*/
+/* @} *//* Surface flags */
 
 /**
  *  Evaluates to true if the surface needs to be locked before access.
@@ -357,7 +357,7 @@ extern DECLSPEC void SDLCALL SDL_GetClipRect(SDL_Surface * surface,
  *  surface.
  */
 extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurface
-    (SDL_Surface * src, SDL_PixelFormat * fmt, Uint32 flags);
+    (SDL_Surface * src, const SDL_PixelFormat * fmt, Uint32 flags);
 extern DECLSPEC SDL_Surface *SDLCALL SDL_ConvertSurfaceFormat
     (SDL_Surface * src, Uint32 pixel_format, Uint32 flags);
 

+ 21 - 5
Source/ThirdParty/SDL/include/SDL_system.h

@@ -29,11 +29,9 @@
 #define _SDL_system_h
 
 #include "SDL_stdinc.h"
-
-#if defined(__IPHONEOS__) && __IPHONEOS__
-#include "SDL_video.h"
 #include "SDL_keyboard.h"
-#endif
+#include "SDL_render.h"
+#include "SDL_video.h"
 
 #include "begin_code.h"
 /* Set up for C function definitions, even when using C++ */
@@ -41,6 +39,25 @@
 extern "C" {
 #endif
 
+
+/* Platform specific functions for Windows */
+#ifdef __WIN32__
+
+/* Returns the D3D9 adapter index that matches the specified display index.
+   This adapter index can be passed to IDirect3D9::CreateDevice and controls
+   on which monitor a full screen application will appear.
+*/
+extern DECLSPEC int SDLCALL SDL_Direct3D9GetAdapterIndex( int displayIndex );
+
+/* Returns the D3D device associated with a renderer, or NULL if it's not a D3D renderer.
+   Once you are done using the device, you should release it to avoid a resource leak.
+ */
+typedef struct IDirect3DDevice9 IDirect3DDevice9;
+extern DECLSPEC IDirect3DDevice9* SDLCALL SDL_RenderGetD3D9Device(SDL_Renderer * renderer);
+
+#endif /* __WIN32__ */
+
+
 /* Platform specific functions for iOS */
 #if defined(__IPHONEOS__) && __IPHONEOS__
 
@@ -93,7 +110,6 @@ extern DECLSPEC const char * SDLCALL SDL_AndroidGetExternalStoragePath();
 
 #endif /* __ANDROID__ */
 
-
 /* Ends C function definitions when using C++ */
 #ifdef __cplusplus
 }

+ 1 - 0
Source/ThirdParty/SDL/include/SDL_test_common.h

@@ -108,6 +108,7 @@ typedef struct
     int gl_major_version;
     int gl_minor_version;
     int gl_debug;
+    int gl_profile_mask;
 } SDLTest_CommonState;
 
 #include "begin_code.h"

+ 14 - 14
Source/ThirdParty/SDL/include/SDL_test_harness.h

@@ -43,43 +43,43 @@ extern "C" {
 #endif
 
 
-//! Definitions for test case structures
+/* ! Definitions for test case structures */
 #define TEST_ENABLED  1
 #define TEST_DISABLED 0
 
-//! Definition of all the possible test return values of the test case method
+/* ! Definition of all the possible test return values of the test case method */
 #define TEST_ABORTED        -1
 #define TEST_STARTED         0
 #define TEST_COMPLETED       1
 #define TEST_SKIPPED         2
 
-//! Definition of all the possible test results for the harness
+/* ! Definition of all the possible test results for the harness */
 #define TEST_RESULT_PASSED              0
 #define TEST_RESULT_FAILED              1
 #define TEST_RESULT_NO_ASSERT           2
 #define TEST_RESULT_SKIPPED             3
 #define TEST_RESULT_SETUP_FAILURE       4
 
-//!< Function pointer to a test case setup function (run before every test)
+/* !< Function pointer to a test case setup function (run before every test) */
 typedef void (*SDLTest_TestCaseSetUpFp)(void *arg);
 
-//!< Function pointer to a test case function
+/* !< Function pointer to a test case function */
 typedef int (*SDLTest_TestCaseFp)(void *arg);
 
-//!< Function pointer to a test case teardown function (run after every test)
+/* !< Function pointer to a test case teardown function (run after every test) */
 typedef void  (*SDLTest_TestCaseTearDownFp)(void *arg);
 
 /**
  * Holds information about a single test case.
  */
 typedef struct SDLTest_TestCaseReference {
-    /*!< Func2Stress */
+    /* !< Func2Stress */
     SDLTest_TestCaseFp testCase;
-    /*!< Short name (or function name) "Func2Stress" */
+    /* !< Short name (or function name) "Func2Stress" */
     char *name;
-    /*!< Long name or full description "This test pushes func2() to the limit." */
+    /* !< Long name or full description "This test pushes func2() to the limit." */
     char *description;
-    /*!< Set to TEST_ENABLED or TEST_DISABLED (test won't be run) */
+    /* !< Set to TEST_ENABLED or TEST_DISABLED (test won't be run) */
     int enabled;
 } SDLTest_TestCaseReference;
 
@@ -87,13 +87,13 @@ typedef struct SDLTest_TestCaseReference {
  * Holds information about a test suite (multiple test cases).
  */
 typedef struct SDLTest_TestSuiteReference {
-    /*!< "PlatformSuite" */
+    /* !< "PlatformSuite" */
     char *name;
-    /*!< The function that is run before each test. NULL skips. */
+    /* !< The function that is run before each test. NULL skips. */
     SDLTest_TestCaseSetUpFp testSetUp;
-    /*!< The test cases that are run as part of the suite. Last item should be NULL. */
+    /* !< The test cases that are run as part of the suite. Last item should be NULL. */
     const SDLTest_TestCaseReference **testCases;
-    /*!< The function that is run after each test. NULL skips. */
+    /* !< The function that is run after each test. NULL skips. */
     SDLTest_TestCaseTearDownFp testTearDown;
 } SDLTest_TestSuiteReference;
 

+ 6 - 4
Source/ThirdParty/SDL/include/SDL_thread.h

@@ -51,9 +51,10 @@ typedef unsigned long SDL_threadID;
 /* Thread local storage ID, 0 is the invalid ID */
 typedef unsigned int SDL_TLSID;
 
-/* The SDL thread priority
+/**
+ *  The SDL thread priority.
  *
- * Note: On many systems you require special privileges to set high priority.
+ *  \note On many systems you require special privileges to set high priority.
  */
 typedef enum {
     SDL_THREAD_PRIORITY_LOW,
@@ -61,8 +62,9 @@ typedef enum {
     SDL_THREAD_PRIORITY_HIGH
 } SDL_ThreadPriority;
 
-/* The function passed to SDL_CreateThread()
-   It is passed a void* user context parameter and returns an int.
+/**
+ *  The function passed to SDL_CreateThread().
+ *  It is passed a void* user context parameter and returns an int.
  */
 typedef int (SDLCALL * SDL_ThreadFunction) (void *data);
 

+ 11 - 0
Source/ThirdParty/SDL/include/SDL_timer.h

@@ -44,6 +44,17 @@ extern "C" {
  */
 extern DECLSPEC Uint32 SDLCALL SDL_GetTicks(void);
 
+/**
+ * \brief Compare SDL ticks values, and return true if A has passed B
+ *
+ * e.g. if you want to wait 100 ms, you could do this:
+ *  Uint32 timeout = SDL_GetTicks() + 100;
+ *  while (!SDL_TICKS_PASSED(SDL_GetTicks(), timeout)) {
+ *      ... do work until timeout has elapsed
+ *  }
+ */
+#define SDL_TICKS_PASSED(A, B)  ((Sint32)((B) - (A)) <= 0)
+
 /**
  * \brief Get the current value of the high resolution counter
  */

+ 1 - 1
Source/ThirdParty/SDL/include/SDL_version.h

@@ -59,7 +59,7 @@ typedef struct SDL_version
 */
 #define SDL_MAJOR_VERSION   2
 #define SDL_MINOR_VERSION   0
-#define SDL_PATCHLEVEL      0
+#define SDL_PATCHLEVEL      1
 
 /**
  *  \brief Macro to determine SDL version program was compiled against.

+ 30 - 9
Source/ThirdParty/SDL/include/SDL_video.h

@@ -109,7 +109,8 @@ typedef enum
     SDL_WINDOW_INPUT_FOCUS = 0x00000200,        /**< window has input focus */
     SDL_WINDOW_MOUSE_FOCUS = 0x00000400,        /**< window has mouse focus */
     SDL_WINDOW_FULLSCREEN_DESKTOP = ( SDL_WINDOW_FULLSCREEN | 0x00001000 ),
-    SDL_WINDOW_FOREIGN = 0x00000800             /**< window not created by SDL */
+    SDL_WINDOW_FOREIGN = 0x00000800,            /**< window not created by SDL */
+    SDL_WINDOW_ALLOW_HIGHDPI = 0x00002000       /**< window should be created in high-DPI mode if supported */
 } SDL_WindowFlags;
 
 /**
@@ -188,14 +189,15 @@ typedef enum
     SDL_GL_CONTEXT_EGL,
     SDL_GL_CONTEXT_FLAGS,
     SDL_GL_CONTEXT_PROFILE_MASK,
-    SDL_GL_SHARE_WITH_CURRENT_CONTEXT
+    SDL_GL_SHARE_WITH_CURRENT_CONTEXT,
+    SDL_GL_FRAMEBUFFER_SRGB_CAPABLE
 } SDL_GLattr;
 
 typedef enum
 {
     SDL_GL_CONTEXT_PROFILE_CORE           = 0x0001,
     SDL_GL_CONTEXT_PROFILE_COMPATIBILITY  = 0x0002,
-    SDL_GL_CONTEXT_PROFILE_ES             = 0x0004
+    SDL_GL_CONTEXT_PROFILE_ES             = 0x0004 /* GLX_CONTEXT_ES2_PROFILE_BIT_EXT */
 } SDL_GLprofile;
 
 typedef enum
@@ -395,10 +397,11 @@ extern DECLSPEC Uint32 SDLCALL SDL_GetWindowPixelFormat(SDL_Window * window);
  *  \param w     The width of the window.
  *  \param h     The height of the window.
  *  \param flags The flags for the window, a mask of any of the following:
- *               ::SDL_WINDOW_FULLSCREEN, ::SDL_WINDOW_OPENGL,
- *               ::SDL_WINDOW_HIDDEN,     ::SDL_WINDOW_BORDERLESS,
- *               ::SDL_WINDOW_RESIZABLE,  ::SDL_WINDOW_MAXIMIZED,
- *               ::SDL_WINDOW_MINIMIZED,  ::SDL_WINDOW_INPUT_GRABBED.
+ *               ::SDL_WINDOW_FULLSCREEN,    ::SDL_WINDOW_OPENGL,
+ *               ::SDL_WINDOW_HIDDEN,        ::SDL_WINDOW_BORDERLESS,
+ *               ::SDL_WINDOW_RESIZABLE,     ::SDL_WINDOW_MAXIMIZED,
+ *               ::SDL_WINDOW_MINIMIZED,     ::SDL_WINDOW_INPUT_GRABBED,
+ *               ::SDL_WINDOW_ALLOW_HIGHDPI.
  *
  *  \return The id of the window created, or zero if window creation failed.
  *
@@ -824,7 +827,7 @@ extern DECLSPEC void SDLCALL SDL_DisableScreenSaver(void);
 /**
  *  \name OpenGL support functions
  */
-/*@{*/
+/* @{ */
 
 /**
  *  \brief Dynamically load an OpenGL library.
@@ -902,6 +905,24 @@ extern DECLSPEC SDL_Window* SDLCALL SDL_GL_GetCurrentWindow(void);
  */
 extern DECLSPEC SDL_GLContext SDLCALL SDL_GL_GetCurrentContext(void);
 
+/**
+ *  \brief Get the size of a window's underlying drawable (for use with glViewport).
+ *
+ *  \param window   Window from which the drawable size should be queried
+ *  \param w        Pointer to variable for storing the width, may be NULL
+ *  \param h        Pointer to variable for storing the height, may be NULL
+ *
+ * This may differ from SDL_GetWindowSize if we're rendering to a high-DPI
+ * drawable, i.e. the window was created with SDL_WINDOW_ALLOW_HIGHDPI on a
+ * platform with high-DPI support (Apple calls this "Retina"), and not disabled
+ * by the SDL_HINT_VIDEO_HIGHDPI_DISABLED hint.
+ *
+ *  \sa SDL_GetWindowSize()
+ *  \sa SDL_CreateWindow()
+ */
+extern DECLSPEC void SDLCALL SDL_GL_GetDrawableSize(SDL_Window * window, int *w,
+                                                    int *h);
+
 /**
  *  \brief Set the swap interval for the current OpenGL context.
  *
@@ -942,7 +963,7 @@ extern DECLSPEC void SDLCALL SDL_GL_SwapWindow(SDL_Window * window);
  */
 extern DECLSPEC void SDLCALL SDL_GL_DeleteContext(SDL_GLContext context);
 
-/*@}*//*OpenGL support functions*/
+/* @} *//* OpenGL support functions */
 
 
 /* Ends C function definitions when using C++ */

+ 25 - 35
Source/ThirdParty/SDL/include/begin_code.h

@@ -35,17 +35,19 @@
 #endif
 #define _begin_code_h
 
+#ifndef SDL_DEPRECATED
+#  if (__GNUC__ >= 4)  /* technically, this arrived in gcc 3.1, but oh well. */
+#    define SDL_DEPRECATED __attribute__((deprecated))
+#  else
+#    define SDL_DEPRECATED
+#  endif
+#endif
+
 /* Some compilers use a special export keyword */
 // Urho3D: Only export when it is being requested
 #ifdef SDL_EXPORTS
 #ifndef DECLSPEC
-# if defined(__BEOS__) || defined(__HAIKU__)
-#  if defined(__GNUC__)
-#   define DECLSPEC __declspec(dllexport)
-#  else
-#   define DECLSPEC __declspec(export)
-#  endif
-# elif defined(__WIN32__)
+# if defined(__WIN32__)
 #  ifdef __BORLANDC__
 #   ifdef BUILD_SDL
 #    define DECLSPEC
@@ -58,6 +60,8 @@
 # else
 #  if defined(__GNUC__) && __GNUC__ >= 4
 #   define DECLSPEC __attribute__ ((visibility("default")))
+#  elif defined(__GNUC__) && __GNUC__ >= 2
+#   define DECLSPEC __declspec(dllexport)
 #  else
 #   define DECLSPEC
 #  endif
@@ -102,48 +106,34 @@
 #endif
 #endif /* Compiler needs structure packing set */
 
-/* Set up compiler-specific options for inlining functions */
-#ifndef SDL_INLINE_OKAY
-#ifdef __GNUC__
-#define SDL_INLINE_OKAY
-#else
-/* Add any special compiler-specific cases here */
-#if defined(_MSC_VER) || defined(__BORLANDC__) || \
-    defined(__DMC__) || defined(__SC__) || \
-    defined(__WATCOMC__) || defined(__LCC__) || \
-    defined(__DECC)
+#ifndef SDL_INLINE
+#if defined(__GNUC__)
+#define SDL_INLINE __inline__
+#elif defined(_MSC_VER) || defined(__BORLANDC__) || \
+      defined(__DMC__) || defined(__SC__) || \
+      defined(__WATCOMC__) || defined(__LCC__) || \
+      defined(__DECC)
+#define SDL_INLINE __inline
 #ifndef __inline__
-#define __inline__  __inline
+#define __inline__ __inline
 #endif
-#define SDL_INLINE_OKAY
 #else
-#if !defined(__MRC__) && !defined(_SGI_SOURCE)
+#define SDL_INLINE inline
 #ifndef __inline__
 #define __inline__ inline
 #endif
-#define SDL_INLINE_OKAY
-#endif /* Not a funky compiler */
-#endif /* Visual C++ */
-#endif /* GNU C */
-#endif /* SDL_INLINE_OKAY */
-
-/* If inlining isn't supported, remove "__inline__", turning static
-   inlined functions into static functions (resulting in code bloat
-   in all files which include the offending header files)
-*/
-#ifndef SDL_INLINE_OKAY
-#define __inline__
 #endif
+#endif /* SDL_INLINE not defined */
 
 #ifndef SDL_FORCE_INLINE
 #if defined(_MSC_VER)
 #define SDL_FORCE_INLINE __forceinline
 #elif ( (defined(__GNUC__) && (__GNUC__ >= 4)) || defined(__clang__) )
-#define SDL_FORCE_INLINE __attribute__((always_inline)) static inline
+#define SDL_FORCE_INLINE __attribute__((always_inline)) static __inline__
 #else
-#define SDL_FORCE_INLINE static __inline__
-#endif
+#define SDL_FORCE_INLINE static SDL_INLINE
 #endif
+#endif /* SDL_FORCE_INLINE not defined */
 
 /* Apparently this is needed by several Windows compilers */
 #if !defined(__MACH__)

+ 4 - 0
Source/ThirdParty/SDL/src/SDL.c

@@ -23,6 +23,10 @@
 
 #include "SDL_config.h"
 
+#if defined(__WIN32__)
+#include "core/windows/SDL_windows.h"
+#endif
+
 /* Initialization code for SDL */
 
 #include "SDL.h"

+ 4 - 2
Source/ThirdParty/SDL/src/SDL_assert.c

@@ -20,6 +20,10 @@
 */
 #include "SDL_config.h"
 
+#if defined(__WIN32__)
+#include "core/windows/SDL_windows.h"
+#endif
+
 #include "SDL.h"
 #include "SDL_atomic.h"
 #include "SDL_messagebox.h"
@@ -29,8 +33,6 @@
 #include "video/SDL_sysvideo.h"
 
 #ifdef __WIN32__
-#include "core/windows/SDL_windows.h"
-
 #ifndef WS_OVERLAPPEDWINDOW
 #define WS_OVERLAPPEDWINDOW 0
 #endif

+ 3 - 11
Source/ThirdParty/SDL/src/SDL_hints.c

@@ -72,14 +72,8 @@ SDL_SetHintWithPriority(const char *name, const char *value,
                     entry->callback(entry->userdata, name, hint->value, value);
                     entry = next;
                 }
-                if (hint->value) {
-                    SDL_free(hint->value);
-                }
-                if (value) {
-                    hint->value = SDL_strdup(value);
-                } else {
-                    hint->value = NULL;
-                }
+                SDL_free(hint->value);
+                hint->value = value ? SDL_strdup(value) : NULL;
             }
             hint->priority = priority;
             return SDL_TRUE;
@@ -210,9 +204,7 @@ void SDL_ClearHints(void)
         SDL_hints = hint->next;
 
         SDL_free(hint->name);
-        if (hint->value) {
-            SDL_free(hint->value);
-        }
+        SDL_free(hint->value);
         for (entry = hint->callbacks; entry; ) {
             SDL_HintWatch *freeable = entry;
             entry = entry->next;

+ 13 - 10
Source/ThirdParty/SDL/src/SDL_log.c

@@ -20,6 +20,10 @@
 */
 #include "SDL_config.h"
 
+#if defined(__WIN32__)
+#include "core/windows/SDL_windows.h"
+#endif
+
 /* Simple log messages in SDL */
 
 #include "SDL_log.h"
@@ -28,9 +32,7 @@
 #include <stdio.h>
 #endif
 
-#if defined(__WIN32__)
-#include "core/windows/SDL_windows.h"
-#elif defined(__ANDROID__)
+#if defined(__ANDROID__)
 #include <android/log.h>
 #endif
 
@@ -84,6 +86,7 @@ static const char *SDL_category_prefixes[SDL_LOG_CATEGORY_RESERVED1] = {
 };
 
 static int SDL_android_priority[SDL_NUM_LOG_PRIORITIES] = {
+    ANDROID_LOG_UNKNOWN,
     ANDROID_LOG_VERBOSE,
     ANDROID_LOG_DEBUG,
     ANDROID_LOG_INFO,
@@ -332,16 +335,16 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
             if (!attachResult) {
                     attachError = GetLastError();
                     if (attachError == ERROR_INVALID_HANDLE) {
-                        OutputDebugString(TEXT("Parent process has no console"));
+                        OutputDebugString(TEXT("Parent process has no console\r\n"));
                         consoleAttached = -1;
                     } else if (attachError == ERROR_GEN_FAILURE) {
-                         OutputDebugString(TEXT("Could not attach to console of parent process"));
+                         OutputDebugString(TEXT("Could not attach to console of parent process\r\n"));
                          consoleAttached = -1;
                     } else if (attachError == ERROR_ACCESS_DENIED) {  
                          /* Already attached */
                         consoleAttached = 1;
                     } else {
-                        OutputDebugString(TEXT("Error attaching console"));
+                        OutputDebugString(TEXT("Error attaching console\r\n"));
                         consoleAttached = -1;
                     }
                 } else {
@@ -354,9 +357,9 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
                 }
         }
 
-        length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1;
+        length = SDL_strlen(SDL_priority_prefixes[priority]) + 2 + SDL_strlen(message) + 1 + 1 + 1;
         output = SDL_stack_alloc(char, length);
-        SDL_snprintf(output, length, "%s: %s\n", SDL_priority_prefixes[priority], message);
+        SDL_snprintf(output, length, "%s: %s\r\n", SDL_priority_prefixes[priority], message);
         tstr = WIN_UTF8ToString(output);
         
         /* Output to debugger */
@@ -365,10 +368,10 @@ SDL_LogOutput(void *userdata, int category, SDL_LogPriority priority,
         /* Screen output to stderr, if console was attached. */
         if (consoleAttached == 1) {
                 if (!WriteConsole(stderrHandle, tstr, lstrlen(tstr), &charsWritten, NULL)) {
-                    OutputDebugString(TEXT("Error calling WriteConsole"));
+                    OutputDebugString(TEXT("Error calling WriteConsole\r\n"));
                 }
                 if (charsWritten == ERROR_NOT_ENOUGH_MEMORY) {
-                    OutputDebugString(TEXT("Insufficient heap memory to write message"));
+                    OutputDebugString(TEXT("Insufficient heap memory to write message\r\n"));
                 }
         }
 

+ 2 - 2
Source/ThirdParty/SDL/src/atomic/SDL_atomic.c

@@ -55,7 +55,7 @@
 
 static SDL_SpinLock locks[32];
 
-static __inline__ void
+static SDL_INLINE void
 enterLock(void *a)
 {
     uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f);
@@ -63,7 +63,7 @@ enterLock(void *a)
     SDL_AtomicLock(&locks[index]);
 }
 
-static __inline__ void
+static SDL_INLINE void
 leaveLock(void *a)
 {
     uintptr_t index = ((((uintptr_t)a) >> 3) & 0x1f);

+ 4 - 4
Source/ThirdParty/SDL/src/atomic/SDL_spinlock.c

@@ -20,14 +20,14 @@
 */
 #include "SDL_config.h"
 
+#ifdef __WIN32__
+#include "../core/windows/SDL_windows.h"
+#endif
+
 #include "SDL_atomic.h"
 #include "SDL_mutex.h"
 #include "SDL_timer.h"
 
-/* Don't do the check for Visual Studio 2005, it's safe here */
-#ifdef __WIN32__
-#include "../core/windows/SDL_windows.h"
-#endif
 
 /* This function is where all the magic happens... */
 SDL_bool

+ 4 - 10
Source/ThirdParty/SDL/src/audio/SDL_audio.c

@@ -300,9 +300,7 @@ SDL_StreamInit(SDL_AudioStreamer * stream, int max_len, Uint8 silence)
 static void
 SDL_StreamDeinit(SDL_AudioStreamer * stream)
 {
-    if (stream->buffer != NULL) {
-        SDL_free(stream->buffer);
-    }
+    SDL_free(stream->buffer);
 }
 
 #if defined(ANDROID)
@@ -419,7 +417,7 @@ SDL_RunAudio(void *devicep)
                     if (istream == NULL) {
                         istream = device->fake_stream;
                     }
-                    /*SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
+                    /* SDL_memcpy(istream, device->convert.buf, device->convert.len_cvt); */
                     SDL_StreamWrite(&device->streamer, device->convert.buf,
                                     device->convert.len_cvt);
                 } else {
@@ -632,9 +630,7 @@ free_device_list(char ***devices, int *devCount)
         }
     }
 
-    if (*devices != NULL) {
-        SDL_free(*devices);
-    }
+    SDL_free(*devices);
 
     *devices = NULL;
     *devCount = 0;
@@ -761,9 +757,7 @@ close_audio_device(SDL_AudioDevice * device)
     if (device->mixer_lock != NULL) {
         SDL_DestroyMutex(device->mixer_lock);
     }
-    if (device->fake_stream != NULL) {
-        SDL_FreeAudioMem(device->fake_stream);
-    }
+    SDL_FreeAudioMem(device->fake_stream);
     if (device->convert.needed) {
         SDL_FreeAudioMem(device->convert.buf);
     }

+ 1 - 1
Source/ThirdParty/SDL/src/audio/SDL_audiodev.c

@@ -46,7 +46,7 @@
 #define _PATH_DEV_AUDIO "/dev/audio"
 #endif
 
-static inline void
+static SDL_INLINE void
 test_device(const char *fname, int flags, int (*test) (int fd),
             SDL_AddAudioDevice addfn)
 {

+ 8 - 16
Source/ThirdParty/SDL/src/audio/SDL_wave.c

@@ -61,7 +61,7 @@ InitMS_ADPCM(WaveFMT * format)
         SDL_SwapLE16(format->bitspersample);
     rogue_feel = (Uint8 *) format + sizeof(*format);
     if (sizeof(*format) == 16) {
-        /*const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]);*/
+        /* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
         rogue_feel += sizeof(Uint16);
     }
     MS_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
@@ -242,7 +242,7 @@ InitIMA_ADPCM(WaveFMT * format)
         SDL_SwapLE16(format->bitspersample);
     rogue_feel = (Uint8 *) format + sizeof(*format);
     if (sizeof(*format) == 16) {
-        /*const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]);*/
+        /* const Uint16 extra_info = ((rogue_feel[1] << 8) | rogue_feel[0]); */
         rogue_feel += sizeof(Uint16);
     }
     IMA_ADPCM_state.wSamplesPerBlock = ((rogue_feel[1] << 8) | rogue_feel[0]);
@@ -449,10 +449,8 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
     /* Read the audio data format chunk */
     chunk.data = NULL;
     do {
-        if (chunk.data != NULL) {
-            SDL_free(chunk.data);
-            chunk.data = NULL;
-        }
+        SDL_free(chunk.data);
+        chunk.data = NULL;
         lenread = ReadChunk(src, &chunk);
         if (lenread < 0) {
             was_error = 1;
@@ -549,10 +547,8 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
     /* Read the audio data chunk */
     *audio_buf = NULL;
     do {
-        if (*audio_buf != NULL) {
-            SDL_free(*audio_buf);
-            *audio_buf = NULL;
-        }
+        SDL_free(*audio_buf);
+        *audio_buf = NULL;
         lenread = ReadChunk(src, &chunk);
         if (lenread < 0) {
             was_error = 1;
@@ -583,9 +579,7 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
     *audio_len &= ~(samplesize - 1);
 
   done:
-    if (format != NULL) {
-        SDL_free(format);
-    }
+    SDL_free(format);
     if (src) {
         if (freesrc) {
             SDL_RWclose(src);
@@ -606,9 +600,7 @@ SDL_LoadWAV_RW(SDL_RWops * src, int freesrc,
 void
 SDL_FreeWAV(Uint8 * audio_buf)
 {
-    if (audio_buf != NULL) {
-        SDL_free(audio_buf);
-    }
+    SDL_free(audio_buf);
 }
 
 static int

+ 8 - 10
Source/ThirdParty/SDL/src/audio/alsa/SDL_alsa_audio.c

@@ -241,25 +241,25 @@ ALSA_WaitDevice(_THIS)
         tmp = ptr[3]; ptr[3] = ptr[5]; ptr[5] = tmp; \
     }
 
-static __inline__ void
+static SDL_INLINE void
 swizzle_alsa_channels_6_64bit(_THIS)
 {
     SWIZ6(Uint64);
 }
 
-static __inline__ void
+static SDL_INLINE void
 swizzle_alsa_channels_6_32bit(_THIS)
 {
     SWIZ6(Uint32);
 }
 
-static __inline__ void
+static SDL_INLINE void
 swizzle_alsa_channels_6_16bit(_THIS)
 {
     SWIZ6(Uint16);
 }
 
-static __inline__ void
+static SDL_INLINE void
 swizzle_alsa_channels_6_8bit(_THIS)
 {
     SWIZ6(Uint8);
@@ -272,7 +272,7 @@ swizzle_alsa_channels_6_8bit(_THIS)
  * Called right before feeding this->hidden->mixbuf to the hardware. Swizzle
  *  channels from Windows/Mac order to the format alsalib will want.
  */
-static __inline__ void
+static SDL_INLINE void
 swizzle_alsa_channels(_THIS)
 {
     if (this->spec.channels == 6) {
@@ -304,7 +304,7 @@ ALSA_PlayDevice(_THIS)
 
     while ( frames_left > 0 && this->enabled ) {
         /* !!! FIXME: This works, but needs more testing before going live */
-        /*ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1);*/
+        /* ALSA_snd_pcm_wait(this->hidden->pcm_handle, -1); */
         status = ALSA_snd_pcm_writei(this->hidden->pcm_handle,
                                      sample_buf, frames_left);
 
@@ -340,10 +340,8 @@ static void
 ALSA_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->pcm_handle) {
             ALSA_snd_pcm_drain(this->hidden->pcm_handle);
             ALSA_snd_pcm_close(this->hidden->pcm_handle);

+ 3 - 5
Source/ThirdParty/SDL/src/audio/arts/SDL_artsaudio.c

@@ -204,10 +204,8 @@ static void
 ARTS_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->stream) {
             SDL_NAME(arts_close_stream) (this->hidden->stream);
             this->hidden->stream = 0;
@@ -222,7 +220,7 @@ static int
 ARTS_Suspend(void)
 {
     const Uint32 abortms = SDL_GetTicks() + 3000; /* give up after 3 secs */
-    while ( (!SDL_NAME(arts_suspended)()) && (SDL_GetTicks() < abortms) ) {
+    while ( (!SDL_NAME(arts_suspended)()) && !SDL_TICKS_PASSED(SDL_GetTicks(), abortms) ) {
         if ( SDL_NAME(arts_suspend)() ) {
             break;
         }

+ 3 - 7
Source/ThirdParty/SDL/src/audio/bsd/SDL_bsdaudio.c

@@ -125,9 +125,7 @@ BSDAUDIO_WaitDevice(_THIS)
         /* Use timer for general audio synchronization */
         Sint32 ticks;
 
-        ticks =
-            ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) -
-            FUDGE_TICKS;
+        ticks = ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
         if (ticks > 0) {
             SDL_Delay(ticks);
         }
@@ -214,10 +212,8 @@ static void
 BSDAUDIO_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->audio_fd >= 0) {
             close(this->hidden->audio_fd);
             this->hidden->audio_fd = -1;

+ 3 - 11
Source/ThirdParty/SDL/src/audio/directsound/SDL_directsound.c

@@ -91,14 +91,6 @@ DSOUND_Load(void)
     return loaded;
 }
 
-static __inline__ char *
-utf16_to_utf8(const WCHAR *S)
-{
-    /* !!! FIXME: this should be UTF-16, not UCS-2! */
-    return SDL_iconv_string("UTF-8", "UCS-2", (char *)(S),
-                            (SDL_wcslen(S)+1)*sizeof(WCHAR));
-}
-
 static int
 SetDSerror(const char *function, int code)
 {
@@ -158,7 +150,7 @@ FindAllDevs(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID data)
 {
     SDL_AddAudioDevice addfn = (SDL_AddAudioDevice) data;
     if (guid != NULL) {  /* skip default device */
-        char *str = utf16_to_utf8(desc);
+        char *str = WIN_StringToUTF8(desc);
         if (str != NULL) {
             addfn(str);
             SDL_free(str);  /* addfn() makes a copy of this string. */
@@ -439,7 +431,7 @@ FindDevGUID(LPGUID guid, LPCWSTR desc, LPCWSTR module, LPVOID _data)
 {
     if (guid != NULL) {  /* skip the default device. */
         FindDevGUIDData *data = (FindDevGUIDData *) _data;
-        char *str = utf16_to_utf8(desc);
+        char *str = WIN_StringToUTF8(desc);
         const int match = (SDL_strcmp(str, data->devname) == 0);
         SDL_free(str);
         if (match) {
@@ -510,7 +502,7 @@ DSOUND_OpenDevice(_THIS, const char *devname, int iscapture)
     if (!valid_format) {
         DSOUND_CloseDevice(this);
         if (tried_format) {
-            return -1;  // CreateSecondary() should have called SDL_SetError().
+            return -1;  /* CreateSecondary() should have called SDL_SetError(). */
         }
         return SDL_SetError("DirectSound: Unsupported audio format");
     }

+ 2 - 4
Source/ThirdParty/SDL/src/audio/disk/SDL_diskaudio.c

@@ -88,10 +88,8 @@ static void
 DISKAUD_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->output != NULL) {
             SDL_RWclose(this->hidden->output);
             this->hidden->output = NULL;

+ 2 - 4
Source/ThirdParty/SDL/src/audio/dsp/SDL_dspaudio.c

@@ -61,10 +61,8 @@ static void
 DSP_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->audio_fd >= 0) {
             close(this->hidden->audio_fd);
             this->hidden->audio_fd = -1;

+ 3 - 6
Source/ThirdParty/SDL/src/audio/esd/SDL_esdaudio.c

@@ -135,8 +135,7 @@ ESD_WaitDevice(_THIS)
     }
 
     /* Use timer for general audio synchronization */
-    ticks =
-        ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
+    ticks = ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
     if (ticks > 0) {
         SDL_Delay(ticks);
     }
@@ -176,10 +175,8 @@ static void
 ESD_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->audio_fd >= 0) {
             SDL_NAME(esd_close) (this->hidden->audio_fd);
             this->hidden->audio_fd = -1;

+ 2 - 4
Source/ThirdParty/SDL/src/audio/fusionsound/SDL_fsaudio.c

@@ -169,10 +169,8 @@ static void
 SDL_FS_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->stream) {
             this->hidden->stream->Release(this->hidden->stream);
             this->hidden->stream = NULL;

+ 2 - 4
Source/ThirdParty/SDL/src/audio/nas/SDL_nasaudio.c

@@ -191,10 +191,8 @@ static void
 NAS_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->aud) {
             NAS_AuCloseServer(this->hidden->aud);
             this->hidden->aud = 0;

+ 3 - 7
Source/ThirdParty/SDL/src/audio/paudio/SDL_paudio.c

@@ -133,9 +133,7 @@ PAUDIO_WaitDevice(_THIS)
         /* Use timer for general audio synchronization */
         Sint32 ticks;
 
-        ticks =
-            ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) -
-            FUDGE_TICKS;
+        ticks = ((Sint32) (this->hidden->next_frame - SDL_GetTicks())) - FUDGE_TICKS;
         if (ticks > 0) {
             SDL_Delay(ticks);
         }
@@ -231,10 +229,8 @@ static void
 PAUDIO_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->audio_fd >= 0) {
             close(this->hidden->audio_fd);
             this->hidden->audio_fd = -1;

+ 5 - 5
Source/ThirdParty/SDL/src/audio/psp/SDL_pspaudio.c

@@ -63,7 +63,7 @@ PSPAUD_OpenDevice(_THIS, const char *devname, int iscapture)
     this->spec.freq = 44100;
 
     /* Update the fragment size as size in bytes. */
-//  SDL_CalculateAudioSpec(this->spec); MOD
+/*  SDL_CalculateAudioSpec(this->spec); MOD */
     switch (this->spec.format) {
     case AUDIO_U8:
         this->spec.silence = 0x80;
@@ -76,7 +76,7 @@ PSPAUD_OpenDevice(_THIS, const char *devname, int iscapture)
     this->spec.size *= this->spec.channels;
     this->spec.size *= this->spec.samples;
 
-//==========================================
+/* ========================================== */
 
     /* Allocate the mixing buffer.  Its size and starting address must
        be a multiple of 64 bytes.  Our sample count is already a multiple of
@@ -162,7 +162,7 @@ static int
 PSPAUD_Init(SDL_AudioDriverImpl * impl)
 {
 
-    // Set the function pointers
+    /* Set the function pointers */
     impl->OpenDevice = PSPAUD_OpenDevice;
     impl->PlayDevice = PSPAUD_PlayDevice;
     impl->WaitDevice = PSPAUD_WaitDevice;
@@ -171,7 +171,7 @@ PSPAUD_Init(SDL_AudioDriverImpl * impl)
     impl->CloseDevice = PSPAUD_CloseDevice;
     impl->ThreadInit = PSPAUD_ThreadInit;
 
-    //PSP audio device
+    /* PSP audio device */
     impl->OnlyHasDefaultOutputDevice = 1;
 /*
     impl->HasCaptureSupport = 1;
@@ -189,7 +189,7 @@ AudioBootStrap PSPAUD_bootstrap = {
     "psp", "PSP audio driver", PSPAUD_Init, 0
 };
 
- /* SDL_AUDI*/
+ /* SDL_AUDI */
 
 
 

+ 5 - 7
Source/ThirdParty/SDL/src/audio/pulseaudio/SDL_pulseaudio.c

@@ -49,7 +49,7 @@
 
 #if (PA_API_VERSION < 12)
 /** Return non-zero if the passed state is one of the connected states */
-static __inline__ int PA_CONTEXT_IS_GOOD(pa_context_state_t x) {
+static SDL_INLINE int PA_CONTEXT_IS_GOOD(pa_context_state_t x) {
     return
         x == PA_CONTEXT_CONNECTING ||
         x == PA_CONTEXT_AUTHORIZING ||
@@ -57,7 +57,7 @@ static __inline__ int PA_CONTEXT_IS_GOOD(pa_context_state_t x) {
         x == PA_CONTEXT_READY;
 }
 /** Return non-zero if the passed state is one of the connected states */
-static __inline__ int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
+static SDL_INLINE int PA_STREAM_IS_GOOD(pa_stream_state_t x) {
     return
         x == PA_STREAM_CREATING ||
         x == PA_STREAM_READY;
@@ -300,10 +300,8 @@ static void
 PULSEAUDIO_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if (this->hidden->stream) {
             PULSEAUDIO_pa_stream_disconnect(this->hidden->stream);
             PULSEAUDIO_pa_stream_unref(this->hidden->stream);
@@ -324,7 +322,7 @@ PULSEAUDIO_CloseDevice(_THIS)
 }
 
 
-static __inline__ int
+static SDL_INLINE int
 squashVersion(const int major, const int minor, const int patch)
 {
     return ((major & 0xFF) << 16) | ((minor & 0xFF) << 8) | (patch & 0xFF);

+ 3 - 5
Source/ThirdParty/SDL/src/audio/qsa/SDL_qsa_audio.c

@@ -83,7 +83,7 @@ uint32_t qsa_playback_devices;
 QSA_Device qsa_capture_device[QSA_MAX_DEVICES];
 uint32_t qsa_capture_devices;
 
-static inline int
+static SDL_INLINE int
 QSA_SetError(const char *fn, int status)
 {
     return SDL_SetError("QSA: %s() failed: %s", fn, snd_strerror(status));
@@ -328,10 +328,8 @@ QSA_CloseDevice(_THIS)
             this->hidden->audio_handle = NULL;
         }
 
-        if (this->hidden->pcm_buf != NULL) {
-            SDL_FreeAudioMem(this->hidden->pcm_buf);
-            this->hidden->pcm_buf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->pcm_buf);
+        this->hidden->pcm_buf = NULL;
 
         SDL_free(this->hidden);
         this->hidden = NULL;

+ 2 - 4
Source/ThirdParty/SDL/src/audio/sndio/SDL_sndioaudio.c

@@ -181,10 +181,8 @@ static void
 SNDIO_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
         if ( this->hidden->dev != NULL ) {
             SNDIO_sio_close(this->hidden->dev);
             this->hidden->dev = NULL;

+ 4 - 8
Source/ThirdParty/SDL/src/audio/sun/SDL_sunaudio.c

@@ -184,14 +184,10 @@ static void
 SUNAUDIO_CloseDevice(_THIS)
 {
     if (this->hidden != NULL) {
-        if (this->hidden->mixbuf != NULL) {
-            SDL_FreeAudioMem(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
-        if (this->hidden->ulaw_buf != NULL) {
-            SDL_free(this->hidden->ulaw_buf);
-            this->hidden->ulaw_buf = NULL;
-        }
+        SDL_FreeAudioMem(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
+        SDL_free(this->hidden->ulaw_buf);
+        this->hidden->ulaw_buf = NULL;
         if (this->hidden->audio_fd >= 0) {
             close(this->hidden->audio_fd);
             this->hidden->audio_fd = -1;

+ 3 - 5
Source/ThirdParty/SDL/src/audio/winmm/SDL_winmm.c

@@ -176,11 +176,9 @@ WINMM_CloseDevice(_THIS)
             }
         }
 
-        if (this->hidden->mixbuf != NULL) {
-            /* Free raw mixing buffer */
-            SDL_free(this->hidden->mixbuf);
-            this->hidden->mixbuf = NULL;
-        }
+        /* Free raw mixing buffer */
+        SDL_free(this->hidden->mixbuf);
+        this->hidden->mixbuf = NULL;
 
         if (this->hidden->hin) {
             waveInClose(this->hidden->hin);

+ 15 - 13
Source/ThirdParty/SDL/src/audio/xaudio2/SDL_xaudio2.c

@@ -48,6 +48,18 @@
 /* Hidden "this" pointer for the audio functions */
 #define _THIS   SDL_AudioDevice *this
 
+/* Fixes bug 1210 where some versions of gcc need named parameters */
+#ifdef __GNUC__
+#ifdef THIS
+#undef THIS
+#endif
+#define THIS    INTERFACE *p
+#ifdef THIS_
+#undef THIS_
+#endif
+#define THIS_   INTERFACE *p,
+#endif
+
 struct SDL_PrivateAudioData
 {
     IXAudio2 *ixa2;
@@ -60,14 +72,6 @@ struct SDL_PrivateAudioData
 };
 
 
-static __inline__ char *
-utf16_to_utf8(const WCHAR *S)
-{
-    /* !!! FIXME: this should be UTF-16, not UCS-2! */
-    return SDL_iconv_string("UTF-8", "UCS-2", (char *)(S),
-                            (SDL_wcslen(S)+1)*sizeof(WCHAR));
-}
-
 static void
 XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
 {
@@ -90,7 +94,7 @@ XAUDIO2_DetectDevices(int iscapture, SDL_AddAudioDevice addfn)
     for (i = 0; i < devcount; i++) {
         XAUDIO2_DEVICE_DETAILS details;
         if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
-            char *str = utf16_to_utf8(details.DisplayName);
+            char *str = WIN_StringToUTF8(details.DisplayName);
             if (str != NULL) {
                 addfn(str);
                 SDL_free(str);  /* addfn() made a copy of the string. */
@@ -213,9 +217,7 @@ XAUDIO2_CloseDevice(_THIS)
         if (ixa2 != NULL) {
             IXAudio2_Release(ixa2);
         }
-        if (this->hidden->mixbuf != NULL) {
-            SDL_free(this->hidden->mixbuf);
-        }
+        SDL_free(this->hidden->mixbuf);
         if (this->hidden->semaphore != NULL) {
             CloseHandle(this->hidden->semaphore);
         }
@@ -265,7 +267,7 @@ XAUDIO2_OpenDevice(_THIS, const char *devname, int iscapture)
         for (i = 0; i < devcount; i++) {
             XAUDIO2_DEVICE_DETAILS details;
             if (IXAudio2_GetDeviceDetails(ixa2, i, &details) == S_OK) {
-                char *str = utf16_to_utf8(details.DisplayName);
+                char *str = WIN_StringToUTF8(details.DisplayName);
                 if (str != NULL) {
                     const int match = (SDL_strcmp(str, devname) == 0);
                     SDL_free(str);

+ 1464 - 1420
Source/ThirdParty/SDL/src/core/android/SDL_android.c

@@ -1,1420 +1,1464 @@
-/*
-  Simple DirectMedia Layer
-  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-*/
-
-// Modified by Lasse Oorni for Urho3D
-
-#include "SDL_config.h"
-#include "SDL_stdinc.h"
-#include "SDL_assert.h"
-#include "SDL_log.h"
-
-#ifdef __ANDROID__
-
-#include "SDL_system.h"
-#include "SDL_android.h"
-// Urho3D: do not require EGL to allow compiling on API level 8
-// #include <EGL/egl.h>
-#define EGL_BUFFER_SIZE			0x3020
-#define EGL_ALPHA_SIZE			0x3021
-#define EGL_BLUE_SIZE			0x3022
-#define EGL_GREEN_SIZE			0x3023
-#define EGL_RED_SIZE			0x3024
-#define EGL_DEPTH_SIZE			0x3025
-#define EGL_STENCIL_SIZE		0x3026
-#define EGL_SAMPLES			0x3031
-#define EGL_SAMPLE_BUFFERS		0x3032
-#define EGL_RENDERABLE_TYPE		0x3040
-#define EGL_OPENGL_ES_BIT		0x0001	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_OPENGL_ES2_BIT		0x0004	/* EGL_RENDERABLE_TYPE mask bits */
-#define EGL_NONE			0x3038	/* Attrib list terminator */
-
-#include "../../events/SDL_events_c.h"
-#include "../../video/android/SDL_androidkeyboard.h"
-#include "../../video/android/SDL_androidtouch.h"
-#include "../../video/android/SDL_androidvideo.h"
-
-#include <android/log.h>
-#include <pthread.h>
-#include <sys/types.h>
-#include <unistd.h>
-#define LOG_TAG "SDL_android"
-//#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
-//#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
-#define LOGI(...) do {} while (false)
-#define LOGE(...) do {} while (false)
-
-/* Uncomment this to log messages entering and exiting methods in this file */
-//#define DEBUG_JNI
-
-static void Android_JNI_ThreadDestroyed(void*);
-
-/*******************************************************************************
- This file links the Java side of Android with libsdl
-*******************************************************************************/
-#include <jni.h>
-#include <android/log.h>
-#include <stdbool.h>
-
-
-/*******************************************************************************
-                               Globals
-*******************************************************************************/
-static pthread_key_t mThreadKey;
-static JavaVM* mJavaVM;
-
-// Main activity
-static jclass mActivityClass;
-
-// method signatures
-static jmethodID midCreateGLContext;
-static jmethodID midDeleteGLContext;
-static jmethodID midFlipBuffers;
-static jmethodID midAudioInit;
-static jmethodID midAudioWriteShortBuffer;
-static jmethodID midAudioWriteByteBuffer;
-static jmethodID midAudioQuit;
-
-// Accelerometer data storage
-static float fLastAccelerometer[3];
-static bool bHasNewData;
-
-// Urho3D: application files dir
-static char* mFilesDir = 0;
-
-/*******************************************************************************
-                 Functions called by JNI
-*******************************************************************************/
-
-// Library init
-jint JNI_OnLoad(JavaVM* vm, void* reserved)
-{
-    JNIEnv *env;
-    mJavaVM = vm;
-    LOGI("JNI_OnLoad called");
-    if ((*mJavaVM)->GetEnv(mJavaVM, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
-        LOGE("Failed to get the environment using GetEnv()");
-        return -1;
-    }
-    /*
-     * Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
-     * Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
-     */
-    if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed)) {
-        __android_log_print(ANDROID_LOG_ERROR, "SDL", "Error initializing pthread key");
-    }
-    else {
-        Android_JNI_SetupThread();
-    }
-
-    return JNI_VERSION_1_4;
-}
-
-// Urho3D: added function
-const char* SDL_Android_GetFilesDir()
-{
-    return mFilesDir;
-}
-
-// Called before SDL_main() to initialize JNI bindings
-// Urho3D: added passing user files directory from SDLActivity on startup
-void SDL_Android_Init(JNIEnv* mEnv, jclass cls, jstring filesDir)
-{
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()");
-
-    Android_JNI_SetupThread();
-
-    // Copy the files dir
-    const char *str;
-    str = (*mEnv)->GetStringUTFChars(mEnv, filesDir, 0);
-    if (str)
-    {
-        if (mFilesDir)
-            free(mFilesDir);
-
-        size_t length = strlen(str) + 1;
-        mFilesDir = (char*)malloc(length);
-        memcpy(mFilesDir, str, length);
-        (*mEnv)->ReleaseStringUTFChars(mEnv, filesDir, str);
-    }
-
-    mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
-
-    midCreateGLContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "createGLContext","(II[I)Z");
-    midDeleteGLContext = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "deleteGLContext","()V");
-    midFlipBuffers = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "flipBuffers","()V");
-    midAudioInit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "audioInit", "(IZZI)I");
-    midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "audioWriteShortBuffer", "([S)V");
-    midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "audioWriteByteBuffer", "([B)V");
-    midAudioQuit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-                                "audioQuit", "()V");
-
-    bHasNewData = false;
-
-    if(!midCreateGLContext || !midFlipBuffers || !midAudioInit ||
-       !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) {
-        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
-    }
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init() finished!");
-}
-
-// Resize
-void Java_org_libsdl_app_SDLActivity_onNativeResize(
-                                    JNIEnv* env, jclass jcls,
-                                    jint width, jint height, jint format)
-{
-    Android_SetScreenResolution(width, height, format);
-}
-
-// Keydown
-void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
-                                    JNIEnv* env, jclass jcls, jint keycode)
-{
-    Android_OnKeyDown(keycode);
-}
-
-// Keyup
-void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
-                                    JNIEnv* env, jclass jcls, jint keycode)
-{
-    Android_OnKeyUp(keycode);
-}
-
-// Keyboard Focus Lost
-void Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost(
-                                    JNIEnv* env, jclass jcls)
-{
-    /* Calling SDL_StopTextInput will take care of hiding the keyboard and cleaning up the DummyText widget */
-    SDL_StopTextInput();
-}
-
-
-// Touch
-void Java_org_libsdl_app_SDLActivity_onNativeTouch(
-                                    JNIEnv* env, jclass jcls,
-                                    jint touch_device_id_in, jint pointer_finger_id_in,
-                                    jint action, jfloat x, jfloat y, jfloat p)
-{
-    Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
-}
-
-// Accelerometer
-void Java_org_libsdl_app_SDLActivity_onNativeAccel(
-                                    JNIEnv* env, jclass jcls,
-                                    jfloat x, jfloat y, jfloat z)
-{
-    fLastAccelerometer[0] = x;
-    fLastAccelerometer[1] = y;
-    fLastAccelerometer[2] = z;
-    bHasNewData = true;
-}
-
-// Low memory
-void Java_org_libsdl_app_SDLActivity_nativeLowMemory(
-                                    JNIEnv* env, jclass cls)
-{
-    SDL_SendAppEvent(SDL_APP_LOWMEMORY);
-}
-
-// Quit
-void Java_org_libsdl_app_SDLActivity_nativeQuit(
-                                    JNIEnv* env, jclass cls)
-{
-    // Urho3D: added log print
-    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeQuit()");
-    // Inject a SDL_QUIT event
-    SDL_SendQuit();
-    SDL_SendAppEvent(SDL_APP_TERMINATING);
-}
-
-// Pause
-void Java_org_libsdl_app_SDLActivity_nativePause(
-                                    JNIEnv* env, jclass cls)
-{
-    if (Android_Window) {
-        /* Signal the pause semaphore so the event loop knows to pause and (optionally) block itself */
-        if (!SDL_SemValue(Android_PauseSem)) SDL_SemPost(Android_PauseSem);
-        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
-        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
-    }
-
-    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativePause()");
-    SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
-    SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
-}
-
-// Resume
-void Java_org_libsdl_app_SDLActivity_nativeResume(
-                                    JNIEnv* env, jclass cls)
-{
-    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeResume()");
-    SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
-    SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
-
-    if (Android_Window) {
-        /* Signal the resume semaphore so the event loop knows to resume and restore the GL Context
-         * We can't restore the GL Context here because it needs to be done on the SDL main thread
-         * and this function will be called from the Java thread instead.
-         */
-        if (!SDL_SemValue(Android_ResumeSem)) SDL_SemPost(Android_ResumeSem);
-        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
-        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
-    }
-}
-
-void Java_org_libsdl_app_SDLInputConnection_nativeCommitText(
-                                    JNIEnv* env, jclass cls,
-                                    jstring text, jint newCursorPosition)
-{
-    const char *utftext = (*env)->GetStringUTFChars(env, text, NULL);
-
-    SDL_SendKeyboardText(utftext);
-
-    (*env)->ReleaseStringUTFChars(env, text, utftext);
-}
-
-void Java_org_libsdl_app_SDLInputConnection_nativeSetComposingText(
-                                    JNIEnv* env, jclass cls,
-                                    jstring text, jint newCursorPosition)
-{
-    const char *utftext = (*env)->GetStringUTFChars(env, text, NULL);
-
-    SDL_SendEditingText(utftext, 0, 0);
-
-    (*env)->ReleaseStringUTFChars(env, text, utftext);
-}
-
-
-
-/*******************************************************************************
-             Functions called by SDL into Java
-*******************************************************************************/
-
-static int s_active = 0;
-struct LocalReferenceHolder
-{
-    JNIEnv *m_env;
-    const char *m_func;
-};
-
-static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func)
-{
-    struct LocalReferenceHolder refholder;
-    refholder.m_env = NULL;
-    refholder.m_func = func;
-#ifdef DEBUG_JNI
-    SDL_Log("Entering function %s", func);
-#endif
-    return refholder;
-}
-
-static SDL_bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env)
-{
-    const int capacity = 16;
-    if ((*env)->PushLocalFrame(env, capacity) < 0) {
-        SDL_SetError("Failed to allocate enough JVM local references");
-        return SDL_FALSE;
-    }
-    ++s_active;
-    refholder->m_env = env;
-    return SDL_TRUE;
-}
-
-static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder)
-{
-#ifdef DEBUG_JNI
-    SDL_Log("Leaving function %s", refholder->m_func);
-#endif
-    if (refholder->m_env) {
-        JNIEnv* env = refholder->m_env;
-        (*env)->PopLocalFrame(env, NULL);
-        --s_active;
-    }
-}
-
-static SDL_bool LocalReferenceHolder_IsActive()
-{
-    return s_active > 0;    
-}
-
-
-SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion,
-                                int red, int green, int blue, int alpha,
-                                int buffer, int depth, int stencil,
-                                int buffers, int samples)
-{
-    JNIEnv *env = Android_JNI_GetEnv();
-
-    jint attribs[] = {
-        EGL_RED_SIZE, red,
-        EGL_GREEN_SIZE, green,
-        EGL_BLUE_SIZE, blue,
-        EGL_ALPHA_SIZE, alpha,
-        EGL_BUFFER_SIZE, buffer,
-        EGL_DEPTH_SIZE, depth,
-        EGL_STENCIL_SIZE, stencil,
-        EGL_SAMPLE_BUFFERS, buffers,
-        EGL_SAMPLES, samples,
-        EGL_RENDERABLE_TYPE, (majorVersion == 1 ? EGL_OPENGL_ES_BIT : EGL_OPENGL_ES2_BIT),
-        EGL_NONE
-    };
-    int len = SDL_arraysize(attribs);
-
-    jintArray array;
-
-    array = (*env)->NewIntArray(env, len);
-    (*env)->SetIntArrayRegion(env, array, 0, len, attribs);
-
-    jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, midCreateGLContext, majorVersion, minorVersion, array);
-
-    (*env)->DeleteLocalRef(env, array);
-
-    return success ? SDL_TRUE : SDL_FALSE;
-}
-
-SDL_bool Android_JNI_DeleteContext(void)
-{
-    /* There's only one context, so no parameter for now */
-    JNIEnv *env = Android_JNI_GetEnv();
-    (*env)->CallStaticVoidMethod(env, mActivityClass, midDeleteGLContext);
-    return SDL_TRUE;
-}
-
-void Android_JNI_SwapWindow()
-{
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-    (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, midFlipBuffers);
-}
-
-void Android_JNI_SetActivityTitle(const char *title)
-{
-    jmethodID mid;
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,"setActivityTitle","(Ljava/lang/String;)Z");
-    if (mid) {
-        jstring jtitle = (jstring)((*mEnv)->NewStringUTF(mEnv, title));
-        (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, mid, jtitle);
-        (*mEnv)->DeleteLocalRef(mEnv, jtitle);
-    }
-}
-
-SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
-{
-    int i;
-    SDL_bool retval = SDL_FALSE;
-
-    if (bHasNewData) {
-        for (i = 0; i < 3; ++i) {
-            values[i] = fLastAccelerometer[i];
-        }
-        bHasNewData = false;
-        retval = SDL_TRUE;
-    }
-
-    return retval;
-}
-
-// Urho3D: added function
-void Android_JNI_FinishActivity()
-{
-    // Terminating the SDL main thread on our own may cause crashes with extra threads, so request
-    // the activity to finish instead
-    jmethodID mid;
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "finishActivity","()V");
-    if (mid)
-        (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, mid);
-}
-
-static void Android_JNI_ThreadDestroyed(void* value) {
-    /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
-    JNIEnv *env = (JNIEnv*) value;
-    if (env != NULL) {
-        (*mJavaVM)->DetachCurrentThread(mJavaVM);
-        pthread_setspecific(mThreadKey, NULL);
-    }
-}
-
-JNIEnv* Android_JNI_GetEnv(void) {
-    /* From http://developer.android.com/guide/practices/jni.html
-     * All threads are Linux threads, scheduled by the kernel.
-     * They're usually started from managed code (using Thread.start), but they can also be created elsewhere and then
-     * attached to the JavaVM. For example, a thread started with pthread_create can be attached with the
-     * JNI AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a thread is attached, it has no JNIEnv,
-     * and cannot make JNI calls.
-     * Attaching a natively-created thread causes a java.lang.Thread object to be constructed and added to the "main"
-     * ThreadGroup, making it visible to the debugger. Calling AttachCurrentThread on an already-attached thread
-     * is a no-op.
-     * Note: You can call this function any number of times for the same thread, there's no harm in it
-     */
-
-    JNIEnv *env;
-    int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env, NULL);
-    if(status < 0) {
-        LOGE("failed to attach current thread");
-        return 0;
-    }
-
-    return env;
-}
-
-int Android_JNI_SetupThread(void) {
-    /* From http://developer.android.com/guide/practices/jni.html
-     * Threads attached through JNI must call DetachCurrentThread before they exit. If coding this directly is awkward,
-     * in Android 2.0 (Eclair) and higher you can use pthread_key_create to define a destructor function that will be
-     * called before the thread exits, and call DetachCurrentThread from there. (Use that key with pthread_setspecific
-     * to store the JNIEnv in thread-local-storage; that way it'll be passed into your destructor as the argument.)
-     * Note: The destructor is not called unless the stored value is != NULL
-     * Note: You can call this function any number of times for the same thread, there's no harm in it
-     *       (except for some lost CPU cycles)
-     */
-    JNIEnv *env = Android_JNI_GetEnv();
-    pthread_setspecific(mThreadKey, (void*) env);
-    return 1;
-}
-
-//
-// Audio support
-//
-static jboolean audioBuffer16Bit = JNI_FALSE;
-static jboolean audioBufferStereo = JNI_FALSE;
-static jobject audioBuffer = NULL;
-static void* audioBufferPinned = NULL;
-
-int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
-{
-    int audioBufferFrames;
-
-    JNIEnv *env = Android_JNI_GetEnv();
-
-    if (!env) {
-        LOGE("callback_handler: failed to attach current thread");
-    }
-    Android_JNI_SetupThread();
-
-    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
-    audioBuffer16Bit = is16Bit;
-    audioBufferStereo = channelCount > 1;
-
-    if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
-        /* Error during audio initialization */
-        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
-        return 0;
-    }
-
-    /* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on
-     * Android >= 4.2 due to a "stale global reference" error. So now we allocate this buffer directly from this side. */
-
-    if (is16Bit) {
-        jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
-        if (audioBufferLocal) {
-            audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
-            (*env)->DeleteLocalRef(env, audioBufferLocal);
-        }
-    }
-    else {
-        jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
-        if (audioBufferLocal) {
-            audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
-            (*env)->DeleteLocalRef(env, audioBufferLocal);
-        }
-    }
-
-    if (audioBuffer == NULL) {
-        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer!");
-        return 0;
-    }
-
-    jboolean isCopy = JNI_FALSE;
-    if (audioBuffer16Bit) {
-        audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
-        audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
-    } else {
-        audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
-        audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
-    }
-    if (audioBufferStereo) {
-        audioBufferFrames /= 2;
-    }
-
-    return audioBufferFrames;
-}
-
-void * Android_JNI_GetAudioBuffer()
-{
-    return audioBufferPinned;
-}
-
-void Android_JNI_WriteAudioBuffer()
-{
-    JNIEnv *mAudioEnv = Android_JNI_GetEnv();
-
-    if (audioBuffer16Bit) {
-        (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
-        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
-    } else {
-        (*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
-        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
-    }
-
-    /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
-}
-
-void Android_JNI_CloseAudioDevice()
-{
-    JNIEnv *env = Android_JNI_GetEnv();
-
-    (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioQuit);
-
-    if (audioBuffer) {
-        (*env)->DeleteGlobalRef(env, audioBuffer);
-        audioBuffer = NULL;
-        audioBufferPinned = NULL;
-    }
-}
-
-// Test for an exception and call SDL_SetError with its detail if one occurs
-// If the parameter silent is truthy then SDL_SetError() will not be called.
-static bool Android_JNI_ExceptionOccurred(bool silent)
-{
-    SDL_assert(LocalReferenceHolder_IsActive());
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-
-    jthrowable exception = (*mEnv)->ExceptionOccurred(mEnv);
-    if (exception != NULL) {
-        jmethodID mid;
-
-        // Until this happens most JNI operations have undefined behaviour
-        (*mEnv)->ExceptionClear(mEnv);
-
-        if (!silent) {
-            jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
-            jclass classClass = (*mEnv)->FindClass(mEnv, "java/lang/Class");
-
-            mid = (*mEnv)->GetMethodID(mEnv, classClass, "getName", "()Ljava/lang/String;");
-            jstring exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
-            const char* exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
-
-            mid = (*mEnv)->GetMethodID(mEnv, exceptionClass, "getMessage", "()Ljava/lang/String;");
-            jstring exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
-
-            if (exceptionMessage != NULL) {
-                const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
-                SDL_SetError("%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
-                (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionMessage, exceptionMessageUTF8);
-            } else {
-                SDL_SetError("%s", exceptionNameUTF8);
-            }
-
-            (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionName, exceptionNameUTF8);
-        }
-
-        return true;
-    }
-
-    return false;
-}
-
-static int Internal_Android_JNI_FileOpen(SDL_RWops* ctx)
-{
-    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
-
-    int result = 0;
-
-    jmethodID mid;
-    jobject context;
-    jobject assetManager;
-    jobject inputStream;
-    jclass channels;
-    jobject readableByteChannel;
-    jstring fileNameJString;
-    jobject fd;
-    jclass fdCls;
-    jfieldID descriptor;
-
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-    if (!LocalReferenceHolder_Init(&refs, mEnv)) {
-        goto failure;
-    }
-
-    fileNameJString = (jstring)ctx->hidden.androidio.fileNameRef;
-    ctx->hidden.androidio.position = 0;
-
-    // context = SDLActivity.getContext();
-    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
-            "getContext","()Landroid/content/Context;");
-    context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, mid);
-
-
-    // assetManager = context.getAssets();
-    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
-            "getAssets", "()Landroid/content/res/AssetManager;");
-    assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
-
-    /* First let's try opening the file to obtain an AssetFileDescriptor.
-    * This method reads the files directly from the APKs using standard *nix calls
-    */
-    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager), "openFd", "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
-    inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString);
-    if (Android_JNI_ExceptionOccurred(true)) {
-        goto fallback;
-    }
-
-    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getStartOffset", "()J");
-    ctx->hidden.androidio.offset = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
-    if (Android_JNI_ExceptionOccurred(true)) {
-        goto fallback;
-    }
-
-    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getDeclaredLength", "()J");
-    ctx->hidden.androidio.size = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
-    if (Android_JNI_ExceptionOccurred(true)) {
-        goto fallback;
-    }
-
-    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getFileDescriptor", "()Ljava/io/FileDescriptor;");
-    fd = (*mEnv)->CallObjectMethod(mEnv, inputStream, mid);
-    fdCls = (*mEnv)->GetObjectClass(mEnv, fd);
-    descriptor = (*mEnv)->GetFieldID(mEnv, fdCls, "descriptor", "I");
-    ctx->hidden.androidio.fd = (*mEnv)->GetIntField(mEnv, fd, descriptor);
-    ctx->hidden.androidio.assetFileDescriptorRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
-
-    // Seek to the correct offset in the file.
-    lseek(ctx->hidden.androidio.fd, (off_t)ctx->hidden.androidio.offset, SEEK_SET);
-
-    if (false) {
-fallback:
-        // Disabled log message because of spam on the Nexus 7
-        //__android_log_print(ANDROID_LOG_DEBUG, "SDL", "Falling back to legacy InputStream method for opening file");
-
-        /* Try the old method using InputStream */
-        ctx->hidden.androidio.assetFileDescriptorRef = NULL;
-
-        // inputStream = assetManager.open(<filename>);
-        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
-                "open", "(Ljava/lang/String;I)Ljava/io/InputStream;");
-        inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 /*ACCESS_RANDOM*/);
-        if (Android_JNI_ExceptionOccurred(false)) {
-            goto failure;
-        }
-
-        ctx->hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
-
-        // Despite all the visible documentation on [Asset]InputStream claiming
-        // that the .available() method is not guaranteed to return the entire file
-        // size, comments in <sdk>/samples/<ver>/ApiDemos/src/com/example/ ...
-        // android/apis/content/ReadAsset.java imply that Android's
-        // AssetInputStream.available() /will/ always return the total file size
-
-        // size = inputStream.available();
-        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
-                "available", "()I");
-        ctx->hidden.androidio.size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
-        if (Android_JNI_ExceptionOccurred(false)) {
-            goto failure;
-        }
-
-        // readableByteChannel = Channels.newChannel(inputStream);
-        channels = (*mEnv)->FindClass(mEnv, "java/nio/channels/Channels");
-        mid = (*mEnv)->GetStaticMethodID(mEnv, channels,
-                "newChannel",
-                "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
-        readableByteChannel = (*mEnv)->CallStaticObjectMethod(
-                mEnv, channels, mid, inputStream);
-        if (Android_JNI_ExceptionOccurred(false)) {
-            goto failure;
-        }
-
-        ctx->hidden.androidio.readableByteChannelRef =
-            (*mEnv)->NewGlobalRef(mEnv, readableByteChannel);
-
-        // Store .read id for reading purposes
-        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, readableByteChannel),
-                "read", "(Ljava/nio/ByteBuffer;)I");
-        ctx->hidden.androidio.readMethod = mid;
-    }
-
-    if (false) {
-failure:
-        result = -1;
-
-        (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.fileNameRef);
-
-        if(ctx->hidden.androidio.inputStreamRef != NULL) {
-            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.inputStreamRef);
-        }
-
-        if(ctx->hidden.androidio.readableByteChannelRef != NULL) {
-            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.readableByteChannelRef);
-        }
-
-        if(ctx->hidden.androidio.assetFileDescriptorRef != NULL) {
-            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.assetFileDescriptorRef);
-        }
-
-    }
-    
-    LocalReferenceHolder_Cleanup(&refs);
-    return result;
-}
-
-int Android_JNI_FileOpen(SDL_RWops* ctx,
-        const char* fileName, const char* mode)
-{
-    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-    int retval;
-
-    if (!LocalReferenceHolder_Init(&refs, mEnv)) {
-        LocalReferenceHolder_Cleanup(&refs);        
-        return -1;
-    }
-
-    if (!ctx) {
-        LocalReferenceHolder_Cleanup(&refs);
-        return -1;
-    }
-
-    jstring fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
-    ctx->hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
-    ctx->hidden.androidio.inputStreamRef = NULL;
-    ctx->hidden.androidio.readableByteChannelRef = NULL;
-    ctx->hidden.androidio.readMethod = NULL;
-    ctx->hidden.androidio.assetFileDescriptorRef = NULL;
-
-    retval = Internal_Android_JNI_FileOpen(ctx);
-    LocalReferenceHolder_Cleanup(&refs);
-    return retval;
-}
-
-size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
-        size_t size, size_t maxnum)
-{
-    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
-
-    if (ctx->hidden.androidio.assetFileDescriptorRef) {
-        size_t bytesMax = size * maxnum;
-        if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && ctx->hidden.androidio.position + bytesMax > ctx->hidden.androidio.size) {
-            bytesMax = ctx->hidden.androidio.size - ctx->hidden.androidio.position;
-        }
-        size_t result = read(ctx->hidden.androidio.fd, buffer, bytesMax );
-        if (result > 0) {
-            ctx->hidden.androidio.position += result;
-            LocalReferenceHolder_Cleanup(&refs);
-            return result / size;
-        }
-        LocalReferenceHolder_Cleanup(&refs);
-        return 0;
-    } else {
-        jlong bytesRemaining = (jlong) (size * maxnum);
-        jlong bytesMax = (jlong) (ctx->hidden.androidio.size -  ctx->hidden.androidio.position);
-        int bytesRead = 0;
-
-        /* Don't read more bytes than those that remain in the file, otherwise we get an exception */
-        if (bytesRemaining >  bytesMax) bytesRemaining = bytesMax;
-
-        JNIEnv *mEnv = Android_JNI_GetEnv();
-        if (!LocalReferenceHolder_Init(&refs, mEnv)) {
-            LocalReferenceHolder_Cleanup(&refs);            
-            return 0;
-        }
-
-        jobject readableByteChannel = (jobject)ctx->hidden.androidio.readableByteChannelRef;
-        jmethodID readMethod = (jmethodID)ctx->hidden.androidio.readMethod;
-        jobject byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
-
-        while (bytesRemaining > 0) {
-            // result = readableByteChannel.read(...);
-            int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
-
-            if (Android_JNI_ExceptionOccurred(false)) {
-                LocalReferenceHolder_Cleanup(&refs);            
-                return 0;
-            }
-
-            if (result < 0) {
-                break;
-            }
-
-            bytesRemaining -= result;
-            bytesRead += result;
-            ctx->hidden.androidio.position += result;
-        }
-        LocalReferenceHolder_Cleanup(&refs);                    
-        return bytesRead / size;
-    }
-}
-
-size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer,
-        size_t size, size_t num)
-{
-    SDL_SetError("Cannot write to Android package filesystem");
-    return 0;
-}
-
-static int Internal_Android_JNI_FileClose(SDL_RWops* ctx, bool release)
-{
-    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
-
-    int result = 0;
-    JNIEnv *mEnv = Android_JNI_GetEnv();
-
-    if (!LocalReferenceHolder_Init(&refs, mEnv)) {
-        LocalReferenceHolder_Cleanup(&refs);
-        return SDL_SetError("Failed to allocate enough JVM local references");
-    }
-
-    if (ctx) {
-        if (release) {
-            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.fileNameRef);
-        }
-
-        if (ctx->hidden.androidio.assetFileDescriptorRef) {
-            jobject inputStream = (jobject)ctx->hidden.androidio.assetFileDescriptorRef;
-            jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
-                    "close", "()V");
-            (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
-            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.assetFileDescriptorRef);
-            if (Android_JNI_ExceptionOccurred(false)) {
-                result = -1;
-            }
-        }
-        else {
-            jobject inputStream = (jobject)ctx->hidden.androidio.inputStreamRef;
-
-            // inputStream.close();
-            jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
-                    "close", "()V");
-            (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
-            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.inputStreamRef);
-            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.readableByteChannelRef);
-            if (Android_JNI_ExceptionOccurred(false)) {
-                result = -1;
-            }
-        }
-
-        if (release) {
-            SDL_FreeRW(ctx);
-        }
-    }
-
-    LocalReferenceHolder_Cleanup(&refs);
-    return result;
-}
-
-
-Sint64 Android_JNI_FileSize(SDL_RWops* ctx)
-{
-    return ctx->hidden.androidio.size;
-}
-
-Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
-{
-    if (ctx->hidden.androidio.assetFileDescriptorRef) {
-        switch (whence) {
-            case RW_SEEK_SET:
-                if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
-                offset += ctx->hidden.androidio.offset;
-                break;
-            case RW_SEEK_CUR:
-                offset += ctx->hidden.androidio.position;
-                if (ctx->hidden.androidio.size != -1 /*UNKNOWN_LENGTH*/ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
-                offset += ctx->hidden.androidio.offset;
-                break;
-            case RW_SEEK_END:
-                offset = ctx->hidden.androidio.offset + ctx->hidden.androidio.size + offset;
-                break;
-            default:
-                return SDL_SetError("Unknown value for 'whence'");
-        }
-        whence = SEEK_SET;
-
-        off_t ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
-        if (ret == -1) return -1;
-        ctx->hidden.androidio.position = ret - ctx->hidden.androidio.offset;
-    } else {
-        Sint64 newPosition;
-
-        switch (whence) {
-            case RW_SEEK_SET:
-                newPosition = offset;
-                break;
-            case RW_SEEK_CUR:
-                newPosition = ctx->hidden.androidio.position + offset;
-                break;
-            case RW_SEEK_END:
-                newPosition = ctx->hidden.androidio.size + offset;
-                break;
-            default:
-                return SDL_SetError("Unknown value for 'whence'");
-        }
-
-        /* Validate the new position */
-        if (newPosition < 0) {
-            return SDL_Error(SDL_EFSEEK);
-        }
-        if (newPosition > ctx->hidden.androidio.size) {
-            newPosition = ctx->hidden.androidio.size;
-        }
-
-        Sint64 movement = newPosition - ctx->hidden.androidio.position;
-        if (movement > 0) {
-            unsigned char buffer[4096];
-
-            // The easy case where we're seeking forwards
-            while (movement > 0) {
-                Sint64 amount = sizeof (buffer);
-                if (amount > movement) {
-                    amount = movement;
-                }
-                size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount);
-                if (result <= 0) {
-                    // Failed to read/skip the required amount, so fail
-                    return -1;
-                }
-
-                movement -= result;
-            }
-
-        } else if (movement < 0) {
-            // We can't seek backwards so we have to reopen the file and seek
-            // forwards which obviously isn't very efficient
-            Internal_Android_JNI_FileClose(ctx, false);
-            Internal_Android_JNI_FileOpen(ctx);
-            Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET);
-        }
-    }
-
-    return ctx->hidden.androidio.position;
-
-}
-
-int Android_JNI_FileClose(SDL_RWops* ctx)
-{
-    return Internal_Android_JNI_FileClose(ctx, true);
-}
-
-// returns a new global reference which needs to be released later
-static jobject Android_JNI_GetSystemServiceObject(const char* name)
-{
-    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
-    JNIEnv* env = Android_JNI_GetEnv();
-    jobject retval = NULL;
-
-    if (!LocalReferenceHolder_Init(&refs, env)) {
-        LocalReferenceHolder_Cleanup(&refs);
-        return NULL;
-    }
-
-    jstring service = (*env)->NewStringUTF(env, name);
-
-    jmethodID mid;
-
-    mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
-    jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
-
-    mid = (*env)->GetMethodID(env, mActivityClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
-    jobject manager = (*env)->CallObjectMethod(env, context, mid, service);
-
-    (*env)->DeleteLocalRef(env, service);
-
-    retval = manager ? (*env)->NewGlobalRef(env, manager) : NULL;
-    LocalReferenceHolder_Cleanup(&refs);
-    return retval;
-}
-
-#define SETUP_CLIPBOARD(error) \
-    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); \
-    JNIEnv* env = Android_JNI_GetEnv(); \
-    if (!LocalReferenceHolder_Init(&refs, env)) { \
-        LocalReferenceHolder_Cleanup(&refs); \
-        return error; \
-    } \
-    jobject clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
-    if (!clipboard) { \
-        LocalReferenceHolder_Cleanup(&refs); \
-        return error; \
-    }
-
-#define CLEANUP_CLIPBOARD() \
-    LocalReferenceHolder_Cleanup(&refs);
-
-int Android_JNI_SetClipboardText(const char* text)
-{
-    SETUP_CLIPBOARD(-1)
-
-    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "setText", "(Ljava/lang/CharSequence;)V");
-    jstring string = (*env)->NewStringUTF(env, text);
-    (*env)->CallVoidMethod(env, clipboard, mid, string);
-    (*env)->DeleteGlobalRef(env, clipboard);
-    (*env)->DeleteLocalRef(env, string);
-
-    CLEANUP_CLIPBOARD();
-
-    return 0;
-}
-
-char* Android_JNI_GetClipboardText()
-{
-    SETUP_CLIPBOARD(SDL_strdup(""))
-
-    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "getText", "()Ljava/lang/CharSequence;");
-    jobject sequence = (*env)->CallObjectMethod(env, clipboard, mid);
-    (*env)->DeleteGlobalRef(env, clipboard);
-    if (sequence) {
-        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, sequence), "toString", "()Ljava/lang/String;");
-        jstring string = (jstring)((*env)->CallObjectMethod(env, sequence, mid));
-        const char* utf = (*env)->GetStringUTFChars(env, string, 0);
-        if (utf) {
-            char* text = SDL_strdup(utf);
-            (*env)->ReleaseStringUTFChars(env, string, utf);
-
-            CLEANUP_CLIPBOARD();
-
-            return text;
-        }
-    }
-
-    CLEANUP_CLIPBOARD();    
-
-    return SDL_strdup("");
-}
-
-SDL_bool Android_JNI_HasClipboardText()
-{
-    SETUP_CLIPBOARD(SDL_FALSE)
-
-    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "hasText", "()Z");
-    jboolean has = (*env)->CallBooleanMethod(env, clipboard, mid);
-    (*env)->DeleteGlobalRef(env, clipboard);
-
-    CLEANUP_CLIPBOARD();
-    
-    return has ? SDL_TRUE : SDL_FALSE;
-}
-
-
-// returns 0 on success or -1 on error (others undefined then)
-// returns truthy or falsy value in plugged, charged and battery
-// returns the value in seconds and percent or -1 if not available
-int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent)
-{
-    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
-    JNIEnv* env = Android_JNI_GetEnv();
-    if (!LocalReferenceHolder_Init(&refs, env)) {
-        LocalReferenceHolder_Cleanup(&refs);
-        return -1;
-    }
-
-    jmethodID mid;
-
-    mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
-    jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
-
-    jstring action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED");
-
-    jclass cls = (*env)->FindClass(env, "android/content/IntentFilter");
-
-    mid = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
-    jobject filter = (*env)->NewObject(env, cls, mid, action);
-
-    (*env)->DeleteLocalRef(env, action);
-
-    mid = (*env)->GetMethodID(env, mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
-    jobject intent = (*env)->CallObjectMethod(env, context, mid, NULL, filter);
-
-    (*env)->DeleteLocalRef(env, filter);
-
-    cls = (*env)->GetObjectClass(env, intent);
-
-    jstring iname;
-    jmethodID imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I");
-
-#define GET_INT_EXTRA(var, key) \
-    iname = (*env)->NewStringUTF(env, key); \
-    int var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \
-    (*env)->DeleteLocalRef(env, iname);
-
-    jstring bname;
-    jmethodID bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
-
-#define GET_BOOL_EXTRA(var, key) \
-    bname = (*env)->NewStringUTF(env, key); \
-    int var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \
-    (*env)->DeleteLocalRef(env, bname);
-
-    if (plugged) {
-        GET_INT_EXTRA(plug, "plugged") // == BatteryManager.EXTRA_PLUGGED (API 5)
-        if (plug == -1) {
-            LocalReferenceHolder_Cleanup(&refs);
-            return -1;
-        }
-        // 1 == BatteryManager.BATTERY_PLUGGED_AC
-        // 2 == BatteryManager.BATTERY_PLUGGED_USB
-        *plugged = (0 < plug) ? 1 : 0;
-    }
-
-    if (charged) {
-        GET_INT_EXTRA(status, "status") // == BatteryManager.EXTRA_STATUS (API 5)
-        if (status == -1) {
-            LocalReferenceHolder_Cleanup(&refs);
-            return -1;
-        }
-        // 5 == BatteryManager.BATTERY_STATUS_FULL
-        *charged = (status == 5) ? 1 : 0;
-    }
-
-    if (battery) {
-        GET_BOOL_EXTRA(present, "present") // == BatteryManager.EXTRA_PRESENT (API 5)
-        *battery = present ? 1 : 0;
-    }
-
-    if (seconds) {
-        *seconds = -1; // not possible
-    }
-
-    if (percent) {
-        GET_INT_EXTRA(level, "level") // == BatteryManager.EXTRA_LEVEL (API 5)
-        GET_INT_EXTRA(scale, "scale") // == BatteryManager.EXTRA_SCALE (API 5)
-        if ((level == -1) || (scale == -1)) {
-            LocalReferenceHolder_Cleanup(&refs);
-            return -1;
-        }
-        *percent = level * 100 / scale;
-    }
-
-    (*env)->DeleteLocalRef(env, intent);
-
-    LocalReferenceHolder_Cleanup(&refs);
-    return 0;
-}
-
-// sends message to be handled on the UI event dispatch thread
-int Android_JNI_SendMessage(int command, int param)
-{
-    JNIEnv *env = Android_JNI_GetEnv();
-    if (!env) {
-        return -1;
-    }
-    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "sendMessage", "(II)Z");
-    if (!mid) {
-        return -1;
-    }
-    jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, mid, command, param);
-    return success ? 0 : -1;
-}
-
-void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
-{
-    JNIEnv *env = Android_JNI_GetEnv();
-    if (!env) {
-        return;
-    }
-
-    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z");
-    if (!mid) {
-        return;
-    }
-    (*env)->CallStaticBooleanMethod(env, mActivityClass, mid,
-                               inputRect->x,
-                               inputRect->y,
-                               inputRect->w,
-                               inputRect->h );
-}
-
-void Android_JNI_HideTextInput()
-{
-    // has to match Activity constant
-    const int COMMAND_TEXTEDIT_HIDE = 3;
-    Android_JNI_SendMessage(COMMAND_TEXTEDIT_HIDE, 0);
-}
-
-//////////////////////////////////////////////////////////////////////////////
-//
-// Functions exposed to SDL applications in SDL_system.h
-//
-
-void *SDL_AndroidGetJNIEnv()
-{
-    return Android_JNI_GetEnv();
-}
-
-
-
-void *SDL_AndroidGetActivity()
-{
-    /* See SDL_system.h for caveats on using this function. */
-
-    jmethodID mid;
-
-    JNIEnv *env = Android_JNI_GetEnv();
-    if (!env) {
-        return NULL;
-    }
-
-    // return SDLActivity.getContext();
-    mid = (*env)->GetStaticMethodID(env, mActivityClass,
-            "getContext","()Landroid/content/Context;");
-    return (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
-}
-
-const char * SDL_AndroidGetInternalStoragePath()
-{
-    static char *s_AndroidInternalFilesPath = NULL;
-
-    if (!s_AndroidInternalFilesPath) {
-        struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
-        jmethodID mid;
-        jobject context;
-        jobject fileObject;
-        jstring pathString;
-        const char *path;
-
-        JNIEnv *env = Android_JNI_GetEnv();
-        if (!LocalReferenceHolder_Init(&refs, env)) {
-            LocalReferenceHolder_Cleanup(&refs);
-            return NULL;
-        }
-
-        // context = SDLActivity.getContext();
-        mid = (*env)->GetStaticMethodID(env, mActivityClass,
-                "getContext","()Landroid/content/Context;");
-        context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
-
-        // fileObj = context.getFilesDir();
-        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
-                "getFilesDir", "()Ljava/io/File;");
-        fileObject = (*env)->CallObjectMethod(env, context, mid);
-        if (!fileObject) {
-            SDL_SetError("Couldn't get internal directory");
-            LocalReferenceHolder_Cleanup(&refs);
-            return NULL;
-        }
-
-        // path = fileObject.getAbsolutePath();
-        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
-                "getAbsolutePath", "()Ljava/lang/String;");
-        pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
-
-        path = (*env)->GetStringUTFChars(env, pathString, NULL);
-        s_AndroidInternalFilesPath = SDL_strdup(path);
-        (*env)->ReleaseStringUTFChars(env, pathString, path);
-
-        LocalReferenceHolder_Cleanup(&refs);
-    }
-    return s_AndroidInternalFilesPath;
-}
-
-int SDL_AndroidGetExternalStorageState()
-{
-    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
-    jmethodID mid;
-    jclass cls;
-    jstring stateString;
-    const char *state;
-    int stateFlags;
-
-    JNIEnv *env = Android_JNI_GetEnv();
-    if (!LocalReferenceHolder_Init(&refs, env)) {
-        LocalReferenceHolder_Cleanup(&refs);
-        return 0;
-    }
-
-    cls = (*env)->FindClass(env, "android/os/Environment");
-    mid = (*env)->GetStaticMethodID(env, cls,
-            "getExternalStorageState", "()Ljava/lang/String;");
-    stateString = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid);
-
-    state = (*env)->GetStringUTFChars(env, stateString, NULL);
-
-    // Print an info message so people debugging know the storage state
-    __android_log_print(ANDROID_LOG_INFO, "SDL", "external storage state: %s", state);
-
-    if (SDL_strcmp(state, "mounted") == 0) {
-        stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ |
-                     SDL_ANDROID_EXTERNAL_STORAGE_WRITE;
-    } else if (SDL_strcmp(state, "mounted_ro") == 0) {
-        stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ;
-    } else {
-        stateFlags = 0;
-    }
-    (*env)->ReleaseStringUTFChars(env, stateString, state);
-
-    LocalReferenceHolder_Cleanup(&refs);
-    return stateFlags;
-}
-
-const char * SDL_AndroidGetExternalStoragePath()
-{
-    static char *s_AndroidExternalFilesPath = NULL;
-
-    if (!s_AndroidExternalFilesPath) {
-        struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
-        jmethodID mid;
-        jobject context;
-        jobject fileObject;
-        jstring pathString;
-        const char *path;
-
-        JNIEnv *env = Android_JNI_GetEnv();
-        if (!LocalReferenceHolder_Init(&refs, env)) {
-            LocalReferenceHolder_Cleanup(&refs);
-            return NULL;
-        }
-
-        // context = SDLActivity.getContext();
-        mid = (*env)->GetStaticMethodID(env, mActivityClass,
-                "getContext","()Landroid/content/Context;");
-        context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
-
-        // fileObj = context.getExternalFilesDir();
-        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
-                "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
-        fileObject = (*env)->CallObjectMethod(env, context, mid, NULL);
-        if (!fileObject) {
-            SDL_SetError("Couldn't get external directory");
-            LocalReferenceHolder_Cleanup(&refs);
-            return NULL;
-        }
-
-        // path = fileObject.getAbsolutePath();
-        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
-                "getAbsolutePath", "()Ljava/lang/String;");
-        pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
-
-        path = (*env)->GetStringUTFChars(env, pathString, NULL);
-        s_AndroidExternalFilesPath = SDL_strdup(path);
-        (*env)->ReleaseStringUTFChars(env, pathString, path);
-
-        LocalReferenceHolder_Cleanup(&refs);
-    }
-    return s_AndroidExternalFilesPath;
-}
-
-#endif /* __ANDROID__ */
-
-/* vi: set ts=4 sw=4 expandtab: */
-
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+// Modified by Lasse Oorni for Urho3D
+
+#include "SDL_config.h"
+#include "SDL_stdinc.h"
+#include "SDL_assert.h"
+#include "SDL_log.h"
+
+#ifdef __ANDROID__
+
+#include "SDL_system.h"
+#include "SDL_android.h"
+
+#include <EGL/egl.h>
+
+#include "../../events/SDL_events_c.h"
+#include "../../video/android/SDL_androidkeyboard.h"
+#include "../../video/android/SDL_androidtouch.h"
+#include "../../video/android/SDL_androidvideo.h"
+#include "../../video/android/SDL_androidwindow.h"
+
+#include <android/log.h>
+#include <pthread.h>
+#include <sys/types.h>
+#include <unistd.h>
+#define LOG_TAG "SDL_android"
+/* #define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__) */
+/* #define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__) */
+#define LOGI(...) do {} while (false)
+#define LOGE(...) do {} while (false)
+
+/* Uncomment this to log messages entering and exiting methods in this file */
+/* #define DEBUG_JNI */
+
+static void Android_JNI_ThreadDestroyed(void*);
+
+/*******************************************************************************
+ This file links the Java side of Android with libsdl
+*******************************************************************************/
+#include <jni.h>
+#include <android/log.h>
+#include <stdbool.h>
+
+
+/*******************************************************************************
+                               Globals
+*******************************************************************************/
+static pthread_key_t mThreadKey;
+static JavaVM* mJavaVM;
+
+/* Main activity */
+static jclass mActivityClass;
+
+/* method signatures */
+static jmethodID midGetNativeSurface;
+static jmethodID midFlipBuffers;
+static jmethodID midAudioInit;
+static jmethodID midAudioWriteShortBuffer;
+static jmethodID midAudioWriteByteBuffer;
+static jmethodID midAudioQuit;
+
+/* Accelerometer data storage */
+static float fLastAccelerometer[3];
+static bool bHasNewData;
+
+// Urho3D: application files dir
+static char* mFilesDir = 0;
+
+/*******************************************************************************
+                 Functions called by JNI
+*******************************************************************************/
+
+/* Library init */
+jint JNI_OnLoad(JavaVM* vm, void* reserved)
+{
+    JNIEnv *env;
+    mJavaVM = vm;
+    LOGI("JNI_OnLoad called");
+    if ((*mJavaVM)->GetEnv(mJavaVM, (void**) &env, JNI_VERSION_1_4) != JNI_OK) {
+        LOGE("Failed to get the environment using GetEnv()");
+        return -1;
+    }
+    /*
+     * Create mThreadKey so we can keep track of the JNIEnv assigned to each thread
+     * Refer to http://developer.android.com/guide/practices/design/jni.html for the rationale behind this
+     */
+    if (pthread_key_create(&mThreadKey, Android_JNI_ThreadDestroyed)) {
+        __android_log_print(ANDROID_LOG_ERROR, "SDL", "Error initializing pthread key");
+    }
+    else {
+        Android_JNI_SetupThread();
+    }
+
+    return JNI_VERSION_1_4;
+}
+
+// Urho3D: added function
+const char* SDL_Android_GetFilesDir()
+{
+    return mFilesDir;
+}
+
+/* Called before SDL_main() to initialize JNI bindings */
+// Urho3D: added passing user files directory from SDLActivity on startup
+void SDL_Android_Init(JNIEnv* mEnv, jclass cls, jstring filesDir)
+{
+    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init()");
+
+    Android_JNI_SetupThread();
+
+    // Copy the files dir
+    const char *str;
+    str = (*mEnv)->GetStringUTFChars(mEnv, filesDir, 0);
+    if (str)
+    {
+        if (mFilesDir)
+            free(mFilesDir);
+
+        size_t length = strlen(str) + 1;
+        mFilesDir = (char*)malloc(length);
+        memcpy(mFilesDir, str, length);
+        (*mEnv)->ReleaseStringUTFChars(mEnv, filesDir, str);
+    }
+
+    mActivityClass = (jclass)((*mEnv)->NewGlobalRef(mEnv, cls));
+
+    midGetNativeSurface = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "getNativeSurface","()Landroid/view/Surface;");
+    midFlipBuffers = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "flipBuffers","()V");
+    midAudioInit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioInit", "(IZZI)I");
+    midAudioWriteShortBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioWriteShortBuffer", "([S)V");
+    midAudioWriteByteBuffer = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioWriteByteBuffer", "([B)V");
+    midAudioQuit = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+                                "audioQuit", "()V");
+
+    bHasNewData = false;
+
+    if(!midGetNativeSurface || !midFlipBuffers || !midAudioInit ||
+       !midAudioWriteShortBuffer || !midAudioWriteByteBuffer || !midAudioQuit) {
+        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL: Couldn't locate Java callbacks, check that they're named and typed correctly");
+    }
+    __android_log_print(ANDROID_LOG_INFO, "SDL", "SDL_Android_Init() finished!");
+}
+
+/* Resize */
+void Java_org_libsdl_app_SDLActivity_onNativeResize(
+                                    JNIEnv* env, jclass jcls,
+                                    jint width, jint height, jint format)
+{
+    Android_SetScreenResolution(width, height, format);
+}
+
+
+/* Surface Created */
+void Java_org_libsdl_app_SDLActivity_onNativeSurfaceChanged(JNIEnv* env, jclass jcls)
+{
+    SDL_WindowData *data;
+    SDL_VideoDevice *_this;
+
+    if (Android_Window == NULL || Android_Window->driverdata == NULL ) {
+        return;
+    }
+    
+    _this =  SDL_GetVideoDevice();
+    data =  (SDL_WindowData *) Android_Window->driverdata;
+    
+    /* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
+    if (data->egl_surface == EGL_NO_SURFACE) {
+        if(data->native_window) {
+            ANativeWindow_release(data->native_window);
+        }
+        data->native_window = Android_JNI_GetNativeWindow();
+        data->egl_surface = SDL_EGL_CreateSurface(_this, (NativeWindowType) data->native_window);
+    }
+    
+    /* GL Context handling is done in the event loop because this function is run from the Java thread */
+    
+}
+
+/* Surface Destroyed */
+void Java_org_libsdl_app_SDLActivity_onNativeSurfaceDestroyed(JNIEnv* env, jclass jcls)
+{
+    /* We have to clear the current context and destroy the egl surface here
+     * Otherwise there's BAD_NATIVE_WINDOW errors coming from eglCreateWindowSurface on resume
+     * Ref: http://stackoverflow.com/questions/8762589/eglcreatewindowsurface-on-ics-and-switching-from-2d-to-3d
+     */
+    SDL_WindowData *data;
+    SDL_VideoDevice *_this;
+    
+    if (Android_Window == NULL || Android_Window->driverdata == NULL ) {
+        return;
+    }
+    
+    _this =  SDL_GetVideoDevice();
+    data = (SDL_WindowData *) Android_Window->driverdata;
+    
+    if (data->egl_surface != EGL_NO_SURFACE) {
+        SDL_EGL_MakeCurrent(_this, NULL, NULL);
+        SDL_EGL_DestroySurface(_this, data->egl_surface);
+        data->egl_surface = EGL_NO_SURFACE;
+    }
+    
+    /* GL Context handling is done in the event loop because this function is run from the Java thread */
+
+}
+
+void Java_org_libsdl_app_SDLActivity_nativeFlipBuffers(JNIEnv* env, jclass jcls)
+{
+    SDL_GL_SwapWindow(Android_Window);
+}
+
+/* Keydown */
+void Java_org_libsdl_app_SDLActivity_onNativeKeyDown(
+                                    JNIEnv* env, jclass jcls, jint keycode)
+{
+    Android_OnKeyDown(keycode);
+}
+
+/* Keyup */
+void Java_org_libsdl_app_SDLActivity_onNativeKeyUp(
+                                    JNIEnv* env, jclass jcls, jint keycode)
+{
+    Android_OnKeyUp(keycode);
+}
+
+/* Keyboard Focus Lost */
+void Java_org_libsdl_app_SDLActivity_onNativeKeyboardFocusLost(
+                                    JNIEnv* env, jclass jcls)
+{
+    /* Calling SDL_StopTextInput will take care of hiding the keyboard and cleaning up the DummyText widget */
+    SDL_StopTextInput();
+}
+
+
+/* Touch */
+void Java_org_libsdl_app_SDLActivity_onNativeTouch(
+                                    JNIEnv* env, jclass jcls,
+                                    jint touch_device_id_in, jint pointer_finger_id_in,
+                                    jint action, jfloat x, jfloat y, jfloat p)
+{
+    Android_OnTouch(touch_device_id_in, pointer_finger_id_in, action, x, y, p);
+}
+
+/* Accelerometer */
+void Java_org_libsdl_app_SDLActivity_onNativeAccel(
+                                    JNIEnv* env, jclass jcls,
+                                    jfloat x, jfloat y, jfloat z)
+{
+    fLastAccelerometer[0] = x;
+    fLastAccelerometer[1] = y;
+    fLastAccelerometer[2] = z;
+    bHasNewData = true;
+}
+
+/* Low memory */
+void Java_org_libsdl_app_SDLActivity_nativeLowMemory(
+                                    JNIEnv* env, jclass cls)
+{
+    SDL_SendAppEvent(SDL_APP_LOWMEMORY);
+}
+
+/* Quit */
+void Java_org_libsdl_app_SDLActivity_nativeQuit(
+                                    JNIEnv* env, jclass cls)
+{
+    // Urho3D: added log print
+    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeQuit()");
+    /* Inject a SDL_QUIT event */
+    SDL_SendQuit();
+    SDL_SendAppEvent(SDL_APP_TERMINATING);
+}
+
+/* Pause */
+void Java_org_libsdl_app_SDLActivity_nativePause(
+                                    JNIEnv* env, jclass cls)
+{
+    if (Android_Window) {
+        /* Signal the pause semaphore so the event loop knows to pause and (optionally) block itself */
+        if (!SDL_SemValue(Android_PauseSem)) SDL_SemPost(Android_PauseSem);
+        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_LOST, 0, 0);
+        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_MINIMIZED, 0, 0);
+    }
+
+    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativePause()");
+    SDL_SendAppEvent(SDL_APP_WILLENTERBACKGROUND);
+    SDL_SendAppEvent(SDL_APP_DIDENTERBACKGROUND);
+}
+
+/* Resume */
+void Java_org_libsdl_app_SDLActivity_nativeResume(
+                                    JNIEnv* env, jclass cls)
+{
+    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "nativeResume()");
+    SDL_SendAppEvent(SDL_APP_WILLENTERFOREGROUND);
+    SDL_SendAppEvent(SDL_APP_DIDENTERFOREGROUND);
+
+    if (Android_Window) {
+        /* Signal the resume semaphore so the event loop knows to resume and restore the GL Context
+         * We can't restore the GL Context here because it needs to be done on the SDL main thread
+         * and this function will be called from the Java thread instead.
+         */
+        if (!SDL_SemValue(Android_ResumeSem)) SDL_SemPost(Android_ResumeSem);
+        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_FOCUS_GAINED, 0, 0);
+        SDL_SendWindowEvent(Android_Window, SDL_WINDOWEVENT_RESTORED, 0, 0);
+    }
+}
+
+void Java_org_libsdl_app_SDLInputConnection_nativeCommitText(
+                                    JNIEnv* env, jclass cls,
+                                    jstring text, jint newCursorPosition)
+{
+    const char *utftext = (*env)->GetStringUTFChars(env, text, NULL);
+
+    SDL_SendKeyboardText(utftext);
+
+    (*env)->ReleaseStringUTFChars(env, text, utftext);
+}
+
+void Java_org_libsdl_app_SDLInputConnection_nativeSetComposingText(
+                                    JNIEnv* env, jclass cls,
+                                    jstring text, jint newCursorPosition)
+{
+    const char *utftext = (*env)->GetStringUTFChars(env, text, NULL);
+
+    SDL_SendEditingText(utftext, 0, 0);
+
+    (*env)->ReleaseStringUTFChars(env, text, utftext);
+}
+
+
+
+/*******************************************************************************
+             Functions called by SDL into Java
+*******************************************************************************/
+
+static int s_active = 0;
+struct LocalReferenceHolder
+{
+    JNIEnv *m_env;
+    const char *m_func;
+};
+
+static struct LocalReferenceHolder LocalReferenceHolder_Setup(const char *func)
+{
+    struct LocalReferenceHolder refholder;
+    refholder.m_env = NULL;
+    refholder.m_func = func;
+#ifdef DEBUG_JNI
+    SDL_Log("Entering function %s", func);
+#endif
+    return refholder;
+}
+
+static SDL_bool LocalReferenceHolder_Init(struct LocalReferenceHolder *refholder, JNIEnv *env)
+{
+    const int capacity = 16;
+    if ((*env)->PushLocalFrame(env, capacity) < 0) {
+        SDL_SetError("Failed to allocate enough JVM local references");
+        return SDL_FALSE;
+    }
+    ++s_active;
+    refholder->m_env = env;
+    return SDL_TRUE;
+}
+
+static void LocalReferenceHolder_Cleanup(struct LocalReferenceHolder *refholder)
+{
+#ifdef DEBUG_JNI
+    SDL_Log("Leaving function %s", refholder->m_func);
+#endif
+    if (refholder->m_env) {
+        JNIEnv* env = refholder->m_env;
+        (*env)->PopLocalFrame(env, NULL);
+        --s_active;
+    }
+}
+
+static SDL_bool LocalReferenceHolder_IsActive()
+{
+    return s_active > 0;    
+}
+
+ANativeWindow* Android_JNI_GetNativeWindow(void)
+{
+    ANativeWindow* anw;
+    jobject s;
+    JNIEnv *env = Android_JNI_GetEnv();
+
+    s = (*env)->CallStaticObjectMethod(env, mActivityClass, midGetNativeSurface);
+    anw = ANativeWindow_fromSurface(env, s);
+    (*env)->DeleteLocalRef(env, s);
+  
+    return anw;
+}
+
+void Android_JNI_SwapWindow()
+{
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, midFlipBuffers);
+}
+
+void Android_JNI_SetActivityTitle(const char *title)
+{
+    jmethodID mid;
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,"setActivityTitle","(Ljava/lang/String;)Z");
+    if (mid) {
+        jstring jtitle = (jstring)((*mEnv)->NewStringUTF(mEnv, title));
+        (*mEnv)->CallStaticBooleanMethod(mEnv, mActivityClass, mid, jtitle);
+        (*mEnv)->DeleteLocalRef(mEnv, jtitle);
+    }
+}
+
+SDL_bool Android_JNI_GetAccelerometerValues(float values[3])
+{
+    int i;
+    SDL_bool retval = SDL_FALSE;
+
+    if (bHasNewData) {
+        for (i = 0; i < 3; ++i) {
+            values[i] = fLastAccelerometer[i];
+        }
+        bHasNewData = false;
+        retval = SDL_TRUE;
+    }
+
+    return retval;
+}
+
+// Urho3D: added function
+void Android_JNI_FinishActivity()
+{
+    // Terminating the SDL main thread on our own may cause crashes with extra threads, so request
+    // the activity to finish instead
+    jmethodID mid;
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass, "finishActivity","()V");
+    if (mid)
+        (*mEnv)->CallStaticVoidMethod(mEnv, mActivityClass, mid);
+}
+
+static void Android_JNI_ThreadDestroyed(void* value) {
+    /* The thread is being destroyed, detach it from the Java VM and set the mThreadKey value to NULL as required */
+    JNIEnv *env = (JNIEnv*) value;
+    if (env != NULL) {
+        (*mJavaVM)->DetachCurrentThread(mJavaVM);
+        pthread_setspecific(mThreadKey, NULL);
+    }
+}
+
+JNIEnv* Android_JNI_GetEnv(void) {
+    /* From http://developer.android.com/guide/practices/jni.html
+     * All threads are Linux threads, scheduled by the kernel.
+     * They're usually started from managed code (using Thread.start), but they can also be created elsewhere and then
+     * attached to the JavaVM. For example, a thread started with pthread_create can be attached with the
+     * JNI AttachCurrentThread or AttachCurrentThreadAsDaemon functions. Until a thread is attached, it has no JNIEnv,
+     * and cannot make JNI calls.
+     * Attaching a natively-created thread causes a java.lang.Thread object to be constructed and added to the "main"
+     * ThreadGroup, making it visible to the debugger. Calling AttachCurrentThread on an already-attached thread
+     * is a no-op.
+     * Note: You can call this function any number of times for the same thread, there's no harm in it
+     */
+
+    JNIEnv *env;
+    int status = (*mJavaVM)->AttachCurrentThread(mJavaVM, &env, NULL);
+    if(status < 0) {
+        LOGE("failed to attach current thread");
+        return 0;
+    }
+
+    return env;
+}
+
+int Android_JNI_SetupThread(void) {
+    /* From http://developer.android.com/guide/practices/jni.html
+     * Threads attached through JNI must call DetachCurrentThread before they exit. If coding this directly is awkward,
+     * in Android 2.0 (Eclair) and higher you can use pthread_key_create to define a destructor function that will be
+     * called before the thread exits, and call DetachCurrentThread from there. (Use that key with pthread_setspecific
+     * to store the JNIEnv in thread-local-storage; that way it'll be passed into your destructor as the argument.)
+     * Note: The destructor is not called unless the stored value is != NULL
+     * Note: You can call this function any number of times for the same thread, there's no harm in it
+     *       (except for some lost CPU cycles)
+     */
+    JNIEnv *env = Android_JNI_GetEnv();
+    pthread_setspecific(mThreadKey, (void*) env);
+    return 1;
+}
+
+/*
+ * Audio support
+ */
+static jboolean audioBuffer16Bit = JNI_FALSE;
+static jboolean audioBufferStereo = JNI_FALSE;
+static jobject audioBuffer = NULL;
+static void* audioBufferPinned = NULL;
+
+int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames)
+{
+    int audioBufferFrames;
+
+    JNIEnv *env = Android_JNI_GetEnv();
+
+    if (!env) {
+        LOGE("callback_handler: failed to attach current thread");
+    }
+    Android_JNI_SetupThread();
+
+    __android_log_print(ANDROID_LOG_VERBOSE, "SDL", "SDL audio: opening device");
+    audioBuffer16Bit = is16Bit;
+    audioBufferStereo = channelCount > 1;
+
+    if ((*env)->CallStaticIntMethod(env, mActivityClass, midAudioInit, sampleRate, audioBuffer16Bit, audioBufferStereo, desiredBufferFrames) != 0) {
+        /* Error during audio initialization */
+        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: error on AudioTrack initialization!");
+        return 0;
+    }
+
+    /* Allocating the audio buffer from the Java side and passing it as the return value for audioInit no longer works on
+     * Android >= 4.2 due to a "stale global reference" error. So now we allocate this buffer directly from this side. */
+
+    if (is16Bit) {
+        jshortArray audioBufferLocal = (*env)->NewShortArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
+        if (audioBufferLocal) {
+            audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
+            (*env)->DeleteLocalRef(env, audioBufferLocal);
+        }
+    }
+    else {
+        jbyteArray audioBufferLocal = (*env)->NewByteArray(env, desiredBufferFrames * (audioBufferStereo ? 2 : 1));
+        if (audioBufferLocal) {
+            audioBuffer = (*env)->NewGlobalRef(env, audioBufferLocal);
+            (*env)->DeleteLocalRef(env, audioBufferLocal);
+        }
+    }
+
+    if (audioBuffer == NULL) {
+        __android_log_print(ANDROID_LOG_WARN, "SDL", "SDL audio: could not allocate an audio buffer!");
+        return 0;
+    }
+
+    jboolean isCopy = JNI_FALSE;
+    if (audioBuffer16Bit) {
+        audioBufferPinned = (*env)->GetShortArrayElements(env, (jshortArray)audioBuffer, &isCopy);
+        audioBufferFrames = (*env)->GetArrayLength(env, (jshortArray)audioBuffer);
+    } else {
+        audioBufferPinned = (*env)->GetByteArrayElements(env, (jbyteArray)audioBuffer, &isCopy);
+        audioBufferFrames = (*env)->GetArrayLength(env, (jbyteArray)audioBuffer);
+    }
+    if (audioBufferStereo) {
+        audioBufferFrames /= 2;
+    }
+
+    return audioBufferFrames;
+}
+
+void * Android_JNI_GetAudioBuffer()
+{
+    return audioBufferPinned;
+}
+
+void Android_JNI_WriteAudioBuffer()
+{
+    JNIEnv *mAudioEnv = Android_JNI_GetEnv();
+
+    if (audioBuffer16Bit) {
+        (*mAudioEnv)->ReleaseShortArrayElements(mAudioEnv, (jshortArray)audioBuffer, (jshort *)audioBufferPinned, JNI_COMMIT);
+        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteShortBuffer, (jshortArray)audioBuffer);
+    } else {
+        (*mAudioEnv)->ReleaseByteArrayElements(mAudioEnv, (jbyteArray)audioBuffer, (jbyte *)audioBufferPinned, JNI_COMMIT);
+        (*mAudioEnv)->CallStaticVoidMethod(mAudioEnv, mActivityClass, midAudioWriteByteBuffer, (jbyteArray)audioBuffer);
+    }
+
+    /* JNI_COMMIT means the changes are committed to the VM but the buffer remains pinned */
+}
+
+void Android_JNI_CloseAudioDevice()
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+
+    (*env)->CallStaticVoidMethod(env, mActivityClass, midAudioQuit);
+
+    if (audioBuffer) {
+        (*env)->DeleteGlobalRef(env, audioBuffer);
+        audioBuffer = NULL;
+        audioBufferPinned = NULL;
+    }
+}
+
+/* Test for an exception and call SDL_SetError with its detail if one occurs */
+/* If the parameter silent is truthy then SDL_SetError() will not be called. */
+static bool Android_JNI_ExceptionOccurred(bool silent)
+{
+    SDL_assert(LocalReferenceHolder_IsActive());
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+
+    jthrowable exception = (*mEnv)->ExceptionOccurred(mEnv);
+    if (exception != NULL) {
+        jmethodID mid;
+
+        /* Until this happens most JNI operations have undefined behaviour */
+        (*mEnv)->ExceptionClear(mEnv);
+
+        if (!silent) {
+            jclass exceptionClass = (*mEnv)->GetObjectClass(mEnv, exception);
+            jclass classClass = (*mEnv)->FindClass(mEnv, "java/lang/Class");
+
+            mid = (*mEnv)->GetMethodID(mEnv, classClass, "getName", "()Ljava/lang/String;");
+            jstring exceptionName = (jstring)(*mEnv)->CallObjectMethod(mEnv, exceptionClass, mid);
+            const char* exceptionNameUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionName, 0);
+
+            mid = (*mEnv)->GetMethodID(mEnv, exceptionClass, "getMessage", "()Ljava/lang/String;");
+            jstring exceptionMessage = (jstring)(*mEnv)->CallObjectMethod(mEnv, exception, mid);
+
+            if (exceptionMessage != NULL) {
+                const char* exceptionMessageUTF8 = (*mEnv)->GetStringUTFChars(mEnv, exceptionMessage, 0);
+                SDL_SetError("%s: %s", exceptionNameUTF8, exceptionMessageUTF8);
+                (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionMessage, exceptionMessageUTF8);
+            } else {
+                SDL_SetError("%s", exceptionNameUTF8);
+            }
+
+            (*mEnv)->ReleaseStringUTFChars(mEnv, exceptionName, exceptionNameUTF8);
+        }
+
+        return true;
+    }
+
+    return false;
+}
+
+static int Internal_Android_JNI_FileOpen(SDL_RWops* ctx)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+
+    int result = 0;
+
+    jmethodID mid;
+    jobject context;
+    jobject assetManager;
+    jobject inputStream;
+    jclass channels;
+    jobject readableByteChannel;
+    jstring fileNameJString;
+    jobject fd;
+    jclass fdCls;
+    jfieldID descriptor;
+
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    if (!LocalReferenceHolder_Init(&refs, mEnv)) {
+        goto failure;
+    }
+
+    fileNameJString = (jstring)ctx->hidden.androidio.fileNameRef;
+    ctx->hidden.androidio.position = 0;
+
+    /* context = SDLActivity.getContext(); */
+    mid = (*mEnv)->GetStaticMethodID(mEnv, mActivityClass,
+            "getContext","()Landroid/content/Context;");
+    context = (*mEnv)->CallStaticObjectMethod(mEnv, mActivityClass, mid);
+
+
+    /* assetManager = context.getAssets(); */
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, context),
+            "getAssets", "()Landroid/content/res/AssetManager;");
+    assetManager = (*mEnv)->CallObjectMethod(mEnv, context, mid);
+
+    /* First let's try opening the file to obtain an AssetFileDescriptor.
+    * This method reads the files directly from the APKs using standard *nix calls
+    */
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager), "openFd", "(Ljava/lang/String;)Landroid/content/res/AssetFileDescriptor;");
+    inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString);
+    if (Android_JNI_ExceptionOccurred(true)) {
+        goto fallback;
+    }
+
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getStartOffset", "()J");
+    ctx->hidden.androidio.offset = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
+    if (Android_JNI_ExceptionOccurred(true)) {
+        goto fallback;
+    }
+
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getDeclaredLength", "()J");
+    ctx->hidden.androidio.size = (*mEnv)->CallLongMethod(mEnv, inputStream, mid);
+    if (Android_JNI_ExceptionOccurred(true)) {
+        goto fallback;
+    }
+
+    mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream), "getFileDescriptor", "()Ljava/io/FileDescriptor;");
+    fd = (*mEnv)->CallObjectMethod(mEnv, inputStream, mid);
+    fdCls = (*mEnv)->GetObjectClass(mEnv, fd);
+    descriptor = (*mEnv)->GetFieldID(mEnv, fdCls, "descriptor", "I");
+    ctx->hidden.androidio.fd = (*mEnv)->GetIntField(mEnv, fd, descriptor);
+    ctx->hidden.androidio.assetFileDescriptorRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
+
+    /* Seek to the correct offset in the file. */
+    lseek(ctx->hidden.androidio.fd, (off_t)ctx->hidden.androidio.offset, SEEK_SET);
+
+    if (false) {
+fallback:
+        /* Disabled log message because of spam on the Nexus 7 */
+        /* __android_log_print(ANDROID_LOG_DEBUG, "SDL", "Falling back to legacy InputStream method for opening file"); */
+
+        /* Try the old method using InputStream */
+        ctx->hidden.androidio.assetFileDescriptorRef = NULL;
+
+        /* inputStream = assetManager.open(<filename>); */
+        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, assetManager),
+                "open", "(Ljava/lang/String;I)Ljava/io/InputStream;");
+        inputStream = (*mEnv)->CallObjectMethod(mEnv, assetManager, mid, fileNameJString, 1 /* ACCESS_RANDOM */);
+        if (Android_JNI_ExceptionOccurred(false)) {
+            goto failure;
+        }
+
+        ctx->hidden.androidio.inputStreamRef = (*mEnv)->NewGlobalRef(mEnv, inputStream);
+
+        /* Despite all the visible documentation on [Asset]InputStream claiming
+         * that the .available() method is not guaranteed to return the entire file
+         * size, comments in <sdk>/samples/<ver>/ApiDemos/src/com/example/ ...
+         * android/apis/content/ReadAsset.java imply that Android's
+         * AssetInputStream.available() /will/ always return the total file size
+        */
+        
+        /* size = inputStream.available(); */
+        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
+                "available", "()I");
+        ctx->hidden.androidio.size = (long)(*mEnv)->CallIntMethod(mEnv, inputStream, mid);
+        if (Android_JNI_ExceptionOccurred(false)) {
+            goto failure;
+        }
+
+        /* readableByteChannel = Channels.newChannel(inputStream); */
+        channels = (*mEnv)->FindClass(mEnv, "java/nio/channels/Channels");
+        mid = (*mEnv)->GetStaticMethodID(mEnv, channels,
+                "newChannel",
+                "(Ljava/io/InputStream;)Ljava/nio/channels/ReadableByteChannel;");
+        readableByteChannel = (*mEnv)->CallStaticObjectMethod(
+                mEnv, channels, mid, inputStream);
+        if (Android_JNI_ExceptionOccurred(false)) {
+            goto failure;
+        }
+
+        ctx->hidden.androidio.readableByteChannelRef =
+            (*mEnv)->NewGlobalRef(mEnv, readableByteChannel);
+
+        /* Store .read id for reading purposes */
+        mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, readableByteChannel),
+                "read", "(Ljava/nio/ByteBuffer;)I");
+        ctx->hidden.androidio.readMethod = mid;
+    }
+
+    if (false) {
+failure:
+        result = -1;
+
+        (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.fileNameRef);
+
+        if(ctx->hidden.androidio.inputStreamRef != NULL) {
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.inputStreamRef);
+        }
+
+        if(ctx->hidden.androidio.readableByteChannelRef != NULL) {
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.readableByteChannelRef);
+        }
+
+        if(ctx->hidden.androidio.assetFileDescriptorRef != NULL) {
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.assetFileDescriptorRef);
+        }
+
+    }
+    
+    LocalReferenceHolder_Cleanup(&refs);
+    return result;
+}
+
+int Android_JNI_FileOpen(SDL_RWops* ctx,
+        const char* fileName, const char* mode)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+    int retval;
+
+    if (!LocalReferenceHolder_Init(&refs, mEnv)) {
+        LocalReferenceHolder_Cleanup(&refs);        
+        return -1;
+    }
+
+    if (!ctx) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return -1;
+    }
+
+    jstring fileNameJString = (*mEnv)->NewStringUTF(mEnv, fileName);
+    ctx->hidden.androidio.fileNameRef = (*mEnv)->NewGlobalRef(mEnv, fileNameJString);
+    ctx->hidden.androidio.inputStreamRef = NULL;
+    ctx->hidden.androidio.readableByteChannelRef = NULL;
+    ctx->hidden.androidio.readMethod = NULL;
+    ctx->hidden.androidio.assetFileDescriptorRef = NULL;
+
+    retval = Internal_Android_JNI_FileOpen(ctx);
+    LocalReferenceHolder_Cleanup(&refs);
+    return retval;
+}
+
+size_t Android_JNI_FileRead(SDL_RWops* ctx, void* buffer,
+        size_t size, size_t maxnum)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+
+    if (ctx->hidden.androidio.assetFileDescriptorRef) {
+        size_t bytesMax = size * maxnum;
+        if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && ctx->hidden.androidio.position + bytesMax > ctx->hidden.androidio.size) {
+            bytesMax = ctx->hidden.androidio.size - ctx->hidden.androidio.position;
+        }
+        size_t result = read(ctx->hidden.androidio.fd, buffer, bytesMax );
+        if (result > 0) {
+            ctx->hidden.androidio.position += result;
+            LocalReferenceHolder_Cleanup(&refs);
+            return result / size;
+        }
+        LocalReferenceHolder_Cleanup(&refs);
+        return 0;
+    } else {
+        jlong bytesRemaining = (jlong) (size * maxnum);
+        jlong bytesMax = (jlong) (ctx->hidden.androidio.size -  ctx->hidden.androidio.position);
+        int bytesRead = 0;
+
+        /* Don't read more bytes than those that remain in the file, otherwise we get an exception */
+        if (bytesRemaining >  bytesMax) bytesRemaining = bytesMax;
+
+        JNIEnv *mEnv = Android_JNI_GetEnv();
+        if (!LocalReferenceHolder_Init(&refs, mEnv)) {
+            LocalReferenceHolder_Cleanup(&refs);            
+            return 0;
+        }
+
+        jobject readableByteChannel = (jobject)ctx->hidden.androidio.readableByteChannelRef;
+        jmethodID readMethod = (jmethodID)ctx->hidden.androidio.readMethod;
+        jobject byteBuffer = (*mEnv)->NewDirectByteBuffer(mEnv, buffer, bytesRemaining);
+
+        while (bytesRemaining > 0) {
+            /* result = readableByteChannel.read(...); */
+            int result = (*mEnv)->CallIntMethod(mEnv, readableByteChannel, readMethod, byteBuffer);
+
+            if (Android_JNI_ExceptionOccurred(false)) {
+                LocalReferenceHolder_Cleanup(&refs);            
+                return 0;
+            }
+
+            if (result < 0) {
+                break;
+            }
+
+            bytesRemaining -= result;
+            bytesRead += result;
+            ctx->hidden.androidio.position += result;
+        }
+        LocalReferenceHolder_Cleanup(&refs);                    
+        return bytesRead / size;
+    }
+}
+
+size_t Android_JNI_FileWrite(SDL_RWops* ctx, const void* buffer,
+        size_t size, size_t num)
+{
+    SDL_SetError("Cannot write to Android package filesystem");
+    return 0;
+}
+
+static int Internal_Android_JNI_FileClose(SDL_RWops* ctx, bool release)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+
+    int result = 0;
+    JNIEnv *mEnv = Android_JNI_GetEnv();
+
+    if (!LocalReferenceHolder_Init(&refs, mEnv)) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return SDL_SetError("Failed to allocate enough JVM local references");
+    }
+
+    if (ctx) {
+        if (release) {
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.fileNameRef);
+        }
+
+        if (ctx->hidden.androidio.assetFileDescriptorRef) {
+            jobject inputStream = (jobject)ctx->hidden.androidio.assetFileDescriptorRef;
+            jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
+                    "close", "()V");
+            (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.assetFileDescriptorRef);
+            if (Android_JNI_ExceptionOccurred(false)) {
+                result = -1;
+            }
+        }
+        else {
+            jobject inputStream = (jobject)ctx->hidden.androidio.inputStreamRef;
+
+            /* inputStream.close(); */
+            jmethodID mid = (*mEnv)->GetMethodID(mEnv, (*mEnv)->GetObjectClass(mEnv, inputStream),
+                    "close", "()V");
+            (*mEnv)->CallVoidMethod(mEnv, inputStream, mid);
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.inputStreamRef);
+            (*mEnv)->DeleteGlobalRef(mEnv, (jobject)ctx->hidden.androidio.readableByteChannelRef);
+            if (Android_JNI_ExceptionOccurred(false)) {
+                result = -1;
+            }
+        }
+
+        if (release) {
+            SDL_FreeRW(ctx);
+        }
+    }
+
+    LocalReferenceHolder_Cleanup(&refs);
+    return result;
+}
+
+
+Sint64 Android_JNI_FileSize(SDL_RWops* ctx)
+{
+    return ctx->hidden.androidio.size;
+}
+
+Sint64 Android_JNI_FileSeek(SDL_RWops* ctx, Sint64 offset, int whence)
+{
+    if (ctx->hidden.androidio.assetFileDescriptorRef) {
+        switch (whence) {
+            case RW_SEEK_SET:
+                if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
+                offset += ctx->hidden.androidio.offset;
+                break;
+            case RW_SEEK_CUR:
+                offset += ctx->hidden.androidio.position;
+                if (ctx->hidden.androidio.size != -1 /* UNKNOWN_LENGTH */ && offset > ctx->hidden.androidio.size) offset = ctx->hidden.androidio.size;
+                offset += ctx->hidden.androidio.offset;
+                break;
+            case RW_SEEK_END:
+                offset = ctx->hidden.androidio.offset + ctx->hidden.androidio.size + offset;
+                break;
+            default:
+                return SDL_SetError("Unknown value for 'whence'");
+        }
+        whence = SEEK_SET;
+
+        off_t ret = lseek(ctx->hidden.androidio.fd, (off_t)offset, SEEK_SET);
+        if (ret == -1) return -1;
+        ctx->hidden.androidio.position = ret - ctx->hidden.androidio.offset;
+    } else {
+        Sint64 newPosition;
+
+        switch (whence) {
+            case RW_SEEK_SET:
+                newPosition = offset;
+                break;
+            case RW_SEEK_CUR:
+                newPosition = ctx->hidden.androidio.position + offset;
+                break;
+            case RW_SEEK_END:
+                newPosition = ctx->hidden.androidio.size + offset;
+                break;
+            default:
+                return SDL_SetError("Unknown value for 'whence'");
+        }
+
+        /* Validate the new position */
+        if (newPosition < 0) {
+            return SDL_Error(SDL_EFSEEK);
+        }
+        if (newPosition > ctx->hidden.androidio.size) {
+            newPosition = ctx->hidden.androidio.size;
+        }
+
+        Sint64 movement = newPosition - ctx->hidden.androidio.position;
+        if (movement > 0) {
+            unsigned char buffer[4096];
+
+            /* The easy case where we're seeking forwards */
+            while (movement > 0) {
+                Sint64 amount = sizeof (buffer);
+                if (amount > movement) {
+                    amount = movement;
+                }
+                size_t result = Android_JNI_FileRead(ctx, buffer, 1, amount);
+                if (result <= 0) {
+                    /* Failed to read/skip the required amount, so fail */
+                    return -1;
+                }
+
+                movement -= result;
+            }
+
+        } else if (movement < 0) {
+            /* We can't seek backwards so we have to reopen the file and seek */
+            /* forwards which obviously isn't very efficient */
+            Internal_Android_JNI_FileClose(ctx, false);
+            Internal_Android_JNI_FileOpen(ctx);
+            Android_JNI_FileSeek(ctx, newPosition, RW_SEEK_SET);
+        }
+    }
+
+    return ctx->hidden.androidio.position;
+
+}
+
+int Android_JNI_FileClose(SDL_RWops* ctx)
+{
+    return Internal_Android_JNI_FileClose(ctx, true);
+}
+
+/* returns a new global reference which needs to be released later */
+static jobject Android_JNI_GetSystemServiceObject(const char* name)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+    JNIEnv* env = Android_JNI_GetEnv();
+    jobject retval = NULL;
+
+    if (!LocalReferenceHolder_Init(&refs, env)) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return NULL;
+    }
+
+    jstring service = (*env)->NewStringUTF(env, name);
+
+    jmethodID mid;
+
+    mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
+    jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+
+    mid = (*env)->GetMethodID(env, mActivityClass, "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;");
+    jobject manager = (*env)->CallObjectMethod(env, context, mid, service);
+
+    (*env)->DeleteLocalRef(env, service);
+
+    retval = manager ? (*env)->NewGlobalRef(env, manager) : NULL;
+    LocalReferenceHolder_Cleanup(&refs);
+    return retval;
+}
+
+#define SETUP_CLIPBOARD(error) \
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__); \
+    JNIEnv* env = Android_JNI_GetEnv(); \
+    if (!LocalReferenceHolder_Init(&refs, env)) { \
+        LocalReferenceHolder_Cleanup(&refs); \
+        return error; \
+    } \
+    jobject clipboard = Android_JNI_GetSystemServiceObject("clipboard"); \
+    if (!clipboard) { \
+        LocalReferenceHolder_Cleanup(&refs); \
+        return error; \
+    }
+
+#define CLEANUP_CLIPBOARD() \
+    LocalReferenceHolder_Cleanup(&refs);
+
+int Android_JNI_SetClipboardText(const char* text)
+{
+    SETUP_CLIPBOARD(-1)
+
+    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "setText", "(Ljava/lang/CharSequence;)V");
+    jstring string = (*env)->NewStringUTF(env, text);
+    (*env)->CallVoidMethod(env, clipboard, mid, string);
+    (*env)->DeleteGlobalRef(env, clipboard);
+    (*env)->DeleteLocalRef(env, string);
+
+    CLEANUP_CLIPBOARD();
+
+    return 0;
+}
+
+char* Android_JNI_GetClipboardText()
+{
+    SETUP_CLIPBOARD(SDL_strdup(""))
+
+    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "getText", "()Ljava/lang/CharSequence;");
+    jobject sequence = (*env)->CallObjectMethod(env, clipboard, mid);
+    (*env)->DeleteGlobalRef(env, clipboard);
+    if (sequence) {
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, sequence), "toString", "()Ljava/lang/String;");
+        jstring string = (jstring)((*env)->CallObjectMethod(env, sequence, mid));
+        const char* utf = (*env)->GetStringUTFChars(env, string, 0);
+        if (utf) {
+            char* text = SDL_strdup(utf);
+            (*env)->ReleaseStringUTFChars(env, string, utf);
+
+            CLEANUP_CLIPBOARD();
+
+            return text;
+        }
+    }
+
+    CLEANUP_CLIPBOARD();    
+
+    return SDL_strdup("");
+}
+
+SDL_bool Android_JNI_HasClipboardText()
+{
+    SETUP_CLIPBOARD(SDL_FALSE)
+
+    jmethodID mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, clipboard), "hasText", "()Z");
+    jboolean has = (*env)->CallBooleanMethod(env, clipboard, mid);
+    (*env)->DeleteGlobalRef(env, clipboard);
+
+    CLEANUP_CLIPBOARD();
+    
+    return has ? SDL_TRUE : SDL_FALSE;
+}
+
+
+/* returns 0 on success or -1 on error (others undefined then)
+ * returns truthy or falsy value in plugged, charged and battery
+ * returns the value in seconds and percent or -1 if not available
+ */
+int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent)
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+    JNIEnv* env = Android_JNI_GetEnv();
+    if (!LocalReferenceHolder_Init(&refs, env)) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return -1;
+    }
+
+    jmethodID mid;
+
+    mid = (*env)->GetStaticMethodID(env, mActivityClass, "getContext", "()Landroid/content/Context;");
+    jobject context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+
+    jstring action = (*env)->NewStringUTF(env, "android.intent.action.BATTERY_CHANGED");
+
+    jclass cls = (*env)->FindClass(env, "android/content/IntentFilter");
+
+    mid = (*env)->GetMethodID(env, cls, "<init>", "(Ljava/lang/String;)V");
+    jobject filter = (*env)->NewObject(env, cls, mid, action);
+
+    (*env)->DeleteLocalRef(env, action);
+
+    mid = (*env)->GetMethodID(env, mActivityClass, "registerReceiver", "(Landroid/content/BroadcastReceiver;Landroid/content/IntentFilter;)Landroid/content/Intent;");
+    jobject intent = (*env)->CallObjectMethod(env, context, mid, NULL, filter);
+
+    (*env)->DeleteLocalRef(env, filter);
+
+    cls = (*env)->GetObjectClass(env, intent);
+
+    jstring iname;
+    jmethodID imid = (*env)->GetMethodID(env, cls, "getIntExtra", "(Ljava/lang/String;I)I");
+
+#define GET_INT_EXTRA(var, key) \
+    iname = (*env)->NewStringUTF(env, key); \
+    int var = (*env)->CallIntMethod(env, intent, imid, iname, -1); \
+    (*env)->DeleteLocalRef(env, iname);
+
+    jstring bname;
+    jmethodID bmid = (*env)->GetMethodID(env, cls, "getBooleanExtra", "(Ljava/lang/String;Z)Z");
+
+#define GET_BOOL_EXTRA(var, key) \
+    bname = (*env)->NewStringUTF(env, key); \
+    int var = (*env)->CallBooleanMethod(env, intent, bmid, bname, JNI_FALSE); \
+    (*env)->DeleteLocalRef(env, bname);
+
+    if (plugged) {
+        GET_INT_EXTRA(plug, "plugged") /* == BatteryManager.EXTRA_PLUGGED (API 5) */
+        if (plug == -1) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return -1;
+        }
+        /* 1 == BatteryManager.BATTERY_PLUGGED_AC */
+        /* 2 == BatteryManager.BATTERY_PLUGGED_USB */
+        *plugged = (0 < plug) ? 1 : 0;
+    }
+
+    if (charged) {
+        GET_INT_EXTRA(status, "status") /* == BatteryManager.EXTRA_STATUS (API 5) */
+        if (status == -1) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return -1;
+        }
+        /* 5 == BatteryManager.BATTERY_STATUS_FULL */
+        *charged = (status == 5) ? 1 : 0;
+    }
+
+    if (battery) {
+        GET_BOOL_EXTRA(present, "present") /* == BatteryManager.EXTRA_PRESENT (API 5) */
+        *battery = present ? 1 : 0;
+    }
+
+    if (seconds) {
+        *seconds = -1; /* not possible */
+    }
+
+    if (percent) {
+        GET_INT_EXTRA(level, "level") /* == BatteryManager.EXTRA_LEVEL (API 5) */
+        GET_INT_EXTRA(scale, "scale") /* == BatteryManager.EXTRA_SCALE (API 5) */
+        if ((level == -1) || (scale == -1)) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return -1;
+        }
+        *percent = level * 100 / scale;
+    }
+
+    (*env)->DeleteLocalRef(env, intent);
+
+    LocalReferenceHolder_Cleanup(&refs);
+    return 0;
+}
+
+/* returns number of found touch devices as return value and ids in parameter ids */
+int Android_JNI_GetTouchDeviceIds(int **ids) {
+    JNIEnv *env = Android_JNI_GetEnv();
+    jint sources = 4098; /* == InputDevice.SOURCE_TOUCHSCREEN */
+    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "inputGetInputDeviceIds", "(I)[I");
+    jintArray array = (jintArray) (*env)->CallStaticObjectMethod(env, mActivityClass, mid, sources);
+    int number = 0;
+    *ids = NULL;
+    if (array) {
+        number = (int) (*env)->GetArrayLength(env, array);
+        if (0 < number) {
+            jint* elements = (*env)->GetIntArrayElements(env, array, NULL);
+            if (elements) {
+                int i;
+                *ids = SDL_malloc(number * sizeof (**ids));
+                for (i = 0; i < number; ++i) { /* not assuming sizeof (jint) == sizeof (int) */
+                    (*ids)[i] = elements[i];
+                }
+                (*env)->ReleaseIntArrayElements(env, array, elements, JNI_ABORT);
+            }
+        }
+        (*env)->DeleteLocalRef(env, array);
+    }
+    return number;
+}
+
+/* sends message to be handled on the UI event dispatch thread */
+int Android_JNI_SendMessage(int command, int param)
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+    if (!env) {
+        return -1;
+    }
+    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "sendMessage", "(II)Z");
+    if (!mid) {
+        return -1;
+    }
+    jboolean success = (*env)->CallStaticBooleanMethod(env, mActivityClass, mid, command, param);
+    return success ? 0 : -1;
+}
+
+void Android_JNI_ShowTextInput(SDL_Rect *inputRect)
+{
+    JNIEnv *env = Android_JNI_GetEnv();
+    if (!env) {
+        return;
+    }
+
+    jmethodID mid = (*env)->GetStaticMethodID(env, mActivityClass, "showTextInput", "(IIII)Z");
+    if (!mid) {
+        return;
+    }
+    (*env)->CallStaticBooleanMethod(env, mActivityClass, mid,
+                               inputRect->x,
+                               inputRect->y,
+                               inputRect->w,
+                               inputRect->h );
+}
+
+void Android_JNI_HideTextInput()
+{
+    /* has to match Activity constant */
+    const int COMMAND_TEXTEDIT_HIDE = 3;
+    Android_JNI_SendMessage(COMMAND_TEXTEDIT_HIDE, 0);
+}
+
+/*
+//////////////////////////////////////////////////////////////////////////////
+//
+// Functions exposed to SDL applications in SDL_system.h
+//////////////////////////////////////////////////////////////////////////////
+*/
+
+void *SDL_AndroidGetJNIEnv()
+{
+    return Android_JNI_GetEnv();
+}
+
+
+
+void *SDL_AndroidGetActivity()
+{
+    /* See SDL_system.h for caveats on using this function. */
+
+    jmethodID mid;
+
+    JNIEnv *env = Android_JNI_GetEnv();
+    if (!env) {
+        return NULL;
+    }
+
+    /* return SDLActivity.getContext(); */
+    mid = (*env)->GetStaticMethodID(env, mActivityClass,
+            "getContext","()Landroid/content/Context;");
+    return (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+}
+
+const char * SDL_AndroidGetInternalStoragePath()
+{
+    static char *s_AndroidInternalFilesPath = NULL;
+
+    if (!s_AndroidInternalFilesPath) {
+        struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+        jmethodID mid;
+        jobject context;
+        jobject fileObject;
+        jstring pathString;
+        const char *path;
+
+        JNIEnv *env = Android_JNI_GetEnv();
+        if (!LocalReferenceHolder_Init(&refs, env)) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return NULL;
+        }
+
+        /* context = SDLActivity.getContext(); */
+        mid = (*env)->GetStaticMethodID(env, mActivityClass,
+                "getContext","()Landroid/content/Context;");
+        context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+
+        /* fileObj = context.getFilesDir(); */
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
+                "getFilesDir", "()Ljava/io/File;");
+        fileObject = (*env)->CallObjectMethod(env, context, mid);
+        if (!fileObject) {
+            SDL_SetError("Couldn't get internal directory");
+            LocalReferenceHolder_Cleanup(&refs);
+            return NULL;
+        }
+
+        /* path = fileObject.getAbsolutePath(); */
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
+                "getAbsolutePath", "()Ljava/lang/String;");
+        pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
+
+        path = (*env)->GetStringUTFChars(env, pathString, NULL);
+        s_AndroidInternalFilesPath = SDL_strdup(path);
+        (*env)->ReleaseStringUTFChars(env, pathString, path);
+
+        LocalReferenceHolder_Cleanup(&refs);
+    }
+    return s_AndroidInternalFilesPath;
+}
+
+int SDL_AndroidGetExternalStorageState()
+{
+    struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+    jmethodID mid;
+    jclass cls;
+    jstring stateString;
+    const char *state;
+    int stateFlags;
+
+    JNIEnv *env = Android_JNI_GetEnv();
+    if (!LocalReferenceHolder_Init(&refs, env)) {
+        LocalReferenceHolder_Cleanup(&refs);
+        return 0;
+    }
+
+    cls = (*env)->FindClass(env, "android/os/Environment");
+    mid = (*env)->GetStaticMethodID(env, cls,
+            "getExternalStorageState", "()Ljava/lang/String;");
+    stateString = (jstring)(*env)->CallStaticObjectMethod(env, cls, mid);
+
+    state = (*env)->GetStringUTFChars(env, stateString, NULL);
+
+    /* Print an info message so people debugging know the storage state */
+    __android_log_print(ANDROID_LOG_INFO, "SDL", "external storage state: %s", state);
+
+    if (SDL_strcmp(state, "mounted") == 0) {
+        stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ |
+                     SDL_ANDROID_EXTERNAL_STORAGE_WRITE;
+    } else if (SDL_strcmp(state, "mounted_ro") == 0) {
+        stateFlags = SDL_ANDROID_EXTERNAL_STORAGE_READ;
+    } else {
+        stateFlags = 0;
+    }
+    (*env)->ReleaseStringUTFChars(env, stateString, state);
+
+    LocalReferenceHolder_Cleanup(&refs);
+    return stateFlags;
+}
+
+const char * SDL_AndroidGetExternalStoragePath()
+{
+    static char *s_AndroidExternalFilesPath = NULL;
+
+    if (!s_AndroidExternalFilesPath) {
+        struct LocalReferenceHolder refs = LocalReferenceHolder_Setup(__FUNCTION__);
+        jmethodID mid;
+        jobject context;
+        jobject fileObject;
+        jstring pathString;
+        const char *path;
+
+        JNIEnv *env = Android_JNI_GetEnv();
+        if (!LocalReferenceHolder_Init(&refs, env)) {
+            LocalReferenceHolder_Cleanup(&refs);
+            return NULL;
+        }
+
+        /* context = SDLActivity.getContext(); */
+        mid = (*env)->GetStaticMethodID(env, mActivityClass,
+                "getContext","()Landroid/content/Context;");
+        context = (*env)->CallStaticObjectMethod(env, mActivityClass, mid);
+
+        /* fileObj = context.getExternalFilesDir(); */
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, context),
+                "getExternalFilesDir", "(Ljava/lang/String;)Ljava/io/File;");
+        fileObject = (*env)->CallObjectMethod(env, context, mid, NULL);
+        if (!fileObject) {
+            SDL_SetError("Couldn't get external directory");
+            LocalReferenceHolder_Cleanup(&refs);
+            return NULL;
+        }
+
+        /* path = fileObject.getAbsolutePath(); */
+        mid = (*env)->GetMethodID(env, (*env)->GetObjectClass(env, fileObject),
+                "getAbsolutePath", "()Ljava/lang/String;");
+        pathString = (jstring)(*env)->CallObjectMethod(env, fileObject, mid);
+
+        path = (*env)->GetStringUTFChars(env, pathString, NULL);
+        s_AndroidExternalFilesPath = SDL_strdup(path);
+        (*env)->ReleaseStringUTFChars(env, pathString, path);
+
+        LocalReferenceHolder_Cleanup(&refs);
+    }
+    return s_AndroidExternalFilesPath;
+}
+
+#endif /* __ANDROID__ */
+
+/* vi: set ts=4 sw=4 expandtab: */
+

+ 13 - 2
Source/ThirdParty/SDL/src/core/android/SDL_android.h

@@ -18,6 +18,9 @@
      misrepresented as being the original software.
   3. This notice may not be removed or altered from any source distribution.
 */
+
+// Modified by Lasse Oorni for Urho3D
+
 #include "SDL_config.h"
 
 /* Set up for C function definitions, even when using C++ */
@@ -27,16 +30,21 @@ extern "C" {
 /* *INDENT-ON* */
 #endif
 
+// Urho3D: do not use EGL includes to allow compiling on API level 8
+// #include <EGL/eglplatform.h>
+#include <android/native_window_jni.h>
+
 #include "SDL_rect.h"
 
 /* Interface from the SDL library into the Android Java activity */
-extern SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion, int red, int green, int blue, int alpha, int buffer, int depth, int stencil, int buffers, int samples);
-extern SDL_bool Android_JNI_DeleteContext(void);
+/* extern SDL_bool Android_JNI_CreateContext(int majorVersion, int minorVersion, int red, int green, int blue, int alpha, int buffer, int depth, int stencil, int buffers, int samples);
+extern SDL_bool Android_JNI_DeleteContext(void); */
 extern void Android_JNI_SwapWindow();
 extern void Android_JNI_SetActivityTitle(const char *title);
 extern SDL_bool Android_JNI_GetAccelerometerValues(float values[3]);
 extern void Android_JNI_ShowTextInput(SDL_Rect *inputRect);
 extern void Android_JNI_HideTextInput();
+extern ANativeWindow* Android_JNI_GetNativeWindow(void);
 
 /* Audio support */
 extern int Android_JNI_OpenAudioDevice(int sampleRate, int is16Bit, int channelCount, int desiredBufferFrames);
@@ -61,6 +69,9 @@ SDL_bool Android_JNI_HasClipboardText();
 /* Power support */
 int Android_JNI_GetPowerInfo(int* plugged, int* charged, int* battery, int* seconds, int* percent);
 
+/* Touch support */
+int Android_JNI_GetTouchDeviceIds(int **ids);
+
 /* Threads */
 #include <jni.h>
 JNIEnv *Android_JNI_GetEnv(void);

+ 398 - 0
Source/ThirdParty/SDL/src/core/linux/SDL_udev.c

@@ -0,0 +1,398 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* 
+ * To list the properties of a device, try something like:
+ * udevadm info -a -n snd/hwC0D0 (for a sound card)
+ * udevadm info --query=all -n input/event3 (for a keyboard, mouse, etc)
+ * udevadm info --query=property -n input/event2
+ */
+
+#include "SDL_udev.h"
+
+#ifdef SDL_USE_LIBUDEV
+
+static char* SDL_UDEV_LIBS[] = { "libudev.so.1", "libudev.so.0" };
+
+#define _THIS SDL_UDEV_PrivateData *_this
+static _THIS = NULL;
+
+#include "SDL.h"
+
+static SDL_bool SDL_UDEV_load_sym(const char *fn, void **addr);
+static int SDL_UDEV_load_syms(void);
+static SDL_bool SDL_UDEV_hotplug_update_available(void);
+static void device_event(SDL_UDEV_deviceevent type, struct udev_device *dev);
+
+static SDL_bool
+SDL_UDEV_load_sym(const char *fn, void **addr)
+{
+    *addr = SDL_LoadFunction(_this->udev_handle, fn);
+    if (*addr == NULL) {
+        /* Don't call SDL_SetError(): SDL_LoadFunction already did. */
+        return SDL_FALSE;
+    }
+
+    return SDL_TRUE;
+}
+
+static int
+SDL_UDEV_load_syms(void)
+{
+    /* cast funcs to char* first, to please GCC's strict aliasing rules. */
+    #define SDL_UDEV_SYM(x) \
+        if (!SDL_UDEV_load_sym(#x, (void **) (char *) & _this->x)) return -1
+
+    SDL_UDEV_SYM(udev_device_get_action);
+    SDL_UDEV_SYM(udev_device_get_devnode);
+    SDL_UDEV_SYM(udev_device_get_subsystem);
+    SDL_UDEV_SYM(udev_device_get_property_value);
+    SDL_UDEV_SYM(udev_device_new_from_syspath);
+    SDL_UDEV_SYM(udev_device_unref);
+    SDL_UDEV_SYM(udev_enumerate_add_match_property);
+    SDL_UDEV_SYM(udev_enumerate_add_match_subsystem);
+    SDL_UDEV_SYM(udev_enumerate_get_list_entry);
+    SDL_UDEV_SYM(udev_enumerate_new);
+    SDL_UDEV_SYM(udev_enumerate_scan_devices);
+    SDL_UDEV_SYM(udev_enumerate_unref);
+    SDL_UDEV_SYM(udev_list_entry_get_name);
+    SDL_UDEV_SYM(udev_list_entry_get_next);
+    SDL_UDEV_SYM(udev_monitor_enable_receiving);
+    SDL_UDEV_SYM(udev_monitor_filter_add_match_subsystem_devtype);
+    SDL_UDEV_SYM(udev_monitor_get_fd);
+    SDL_UDEV_SYM(udev_monitor_new_from_netlink);
+    SDL_UDEV_SYM(udev_monitor_receive_device);
+    SDL_UDEV_SYM(udev_monitor_unref);
+    SDL_UDEV_SYM(udev_new);
+    SDL_UDEV_SYM(udev_unref);
+    SDL_UDEV_SYM(udev_device_new_from_devnum);
+    SDL_UDEV_SYM(udev_device_get_devnum);
+    #undef SDL_UDEV_SYM
+
+    return 0;
+}
+
+static SDL_bool
+SDL_UDEV_hotplug_update_available(void)
+{
+    if (_this->udev_mon != NULL) {
+        const int fd = _this->udev_monitor_get_fd(_this->udev_mon);
+        fd_set fds;
+        struct timeval tv;
+
+        FD_ZERO(&fds);
+        FD_SET(fd, &fds);
+        tv.tv_sec = 0;
+        tv.tv_usec = 0;
+        if ((select(fd+1, &fds, NULL, NULL, &tv) > 0) && (FD_ISSET(fd, &fds))) {
+            return SDL_TRUE;
+        }
+    }
+    return SDL_FALSE;
+}
+
+
+int
+SDL_UDEV_Init(void)
+{
+    int retval = 0;
+    
+    if (_this == NULL) {
+        _this = (SDL_UDEV_PrivateData *) SDL_calloc(1, sizeof(*_this));
+        if(_this == NULL) {
+            return SDL_OutOfMemory();
+        }
+        
+        retval = SDL_UDEV_LoadLibrary();
+        if (retval < 0) {
+            SDL_UDEV_Quit();
+            return retval;
+        }
+        
+        /* Set up udev monitoring 
+         * Listen for input devices (mouse, keyboard, joystick, etc) and sound devices
+         */
+        
+        _this->udev = _this->udev_new();
+        if (_this->udev == NULL) {
+            SDL_UDEV_Quit();
+            return SDL_SetError("udev_new() failed");
+        }
+
+        _this->udev_mon = _this->udev_monitor_new_from_netlink(_this->udev, "udev");
+        if (_this->udev_mon == NULL) {
+            SDL_UDEV_Quit();
+            return SDL_SetError("udev_monitor_new_from_netlink() failed");
+        }
+        
+        _this->udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "input", NULL);
+        _this->udev_monitor_filter_add_match_subsystem_devtype(_this->udev_mon, "sound", NULL);
+        _this->udev_monitor_enable_receiving(_this->udev_mon);
+        
+        /* Do an initial scan of existing devices */
+        SDL_UDEV_Scan();
+
+    }
+    
+    _this->ref_count += 1;
+    
+    return retval;
+}
+
+void
+SDL_UDEV_Quit(void)
+{
+    SDL_UDEV_CallbackList *item;
+    
+    if (_this == NULL) {
+        return;
+    }
+    
+    _this->ref_count -= 1;
+    
+    if (_this->ref_count < 1) {
+        
+        if (_this->udev_mon != NULL) {
+            _this->udev_monitor_unref(_this->udev_mon);
+            _this->udev_mon = NULL;
+        }
+        if (_this->udev != NULL) {
+            _this->udev_unref(_this->udev);
+            _this->udev = NULL;
+        }
+        
+        /* Remove existing devices */
+        while (_this->first != NULL) {
+            item = _this->first;
+            _this->first = _this->first->next;
+            SDL_free(item);
+        }
+        
+        SDL_UDEV_UnloadLibrary();
+        SDL_free(_this);
+        _this = NULL;
+    }
+}
+
+void
+SDL_UDEV_Scan(void)
+{
+    struct udev_enumerate *enumerate = NULL;
+    struct udev_list_entry *devs = NULL;
+    struct udev_list_entry *item = NULL;  
+    
+    if (_this == NULL) {
+        return;
+    }
+   
+    enumerate = _this->udev_enumerate_new(_this->udev);
+    if (enumerate == NULL) {
+        SDL_UDEV_Quit();
+        SDL_SetError("udev_monitor_new_from_netlink() failed");
+        return;
+    }
+    
+    _this->udev_enumerate_add_match_subsystem(enumerate, "input");
+    _this->udev_enumerate_add_match_subsystem(enumerate, "sound");
+    
+    _this->udev_enumerate_scan_devices(enumerate);
+    devs = _this->udev_enumerate_get_list_entry(enumerate);
+    for (item = devs; item; item = _this->udev_list_entry_get_next(item)) {
+        const char *path = _this->udev_list_entry_get_name(item);
+        struct udev_device *dev = _this->udev_device_new_from_syspath(_this->udev, path);
+        if (dev != NULL) {
+            device_event(SDL_UDEV_DEVICEADDED, dev);
+            _this->udev_device_unref(dev);
+        }
+    }
+
+    _this->udev_enumerate_unref(enumerate);
+}
+
+
+void
+SDL_UDEV_UnloadLibrary(void)
+{
+    if (_this == NULL) {
+        return;
+    }
+    
+    if (_this->udev_handle != NULL) {
+        SDL_UnloadObject(_this->udev_handle);
+        _this->udev_handle = NULL;
+    }
+}
+
+int
+SDL_UDEV_LoadLibrary(void)
+{
+    int retval = 0, i;
+    
+    if (_this == NULL) {
+        return SDL_SetError("UDEV not initialized");
+    }
+    
+   
+    if (_this->udev_handle == NULL) {
+        for( i = 0 ; i < SDL_arraysize(SDL_UDEV_LIBS); i++) {
+            _this->udev_handle = SDL_LoadObject(SDL_UDEV_LIBS[i]);
+            if (_this->udev_handle != NULL) {
+                retval = SDL_UDEV_load_syms();
+                if (retval < 0) {
+                    SDL_UDEV_UnloadLibrary();
+                }
+                else {
+                    break;
+                }
+            }
+        }
+        
+        if (_this->udev_handle == NULL) {
+            retval = -1;
+            /* Don't call SDL_SetError(): SDL_LoadObject already did. */
+        }
+    }
+
+    return retval;
+}
+
+static void 
+device_event(SDL_UDEV_deviceevent type, struct udev_device *dev) 
+{
+    const char *subsystem;
+    const char *val = NULL;
+    int devclass = 0;
+    const char *path;
+    SDL_UDEV_CallbackList *item;
+    
+    path = _this->udev_device_get_devnode(dev);
+    if (path == NULL) {
+        return;
+    }
+    
+    subsystem = _this->udev_device_get_subsystem(dev);
+    if (SDL_strcmp(subsystem, "sound") == 0) {
+        devclass = SDL_UDEV_DEVICE_SOUND;
+    } else if (SDL_strcmp(subsystem, "input") == 0) {
+        val = _this->udev_device_get_property_value(dev, "ID_INPUT_JOYSTICK");
+        if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
+            devclass |= SDL_UDEV_DEVICE_JOYSTICK;
+        }
+        
+        val = _this->udev_device_get_property_value(dev, "ID_INPUT_MOUSE");
+        if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
+            devclass |= SDL_UDEV_DEVICE_MOUSE;
+        }
+
+        val = _this->udev_device_get_property_value(dev, "ID_INPUT_KEYBOARD");
+        if (val != NULL && SDL_strcmp(val, "1") == 0 ) {
+            devclass |= SDL_UDEV_DEVICE_KEYBOARD;
+        }
+
+        if (devclass == 0) {
+            return;
+        }
+    } else {
+        return;
+    }
+    
+    /* Process callbacks */
+    for (item = _this->first; item != NULL; item = item->next) {
+        item->callback(type, devclass, path);
+    }
+}
+
+void 
+SDL_UDEV_Poll(void)
+{
+    struct udev_device *dev = NULL;
+    const char *action = NULL;
+
+    if (_this == NULL) {
+        return;
+    }
+
+    while (SDL_UDEV_hotplug_update_available()) {
+        dev = _this->udev_monitor_receive_device(_this->udev_mon);
+        if (dev == NULL) {
+            break;
+        }
+        action = _this->udev_device_get_action(dev);
+
+        if (SDL_strcmp(action, "add") == 0) {
+            device_event(SDL_UDEV_DEVICEADDED, dev);
+        } else if (SDL_strcmp(action, "remove") == 0) {
+            device_event(SDL_UDEV_DEVICEREMOVED, dev);
+        }
+        
+        _this->udev_device_unref(dev);
+    }
+}
+
+int 
+SDL_UDEV_AddCallback(SDL_UDEV_Callback cb)
+{
+    SDL_UDEV_CallbackList *item;
+    item = (SDL_UDEV_CallbackList *) SDL_calloc(1, sizeof (SDL_UDEV_CallbackList));
+    if (item == NULL) {
+        return SDL_OutOfMemory();
+    }
+    
+    item->callback = cb;
+
+    if (_this->last == NULL) {
+        _this->first = _this->last = item;
+    } else {
+        _this->last->next = item;
+        _this->last = item;
+    }
+    
+    return 1;
+}
+
+void 
+SDL_UDEV_DelCallback(SDL_UDEV_Callback cb)
+{
+    SDL_UDEV_CallbackList *item;
+    SDL_UDEV_CallbackList *prev = NULL;
+
+    for (item = _this->first; item != NULL; item = item->next) {
+        /* found it, remove it. */
+        if (item->callback == cb) {
+            if (prev != NULL) {
+                prev->next = item->next;
+            } else {
+                SDL_assert(_this->first == item);
+                _this->first = item->next;
+            }
+            if (item == _this->last) {
+                _this->last = prev;
+            }
+            SDL_free(item);
+            return;
+        }
+        prev = item;
+    }
+    
+}
+
+
+#endif /* SDL_USE_LIBUDEV */

+ 115 - 0
Source/ThirdParty/SDL/src/core/linux/SDL_udev.h

@@ -0,0 +1,115 @@
+/*
+  Simple DirectMedia Layer
+  Copyright (C) 1997-2013 Sam Lantinga <[email protected]>
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+*/
+
+#include "SDL_config.h"
+
+#ifndef _SDL_udev_h
+#define _SDL_udev_h
+
+#if HAVE_LIBUDEV_H
+
+#ifndef SDL_USE_LIBUDEV
+#define SDL_USE_LIBUDEV 1
+#endif
+
+#include "SDL_loadso.h"
+#include "SDL_events.h"
+#include <libudev.h>
+#include <sys/time.h>
+#include <sys/types.h>
+
+/**
+ *  \brief Device type
+ */
+
+typedef enum
+{
+    SDL_UDEV_DEVICEADDED = 0x0001,
+    SDL_UDEV_DEVICEREMOVED
+} SDL_UDEV_deviceevent;
+
+/* A device can be any combination of these classes */
+typedef enum
+{
+    SDL_UDEV_DEVICE_MOUSE       = 0x0001,
+    SDL_UDEV_DEVICE_KEYBOARD    = 0x0002,
+    SDL_UDEV_DEVICE_JOYSTICK    = 0x0004,
+    SDL_UDEV_DEVICE_SOUND       = 0x0008
+} SDL_UDEV_deviceclass;
+
+typedef void (*SDL_UDEV_Callback)(SDL_UDEV_deviceevent udev_type, int udev_class, const char *devpath);
+
+typedef struct SDL_UDEV_CallbackList {
+    SDL_UDEV_Callback callback;
+    struct SDL_UDEV_CallbackList *next;
+} SDL_UDEV_CallbackList;
+
+typedef struct SDL_UDEV_PrivateData
+{
+    const char *udev_library;
+    void *udev_handle;
+    struct udev *udev;
+    struct udev_monitor *udev_mon;
+    int ref_count;
+    SDL_UDEV_CallbackList *first, *last;
+    
+    /* Function pointers */
+    const char *(*udev_device_get_action)(struct udev_device *);
+    const char *(*udev_device_get_devnode)(struct udev_device *);
+    const char *(*udev_device_get_subsystem)(struct udev_device *);
+    const char *(*udev_device_get_property_value)(struct udev_device *, const char *);
+    struct udev_device *(*udev_device_new_from_syspath)(struct udev *, const char *);
+    void (*udev_device_unref)(struct udev_device *);
+    int (*udev_enumerate_add_match_property)(struct udev_enumerate *, const char *, const char *);
+    int (*udev_enumerate_add_match_subsystem)(struct udev_enumerate *, const char *);
+    struct udev_list_entry *(*udev_enumerate_get_list_entry)(struct udev_enumerate *);
+    struct udev_enumerate *(*udev_enumerate_new)(struct udev *);
+    int (*udev_enumerate_scan_devices)(struct udev_enumerate *);
+    void (*udev_enumerate_unref)(struct udev_enumerate *);
+    const char *(*udev_list_entry_get_name)(struct udev_list_entry *);
+    struct udev_list_entry *(*udev_list_entry_get_next)(struct udev_list_entry *);
+    int (*udev_monitor_enable_receiving)(struct udev_monitor *);
+    int (*udev_monitor_filter_add_match_subsystem_devtype)(struct udev_monitor *, const char *, const char *);
+    int (*udev_monitor_get_fd)(struct udev_monitor *);
+    struct udev_monitor *(*udev_monitor_new_from_netlink)(struct udev *, const char *);
+    struct udev_device *(*udev_monitor_receive_device)(struct udev_monitor *);
+    void (*udev_monitor_unref)(struct udev_monitor *);
+    struct udev *(*udev_new)(void);
+    void (*udev_unref)(struct udev *);
+    struct udev_device * (*udev_device_new_from_devnum)(struct udev *udev, char type, dev_t devnum);
+    dev_t (*udev_device_get_devnum) (struct udev_device *udev_device);
+} SDL_UDEV_PrivateData;
+
+extern int SDL_UDEV_Init(void);
+extern void SDL_UDEV_Quit(void);
+extern void SDL_UDEV_UnloadLibrary(void);
+extern int SDL_UDEV_LoadLibrary(void);
+extern void SDL_UDEV_Poll(void);
+extern void SDL_UDEV_Scan(void);
+extern int SDL_UDEV_AddCallback(SDL_UDEV_Callback cb);
+extern void SDL_UDEV_DelCallback(SDL_UDEV_Callback cb);
+
+
+
+
+#endif /* HAVE_LIBUDEV_H */
+
+#endif /* _SDL_udev_h */

+ 1 - 1
Source/ThirdParty/SDL/src/core/windows/SDL_windows.c

@@ -22,8 +22,8 @@
 
 #ifdef __WIN32__
 
-#include "SDL_error.h"
 #include "SDL_windows.h"
+#include "SDL_error.h"
 #include "SDL_assert.h"
 
 #include <objbase.h>  /* for CoInitialize/CoUninitialize */

+ 3 - 2
Source/ThirdParty/SDL/src/core/windows/SDL_windows.h

@@ -36,9 +36,10 @@
 
 /* Routines to convert from UTF8 to native Windows text */
 #if UNICODE
-#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UCS-2-INTERNAL", (char *)(S), (SDL_wcslen(S)+1)*sizeof(WCHAR))
-#define WIN_UTF8ToString(S) (WCHAR *)SDL_iconv_string("UCS-2-INTERNAL", "UTF-8", (char *)(S), SDL_strlen(S)+1)
+#define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "UTF-16LE", (char *)(S), (SDL_wcslen(S)+1)*sizeof(WCHAR))
+#define WIN_UTF8ToString(S) (WCHAR *)SDL_iconv_string("UTF-16LE", "UTF-8", (char *)(S), SDL_strlen(S)+1)
 #else
+/* !!! FIXME: UTF8ToString() can just be a SDL_strdup() here. */
 #define WIN_StringToUTF8(S) SDL_iconv_string("UTF-8", "ASCII", (char *)(S), (SDL_strlen(S)+1))
 #define WIN_UTF8ToString(S) SDL_iconv_string("ASCII", "UTF-8", (char *)(S), SDL_strlen(S)+1)
 #endif

+ 61 - 14
Source/ThirdParty/SDL/src/cpuinfo/SDL_cpuinfo.c

@@ -20,6 +20,10 @@
 */
 #include "SDL_config.h"
 
+#if defined(__WIN32__)
+#include "../core/windows/SDL_windows.h"
+#endif
+
 /* CPU feature detection for SDL */
 
 #include "SDL_cpuinfo.h"
@@ -41,9 +45,6 @@
 #include <signal.h>
 #include <setjmp.h>
 #endif
-#ifdef __WIN32__
-#include "../core/windows/SDL_windows.h"
-#endif
 
 #define CPU_HAS_RDTSC   0x00000001
 #define CPU_HAS_ALTIVEC 0x00000002
@@ -67,7 +68,7 @@ illegal_instruction(int sig)
 }
 #endif /* HAVE_SETJMP */
 
-static __inline__ int
+static SDL_INLINE int
 CPU_haveCPUID(void)
 {
     int has_CPUID = 0;
@@ -191,7 +192,7 @@ done:
     a = b = c = d = 0
 #endif
 
-static __inline__ int
+static SDL_INLINE int
 CPU_getCPUIDFeatures(void)
 {
     int features = 0;
@@ -205,7 +206,7 @@ CPU_getCPUIDFeatures(void)
     return features;
 }
 
-static __inline__ int
+static SDL_INLINE int
 CPU_haveRDTSC(void)
 {
     if (CPU_haveCPUID()) {
@@ -214,7 +215,7 @@ CPU_haveRDTSC(void)
     return 0;
 }
 
-static __inline__ int
+static SDL_INLINE int
 CPU_haveAltiVec(void)
 {
     volatile int altivec = 0;
@@ -241,7 +242,7 @@ CPU_haveAltiVec(void)
     return altivec;
 }
 
-static __inline__ int
+static SDL_INLINE int
 CPU_haveMMX(void)
 {
     if (CPU_haveCPUID()) {
@@ -250,7 +251,7 @@ CPU_haveMMX(void)
     return 0;
 }
 
-static __inline__ int
+static SDL_INLINE int
 CPU_have3DNow(void)
 {
     if (CPU_haveCPUID()) {
@@ -265,7 +266,7 @@ CPU_have3DNow(void)
     return 0;
 }
 
-static __inline__ int
+static SDL_INLINE int
 CPU_haveSSE(void)
 {
     if (CPU_haveCPUID()) {
@@ -274,7 +275,7 @@ CPU_haveSSE(void)
     return 0;
 }
 
-static __inline__ int
+static SDL_INLINE int
 CPU_haveSSE2(void)
 {
     if (CPU_haveCPUID()) {
@@ -283,7 +284,7 @@ CPU_haveSSE2(void)
     return 0;
 }
 
-static __inline__ int
+static SDL_INLINE int
 CPU_haveSSE3(void)
 {
     if (CPU_haveCPUID()) {
@@ -298,7 +299,7 @@ CPU_haveSSE3(void)
     return 0;
 }
 
-static __inline__ int
+static SDL_INLINE int
 CPU_haveSSE41(void)
 {
     if (CPU_haveCPUID()) {
@@ -313,7 +314,7 @@ CPU_haveSSE41(void)
     return 0;
 }
 
-static __inline__ int
+static SDL_INLINE int
 CPU_haveSSE42(void)
 {
     if (CPU_haveCPUID()) {
@@ -607,6 +608,51 @@ SDL_HasSSE42(void)
     return SDL_FALSE;
 }
 
+static int SDL_SystemRAM = 0;
+
+int
+SDL_GetSystemRAM(void)
+{
+    if (!SDL_SystemRAM) {
+#if defined(HAVE_SYSCONF) && defined(_SC_PHYS_PAGES) && defined(_SC_PAGESIZE)
+        if (SDL_SystemRAM <= 0) {
+            SDL_SystemRAM = (int)((Sint64)sysconf(_SC_PHYS_PAGES) * sysconf(_SC_PAGESIZE) / (1024*1024));
+        }
+#endif
+#ifdef HAVE_SYSCTLBYNAME
+        if (SDL_SystemRAM <= 0) {
+#ifdef __FreeBSD__
+#ifdef HW_REALMEM
+            int mib[2] = {CTL_HW, HW_REALMEM};
+#else
+            /* might only report up to 2 GiB */
+            int mib[2] = {CTL_HW, HW_PHYSMEM};
+#endif /* HW_REALMEM */
+#else
+            int mib[2] = {CTL_HW, HW_MEMSIZE};
+#endif /* __FreeBSD__ */
+            Uint64 memsize = 0;
+            size_t len = sizeof(memsize);
+            
+            if (sysctl(mib, 2, &memsize, &len, NULL, 0) == 0) {
+                SDL_SystemRAM = (int)(memsize / (1024*1024));
+            }
+        }
+#endif
+#ifdef __WIN32__
+        if (SDL_SystemRAM <= 0) {
+            MEMORYSTATUSEX stat;
+            stat.dwLength = sizeof(stat);
+            if (GlobalMemoryStatusEx(&stat)) {
+                SDL_SystemRAM = (int)(stat.ullTotalPhys / (1024 * 1024));
+            }
+        }
+#endif
+    }
+    return SDL_SystemRAM;
+}
+
+
 #ifdef TEST_MAIN
 
 #include <stdio.h>
@@ -627,6 +673,7 @@ main()
     printf("SSE3: %d\n", SDL_HasSSE3());
     printf("SSE4.1: %d\n", SDL_HasSSE41());
     printf("SSE4.2: %d\n", SDL_HasSSE42());
+    printf("RAM: %d MB\n", SDL_GetSystemRAM());
     return 0;
 }
 

+ 4 - 6
Source/ThirdParty/SDL/src/events/SDL_events.c

@@ -83,7 +83,7 @@ static struct
 } SDL_EventQ = { NULL, SDL_TRUE };
 
 
-static __inline__ SDL_bool
+static SDL_INLINE SDL_bool
 SDL_ShouldPollJoystick()
 {
 #if !SDL_JOYSTICK_DISABLED
@@ -141,10 +141,8 @@ SDL_StopEventLoop(void)
 
     /* Clear disabled event state */
     for (i = 0; i < SDL_arraysize(SDL_disabled_events); ++i) {
-        if (SDL_disabled_events[i]) {
-            SDL_free(SDL_disabled_events[i]);
-            SDL_disabled_events[i] = NULL;
-        }
+        SDL_free(SDL_disabled_events[i]);
+        SDL_disabled_events[i] = NULL;
     }
 
     while (SDL_event_watchers) {
@@ -445,7 +443,7 @@ SDL_WaitEventTimeout(SDL_Event * event, int timeout)
                 /* Polling and no events, just return */
                 return 0;
             }
-            if (timeout > 0 && ((int) (SDL_GetTicks() - expiration) >= 0)) {
+            if (timeout > 0 && SDL_TICKS_PASSED(SDL_GetTicks(), expiration)) {
                 /* Timeout expired and no events */
                 return 0;
             }

+ 62 - 61
Source/ThirdParty/SDL/src/events/SDL_gesture.c

@@ -121,8 +121,8 @@ static int SaveTemplate(SDL_DollarTemplate *templ, SDL_RWops * src)
     if (src == NULL) return 0;
 
 
-    //No Longer storing the Hash, rehash on load
-    //if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0;
+    /* No Longer storing the Hash, rehash on load */
+    /* if(SDL_RWops.write(src,&(templ->hash),sizeof(templ->hash),1) != 1) return 0; */
 
     if (SDL_RWwrite(src,templ->path,
                     sizeof(templ->path[0]),DOLLARNPOINTS) != DOLLARNPOINTS)
@@ -158,8 +158,8 @@ int SDL_SaveDollarTemplate(SDL_GestureID gestureId, SDL_RWops *src)
     return SDL_SetError("Unknown gestureId");
 }
 
-//path is an already sampled set of points
-//Returns the index of the gesture on success, or -1
+/* path is an already sampled set of points
+Returns the index of the gesture on success, or -1 */
 static int SDL_AddDollarGesture_one(SDL_GestureTouch* inTouch, SDL_FloatPoint* path)
 {
     SDL_DollarTemplate* dollarTemplate;
@@ -196,7 +196,7 @@ static int SDL_AddDollarGesture(SDL_GestureTouch* inTouch, SDL_FloatPoint* path)
             if (index < 0)
                 return -1;
         }
-        // Use the index of the last one added.
+        /* Use the index of the last one added. */
         return index;
     } else {
         return SDL_AddDollarGesture_one(inTouch, path);
@@ -223,16 +223,16 @@ int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src)
            DOLLARNPOINTS) break;
 
         if (touchId >= 0) {
-            //printf("Adding loaded gesture to 1 touch\n");
+            /* printf("Adding loaded gesture to 1 touch\n"); */
             if (SDL_AddDollarGesture(touch, templ.path) >= 0)
                 loaded++;
         }
         else {
-            //printf("Adding to: %i touches\n",SDL_numGestureTouches);
+            /* printf("Adding to: %i touches\n",SDL_numGestureTouches); */
             for (i = 0; i < SDL_numGestureTouches; i++) {
                 touch = &SDL_gestureTouch[i];
-                //printf("Adding loaded gesture to + touches\n");
-                //TODO: What if this fails?
+                /* printf("Adding loaded gesture to + touches\n"); */
+                /* TODO: What if this fails? */
                 SDL_AddDollarGesture(touch,templ.path);
             }
             loaded++;
@@ -245,7 +245,7 @@ int SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src)
 
 static float dollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ,float ang)
 {
-    //  SDL_FloatPoint p[DOLLARNPOINTS];
+    /*  SDL_FloatPoint p[DOLLARNPOINTS]; */
     float dist = 0;
     SDL_FloatPoint p;
     int i;
@@ -261,9 +261,10 @@ static float dollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ,float
 
 static float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ)
 {
-    //------------BEGIN DOLLAR BLACKBOX----------------//
-    //-TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-//
-    //-"http://depts.washington.edu/aimgroup/proj/dollar/"-//
+    /*------------BEGIN DOLLAR BLACKBOX------------------
+      -TRANSLATED DIRECTLY FROM PSUDEO-CODE AVAILABLE AT-
+      -"http://depts.washington.edu/aimgroup/proj/dollar/"
+    */
     double ta = -M_PI/4;
     double tb = M_PI/4;
     double dt = M_PI/90;
@@ -296,7 +297,7 @@ static float bestDollarDifference(SDL_FloatPoint* points,SDL_FloatPoint* templ)
     return SDL_min(f1,f2);
 }
 
-//DollarPath contains raw points, plus (possibly) the calculated length
+/* DollarPath contains raw points, plus (possibly) the calculated length */
 static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
 {
     int i;
@@ -309,7 +310,7 @@ static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
     float w,h;
     float length = path->length;
 
-    //Calculate length if it hasn't already been done
+    /* Calculate length if it hasn't already been done */
     if (length <= 0) {
         for (i=1;i < path->numPoints; i++) {
             float dx = path->p[i  ].x - path->p[i-1].x;
@@ -318,17 +319,17 @@ static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
         }
     }
 
-    //Resample
+    /* Resample */
     interval = length/(DOLLARNPOINTS - 1);
     dist = interval;
 
     centroid.x = 0;centroid.y = 0;
 
-    //printf("(%f,%f)\n",path->p[path->numPoints-1].x,path->p[path->numPoints-1].y);
+    /* printf("(%f,%f)\n",path->p[path->numPoints-1].x,path->p[path->numPoints-1].y); */
     for (i = 1; i < path->numPoints; i++) {
         float d = (float)(SDL_sqrt((path->p[i-1].x-path->p[i].x)*(path->p[i-1].x-path->p[i].x)+
                                    (path->p[i-1].y-path->p[i].y)*(path->p[i-1].y-path->p[i].y)));
-        //printf("d = %f dist = %f/%f\n",d,dist,interval);
+        /* printf("d = %f dist = %f/%f\n",d,dist,interval); */
         while (dist + d > interval) {
             points[numPoints].x = path->p[i-1].x +
                 ((interval-dist)/d)*(path->p[i].x-path->p[i-1].x);
@@ -346,15 +347,15 @@ static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
         SDL_SetError("ERROR: NumPoints = %i\n",numPoints);
         return 0;
     }
-    //copy the last point
+    /* copy the last point */
     points[DOLLARNPOINTS-1] = path->p[path->numPoints-1];
     numPoints = DOLLARNPOINTS;
 
     centroid.x /= numPoints;
     centroid.y /= numPoints;
 
-    //printf("Centroid (%f,%f)",centroid.x,centroid.y);
-    //Rotate Points so point 0 is left of centroid and solve for the bounding box
+    /* printf("Centroid (%f,%f)",centroid.x,centroid.y); */
+    /* Rotate Points so point 0 is left of centroid and solve for the bounding box */
     xmin = centroid.x;
     xmax = centroid.x;
     ymin = centroid.y;
@@ -378,7 +379,7 @@ static int dollarNormalize(const SDL_DollarPath *path,SDL_FloatPoint *points)
         if (points[i].y > ymax) ymax = points[i].y;
     }
 
-    //Scale points to DOLLARSIZE, and translate to the origin
+    /* Scale points to DOLLARSIZE, and translate to the origin */
     w = xmax-xmin;
     h = ymax-ymin;
 
@@ -399,7 +400,7 @@ static float dollarRecognize(const SDL_DollarPath *path,int *bestTempl,SDL_Gestu
 
     dollarNormalize(path,points);
 
-    //PrintPath(points);
+    /* PrintPath(points); */
     *bestTempl = -1;
     for (i = 0; i < touch->numDollarTemplates; i++) {
         float diff = bestDollarDifference(points,touch->dollarTemplate[i].path);
@@ -435,7 +436,7 @@ static SDL_GestureTouch * SDL_GetGestureTouch(SDL_TouchID id)
 {
     int i;
     for (i = 0; i < SDL_numGestureTouches; i++) {
-        //printf("%i ?= %i\n",SDL_gestureTouch[i].id,id);
+        /* printf("%i ?= %i\n",SDL_gestureTouch[i].id,id); */
         if (SDL_gestureTouch[i].id == id)
             return &SDL_gestureTouch[i];
     }
@@ -465,7 +466,7 @@ static int SDL_SendGestureDollar(SDL_GestureTouch* touch,
     event.mgesture.y = touch->centroid.y;
     event.dgesture.gestureId = gestureId;
     event.dgesture.error = error;
-    //A finger came up to trigger this event.
+    /* A finger came up to trigger this event. */
     event.dgesture.numFingers = touch->numDownFingers + 1;
     return SDL_PushEvent(&event) > 0;
 }
@@ -500,13 +501,13 @@ void SDL_GestureProcessEvent(SDL_Event* event)
         event->type == SDL_FINGERUP) {
         SDL_GestureTouch* inTouch = SDL_GetGestureTouch(event->tfinger.touchId);
 
-        //Shouldn't be possible
+        /* Shouldn't be possible */
         if (inTouch == NULL) return;
 
         x = event->tfinger.x;
         y = event->tfinger.y;
 
-        //Finger Up
+        /* Finger Up */
         if (event->type == SDL_FINGERUP) {
             inTouch->numDownFingers--;
 
@@ -514,7 +515,7 @@ void SDL_GestureProcessEvent(SDL_Event* event)
             if (inTouch->recording) {
                 inTouch->recording = SDL_FALSE;
                 dollarNormalize(&inTouch->dollarPath,path);
-                //PrintPath(path);
+                /* PrintPath(path); */
                 if (recordAll) {
                     index = SDL_AddDollarGesture(NULL,path);
                     for (i = 0; i < SDL_numGestureTouches; i++)
@@ -537,14 +538,14 @@ void SDL_GestureProcessEvent(SDL_Event* event)
                 error = dollarRecognize(&inTouch->dollarPath,
                                         &bestTempl,inTouch);
                 if (bestTempl >= 0){
-                    //Send Event
+                    /* Send Event */
                     unsigned long gestureId = inTouch->dollarTemplate[bestTempl].hash;
                     SDL_SendGestureDollar(inTouch,gestureId,error);
-                    //printf ("%s\n",);("Dollar error: %f\n",error);
+                    /* printf ("%s\n",);("Dollar error: %f\n",error); */
                 }
             }
 #endif
-            //inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers];
+            /* inTouch->gestureLast[j] = inTouch->gestureLast[inTouch->numDownFingers]; */
             if (inTouch->numDownFingers > 0) {
                 inTouch->centroid.x = (inTouch->centroid.x*(inTouch->numDownFingers+1)-
                                        x)/inTouch->numDownFingers;
@@ -574,22 +575,22 @@ void SDL_GestureProcessEvent(SDL_Event* event)
 
             inTouch->centroid.x += dx/inTouch->numDownFingers;
             inTouch->centroid.y += dy/inTouch->numDownFingers;
-            //printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y);
+            /* printf("Centrid : (%f,%f)\n",inTouch->centroid.x,inTouch->centroid.y); */
             if (inTouch->numDownFingers > 1) {
-                SDL_FloatPoint lv; //Vector from centroid to last x,y position
-                SDL_FloatPoint v; //Vector from centroid to current x,y position
-                //lv = inTouch->gestureLast[j].cv;
+                SDL_FloatPoint lv; /* Vector from centroid to last x,y position */
+                SDL_FloatPoint v; /* Vector from centroid to current x,y position */
+                /* lv = inTouch->gestureLast[j].cv; */
                 lv.x = lastP.x - lastCentroid.x;
                 lv.y = lastP.y - lastCentroid.y;
                 lDist = (float)SDL_sqrt(lv.x*lv.x + lv.y*lv.y);
-                //printf("lDist = %f\n",lDist);
+                /* printf("lDist = %f\n",lDist); */
                 v.x = x - inTouch->centroid.x;
                 v.y = y - inTouch->centroid.y;
-                //inTouch->gestureLast[j].cv = v;
+                /* inTouch->gestureLast[j].cv = v; */
                 Dist = (float)SDL_sqrt(v.x*v.x+v.y*v.y);
-                // SDL_cos(dTheta) = (v . lv)/(|v| * |lv|)
+                /* SDL_cos(dTheta) = (v . lv)/(|v| * |lv|) */
 
-                //Normalize Vectors to simplify angle calculation
+                /* Normalize Vectors to simplify angle calculation */
                 lv.x/=lDist;
                 lv.y/=lDist;
                 v.x/=Dist;
@@ -597,30 +598,30 @@ void SDL_GestureProcessEvent(SDL_Event* event)
                 dtheta = (float)SDL_atan2(lv.x*v.y - lv.y*v.x,lv.x*v.x + lv.y*v.y);
 
                 dDist = (Dist - lDist);
-                if (lDist == 0) {dDist = 0;dtheta = 0;} //To avoid impossible values
-
-                //inTouch->gestureLast[j].dDist = dDist;
-                //inTouch->gestureLast[j].dtheta = dtheta;
-
-                //printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
-                //gdtheta = gdtheta*.9 + dtheta*.1;
-                //gdDist  =  gdDist*.9 +  dDist*.1
-                //knob.r += dDist/numDownFingers;
-                //knob.ang += dtheta;
-                //printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
-                //printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist);
+                if (lDist == 0) {dDist = 0;dtheta = 0;} /* To avoid impossible values */
+
+                /* inTouch->gestureLast[j].dDist = dDist;
+                inTouch->gestureLast[j].dtheta = dtheta;
+
+                printf("dDist = %f, dTheta = %f\n",dDist,dtheta);
+                gdtheta = gdtheta*.9 + dtheta*.1;
+                gdDist  =  gdDist*.9 +  dDist*.1
+                knob.r += dDist/numDownFingers;
+                knob.ang += dtheta;
+                printf("thetaSum = %f, distSum = %f\n",gdtheta,gdDist);
+                printf("id: %i dTheta = %f, dDist = %f\n",j,dtheta,dDist); */
                 SDL_SendGestureMulti(inTouch,dtheta,dDist);
             }
             else {
-                //inTouch->gestureLast[j].dDist = 0;
-                //inTouch->gestureLast[j].dtheta = 0;
-                //inTouch->gestureLast[j].cv.x = 0;
-                //inTouch->gestureLast[j].cv.y = 0;
+                /* inTouch->gestureLast[j].dDist = 0;
+                inTouch->gestureLast[j].dtheta = 0;
+                inTouch->gestureLast[j].cv.x = 0;
+                inTouch->gestureLast[j].cv.y = 0; */
             }
-            //inTouch->gestureLast[j].f.p.x = x;
-            //inTouch->gestureLast[j].f.p.y = y;
-            //break;
-            //pressure?
+            /* inTouch->gestureLast[j].f.p.x = x;
+            inTouch->gestureLast[j].f.p.y = y;
+            break;
+            pressure? */
         }
 
         if (event->type == SDL_FINGERDOWN) {
@@ -630,8 +631,8 @@ void SDL_GestureProcessEvent(SDL_Event* event)
                                    x)/inTouch->numDownFingers;
             inTouch->centroid.y = (inTouch->centroid.y*(inTouch->numDownFingers - 1)+
                                    y)/inTouch->numDownFingers;
-            //printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
-            //     inTouch->centroid.x,inTouch->centroid.y);
+            /* printf("Finger Down: (%f,%f). Centroid: (%f,%f\n",x,y,
+                 inTouch->centroid.x,inTouch->centroid.y); */
 
 #ifdef ENABLE_DOLLAR
             inTouch->dollarPath.length = 0;

+ 2 - 2
Source/ThirdParty/SDL/src/events/SDL_keyboard.c

@@ -28,7 +28,7 @@
 #include "../video/SDL_sysvideo.h"
 
 
-/*#define DEBUG_KEYBOARD*/
+/* #define DEBUG_KEYBOARD */
 
 /* Global keyboard information */
 
@@ -507,7 +507,7 @@ static const char *SDL_scancode_names[SDL_NUM_SCANCODES] = {
 };
 
 /* Taken from SDL_iconv() */
-static char *
+char *
 SDL_UCS4ToUTF8(Uint32 ch, char *dst)
 {
     Uint8 *p = (Uint8 *) dst;

+ 3 - 0
Source/ThirdParty/SDL/src/events/SDL_keyboard_c.h

@@ -59,6 +59,9 @@ extern int SDL_SendEditingText(const char *text, int start, int end);
 /* Shutdown the keyboard subsystem */
 extern void SDL_KeyboardQuit(void);
 
+/* Convert to UTF-8 */
+extern char *SDL_UCS4ToUTF8(Uint32 ch, char *dst);
+
 #endif /* _SDL_keyboard_c_h */
 
 /* vi: set ts=4 sw=4 expandtab: */

Some files were not shown because too many files changed in this diff