forked from suyu/suyu
android: Convert EmulationActivity to Kotlin
This commit is contained in:
parent
7cd72a7c6d
commit
39a65f8446
2 changed files with 286 additions and 347 deletions
|
@ -1,347 +0,0 @@
|
|||
package org.yuzu.yuzu_emu.activities;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.view.InputDevice;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.SeekBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.annotation.IntDef;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.AlertDialog;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.core.app.NotificationManagerCompat;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.fragment.app.FragmentActivity;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import org.yuzu.yuzu_emu.NativeLibrary;
|
||||
import org.yuzu.yuzu_emu.R;
|
||||
import org.yuzu.yuzu_emu.fragments.EmulationFragment;
|
||||
import org.yuzu.yuzu_emu.fragments.MenuFragment;
|
||||
import org.yuzu.yuzu_emu.utils.ControllerMappingHelper;
|
||||
import org.yuzu.yuzu_emu.utils.ForegroundService;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
|
||||
import static java.lang.annotation.RetentionPolicy.SOURCE;
|
||||
|
||||
public final class EmulationActivity extends AppCompatActivity {
|
||||
private static final String BACKSTACK_NAME_MENU = "menu";
|
||||
|
||||
private static final String BACKSTACK_NAME_SUBMENU = "submenu";
|
||||
|
||||
public static final String EXTRA_SELECTED_GAME = "SelectedGame";
|
||||
public static final String EXTRA_SELECTED_TITLE = "SelectedTitle";
|
||||
public static final int MENU_ACTION_EDIT_CONTROLS_PLACEMENT = 0;
|
||||
public static final int MENU_ACTION_TOGGLE_CONTROLS = 1;
|
||||
public static final int MENU_ACTION_ADJUST_SCALE = 2;
|
||||
public static final int MENU_ACTION_EXIT = 3;
|
||||
public static final int MENU_ACTION_SHOW_FPS = 4;
|
||||
public static final int MENU_ACTION_RESET_OVERLAY = 6;
|
||||
public static final int MENU_ACTION_SHOW_OVERLAY = 7;
|
||||
public static final int MENU_ACTION_OPEN_SETTINGS = 8;
|
||||
private static final int EMULATION_RUNNING_NOTIFICATION = 0x1000;
|
||||
private View mDecorView;
|
||||
private EmulationFragment mEmulationFragment;
|
||||
private SharedPreferences mPreferences;
|
||||
private ControllerMappingHelper mControllerMappingHelper;
|
||||
// TODO(bunnei): Disable notifications until we support app suspension.
|
||||
// private Intent foregroundService;
|
||||
private boolean activityRecreated;
|
||||
private String mSelectedTitle;
|
||||
private String mPath;
|
||||
|
||||
private boolean mMenuVisible;
|
||||
|
||||
public static void launch(FragmentActivity activity, String path, String title) {
|
||||
Intent launcher = new Intent(activity, EmulationActivity.class);
|
||||
|
||||
launcher.putExtra(EXTRA_SELECTED_GAME, path);
|
||||
launcher.putExtra(EXTRA_SELECTED_TITLE, title);
|
||||
activity.startActivity(launcher);
|
||||
}
|
||||
|
||||
public static void tryDismissRunningNotification(Activity activity) {
|
||||
// TODO(bunnei): Disable notifications until we support app suspension.
|
||||
// NotificationManagerCompat.from(activity).cancel(EMULATION_RUNNING_NOTIFICATION);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
// TODO(bunnei): Disable notifications until we support app suspension.
|
||||
// stopService(foregroundService);
|
||||
super.onDestroy();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (savedInstanceState == null) {
|
||||
// Get params we were passed
|
||||
Intent gameToEmulate = getIntent();
|
||||
mPath = gameToEmulate.getStringExtra(EXTRA_SELECTED_GAME);
|
||||
mSelectedTitle = gameToEmulate.getStringExtra(EXTRA_SELECTED_TITLE);
|
||||
activityRecreated = false;
|
||||
} else {
|
||||
activityRecreated = true;
|
||||
restoreState(savedInstanceState);
|
||||
}
|
||||
|
||||
mControllerMappingHelper = new ControllerMappingHelper();
|
||||
|
||||
// Get a handle to the Window containing the UI.
|
||||
mDecorView = getWindow().getDecorView();
|
||||
mDecorView.setOnSystemUiVisibilityChangeListener(visibility ->
|
||||
{
|
||||
if ((visibility & View.SYSTEM_UI_FLAG_FULLSCREEN) == 0) {
|
||||
// Go back to immersive fullscreen mode in 3s
|
||||
Handler handler = new Handler(getMainLooper());
|
||||
handler.postDelayed(this::enableFullscreenImmersive, 3000 /* 3s */);
|
||||
}
|
||||
});
|
||||
// Set these options now so that the SurfaceView the game renders into is the right size.
|
||||
enableFullscreenImmersive();
|
||||
|
||||
setTheme(R.style.YuzuEmulationBase);
|
||||
|
||||
setContentView(R.layout.activity_emulation);
|
||||
|
||||
// Find or create the EmulationFragment
|
||||
mEmulationFragment = (EmulationFragment) getSupportFragmentManager()
|
||||
.findFragmentById(R.id.frame_emulation_fragment);
|
||||
if (mEmulationFragment == null) {
|
||||
mEmulationFragment = EmulationFragment.newInstance(mPath);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.add(R.id.frame_emulation_fragment, mEmulationFragment)
|
||||
.commit();
|
||||
}
|
||||
|
||||
setTitle(mSelectedTitle);
|
||||
|
||||
mPreferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
|
||||
// Start a foreground service to prevent the app from getting killed in the background
|
||||
// TODO(bunnei): Disable notifications until we support app suspension.
|
||||
// foregroundService = new Intent(EmulationActivity.this, ForegroundService.class);
|
||||
// startForegroundService(foregroundService);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(@NonNull Bundle outState) {
|
||||
outState.putString(EXTRA_SELECTED_GAME, mPath);
|
||||
outState.putString(EXTRA_SELECTED_TITLE, mSelectedTitle);
|
||||
super.onSaveInstanceState(outState);
|
||||
}
|
||||
|
||||
protected void restoreState(Bundle savedInstanceState) {
|
||||
mPath = savedInstanceState.getString(EXTRA_SELECTED_GAME);
|
||||
mSelectedTitle = savedInstanceState.getString(EXTRA_SELECTED_TITLE);
|
||||
|
||||
// If an alert prompt was in progress when state was restored, retry displaying it
|
||||
NativeLibrary.retryDisplayAlertPrompt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRestart() {
|
||||
super.onRestart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
toggleMenu();
|
||||
}
|
||||
|
||||
private void enableFullscreenImmersive() {
|
||||
getWindow().getAttributes().layoutInDisplayCutoutMode=
|
||||
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES;
|
||||
|
||||
// It would be nice to use IMMERSIVE_STICKY, but that doesn't show the toolbar.
|
||||
mDecorView.setSystemUiVisibility(
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN |
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE);
|
||||
}
|
||||
|
||||
public void handleMenuAction(int action) {
|
||||
switch (action) {
|
||||
case MENU_ACTION_EXIT:
|
||||
mEmulationFragment.stopEmulation();
|
||||
finish();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void editControlsPlacement() {
|
||||
if (mEmulationFragment.isConfiguringControls()) {
|
||||
mEmulationFragment.stopConfiguringControls();
|
||||
} else {
|
||||
mEmulationFragment.startConfiguringControls();
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustScale() {
|
||||
LayoutInflater inflater = LayoutInflater.from(this);
|
||||
View view = inflater.inflate(R.layout.dialog_seekbar, null);
|
||||
|
||||
final SeekBar seekbar = view.findViewById(R.id.seekbar);
|
||||
final TextView value = view.findViewById(R.id.text_value);
|
||||
final TextView units = view.findViewById(R.id.text_units);
|
||||
|
||||
seekbar.setMax(150);
|
||||
seekbar.setProgress(mPreferences.getInt("controlScale", 50));
|
||||
seekbar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
|
||||
public void onStartTrackingTouch(SeekBar seekBar) {
|
||||
}
|
||||
|
||||
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
|
||||
value.setText(String.valueOf(progress + 50));
|
||||
}
|
||||
|
||||
public void onStopTrackingTouch(SeekBar seekBar) {
|
||||
setControlScale(seekbar.getProgress());
|
||||
}
|
||||
});
|
||||
|
||||
value.setText(String.valueOf(seekbar.getProgress() + 50));
|
||||
units.setText("%");
|
||||
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(this);
|
||||
builder.setTitle(R.string.emulation_control_scale);
|
||||
builder.setView(view);
|
||||
final int previousProgress = seekbar.getProgress();
|
||||
builder.setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> {
|
||||
setControlScale(previousProgress);
|
||||
});
|
||||
builder.setPositiveButton(android.R.string.ok, (dialogInterface, i) ->
|
||||
{
|
||||
setControlScale(seekbar.getProgress());
|
||||
});
|
||||
builder.setNeutralButton(R.string.slider_default, (dialogInterface, i) -> {
|
||||
setControlScale(50);
|
||||
});
|
||||
|
||||
AlertDialog alertDialog = builder.create();
|
||||
alertDialog.show();
|
||||
}
|
||||
|
||||
private void setControlScale(int scale) {
|
||||
SharedPreferences.Editor editor = mPreferences.edit();
|
||||
editor.putInt("controlScale", scale);
|
||||
editor.apply();
|
||||
mEmulationFragment.refreshInputOverlay();
|
||||
}
|
||||
|
||||
private void resetOverlay() {
|
||||
new AlertDialog.Builder(this)
|
||||
.setTitle(getString(R.string.emulation_touch_overlay_reset))
|
||||
.setPositiveButton(android.R.string.yes, (dialogInterface, i) -> mEmulationFragment.resetInputOverlay())
|
||||
.setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> {
|
||||
})
|
||||
.create()
|
||||
.show();
|
||||
}
|
||||
|
||||
private static boolean areCoordinatesOutside(@Nullable View view, float x, float y)
|
||||
{
|
||||
if (view == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
Rect viewBounds = new Rect();
|
||||
view.getGlobalVisibleRect(viewBounds);
|
||||
return !viewBounds.contains(Math.round(x), Math.round(y));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent event)
|
||||
{
|
||||
if (event.getActionMasked() == MotionEvent.ACTION_DOWN)
|
||||
{
|
||||
boolean anyMenuClosed = false;
|
||||
|
||||
Fragment submenu = getSupportFragmentManager().findFragmentById(R.id.frame_submenu);
|
||||
if (submenu != null && areCoordinatesOutside(submenu.getView(), event.getX(), event.getY()))
|
||||
{
|
||||
closeSubmenu();
|
||||
submenu = null;
|
||||
anyMenuClosed = true;
|
||||
}
|
||||
|
||||
if (submenu == null)
|
||||
{
|
||||
Fragment menu = getSupportFragmentManager().findFragmentById(R.id.frame_menu);
|
||||
if (menu != null && areCoordinatesOutside(menu.getView(), event.getX(), event.getY()))
|
||||
{
|
||||
closeMenu();
|
||||
anyMenuClosed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (anyMenuClosed)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return super.dispatchTouchEvent(event);
|
||||
}
|
||||
|
||||
public boolean isActivityRecreated() {
|
||||
return activityRecreated;
|
||||
}
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({MENU_ACTION_EDIT_CONTROLS_PLACEMENT, MENU_ACTION_TOGGLE_CONTROLS, MENU_ACTION_ADJUST_SCALE,
|
||||
MENU_ACTION_EXIT, MENU_ACTION_SHOW_FPS, MENU_ACTION_RESET_OVERLAY, MENU_ACTION_SHOW_OVERLAY, MENU_ACTION_OPEN_SETTINGS})
|
||||
public @interface MenuAction {
|
||||
}
|
||||
|
||||
private boolean closeSubmenu()
|
||||
{
|
||||
return getSupportFragmentManager().popBackStackImmediate(BACKSTACK_NAME_SUBMENU,
|
||||
FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
}
|
||||
|
||||
private boolean closeMenu()
|
||||
{
|
||||
mMenuVisible = false;
|
||||
return getSupportFragmentManager().popBackStackImmediate(BACKSTACK_NAME_MENU,
|
||||
FragmentManager.POP_BACK_STACK_INCLUSIVE);
|
||||
}
|
||||
|
||||
private void toggleMenu()
|
||||
{
|
||||
if (!closeMenu()) {
|
||||
// Removing the menu failed, so that means it wasn't visible. Add it.
|
||||
Fragment fragment = MenuFragment.newInstance();
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.setCustomAnimations(
|
||||
R.animator.menu_slide_in_from_start,
|
||||
R.animator.menu_slide_out_to_start,
|
||||
R.animator.menu_slide_in_from_start,
|
||||
R.animator.menu_slide_out_to_start)
|
||||
.add(R.id.frame_menu, fragment)
|
||||
.addToBackStack(BACKSTACK_NAME_MENU)
|
||||
.commit();
|
||||
mMenuVisible = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,286 @@
|
|||
package org.yuzu.yuzu_emu.activities
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.graphics.Rect
|
||||
import android.os.Bundle
|
||||
import android.view.LayoutInflater
|
||||
import android.view.MotionEvent
|
||||
import android.view.View
|
||||
import android.view.WindowManager
|
||||
import android.widget.TextView
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
import androidx.annotation.IntDef
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.preference.PreferenceManager
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import com.google.android.material.slider.Slider
|
||||
import com.google.android.material.slider.Slider.OnChangeListener
|
||||
import org.yuzu.yuzu_emu.NativeLibrary
|
||||
import org.yuzu.yuzu_emu.R
|
||||
import org.yuzu.yuzu_emu.features.settings.model.Settings
|
||||
import org.yuzu.yuzu_emu.fragments.EmulationFragment
|
||||
import org.yuzu.yuzu_emu.fragments.MenuFragment
|
||||
import org.yuzu.yuzu_emu.utils.ControllerMappingHelper
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
open class EmulationActivity : AppCompatActivity() {
|
||||
private var controllerMappingHelper: ControllerMappingHelper? = null
|
||||
|
||||
// TODO(bunnei): Disable notifications until we support app suspension.
|
||||
//private Intent foregroundService;
|
||||
|
||||
var isActivityRecreated = false
|
||||
private var selectedTitle: String? = null
|
||||
private var path: String? = null
|
||||
private var menuVisible = false
|
||||
private var emulationFragment: EmulationFragment? = null
|
||||
|
||||
override fun onDestroy() {
|
||||
// TODO(bunnei): Disable notifications until we support app suspension.
|
||||
//stopService(foregroundService);
|
||||
super.onDestroy()
|
||||
}
|
||||
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
if (savedInstanceState == null) {
|
||||
// Get params we were passed
|
||||
val gameToEmulate = intent
|
||||
path = gameToEmulate.getStringExtra(EXTRA_SELECTED_GAME)
|
||||
selectedTitle = gameToEmulate.getStringExtra(EXTRA_SELECTED_TITLE)
|
||||
isActivityRecreated = false
|
||||
} else {
|
||||
isActivityRecreated = true
|
||||
restoreState(savedInstanceState)
|
||||
}
|
||||
controllerMappingHelper = ControllerMappingHelper()
|
||||
|
||||
// Set these options now so that the SurfaceView the game renders into is the right size.
|
||||
enableFullscreenImmersive()
|
||||
|
||||
setContentView(R.layout.activity_emulation)
|
||||
|
||||
// Find or create the EmulationFragment
|
||||
var emulationFragment =
|
||||
supportFragmentManager.findFragmentById(R.id.frame_emulation_fragment) as EmulationFragment?
|
||||
if (emulationFragment == null) {
|
||||
emulationFragment = EmulationFragment.newInstance(path)
|
||||
supportFragmentManager.beginTransaction()
|
||||
.add(R.id.frame_emulation_fragment, emulationFragment)
|
||||
.commit()
|
||||
}
|
||||
title = selectedTitle
|
||||
|
||||
// Start a foreground service to prevent the app from getting killed in the background
|
||||
// TODO(bunnei): Disable notifications until we support app suspension.
|
||||
//foregroundService = new Intent(EmulationActivity.this, ForegroundService.class);
|
||||
//startForegroundService(foregroundService);
|
||||
|
||||
onBackPressedDispatcher.addCallback(this, object : OnBackPressedCallback(true) {
|
||||
override fun handleOnBackPressed() {
|
||||
toggleMenu()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onSaveInstanceState(outState: Bundle) {
|
||||
outState.putString(EXTRA_SELECTED_GAME, path)
|
||||
outState.putString(EXTRA_SELECTED_TITLE, selectedTitle)
|
||||
super.onSaveInstanceState(outState)
|
||||
}
|
||||
|
||||
private fun restoreState(savedInstanceState: Bundle) {
|
||||
path = savedInstanceState.getString(EXTRA_SELECTED_GAME)
|
||||
selectedTitle = savedInstanceState.getString(EXTRA_SELECTED_TITLE)
|
||||
|
||||
// If an alert prompt was in progress when state was restored, retry displaying it
|
||||
NativeLibrary.retryDisplayAlertPrompt()
|
||||
}
|
||||
|
||||
private fun enableFullscreenImmersive() {
|
||||
window.attributes.layoutInDisplayCutoutMode =
|
||||
WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
|
||||
|
||||
// It would be nice to use IMMERSIVE_STICKY, but that doesn't show the toolbar.
|
||||
window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN or
|
||||
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION or
|
||||
View.SYSTEM_UI_FLAG_FULLSCREEN or
|
||||
View.SYSTEM_UI_FLAG_IMMERSIVE
|
||||
}
|
||||
|
||||
fun handleMenuAction(action: Int) {
|
||||
when (action) {
|
||||
MENU_ACTION_EXIT -> {
|
||||
emulationFragment!!.stopEmulation()
|
||||
finish()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun editControlsPlacement() {
|
||||
if (emulationFragment!!.isConfiguringControls) {
|
||||
emulationFragment!!.stopConfiguringControls()
|
||||
} else {
|
||||
emulationFragment!!.startConfiguringControls()
|
||||
}
|
||||
}
|
||||
|
||||
private fun adjustScale() {
|
||||
val inflater = LayoutInflater.from(this)
|
||||
val view = inflater.inflate(R.layout.dialog_slider, null)
|
||||
val slider = view.findViewById<Slider>(R.id.slider)
|
||||
val textValue = view.findViewById<TextView>(R.id.text_value)
|
||||
val units = view.findViewById<TextView>(R.id.text_units)
|
||||
|
||||
slider.valueTo = 150F
|
||||
slider.value = PreferenceManager.getDefaultSharedPreferences(applicationContext)
|
||||
.getInt(Settings.PREF_CONTROL_SCALE, 50).toFloat()
|
||||
slider.addOnChangeListener(OnChangeListener { _, value, _ ->
|
||||
textValue.text = value.toString()
|
||||
setControlScale(value.toInt())
|
||||
})
|
||||
textValue.text = slider.value.toString()
|
||||
units.text = "%"
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(R.string.emulation_control_scale)
|
||||
.setView(view)
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int ->
|
||||
setControlScale(slider.value.toInt())
|
||||
}
|
||||
.setNeutralButton(R.string.slider_default) { _: DialogInterface?, _: Int ->
|
||||
setControlScale(50)
|
||||
}
|
||||
.show()
|
||||
}
|
||||
|
||||
private fun setControlScale(scale: Int) {
|
||||
PreferenceManager.getDefaultSharedPreferences(applicationContext).edit()
|
||||
.putInt(Settings.PREF_CONTROL_SCALE, scale)
|
||||
.apply()
|
||||
emulationFragment!!.refreshInputOverlay()
|
||||
}
|
||||
|
||||
private fun resetOverlay() {
|
||||
MaterialAlertDialogBuilder(this)
|
||||
.setTitle(getString(R.string.emulation_touch_overlay_reset))
|
||||
.setPositiveButton(android.R.string.ok) { _: DialogInterface?, _: Int -> emulationFragment!!.resetInputOverlay() }
|
||||
.setNegativeButton(android.R.string.cancel, null)
|
||||
.create()
|
||||
.show()
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
||||
if (event.actionMasked == MotionEvent.ACTION_DOWN) {
|
||||
var anyMenuClosed = false
|
||||
var submenu = supportFragmentManager.findFragmentById(R.id.frame_submenu)
|
||||
if (submenu != null && areCoordinatesOutside(submenu.view, event.x, event.y)) {
|
||||
closeSubmenu()
|
||||
submenu = null
|
||||
anyMenuClosed = true
|
||||
}
|
||||
if (submenu == null) {
|
||||
val menu = supportFragmentManager.findFragmentById(R.id.frame_menu)
|
||||
if (menu != null && areCoordinatesOutside(menu.view, event.x, event.y)) {
|
||||
closeMenu()
|
||||
anyMenuClosed = true
|
||||
}
|
||||
}
|
||||
if (anyMenuClosed) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return super.dispatchTouchEvent(event)
|
||||
}
|
||||
|
||||
@Retention(AnnotationRetention.SOURCE)
|
||||
@IntDef(
|
||||
MENU_ACTION_EDIT_CONTROLS_PLACEMENT,
|
||||
MENU_ACTION_TOGGLE_CONTROLS,
|
||||
MENU_ACTION_ADJUST_SCALE,
|
||||
MENU_ACTION_EXIT,
|
||||
MENU_ACTION_SHOW_FPS,
|
||||
MENU_ACTION_RESET_OVERLAY,
|
||||
MENU_ACTION_SHOW_OVERLAY,
|
||||
MENU_ACTION_OPEN_SETTINGS
|
||||
)
|
||||
annotation class MenuAction
|
||||
|
||||
private fun closeSubmenu(): Boolean {
|
||||
return supportFragmentManager.popBackStackImmediate(
|
||||
BACKSTACK_NAME_SUBMENU,
|
||||
FragmentManager.POP_BACK_STACK_INCLUSIVE
|
||||
)
|
||||
}
|
||||
|
||||
private fun closeMenu(): Boolean {
|
||||
menuVisible = false
|
||||
return supportFragmentManager.popBackStackImmediate(
|
||||
BACKSTACK_NAME_MENU,
|
||||
FragmentManager.POP_BACK_STACK_INCLUSIVE
|
||||
)
|
||||
}
|
||||
|
||||
private fun toggleMenu() {
|
||||
if (!closeMenu()) {
|
||||
val fragment: Fragment = MenuFragment.newInstance()
|
||||
supportFragmentManager.beginTransaction()
|
||||
.setCustomAnimations(
|
||||
R.animator.menu_slide_in_from_start,
|
||||
R.animator.menu_slide_out_to_start,
|
||||
R.animator.menu_slide_in_from_start,
|
||||
R.animator.menu_slide_out_to_start
|
||||
)
|
||||
.add(R.id.frame_menu, fragment)
|
||||
.addToBackStack(BACKSTACK_NAME_MENU)
|
||||
.commit()
|
||||
menuVisible = true
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val BACKSTACK_NAME_MENU = "menu"
|
||||
private const val BACKSTACK_NAME_SUBMENU = "submenu"
|
||||
const val EXTRA_SELECTED_GAME = "SelectedGame"
|
||||
const val EXTRA_SELECTED_TITLE = "SelectedTitle"
|
||||
const val MENU_ACTION_EDIT_CONTROLS_PLACEMENT = 0
|
||||
const val MENU_ACTION_TOGGLE_CONTROLS = 1
|
||||
const val MENU_ACTION_ADJUST_SCALE = 2
|
||||
const val MENU_ACTION_EXIT = 3
|
||||
const val MENU_ACTION_SHOW_FPS = 4
|
||||
const val MENU_ACTION_RESET_OVERLAY = 6
|
||||
const val MENU_ACTION_SHOW_OVERLAY = 7
|
||||
const val MENU_ACTION_OPEN_SETTINGS = 8
|
||||
private const val EMULATION_RUNNING_NOTIFICATION = 0x1000
|
||||
|
||||
@JvmStatic
|
||||
fun launch(activity: FragmentActivity, path: String?, title: String?) {
|
||||
val launcher = Intent(activity, EmulationActivity::class.java)
|
||||
launcher.putExtra(EXTRA_SELECTED_GAME, path)
|
||||
launcher.putExtra(EXTRA_SELECTED_TITLE, title)
|
||||
activity.startActivity(launcher)
|
||||
}
|
||||
|
||||
@JvmStatic
|
||||
fun tryDismissRunningNotification(activity: Activity?) {
|
||||
// TODO(bunnei): Disable notifications until we support app suspension.
|
||||
//NotificationManagerCompat.from(activity).cancel(EMULATION_RUNNING_NOTIFICATION);
|
||||
}
|
||||
|
||||
private fun areCoordinatesOutside(view: View?, x: Float, y: Float): Boolean {
|
||||
if (view == null) {
|
||||
return true
|
||||
}
|
||||
val viewBounds = Rect()
|
||||
view.getGlobalVisibleRect(viewBounds)
|
||||
return !viewBounds.contains(x.roundToInt(), y.roundToInt())
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue