Xrasher/src/in/celest/xash3d/XashActivity.java

861 lines
23 KiB
Java
Raw Normal View History

package in.celest.xash3d;
import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLContext;
import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.egl.*;
import android.app.*;
import android.content.*;
import android.view.*;
import android.os.*;
import android.util.Log;
import android.graphics.*;
import android.text.method.*;
import android.text.*;
import android.media.*;
import android.hardware.*;
import android.content.*;
2016-05-08 22:57:35 +00:00
import android.widget.*;
import android.view.inputmethod.*;
import java.lang.*;
/**
SDL Activity
*/
public class XashActivity extends Activity {
2016-05-09 14:03:50 +00:00
// Main components
protected static XashActivity mSingleton;
protected static View mTextEdit;
private static EngineSurface mSurface;
public static String mArgv[];
public static final int sdk = Integer.valueOf(Build.VERSION.SDK);
public static final String TAG = "XASH3D:XashActivity";
public static int mPixelFormat;
protected static ViewGroup mLayout;
2016-07-26 22:39:54 +06:00
// Preferences
2016-05-09 14:03:50 +00:00
public static SharedPreferences mPref = null;
2016-05-31 09:03:38 +00:00
private static boolean mUseVolume;
2016-05-09 14:03:50 +00:00
// Audio
private static Thread mAudioThread;
private static AudioTrack mAudioTrack;
// Load the .so
static {
System.loadLibrary("xash");
}
// Setup
protected void onCreate(Bundle savedInstanceState) {
Log.v(TAG, "onCreate()");
super.onCreate(savedInstanceState);
// So we can call stuff from static callbacks
mSingleton = this;
Intent intent = getIntent();
// fullscreen
2016-05-06 16:49:42 +00:00
requestWindowFeature(Window.FEATURE_NO_TITLE);
2016-05-09 15:05:28 +00:00
//if(sdk >= 12)
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
2016-05-06 16:49:42 +00:00
2016-05-08 07:59:53 +00:00
// landscapeSensor is not supported until API9
if( sdk < 9 )
setRequestedOrientation(0);
2016-05-06 16:49:42 +00:00
// keep screen on
2016-05-09 14:03:50 +00:00
getWindow().setFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON, WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
2016-05-06 16:49:42 +00:00
// Set up the surface
2016-05-09 14:03:50 +00:00
mSurface = new EngineSurface(getApplication());
mLayout = new FrameLayout(this);
mLayout.addView(mSurface);
setContentView(mLayout);
SurfaceHolder holder = mSurface.getHolder();
holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
// setup envs
2016-05-04 21:02:09 +00:00
mPref = this.getSharedPreferences("engine", 0);
String argv = intent.getStringExtra("argv");
if(argv == null) argv = mPref.getString("argv", "-dev 3 -log");
if(argv == null) argv = "-dev 3 -log";
mArgv= argv.split(" ");
2016-05-09 14:03:50 +00:00
2016-05-04 21:02:09 +00:00
String gamelibdir = intent.getStringExtra("gamelibdir");
if(gamelibdir == null)
gamelibdir = getFilesDir().getParentFile().getPath() + "/lib";
2016-05-09 14:03:50 +00:00
2016-05-04 21:02:09 +00:00
String gamedir = intent.getStringExtra("gamedir");
if(gamedir == null)
gamedir = "valve";
2016-05-09 14:03:50 +00:00
2016-05-04 21:02:09 +00:00
String basedir = intent.getStringExtra("basedir");
if(basedir == null)
basedir = mPref.getString("basedir","/sdcard/xash/");
setenv("XASH3D_BASEDIR", basedir, true);
setenv("XASH3D_ENGLIBDIR", getFilesDir().getParentFile().getPath() + "/lib", true);
setenv("XASH3D_GAMELIBDIR", gamelibdir, true);
setenv("XASH3D_GAMEDIR", gamedir, true);
2016-05-09 14:03:50 +00:00
2016-05-04 21:02:09 +00:00
setenv("XASH3D_EXTRAS_PAK1", getFilesDir().getPath() + "/extras.pak", true);
String pakfile = intent.getStringExtra("pakfile");
if( pakfile != null && pakfile != "" )
setenv("XASH3D_EXTRAS_PAK2", pakfile, true);
String[] env = intent.getStringArrayExtra("env");
try
{
if( env != null )
for(int i = 0; i+1 < env.length; i+=2)
{
setenv(env[i],env[i+1], true);
}
}
catch(Exception e)
{
e.printStackTrace();
}
2016-05-09 14:03:50 +00:00
InstallReceiver.extractPAK(this, false);
2016-05-08 08:44:32 +00:00
mPixelFormat = mPref.getInt("pixelformat", 0);
2016-05-31 09:03:38 +00:00
mUseVolume = mPref.getBoolean("usevolume", false);
2016-07-02 22:31:25 +00:00
if( mPref.getBoolean("enableResizeWorkaround", true) )
AndroidBug5497Workaround.assistActivity(this);
2016-05-09 14:03:50 +00:00
}
// Events
protected void onPause() {
Log.v(TAG, "onPause()");
super.onPause();
}
protected void onResume() {
Log.v(TAG, "onResume()");
super.onResume();
}
public static native int nativeInit(Object arguments);
public static native void nativeQuit();
public static native void onNativeResize(int x, int y);
public static native void nativeTouch(int pointerFingerId, int action, float x, float y);
public static native void nativeKey( int down, int code );
public static native void nativeString( String text );
public static native void nativeSetPause(int pause);
2016-07-26 22:39:54 +06:00
public static native void nativeHat(int id, byte hat, byte keycode, byte down);
public static native void nativeAxis(int id, byte axis, short value);
public static native void nativeJoyButton(int id, byte button, byte down);
// for future expansion
public static native void nativeBall(int id, byte ball, short xrel, short yrel);
public static native void nativeJoyAdd( int id );
public static native void nativeJoyDel( int id );
2016-05-09 14:03:50 +00:00
public static native int setenv(String key, String value, boolean overwrite);
// Java functions called from C
public static boolean createGLContext() {
return mSurface.InitGL();
}
public static void swapBuffers() {
mSurface.SwapBuffers();
}
public static Surface getNativeSurface() {
return XashActivity.mSurface.getNativeSurface();
}
2016-05-09 14:03:50 +00:00
public static void vibrate( int time ) {
((Vibrator) mSingleton.getSystemService(Context.VIBRATOR_SERVICE)).vibrate( time );
}
public static void toggleEGL(int toggle) {
mSurface.toggleEGL(toggle);
}
public static Context getContext() {
return mSingleton;
}
2016-05-09 15:05:28 +00:00
protected final String[] messageboxData = new String[2];
public static void messageBox(String title, String text)
{
mSingleton.messageboxData[0] = title;
mSingleton.messageboxData[1] = text;
mSingleton.runOnUiThread(new Runnable() {
@Override
public void run()
{
new AlertDialog.Builder(mSingleton)
.setTitle(mSingleton.messageboxData[0])
.setMessage(mSingleton.messageboxData[1])
.setPositiveButton( "Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int whichButton) {
synchronized(mSingleton.messageboxData)
{
mSingleton.messageboxData.notify();
}
}
})
.setCancelable(false)
.show();
}
});
synchronized (mSingleton.messageboxData) {
try {
mSingleton.messageboxData.wait();
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
2016-05-09 14:03:50 +00:00
public static boolean handleKey( int keyCode, KeyEvent event )
{
2016-07-26 22:39:54 +06:00
if ( mUseVolume && ( keyCode == KeyEvent.KEYCODE_VOLUME_DOWN ||
2016-05-31 09:03:38 +00:00
keyCode == KeyEvent.KEYCODE_VOLUME_UP ) )
2016-07-26 22:39:54 +06:00
return false;
int source = event.getSource();
boolean isGamePad = (source & InputDevice.SOURCE_GAMEPAD) == InputDevice.SOURCE_GAMEPAD;
boolean isJoystick = (source & InputDevice.SOURCE_JOYSTICK) == InputDevice.SOURCE_CLASS_JOYSTICK;
boolean isDPad = (source & InputDevice.SOURCE_DPAD) == InputDevice.SOURCE_DPAD;
if( isGamePad || isJoystick )
{
byte value;
switch( keyCode )
{
// main buttons. DONT CHANGE THIS!!!!111oneone
case KeyEvent.KEYCODE_BUTTON_A: value = 0; break;
case KeyEvent.KEYCODE_BUTTON_B: value = 1; break;
case KeyEvent.KEYCODE_BUTTON_X: value = 2; break;
case KeyEvent.KEYCODE_BUTTON_Y: value = 3; break;
case KeyEvent.KEYCODE_BUTTON_L1: value = 4; break;
case KeyEvent.KEYCODE_BUTTON_R1: value = 5; break;
case KeyEvent.KEYCODE_BUTTON_SELECT: value = 6; break;
case KeyEvent.KEYCODE_BUTTON_MODE: value = 7; break;
case KeyEvent.KEYCODE_BUTTON_START: value = 8; break;
case KeyEvent.KEYCODE_BUTTON_THUMBL: value = 9; break;
case KeyEvent.KEYCODE_BUTTON_THUMBR: value = 10; break;
// other
case KeyEvent.KEYCODE_BUTTON_C: value = 11; break;
case KeyEvent.KEYCODE_BUTTON_Z: value = 12; break;
case KeyEvent.KEYCODE_BUTTON_L2: value = 13; break;
case KeyEvent.KEYCODE_BUTTON_R2: value = 14; break;
default:
if( keyCode >= KeyEvent.KEYCODE_BUTTON_1 && keyCode <= KeyEvent.KEYCODE_BUTTON_16 )
{
value = keyCode - KeyEvent.KEYCODE_BUTTON_1 + 15;
}
else if( KeyEvent.isGamePadButton(keyCode) )
{
Log.d(TAG, "Unhandled GamePad button: " + KeyEvent.keyCodeToString(keyCode) );
return false;
}
}
if( event.getAction() == KeyEvent.ACTION_DOWN )
nativeJoyButton( 0, value, true );
else if( event.getAction() == KeyEvent.ACTION_UP )
nativeJoyButton( 0, value, false );
return true;
}
if( isDPad )
{
int dpad;
switch( keyCode )
{
case KeyEvent.KEYCODE_DPAD_CENTER:
dpad = 0; break;
case KeyEvent.KEYCODE_DPAD_UP:
dpad = 1; break;
case KeyEvent.KEYCODE_DPAD_RIGHT:
dpad = 2; break;
case KeyEvent.KEYCODE_DPAD_LEFT:
dpad = 3; break;
case KeyEvent.KEYCODE_DPAD_DOWN:
dpad = 4; break;
default: return false;
}
if( event.getAction() == KeyEvent.ACTION_DOWN )
nativeJoyButton( 0, 0, dpad, true );
else if( event.getAction() == KeyEvent.ACTION_UP )
nativeJoyButton( 0, 0, dpad, false );
return true;
}
Log.d( TAG, "Keycode " + KeyEvent.keyCodeToString(keyCode) +
". IsGamePadButton(" + KeyEvent.isGamePadButton(keyCode) + ")" );
2016-05-09 14:03:50 +00:00
if (event.getAction() == KeyEvent.ACTION_DOWN)
{
if (event.isPrintingKey() || keyCode == 62)// space is printing too
2016-05-08 22:57:35 +00:00
XashActivity.nativeString(String.valueOf((char) event.getUnicodeChar()));
2016-05-09 14:03:50 +00:00
2016-07-26 22:39:54 +06:00
XashActivity.nativeKey(1, keyCode);
2016-05-09 14:03:50 +00:00
2016-05-08 22:57:35 +00:00
return true;
2016-05-09 14:03:50 +00:00
}
else if (event.getAction() == KeyEvent.ACTION_UP)
{
2016-05-08 22:57:35 +00:00
2016-07-26 22:39:54 +06:00
XashActivity.nativeKey(0, keyCode);
2016-05-08 22:57:35 +00:00
return true;
}
return false;
}
2016-07-26 22:39:54 +06:00
public static float performEngineAxisEvent( MotionEvent event, int axis, byte engineAxis, float prev )
{
final float current = event.getAxisValue( axis );
if( prev != current && engineAxis != 255 )
{
if( current < 0 )
nativeAxis( 0, engineAxis, (short)(current * -32768) );
else nativeAxis(0, engineAxis, (short)(current * 32767) );
}
return current;
}
private static float prevLeftX, prevLeftY, prevRightX, prevRightY, prevLT, prevRT, prevHX, prevHY;
public static boolean handleAxis( MotionEvent event )
{
prevLeftX = performEngineAxisEvent(event, event.AXIS_X, 0, prevLeftX);
prevLeftY = performEngineAxisEvent(event, event.AXIS_Y, 1, prevLeftY);
prevRightX = performEngineAxisEvent(event, event.AXIS_Z, 2, prevRightX);
prevRightY = performEngineAxisEvent(event, event.AXIS_RZ, 3, prevRightY);
prevLT = performEngineAxisEvent(event, event.LTRIGGER, 4, prevLT);
prevRT = performEngineAxisEvent(event, event.RTRIGGER, 5, prevRT);
// Because Android may map DPad to AXIS_HAT_X/Y, we need to check these again here
float HX = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_X);
float HY = motionEvent.getAxisValue(MotionEvent.AXIS_HAT_Y);
if(prevHX != HX)
{
if(HX == 1.0f)
nativeHat( 0, 0, 2, true );
else if(HX == -1.0f)
nativeHat( 0, 0, 3, true );
else
{
nativeHat( 0, 0, 2, false );
nativeHat( 0, 0, 3, false );
}
prevHX = HX;
}
if( prevHY != HY )
{
if(HX == 1.0f)
nativeHat( 0, 0, 1, true );
else if(HX == -1.0f)
nativeHat( 0, 0, 4, true );
else
{
nativeHat( 0, 0, 1, false );
nativeHat( 0, 0, 4, false );
}
prevHY = HY;
}
}
2016-05-09 14:03:50 +00:00
static class ShowTextInputTask implements Runnable
{
2016-05-08 22:57:35 +00:00
/*
* This is used to regulate the pan&scan method to have some offset from
* the bottom edge of the input region and the top edge of an input
* method (soft keyboard)
*/
private int show;
public ShowTextInputTask(int show1) {
show = show1;
}
@Override
public void run() {
InputMethodManager imm = (InputMethodManager) getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
if (mTextEdit == null)
{
mTextEdit = new DummyEdit(getContext());
mLayout.addView(mTextEdit);
}
if( show == 1 )
{
2016-05-09 14:03:50 +00:00
mTextEdit.setVisibility(View.VISIBLE);
mTextEdit.requestFocus();
2016-05-08 22:57:35 +00:00
2016-05-09 14:03:50 +00:00
imm.showSoftInput(mTextEdit, 0);
2016-05-08 22:57:35 +00:00
}
else
{
mTextEdit.setVisibility(View.GONE);
imm.hideSoftInputFromWindow(mTextEdit.getWindowToken(), 0);
}
}
}
/**
* This method is called by SDL using JNI.
*/
2016-05-09 14:03:50 +00:00
public static void showKeyboard( int show )
{
2016-05-08 22:57:35 +00:00
// Transfer the task to the main thread as a Runnable
mSingleton.runOnUiThread(new ShowTextInputTask(show));
}
}
/**
Simple nativeInit() runnable
*/
class XashMain implements Runnable {
2016-05-09 14:03:50 +00:00
public void run()
{
XashActivity.nativeInit(XashActivity.mArgv);
}
}
/**
SDLSurface. This is what we draw on, so we need to know when it's created
2016-05-04 21:02:09 +00:00
in order to do anything useful.
Because of this, that's where we set up the SDL thread
*/
2016-05-04 21:02:09 +00:00
class EngineSurface extends SurfaceView implements SurfaceHolder.Callback,
2016-05-06 08:58:01 +00:00
View.OnKeyListener {
2016-05-09 14:03:50 +00:00
// This is what SDL runs in. It invokes SDL_main(), eventually
private Thread mEngThread;
// EGL private objects
private EGLContext mEGLContext;
private EGLSurface mEGLSurface;
private EGLDisplay mEGLDisplay;
private EGL10 mEGL;
private EGLConfig mEGLConfig;
public static final String TAG = "XASH3D-EngineSurface";
// Sensors
// Startup
public EngineSurface(Context context)
{
super(context);
getHolder().addCallback(this);
setFocusable(true);
setFocusableInTouchMode(true);
requestFocus();
setOnKeyListener(this);
if( XashActivity.sdk >= 5 )
setOnTouchListener(new EngineTouchListener_v5());
else
setOnTouchListener(new EngineTouchListener_v1());
}
// Called when we have a valid drawing surface
public void surfaceCreated(SurfaceHolder holder)
{
Log.v(TAG, "surfaceCreated()");
if( mEGL == null )
return;
XashActivity.nativeSetPause(0);
}
// Called when we lose the surface
public void surfaceDestroyed(SurfaceHolder holder)
{
Log.v(TAG, "surfaceDestroyed()");
if( mEGL == null )
return;
XashActivity.nativeSetPause(1);
}
// Called when the surface is resized
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height)
{
Log.v(TAG, "surfaceChanged()");
XashActivity.onNativeResize(width, height);
// Now start up the C app thread
if (mEngThread == null) {
mEngThread = new Thread(new XashMain(), "EngineThread");
mEngThread.start();
}
}
// unused
public void onDraw(Canvas canvas) {}
// first, initialize native backend
public Surface getNativeSurface() {
return getHolder().getSurface();
}
2016-05-09 14:03:50 +00:00
// EGL functions
public boolean InitGL() {
try
{
EGL10 egl = (EGL10)EGLContext.getEGL();
EGLDisplay dpy = egl.eglGetDisplay(EGL10.EGL_DEFAULT_DISPLAY);
int[] version = new int[2];
egl.eglInitialize(dpy, version);
int[][] configSpec = {{
EGL10.EGL_DEPTH_SIZE, 8,
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 8,
EGL10.EGL_NONE
}, {
EGL10.EGL_DEPTH_SIZE, 8,
EGL10.EGL_RED_SIZE, 8,
EGL10.EGL_GREEN_SIZE, 8,
EGL10.EGL_BLUE_SIZE, 8,
EGL10.EGL_ALPHA_SIZE, 0,
EGL10.EGL_NONE
}, {
EGL10.EGL_DEPTH_SIZE, 8,
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 6,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_ALPHA_SIZE, 0,
EGL10.EGL_NONE
}, {
EGL10.EGL_DEPTH_SIZE, 8,
EGL10.EGL_RED_SIZE, 5,
EGL10.EGL_GREEN_SIZE, 5,
EGL10.EGL_BLUE_SIZE, 5,
EGL10.EGL_ALPHA_SIZE, 1,
EGL10.EGL_NONE
}, {
EGL10.EGL_DEPTH_SIZE, 8,
EGL10.EGL_RED_SIZE, 4,
EGL10.EGL_GREEN_SIZE, 4,
EGL10.EGL_BLUE_SIZE, 4,
EGL10.EGL_ALPHA_SIZE, 4,
EGL10.EGL_NONE
}, {
EGL10.EGL_DEPTH_SIZE, 8,
EGL10.EGL_RED_SIZE, 3,
EGL10.EGL_GREEN_SIZE, 3,
EGL10.EGL_BLUE_SIZE, 2,
EGL10.EGL_ALPHA_SIZE, 0,
EGL10.EGL_NONE
}};
EGLConfig[] configs = new EGLConfig[1];
int[] num_config = new int[1];
if (!egl.eglChooseConfig(dpy, configSpec[XashActivity.mPixelFormat], configs, 1, num_config) || num_config[0] == 0)
{
Log.e(TAG, "No EGL config available");
return false;
}
EGLConfig config = configs[0];
int EGL_CONTEXT_CLIENT_VERSION=0x3098;
int contextAttrs[] = new int[]
{
EGL_CONTEXT_CLIENT_VERSION, 1,
EGL10.EGL_NONE
};
EGLContext ctx = egl.eglCreateContext(dpy, config, EGL10.EGL_NO_CONTEXT, contextAttrs);
if (ctx == EGL10.EGL_NO_CONTEXT) {
Log.e(TAG, "Couldn't create context");
return false;
}
EGLSurface surface = egl.eglCreateWindowSurface(dpy, config, this, null);
if (surface == EGL10.EGL_NO_SURFACE) {
Log.e(TAG, "Couldn't create surface");
return false;
}
if (!egl.eglMakeCurrent(dpy, surface, surface, ctx)) {
Log.e(TAG, "Couldn't make context current");
return false;
}
mEGLContext = ctx;
mEGLDisplay = dpy;
mEGLSurface = surface;
mEGL = egl;
mEGLConfig = config;
} catch(Exception e) {
Log.v(TAG, e + "");
for (StackTraceElement s : e.getStackTrace()) {
Log.v(TAG, s.toString());
}
}
return true;
}
// EGL buffer flip
public void SwapBuffers()
{
if( mEGLSurface == null )
return;
mEGL.eglSwapBuffers(mEGLDisplay, mEGLSurface);
}
public void toggleEGL(int toggle)
{
if( toggle != 0 )
{
mEGLSurface = mEGL.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, this, null);
mEGL.eglMakeCurrent(mEGLDisplay, mEGLSurface, mEGLSurface, mEGLContext);
}
else
{
mEGL.eglMakeCurrent(mEGLDisplay, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_SURFACE, EGL10.EGL_NO_CONTEXT);
mEGL.eglDestroySurface(mEGLDisplay, mEGLSurface);
mEGLSurface = null;
}
}
2016-05-08 22:57:35 +00:00
@Override
2016-07-26 22:39:54 +06:00
public boolean onKey(View v, int keyCode, KeyEvent event)
{
2016-05-08 22:57:35 +00:00
return XashActivity.handleKey( keyCode, event );
}
2016-07-26 22:39:54 +06:00
@Override
public boolean onGenericMotionEvent(MotionEvent event)
{
if( (event.getSource & InputDevice.SOURCE_CLASS_JOYSTICK) == InputDevice.SOURCE_CLASS_JOYSTICK )
return XashActivity.handleAxis( event );
// TODO: Add it someday
// else if( (event.getSource & InputDevice.SOURCE_CLASS_TRACKBALL) == InputDevice.SOURCE_CLASS_TRACKBALL )
// return XashActivity.handleBall( event );
return super.onGenericMotionEvent( event );
}
2016-05-08 22:57:35 +00:00
}
/* This is a fake invisible editor view that receives the input and defines the
* pan&scan region
*/
class DummyEdit extends View implements View.OnKeyListener {
InputConnection ic;
public DummyEdit(Context context) {
super(context);
setFocusableInTouchMode(true);
setFocusable(true);
setOnKeyListener(this);
}
@Override
public boolean onCheckIsTextEditor() {
return true;
}
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
return XashActivity.handleKey( keyCode, event );
}
@Override
public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
ic = new XashInputConnection(this, true);
outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI
| 33554432 /* API 11: EditorInfo.IME_FLAG_NO_FULLSCREEN */;
return ic;
}
}
class XashInputConnection extends BaseInputConnection {
public XashInputConnection(View targetView, boolean fullEditor) {
super(targetView, fullEditor);
}
@Override
public boolean sendKeyEvent(KeyEvent event) {
if( XashActivity.handleKey( event.getKeyCode(), event ) )
2016-05-05 20:01:43 +00:00
return true;
2016-05-08 22:57:35 +00:00
return super.sendKeyEvent(event);
}
@Override
public boolean commitText(CharSequence text, int newCursorPosition) {
//nativeCommitText(text.toString(), newCursorPosition);
XashActivity.nativeString(text.toString());
return super.commitText(text, newCursorPosition);
}
@Override
public boolean setComposingText(CharSequence text, int newCursorPosition) {
//nativeSetComposingText(text.toString(), newCursorPosition);
XashActivity.nativeString(text.toString());
return super.setComposingText(text, newCursorPosition);
}
public native void nativeSetComposingText(String text, int newCursorPosition);
@Override
public boolean deleteSurroundingText(int beforeLength, int afterLength) {
// Workaround to capture backspace key. Ref: http://stackoverflow.com/questions/14560344/android-backspace-in-webview-baseinputconnection
if (beforeLength == 1 && afterLength == 0) {
// backspace
XashActivity.nativeKey(1,KeyEvent.KEYCODE_DEL);
XashActivity.nativeKey(0,KeyEvent.KEYCODE_DEL);
2016-05-05 20:01:43 +00:00
}
2016-05-08 22:57:35 +00:00
return super.deleteSurroundingText(beforeLength, afterLength);
}
2016-05-06 08:58:01 +00:00
}
class EngineTouchListener_v1 implements View.OnTouchListener{
2016-05-09 14:03:50 +00:00
// Touch events
public boolean onTouch(View v, MotionEvent event)
{
XashActivity.nativeTouch(0, event.getAction(), event.getX(), event.getY());
2016-05-06 08:58:01 +00:00
return true;
}
}
2016-05-04 21:34:15 +00:00
2016-05-06 08:58:01 +00:00
class EngineTouchListener_v5 implements View.OnTouchListener{
2016-05-09 14:03:50 +00:00
// Touch events
public boolean onTouch(View v, MotionEvent event)
{
final int touchDevId = event.getDeviceId();
final int pointerCount = event.getPointerCount();
int action = event.getActionMasked();
int pointerFingerId;
int mouseButton;
int i = -1;
float x,y;
switch(action) {
case MotionEvent.ACTION_MOVE:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i);
y = event.getY(i);
XashActivity.nativeTouch(pointerFingerId, 2, x, y);
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_DOWN:
// Primary pointer up/down, the index is always zero
i = 0;
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);
y = event.getY(i);
if( action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_POINTER_UP )
XashActivity.nativeTouch(pointerFingerId,1, x, y);
if( action == MotionEvent.ACTION_DOWN || action == MotionEvent.ACTION_POINTER_DOWN )
XashActivity.nativeTouch(pointerFingerId,0, x, y);
break;
case MotionEvent.ACTION_CANCEL:
for (i = 0; i < pointerCount; i++) {
pointerFingerId = event.getPointerId(i);
x = event.getX(i);
y = event.getY(i);
XashActivity.nativeTouch(pointerFingerId, 1, x, y);
}
break;
default:
break;
}
return true;
2016-05-04 21:02:09 +00:00
}
2016-05-09 14:03:50 +00:00
}
2016-05-09 15:05:28 +00:00
class AndroidBug5497Workaround {
// For more information, see https://code.google.com/p/android/issues/detail?id=5497
// To use this class, simply invoke assistActivity() on an Activity that already has its content view set.
public static void assistActivity (Activity activity) {
new AndroidBug5497Workaround(activity);
}
private View mChildOfContent;
private int usableHeightPrevious;
private FrameLayout.LayoutParams frameLayoutParams;
private AndroidBug5497Workaround(Activity activity) {
FrameLayout content = (FrameLayout) activity.findViewById(android.R.id.content);
mChildOfContent = content.getChildAt(0);
mChildOfContent.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
public void onGlobalLayout() {
possiblyResizeChildOfContent();
}
});
frameLayoutParams = (FrameLayout.LayoutParams) mChildOfContent.getLayoutParams();
}
private void possiblyResizeChildOfContent() {
int usableHeightNow = computeUsableHeight();
if (usableHeightNow != usableHeightPrevious) {
int usableHeightSansKeyboard = mChildOfContent.getRootView().getHeight();
int heightDifference = usableHeightSansKeyboard - usableHeightNow;
if (heightDifference > (usableHeightSansKeyboard/4)) {
// keyboard probably just became visible
frameLayoutParams.height = usableHeightSansKeyboard - heightDifference;
} else {
// keyboard probably just became hidden
frameLayoutParams.height = usableHeightSansKeyboard;
}
mChildOfContent.requestLayout();
usableHeightPrevious = usableHeightNow;
}
}
private int computeUsableHeight() {
Rect r = new Rect();
mChildOfContent.getWindowVisibleDisplayFrame(r);
return (r.bottom - r.top);
}
}