mirror of https://git.sr.ht/~rabbits/uxn
9 changed files with 776 additions and 585 deletions
@ -1 +1 @@
|
||||
Subproject commit 565ef63873c2dfa85e1e80db9dfbefbd9a8c67db |
||||
Subproject commit 9b061c04e71be9e6729c06c3e64be95cf09244a2 |
||||
File diff suppressed because it is too large
Load Diff
@ -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; |
||||
} |
||||
} |
||||
@ -1,6 +1,6 @@
|
||||
#Thu Nov 11 18:20:34 PST 2021 |
||||
#Mon Feb 13 14:40:52 CET 2023 |
||||
distributionBase=GRADLE_USER_HOME |
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-bin.zip |
||||
distributionPath=wrapper/dists |
||||
zipStorePath=wrapper/dists |
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.6-bin.zip |
||||
zipStoreBase=GRADLE_USER_HOME |
||||
zipStorePath=wrapper/dists |
||||
|
||||
Loading…
Reference in new issue