From 9b20bcea0fd6eaa753d53d63601db0c4d44f5fb9 Mon Sep 17 00:00:00 2001 From: JosJuice Date: Sun, 22 Jan 2023 08:42:27 +0100 Subject: [PATCH] android: Allow opening in-emulation menu by pressing Back (#6248) It seems like the menu isn't showing up for users on Android 13. We're not sure what's wrong, and the approach we've been using for the menu hasn't been entirely reliable in the past either (in particular not on non-mobile form factors like Chromebooks and VR devices), so let's make it possible to open the menu by pressing Back, an action that works reliably on most kinds of Android devices. (Not sure if there's an equivalent of Back on devices like watches, but I think we can pretty safely ignore those for now.) --- .../activities/EmulationActivity.java | 65 +++++++++++++------ .../DiskShaderCacheProgress.java | 2 + .../main/res/layout/activity_emulation.xml | 8 ++- .../app/src/main/res/menu/menu_emulation.xml | 5 ++ .../app/src/main/res/values/strings.xml | 1 + 5 files changed, 60 insertions(+), 21 deletions(-) diff --git a/src/android/app/src/main/java/org/citra/citra_emu/activities/EmulationActivity.java b/src/android/app/src/main/java/org/citra/citra_emu/activities/EmulationActivity.java index 34ab49c96..b5e547266 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/activities/EmulationActivity.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/activities/EmulationActivity.java @@ -12,6 +12,7 @@ import android.view.InputDevice; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.SubMenu; @@ -19,11 +20,13 @@ import android.view.View; import android.widget.CheckBox; import android.widget.SeekBar; import android.widget.TextView; +import android.widget.Toast; import androidx.annotation.IntDef; import androidx.annotation.NonNull; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AppCompatActivity; +import androidx.appcompat.widget.PopupMenu; import androidx.core.app.NotificationManagerCompat; import androidx.fragment.app.FragmentActivity; @@ -74,6 +77,7 @@ public final class EmulationActivity extends AppCompatActivity { public static final int MENU_ACTION_JOYSTICK_REL_CENTER = 15; public static final int MENU_ACTION_DPAD_SLIDE_ENABLE = 16; public static final int MENU_ACTION_OPEN_CHEATS = 17; + public static final int MENU_ACTION_CLOSE_GAME = 18; public static final int REQUEST_SELECT_AMIIBO = 2; private static final int EMULATION_RUNNING_NOTIFICATION = 0x1000; @@ -114,6 +118,8 @@ public final class EmulationActivity extends AppCompatActivity { EmulationActivity.MENU_ACTION_DPAD_SLIDE_ENABLE); buttonsActionsMap .append(R.id.menu_emulation_open_cheats, EmulationActivity.MENU_ACTION_OPEN_CHEATS); + buttonsActionsMap + .append(R.id.menu_emulation_close_game, EmulationActivity.MENU_ACTION_CLOSE_GAME); } private View mDecorView; @@ -223,21 +229,12 @@ public final class EmulationActivity extends AppCompatActivity { @Override public void onBackPressed() { - NativeLibrary.PauseEmulation(); - new AlertDialog.Builder(this) - .setTitle(R.string.emulation_close_game) - .setMessage(R.string.emulation_close_game_message) - .setPositiveButton(android.R.string.yes, (dialogInterface, i) -> - { - mEmulationFragment.stopEmulation(); - finish(); - }) - .setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> - NativeLibrary.UnPauseEmulation()) - .setOnCancelListener(dialogInterface -> - NativeLibrary.UnPauseEmulation()) - .create() - .show(); + View anchor = findViewById(R.id.menu_anchor); + PopupMenu popupMenu = new PopupMenu(this, anchor); + onCreateOptionsMenu(popupMenu.getMenu(), popupMenu.getMenuInflater()); + updateSavestateMenuOptions(popupMenu.getMenu()); + popupMenu.setOnMenuItemClickListener(this::onOptionsItemSelected); + popupMenu.show(); } @Override @@ -271,6 +268,10 @@ public final class EmulationActivity extends AppCompatActivity { } } + public void onEmulationStarted() { + Toast.makeText(this, getString(R.string.emulation_menu_help), Toast.LENGTH_LONG).show(); + } + private void enableFullscreenImmersive() { // It would be nice to use IMMERSIVE_STICKY, but that doesn't show the toolbar. mDecorView.setSystemUiVisibility( @@ -285,7 +286,12 @@ public final class EmulationActivity extends AppCompatActivity { @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.menu_emulation, menu); + onCreateOptionsMenu(menu, getMenuInflater()); + return true; + } + + private void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { + inflater.inflate(R.menu.menu_emulation, menu); int layoutOptionMenuItem = R.id.menu_screen_layout_landscape; switch (EmulationMenuSettings.getLandscapeScreenLayout()) { @@ -306,8 +312,6 @@ public final class EmulationActivity extends AppCompatActivity { menu.findItem(R.id.menu_emulation_show_fps).setChecked(EmulationMenuSettings.getShowFps()); menu.findItem(R.id.menu_emulation_swap_screens).setChecked(EmulationMenuSettings.getSwapScreens()); menu.findItem(R.id.menu_emulation_show_overlay).setChecked(EmulationMenuSettings.getShowOverlay()); - - return true; } private void DisplaySavestateWarning() { @@ -333,12 +337,16 @@ public final class EmulationActivity extends AppCompatActivity { @Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); + updateSavestateMenuOptions(menu); + return true; + } + private void updateSavestateMenuOptions(Menu menu) { final NativeLibrary.SavestateInfo[] savestates = NativeLibrary.GetSavestateInfo(); if (savestates == null) { menu.findItem(R.id.menu_emulation_save_state).setVisible(false); menu.findItem(R.id.menu_emulation_load_state).setVisible(false); - return true; + return; } menu.findItem(R.id.menu_emulation_save_state).setVisible(true); menu.findItem(R.id.menu_emulation_load_state).setVisible(true); @@ -367,7 +375,6 @@ public final class EmulationActivity extends AppCompatActivity { saveStateMenu.getItem(info.slot - 1).setTitle(text); loadStateMenu.getItem(info.slot - 1).setTitle(text).setEnabled(true); } - return true; } @SuppressWarnings("WrongConstant") @@ -480,6 +487,24 @@ public final class EmulationActivity extends AppCompatActivity { case MENU_ACTION_OPEN_CHEATS: CheatsActivity.launch(this); break; + + case MENU_ACTION_CLOSE_GAME: + NativeLibrary.PauseEmulation(); + new AlertDialog.Builder(this) + .setTitle(R.string.emulation_close_game) + .setMessage(R.string.emulation_close_game_message) + .setPositiveButton(android.R.string.yes, (dialogInterface, i) -> + { + mEmulationFragment.stopEmulation(); + finish(); + }) + .setNegativeButton(android.R.string.cancel, (dialogInterface, i) -> + NativeLibrary.UnPauseEmulation()) + .setOnCancelListener(dialogInterface -> + NativeLibrary.UnPauseEmulation()) + .create() + .show(); + break; } return true; diff --git a/src/android/app/src/main/java/org/citra/citra_emu/disk_shader_cache/DiskShaderCacheProgress.java b/src/android/app/src/main/java/org/citra/citra_emu/disk_shader_cache/DiskShaderCacheProgress.java index 8f9d215a3..e71c2cfc1 100644 --- a/src/android/app/src/main/java/org/citra/citra_emu/disk_shader_cache/DiskShaderCacheProgress.java +++ b/src/android/app/src/main/java/org/citra/citra_emu/disk_shader_cache/DiskShaderCacheProgress.java @@ -133,6 +133,8 @@ public class DiskShaderCacheProgress { case Complete: // Workaround for when dialog is dismissed when the app is in the background fragment.dismissAllowingStateLoss(); + + emulationActivity.runOnUiThread(emulationActivity::onEmulationStarted); break; } } diff --git a/src/android/app/src/main/res/layout/activity_emulation.xml b/src/android/app/src/main/res/layout/activity_emulation.xml index 7d7f36925..5f5ff777d 100644 --- a/src/android/app/src/main/res/layout/activity_emulation.xml +++ b/src/android/app/src/main/res/layout/activity_emulation.xml @@ -14,4 +14,10 @@ android:layout_height="match_parent" android:transitionName="image_game_icon" /> - \ No newline at end of file + + + diff --git a/src/android/app/src/main/res/menu/menu_emulation.xml b/src/android/app/src/main/res/menu/menu_emulation.xml index b6c0d7cc4..8492dfdb9 100644 --- a/src/android/app/src/main/res/menu/menu_emulation.xml +++ b/src/android/app/src/main/res/menu/menu_emulation.xml @@ -115,4 +115,9 @@ app:showAsAction="never" android:title="@string/emulation_open_settings" /> + + diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index b72357eb0..7a7a59a79 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -157,6 +157,7 @@ Invalid ROM format + Press Back to access the menu. Save State Load State Slot %1$d