diff --git a/android/src/su/xash/engine/LauncherActivity.java b/android/src/su/xash/engine/LauncherActivity.java index 4a90f139..c6816361 100644 --- a/android/src/su/xash/engine/LauncherActivity.java +++ b/android/src/su/xash/engine/LauncherActivity.java @@ -59,6 +59,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); @@ -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(){ diff --git a/android/src/su/xash/engine/XashActivity.java b/android/src/su/xash/engine/XashActivity.java index 204871f3..008c9ee4 100644 --- a/android/src/su/xash/engine/XashActivity.java +++ b/android/src/su/xash/engine/XashActivity.java @@ -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 ) @@ -161,8 +161,7 @@ public class XashActivity extends Activity { checkWritePermission( basedir ); } } - - @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; @@ -1651,377 +1399,4 @@ class AndroidBug5497Workaround mChildOfContent.getWindowVisibleDisplayFrame( r ); 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(); - } -} +} \ No newline at end of file diff --git a/android/src/su/xash/engine/XashInput.java b/android/src/su/xash/engine/XashInput.java new file mode 100644 index 00000000..48af56a9 --- /dev/null +++ b/android/src/su/xash/engine/XashInput.java @@ -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); + } +} diff --git a/android/src/su/xash/engine/XashService.java b/android/src/su/xash/engine/XashService.java index 31d56735..3088c449 100644 --- a/android/src/su/xash/engine/XashService.java +++ b/android/src/su/xash/engine/XashService.java @@ -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; } @@ -98,20 +97,16 @@ public class XashService extends Service } stopSelf(); } - + public static class XashNotification { public Notification notification; public final int notificationId = 100; - public Context ctx; - - public XashNotification(Context ctx) - { - this.ctx = ctx; - } + protected Context 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); } } }; diff --git a/android/src/su/xash/fwgslib/FWGSLib.java b/android/src/su/xash/fwgslib/FWGSLib.java index ef988381..c1cdba26 100644 --- a/android/src/su/xash/fwgslib/FWGSLib.java +++ b/android/src/su/xash/fwgslib/FWGSLib.java @@ -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 requestPermissions = new ArrayList(); @@ -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); } +