Refactor XashActivity, fix crash in XashService, add compat wrappers
This commit is contained in:
parent
ac0e9b633d
commit
8602bd4e9e
5 changed files with 747 additions and 689 deletions
|
@ -60,6 +60,12 @@ public class LauncherActivity extends Activity
|
|||
|
||||
setContentView(R.layout.activity_launcher);
|
||||
|
||||
if( sdk > 17 )
|
||||
{
|
||||
ImageView icon = (ImageView) findViewById(R.id.launcherIcon);
|
||||
icon.setImageDrawable(getResources().getDrawable(R.mipmap.ic_launcher));
|
||||
}
|
||||
|
||||
TabHost tabHost = (TabHost) findViewById(R.id.tabhost);
|
||||
|
||||
tabHost.setup();
|
||||
|
@ -264,12 +270,11 @@ public class LauncherActivity extends Activity
|
|||
hideRodirSettings( !useRoDir.isChecked() );
|
||||
updateResolutionResult();
|
||||
toggleResolutionFields();
|
||||
FWGSLib.applyPermissions( this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, REQUEST_PERMISSIONS );
|
||||
FWGSLib.cmp.applyPermissions( this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, REQUEST_PERMISSIONS );
|
||||
if( !mPref.getBoolean("successfulRun",false) )
|
||||
showFirstRun();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults )
|
||||
{
|
||||
if( requestCode == REQUEST_PERMISSIONS )
|
||||
|
@ -434,6 +439,12 @@ public class LauncherActivity extends Activity
|
|||
dialog.setContentView(R.layout.about);
|
||||
dialog.setCancelable(true);
|
||||
dialog.show();
|
||||
if( sdk > 17 )
|
||||
{
|
||||
ImageView icon = (ImageView) dialog.findViewById(R.id.aboutIcon);
|
||||
icon.setImageDrawable(getResources().getDrawable(R.mipmap.ic_launcher));
|
||||
}
|
||||
|
||||
TextView tView6 = (TextView) dialog.findViewById(R.id.textView6);
|
||||
tView6.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
((Button)dialog.findViewById( R.id.button_about_ok )).setOnClickListener(new View.OnClickListener(){
|
||||
|
|
|
@ -32,7 +32,7 @@ import java.security.MessageDigest;
|
|||
|
||||
import su.xash.engine.R;
|
||||
import su.xash.engine.XashConfig;
|
||||
import su.xash.engine.JoystickHandler;
|
||||
import su.xash.engine.XashInput;
|
||||
import android.provider.Settings.Secure;
|
||||
import android.Manifest;
|
||||
|
||||
|
@ -57,8 +57,7 @@ public class XashActivity extends Activity {
|
|||
public static final int sdk = Integer.valueOf( Build.VERSION.SDK );
|
||||
public static final String TAG = "XASH3D:XashActivity";
|
||||
public static int mPixelFormat;
|
||||
public static JoystickHandler handler;
|
||||
public static ImmersiveMode mImmersiveMode;
|
||||
public static XashInput.JoystickHandler handler;
|
||||
public static boolean keyboardVisible = false;
|
||||
public static boolean mEngineReady = false;
|
||||
public static boolean mEnginePaused = false;
|
||||
|
@ -110,6 +109,7 @@ public class XashActivity extends Activity {
|
|||
{
|
||||
Log.v( TAG, "onCreate()" );
|
||||
super.onCreate( savedInstanceState );
|
||||
|
||||
mEngineReady = false;
|
||||
|
||||
if( sdk >= 8 && CertCheck.dumbAntiPDALifeCheck( this ) )
|
||||
|
@ -137,7 +137,7 @@ public class XashActivity extends Activity {
|
|||
mUseRoDir = mPref.getBoolean("use_rodir", false);
|
||||
mWriteDir = mPref.getString("writedir", FWGSLib.getExternalFilesDir( this ));
|
||||
|
||||
FWGSLib.applyPermissions( this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, REQUEST_PERMISSIONS );
|
||||
FWGSLib.cmp.applyPermissions( this, new String[] { Manifest.permission.WRITE_EXTERNAL_STORAGE }, REQUEST_PERMISSIONS );
|
||||
|
||||
// just in case
|
||||
if( mWriteDir.length() == 0 )
|
||||
|
@ -162,7 +162,6 @@ public class XashActivity extends Activity {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRequestPermissionsResult( int requestCode, String[] permissions, int[] grantResults )
|
||||
{
|
||||
if( requestCode == REQUEST_PERMISSIONS )
|
||||
|
@ -294,10 +293,7 @@ public class XashActivity extends Activity {
|
|||
|
||||
super.onWindowFocusChanged( hasFocus );
|
||||
|
||||
if( mImmersiveMode != null )
|
||||
{
|
||||
mImmersiveMode.apply();
|
||||
}
|
||||
FWGSLib.cmp.applyImmersiveMode(keyboardVisible, mDecorView);
|
||||
}
|
||||
|
||||
public static void setFolderAsk( Context ctx, Boolean b )
|
||||
|
@ -430,14 +426,7 @@ public class XashActivity extends Activity {
|
|||
|
||||
SurfaceHolder holder = mSurface.getHolder();
|
||||
holder.setType( SurfaceHolder.SURFACE_TYPE_GPU );
|
||||
|
||||
if( sdk >= 14 )
|
||||
handler = new JoystickHandler_v14();
|
||||
else if( sdk >= 12 )
|
||||
handler = new JoystickHandler_v12();
|
||||
else
|
||||
handler = new JoystickHandler();
|
||||
handler.init();
|
||||
handler = XashInput.getJoystickHandler();
|
||||
|
||||
mVibrator = ( Vibrator )getSystemService( Context.VIBRATOR_SERVICE );
|
||||
mHasVibrator = handler.hasVibrator() && (mVibrator != null);
|
||||
|
@ -446,14 +435,8 @@ public class XashActivity extends Activity {
|
|||
mUseVolume = mPref.getBoolean( "usevolume", false );
|
||||
if( mPref.getBoolean( "enableResizeWorkaround", true ) )
|
||||
AndroidBug5497Workaround.assistActivity( this );
|
||||
|
||||
// Immersive Mode is available only at >KitKat
|
||||
Boolean enableImmersive = ( sdk >= 19 ) && ( mPref.getBoolean( "immersive_mode", true ) );
|
||||
if( enableImmersive )
|
||||
mImmersiveMode = new ImmersiveMode_v19();
|
||||
else mImmersiveMode = new ImmersiveMode();
|
||||
|
||||
mDecorView = getWindow().getDecorView();
|
||||
if( XashActivity.mPref.getBoolean( "immersive_mode", false ) )
|
||||
mDecorView = getWindow().getDecorView();
|
||||
|
||||
if( mPref.getBoolean( "resolution_fixed", false ) )
|
||||
{
|
||||
|
@ -480,11 +463,7 @@ public class XashActivity extends Activity {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( sdk >= Build.VERSION_CODES.O )
|
||||
startForegroundService( new Intent( getBaseContext(), XashService.class ) );
|
||||
else if( sdk >= 5 )
|
||||
startService( new Intent( getBaseContext(), XashService.class ) );
|
||||
FWGSLib.cmp.startForegroundService( this, new Intent( getBaseContext(), XashService.class ) );
|
||||
|
||||
mEngineReady = true;
|
||||
}
|
||||
|
@ -494,18 +473,7 @@ public class XashActivity extends Activity {
|
|||
{
|
||||
Intent intent = getIntent();
|
||||
|
||||
String enginedir;
|
||||
|
||||
try
|
||||
{
|
||||
ApplicationInfo ai = FWGSLib.getApplicationInfo(this, null, 0);
|
||||
enginedir = ai.nativeLibraryDir;
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
enginedir = getFilesDir().getParentFile().getPath() + "/lib";
|
||||
}
|
||||
String enginedir = FWGSLib.cmp.getNativeLibDir(this);
|
||||
|
||||
String argv = FWGSLib.getStringExtraFromIntent( intent, "argv", mPref.getString( "argv", "-dev 3 -log" ) );
|
||||
String gamelibdir = FWGSLib.getStringExtraFromIntent( intent, "gamelibdir", enginedir );
|
||||
|
@ -920,16 +888,14 @@ public class XashActivity extends Activity {
|
|||
|
||||
imm.showSoftInput( mTextEdit, 0 );
|
||||
keyboardVisible = true;
|
||||
if( XashActivity.mImmersiveMode != null )
|
||||
XashActivity.mImmersiveMode.apply();
|
||||
FWGSLib.cmp.applyImmersiveMode( keyboardVisible, mDecorView );
|
||||
}
|
||||
else
|
||||
{
|
||||
mTextEdit.setVisibility( View.GONE );
|
||||
imm.hideSoftInputFromWindow( mTextEdit.getWindowToken(), 0 );
|
||||
keyboardVisible = false;
|
||||
if( XashActivity.mImmersiveMode != null )
|
||||
XashActivity.mImmersiveMode.apply();
|
||||
FWGSLib.cmp.applyImmersiveMode( keyboardVisible, mDecorView );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1050,18 +1016,6 @@ public class XashActivity extends Activity {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Simple nativeInit() runnable
|
||||
*/
|
||||
class XashMain implements Runnable
|
||||
{
|
||||
public void run()
|
||||
{
|
||||
XashActivity.nativeInit( XashActivity.mArgv );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
EngineSurface. This is what we draw on, so we need to know when it's created
|
||||
in order to do anything useful.
|
||||
|
@ -1096,10 +1050,7 @@ class EngineSurface extends SurfaceView implements SurfaceHolder.Callback, View.
|
|||
setFocusableInTouchMode( true );
|
||||
requestFocus();
|
||||
setOnKeyListener( this );
|
||||
if( XashActivity.sdk >= 5 )
|
||||
setOnTouchListener( new EngineTouchListener_v5() );
|
||||
else
|
||||
setOnTouchListener( new EngineTouchListener_v1() );
|
||||
setOnTouchListener( XashInput.getTouchListener() );
|
||||
}
|
||||
|
||||
// Called when we have a valid drawing surface
|
||||
|
@ -1161,7 +1112,13 @@ class EngineSurface extends SurfaceView implements SurfaceHolder.Callback, View.
|
|||
// Now start up the C app thread
|
||||
if( mEngThread == null )
|
||||
{
|
||||
mEngThread = new Thread( new XashMain(), "EngineThread" );
|
||||
mEngThread = new Thread( new Runnable(){
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
XashActivity.nativeInit( XashActivity.mArgv );
|
||||
}
|
||||
}, "EngineThread" );
|
||||
mEngThread.start();
|
||||
}
|
||||
resizing = false;
|
||||
|
@ -1381,214 +1338,6 @@ class EngineSurface extends SurfaceView implements SurfaceHolder.Callback, View.
|
|||
|
||||
}
|
||||
|
||||
/* 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 ) )
|
||||
return true;
|
||||
return super.sendKeyEvent( event );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commitText( CharSequence text, int newCursorPosition )
|
||||
{
|
||||
// nativeCommitText(text.toString(), newCursorPosition);
|
||||
if( text.toString().equals( "\n" ) )
|
||||
{
|
||||
XashActivity.nativeKey( 1, KeyEvent.KEYCODE_ENTER );
|
||||
XashActivity.nativeKey( 0, KeyEvent.KEYCODE_ENTER );
|
||||
}
|
||||
XashActivity.nativeString( text.toString() );
|
||||
|
||||
return super.commitText( text, newCursorPosition );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComposingText( CharSequence text, int newCursorPosition )
|
||||
{
|
||||
// a1batross:
|
||||
// This method is intended to show composed text immediately
|
||||
// that after will be replaced by text from "commitText" method
|
||||
// Just leaving this unimplemented fixes "twice" input on T9/Swype-like keyboards
|
||||
|
||||
//ativeSetComposingText(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
|
||||
// and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
|
||||
if( beforeLength > 0 && afterLength == 0 )
|
||||
{
|
||||
boolean ret = true;
|
||||
// backspace(s)
|
||||
while( beforeLength-- > 0 )
|
||||
{
|
||||
boolean ret_key = sendKeyEvent( new KeyEvent( KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL ) )
|
||||
&& sendKeyEvent( new KeyEvent( KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL ) );
|
||||
ret = ret && ret_key;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return super.deleteSurroundingText(beforeLength, afterLength);
|
||||
}
|
||||
}
|
||||
class EngineTouchListener_v1 implements View.OnTouchListener
|
||||
{
|
||||
// Touch events
|
||||
public boolean onTouch( View v, MotionEvent event )
|
||||
{
|
||||
XashActivity.nativeTouch( 0, event.getAction(), event.getX(), event.getY() );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class EngineTouchListener_v5 implements View.OnTouchListener
|
||||
{
|
||||
float lx = 0, ly = 0;
|
||||
boolean secondarypressed = false;
|
||||
|
||||
// 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, mouseButton, i = -1;
|
||||
float x, y;
|
||||
|
||||
switch( action )
|
||||
{
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if( ( !XashActivity.fMouseShown ) && ( ( XashActivity.handler.getSource( event ) & InputDevice.SOURCE_MOUSE ) == InputDevice.SOURCE_MOUSE ) )
|
||||
{
|
||||
x = event.getX();
|
||||
y = event.getY();
|
||||
|
||||
XashActivity.nativeMouseMove( x - lx, y - ly );
|
||||
lx = x;
|
||||
ly = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
for( i = 0; i < pointerCount; i++ )
|
||||
{
|
||||
pointerFingerId = event.getPointerId( i );
|
||||
x = event.getX( i ) * XashActivity.mTouchScaleX;
|
||||
y = event.getY( i ) * XashActivity.mTouchScaleY;
|
||||
XashActivity.nativeTouch( pointerFingerId, 2, x, y );
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if( !XashActivity.fMouseShown && ( ( XashActivity.handler.getSource( event ) & InputDevice.SOURCE_MOUSE ) == InputDevice.SOURCE_MOUSE ) )
|
||||
{
|
||||
lx = event.getX();
|
||||
ly = event.getY();
|
||||
boolean down = ( action == MotionEvent.ACTION_DOWN ) || ( action == MotionEvent.ACTION_POINTER_DOWN );
|
||||
int buttonState = XashActivity.handler.getButtonState( event );
|
||||
if( down && ( buttonState & MotionEvent.BUTTON_SECONDARY ) != 0 )
|
||||
{
|
||||
XashActivity.nativeKey( 1, -243 );
|
||||
secondarypressed = true;
|
||||
return true;
|
||||
}
|
||||
else if( !down && secondarypressed && ( buttonState & MotionEvent.BUTTON_SECONDARY ) == 0 )
|
||||
{
|
||||
secondarypressed = false;
|
||||
XashActivity.nativeKey( 0, -243 );
|
||||
return true;
|
||||
}
|
||||
XashActivity.nativeKey( down ? 1 : 0, -241 );
|
||||
return true;
|
||||
}
|
||||
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 ) * XashActivity.mTouchScaleX;
|
||||
y = event.getY( i ) * XashActivity.mTouchScaleY;
|
||||
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 ) * XashActivity.mTouchScaleX;
|
||||
y = event.getY( i ) * XashActivity.mTouchScaleY;
|
||||
XashActivity.nativeTouch( pointerFingerId, 1, x, y );
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class AndroidBug5497Workaround
|
||||
{
|
||||
// For more information, see https://code.google.com/p/android/issues/detail?id=5497
|
||||
|
@ -1637,8 +1386,7 @@ class AndroidBug5497Workaround
|
|||
XashActivity.keyboardVisible = false;
|
||||
}
|
||||
|
||||
if( XashActivity.mImmersiveMode != null )
|
||||
XashActivity.mImmersiveMode.apply();
|
||||
FWGSLib.cmp.applyImmersiveMode( XashActivity.keyboardVisible, XashActivity.mDecorView );
|
||||
|
||||
mChildOfContent.requestLayout();
|
||||
usableHeightPrevious = usableHeightNow;
|
||||
|
@ -1652,376 +1400,3 @@ class AndroidBug5497Workaround
|
|||
return r.bottom - r.top;
|
||||
}
|
||||
}
|
||||
|
||||
class ImmersiveMode
|
||||
{
|
||||
void apply()
|
||||
{
|
||||
//stub
|
||||
}
|
||||
}
|
||||
|
||||
class ImmersiveMode_v19 extends ImmersiveMode
|
||||
{
|
||||
@Override
|
||||
void apply()
|
||||
{
|
||||
if( !XashActivity.keyboardVisible )
|
||||
XashActivity.mDecorView.setSystemUiVisibility(
|
||||
0x00000100 // View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| 0x00000200 // View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| 0x00000400 // View.SYSTEM_UI_FLAG_LAYOUT_FULSCREEN
|
||||
| 0x00000002 // View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
|
||||
| 0x00000004 // View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
|
||||
| 0x00001000 // View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
);
|
||||
else
|
||||
XashActivity.mDecorView.setSystemUiVisibility( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
class JoystickHandler
|
||||
{
|
||||
public int getSource( KeyEvent event )
|
||||
{
|
||||
return InputDevice.SOURCE_UNKNOWN;
|
||||
}
|
||||
|
||||
public int getSource( MotionEvent event )
|
||||
{
|
||||
return InputDevice.SOURCE_UNKNOWN;
|
||||
}
|
||||
|
||||
public boolean handleAxis( MotionEvent event )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isGamepadButton( int keyCode )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public String keyCodeToString( int keyCode )
|
||||
{
|
||||
return String.valueOf( keyCode );
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
}
|
||||
|
||||
public boolean hasVibrator()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showMouse( boolean show )
|
||||
{
|
||||
}
|
||||
|
||||
public int getButtonState( MotionEvent event )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
class Wrap_NVMouseExtensions
|
||||
{
|
||||
private static Object inputManager;
|
||||
private static Method mInputManager_setCursorVisibility;
|
||||
private static Method mView_setPointerIcon;
|
||||
private static Class mPointerIcon;
|
||||
private static Object mEmptyIcon;
|
||||
public static int nMotionEvent_AXIS_RELATIVE_X = 0;
|
||||
public static int nMotionEvent_AXIS_RELATIVE_Y = 0;
|
||||
|
||||
//**************************************************************************
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
mInputManager_setCursorVisibility =
|
||||
Class.forName( "android.hardware.input.InputManager" ).getMethod( "setCursorVisibility", boolean.class );
|
||||
|
||||
inputManager = XashActivity.mSingleton.getSystemService( "input" );
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
try
|
||||
{
|
||||
mPointerIcon=Class.forName("android.view.PointerIcon");
|
||||
mEmptyIcon = mPointerIcon.getDeclaredMethod("getSystemIcon",android.content.Context.class, int.class).invoke(null,XashActivity.mSingleton.getContext(),0);
|
||||
mView_setPointerIcon = View.class.getMethod("setPointerIcon",mPointerIcon);
|
||||
}
|
||||
catch( Exception ex1 )
|
||||
{
|
||||
ex1.printStackTrace();
|
||||
}
|
||||
}
|
||||
/* DO THE SAME FOR RELATIVEY */
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
public static void checkAvailable() throws Exception
|
||||
{
|
||||
Field fieldMotionEvent_AXIS_RELATIVE_X = MotionEvent.class.getField( "AXIS_RELATIVE_X" );
|
||||
nMotionEvent_AXIS_RELATIVE_X = ( Integer )fieldMotionEvent_AXIS_RELATIVE_X.get( null );
|
||||
Field fieldMotionEvent_AXIS_RELATIVE_Y = MotionEvent.class.getField( "AXIS_RELATIVE_Y" );
|
||||
nMotionEvent_AXIS_RELATIVE_Y = ( Integer )fieldMotionEvent_AXIS_RELATIVE_Y.get( null );
|
||||
}
|
||||
|
||||
static void setPointerIcon( View view, boolean fVisibility )
|
||||
{
|
||||
Log.v("XashInput", "SET CURSOR VISIBILITY " + fVisibility + " obj " + mEmptyIcon.toString() );
|
||||
try
|
||||
{
|
||||
mView_setPointerIcon.invoke(view,fVisibility?null:mEmptyIcon);
|
||||
}
|
||||
catch( Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
static void setGroupPointerIcon( ViewGroup parent, boolean fVisibility )
|
||||
{
|
||||
for( int i = parent.getChildCount() - 1; i >= 0; i-- )
|
||||
{
|
||||
try
|
||||
{
|
||||
final View child = parent.getChildAt(i);
|
||||
|
||||
if( child == null )
|
||||
continue;
|
||||
|
||||
if( child instanceof ViewGroup )
|
||||
{
|
||||
setGroupPointerIcon((ViewGroup) child, fVisibility);
|
||||
}
|
||||
setPointerIcon( child, fVisibility);
|
||||
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
public static void setCursorVisibility( boolean fVisibility )
|
||||
{
|
||||
try
|
||||
{
|
||||
mInputManager_setCursorVisibility.invoke( inputManager, fVisibility );
|
||||
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
try
|
||||
{
|
||||
ViewGroup rootViewGroup = (ViewGroup) XashActivity.mSingleton.getWindow().getDecorView();
|
||||
setGroupPointerIcon(rootViewGroup, fVisibility);
|
||||
setGroupPointerIcon((ViewGroup)XashActivity.mDecorView, fVisibility);
|
||||
for (int i = 0; i < rootViewGroup.getChildCount(); i++) {
|
||||
View view = rootViewGroup.getChildAt(i);
|
||||
setPointerIcon(view, fVisibility);
|
||||
}
|
||||
}
|
||||
catch( Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
public static int getAxisRelativeX()
|
||||
{
|
||||
return nMotionEvent_AXIS_RELATIVE_X;
|
||||
}
|
||||
|
||||
public static int getAxisRelativeY()
|
||||
{
|
||||
return nMotionEvent_AXIS_RELATIVE_Y;
|
||||
}
|
||||
}
|
||||
|
||||
class JoystickHandler_v12 extends JoystickHandler
|
||||
{
|
||||
private static float prevSide, prevFwd, prevYaw, prevPtch, prevLT, prevRT, prevHX, prevHY;
|
||||
|
||||
public static boolean mNVMouseExtensions = false;
|
||||
|
||||
static int mouseId;
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
Wrap_NVMouseExtensions.checkAvailable();
|
||||
mNVMouseExtensions = true;
|
||||
}
|
||||
catch( Throwable t )
|
||||
{
|
||||
mNVMouseExtensions = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
XashActivity.mSurface.setOnGenericMotionListener( new MotionListener() );
|
||||
Log.d( XashActivity.TAG, "mNVMouseExtensions = " + mNVMouseExtensions );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSource( KeyEvent event )
|
||||
{
|
||||
return event.getSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSource( MotionEvent event )
|
||||
{
|
||||
if( event.getDeviceId() == mouseId )
|
||||
return InputDevice.SOURCE_MOUSE;
|
||||
return event.getSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleAxis( MotionEvent event )
|
||||
{
|
||||
// how event can be from null device, Android?
|
||||
final InputDevice device = event.getDevice();
|
||||
if( device == null )
|
||||
return false;
|
||||
|
||||
// maybe I need to cache this...
|
||||
for( InputDevice.MotionRange range: device.getMotionRanges() )
|
||||
{
|
||||
// normalize in -1.0..1.0 (copied from SDL2)
|
||||
final float cur = ( event.getAxisValue( range.getAxis(), event.getActionIndex() ) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
|
||||
final float dead = range.getFlat(); // get axis dead zone
|
||||
switch( range.getAxis() )
|
||||
{
|
||||
// typical axes
|
||||
// move
|
||||
case MotionEvent.AXIS_X:
|
||||
prevSide = XashActivity.performEngineAxisEvent( cur, XashActivity.JOY_AXIS_SIDE, prevSide, dead );
|
||||
break;
|
||||
case MotionEvent.AXIS_Y:
|
||||
prevFwd = XashActivity.performEngineAxisEvent( cur, XashActivity.JOY_AXIS_FWD, prevFwd, dead );
|
||||
break;
|
||||
|
||||
// rotate. Invert, so by default this works as it's should
|
||||
case MotionEvent.AXIS_Z:
|
||||
prevPtch = XashActivity.performEngineAxisEvent( -cur, XashActivity.JOY_AXIS_PITCH, prevPtch, dead );
|
||||
break;
|
||||
case MotionEvent.AXIS_RZ:
|
||||
prevYaw = XashActivity.performEngineAxisEvent( -cur, XashActivity.JOY_AXIS_YAW, prevYaw, dead );
|
||||
break;
|
||||
|
||||
// trigger
|
||||
case MotionEvent.AXIS_RTRIGGER:
|
||||
prevLT = XashActivity.performEngineAxisEvent( cur, XashActivity.JOY_AXIS_RT, prevLT, dead );
|
||||
break;
|
||||
case MotionEvent.AXIS_LTRIGGER:
|
||||
prevRT = XashActivity.performEngineAxisEvent( cur, XashActivity.JOY_AXIS_LT, prevRT, dead );
|
||||
break;
|
||||
|
||||
// hats
|
||||
case MotionEvent.AXIS_HAT_X:
|
||||
prevHX = XashActivity.performEngineHatEvent( cur, true, prevHX );
|
||||
break;
|
||||
case MotionEvent.AXIS_HAT_Y:
|
||||
prevHY = XashActivity.performEngineHatEvent( cur, false, prevHY );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGamepadButton( int keyCode )
|
||||
{
|
||||
return KeyEvent.isGamepadButton( keyCode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String keyCodeToString( int keyCode )
|
||||
{
|
||||
return KeyEvent.keyCodeToString( keyCode );
|
||||
}
|
||||
|
||||
class MotionListener implements View.OnGenericMotionListener
|
||||
{
|
||||
@Override
|
||||
public boolean onGenericMotion( View view, MotionEvent event )
|
||||
{
|
||||
final int source = XashActivity.handler.getSource( event );
|
||||
|
||||
if( FWGSLib.FExactBitSet( source, InputDevice.SOURCE_GAMEPAD ) ||
|
||||
FWGSLib.FExactBitSet( source, InputDevice.SOURCE_CLASS_JOYSTICK ) )
|
||||
return XashActivity.handler.handleAxis( event );
|
||||
|
||||
if( mNVMouseExtensions )
|
||||
{
|
||||
float x = event.getAxisValue( Wrap_NVMouseExtensions.getAxisRelativeX(), 0 );
|
||||
float y = event.getAxisValue( Wrap_NVMouseExtensions.getAxisRelativeY(), 0 );
|
||||
if( !FWGSLib.FExactBitSet( source, InputDevice.SOURCE_MOUSE) && (x != 0 || y != 0 ))
|
||||
mouseId = event.getDeviceId();
|
||||
|
||||
switch( event.getAction() )
|
||||
{
|
||||
case MotionEvent.ACTION_SCROLL:
|
||||
if( event.getAxisValue( MotionEvent.AXIS_VSCROLL ) < 0.0f )
|
||||
{
|
||||
XashActivity.nativeKey( 1, -239 );
|
||||
XashActivity.nativeKey( 0, -239 );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
XashActivity.nativeKey( 1, -240 );
|
||||
XashActivity.nativeKey( 0, -240 );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
XashActivity.nativeMouseMove( x, y );
|
||||
// Log.v("XashInput", "MouseMove: " +x + " " + y );
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Add it someday
|
||||
// else if( (event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == InputDevice.SOURCE_CLASS_TRACKBALL )
|
||||
// return XashActivity.handleBall( event );
|
||||
//return super.onGenericMotion( view, event );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasVibrator()
|
||||
{
|
||||
if( XashActivity.mVibrator != null )
|
||||
return XashActivity.mVibrator.hasVibrator();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMouse( boolean show )
|
||||
{
|
||||
if( mNVMouseExtensions )
|
||||
Wrap_NVMouseExtensions.setCursorVisibility( show );
|
||||
}
|
||||
}
|
||||
|
||||
class JoystickHandler_v14 extends JoystickHandler_v12
|
||||
{
|
||||
@Override
|
||||
public int getButtonState( MotionEvent event )
|
||||
{
|
||||
return event.getButtonState();
|
||||
}
|
||||
}
|
||||
|
|
614
android/src/su/xash/engine/XashInput.java
Normal file
614
android/src/su/xash/engine/XashInput.java
Normal file
|
@ -0,0 +1,614 @@
|
|||
|
||||
|
||||
|
||||
package su.xash.engine;
|
||||
import java.lang.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
import android.app.*;
|
||||
import android.content.*;
|
||||
import android.view.*;
|
||||
import android.os.*;
|
||||
import android.util.*;
|
||||
import android.graphics.*;
|
||||
import android.text.method.*;
|
||||
import android.text.*;
|
||||
import android.media.*;
|
||||
import android.hardware.*;
|
||||
import android.content.*;
|
||||
import android.widget.*;
|
||||
import android.content.pm.*;
|
||||
import android.net.Uri;
|
||||
import android.provider.*;
|
||||
import android.view.inputmethod.*;
|
||||
import su.xash.fwgslib.*;
|
||||
|
||||
|
||||
|
||||
|
||||
public class XashInput
|
||||
{
|
||||
public static JoystickHandler getJoystickHandler()
|
||||
{
|
||||
JoystickHandler handler;
|
||||
|
||||
if( FWGSLib.sdk >= 14 )
|
||||
handler = new JoystickHandler_v14();
|
||||
else if( FWGSLib.sdk >= 12 )
|
||||
handler = new JoystickHandler_v12();
|
||||
else
|
||||
handler = new JoystickHandler();
|
||||
handler.init();
|
||||
return handler;
|
||||
}
|
||||
|
||||
|
||||
public static class JoystickHandler
|
||||
{
|
||||
public int getSource( KeyEvent event )
|
||||
{
|
||||
return InputDevice.SOURCE_UNKNOWN;
|
||||
}
|
||||
|
||||
public int getSource( MotionEvent event )
|
||||
{
|
||||
return InputDevice.SOURCE_UNKNOWN;
|
||||
}
|
||||
|
||||
public boolean handleAxis( MotionEvent event )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isGamepadButton( int keyCode )
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public String keyCodeToString( int keyCode )
|
||||
{
|
||||
return String.valueOf( keyCode );
|
||||
}
|
||||
|
||||
public void init()
|
||||
{
|
||||
}
|
||||
|
||||
public boolean hasVibrator()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showMouse( boolean show )
|
||||
{
|
||||
}
|
||||
|
||||
public int getButtonState( MotionEvent event )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static class JoystickHandler_v12 extends JoystickHandler
|
||||
{
|
||||
private static float prevSide, prevFwd, prevYaw, prevPtch, prevLT, prevRT, prevHX, prevHY;
|
||||
|
||||
public static boolean mNVMouseExtensions = false;
|
||||
|
||||
static int mouseId;
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
Wrap_NVMouseExtensions.checkAvailable();
|
||||
mNVMouseExtensions = true;
|
||||
}
|
||||
catch( Throwable t )
|
||||
{
|
||||
mNVMouseExtensions = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
XashActivity.mSurface.setOnGenericMotionListener( new MotionListener() );
|
||||
Log.d( XashActivity.TAG, "mNVMouseExtensions = " + mNVMouseExtensions );
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSource( KeyEvent event )
|
||||
{
|
||||
return event.getSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSource( MotionEvent event )
|
||||
{
|
||||
if( event.getDeviceId() == mouseId )
|
||||
return InputDevice.SOURCE_MOUSE;
|
||||
return event.getSource();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean handleAxis( MotionEvent event )
|
||||
{
|
||||
// how event can be from null device, Android?
|
||||
final InputDevice device = event.getDevice();
|
||||
if( device == null )
|
||||
return false;
|
||||
|
||||
// maybe I need to cache this...
|
||||
for( InputDevice.MotionRange range: device.getMotionRanges() )
|
||||
{
|
||||
// normalize in -1.0..1.0 (copied from SDL2)
|
||||
final float cur = ( event.getAxisValue( range.getAxis(), event.getActionIndex() ) - range.getMin() ) / range.getRange() * 2.0f - 1.0f;
|
||||
final float dead = range.getFlat(); // get axis dead zone
|
||||
switch( range.getAxis() )
|
||||
{
|
||||
// typical axes
|
||||
// move
|
||||
case MotionEvent.AXIS_X:
|
||||
prevSide = XashActivity.performEngineAxisEvent( cur, XashActivity.JOY_AXIS_SIDE, prevSide, dead );
|
||||
break;
|
||||
case MotionEvent.AXIS_Y:
|
||||
prevFwd = XashActivity.performEngineAxisEvent( cur, XashActivity.JOY_AXIS_FWD, prevFwd, dead );
|
||||
break;
|
||||
|
||||
// rotate. Invert, so by default this works as it's should
|
||||
case MotionEvent.AXIS_Z:
|
||||
prevPtch = XashActivity.performEngineAxisEvent( -cur, XashActivity.JOY_AXIS_PITCH, prevPtch, dead );
|
||||
break;
|
||||
case MotionEvent.AXIS_RZ:
|
||||
prevYaw = XashActivity.performEngineAxisEvent( -cur, XashActivity.JOY_AXIS_YAW, prevYaw, dead );
|
||||
break;
|
||||
|
||||
// trigger
|
||||
case MotionEvent.AXIS_RTRIGGER:
|
||||
prevLT = XashActivity.performEngineAxisEvent( cur, XashActivity.JOY_AXIS_RT, prevLT, dead );
|
||||
break;
|
||||
case MotionEvent.AXIS_LTRIGGER:
|
||||
prevRT = XashActivity.performEngineAxisEvent( cur, XashActivity.JOY_AXIS_LT, prevRT, dead );
|
||||
break;
|
||||
|
||||
// hats
|
||||
case MotionEvent.AXIS_HAT_X:
|
||||
prevHX = XashActivity.performEngineHatEvent( cur, true, prevHX );
|
||||
break;
|
||||
case MotionEvent.AXIS_HAT_Y:
|
||||
prevHY = XashActivity.performEngineHatEvent( cur, false, prevHY );
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGamepadButton( int keyCode )
|
||||
{
|
||||
return KeyEvent.isGamepadButton( keyCode );
|
||||
}
|
||||
|
||||
@Override
|
||||
public String keyCodeToString( int keyCode )
|
||||
{
|
||||
return KeyEvent.keyCodeToString( keyCode );
|
||||
}
|
||||
|
||||
class MotionListener implements View.OnGenericMotionListener
|
||||
{
|
||||
@Override
|
||||
public boolean onGenericMotion( View view, MotionEvent event )
|
||||
{
|
||||
final int source = XashActivity.handler.getSource( event );
|
||||
|
||||
if( FWGSLib.FExactBitSet( source, InputDevice.SOURCE_GAMEPAD ) ||
|
||||
FWGSLib.FExactBitSet( source, InputDevice.SOURCE_CLASS_JOYSTICK ) )
|
||||
return XashActivity.handler.handleAxis( event );
|
||||
|
||||
if( mNVMouseExtensions )
|
||||
{
|
||||
float x = event.getAxisValue( Wrap_NVMouseExtensions.getAxisRelativeX(), 0 );
|
||||
float y = event.getAxisValue( Wrap_NVMouseExtensions.getAxisRelativeY(), 0 );
|
||||
if( !FWGSLib.FExactBitSet( source, InputDevice.SOURCE_MOUSE) && (x != 0 || y != 0 ))
|
||||
mouseId = event.getDeviceId();
|
||||
|
||||
switch( event.getAction() )
|
||||
{
|
||||
case MotionEvent.ACTION_SCROLL:
|
||||
if( event.getAxisValue( MotionEvent.AXIS_VSCROLL ) < 0.0f )
|
||||
{
|
||||
XashActivity.nativeKey( 1, -239 );
|
||||
XashActivity.nativeKey( 0, -239 );
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
XashActivity.nativeKey( 1, -240 );
|
||||
XashActivity.nativeKey( 0, -240 );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
XashActivity.nativeMouseMove( x, y );
|
||||
// Log.v("XashInput", "MouseMove: " +x + " " + y );
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO: Add it someday
|
||||
// else if( (event.getSource() & InputDevice.SOURCE_CLASS_TRACKBALL) == InputDevice.SOURCE_CLASS_TRACKBALL )
|
||||
// return XashActivity.handleBall( event );
|
||||
//return super.onGenericMotion( view, event );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasVibrator()
|
||||
{
|
||||
if( XashActivity.mVibrator != null )
|
||||
return XashActivity.mVibrator.hasVibrator();
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void showMouse( boolean show )
|
||||
{
|
||||
if( mNVMouseExtensions )
|
||||
Wrap_NVMouseExtensions.setCursorVisibility( show );
|
||||
}
|
||||
}
|
||||
|
||||
static class JoystickHandler_v14 extends JoystickHandler_v12
|
||||
{
|
||||
@Override
|
||||
public int getButtonState( MotionEvent event )
|
||||
{
|
||||
return event.getButtonState();
|
||||
}
|
||||
}
|
||||
|
||||
public static View.OnTouchListener getTouchListener()
|
||||
{
|
||||
if( FWGSLib.sdk >= 5 )
|
||||
return new EngineTouchListener_v5();
|
||||
else
|
||||
return new EngineTouchListener_v1();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class Wrap_NVMouseExtensions
|
||||
{
|
||||
private static Object inputManager;
|
||||
private static Method mInputManager_setCursorVisibility;
|
||||
private static Method mView_setPointerIcon;
|
||||
private static Class mPointerIcon;
|
||||
private static Object mEmptyIcon;
|
||||
public static int nMotionEvent_AXIS_RELATIVE_X = 0;
|
||||
public static int nMotionEvent_AXIS_RELATIVE_Y = 0;
|
||||
|
||||
//**************************************************************************
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
mInputManager_setCursorVisibility =
|
||||
Class.forName( "android.hardware.input.InputManager" ).getMethod( "setCursorVisibility", boolean.class );
|
||||
|
||||
inputManager = XashActivity.mSingleton.getSystemService( "input" );
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
try
|
||||
{
|
||||
mPointerIcon=Class.forName("android.view.PointerIcon");
|
||||
mEmptyIcon = mPointerIcon.getDeclaredMethod("getSystemIcon",android.content.Context.class, int.class).invoke(null,XashActivity.mSingleton.getContext(),0);
|
||||
mView_setPointerIcon = View.class.getMethod("setPointerIcon",mPointerIcon);
|
||||
}
|
||||
catch( Exception ex1 )
|
||||
{
|
||||
ex1.printStackTrace();
|
||||
}
|
||||
}
|
||||
/* DO THE SAME FOR RELATIVEY */
|
||||
}
|
||||
|
||||
//*************************************************************************
|
||||
public static void checkAvailable() throws Exception
|
||||
{
|
||||
Field fieldMotionEvent_AXIS_RELATIVE_X = MotionEvent.class.getField( "AXIS_RELATIVE_X" );
|
||||
nMotionEvent_AXIS_RELATIVE_X = ( Integer )fieldMotionEvent_AXIS_RELATIVE_X.get( null );
|
||||
Field fieldMotionEvent_AXIS_RELATIVE_Y = MotionEvent.class.getField( "AXIS_RELATIVE_Y" );
|
||||
nMotionEvent_AXIS_RELATIVE_Y = ( Integer )fieldMotionEvent_AXIS_RELATIVE_Y.get( null );
|
||||
}
|
||||
|
||||
static void setPointerIcon( View view, boolean fVisibility )
|
||||
{
|
||||
Log.v("XashInput", "SET CURSOR VISIBILITY " + fVisibility + " obj " + mEmptyIcon.toString() );
|
||||
try
|
||||
{
|
||||
mView_setPointerIcon.invoke(view,fVisibility?null:mEmptyIcon);
|
||||
}
|
||||
catch( Exception e)
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
static void setGroupPointerIcon( ViewGroup parent, boolean fVisibility )
|
||||
{
|
||||
for( int i = parent.getChildCount() - 1; i >= 0; i-- )
|
||||
{
|
||||
try
|
||||
{
|
||||
final View child = parent.getChildAt(i);
|
||||
|
||||
if( child == null )
|
||||
continue;
|
||||
|
||||
if( child instanceof ViewGroup )
|
||||
{
|
||||
setGroupPointerIcon((ViewGroup) child, fVisibility);
|
||||
}
|
||||
setPointerIcon( child, fVisibility);
|
||||
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
public static void setCursorVisibility( boolean fVisibility )
|
||||
{
|
||||
try
|
||||
{
|
||||
mInputManager_setCursorVisibility.invoke( inputManager, fVisibility );
|
||||
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
try
|
||||
{
|
||||
ViewGroup rootViewGroup = (ViewGroup) XashActivity.mSingleton.getWindow().getDecorView();
|
||||
setGroupPointerIcon(rootViewGroup, fVisibility);
|
||||
setGroupPointerIcon((ViewGroup)XashActivity.mDecorView, fVisibility);
|
||||
for (int i = 0; i < rootViewGroup.getChildCount(); i++) {
|
||||
View view = rootViewGroup.getChildAt(i);
|
||||
setPointerIcon(view, fVisibility);
|
||||
}
|
||||
}
|
||||
catch( Exception ex)
|
||||
{
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//**************************************************************************
|
||||
public static int getAxisRelativeX()
|
||||
{
|
||||
return nMotionEvent_AXIS_RELATIVE_X;
|
||||
}
|
||||
|
||||
public static int getAxisRelativeY()
|
||||
{
|
||||
return nMotionEvent_AXIS_RELATIVE_Y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
class EngineTouchListener_v1 implements View.OnTouchListener
|
||||
{
|
||||
// Touch events
|
||||
public boolean onTouch( View v, MotionEvent event )
|
||||
{
|
||||
XashActivity.nativeTouch( 0, event.getAction(), event.getX(), event.getY() );
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
class EngineTouchListener_v5 implements View.OnTouchListener
|
||||
{
|
||||
float lx = 0, ly = 0;
|
||||
boolean secondarypressed = false;
|
||||
|
||||
// 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, mouseButton, i = -1;
|
||||
float x, y;
|
||||
|
||||
switch( action )
|
||||
{
|
||||
case MotionEvent.ACTION_MOVE:
|
||||
if( ( !XashActivity.fMouseShown ) && ( ( XashActivity.handler.getSource( event ) & InputDevice.SOURCE_MOUSE ) == InputDevice.SOURCE_MOUSE ) )
|
||||
{
|
||||
x = event.getX();
|
||||
y = event.getY();
|
||||
|
||||
XashActivity.nativeMouseMove( x - lx, y - ly );
|
||||
lx = x;
|
||||
ly = y;
|
||||
return true;
|
||||
}
|
||||
|
||||
for( i = 0; i < pointerCount; i++ )
|
||||
{
|
||||
pointerFingerId = event.getPointerId( i );
|
||||
x = event.getX( i ) * XashActivity.mTouchScaleX;
|
||||
y = event.getY( i ) * XashActivity.mTouchScaleY;
|
||||
XashActivity.nativeTouch( pointerFingerId, 2, x, y );
|
||||
}
|
||||
break;
|
||||
case MotionEvent.ACTION_UP:
|
||||
case MotionEvent.ACTION_DOWN:
|
||||
if( !XashActivity.fMouseShown && ( ( XashActivity.handler.getSource( event ) & InputDevice.SOURCE_MOUSE ) == InputDevice.SOURCE_MOUSE ) )
|
||||
{
|
||||
lx = event.getX();
|
||||
ly = event.getY();
|
||||
boolean down = ( action == MotionEvent.ACTION_DOWN ) || ( action == MotionEvent.ACTION_POINTER_DOWN );
|
||||
int buttonState = XashActivity.handler.getButtonState( event );
|
||||
if( down && ( buttonState & MotionEvent.BUTTON_SECONDARY ) != 0 )
|
||||
{
|
||||
XashActivity.nativeKey( 1, -243 );
|
||||
secondarypressed = true;
|
||||
return true;
|
||||
}
|
||||
else if( !down && secondarypressed && ( buttonState & MotionEvent.BUTTON_SECONDARY ) == 0 )
|
||||
{
|
||||
secondarypressed = false;
|
||||
XashActivity.nativeKey( 0, -243 );
|
||||
return true;
|
||||
}
|
||||
XashActivity.nativeKey( down ? 1 : 0, -241 );
|
||||
return true;
|
||||
}
|
||||
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 ) * XashActivity.mTouchScaleX;
|
||||
y = event.getY( i ) * XashActivity.mTouchScaleY;
|
||||
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 ) * XashActivity.mTouchScaleX;
|
||||
y = event.getY( i ) * XashActivity.mTouchScaleY;
|
||||
XashActivity.nativeTouch( pointerFingerId, 1, x, y );
|
||||
}
|
||||
break;
|
||||
default: break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 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 ) )
|
||||
return true;
|
||||
return super.sendKeyEvent( event );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean commitText( CharSequence text, int newCursorPosition )
|
||||
{
|
||||
// nativeCommitText(text.toString(), newCursorPosition);
|
||||
if( text.toString().equals( "\n" ) )
|
||||
{
|
||||
XashActivity.nativeKey( 1, KeyEvent.KEYCODE_ENTER );
|
||||
XashActivity.nativeKey( 0, KeyEvent.KEYCODE_ENTER );
|
||||
}
|
||||
XashActivity.nativeString( text.toString() );
|
||||
|
||||
return super.commitText( text, newCursorPosition );
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setComposingText( CharSequence text, int newCursorPosition )
|
||||
{
|
||||
// a1batross:
|
||||
// This method is intended to show composed text immediately
|
||||
// that after will be replaced by text from "commitText" method
|
||||
// Just leaving this unimplemented fixes "twice" input on T9/Swype-like keyboards
|
||||
|
||||
//ativeSetComposingText(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
|
||||
// and https://bugzilla.libsdl.org/show_bug.cgi?id=2265
|
||||
if( beforeLength > 0 && afterLength == 0 )
|
||||
{
|
||||
boolean ret = true;
|
||||
// backspace(s)
|
||||
while( beforeLength-- > 0 )
|
||||
{
|
||||
boolean ret_key = sendKeyEvent( new KeyEvent( KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DEL ) )
|
||||
&& sendKeyEvent( new KeyEvent( KeyEvent.ACTION_UP, KeyEvent.KEYCODE_DEL ) );
|
||||
ret = ret && ret_key;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
return super.deleteSurroundingText(beforeLength, afterLength);
|
||||
}
|
||||
}
|
|
@ -32,7 +32,6 @@ import java.security.MessageDigest;
|
|||
|
||||
import su.xash.engine.R;
|
||||
import su.xash.engine.XashConfig;
|
||||
import su.xash.engine.JoystickHandler;
|
||||
|
||||
|
||||
public class XashService extends Service
|
||||
|
@ -64,9 +63,9 @@ public class XashService extends Service
|
|||
{
|
||||
Log.d("XashService", "Service Started");
|
||||
|
||||
not = XashNotification.getXashNotification(this);
|
||||
not = XashNotification.getXashNotification();
|
||||
|
||||
startForeground(not.getId(), not.createNotification());
|
||||
startForeground(not.getId(), not.createNotification(this));
|
||||
|
||||
return START_NOT_STICKY;
|
||||
}
|
||||
|
@ -103,15 +102,11 @@ public class XashService extends Service
|
|||
{
|
||||
public Notification notification;
|
||||
public final int notificationId = 100;
|
||||
public Context ctx;
|
||||
protected Context ctx;
|
||||
|
||||
public XashNotification(Context ctx)
|
||||
{
|
||||
this.ctx = ctx;
|
||||
}
|
||||
|
||||
public Notification createNotification()
|
||||
public Notification createNotification(Context context)
|
||||
{
|
||||
ctx = context;
|
||||
Intent engineIntent = new Intent(ctx, XashActivity.class);
|
||||
engineIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
|
||||
|
@ -133,14 +128,14 @@ public class XashService extends Service
|
|||
public void setIcon(Bitmap bmp)
|
||||
{
|
||||
notification.contentView.setImageViewBitmap( R.id.status_image, bmp );
|
||||
NotificationManager nm = ctx.getSystemService(NotificationManager.class);
|
||||
NotificationManager nm = (NotificationManager)ctx.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify( notificationId, notification );
|
||||
}
|
||||
|
||||
public void setText(String title)
|
||||
{
|
||||
notification.contentView.setTextViewText( R.id.status_text, title );
|
||||
NotificationManager nm = ctx.getSystemService(NotificationManager.class);
|
||||
NotificationManager nm = (NotificationManager)ctx.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify( notificationId, notification );
|
||||
}
|
||||
|
||||
|
@ -149,28 +144,26 @@ public class XashService extends Service
|
|||
return notificationId;
|
||||
}
|
||||
|
||||
public static XashNotification getXashNotification(Context ctx)
|
||||
public static XashNotification getXashNotification()
|
||||
{
|
||||
if( XashActivity.sdk >= Build.VERSION_CODES.O )
|
||||
return new XashNotification_O(ctx);
|
||||
else if( XashActivity.sdk >= 21 )
|
||||
return new XashNotification_v21(ctx);
|
||||
return new XashNotification(ctx);
|
||||
if( XashActivity.sdk >= 26 )
|
||||
return new XashNotification_v26();
|
||||
// else if( XashActivity.sdk >= 21 )
|
||||
// return new XashNotification_v21();
|
||||
else
|
||||
return new XashNotification();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class XashNotification_v21 extends XashNotification
|
||||
{
|
||||
protected Notification.Builder builder;
|
||||
|
||||
public XashNotification_v21(Context ctx)
|
||||
{
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Notification createNotification()
|
||||
public Notification createNotification(Context context)
|
||||
{
|
||||
ctx = context;
|
||||
Intent engineIntent = new Intent(ctx, XashActivity.class);
|
||||
engineIntent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
|
||||
|
||||
|
@ -196,7 +189,7 @@ public class XashService extends Service
|
|||
public void setIcon(Bitmap bmp)
|
||||
{
|
||||
notification = builder.setLargeIcon(bmp).build();
|
||||
NotificationManager nm = ctx.getSystemService(NotificationManager.class);
|
||||
NotificationManager nm = (NotificationManager)ctx.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify( notificationId, notification );
|
||||
}
|
||||
|
||||
|
@ -204,25 +197,21 @@ public class XashService extends Service
|
|||
public void setText(String str)
|
||||
{
|
||||
notification = builder.setContentText(str).build();
|
||||
NotificationManager nm = ctx.getSystemService(NotificationManager.class);
|
||||
NotificationManager nm = (NotificationManager)ctx.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
nm.notify( notificationId, notification );
|
||||
}
|
||||
}
|
||||
|
||||
private static class XashNotification_O extends XashNotification_v21
|
||||
|
||||
private static class XashNotification_v26 extends XashNotification_v21
|
||||
{
|
||||
private static final String CHANNEL_ID = "XashServiceChannel";
|
||||
|
||||
public XashNotification_O(Context ctx)
|
||||
{
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
private void createNotificationChannel()
|
||||
{
|
||||
// Create the NotificationChannel, but only on API 26+ because
|
||||
// the NotificationChannel class is new and not in the support library
|
||||
if (XashActivity.sdk >= Build.VERSION_CODES.O)
|
||||
if (XashActivity.sdk >= 26)
|
||||
{
|
||||
final NotificationManager nm = ctx.getSystemService(NotificationManager.class);
|
||||
|
||||
|
@ -244,14 +233,14 @@ public class XashService extends Service
|
|||
}
|
||||
|
||||
@Override
|
||||
public Notification createNotification()
|
||||
public Notification createNotification(Context ctx)
|
||||
{
|
||||
createNotificationChannel();
|
||||
|
||||
builder = new Notification.Builder(ctx);
|
||||
builder.setChannelId(CHANNEL_ID);
|
||||
|
||||
return super.createNotification();
|
||||
return super.createNotification(ctx);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
@ -229,9 +229,58 @@ public class FWGSLib
|
|||
}
|
||||
}
|
||||
|
||||
public static void applyPermissions( final Activity act, final String permissions[], final int code )
|
||||
public static class Compat
|
||||
{
|
||||
if( sdk >= 23 )
|
||||
public void applyPermissions( final Activity act, final String permissions[], final int code ) {}
|
||||
public void applyImmersiveMode( boolean keyboardVisible, View decorView ) {}
|
||||
public void startForegroundService( Context ctx, Intent intent ) {}
|
||||
public String getNativeLibDir(Context ctx)
|
||||
{
|
||||
return ctx.getFilesDir().getParentFile().getPath() + "/lib";
|
||||
}
|
||||
}
|
||||
|
||||
static class Compat_9 extends Compat
|
||||
{
|
||||
public String getNativeLibDir(Context ctx)
|
||||
{
|
||||
try {
|
||||
ApplicationInfo ai = getApplicationInfo(ctx, null, 0);
|
||||
return ai.nativeLibraryDir;
|
||||
}
|
||||
catch(Exception e) {
|
||||
return super.getNativeLibDir(ctx);
|
||||
}
|
||||
}
|
||||
public void startForegroundService( Context ctx, Intent intent ) {
|
||||
ctx.startService( intent );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class Compat_19 extends Compat_9
|
||||
{
|
||||
public void applyImmersiveMode(boolean keyboardVisible, View decorView)
|
||||
{
|
||||
//if( !XashActivity.mPref.getBoolean( "immersive_mode", false ) )
|
||||
// return;
|
||||
if( keyboardVisible )
|
||||
decorView.setSystemUiVisibility(
|
||||
0x00000100 // View.SYSTEM_UI_FLAG_LAYOUT_STABLE
|
||||
| 0x00000200 // View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||
| 0x00000400 // View.SYSTEM_UI_FLAG_LAYOUT_FULSCREEN
|
||||
| 0x00000002 // View.SYSTEM_UI_FLAG_HIDE_NAVIGATION // hide nav bar
|
||||
| 0x00000004 // View.SYSTEM_UI_FLAG_FULLSCREEN // hide status bar
|
||||
| 0x00001000 // View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
|
||||
);
|
||||
else
|
||||
decorView.setSystemUiVisibility( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
static class Compat_23 extends Compat_19
|
||||
{
|
||||
public void applyPermissions( final Activity act, final String permissions[], final int code )
|
||||
{
|
||||
List<String> requestPermissions = new ArrayList<String>();
|
||||
|
||||
|
@ -256,6 +305,25 @@ public class FWGSLib
|
|||
}
|
||||
}
|
||||
|
||||
static class Compat_26 extends Compat_23
|
||||
{
|
||||
public void startForegroundService(Context ctx, Intent intent){
|
||||
ctx.startForegroundService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
public static Compat cmp;
|
||||
static {
|
||||
int sdk1 = Integer.valueOf(Build.VERSION.SDK);
|
||||
if( sdk1 >= 26 )
|
||||
cmp = new Compat_26();
|
||||
if( sdk1 >= 23 )
|
||||
cmp = new Compat_23();
|
||||
else if( sdk1 >= 9 )
|
||||
cmp = new Compat_9();
|
||||
else cmp = new Compat();
|
||||
}
|
||||
|
||||
public static ApplicationInfo getApplicationInfo(Context ctx, String pkgName, int flags) throws PackageManager.NameNotFoundException
|
||||
{
|
||||
PackageManager pm = ctx.getPackageManager();
|
||||
|
@ -268,3 +336,4 @@ public class FWGSLib
|
|||
|
||||
public static final int sdk = Integer.valueOf(Build.VERSION.SDK);
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue