update SDL3 from 3.2.20 to 3.4.2
This commit is contained in:
@@ -71,6 +71,7 @@
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:allowBackup="true"
|
||||
android:theme="@style/AppTheme"
|
||||
android:enableOnBackInvokedCallback="false"
|
||||
android:hardwareAccelerated="true" >
|
||||
|
||||
<!-- Example of setting SDL hints from AndroidManifest.xml:
|
||||
|
||||
+21
-11
@@ -44,9 +44,9 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
|
||||
private static final int CHROMEBOOK_CONNECTION_CHECK_INTERVAL = 10000;
|
||||
|
||||
static public final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
|
||||
static public final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
|
||||
static public final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
|
||||
static final UUID steamControllerService = UUID.fromString("100F6C32-1735-4313-B402-38567131E5F3");
|
||||
static final UUID inputCharacteristic = UUID.fromString("100F6C33-1735-4313-B402-38567131E5F3");
|
||||
static final UUID reportCharacteristic = UUID.fromString("100F6C34-1735-4313-B402-38567131E5F3");
|
||||
static private final byte[] enterValveMode = new byte[] { (byte)0xC0, (byte)0x87, 0x03, 0x08, 0x07, 0x00 };
|
||||
|
||||
static class GattOperation {
|
||||
@@ -156,12 +156,12 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
}
|
||||
}
|
||||
|
||||
public HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
|
||||
HIDDeviceBLESteamController(HIDDeviceManager manager, BluetoothDevice device) {
|
||||
mManager = manager;
|
||||
mDevice = device;
|
||||
mDeviceId = mManager.getDeviceIDForIdentifier(getIdentifier());
|
||||
mIsRegistered = false;
|
||||
mIsChromebook = mManager.getContext().getPackageManager().hasSystemFeature("org.chromium.arc.device_management");
|
||||
mIsChromebook = SDLActivity.isChromebook();
|
||||
mOperations = new LinkedList<GattOperation>();
|
||||
mHandler = new Handler(Looper.getMainLooper());
|
||||
|
||||
@@ -169,17 +169,17 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
// final HIDDeviceBLESteamController finalThis = this;
|
||||
// mHandler.postDelayed(new Runnable() {
|
||||
// @Override
|
||||
// public void run() {
|
||||
// void run() {
|
||||
// finalThis.checkConnectionForChromebookIssue();
|
||||
// }
|
||||
// }, CHROMEBOOK_CONNECTION_CHECK_INTERVAL);
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
String getIdentifier() {
|
||||
return String.format("SteamController.%s", mDevice.getAddress());
|
||||
}
|
||||
|
||||
public BluetoothGatt getGatt() {
|
||||
BluetoothGatt getGatt() {
|
||||
return mGatt;
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
return btManager.getConnectionState(mDevice, BluetoothProfile.GATT);
|
||||
}
|
||||
|
||||
public void reconnect() {
|
||||
void reconnect() {
|
||||
|
||||
if (getConnectionState() != BluetoothProfile.STATE_CONNECTED) {
|
||||
mGatt.disconnect();
|
||||
@@ -401,12 +401,12 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
queueGattOperation(op);
|
||||
}
|
||||
|
||||
public void writeCharacteristic(UUID uuid, byte[] value) {
|
||||
void writeCharacteristic(UUID uuid, byte[] value) {
|
||||
GattOperation op = HIDDeviceBLESteamController.GattOperation.writeCharacteristic(mGatt, uuid, value);
|
||||
queueGattOperation(op);
|
||||
}
|
||||
|
||||
public void readCharacteristic(UUID uuid) {
|
||||
void readCharacteristic(UUID uuid) {
|
||||
GattOperation op = HIDDeviceBLESteamController.GattOperation.readCharacteristic(mGatt, uuid);
|
||||
queueGattOperation(op);
|
||||
}
|
||||
@@ -415,6 +415,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
////////////// BluetoothGattCallback overridden methods
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public void onConnectionStateChange(BluetoothGatt g, int status, int newState) {
|
||||
//Log.v(TAG, "onConnectionStateChange status=" + status + " newState=" + newState);
|
||||
mIsReconnecting = false;
|
||||
@@ -437,6 +438,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
// Disconnection is handled in SteamLink using the ACTION_ACL_DISCONNECTED Intent.
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onServicesDiscovered(BluetoothGatt gatt, int status) {
|
||||
//Log.v(TAG, "onServicesDiscovered status=" + status);
|
||||
if (status == 0) {
|
||||
@@ -453,6 +455,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||
//Log.v(TAG, "onCharacteristicRead status=" + status + " uuid=" + characteristic.getUuid());
|
||||
|
||||
@@ -463,6 +466,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
finishCurrentGattOperation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
|
||||
//Log.v(TAG, "onCharacteristicWrite status=" + status + " uuid=" + characteristic.getUuid());
|
||||
|
||||
@@ -478,6 +482,7 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
finishCurrentGattOperation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
|
||||
// Enable this for verbose logging of controller input reports
|
||||
//Log.v(TAG, "onCharacteristicChanged uuid=" + characteristic.getUuid() + " data=" + HexDump.dumpHexString(characteristic.getValue()));
|
||||
@@ -487,10 +492,12 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDescriptorRead(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
|
||||
//Log.v(TAG, "onDescriptorRead status=" + status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
|
||||
BluetoothGattCharacteristic chr = descriptor.getCharacteristic();
|
||||
//Log.v(TAG, "onDescriptorWrite status=" + status + " uuid=" + chr.getUuid() + " descriptor=" + descriptor.getUuid());
|
||||
@@ -508,14 +515,17 @@ class HIDDeviceBLESteamController extends BluetoothGattCallback implements HIDDe
|
||||
finishCurrentGattOperation();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReliableWriteCompleted(BluetoothGatt gatt, int status) {
|
||||
//Log.v(TAG, "onReliableWriteCompleted status=" + status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
|
||||
//Log.v(TAG, "onReadRemoteRssi status=" + status);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
|
||||
//Log.v(TAG, "onMtuChanged status=" + status);
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ public class HIDDeviceManager {
|
||||
private static HIDDeviceManager sManager;
|
||||
private static int sManagerRefCount = 0;
|
||||
|
||||
public static HIDDeviceManager acquire(Context context) {
|
||||
static public HIDDeviceManager acquire(Context context) {
|
||||
if (sManagerRefCount == 0) {
|
||||
sManager = new HIDDeviceManager(context);
|
||||
}
|
||||
@@ -40,7 +40,7 @@ public class HIDDeviceManager {
|
||||
return sManager;
|
||||
}
|
||||
|
||||
public static void release(HIDDeviceManager manager) {
|
||||
static public void release(HIDDeviceManager manager) {
|
||||
if (manager == sManager) {
|
||||
--sManagerRefCount;
|
||||
if (sManagerRefCount == 0) {
|
||||
@@ -108,12 +108,12 @@ public class HIDDeviceManager {
|
||||
HIDDeviceRegisterCallback();
|
||||
|
||||
mSharedPreferences = mContext.getSharedPreferences("hidapi", Context.MODE_PRIVATE);
|
||||
mIsChromebook = mContext.getPackageManager().hasSystemFeature("org.chromium.arc.device_management");
|
||||
mIsChromebook = SDLActivity.isChromebook();
|
||||
|
||||
// if (shouldClear) {
|
||||
// SharedPreferences.Editor spedit = mSharedPreferences.edit();
|
||||
// spedit.clear();
|
||||
// spedit.commit();
|
||||
// spedit.apply();
|
||||
// }
|
||||
// else
|
||||
{
|
||||
@@ -121,11 +121,11 @@ public class HIDDeviceManager {
|
||||
}
|
||||
}
|
||||
|
||||
public Context getContext() {
|
||||
Context getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public int getDeviceIDForIdentifier(String identifier) {
|
||||
int getDeviceIDForIdentifier(String identifier) {
|
||||
SharedPreferences.Editor spedit = mSharedPreferences.edit();
|
||||
|
||||
int result = mSharedPreferences.getInt(identifier, 0);
|
||||
@@ -135,7 +135,7 @@ public class HIDDeviceManager {
|
||||
}
|
||||
|
||||
spedit.putInt(identifier, result);
|
||||
spedit.commit();
|
||||
spedit.apply();
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ public class HIDDeviceManager {
|
||||
filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
|
||||
filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
|
||||
filter.addAction(HIDDeviceManager.ACTION_USB_PERMISSION);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (Build.VERSION.SDK_INT >= 33) { /* Android 13.0 (TIRAMISU) */
|
||||
mContext.registerReceiver(mUsbBroadcast, filter, Context.RECEIVER_EXPORTED);
|
||||
} else {
|
||||
mContext.registerReceiver(mUsbBroadcast, filter);
|
||||
@@ -288,9 +288,13 @@ public class HIDDeviceManager {
|
||||
0x1532, // Razer Wildcat
|
||||
0x20d6, // PowerA
|
||||
0x24c6, // PowerA
|
||||
0x294b, // Snakebyte
|
||||
0x2dc8, // 8BitDo
|
||||
0x2e24, // Hyperkin
|
||||
0x2e95, // SCUF
|
||||
0x3285, // Nacon
|
||||
0x3537, // GameSir
|
||||
0x366c, // ByoWave
|
||||
};
|
||||
|
||||
if (usbInterface.getId() == 0 &&
|
||||
@@ -376,7 +380,7 @@ public class HIDDeviceManager {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE) || (Build.VERSION.SDK_INT < 18 /* Android 4.3 (JELLY_BEAN_MR2) */)) {
|
||||
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
|
||||
Log.d(TAG, "Couldn't initialize Bluetooth, this version of Android does not support Bluetooth LE");
|
||||
return;
|
||||
}
|
||||
@@ -408,7 +412,7 @@ public class HIDDeviceManager {
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(BluetoothDevice.ACTION_ACL_CONNECTED);
|
||||
filter.addAction(BluetoothDevice.ACTION_ACL_DISCONNECTED);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||
if (Build.VERSION.SDK_INT >= 33) { /* Android 13.0 (TIRAMISU) */
|
||||
mContext.registerReceiver(mBluetoothBroadcast, filter, Context.RECEIVER_EXPORTED);
|
||||
} else {
|
||||
mContext.registerReceiver(mBluetoothBroadcast, filter);
|
||||
@@ -439,7 +443,7 @@ public class HIDDeviceManager {
|
||||
// Chromebooks do not pass along ACTION_ACL_CONNECTED / ACTION_ACL_DISCONNECTED properly.
|
||||
// This function provides a sort of dummy version of that, watching for changes in the
|
||||
// connected devices and attempting to add controllers as things change.
|
||||
public void chromebookConnectionHandler() {
|
||||
void chromebookConnectionHandler() {
|
||||
if (!mIsChromebook) {
|
||||
return;
|
||||
}
|
||||
@@ -478,7 +482,7 @@ public class HIDDeviceManager {
|
||||
}, 10000);
|
||||
}
|
||||
|
||||
public boolean connectBluetoothDevice(BluetoothDevice bluetoothDevice) {
|
||||
boolean connectBluetoothDevice(BluetoothDevice bluetoothDevice) {
|
||||
Log.v(TAG, "connectBluetoothDevice device=" + bluetoothDevice);
|
||||
synchronized (this) {
|
||||
if (mBluetoothDevices.containsKey(bluetoothDevice)) {
|
||||
@@ -499,7 +503,7 @@ public class HIDDeviceManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void disconnectBluetoothDevice(BluetoothDevice bluetoothDevice) {
|
||||
void disconnectBluetoothDevice(BluetoothDevice bluetoothDevice) {
|
||||
synchronized (this) {
|
||||
HIDDeviceBLESteamController device = mBluetoothDevices.get(bluetoothDevice);
|
||||
if (device == null)
|
||||
@@ -513,7 +517,7 @@ public class HIDDeviceManager {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSteamController(BluetoothDevice bluetoothDevice) {
|
||||
boolean isSteamController(BluetoothDevice bluetoothDevice) {
|
||||
// Sanity check. If you pass in a null device, by definition it is never a Steam Controller.
|
||||
if (bluetoothDevice == null) {
|
||||
return false;
|
||||
@@ -567,7 +571,7 @@ public class HIDDeviceManager {
|
||||
////////// JNI interface functions
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
public boolean initialize(boolean usb, boolean bluetooth) {
|
||||
boolean initialize(boolean usb, boolean bluetooth) {
|
||||
Log.v(TAG, "initialize(" + usb + ", " + bluetooth + ")");
|
||||
|
||||
if (usb) {
|
||||
@@ -579,7 +583,7 @@ public class HIDDeviceManager {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean openDevice(int deviceID) {
|
||||
boolean openDevice(int deviceID) {
|
||||
Log.v(TAG, "openDevice deviceID=" + deviceID);
|
||||
HIDDevice device = getDevice(deviceID);
|
||||
if (device == null) {
|
||||
@@ -599,13 +603,10 @@ public class HIDDeviceManager {
|
||||
} else {
|
||||
flags = 0;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 33 /* Android 14.0 (U) */) {
|
||||
Intent intent = new Intent(HIDDeviceManager.ACTION_USB_PERMISSION);
|
||||
intent.setPackage(mContext.getPackageName());
|
||||
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, intent, flags));
|
||||
} else {
|
||||
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, new Intent(HIDDeviceManager.ACTION_USB_PERMISSION), flags));
|
||||
}
|
||||
|
||||
Intent intent = new Intent(HIDDeviceManager.ACTION_USB_PERMISSION);
|
||||
intent.setPackage(mContext.getPackageName());
|
||||
mUsbManager.requestPermission(usbDevice, PendingIntent.getBroadcast(mContext, 0, intent, flags));
|
||||
} catch (Exception e) {
|
||||
Log.v(TAG, "Couldn't request permission for USB device " + usbDevice);
|
||||
HIDDeviceOpenResult(deviceID, false);
|
||||
@@ -621,7 +622,7 @@ public class HIDDeviceManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
public int writeReport(int deviceID, byte[] report, boolean feature) {
|
||||
int writeReport(int deviceID, byte[] report, boolean feature) {
|
||||
try {
|
||||
//Log.v(TAG, "writeReport deviceID=" + deviceID + " length=" + report.length);
|
||||
HIDDevice device;
|
||||
@@ -638,7 +639,7 @@ public class HIDDeviceManager {
|
||||
return -1;
|
||||
}
|
||||
|
||||
public boolean readReport(int deviceID, byte[] report, boolean feature) {
|
||||
boolean readReport(int deviceID, byte[] report, boolean feature) {
|
||||
try {
|
||||
//Log.v(TAG, "readReport deviceID=" + deviceID);
|
||||
HIDDevice device;
|
||||
@@ -655,7 +656,7 @@ public class HIDDeviceManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void closeDevice(int deviceID) {
|
||||
void closeDevice(int deviceID) {
|
||||
try {
|
||||
Log.v(TAG, "closeDevice deviceID=" + deviceID);
|
||||
HIDDevice device;
|
||||
|
||||
@@ -4,6 +4,7 @@ import android.hardware.usb.*;
|
||||
import android.os.Build;
|
||||
import android.util.Log;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
class HIDDeviceUSB implements HIDDevice {
|
||||
|
||||
@@ -30,8 +31,8 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
mRunning = false;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return String.format("%s/%x/%x/%d", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId(), mInterfaceIndex);
|
||||
String getIdentifier() {
|
||||
return String.format(Locale.ENGLISH, "%s/%x/%x/%d", mDevice.getDeviceName(), mDevice.getVendorId(), mDevice.getProductId(), mInterfaceIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,13 +53,11 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
@Override
|
||||
public String getSerialNumber() {
|
||||
String result = null;
|
||||
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
try {
|
||||
result = mDevice.getSerialNumber();
|
||||
}
|
||||
catch (SecurityException exception) {
|
||||
//Log.w(TAG, "App permissions mean we cannot get serial number for device " + getDeviceName() + " message: " + exception.getMessage());
|
||||
}
|
||||
try {
|
||||
result = mDevice.getSerialNumber();
|
||||
}
|
||||
catch (SecurityException exception) {
|
||||
//Log.w(TAG, "App permissions mean we cannot get serial number for device " + getDeviceName() + " message: " + exception.getMessage());
|
||||
}
|
||||
if (result == null) {
|
||||
result = "";
|
||||
@@ -73,10 +72,8 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
|
||||
@Override
|
||||
public String getManufacturerName() {
|
||||
String result = null;
|
||||
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
result = mDevice.getManufacturerName();
|
||||
}
|
||||
String result;
|
||||
result = mDevice.getManufacturerName();
|
||||
if (result == null) {
|
||||
result = String.format("%x", getVendorId());
|
||||
}
|
||||
@@ -85,10 +82,8 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
|
||||
@Override
|
||||
public String getProductName() {
|
||||
String result = null;
|
||||
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
result = mDevice.getProductName();
|
||||
}
|
||||
String result;
|
||||
result = mDevice.getProductName();
|
||||
if (result == null) {
|
||||
result = String.format("%x", getProductId());
|
||||
}
|
||||
@@ -100,7 +95,7 @@ class HIDDeviceUSB implements HIDDevice {
|
||||
return mDevice;
|
||||
}
|
||||
|
||||
public String getDeviceName() {
|
||||
String getDeviceName() {
|
||||
return getManufacturerName() + " " + getProductName() + "(0x" + String.format("%x", getVendorId()) + "/0x" + String.format("%x", getProductId()) + ")";
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
package org.libsdl.app;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Context;
|
||||
|
||||
import java.lang.Class;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
@@ -12,14 +12,14 @@ public class SDL {
|
||||
|
||||
// This function should be called first and sets up the native code
|
||||
// so it can call into the Java classes
|
||||
public static void setupJNI() {
|
||||
static public void setupJNI() {
|
||||
SDLActivity.nativeSetupJNI();
|
||||
SDLAudioManager.nativeSetupJNI();
|
||||
SDLControllerManager.nativeSetupJNI();
|
||||
}
|
||||
|
||||
// This function should be called each time the activity is started
|
||||
public static void initialize() {
|
||||
static public void initialize() {
|
||||
setContext(null);
|
||||
|
||||
SDLActivity.initialize();
|
||||
@@ -28,20 +28,20 @@ public class SDL {
|
||||
}
|
||||
|
||||
// This function stores the current activity (SDL or not)
|
||||
public static void setContext(Context context) {
|
||||
static public void setContext(Activity context) {
|
||||
SDLAudioManager.setContext(context);
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public static Context getContext() {
|
||||
static public Activity getContext() {
|
||||
return mContext;
|
||||
}
|
||||
|
||||
public static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
|
||||
static void loadLibrary(String libraryName) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
|
||||
loadLibrary(libraryName, mContext);
|
||||
}
|
||||
|
||||
public static void loadLibrary(String libraryName, Context context) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
|
||||
static void loadLibrary(String libraryName, Context context) throws UnsatisfiedLinkError, SecurityException, NullPointerException {
|
||||
|
||||
if (libraryName == null) {
|
||||
throw new NullPointerException("No library name provided.");
|
||||
@@ -86,5 +86,5 @@ public class SDL {
|
||||
}
|
||||
}
|
||||
|
||||
protected static Context mContext;
|
||||
protected static Activity mContext;
|
||||
}
|
||||
|
||||
@@ -60,8 +60,8 @@ import java.util.Locale;
|
||||
public class SDLActivity extends Activity implements View.OnSystemUiVisibilityChangeListener {
|
||||
private static final String TAG = "SDL";
|
||||
private static final int SDL_MAJOR_VERSION = 3;
|
||||
private static final int SDL_MINOR_VERSION = 2;
|
||||
private static final int SDL_MICRO_VERSION = 20;
|
||||
private static final int SDL_MINOR_VERSION = 4;
|
||||
private static final int SDL_MICRO_VERSION = 2;
|
||||
/*
|
||||
// Display InputType.SOURCE/CLASS of events and devices
|
||||
//
|
||||
@@ -107,11 +107,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
if ((s & tst) == tst) src += " GAMEPAD";
|
||||
s2 &= ~tst;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
tst = InputDevice.SOURCE_HDMI;
|
||||
if ((s & tst) == tst) src += " HDMI";
|
||||
s2 &= ~tst;
|
||||
}
|
||||
tst = InputDevice.SOURCE_HDMI;
|
||||
if ((s & tst) == tst) src += " HDMI";
|
||||
s2 &= ~tst;
|
||||
|
||||
tst = InputDevice.SOURCE_JOYSTICK;
|
||||
if ((s & tst) == tst) src += " JOYSTICK";
|
||||
@@ -146,11 +144,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
if ((s & tst) == tst) src += " TOUCHSCREEN";
|
||||
s2 &= ~tst;
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 18) {
|
||||
tst = InputDevice.SOURCE_TOUCH_NAVIGATION;
|
||||
if ((s & tst) == tst) src += " TOUCH_NAVIGATION";
|
||||
s2 &= ~tst;
|
||||
}
|
||||
tst = InputDevice.SOURCE_TOUCH_NAVIGATION;
|
||||
if ((s & tst) == tst) src += " TOUCH_NAVIGATION";
|
||||
s2 &= ~tst;
|
||||
|
||||
tst = InputDevice.SOURCE_TRACKBALL;
|
||||
if ((s & tst) == tst) src += " TRACKBALL";
|
||||
@@ -219,7 +215,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
protected static SDLActivity mSingleton;
|
||||
protected static SDLSurface mSurface;
|
||||
protected static SDLDummyEdit mTextEdit;
|
||||
protected static boolean mScreenKeyboardShown;
|
||||
protected static ViewGroup mLayout;
|
||||
protected static SDLClipboardHandler mClipboardHandler;
|
||||
protected static Hashtable<Integer, PointerIcon> mCursors;
|
||||
@@ -234,9 +229,11 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
private static SDLFileDialogState mFileDialogState = null;
|
||||
protected static boolean mDispatchingKeyEvent = false;
|
||||
|
||||
protected static SDLGenericMotionListener_API14 getMotionListener() {
|
||||
public static SDLGenericMotionListener_API14 getMotionListener() {
|
||||
if (mMotionListener == null) {
|
||||
if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
|
||||
if (Build.VERSION.SDK_INT >= 29 /* Android 10 (Q) */) {
|
||||
mMotionListener = new SDLGenericMotionListener_API29();
|
||||
} else if (Build.VERSION.SDK_INT >= 26 /* Android 8.0 (O) */) {
|
||||
mMotionListener = new SDLGenericMotionListener_API26();
|
||||
} else if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
mMotionListener = new SDLGenericMotionListener_API24();
|
||||
@@ -898,7 +895,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
protected static class SDLCommandHandler extends Handler {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
Context context = SDL.getContext();
|
||||
Context context = getContext();
|
||||
if (context == null) {
|
||||
Log.e(TAG, "error handling message, getContext() returned null");
|
||||
return;
|
||||
@@ -912,39 +909,37 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
}
|
||||
break;
|
||||
case COMMAND_CHANGE_WINDOW_STYLE:
|
||||
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
|
||||
if (context instanceof Activity) {
|
||||
Window window = ((Activity) context).getWindow();
|
||||
if (window != null) {
|
||||
if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) {
|
||||
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
|
||||
window.getDecorView().setSystemUiVisibility(flags);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
SDLActivity.mFullscreenModeActive = true;
|
||||
} else {
|
||||
int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE;
|
||||
window.getDecorView().setSystemUiVisibility(flags);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
SDLActivity.mFullscreenModeActive = false;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 28 /* Android 9 (Pie) */) {
|
||||
window.getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 30 /* Android 11 (R) */ &&
|
||||
Build.VERSION.SDK_INT < 35 /* Android 15 */) {
|
||||
SDLActivity.onNativeInsetsChanged(0, 0, 0, 0);
|
||||
}
|
||||
if (context instanceof Activity) {
|
||||
Window window = ((Activity) context).getWindow();
|
||||
if (window != null) {
|
||||
if ((msg.obj instanceof Integer) && ((Integer) msg.obj != 0)) {
|
||||
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
|
||||
window.getDecorView().setSystemUiVisibility(flags);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
SDLActivity.mFullscreenModeActive = true;
|
||||
} else {
|
||||
int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_VISIBLE;
|
||||
window.getDecorView().setSystemUiVisibility(flags);
|
||||
window.addFlags(WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
|
||||
window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
|
||||
SDLActivity.mFullscreenModeActive = false;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 30 /* Android 11 (R) */) {
|
||||
window.getAttributes().layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_ALWAYS;
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 30 /* Android 11 (R) */ &&
|
||||
Build.VERSION.SDK_INT < 35 /* Android 15 */) {
|
||||
SDLActivity.onNativeInsetsChanged(0, 0, 0, 0);
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "error handling message, getContext() returned no Activity");
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "error handling message, getContext() returned no Activity");
|
||||
}
|
||||
break;
|
||||
case COMMAND_TEXTEDIT_HIDE:
|
||||
@@ -957,7 +952,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
InputMethodManager imm = (InputMethodManager) context.getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0);
|
||||
|
||||
mScreenKeyboardShown = false;
|
||||
onNativeScreenKeyboardHidden();
|
||||
|
||||
mSurface.requestFocus();
|
||||
}
|
||||
@@ -994,53 +989,51 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
msg.obj = data;
|
||||
boolean result = commandHandler.sendMessage(msg);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
|
||||
if (command == COMMAND_CHANGE_WINDOW_STYLE) {
|
||||
// Ensure we don't return until the resize has actually happened,
|
||||
// or 500ms have passed.
|
||||
if (command == COMMAND_CHANGE_WINDOW_STYLE) {
|
||||
// Ensure we don't return until the resize has actually happened,
|
||||
// or 500ms have passed.
|
||||
|
||||
boolean bShouldWait = false;
|
||||
boolean bShouldWait = false;
|
||||
|
||||
if (data instanceof Integer) {
|
||||
// Let's figure out if we're already laid out fullscreen or not.
|
||||
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
DisplayMetrics realMetrics = new DisplayMetrics();
|
||||
display.getRealMetrics(realMetrics);
|
||||
if (data instanceof Integer) {
|
||||
// Let's figure out if we're already laid out fullscreen or not.
|
||||
Display display = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay();
|
||||
DisplayMetrics realMetrics = new DisplayMetrics();
|
||||
display.getRealMetrics(realMetrics);
|
||||
|
||||
boolean bFullscreenLayout = ((realMetrics.widthPixels == mSurface.getWidth()) &&
|
||||
(realMetrics.heightPixels == mSurface.getHeight()));
|
||||
boolean bFullscreenLayout = ((realMetrics.widthPixels == mSurface.getWidth()) &&
|
||||
(realMetrics.heightPixels == mSurface.getHeight()));
|
||||
|
||||
if ((Integer) data == 1) {
|
||||
// If we aren't laid out fullscreen or actively in fullscreen mode already, we're going
|
||||
// to change size and should wait for surfaceChanged() before we return, so the size
|
||||
// is right back in native code. If we're already laid out fullscreen, though, we're
|
||||
// not going to change size even if we change decor modes, so we shouldn't wait for
|
||||
// surfaceChanged() -- which may not even happen -- and should return immediately.
|
||||
bShouldWait = !bFullscreenLayout;
|
||||
} else {
|
||||
// If we're laid out fullscreen (even if the status bar and nav bar are present),
|
||||
// or are actively in fullscreen, we're going to change size and should wait for
|
||||
// surfaceChanged before we return, so the size is right back in native code.
|
||||
bShouldWait = bFullscreenLayout;
|
||||
}
|
||||
if ((Integer) data == 1) {
|
||||
// If we aren't laid out fullscreen or actively in fullscreen mode already, we're going
|
||||
// to change size and should wait for surfaceChanged() before we return, so the size
|
||||
// is right back in native code. If we're already laid out fullscreen, though, we're
|
||||
// not going to change size even if we change decor modes, so we shouldn't wait for
|
||||
// surfaceChanged() -- which may not even happen -- and should return immediately.
|
||||
bShouldWait = !bFullscreenLayout;
|
||||
} else {
|
||||
// If we're laid out fullscreen (even if the status bar and nav bar are present),
|
||||
// or are actively in fullscreen, we're going to change size and should wait for
|
||||
// surfaceChanged before we return, so the size is right back in native code.
|
||||
bShouldWait = bFullscreenLayout;
|
||||
}
|
||||
}
|
||||
|
||||
if (bShouldWait && (SDLActivity.getContext() != null)) {
|
||||
// We'll wait for the surfaceChanged() method, which will notify us
|
||||
// when called. That way, we know our current size is really the
|
||||
// size we need, instead of grabbing a size that's still got
|
||||
// the navigation and/or status bars before they're hidden.
|
||||
//
|
||||
// We'll wait for up to half a second, because some devices
|
||||
// take a surprisingly long time for the surface resize, but
|
||||
// then we'll just give up and return.
|
||||
//
|
||||
synchronized (SDLActivity.getContext()) {
|
||||
try {
|
||||
SDLActivity.getContext().wait(500);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
if (bShouldWait && (getContext() != null)) {
|
||||
// We'll wait for the surfaceChanged() method, which will notify us
|
||||
// when called. That way, we know our current size is really the
|
||||
// size we need, instead of grabbing a size that's still got
|
||||
// the navigation and/or status bars before they're hidden.
|
||||
//
|
||||
// We'll wait for up to half a second, because some devices
|
||||
// take a surprisingly long time for the surface resize, but
|
||||
// then we'll just give up and return.
|
||||
//
|
||||
synchronized (getContext()) {
|
||||
try {
|
||||
getContext().wait(500);
|
||||
} catch (InterruptedException ie) {
|
||||
ie.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1051,7 +1044,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
|
||||
// C functions we call
|
||||
public static native String nativeGetVersion();
|
||||
public static native int nativeSetupJNI();
|
||||
public static native void nativeSetupJNI();
|
||||
public static native void nativeInitMainThread();
|
||||
public static native void nativeCleanupMainThread();
|
||||
public static native int nativeRunMain(String library, String function, Object arguments);
|
||||
@@ -1072,12 +1065,14 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
public static native void onNativeTouch(int touchDevId, int pointerFingerId,
|
||||
int action, float x,
|
||||
float y, float p);
|
||||
public static native void onNativePen(int penId, int button, int action, float x, float y, float p);
|
||||
public static native void onNativePen(int penId, int device_type, int button, int action, float x, float y, float p);
|
||||
public static native void onNativeAccel(float x, float y, float z);
|
||||
public static native void onNativeClipboardChanged();
|
||||
public static native void onNativeSurfaceCreated();
|
||||
public static native void onNativeSurfaceChanged();
|
||||
public static native void onNativeSurfaceDestroyed();
|
||||
public static native void onNativeScreenKeyboardShown();
|
||||
public static native void onNativeScreenKeyboardHidden();
|
||||
public static native String nativeGetHint(String name);
|
||||
public static native boolean nativeGetHintBoolean(String name, boolean default_value);
|
||||
public static native void nativeSetenv(String name, String value);
|
||||
@@ -1091,6 +1086,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
public static native boolean nativeAllowRecreateActivity();
|
||||
public static native int nativeCheckSDLThreadCounter();
|
||||
public static native void onNativeFileDialog(int requestCode, String[] filelist, int filter);
|
||||
public static native void onNativePinchStart();
|
||||
public static native void onNativePinchUpdate(float scale);
|
||||
public static native void onNativePinchEnd();
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
@@ -1128,6 +1126,11 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
int orientation_landscape = -1;
|
||||
int orientation_portrait = -1;
|
||||
|
||||
if (w <= 1 || h <= 1) {
|
||||
// Invalid width/height, ignore this request
|
||||
return;
|
||||
}
|
||||
|
||||
/* If set, hint "explicitly controls which UI orientations are allowed". */
|
||||
if (hint.contains("LandscapeRight") && hint.contains("LandscapeLeft")) {
|
||||
orientation_landscape = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE;
|
||||
@@ -1208,24 +1211,6 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static boolean isScreenKeyboardShown()
|
||||
{
|
||||
if (mTextEdit == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!mScreenKeyboardShown) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
return imm.isAcceptingText();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
@@ -1270,7 +1255,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static Context getContext() {
|
||||
public static Activity getContext() {
|
||||
return SDL.getContext();
|
||||
}
|
||||
|
||||
@@ -1285,10 +1270,10 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
if (Build.MANUFACTURER.equals("MINIX") && Build.MODEL.equals("NEO-U1")) {
|
||||
return true;
|
||||
}
|
||||
if (Build.MANUFACTURER.equals("Amlogic") && Build.MODEL.equals("X96-W")) {
|
||||
return true;
|
||||
}
|
||||
if (Build.MANUFACTURER.equals("Amlogic") && Build.MODEL.startsWith("TV")) {
|
||||
if (Build.MANUFACTURER.equals("Amlogic") &&
|
||||
(Build.MODEL.startsWith("TV") ||
|
||||
Build.MODEL.equals("X96-W") ||
|
||||
Build.MODEL.equals("A95X-R1"))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -1331,10 +1316,17 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static boolean isChromebook() {
|
||||
if (getContext() == null) {
|
||||
return false;
|
||||
// https://stackoverflow.com/questions/39784415/how-to-detect-programmatically-if-android-app-is-running-in-chrome-book-or-in
|
||||
if (getContext() != null) {
|
||||
if (getContext().getPackageManager().hasSystemFeature("org.chromium.arc")
|
||||
|| getContext().getPackageManager().hasSystemFeature("org.chromium.arc.device_management")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return getContext().getPackageManager().hasSystemFeature("org.chromium.arc.device_management");
|
||||
|
||||
// Running on AVD emulator
|
||||
boolean isChromebookEmulator = (Build.MODEL != null && Build.MODEL.startsWith("sdk_gpc_"));
|
||||
return isChromebookEmulator;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1424,7 +1416,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
params.topMargin = y;
|
||||
|
||||
if (mTextEdit == null) {
|
||||
mTextEdit = new SDLDummyEdit(SDL.getContext());
|
||||
mTextEdit = new SDLDummyEdit(getContext());
|
||||
|
||||
mLayout.addView(mTextEdit, params);
|
||||
} else {
|
||||
@@ -1435,10 +1427,12 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
mTextEdit.setVisibility(View.VISIBLE);
|
||||
mTextEdit.requestFocus();
|
||||
|
||||
InputMethodManager imm = (InputMethodManager) SDL.getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showSoftInput(mTextEdit, 0);
|
||||
|
||||
mScreenKeyboardShown = true;
|
||||
if (imm.isAcceptingText()) {
|
||||
onNativeScreenKeyboardShown();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1767,16 +1761,14 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
private final Runnable rehideSystemUi = new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
|
||||
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
|
||||
int flags = View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.INVISIBLE;
|
||||
|
||||
SDLActivity.this.getWindow().getDecorView().setSystemUiVisibility(flags);
|
||||
}
|
||||
SDLActivity.this.getWindow().getDecorView().setSystemUiVisibility(flags);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1931,7 +1923,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
try {
|
||||
mSurface.setPointerIcon(PointerIcon.getSystemIcon(SDL.getContext(), cursor_type));
|
||||
mSurface.setPointerIcon(PointerIcon.getSystemIcon(getContext(), cursor_type));
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
@@ -1971,12 +1963,9 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
Intent i = new Intent(Intent.ACTION_VIEW);
|
||||
i.setData(Uri.parse(url));
|
||||
|
||||
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY | Intent.FLAG_ACTIVITY_MULTIPLE_TASK;
|
||||
if (Build.VERSION.SDK_INT >= 21 /* Android 5.0 (LOLLIPOP) */) {
|
||||
flags |= Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
|
||||
} else {
|
||||
flags |= Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET;
|
||||
}
|
||||
int flags = Intent.FLAG_ACTIVITY_NO_HISTORY
|
||||
| Intent.FLAG_ACTIVITY_MULTIPLE_TASK
|
||||
| Intent.FLAG_ACTIVITY_NEW_DOCUMENT;
|
||||
i.addFlags(flags);
|
||||
|
||||
mSingleton.startActivity(i);
|
||||
@@ -2117,7 +2106,7 @@ public class SDLActivity extends Activity implements View.OnSystemUiVisibilityCh
|
||||
int requestCode;
|
||||
boolean multipleChoice;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
@@ -2196,7 +2185,11 @@ class SDLClipboardHandler implements
|
||||
}
|
||||
|
||||
public boolean clipboardHasText() {
|
||||
return mClipMgr.hasPrimaryClip();
|
||||
if (Build.VERSION.SDK_INT >= 28 /* Android 9 (P) */) {
|
||||
return mClipMgr.hasPrimaryClip();
|
||||
} else {
|
||||
return mClipMgr.hasText();
|
||||
}
|
||||
}
|
||||
|
||||
public String clipboardGetText() {
|
||||
@@ -2214,10 +2207,19 @@ class SDLClipboardHandler implements
|
||||
}
|
||||
|
||||
public void clipboardSetText(String string) {
|
||||
mClipMgr.removePrimaryClipChangedListener(this);
|
||||
ClipData clip = ClipData.newPlainText(null, string);
|
||||
mClipMgr.setPrimaryClip(clip);
|
||||
mClipMgr.addPrimaryClipChangedListener(this);
|
||||
mClipMgr.removePrimaryClipChangedListener(this);
|
||||
if (string.isEmpty()) {
|
||||
if (Build.VERSION.SDK_INT >= 28 /* Android 9 (P) */) {
|
||||
mClipMgr.clearPrimaryClip();
|
||||
} else {
|
||||
ClipData clip = ClipData.newPlainText(null, "");
|
||||
mClipMgr.setPrimaryClip(clip);
|
||||
}
|
||||
} else {
|
||||
ClipData clip = ClipData.newPlainText(null, string);
|
||||
mClipMgr.setPrimaryClip(clip);
|
||||
}
|
||||
mClipMgr.addPrimaryClipChangedListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,14 +10,14 @@ import android.util.Log;
|
||||
import java.util.Arrays;
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class SDLAudioManager {
|
||||
class SDLAudioManager {
|
||||
protected static final String TAG = "SDLAudio";
|
||||
|
||||
protected static Context mContext;
|
||||
|
||||
private static AudioDeviceCallback mAudioDeviceCallback;
|
||||
|
||||
public static void initialize() {
|
||||
static void initialize() {
|
||||
mAudioDeviceCallback = null;
|
||||
|
||||
if(Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */)
|
||||
@@ -26,25 +26,25 @@ public class SDLAudioManager {
|
||||
@Override
|
||||
public void onAudioDevicesAdded(AudioDeviceInfo[] addedDevices) {
|
||||
for (AudioDeviceInfo deviceInfo : addedDevices) {
|
||||
addAudioDevice(deviceInfo.isSink(), deviceInfo.getProductName().toString(), deviceInfo.getId());
|
||||
nativeAddAudioDevice(deviceInfo.isSink(), deviceInfo.getProductName().toString(), deviceInfo.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAudioDevicesRemoved(AudioDeviceInfo[] removedDevices) {
|
||||
for (AudioDeviceInfo deviceInfo : removedDevices) {
|
||||
removeAudioDevice(deviceInfo.isSink(), deviceInfo.getId());
|
||||
nativeRemoveAudioDevice(deviceInfo.isSink(), deviceInfo.getId());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public static void setContext(Context context) {
|
||||
static void setContext(Context context) {
|
||||
mContext = context;
|
||||
}
|
||||
|
||||
public static void release(Context context) {
|
||||
static void release(Context context) {
|
||||
// no-op atm
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ public class SDLAudioManager {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void registerAudioDeviceCallback() {
|
||||
static void registerAudioDeviceCallback() {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
// get an initial list now, before hotplug callbacks fire.
|
||||
@@ -82,16 +82,16 @@ public class SDLAudioManager {
|
||||
if (dev.getType() == AudioDeviceInfo.TYPE_TELEPHONY) {
|
||||
continue; // Device cannot be opened
|
||||
}
|
||||
addAudioDevice(dev.isSink(), dev.getProductName().toString(), dev.getId());
|
||||
nativeAddAudioDevice(dev.isSink(), dev.getProductName().toString(), dev.getId());
|
||||
}
|
||||
for (AudioDeviceInfo dev : audioManager.getDevices(AudioManager.GET_DEVICES_INPUTS)) {
|
||||
addAudioDevice(dev.isSink(), dev.getProductName().toString(), dev.getId());
|
||||
nativeAddAudioDevice(dev.isSink(), dev.getProductName().toString(), dev.getId());
|
||||
}
|
||||
audioManager.registerAudioDeviceCallback(mAudioDeviceCallback, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static void unregisterAudioDeviceCallback() {
|
||||
static void unregisterAudioDeviceCallback() {
|
||||
if (Build.VERSION.SDK_INT >= 24 /* Android 7.0 (N) */) {
|
||||
AudioManager audioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
|
||||
audioManager.unregisterAudioDeviceCallback(mAudioDeviceCallback);
|
||||
@@ -99,7 +99,7 @@ public class SDLAudioManager {
|
||||
}
|
||||
|
||||
/** This method is called by SDL using JNI. */
|
||||
public static void audioSetThreadPriority(boolean recording, int device_id) {
|
||||
static void audioSetThreadPriority(boolean recording, int device_id) {
|
||||
try {
|
||||
|
||||
/* Set thread name */
|
||||
@@ -117,10 +117,10 @@ public class SDLAudioManager {
|
||||
}
|
||||
}
|
||||
|
||||
public static native int nativeSetupJNI();
|
||||
static native void nativeSetupJNI();
|
||||
|
||||
public static native void removeAudioDevice(boolean recording, int deviceId);
|
||||
static native void nativeRemoveAudioDevice(boolean recording, int deviceId);
|
||||
|
||||
public static native void addAudioDevice(boolean recording, String name, int deviceId);
|
||||
static native void nativeAddAudioDevice(boolean recording, String name, int deviceId);
|
||||
|
||||
}
|
||||
|
||||
+198
-112
@@ -6,6 +6,11 @@ import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.hardware.lights.Light;
|
||||
import android.hardware.lights.LightsRequest;
|
||||
import android.hardware.lights.LightsManager;
|
||||
import android.hardware.lights.LightState;
|
||||
import android.graphics.Color;
|
||||
import android.os.Build;
|
||||
import android.os.VibrationEffect;
|
||||
import android.os.Vibrator;
|
||||
@@ -20,20 +25,20 @@ import android.view.View;
|
||||
public class SDLControllerManager
|
||||
{
|
||||
|
||||
public static native int nativeSetupJNI();
|
||||
static native void nativeSetupJNI();
|
||||
|
||||
public static native void nativeAddJoystick(int device_id, String name, String desc,
|
||||
static native void nativeAddJoystick(int device_id, String name, String desc,
|
||||
int vendor_id, int product_id,
|
||||
int button_mask,
|
||||
int naxes, int axis_mask, int nhats, boolean can_rumble);
|
||||
public static native void nativeRemoveJoystick(int device_id);
|
||||
public static native void nativeAddHaptic(int device_id, String name);
|
||||
public static native void nativeRemoveHaptic(int device_id);
|
||||
public static native boolean onNativePadDown(int device_id, int keycode);
|
||||
public static native boolean onNativePadUp(int device_id, int keycode);
|
||||
public static native void onNativeJoy(int device_id, int axis,
|
||||
int naxes, int axis_mask, int nhats, boolean can_rumble, boolean has_rgb_led);
|
||||
static native void nativeRemoveJoystick(int device_id);
|
||||
static native void nativeAddHaptic(int device_id, String name);
|
||||
static native void nativeRemoveHaptic(int device_id);
|
||||
static public native boolean onNativePadDown(int device_id, int keycode);
|
||||
static public native boolean onNativePadUp(int device_id, int keycode);
|
||||
static native void onNativeJoy(int device_id, int axis,
|
||||
float value);
|
||||
public static native void onNativeHat(int device_id, int hat_id,
|
||||
static native void onNativeHat(int device_id, int hat_id,
|
||||
int x, int y);
|
||||
|
||||
protected static SDLJoystickHandler mJoystickHandler;
|
||||
@@ -41,13 +46,9 @@ public class SDLControllerManager
|
||||
|
||||
private static final String TAG = "SDLControllerManager";
|
||||
|
||||
public static void initialize() {
|
||||
static void initialize() {
|
||||
if (mJoystickHandler == null) {
|
||||
if (Build.VERSION.SDK_INT >= 19 /* Android 4.4 (KITKAT) */) {
|
||||
mJoystickHandler = new SDLJoystickHandler_API19();
|
||||
} else {
|
||||
mJoystickHandler = new SDLJoystickHandler_API16();
|
||||
}
|
||||
mJoystickHandler = new SDLJoystickHandler();
|
||||
}
|
||||
|
||||
if (mHapticHandler == null) {
|
||||
@@ -62,48 +63,55 @@ public class SDLControllerManager
|
||||
}
|
||||
|
||||
// Joystick glue code, just a series of stubs that redirect to the SDLJoystickHandler instance
|
||||
public static boolean handleJoystickMotionEvent(MotionEvent event) {
|
||||
static public boolean handleJoystickMotionEvent(MotionEvent event) {
|
||||
return mJoystickHandler.handleMotionEvent(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void pollInputDevices() {
|
||||
static void pollInputDevices() {
|
||||
mJoystickHandler.pollInputDevices();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void pollHapticDevices() {
|
||||
static void joystickSetLED(int device_id, int red, int green, int blue) {
|
||||
mJoystickHandler.setLED(device_id, red, green, blue);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
static void pollHapticDevices() {
|
||||
mHapticHandler.pollHapticDevices();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void hapticRun(int device_id, float intensity, int length) {
|
||||
static void hapticRun(int device_id, float intensity, int length) {
|
||||
mHapticHandler.run(device_id, intensity, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void hapticRumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
|
||||
static void hapticRumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
|
||||
mHapticHandler.rumble(device_id, low_frequency_intensity, high_frequency_intensity, length);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called by SDL using JNI.
|
||||
*/
|
||||
public static void hapticStop(int device_id)
|
||||
static void hapticStop(int device_id)
|
||||
{
|
||||
mHapticHandler.stop(device_id);
|
||||
}
|
||||
|
||||
// Check if a given device is considered a possible SDL joystick
|
||||
public static boolean isDeviceSDLJoystick(int deviceId) {
|
||||
static public boolean isDeviceSDLJoystick(int deviceId) {
|
||||
InputDevice device = InputDevice.getDevice(deviceId);
|
||||
// We cannot use InputDevice.isVirtual before API 16, so let's accept
|
||||
// only nonnegative device ids (VIRTUAL_KEYBOARD equals -1)
|
||||
@@ -133,33 +141,18 @@ public class SDLControllerManager
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* Actual joystick functionality available for API >= 19 devices */
|
||||
class SDLJoystickHandler {
|
||||
|
||||
/**
|
||||
* Handles given MotionEvent.
|
||||
* @param event the event to be handled.
|
||||
* @return if given event was processed.
|
||||
*/
|
||||
public boolean handleMotionEvent(MotionEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles adding and removing of input devices.
|
||||
*/
|
||||
public void pollInputDevices() {
|
||||
}
|
||||
}
|
||||
|
||||
/* Actual joystick functionality available for API >= 12 devices */
|
||||
class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
|
||||
static class SDLJoystick {
|
||||
public int device_id;
|
||||
public String name;
|
||||
public String desc;
|
||||
public ArrayList<InputDevice.MotionRange> axes;
|
||||
public ArrayList<InputDevice.MotionRange> hats;
|
||||
int device_id;
|
||||
String name;
|
||||
String desc;
|
||||
ArrayList<InputDevice.MotionRange> axes;
|
||||
ArrayList<InputDevice.MotionRange> hats;
|
||||
ArrayList<Light> lights;
|
||||
LightsManager.LightsSession lightsSession;
|
||||
}
|
||||
static class RangeComparator implements Comparator<InputDevice.MotionRange> {
|
||||
@Override
|
||||
@@ -210,13 +203,15 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
|
||||
private final ArrayList<SDLJoystick> mJoysticks;
|
||||
|
||||
public SDLJoystickHandler_API16() {
|
||||
SDLJoystickHandler() {
|
||||
|
||||
mJoysticks = new ArrayList<SDLJoystick>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pollInputDevices() {
|
||||
/**
|
||||
* Handles adding and removing of input devices.
|
||||
*/
|
||||
synchronized void pollInputDevices() {
|
||||
int[] deviceIds = InputDevice.getDeviceIds();
|
||||
|
||||
for (int device_id : deviceIds) {
|
||||
@@ -230,6 +225,7 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
joystick.desc = getJoystickDescriptor(joystickDevice);
|
||||
joystick.axes = new ArrayList<InputDevice.MotionRange>();
|
||||
joystick.hats = new ArrayList<InputDevice.MotionRange>();
|
||||
joystick.lights = new ArrayList<Light>();
|
||||
|
||||
List<InputDevice.MotionRange> ranges = joystickDevice.getMotionRanges();
|
||||
Collections.sort(ranges, new RangeComparator());
|
||||
@@ -244,18 +240,30 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
}
|
||||
|
||||
boolean can_rumble = false;
|
||||
boolean has_rgb_led = false;
|
||||
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
||||
VibratorManager manager = joystickDevice.getVibratorManager();
|
||||
int[] vibrators = manager.getVibratorIds();
|
||||
VibratorManager vibratorManager = joystickDevice.getVibratorManager();
|
||||
int[] vibrators = vibratorManager.getVibratorIds();
|
||||
if (vibrators.length > 0) {
|
||||
can_rumble = true;
|
||||
}
|
||||
LightsManager lightsManager = joystickDevice.getLightsManager();
|
||||
List<Light> lights = lightsManager.getLights();
|
||||
for (Light light : lights) {
|
||||
if (light.hasRgbControl()) {
|
||||
joystick.lights.add(light);
|
||||
}
|
||||
}
|
||||
if (!joystick.lights.isEmpty()) {
|
||||
joystick.lightsSession = lightsManager.openSession();
|
||||
has_rgb_led = true;
|
||||
}
|
||||
}
|
||||
|
||||
mJoysticks.add(joystick);
|
||||
SDLControllerManager.nativeAddJoystick(joystick.device_id, joystick.name, joystick.desc,
|
||||
getVendorId(joystickDevice), getProductId(joystickDevice),
|
||||
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble);
|
||||
getButtonMask(joystickDevice), joystick.axes.size(), getAxisMask(joystick.axes), joystick.hats.size()/2, can_rumble, has_rgb_led);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -281,6 +289,16 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
SDLControllerManager.nativeRemoveJoystick(device_id);
|
||||
for (int i = 0; i < mJoysticks.size(); i++) {
|
||||
if (mJoysticks.get(i).device_id == device_id) {
|
||||
if (Build.VERSION.SDK_INT >= 31 /* Android 12.0 (S) */) {
|
||||
if (mJoysticks.get(i).lightsSession != null) {
|
||||
try {
|
||||
mJoysticks.get(i).lightsSession.close();
|
||||
} catch (Exception e) {
|
||||
// Session may already be unregistered when device disconnects
|
||||
}
|
||||
mJoysticks.get(i).lightsSession = null;
|
||||
}
|
||||
}
|
||||
mJoysticks.remove(i);
|
||||
break;
|
||||
}
|
||||
@@ -289,7 +307,7 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
}
|
||||
}
|
||||
|
||||
protected SDLJoystick getJoystick(int device_id) {
|
||||
synchronized protected SDLJoystick getJoystick(int device_id) {
|
||||
for (SDLJoystick joystick : mJoysticks) {
|
||||
if (joystick.device_id == device_id) {
|
||||
return joystick;
|
||||
@@ -298,8 +316,12 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleMotionEvent(MotionEvent event) {
|
||||
/**
|
||||
* Handles given MotionEvent.
|
||||
* @param event the event to be handled.
|
||||
* @return if given event was processed.
|
||||
*/
|
||||
boolean handleMotionEvent(MotionEvent event) {
|
||||
int actionPointerIndex = event.getActionIndex();
|
||||
int action = event.getActionMasked();
|
||||
if (action == MotionEvent.ACTION_MOVE) {
|
||||
@@ -321,7 +343,7 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
public String getJoystickDescriptor(InputDevice joystickDevice) {
|
||||
String getJoystickDescriptor(InputDevice joystickDevice) {
|
||||
String desc = joystickDevice.getDescriptor();
|
||||
|
||||
if (desc != null && !desc.isEmpty()) {
|
||||
@@ -330,34 +352,16 @@ class SDLJoystickHandler_API16 extends SDLJoystickHandler {
|
||||
|
||||
return joystickDevice.getName();
|
||||
}
|
||||
public int getProductId(InputDevice joystickDevice) {
|
||||
return 0;
|
||||
}
|
||||
public int getVendorId(InputDevice joystickDevice) {
|
||||
return 0;
|
||||
}
|
||||
public int getAxisMask(List<InputDevice.MotionRange> ranges) {
|
||||
return -1;
|
||||
}
|
||||
public int getButtonMask(InputDevice joystickDevice) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
class SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 {
|
||||
|
||||
@Override
|
||||
public int getProductId(InputDevice joystickDevice) {
|
||||
int getProductId(InputDevice joystickDevice) {
|
||||
return joystickDevice.getProductId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVendorId(InputDevice joystickDevice) {
|
||||
int getVendorId(InputDevice joystickDevice) {
|
||||
return joystickDevice.getVendorId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getAxisMask(List<InputDevice.MotionRange> ranges) {
|
||||
int getAxisMask(List<InputDevice.MotionRange> ranges) {
|
||||
// For compatibility, keep computing the axis mask like before,
|
||||
// only really distinguishing 2, 4 and 6 axes.
|
||||
int axis_mask = 0;
|
||||
@@ -393,8 +397,7 @@ class SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 {
|
||||
return axis_mask;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getButtonMask(InputDevice joystickDevice) {
|
||||
int getButtonMask(InputDevice joystickDevice) {
|
||||
int button_mask = 0;
|
||||
int[] keys = new int[] {
|
||||
KeyEvent.KEYCODE_BUTTON_A,
|
||||
@@ -487,11 +490,29 @@ class SDLJoystickHandler_API19 extends SDLJoystickHandler_API16 {
|
||||
}
|
||||
return button_mask;
|
||||
}
|
||||
|
||||
void setLED(int device_id, int red, int green, int blue) {
|
||||
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
|
||||
return;
|
||||
}
|
||||
SDLJoystick joystick = getJoystick(device_id);
|
||||
if (joystick == null || joystick.lights.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
LightsRequest.Builder lightsRequest = new LightsRequest.Builder();
|
||||
LightState lightState = new LightState.Builder().setColor(Color.rgb(red, green, blue)).build();
|
||||
for (Light light : joystick.lights) {
|
||||
if (light.hasRgbControl()) {
|
||||
lightsRequest.addLight(light, lightState);
|
||||
}
|
||||
}
|
||||
joystick.lightsSession.requestLights(lightsRequest.build());
|
||||
}
|
||||
}
|
||||
|
||||
class SDLHapticHandler_API31 extends SDLHapticHandler {
|
||||
@Override
|
||||
public void run(int device_id, float intensity, int length) {
|
||||
void run(int device_id, float intensity, int length) {
|
||||
SDLHaptic haptic = getHaptic(device_id);
|
||||
if (haptic != null) {
|
||||
vibrate(haptic.vib, intensity, length);
|
||||
@@ -499,12 +520,17 @@ class SDLHapticHandler_API31 extends SDLHapticHandler {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void rumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
|
||||
void rumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
|
||||
InputDevice device = InputDevice.getDevice(device_id);
|
||||
if (device == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
|
||||
/* Silence 'lint' warning */
|
||||
return;
|
||||
}
|
||||
|
||||
VibratorManager manager = device.getVibratorManager();
|
||||
int[] vibrators = manager.getVibratorIds();
|
||||
if (vibrators.length >= 2) {
|
||||
@@ -517,6 +543,12 @@ class SDLHapticHandler_API31 extends SDLHapticHandler {
|
||||
}
|
||||
|
||||
private void vibrate(Vibrator vibrator, float intensity, int length) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < 31 /* Android 12.0 (S) */) {
|
||||
/* Silence 'lint' warning */
|
||||
return;
|
||||
}
|
||||
|
||||
if (intensity == 0.0f) {
|
||||
vibrator.cancel();
|
||||
return;
|
||||
@@ -543,7 +575,13 @@ class SDLHapticHandler_API31 extends SDLHapticHandler {
|
||||
|
||||
class SDLHapticHandler_API26 extends SDLHapticHandler {
|
||||
@Override
|
||||
public void run(int device_id, float intensity, int length) {
|
||||
void run(int device_id, float intensity, int length) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < 26 /* Android 8.0 (O) */) {
|
||||
/* Silence 'lint' warning */
|
||||
return;
|
||||
}
|
||||
|
||||
SDLHaptic haptic = getHaptic(device_id);
|
||||
if (haptic != null) {
|
||||
if (intensity == 0.0f) {
|
||||
@@ -575,36 +613,36 @@ class SDLHapticHandler_API26 extends SDLHapticHandler {
|
||||
class SDLHapticHandler {
|
||||
|
||||
static class SDLHaptic {
|
||||
public int device_id;
|
||||
public String name;
|
||||
public Vibrator vib;
|
||||
int device_id;
|
||||
String name;
|
||||
Vibrator vib;
|
||||
}
|
||||
|
||||
private final ArrayList<SDLHaptic> mHaptics;
|
||||
|
||||
public SDLHapticHandler() {
|
||||
SDLHapticHandler() {
|
||||
mHaptics = new ArrayList<SDLHaptic>();
|
||||
}
|
||||
|
||||
public void run(int device_id, float intensity, int length) {
|
||||
void run(int device_id, float intensity, int length) {
|
||||
SDLHaptic haptic = getHaptic(device_id);
|
||||
if (haptic != null) {
|
||||
haptic.vib.vibrate(length);
|
||||
}
|
||||
}
|
||||
|
||||
public void rumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
|
||||
void rumble(int device_id, float low_frequency_intensity, float high_frequency_intensity, int length) {
|
||||
// Not supported in older APIs
|
||||
}
|
||||
|
||||
public void stop(int device_id) {
|
||||
void stop(int device_id) {
|
||||
SDLHaptic haptic = getHaptic(device_id);
|
||||
if (haptic != null) {
|
||||
haptic.vib.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public void pollHapticDevices() {
|
||||
synchronized void pollHapticDevices() {
|
||||
|
||||
final int deviceId_VIBRATOR_SERVICE = 999999;
|
||||
boolean hasVibratorService = false;
|
||||
@@ -652,7 +690,7 @@ class SDLHapticHandler {
|
||||
}
|
||||
}
|
||||
|
||||
protected SDLHaptic getHaptic(int device_id) {
|
||||
synchronized protected SDLHaptic getHaptic(int device_id) {
|
||||
for (SDLHaptic haptic : mHaptics) {
|
||||
if (haptic.device_id == device_id) {
|
||||
return haptic;
|
||||
@@ -663,6 +701,10 @@ class SDLHapticHandler {
|
||||
}
|
||||
|
||||
class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
|
||||
protected static final int SDL_PEN_DEVICE_TYPE_UNKNOWN = 0;
|
||||
protected static final int SDL_PEN_DEVICE_TYPE_DIRECT = 1;
|
||||
protected static final int SDL_PEN_DEVICE_TYPE_INDIRECT = 2;
|
||||
|
||||
// Generic Motion (mouse hover, joystick...) events go here
|
||||
@Override
|
||||
public boolean onGenericMotion(View v, MotionEvent event) {
|
||||
@@ -713,8 +755,11 @@ class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
|
||||
|
||||
// BUTTON_STYLUS_PRIMARY is 2^5, so shift by 4, and apply SDL_PEN_INPUT_DOWN/SDL_PEN_INPUT_ERASER_TIP
|
||||
int buttons = (event.getButtonState() >> 4) | (1 << (toolType == MotionEvent.TOOL_TYPE_STYLUS ? 0 : 30));
|
||||
if ((event.getButtonState() & MotionEvent.BUTTON_TERTIARY) != 0) {
|
||||
buttons |= 0x08;
|
||||
}
|
||||
|
||||
SDLActivity.onNativePen(event.getPointerId(i), buttons, action, x, y, p);
|
||||
SDLActivity.onNativePen(event.getPointerId(i), getPenDeviceType(event.getDevice()), buttons, action, x, y, p);
|
||||
consumed = true;
|
||||
break;
|
||||
}
|
||||
@@ -724,34 +769,37 @@ class SDLGenericMotionListener_API14 implements View.OnGenericMotionListener {
|
||||
return consumed;
|
||||
}
|
||||
|
||||
public boolean supportsRelativeMouse() {
|
||||
boolean supportsRelativeMouse() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean inRelativeMode() {
|
||||
boolean inRelativeMode() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean setRelativeMouseEnabled(boolean enabled) {
|
||||
boolean setRelativeMouseEnabled(boolean enabled) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void reclaimRelativeMouseModeIfNeeded() {
|
||||
void reclaimRelativeMouseModeIfNeeded() {
|
||||
|
||||
}
|
||||
|
||||
public boolean checkRelativeEvent(MotionEvent event) {
|
||||
boolean checkRelativeEvent(MotionEvent event) {
|
||||
return inRelativeMode();
|
||||
}
|
||||
|
||||
public float getEventX(MotionEvent event, int pointerIndex) {
|
||||
float getEventX(MotionEvent event, int pointerIndex) {
|
||||
return event.getX(pointerIndex);
|
||||
}
|
||||
|
||||
public float getEventY(MotionEvent event, int pointerIndex) {
|
||||
float getEventY(MotionEvent event, int pointerIndex) {
|
||||
return event.getY(pointerIndex);
|
||||
}
|
||||
|
||||
int getPenDeviceType(InputDevice penDevice) {
|
||||
return SDL_PEN_DEVICE_TYPE_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API14 {
|
||||
@@ -760,23 +808,28 @@ class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API14 {
|
||||
private boolean mRelativeModeEnabled;
|
||||
|
||||
@Override
|
||||
public boolean supportsRelativeMouse() {
|
||||
boolean supportsRelativeMouse() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inRelativeMode() {
|
||||
boolean inRelativeMode() {
|
||||
return mRelativeModeEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setRelativeMouseEnabled(boolean enabled) {
|
||||
boolean setRelativeMouseEnabled(boolean enabled) {
|
||||
mRelativeModeEnabled = enabled;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getEventX(MotionEvent event, int pointerIndex) {
|
||||
float getEventX(MotionEvent event, int pointerIndex) {
|
||||
if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {
|
||||
/* Silence 'lint' warning */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mRelativeModeEnabled && event.getToolType(pointerIndex) == MotionEvent.TOOL_TYPE_MOUSE) {
|
||||
return event.getAxisValue(MotionEvent.AXIS_RELATIVE_X, pointerIndex);
|
||||
} else {
|
||||
@@ -785,7 +838,12 @@ class SDLGenericMotionListener_API24 extends SDLGenericMotionListener_API14 {
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getEventY(MotionEvent event, int pointerIndex) {
|
||||
float getEventY(MotionEvent event, int pointerIndex) {
|
||||
if (Build.VERSION.SDK_INT < 24 /* Android 7.0 (N) */) {
|
||||
/* Silence 'lint' warning */
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (mRelativeModeEnabled && event.getToolType(pointerIndex) == MotionEvent.TOOL_TYPE_MOUSE) {
|
||||
return event.getAxisValue(MotionEvent.AXIS_RELATIVE_Y, pointerIndex);
|
||||
} else {
|
||||
@@ -799,17 +857,23 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
|
||||
private boolean mRelativeModeEnabled;
|
||||
|
||||
@Override
|
||||
public boolean supportsRelativeMouse() {
|
||||
boolean supportsRelativeMouse() {
|
||||
return (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inRelativeMode() {
|
||||
boolean inRelativeMode() {
|
||||
return mRelativeModeEnabled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setRelativeMouseEnabled(boolean enabled) {
|
||||
boolean setRelativeMouseEnabled(boolean enabled) {
|
||||
|
||||
if (Build.VERSION.SDK_INT < 26 /* Android 8.0 (O) */) {
|
||||
/* Silence 'lint' warning */
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!SDLActivity.isDeXMode() || Build.VERSION.SDK_INT >= 27 /* Android 8.1 (O_MR1) */) {
|
||||
if (enabled) {
|
||||
SDLActivity.getContentView().requestPointerCapture();
|
||||
@@ -824,26 +888,48 @@ class SDLGenericMotionListener_API26 extends SDLGenericMotionListener_API24 {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reclaimRelativeMouseModeIfNeeded() {
|
||||
void reclaimRelativeMouseModeIfNeeded() {
|
||||
|
||||
if (Build.VERSION.SDK_INT < 26 /* Android 8.0 (O) */) {
|
||||
/* Silence 'lint' warning */
|
||||
return;
|
||||
}
|
||||
|
||||
if (mRelativeModeEnabled && !SDLActivity.isDeXMode()) {
|
||||
SDLActivity.getContentView().requestPointerCapture();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean checkRelativeEvent(MotionEvent event) {
|
||||
boolean checkRelativeEvent(MotionEvent event) {
|
||||
if (Build.VERSION.SDK_INT < 26 /* Android 8.0 (O) */) {
|
||||
/* Silence 'lint' warning */
|
||||
return false;
|
||||
}
|
||||
return event.getSource() == InputDevice.SOURCE_MOUSE_RELATIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getEventX(MotionEvent event, int pointerIndex) {
|
||||
float getEventX(MotionEvent event, int pointerIndex) {
|
||||
// Relative mouse in capture mode will only have relative for X/Y
|
||||
return event.getX(pointerIndex);
|
||||
}
|
||||
|
||||
@Override
|
||||
public float getEventY(MotionEvent event, int pointerIndex) {
|
||||
float getEventY(MotionEvent event, int pointerIndex) {
|
||||
// Relative mouse in capture mode will only have relative for X/Y
|
||||
return event.getY(pointerIndex);
|
||||
}
|
||||
}
|
||||
|
||||
class SDLGenericMotionListener_API29 extends SDLGenericMotionListener_API26 {
|
||||
@Override
|
||||
int getPenDeviceType(InputDevice penDevice)
|
||||
{
|
||||
if (penDevice == null) {
|
||||
return SDL_PEN_DEVICE_TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
return penDevice.isExternal() ? SDL_PEN_DEVICE_TYPE_INDIRECT : SDL_PEN_DEVICE_TYPE_DIRECT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,14 +14,14 @@ public class SDLDummyEdit extends View implements View.OnKeyListener
|
||||
InputConnection ic;
|
||||
int input_type;
|
||||
|
||||
public SDLDummyEdit(Context context) {
|
||||
SDLDummyEdit(Context context) {
|
||||
super(context);
|
||||
setFocusableInTouchMode(true);
|
||||
setFocusable(true);
|
||||
setOnKeyListener(this);
|
||||
}
|
||||
|
||||
public void setInputType(int input_type) {
|
||||
void setInputType(int input_type) {
|
||||
this.input_type = input_type;
|
||||
}
|
||||
|
||||
|
||||
@@ -7,12 +7,12 @@ import android.view.*;
|
||||
import android.view.inputmethod.BaseInputConnection;
|
||||
import android.widget.EditText;
|
||||
|
||||
public class SDLInputConnection extends BaseInputConnection
|
||||
class SDLInputConnection extends BaseInputConnection
|
||||
{
|
||||
protected EditText mEditText;
|
||||
protected String mCommittedText = "";
|
||||
|
||||
public SDLInputConnection(View targetView, boolean fullEditor) {
|
||||
SDLInputConnection(View targetView, boolean fullEditor) {
|
||||
super(targetView, fullEditor);
|
||||
mEditText = new EditText(SDL.getContext());
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.view.Display;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.PointerIcon;
|
||||
import android.view.Surface;
|
||||
import android.view.SurfaceHolder;
|
||||
import android.view.SurfaceView;
|
||||
@@ -22,6 +23,7 @@ import android.view.View;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import android.view.ScaleGestureDetector;
|
||||
|
||||
/**
|
||||
SDLSurface. This is what we draw on, so we need to know when it's created
|
||||
@@ -30,7 +32,8 @@ import android.view.WindowManager;
|
||||
Because of this, that's where we set up the SDL thread
|
||||
*/
|
||||
public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
View.OnApplyWindowInsetsListener, View.OnKeyListener, View.OnTouchListener, SensorEventListener {
|
||||
View.OnApplyWindowInsetsListener, View.OnKeyListener, View.OnTouchListener,
|
||||
SensorEventListener, ScaleGestureDetector.OnScaleGestureListener {
|
||||
|
||||
// Sensors
|
||||
protected SensorManager mSensorManager;
|
||||
@@ -40,13 +43,18 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
protected float mWidth, mHeight;
|
||||
|
||||
// Is SurfaceView ready for rendering
|
||||
public boolean mIsSurfaceReady;
|
||||
protected boolean mIsSurfaceReady;
|
||||
|
||||
// Pinch events
|
||||
private final ScaleGestureDetector scaleGestureDetector;
|
||||
|
||||
// Startup
|
||||
public SDLSurface(Context context) {
|
||||
protected SDLSurface(Context context) {
|
||||
super(context);
|
||||
getHolder().addCallback(this);
|
||||
|
||||
scaleGestureDetector = new ScaleGestureDetector(context, this);
|
||||
|
||||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
requestFocus();
|
||||
@@ -66,11 +74,11 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
mIsSurfaceReady = false;
|
||||
}
|
||||
|
||||
public void handlePause() {
|
||||
protected void handlePause() {
|
||||
enableSensor(Sensor.TYPE_ACCELEROMETER, false);
|
||||
}
|
||||
|
||||
public void handleResume() {
|
||||
protected void handleResume() {
|
||||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
requestFocus();
|
||||
@@ -80,7 +88,7 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
enableSensor(Sensor.TYPE_ACCELEROMETER, true);
|
||||
}
|
||||
|
||||
public Surface getNativeSurface() {
|
||||
protected Surface getNativeSurface() {
|
||||
return getHolder().getSurface();
|
||||
}
|
||||
|
||||
@@ -121,14 +129,12 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
float density = 1.0f;
|
||||
try
|
||||
{
|
||||
if (Build.VERSION.SDK_INT >= 17 /* Android 4.2 (JELLY_BEAN_MR1) */) {
|
||||
DisplayMetrics realMetrics = new DisplayMetrics();
|
||||
mDisplay.getRealMetrics( realMetrics );
|
||||
nDeviceWidth = realMetrics.widthPixels;
|
||||
nDeviceHeight = realMetrics.heightPixels;
|
||||
// Use densityDpi instead of density to more closely match what the UI scale is
|
||||
density = (float)realMetrics.densityDpi / 160.0f;
|
||||
}
|
||||
DisplayMetrics realMetrics = new DisplayMetrics();
|
||||
mDisplay.getRealMetrics( realMetrics );
|
||||
nDeviceWidth = realMetrics.widthPixels;
|
||||
nDeviceHeight = realMetrics.heightPixels;
|
||||
// Use densityDpi instead of density to more closely match what the UI scale is
|
||||
density = (float)realMetrics.densityDpi / 160.0f;
|
||||
} catch(Exception ignored) {
|
||||
}
|
||||
|
||||
@@ -274,8 +280,11 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
|
||||
// BUTTON_STYLUS_PRIMARY is 2^5, so shift by 4, and apply SDL_PEN_INPUT_DOWN/SDL_PEN_INPUT_ERASER_TIP
|
||||
int buttonState = (event.getButtonState() >> 4) | (1 << (toolType == MotionEvent.TOOL_TYPE_STYLUS ? 0 : 30));
|
||||
if ((event.getButtonState() & MotionEvent.BUTTON_TERTIARY) != 0) {
|
||||
buttonState |= 0x08;
|
||||
}
|
||||
|
||||
SDLActivity.onNativePen(pointerId, buttonState, action, x, y, p);
|
||||
SDLActivity.onNativePen(pointerId, SDLActivity.getMotionListener().getPenDeviceType(event.getDevice()), buttonState, action, x, y, p);
|
||||
} else { // MotionEvent.TOOL_TYPE_FINGER or MotionEvent.TOOL_TYPE_UNKNOWN
|
||||
pointerId = event.getPointerId(i);
|
||||
x = getNormalizedX(event.getX(i));
|
||||
@@ -295,11 +304,13 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
break;
|
||||
} while (++i < pointerCount);
|
||||
|
||||
scaleGestureDetector.onTouchEvent(event);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Sensor events
|
||||
public void enableSensor(int sensortype, boolean enabled) {
|
||||
protected void enableSensor(int sensortype, boolean enabled) {
|
||||
// TODO: This uses getDefaultSensor - what if we have >1 accels?
|
||||
if (enabled) {
|
||||
mSensorManager.registerListener(this,
|
||||
@@ -362,7 +373,18 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent android internal NullPointerException (https://github.com/libsdl-org/SDL/issues/13306)
|
||||
@Override
|
||||
public PointerIcon onResolvePointerIcon(MotionEvent event, int pointerIndex) {
|
||||
try {
|
||||
return super.onResolvePointerIcon(event, pointerIndex);
|
||||
} catch (NullPointerException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Captured pointer events for API 26.
|
||||
@Override
|
||||
public boolean onCapturedPointerEvent(MotionEvent event)
|
||||
{
|
||||
int action = event.getActionMasked();
|
||||
@@ -401,8 +423,27 @@ public class SDLSurface extends SurfaceView implements SurfaceHolder.Callback,
|
||||
SDLActivity.onNativeMouse(button, action, x, y, true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScale(ScaleGestureDetector detector) {
|
||||
float scale = detector.getScaleFactor();
|
||||
SDLActivity.onNativePinchUpdate(scale);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onScaleBegin(ScaleGestureDetector detector) {
|
||||
SDLActivity.onNativePinchStart();
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScaleEnd(ScaleGestureDetector detector) {
|
||||
SDLActivity.onNativePinchEnd();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user