Bump libsdl to 2.26.1
This commit is contained in:
parent
0d93279a10
commit
4b03c714b4
|
@ -15,13 +15,9 @@ import android.content.pm.PackageManager;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.PixelFormat;
|
|
||||||
import android.graphics.PorterDuff;
|
import android.graphics.PorterDuff;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.hardware.Sensor;
|
import android.hardware.Sensor;
|
||||||
import android.hardware.SensorEvent;
|
|
||||||
import android.hardware.SensorEventListener;
|
|
||||||
import android.hardware.SensorManager;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
@ -37,11 +33,8 @@ import android.view.Display;
|
||||||
import android.view.Gravity;
|
import android.view.Gravity;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
import android.view.KeyEvent;
|
import android.view.KeyEvent;
|
||||||
import android.view.MotionEvent;
|
|
||||||
import android.view.PointerIcon;
|
import android.view.PointerIcon;
|
||||||
import android.view.Surface;
|
import android.view.Surface;
|
||||||
import android.view.SurfaceHolder;
|
|
||||||
import android.view.SurfaceView;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
|
@ -51,6 +44,7 @@ import android.view.inputmethod.EditorInfo;
|
||||||
import android.view.inputmethod.InputConnection;
|
import android.view.inputmethod.InputConnection;
|
||||||
import android.view.inputmethod.InputMethodManager;
|
import android.view.inputmethod.InputMethodManager;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.EditText;
|
||||||
import android.widget.LinearLayout;
|
import android.widget.LinearLayout;
|
||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
@ -65,6 +59,9 @@ import java.util.Locale;
|
||||||
*/
|
*/
|
||||||
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
|
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
|
||||||
private static final String TAG = "SDL";
|
private static final String TAG = "SDL";
|
||||||
|
private static final int SDL_MAJOR_VERSION = 2;
|
||||||
|
private static final int SDL_MINOR_VERSION = 26;
|
||||||
|
private static final int SDL_MICRO_VERSION = 1;
|
||||||
/*
|
/*
|
||||||
// Display InputType.SOURCE/CLASS of events and devices
|
// Display InputType.SOURCE/CLASS of events and devices
|
||||||
//
|
//
|
||||||
|
@ -213,7 +210,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
// Main components
|
// Main components
|
||||||
protected static SDLActivity mSingleton;
|
protected static SDLActivity mSingleton;
|
||||||
protected static SDLSurface mSurface;
|
protected static SDLSurface mSurface;
|
||||||
protected static View mTextEdit;
|
protected static DummyEdit mTextEdit;
|
||||||
protected static boolean mScreenKeyboardShown;
|
protected static boolean mScreenKeyboardShown;
|
||||||
protected static ViewGroup mLayout;
|
protected static ViewGroup mLayout;
|
||||||
protected static SDLClipboardHandler mClipboardHandler;
|
protected static SDLClipboardHandler mClipboardHandler;
|
||||||
|
@ -314,6 +311,10 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
mNextNativeState = NativeState.INIT;
|
mNextNativeState = NativeState.INIT;
|
||||||
mCurrentNativeState = NativeState.INIT;
|
mCurrentNativeState = NativeState.INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected SDLSurface createSDLSurface(Context context) {
|
||||||
|
return new SDLSurface(context);
|
||||||
|
}
|
||||||
|
|
||||||
// Setup
|
// Setup
|
||||||
@Override
|
@Override
|
||||||
|
@ -344,8 +345,18 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
errorMsgBrokenLib = e.getMessage();
|
errorMsgBrokenLib = e.getMessage();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mBrokenLibraries)
|
if (!mBrokenLibraries) {
|
||||||
{
|
String expected_version = String.valueOf(SDL_MAJOR_VERSION) + "." +
|
||||||
|
String.valueOf(SDL_MINOR_VERSION) + "." +
|
||||||
|
String.valueOf(SDL_MICRO_VERSION);
|
||||||
|
String version = nativeGetVersion();
|
||||||
|
if (!version.equals(expected_version)) {
|
||||||
|
mBrokenLibraries = true;
|
||||||
|
errorMsgBrokenLib = "SDL C/Java version mismatch (expected " + expected_version + ", got " + version + ")";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mBrokenLibraries) {
|
||||||
mSingleton = this;
|
mSingleton = this;
|
||||||
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
|
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
|
||||||
dlgAlert.setMessage("An error occurred while trying to start the application. Please try again and/or reinstall."
|
dlgAlert.setMessage("An error occurred while trying to start the application. Please try again and/or reinstall."
|
||||||
|
@ -382,7 +393,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
mHIDDeviceManager = HIDDeviceManager.acquire(this);
|
mHIDDeviceManager = HIDDeviceManager.acquire(this);
|
||||||
|
|
||||||
// Set up the surface
|
// Set up the surface
|
||||||
mSurface = new SDLSurface(getApplication());
|
mSurface = createSDLSurface(getApplication());
|
||||||
|
|
||||||
mLayout = new RelativeLayout(this);
|
mLayout = new RelativeLayout(this);
|
||||||
mLayout.addView(mSurface);
|
mLayout.addView(mSurface);
|
||||||
|
@ -886,6 +897,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
}
|
}
|
||||||
|
|
||||||
// C functions we call
|
// C functions we call
|
||||||
|
public static native String nativeGetVersion();
|
||||||
public static native int nativeSetupJNI();
|
public static native int nativeSetupJNI();
|
||||||
public static native int nativeRunMain(String library, String function, Object arguments);
|
public static native int nativeRunMain(String library, String function, Object arguments);
|
||||||
public static native void nativeLowMemory();
|
public static native void nativeLowMemory();
|
||||||
|
@ -1220,8 +1232,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
}
|
}
|
||||||
|
|
||||||
// This method is called by SDLControllerManager's API 26 Generic Motion Handler.
|
// This method is called by SDLControllerManager's API 26 Generic Motion Handler.
|
||||||
public static View getContentView()
|
public static View getContentView() {
|
||||||
{
|
|
||||||
return mLayout;
|
return mLayout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1292,6 +1303,77 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||||
return event.isPrintingKey() || event.getKeyCode() == KeyEvent.KEYCODE_SPACE;
|
return event.isPrintingKey() || event.getKeyCode() == KeyEvent.KEYCODE_SPACE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean handleKeyEvent(View v, int keyCode, KeyEvent event, InputConnection ic) {
|
||||||
|
int deviceId = event.getDeviceId();
|
||||||
|
int source = event.getSource();
|
||||||
|
|
||||||
|
if (source == InputDevice.SOURCE_UNKNOWN) {
|
||||||
|
InputDevice device = InputDevice.getDevice(deviceId);
|
||||||
|
if (device != null) {
|
||||||
|
source = device.getSources();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
|
// Log.v("SDL", "key down: " + keyCode + ", deviceId = " + deviceId + ", source = " + source);
|
||||||
|
// } else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
// Log.v("SDL", "key up: " + keyCode + ", deviceId = " + deviceId + ", source = " + source);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Dispatch the different events depending on where they come from
|
||||||
|
// Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
|
||||||
|
// So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD
|
||||||
|
//
|
||||||
|
// Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
|
||||||
|
// SOURCE_JOYSTICK, while its key events arrive from the keyboard source
|
||||||
|
// So, retrieve the device itself and check all of its sources
|
||||||
|
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
|
||||||
|
// Note that we process events with specific key codes here
|
||||||
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
|
if (SDLControllerManager.onNativePadDown(deviceId, keyCode) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
if (SDLControllerManager.onNativePadUp(deviceId, keyCode) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
|
||||||
|
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
||||||
|
if (isTextInputEvent(event)) {
|
||||||
|
if (ic != null) {
|
||||||
|
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
|
||||||
|
} else {
|
||||||
|
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
onNativeKeyDown(keyCode);
|
||||||
|
return true;
|
||||||
|
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
||||||
|
onNativeKeyUp(keyCode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
|
||||||
|
// on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
|
||||||
|
// they are ignored here because sending them as mouse input to SDL is messy
|
||||||
|
if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) {
|
||||||
|
switch (event.getAction()) {
|
||||||
|
case KeyEvent.ACTION_DOWN:
|
||||||
|
case KeyEvent.ACTION_UP:
|
||||||
|
// mark the event as handled or it will be handled by system
|
||||||
|
// handling KEYCODE_BACK by system will call onBackPressed()
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is called by SDL using JNI.
|
* This method is called by SDL using JNI.
|
||||||
*/
|
*/
|
||||||
|
@ -1809,455 +1891,6 @@ class SDLMain implements Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
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 SensorManager mSensorManager;
|
|
||||||
protected Display mDisplay;
|
|
||||||
|
|
||||||
// Keep track of the surface size to normalize touch events
|
|
||||||
protected float mWidth, mHeight;
|
|
||||||
|
|
||||||
// Is SurfaceView ready for rendering
|
|
||||||
public boolean mIsSurfaceReady;
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
setOnGenericMotionListener(SDLActivity.getMotionListener());
|
|
||||||
|
|
||||||
// Some arbitrary defaults to avoid a potential division by zero
|
|
||||||
mWidth = 1.0f;
|
|
||||||
mHeight = 1.0f;
|
|
||||||
|
|
||||||
mIsSurfaceReady = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handlePause() {
|
|
||||||
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handleResume() {
|
|
||||||
setFocusable(true);
|
|
||||||
setFocusableInTouchMode(true);
|
|
||||||
requestFocus();
|
|
||||||
setOnKeyListener(this);
|
|
||||||
setOnTouchListener(this);
|
|
||||||
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Surface getNativeSurface() {
|
|
||||||
return getHolder().getSurface();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when we have a valid drawing surface
|
|
||||||
@Override
|
|
||||||
public void surfaceCreated(SurfaceHolder holder) {
|
|
||||||
Log.v("SDL", "surfaceCreated()");
|
|
||||||
SDLActivity.onNativeSurfaceCreated();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called when we lose the surface
|
|
||||||
@Override
|
|
||||||
public void surfaceDestroyed(SurfaceHolder holder) {
|
|
||||||
Log.v("SDL", "surfaceDestroyed()");
|
|
||||||
|
|
||||||
// Transition to pause, if needed
|
|
||||||
SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;
|
|
||||||
SDLActivity.handleNativeState();
|
|
||||||
|
|
||||||
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()");
|
|
||||||
|
|
||||||
if (SDLActivity.mSingleton == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mWidth = width;
|
|
||||||
mHeight = height;
|
|
||||||
int nDeviceWidth = width;
|
|
||||||
int nDeviceHeight = height;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (Build.VERSION.SDK_INT >= 17) {
|
|
||||||
DisplayMetrics realMetrics = new DisplayMetrics();
|
|
||||||
mDisplay.getRealMetrics( realMetrics );
|
|
||||||
nDeviceWidth = realMetrics.widthPixels;
|
|
||||||
nDeviceHeight = realMetrics.heightPixels;
|
|
||||||
}
|
|
||||||
} catch(Exception ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
synchronized(SDLActivity.getContext()) {
|
|
||||||
// In case we're waiting on a size change after going fullscreen, send a notification.
|
|
||||||
SDLActivity.getContext().notifyAll();
|
|
||||||
}
|
|
||||||
|
|
||||||
Log.v("SDL", "Window size: " + width + "x" + height);
|
|
||||||
Log.v("SDL", "Device size: " + nDeviceWidth + "x" + nDeviceHeight);
|
|
||||||
SDLActivity.nativeSetScreenResolution(width, height, nDeviceWidth, nDeviceHeight, mDisplay.getRefreshRate());
|
|
||||||
SDLActivity.onNativeResize();
|
|
||||||
|
|
||||||
// Prevent a screen distortion glitch,
|
|
||||||
// for instance when the device is in Landscape and a Portrait App is resumed.
|
|
||||||
boolean skip = false;
|
|
||||||
int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();
|
|
||||||
|
|
||||||
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
|
|
||||||
if (mWidth > mHeight) {
|
|
||||||
skip = true;
|
|
||||||
}
|
|
||||||
} else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
|
|
||||||
if (mWidth < mHeight) {
|
|
||||||
skip = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Special Patch for Square Resolution: Black Berry Passport
|
|
||||||
if (skip) {
|
|
||||||
double min = Math.min(mWidth, mHeight);
|
|
||||||
double max = Math.max(mWidth, mHeight);
|
|
||||||
|
|
||||||
if (max / min < 1.20) {
|
|
||||||
Log.v("SDL", "Don't skip on such aspect-ratio. Could be a square resolution.");
|
|
||||||
skip = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Don't skip in MultiWindow.
|
|
||||||
if (skip) {
|
|
||||||
if (Build.VERSION.SDK_INT >= 24) {
|
|
||||||
if (SDLActivity.mSingleton.isInMultiWindowMode()) {
|
|
||||||
Log.v("SDL", "Don't skip in Multi-Window");
|
|
||||||
skip = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (skip) {
|
|
||||||
Log.v("SDL", "Skip .. Surface is not ready.");
|
|
||||||
mIsSurfaceReady = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
|
|
||||||
SDLActivity.onNativeSurfaceChanged();
|
|
||||||
|
|
||||||
/* Surface is ready */
|
|
||||||
mIsSurfaceReady = true;
|
|
||||||
|
|
||||||
SDLActivity.mNextNativeState = SDLActivity.NativeState.RESUMED;
|
|
||||||
SDLActivity.handleNativeState();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Key events
|
|
||||||
@Override
|
|
||||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
|
||||||
|
|
||||||
int deviceId = event.getDeviceId();
|
|
||||||
int source = event.getSource();
|
|
||||||
|
|
||||||
if (source == InputDevice.SOURCE_UNKNOWN) {
|
|
||||||
InputDevice device = InputDevice.getDevice(deviceId);
|
|
||||||
if (device != null) {
|
|
||||||
source = device.getSources();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
|
||||||
// Log.v("SDL", "key down: " + keyCode + ", deviceId = " + deviceId + ", source = " + source);
|
|
||||||
// } else if (event.getAction() == KeyEvent.ACTION_UP) {
|
|
||||||
// Log.v("SDL", "key up: " + keyCode + ", deviceId = " + deviceId + ", source = " + source);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Dispatch the different events depending on where they come from
|
|
||||||
// Some SOURCE_JOYSTICK, SOURCE_DPAD or SOURCE_GAMEPAD are also SOURCE_KEYBOARD
|
|
||||||
// So, we try to process them as JOYSTICK/DPAD/GAMEPAD events first, if that fails we try them as KEYBOARD
|
|
||||||
//
|
|
||||||
// Furthermore, it's possible a game controller has SOURCE_KEYBOARD and
|
|
||||||
// SOURCE_JOYSTICK, while its key events arrive from the keyboard source
|
|
||||||
// So, retrieve the device itself and check all of its sources
|
|
||||||
if (SDLControllerManager.isDeviceSDLJoystick(deviceId)) {
|
|
||||||
// Note that we process events with specific key codes here
|
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
|
||||||
if (SDLControllerManager.onNativePadDown(deviceId, keyCode) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
|
||||||
if (SDLControllerManager.onNativePadUp(deviceId, keyCode) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((source & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
|
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
|
||||||
if (SDLActivity.isTextInputEvent(event)) {
|
|
||||||
SDLInputConnection.nativeCommitText(String.valueOf((char) event.getUnicodeChar()), 1);
|
|
||||||
}
|
|
||||||
SDLActivity.onNativeKeyDown(keyCode);
|
|
||||||
return true;
|
|
||||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
|
||||||
SDLActivity.onNativeKeyUp(keyCode);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((source & InputDevice.SOURCE_MOUSE) == InputDevice.SOURCE_MOUSE) {
|
|
||||||
// on some devices key events are sent for mouse BUTTON_BACK/FORWARD presses
|
|
||||||
// they are ignored here because sending them as mouse input to SDL is messy
|
|
||||||
if ((keyCode == KeyEvent.KEYCODE_BACK) || (keyCode == KeyEvent.KEYCODE_FORWARD)) {
|
|
||||||
switch (event.getAction()) {
|
|
||||||
case KeyEvent.ACTION_DOWN:
|
|
||||||
case KeyEvent.ACTION_UP:
|
|
||||||
// mark the event as handled or it will be handled by system
|
|
||||||
// handling KEYCODE_BACK by system will call onBackPressed()
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Touch events
|
|
||||||
@Override
|
|
||||||
public boolean onTouch(View v, MotionEvent event) {
|
|
||||||
/* Ref: http://developer.android.com/training/gestures/multi.html */
|
|
||||||
int touchDevId = event.getDeviceId();
|
|
||||||
final int pointerCount = event.getPointerCount();
|
|
||||||
int action = event.getActionMasked();
|
|
||||||
int pointerFingerId;
|
|
||||||
int i = -1;
|
|
||||||
float x,y,p;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Prevent id to be -1, since it's used in SDL internal for synthetic events
|
|
||||||
* Appears when using Android emulator, eg:
|
|
||||||
* adb shell input mouse tap 100 100
|
|
||||||
* adb shell input touchscreen tap 100 100
|
|
||||||
*/
|
|
||||||
if (touchDevId < 0) {
|
|
||||||
touchDevId -= 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 12290 = Samsung DeX mode desktop mouse
|
|
||||||
// 12290 = 0x3002 = 0x2002 | 0x1002 = SOURCE_MOUSE | SOURCE_TOUCHSCREEN
|
|
||||||
// 0x2 = SOURCE_CLASS_POINTER
|
|
||||||
if (event.getSource() == InputDevice.SOURCE_MOUSE || event.getSource() == (InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN)) {
|
|
||||||
int mouseButton = 1;
|
|
||||||
try {
|
|
||||||
Object object = event.getClass().getMethod("getButtonState").invoke(event);
|
|
||||||
if (object != null) {
|
|
||||||
mouseButton = (Integer) object;
|
|
||||||
}
|
|
||||||
} catch(Exception ignored) {
|
|
||||||
}
|
|
||||||
|
|
||||||
// We need to check if we're in relative mouse mode and get the axis offset rather than the x/y values
|
|
||||||
// if we are. We'll leverage our existing mouse motion listener
|
|
||||||
SDLGenericMotionListener_API12 motionListener = SDLActivity.getMotionListener();
|
|
||||||
x = motionListener.getEventX(event);
|
|
||||||
y = motionListener.getEventY(event);
|
|
||||||
|
|
||||||
SDLActivity.onNativeMouse(mouseButton, action, x, y, motionListener.inRelativeMode());
|
|
||||||
} else {
|
|
||||||
switch(action) {
|
|
||||||
case MotionEvent.ACTION_MOVE:
|
|
||||||
for (i = 0; i < pointerCount; i++) {
|
|
||||||
pointerFingerId = event.getPointerId(i);
|
|
||||||
x = event.getX(i) / mWidth;
|
|
||||||
y = event.getY(i) / mHeight;
|
|
||||||
p = event.getPressure(i);
|
|
||||||
if (p > 1.0f) {
|
|
||||||
// may be larger than 1.0f on some devices
|
|
||||||
// see the documentation of getPressure(i)
|
|
||||||
p = 1.0f;
|
|
||||||
}
|
|
||||||
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_UP:
|
|
||||||
case MotionEvent.ACTION_DOWN:
|
|
||||||
// Primary pointer up/down, the index is always zero
|
|
||||||
i = 0;
|
|
||||||
/* fallthrough */
|
|
||||||
case MotionEvent.ACTION_POINTER_UP:
|
|
||||||
case MotionEvent.ACTION_POINTER_DOWN:
|
|
||||||
// Non primary pointer up/down
|
|
||||||
if (i == -1) {
|
|
||||||
i = event.getActionIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
pointerFingerId = event.getPointerId(i);
|
|
||||||
x = event.getX(i) / mWidth;
|
|
||||||
y = event.getY(i) / mHeight;
|
|
||||||
p = event.getPressure(i);
|
|
||||||
if (p > 1.0f) {
|
|
||||||
// may be larger than 1.0f on some devices
|
|
||||||
// see the documentation of getPressure(i)
|
|
||||||
p = 1.0f;
|
|
||||||
}
|
|
||||||
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_CANCEL:
|
|
||||||
for (i = 0; i < pointerCount; i++) {
|
|
||||||
pointerFingerId = event.getPointerId(i);
|
|
||||||
x = event.getX(i) / mWidth;
|
|
||||||
y = event.getY(i) / mHeight;
|
|
||||||
p = event.getPressure(i);
|
|
||||||
if (p > 1.0f) {
|
|
||||||
// may be larger than 1.0f on some devices
|
|
||||||
// see the documentation of getPressure(i)
|
|
||||||
p = 1.0f;
|
|
||||||
}
|
|
||||||
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
|
|
||||||
// Since we may have an orientation set, we won't receive onConfigurationChanged events.
|
|
||||||
// We thus should check here.
|
|
||||||
int newOrientation;
|
|
||||||
|
|
||||||
float x, y;
|
|
||||||
switch (mDisplay.getRotation()) {
|
|
||||||
case Surface.ROTATION_90:
|
|
||||||
x = -event.values[1];
|
|
||||||
y = event.values[0];
|
|
||||||
newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE;
|
|
||||||
break;
|
|
||||||
case Surface.ROTATION_270:
|
|
||||||
x = event.values[1];
|
|
||||||
y = -event.values[0];
|
|
||||||
newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE_FLIPPED;
|
|
||||||
break;
|
|
||||||
case Surface.ROTATION_180:
|
|
||||||
x = -event.values[0];
|
|
||||||
y = -event.values[1];
|
|
||||||
newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT_FLIPPED;
|
|
||||||
break;
|
|
||||||
case Surface.ROTATION_0:
|
|
||||||
default:
|
|
||||||
x = event.values[0];
|
|
||||||
y = event.values[1];
|
|
||||||
newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newOrientation != SDLActivity.mCurrentOrientation) {
|
|
||||||
SDLActivity.mCurrentOrientation = newOrientation;
|
|
||||||
SDLActivity.onNativeOrientationChanged(newOrientation);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
|
|
||||||
y / SensorManager.GRAVITY_EARTH,
|
|
||||||
event.values[2] / SensorManager.GRAVITY_EARTH);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Captured pointer events for API 26.
|
|
||||||
public boolean onCapturedPointerEvent(MotionEvent event)
|
|
||||||
{
|
|
||||||
int action = event.getActionMasked();
|
|
||||||
|
|
||||||
float x, y;
|
|
||||||
switch (action) {
|
|
||||||
case MotionEvent.ACTION_SCROLL:
|
|
||||||
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
|
|
||||||
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
|
|
||||||
SDLActivity.onNativeMouse(0, action, x, y, false);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_HOVER_MOVE:
|
|
||||||
case MotionEvent.ACTION_MOVE:
|
|
||||||
x = event.getX(0);
|
|
||||||
y = event.getY(0);
|
|
||||||
SDLActivity.onNativeMouse(0, action, x, y, true);
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case MotionEvent.ACTION_BUTTON_PRESS:
|
|
||||||
case MotionEvent.ACTION_BUTTON_RELEASE:
|
|
||||||
|
|
||||||
// Change our action value to what SDL's code expects.
|
|
||||||
if (action == MotionEvent.ACTION_BUTTON_PRESS) {
|
|
||||||
action = MotionEvent.ACTION_DOWN;
|
|
||||||
} else { /* MotionEvent.ACTION_BUTTON_RELEASE */
|
|
||||||
action = MotionEvent.ACTION_UP;
|
|
||||||
}
|
|
||||||
|
|
||||||
x = event.getX(0);
|
|
||||||
y = event.getY(0);
|
|
||||||
int button = event.getButtonState();
|
|
||||||
|
|
||||||
SDLActivity.onNativeMouse(button, action, x, y, true);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is a fake invisible editor view that receives the input and defines the
|
/* This is a fake invisible editor view that receives the input and defines the
|
||||||
* pan&scan region
|
* pan&scan region
|
||||||
*/
|
*/
|
||||||
|
@ -2278,21 +1911,7 @@ class DummyEdit extends View implements View.OnKeyListener {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||||
/*
|
return SDLActivity.handleKeyEvent(v, keyCode, event, ic);
|
||||||
* This handles the hardware keyboard input
|
|
||||||
*/
|
|
||||||
if (event.getAction() == KeyEvent.ACTION_DOWN) {
|
|
||||||
if (SDLActivity.isTextInputEvent(event)) {
|
|
||||||
ic.commitText(String.valueOf((char) event.getUnicodeChar()), 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
SDLActivity.onNativeKeyDown(keyCode);
|
|
||||||
return true;
|
|
||||||
} else if (event.getAction() == KeyEvent.ACTION_UP) {
|
|
||||||
SDLActivity.onNativeKeyUp(keyCode);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -2316,9 +1935,10 @@ class DummyEdit extends View implements View.OnKeyListener {
|
||||||
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
|
||||||
ic = new SDLInputConnection(this, true);
|
ic = new SDLInputConnection(this, true);
|
||||||
|
|
||||||
outAttrs.inputType = InputType.TYPE_CLASS_TEXT;
|
outAttrs.inputType = InputType.TYPE_CLASS_TEXT |
|
||||||
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
|
InputType.TYPE_TEXT_FLAG_MULTI_LINE;
|
||||||
| EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */;
|
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI |
|
||||||
|
EditorInfo.IME_FLAG_NO_FULLSCREEN /* API 11 */;
|
||||||
|
|
||||||
return ic;
|
return ic;
|
||||||
}
|
}
|
||||||
|
@ -2326,9 +1946,17 @@ class DummyEdit extends View implements View.OnKeyListener {
|
||||||
|
|
||||||
class SDLInputConnection extends BaseInputConnection {
|
class SDLInputConnection extends BaseInputConnection {
|
||||||
|
|
||||||
|
protected EditText mEditText;
|
||||||
|
protected String mCommittedText = "";
|
||||||
|
|
||||||
public SDLInputConnection(View targetView, boolean fullEditor) {
|
public SDLInputConnection(View targetView, boolean fullEditor) {
|
||||||
super(targetView, fullEditor);
|
super(targetView, fullEditor);
|
||||||
|
mEditText = new EditText(SDL.getContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Editable getEditable() {
|
||||||
|
return mEditText.getEditableText();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2351,79 +1979,84 @@ class SDLInputConnection extends BaseInputConnection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
return super.sendKeyEvent(event);
|
return super.sendKeyEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean commitText(CharSequence text, int newCursorPosition) {
|
public boolean commitText(CharSequence text, int newCursorPosition) {
|
||||||
|
if (!super.commitText(text, newCursorPosition)) {
|
||||||
/* Generate backspaces for the text we're going to replace */
|
return false;
|
||||||
final Editable content = getEditable();
|
|
||||||
if (content != null) {
|
|
||||||
int a = getComposingSpanStart(content);
|
|
||||||
int b = getComposingSpanEnd(content);
|
|
||||||
if (a == -1 || b == -1) {
|
|
||||||
a = Selection.getSelectionStart(content);
|
|
||||||
b = Selection.getSelectionEnd(content);
|
|
||||||
}
|
|
||||||
if (a < 0) a = 0;
|
|
||||||
if (b < 0) b = 0;
|
|
||||||
if (b < a) {
|
|
||||||
int tmp = a;
|
|
||||||
a = b;
|
|
||||||
b = tmp;
|
|
||||||
}
|
|
||||||
int backspaces = (b - a);
|
|
||||||
|
|
||||||
for (int i = 0; i < backspaces; i++) {
|
|
||||||
nativeGenerateScancodeForUnichar('\b');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
updateText();
|
||||||
for (int i = 0; i < text.length(); i++) {
|
return true;
|
||||||
char c = text.charAt(i);
|
|
||||||
if (c == '\n') {
|
|
||||||
if (SDLActivity.onNativeSoftReturnKey()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
nativeGenerateScancodeForUnichar(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDLInputConnection.nativeCommitText(text.toString(), newCursorPosition);
|
|
||||||
|
|
||||||
return super.commitText(text, newCursorPosition);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
public boolean setComposingText(CharSequence text, int newCursorPosition) {
|
||||||
|
if (!super.setComposingText(text, newCursorPosition)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
updateText();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
nativeSetComposingText(text.toString(), newCursorPosition);
|
@Override
|
||||||
|
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
||||||
|
if (!super.deleteSurroundingText(beforeLength, afterLength)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
updateText();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return super.setComposingText(text, newCursorPosition);
|
protected void updateText() {
|
||||||
|
final Editable content = getEditable();
|
||||||
|
if (content == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
String text = content.toString();
|
||||||
|
int compareLength = Math.min(text.length(), mCommittedText.length());
|
||||||
|
int matchLength, offset;
|
||||||
|
|
||||||
|
/* Backspace over characters that are no longer in the string */
|
||||||
|
for (matchLength = 0; matchLength < compareLength; ) {
|
||||||
|
int codePoint = mCommittedText.codePointAt(matchLength);
|
||||||
|
if (codePoint != text.codePointAt(matchLength)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
matchLength += Character.charCount(codePoint);
|
||||||
|
}
|
||||||
|
/* FIXME: This doesn't handle graphemes, like '🌬️' */
|
||||||
|
for (offset = matchLength; offset < mCommittedText.length(); ) {
|
||||||
|
int codePoint = mCommittedText.codePointAt(offset);
|
||||||
|
nativeGenerateScancodeForUnichar('\b');
|
||||||
|
offset += Character.charCount(codePoint);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matchLength < text.length()) {
|
||||||
|
String pendingText = text.subSequence(matchLength, text.length()).toString();
|
||||||
|
for (offset = 0; offset < pendingText.length(); ) {
|
||||||
|
int codePoint = pendingText.codePointAt(offset);
|
||||||
|
if (codePoint == '\n') {
|
||||||
|
if (SDLActivity.onNativeSoftReturnKey()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Higher code points don't generate simulated scancodes */
|
||||||
|
if (codePoint < 128) {
|
||||||
|
nativeGenerateScancodeForUnichar((char)codePoint);
|
||||||
|
}
|
||||||
|
offset += Character.charCount(codePoint);
|
||||||
|
}
|
||||||
|
SDLInputConnection.nativeCommitText(pendingText, 0);
|
||||||
|
}
|
||||||
|
mCommittedText = text;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static native void nativeCommitText(String text, int newCursorPosition);
|
public static native void nativeCommitText(String text, int newCursorPosition);
|
||||||
|
|
||||||
public native void nativeGenerateScancodeForUnichar(char c);
|
public static native void nativeGenerateScancodeForUnichar(char c);
|
||||||
|
|
||||||
public native void nativeSetComposingText(String text, int newCursorPosition);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
|
|
||||||
// Workaround to capture backspace key. Ref: http://stackoverflow.com/questions/14560344/android-backspace-in-webview-baseinputconnection
|
|
||||||
// and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
|
|
||||||
if (beforeLength > 0 && afterLength == 0) {
|
|
||||||
// backspace(s)
|
|
||||||
while (beforeLength-- > 0) {
|
|
||||||
nativeGenerateScancodeForUnichar('\b');
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return super.deleteSurroundingText(beforeLength, afterLength);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class SDLClipboardHandler implements
|
class SDLClipboardHandler implements
|
||||||
|
|
|
@ -0,0 +1,405 @@
|
||||||
|
package org.libsdl.app;
|
||||||
|
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.pm.ActivityInfo;
|
||||||
|
import android.hardware.Sensor;
|
||||||
|
import android.hardware.SensorEvent;
|
||||||
|
import android.hardware.SensorEventListener;
|
||||||
|
import android.hardware.SensorManager;
|
||||||
|
import android.os.Build;
|
||||||
|
import android.util.DisplayMetrics;
|
||||||
|
import android.util.Log;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.view.InputDevice;
|
||||||
|
import android.view.KeyEvent;
|
||||||
|
import android.view.MotionEvent;
|
||||||
|
import android.view.Surface;
|
||||||
|
import android.view.SurfaceHolder;
|
||||||
|
import android.view.SurfaceView;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.WindowManager;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
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
|
||||||
|
*/
|
||||||
|
public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||||
|
View.OnKeyListener, View.OnTouchListener, SensorEventListener {
|
||||||
|
|
||||||
|
// Sensors
|
||||||
|
protected SensorManager mSensorManager;
|
||||||
|
protected Display mDisplay;
|
||||||
|
|
||||||
|
// Keep track of the surface size to normalize touch events
|
||||||
|
protected float mWidth, mHeight;
|
||||||
|
|
||||||
|
// Is SurfaceView ready for rendering
|
||||||
|
public boolean mIsSurfaceReady;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
setOnGenericMotionListener(SDLActivity.getMotionListener());
|
||||||
|
|
||||||
|
// Some arbitrary defaults to avoid a potential division by zero
|
||||||
|
mWidth = 1.0f;
|
||||||
|
mHeight = 1.0f;
|
||||||
|
|
||||||
|
mIsSurfaceReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handlePause() {
|
||||||
|
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void handleResume() {
|
||||||
|
setFocusable(true);
|
||||||
|
setFocusableInTouchMode(true);
|
||||||
|
requestFocus();
|
||||||
|
setOnKeyListener(this);
|
||||||
|
setOnTouchListener(this);
|
||||||
|
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Surface getNativeSurface() {
|
||||||
|
return getHolder().getSurface();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we have a valid drawing surface
|
||||||
|
@Override
|
||||||
|
public void surfaceCreated(SurfaceHolder holder) {
|
||||||
|
Log.v("SDL", "surfaceCreated()");
|
||||||
|
SDLActivity.onNativeSurfaceCreated();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called when we lose the surface
|
||||||
|
@Override
|
||||||
|
public void surfaceDestroyed(SurfaceHolder holder) {
|
||||||
|
Log.v("SDL", "surfaceDestroyed()");
|
||||||
|
|
||||||
|
// Transition to pause, if needed
|
||||||
|
SDLActivity.mNextNativeState = SDLActivity.NativeState.PAUSED;
|
||||||
|
SDLActivity.handleNativeState();
|
||||||
|
|
||||||
|
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()");
|
||||||
|
|
||||||
|
if (SDLActivity.mSingleton == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mWidth = width;
|
||||||
|
mHeight = height;
|
||||||
|
int nDeviceWidth = width;
|
||||||
|
int nDeviceHeight = height;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (Build.VERSION.SDK_INT >= 17) {
|
||||||
|
DisplayMetrics realMetrics = new DisplayMetrics();
|
||||||
|
mDisplay.getRealMetrics( realMetrics );
|
||||||
|
nDeviceWidth = realMetrics.widthPixels;
|
||||||
|
nDeviceHeight = realMetrics.heightPixels;
|
||||||
|
}
|
||||||
|
} catch(Exception ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
synchronized(SDLActivity.getContext()) {
|
||||||
|
// In case we're waiting on a size change after going fullscreen, send a notification.
|
||||||
|
SDLActivity.getContext().notifyAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.v("SDL", "Window size: " + width + "x" + height);
|
||||||
|
Log.v("SDL", "Device size: " + nDeviceWidth + "x" + nDeviceHeight);
|
||||||
|
SDLActivity.nativeSetScreenResolution(width, height, nDeviceWidth, nDeviceHeight, mDisplay.getRefreshRate());
|
||||||
|
SDLActivity.onNativeResize();
|
||||||
|
|
||||||
|
// Prevent a screen distortion glitch,
|
||||||
|
// for instance when the device is in Landscape and a Portrait App is resumed.
|
||||||
|
boolean skip = false;
|
||||||
|
int requestedOrientation = SDLActivity.mSingleton.getRequestedOrientation();
|
||||||
|
|
||||||
|
if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT) {
|
||||||
|
if (mWidth > mHeight) {
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
} else if (requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE || requestedOrientation == ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) {
|
||||||
|
if (mWidth < mHeight) {
|
||||||
|
skip = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Special Patch for Square Resolution: Black Berry Passport
|
||||||
|
if (skip) {
|
||||||
|
double min = Math.min(mWidth, mHeight);
|
||||||
|
double max = Math.max(mWidth, mHeight);
|
||||||
|
|
||||||
|
if (max / min < 1.20) {
|
||||||
|
Log.v("SDL", "Don't skip on such aspect-ratio. Could be a square resolution.");
|
||||||
|
skip = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't skip in MultiWindow.
|
||||||
|
if (skip) {
|
||||||
|
if (Build.VERSION.SDK_INT >= 24) {
|
||||||
|
if (SDLActivity.mSingleton.isInMultiWindowMode()) {
|
||||||
|
Log.v("SDL", "Don't skip in Multi-Window");
|
||||||
|
skip = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (skip) {
|
||||||
|
Log.v("SDL", "Skip .. Surface is not ready.");
|
||||||
|
mIsSurfaceReady = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If the surface has been previously destroyed by onNativeSurfaceDestroyed, recreate it here */
|
||||||
|
SDLActivity.onNativeSurfaceChanged();
|
||||||
|
|
||||||
|
/* Surface is ready */
|
||||||
|
mIsSurfaceReady = true;
|
||||||
|
|
||||||
|
SDLActivity.mNextNativeState = SDLActivity.NativeState.RESUMED;
|
||||||
|
SDLActivity.handleNativeState();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Key events
|
||||||
|
@Override
|
||||||
|
public boolean onKey(View v, int keyCode, KeyEvent event) {
|
||||||
|
return SDLActivity.handleKeyEvent(v, keyCode, event, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Touch events
|
||||||
|
@Override
|
||||||
|
public boolean onTouch(View v, MotionEvent event) {
|
||||||
|
/* Ref: http://developer.android.com/training/gestures/multi.html */
|
||||||
|
int touchDevId = event.getDeviceId();
|
||||||
|
final int pointerCount = event.getPointerCount();
|
||||||
|
int action = event.getActionMasked();
|
||||||
|
int pointerFingerId;
|
||||||
|
int i = -1;
|
||||||
|
float x,y,p;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prevent id to be -1, since it's used in SDL internal for synthetic events
|
||||||
|
* Appears when using Android emulator, eg:
|
||||||
|
* adb shell input mouse tap 100 100
|
||||||
|
* adb shell input touchscreen tap 100 100
|
||||||
|
*/
|
||||||
|
if (touchDevId < 0) {
|
||||||
|
touchDevId -= 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 12290 = Samsung DeX mode desktop mouse
|
||||||
|
// 12290 = 0x3002 = 0x2002 | 0x1002 = SOURCE_MOUSE | SOURCE_TOUCHSCREEN
|
||||||
|
// 0x2 = SOURCE_CLASS_POINTER
|
||||||
|
if (event.getSource() == InputDevice.SOURCE_MOUSE || event.getSource() == (InputDevice.SOURCE_MOUSE | InputDevice.SOURCE_TOUCHSCREEN)) {
|
||||||
|
int mouseButton = 1;
|
||||||
|
try {
|
||||||
|
Object object = event.getClass().getMethod("getButtonState").invoke(event);
|
||||||
|
if (object != null) {
|
||||||
|
mouseButton = (Integer) object;
|
||||||
|
}
|
||||||
|
} catch(Exception ignored) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// We need to check if we're in relative mouse mode and get the axis offset rather than the x/y values
|
||||||
|
// if we are. We'll leverage our existing mouse motion listener
|
||||||
|
SDLGenericMotionListener_API12 motionListener = SDLActivity.getMotionListener();
|
||||||
|
x = motionListener.getEventX(event);
|
||||||
|
y = motionListener.getEventY(event);
|
||||||
|
|
||||||
|
SDLActivity.onNativeMouse(mouseButton, action, x, y, motionListener.inRelativeMode());
|
||||||
|
} else {
|
||||||
|
switch(action) {
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
for (i = 0; i < pointerCount; i++) {
|
||||||
|
pointerFingerId = event.getPointerId(i);
|
||||||
|
x = event.getX(i) / mWidth;
|
||||||
|
y = event.getY(i) / mHeight;
|
||||||
|
p = event.getPressure(i);
|
||||||
|
if (p > 1.0f) {
|
||||||
|
// may be larger than 1.0f on some devices
|
||||||
|
// see the documentation of getPressure(i)
|
||||||
|
p = 1.0f;
|
||||||
|
}
|
||||||
|
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_UP:
|
||||||
|
case MotionEvent.ACTION_DOWN:
|
||||||
|
// Primary pointer up/down, the index is always zero
|
||||||
|
i = 0;
|
||||||
|
/* fallthrough */
|
||||||
|
case MotionEvent.ACTION_POINTER_UP:
|
||||||
|
case MotionEvent.ACTION_POINTER_DOWN:
|
||||||
|
// Non primary pointer up/down
|
||||||
|
if (i == -1) {
|
||||||
|
i = event.getActionIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
pointerFingerId = event.getPointerId(i);
|
||||||
|
x = event.getX(i) / mWidth;
|
||||||
|
y = event.getY(i) / mHeight;
|
||||||
|
p = event.getPressure(i);
|
||||||
|
if (p > 1.0f) {
|
||||||
|
// may be larger than 1.0f on some devices
|
||||||
|
// see the documentation of getPressure(i)
|
||||||
|
p = 1.0f;
|
||||||
|
}
|
||||||
|
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, action, x, y, p);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_CANCEL:
|
||||||
|
for (i = 0; i < pointerCount; i++) {
|
||||||
|
pointerFingerId = event.getPointerId(i);
|
||||||
|
x = event.getX(i) / mWidth;
|
||||||
|
y = event.getY(i) / mHeight;
|
||||||
|
p = event.getPressure(i);
|
||||||
|
if (p > 1.0f) {
|
||||||
|
// may be larger than 1.0f on some devices
|
||||||
|
// see the documentation of getPressure(i)
|
||||||
|
p = 1.0f;
|
||||||
|
}
|
||||||
|
SDLActivity.onNativeTouch(touchDevId, pointerFingerId, MotionEvent.ACTION_UP, x, y, p);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
// Since we may have an orientation set, we won't receive onConfigurationChanged events.
|
||||||
|
// We thus should check here.
|
||||||
|
int newOrientation;
|
||||||
|
|
||||||
|
float x, y;
|
||||||
|
switch (mDisplay.getRotation()) {
|
||||||
|
case Surface.ROTATION_90:
|
||||||
|
x = -event.values[1];
|
||||||
|
y = event.values[0];
|
||||||
|
newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE;
|
||||||
|
break;
|
||||||
|
case Surface.ROTATION_270:
|
||||||
|
x = event.values[1];
|
||||||
|
y = -event.values[0];
|
||||||
|
newOrientation = SDLActivity.SDL_ORIENTATION_LANDSCAPE_FLIPPED;
|
||||||
|
break;
|
||||||
|
case Surface.ROTATION_180:
|
||||||
|
x = -event.values[0];
|
||||||
|
y = -event.values[1];
|
||||||
|
newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT_FLIPPED;
|
||||||
|
break;
|
||||||
|
case Surface.ROTATION_0:
|
||||||
|
default:
|
||||||
|
x = event.values[0];
|
||||||
|
y = event.values[1];
|
||||||
|
newOrientation = SDLActivity.SDL_ORIENTATION_PORTRAIT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newOrientation != SDLActivity.mCurrentOrientation) {
|
||||||
|
SDLActivity.mCurrentOrientation = newOrientation;
|
||||||
|
SDLActivity.onNativeOrientationChanged(newOrientation);
|
||||||
|
}
|
||||||
|
|
||||||
|
SDLActivity.onNativeAccel(-x / SensorManager.GRAVITY_EARTH,
|
||||||
|
y / SensorManager.GRAVITY_EARTH,
|
||||||
|
event.values[2] / SensorManager.GRAVITY_EARTH);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Captured pointer events for API 26.
|
||||||
|
public boolean onCapturedPointerEvent(MotionEvent event)
|
||||||
|
{
|
||||||
|
int action = event.getActionMasked();
|
||||||
|
|
||||||
|
float x, y;
|
||||||
|
switch (action) {
|
||||||
|
case MotionEvent.ACTION_SCROLL:
|
||||||
|
x = event.getAxisValue(MotionEvent.AXIS_HSCROLL, 0);
|
||||||
|
y = event.getAxisValue(MotionEvent.AXIS_VSCROLL, 0);
|
||||||
|
SDLActivity.onNativeMouse(0, action, x, y, false);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_HOVER_MOVE:
|
||||||
|
case MotionEvent.ACTION_MOVE:
|
||||||
|
x = event.getX(0);
|
||||||
|
y = event.getY(0);
|
||||||
|
SDLActivity.onNativeMouse(0, action, x, y, true);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case MotionEvent.ACTION_BUTTON_PRESS:
|
||||||
|
case MotionEvent.ACTION_BUTTON_RELEASE:
|
||||||
|
|
||||||
|
// Change our action value to what SDL's code expects.
|
||||||
|
if (action == MotionEvent.ACTION_BUTTON_PRESS) {
|
||||||
|
action = MotionEvent.ACTION_DOWN;
|
||||||
|
} else { /* MotionEvent.ACTION_BUTTON_RELEASE */
|
||||||
|
action = MotionEvent.ACTION_UP;
|
||||||
|
}
|
||||||
|
|
||||||
|
x = event.getX(0);
|
||||||
|
y = event.getY(0);
|
||||||
|
int button = event.getButtonState();
|
||||||
|
|
||||||
|
SDLActivity.onNativeMouse(button, action, x, y, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
|
@ -14,7 +14,7 @@ include(FetchContent)
|
||||||
|
|
||||||
FetchContent_Declare(sdl2
|
FetchContent_Declare(sdl2
|
||||||
GIT_REPOSITORY "https://github.com/libsdl-org/SDL"
|
GIT_REPOSITORY "https://github.com/libsdl-org/SDL"
|
||||||
GIT_TAG "release-2.0.22"
|
GIT_TAG "release-2.26.1"
|
||||||
)
|
)
|
||||||
|
|
||||||
FetchContent_GetProperties(sdl2)
|
FetchContent_GetProperties(sdl2)
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
Copyright (C) 1997-2022 Sam Lantinga <slouken@libsdl.org>
|
||||||
|
|
||||||
|
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.
|
Loading…
Reference in New Issue