diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
index 888ff331a0..e2b637ba4e 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/activities/EmulationActivity.java
@@ -26,6 +26,7 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
+import androidx.appcompat.widget.PopupMenu;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager;
@@ -103,7 +104,7 @@ public final class EmulationActivity extends AppCompatActivity
MENU_ACTION_LOAD_SLOT6, MENU_ACTION_EXIT, MENU_ACTION_CHANGE_DISC,
MENU_ACTION_RESET_OVERLAY, MENU_SET_IR_SENSITIVITY, MENU_ACTION_CHOOSE_DOUBLETAP,
MENU_ACTION_SCREEN_ORIENTATION, MENU_ACTION_MOTION_CONTROLS, MENU_ACTION_PAUSE_EMULATION,
- MENU_ACTION_UNPAUSE_EMULATION})
+ MENU_ACTION_UNPAUSE_EMULATION, MENU_ACTION_OVERLAY_CONTROLS})
public @interface MenuAction
{
}
@@ -141,7 +142,7 @@ public final class EmulationActivity extends AppCompatActivity
public static final int MENU_ACTION_MOTION_CONTROLS = 30;
public static final int MENU_ACTION_PAUSE_EMULATION = 31;
public static final int MENU_ACTION_UNPAUSE_EMULATION = 32;
-
+ public static final int MENU_ACTION_OVERLAY_CONTROLS = 33;
private static SparseIntArray buttonsActionsMap = new SparseIntArray();
@@ -155,33 +156,6 @@ public final class EmulationActivity extends AppCompatActivity
.append(R.id.menu_emulation_adjust_scale, EmulationActivity.MENU_ACTION_ADJUST_SCALE);
buttonsActionsMap.append(R.id.menu_emulation_choose_controller,
EmulationActivity.MENU_ACTION_CHOOSE_CONTROLLER);
- buttonsActionsMap
- .append(R.id.menu_refresh_wiimotes, EmulationActivity.MENU_ACTION_REFRESH_WIIMOTES);
- buttonsActionsMap
- .append(R.id.menu_emulation_pause, EmulationActivity.MENU_ACTION_PAUSE_EMULATION);
- buttonsActionsMap
- .append(R.id.menu_emulation_unpause, EmulationActivity.MENU_ACTION_UNPAUSE_EMULATION);
- buttonsActionsMap
- .append(R.id.menu_emulation_screenshot, EmulationActivity.MENU_ACTION_TAKE_SCREENSHOT);
-
- buttonsActionsMap.append(R.id.menu_quicksave, EmulationActivity.MENU_ACTION_QUICK_SAVE);
- buttonsActionsMap.append(R.id.menu_quickload, EmulationActivity.MENU_ACTION_QUICK_LOAD);
- buttonsActionsMap
- .append(R.id.menu_emulation_save_root, EmulationActivity.MENU_ACTION_SAVE_ROOT);
- buttonsActionsMap
- .append(R.id.menu_emulation_load_root, EmulationActivity.MENU_ACTION_LOAD_ROOT);
- buttonsActionsMap.append(R.id.menu_emulation_save_1, EmulationActivity.MENU_ACTION_SAVE_SLOT1);
- buttonsActionsMap.append(R.id.menu_emulation_save_2, EmulationActivity.MENU_ACTION_SAVE_SLOT2);
- buttonsActionsMap.append(R.id.menu_emulation_save_3, EmulationActivity.MENU_ACTION_SAVE_SLOT3);
- buttonsActionsMap.append(R.id.menu_emulation_save_4, EmulationActivity.MENU_ACTION_SAVE_SLOT4);
- buttonsActionsMap.append(R.id.menu_emulation_save_5, EmulationActivity.MENU_ACTION_SAVE_SLOT5);
- buttonsActionsMap.append(R.id.menu_emulation_load_1, EmulationActivity.MENU_ACTION_LOAD_SLOT1);
- buttonsActionsMap.append(R.id.menu_emulation_load_2, EmulationActivity.MENU_ACTION_LOAD_SLOT2);
- buttonsActionsMap.append(R.id.menu_emulation_load_3, EmulationActivity.MENU_ACTION_LOAD_SLOT3);
- buttonsActionsMap.append(R.id.menu_emulation_load_4, EmulationActivity.MENU_ACTION_LOAD_SLOT4);
- buttonsActionsMap.append(R.id.menu_emulation_load_5, EmulationActivity.MENU_ACTION_LOAD_SLOT5);
- buttonsActionsMap.append(R.id.menu_change_disc, EmulationActivity.MENU_ACTION_CHANGE_DISC);
- buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT);
buttonsActionsMap.append(R.id.menu_emulation_joystick_rel_center,
EmulationActivity.MENU_ACTION_JOYSTICK_REL_CENTER);
buttonsActionsMap.append(R.id.menu_emulation_rumble, EmulationActivity.MENU_ACTION_RUMBLE);
@@ -191,8 +165,6 @@ public final class EmulationActivity extends AppCompatActivity
EmulationActivity.MENU_SET_IR_SENSITIVITY);
buttonsActionsMap.append(R.id.menu_emulation_choose_doubletap,
EmulationActivity.MENU_ACTION_CHOOSE_DOUBLETAP);
- buttonsActionsMap.append(R.id.menu_screen_orientation,
- EmulationActivity.MENU_ACTION_SCREEN_ORIENTATION);
buttonsActionsMap.append(R.id.menu_emulation_motion_controls,
EmulationActivity.MENU_ACTION_MOTION_CONTROLS);
}
@@ -470,35 +442,13 @@ public final class EmulationActivity extends AppCompatActivity
}
}
- @Override
- public boolean onCreateOptionsMenu(Menu menu)
+ public void showOverlayControlsMenu(@NonNull View anchor)
{
- // Inflate the menu; this adds items to the action bar if it is present.
- if (sIsGameCubeGame)
- {
- getMenuInflater().inflate(R.menu.menu_emulation, menu);
- }
- else
- {
- getMenuInflater().inflate(R.menu.menu_emulation_wii, menu);
- }
+ PopupMenu popup = new PopupMenu(this, anchor);
+ Menu menu = popup.getMenu();
- mPauseEmulationButton = menu.findItem(R.id.menu_emulation_pause);
- mUnpauseEmulationButton = menu.findItem(R.id.menu_emulation_unpause);
-
- if (sUserPausedEmulation)
- {
- showUnpauseEmulationButton();
- }
-
- if (mSettings.getSection(SettingsFile.FILE_NAME_DOLPHIN, Settings.SECTION_INI_CORE)
- .getBoolean(SettingsFile.KEY_ENABLE_SAVE_STATES, false))
- {
- menu.findItem(R.id.menu_quicksave).setVisible(true);
- menu.findItem(R.id.menu_quickload).setVisible(true);
- menu.findItem(R.id.menu_emulation_save_root).setVisible(true);
- menu.findItem(R.id.menu_emulation_load_root).setVisible(true);
- }
+ int id = sIsGameCubeGame ? R.menu.menu_overlay_controls_gc : R.menu.menu_overlay_controls_wii;
+ popup.getMenuInflater().inflate(id, menu);
// Populate the checkbox value for joystick center on touch
menu.findItem(R.id.menu_emulation_joystick_rel_center)
@@ -506,7 +456,9 @@ public final class EmulationActivity extends AppCompatActivity
menu.findItem(R.id.menu_emulation_rumble)
.setChecked(mPreferences.getBoolean("phoneRumble", true));
- return true;
+ popup.setOnMenuItemClickListener(this::onOptionsItemSelected);
+
+ popup.show();
}
@SuppressWarnings("WrongConstant")
@@ -735,6 +687,8 @@ public final class EmulationActivity extends AppCompatActivity
}
else
{
+ closeSubmenu();
+ closeMenu();
mEmulationFragment.startConfiguringControls();
}
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java
index 2e55d0df70..256a1a8188 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/MenuFragment.java
@@ -1,5 +1,6 @@
package org.dolphinemu.dolphinemu.fragments;
+import android.content.pm.PackageManager;
import android.os.Bundle;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
@@ -19,8 +20,10 @@ import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
public final class MenuFragment extends Fragment implements View.OnClickListener
{
+ private TextView mTitleText;
private View mPauseEmulation;
private View mUnpauseEmulation;
+
private static final String KEY_TITLE = "title";
private static SparseIntArray buttonsActionsMap = new SparseIntArray();
@@ -38,8 +41,12 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
.append(R.id.menu_emulation_save_root, EmulationActivity.MENU_ACTION_SAVE_ROOT);
buttonsActionsMap
.append(R.id.menu_emulation_load_root, EmulationActivity.MENU_ACTION_LOAD_ROOT);
+ buttonsActionsMap
+ .append(R.id.menu_overlay_controls, EmulationActivity.MENU_ACTION_OVERLAY_CONTROLS);
buttonsActionsMap
.append(R.id.menu_refresh_wiimotes, EmulationActivity.MENU_ACTION_REFRESH_WIIMOTES);
+ buttonsActionsMap
+ .append(R.id.menu_screen_orientation, EmulationActivity.MENU_ACTION_SCREEN_ORIENTATION);
buttonsActionsMap.append(R.id.menu_change_disc, EmulationActivity.MENU_ACTION_CHANGE_DISC);
buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT);
}
@@ -82,6 +89,21 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
options.findViewById(R.id.menu_emulation_load_root).setVisibility(View.VISIBLE);
}
+ PackageManager packageManager = requireActivity().getPackageManager();
+
+ if (!packageManager.hasSystemFeature(PackageManager.FEATURE_TOUCHSCREEN))
+ {
+ options.findViewById(R.id.menu_overlay_controls).setVisibility(View.GONE);
+ }
+
+ // Old devices which support both portrait and landscape may report support for neither,
+ // so we only hide the orientation button if the device only supports one orientation
+ if (packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_PORTRAIT) !=
+ packageManager.hasSystemFeature(PackageManager.FEATURE_SCREEN_LANDSCAPE))
+ {
+ options.findViewById(R.id.menu_screen_orientation).setVisibility(View.GONE);
+ }
+
for (int childIndex = 0; childIndex < options.getChildCount(); childIndex++)
{
Button button = (Button) options.getChildAt(childIndex);
@@ -89,11 +111,11 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
button.setOnClickListener(this);
}
- TextView titleText = rootView.findViewById(R.id.text_game_title);
+ mTitleText = rootView.findViewById(R.id.text_game_title);
String title = getArguments().getString(KEY_TITLE);
if (title != null)
{
- titleText.setText(title);
+ mTitleText.setText(title);
}
return rootView;
@@ -116,6 +138,8 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
public void onClick(View button)
{
int action = buttonsActionsMap.get(button.getId());
+ EmulationActivity activity = (EmulationActivity) requireActivity();
+
if (action == EmulationActivity.MENU_ACTION_PAUSE_EMULATION)
{
EmulationActivity.setHasUserPausedEmulation(true);
@@ -128,9 +152,15 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
NativeLibrary.UnPauseEmulation();
showPauseEmulationButton();
}
+ else if (action == EmulationActivity.MENU_ACTION_OVERLAY_CONTROLS)
+ {
+ // We could use the button parameter as the anchor here, but this often results in a tiny menu
+ // (because the button often is in the middle of the screen), so let's use mTitleText instead
+ activity.showOverlayControlsMenu(mTitleText);
+ }
else if (action >= 0)
{
- ((EmulationActivity) getActivity()).handleMenuAction(action);
+ activity.handleMenuAction(action);
}
}
}
diff --git a/Source/Android/app/src/main/res/layout/fragment_ingame_menu.xml b/Source/Android/app/src/main/res/layout/fragment_ingame_menu.xml
index aa0f307e91..a0c90d1b05 100644
--- a/Source/Android/app/src/main/res/layout/fragment_ingame_menu.xml
+++ b/Source/Android/app/src/main/res/layout/fragment_ingame_menu.xml
@@ -67,11 +67,21 @@
style="@style/InGameMenuOption"
android:visibility="gone"/>
+
+
+
+