123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- 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;
- }
- }
|