Merge pull request #9004 from JosJuice/android-menu-back

Android: Use Back to open the emulation menu on all devices
This commit is contained in:
JMC47 2020-09-12 08:17:23 -04:00 committed by GitHub
commit b1fecbb71c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 347 additions and 567 deletions

View File

@ -5,8 +5,8 @@ import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.SparseIntArray; import android.util.SparseIntArray;
@ -23,8 +23,10 @@ import android.widget.Toast;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog; import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.PopupMenu;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentManager;
@ -62,7 +64,6 @@ public final class EmulationActivity extends AppCompatActivity
private static final String BACKSTACK_NAME_SUBMENU = "submenu"; private static final String BACKSTACK_NAME_SUBMENU = "submenu";
public static final int REQUEST_CHANGE_DISC = 1; public static final int REQUEST_CHANGE_DISC = 1;
private View mDecorView;
private EmulationFragment mEmulationFragment; private EmulationFragment mEmulationFragment;
private SharedPreferences mPreferences; private SharedPreferences mPreferences;
@ -70,9 +71,6 @@ public final class EmulationActivity extends AppCompatActivity
private Settings mSettings; private Settings mSettings;
private MenuItem mPauseEmulationButton;
private MenuItem mUnpauseEmulationButton;
private boolean mDeviceHasTouchScreen; private boolean mDeviceHasTouchScreen;
private boolean mMenuVisible; private boolean mMenuVisible;
@ -85,7 +83,6 @@ public final class EmulationActivity extends AppCompatActivity
private int mPlatform; private int mPlatform;
private String[] mPaths; private String[] mPaths;
private static boolean sUserPausedEmulation; private static boolean sUserPausedEmulation;
private boolean backPressedOnce = false;
public static final String EXTRA_SELECTED_GAMES = "SelectedGames"; public static final String EXTRA_SELECTED_GAMES = "SelectedGames";
public static final String EXTRA_SELECTED_TITLE = "SelectedTitle"; public static final String EXTRA_SELECTED_TITLE = "SelectedTitle";
@ -104,7 +101,7 @@ public final class EmulationActivity extends AppCompatActivity
MENU_ACTION_LOAD_SLOT6, MENU_ACTION_EXIT, MENU_ACTION_CHANGE_DISC, 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_RESET_OVERLAY, MENU_SET_IR_SENSITIVITY, MENU_ACTION_CHOOSE_DOUBLETAP,
MENU_ACTION_SCREEN_ORIENTATION, MENU_ACTION_MOTION_CONTROLS, MENU_ACTION_PAUSE_EMULATION, 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 public @interface MenuAction
{ {
} }
@ -142,7 +139,7 @@ public final class EmulationActivity extends AppCompatActivity
public static final int MENU_ACTION_MOTION_CONTROLS = 30; public static final int MENU_ACTION_MOTION_CONTROLS = 30;
public static final int MENU_ACTION_PAUSE_EMULATION = 31; public static final int MENU_ACTION_PAUSE_EMULATION = 31;
public static final int MENU_ACTION_UNPAUSE_EMULATION = 32; public static final int MENU_ACTION_UNPAUSE_EMULATION = 32;
public static final int MENU_ACTION_OVERLAY_CONTROLS = 33;
private static SparseIntArray buttonsActionsMap = new SparseIntArray(); private static SparseIntArray buttonsActionsMap = new SparseIntArray();
@ -156,33 +153,6 @@ public final class EmulationActivity extends AppCompatActivity
.append(R.id.menu_emulation_adjust_scale, EmulationActivity.MENU_ACTION_ADJUST_SCALE); .append(R.id.menu_emulation_adjust_scale, EmulationActivity.MENU_ACTION_ADJUST_SCALE);
buttonsActionsMap.append(R.id.menu_emulation_choose_controller, buttonsActionsMap.append(R.id.menu_emulation_choose_controller,
EmulationActivity.MENU_ACTION_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, buttonsActionsMap.append(R.id.menu_emulation_joystick_rel_center,
EmulationActivity.MENU_ACTION_JOYSTICK_REL_CENTER); EmulationActivity.MENU_ACTION_JOYSTICK_REL_CENTER);
buttonsActionsMap.append(R.id.menu_emulation_rumble, EmulationActivity.MENU_ACTION_RUMBLE); buttonsActionsMap.append(R.id.menu_emulation_rumble, EmulationActivity.MENU_ACTION_RUMBLE);
@ -192,8 +162,6 @@ public final class EmulationActivity extends AppCompatActivity
EmulationActivity.MENU_SET_IR_SENSITIVITY); EmulationActivity.MENU_SET_IR_SENSITIVITY);
buttonsActionsMap.append(R.id.menu_emulation_choose_doubletap, buttonsActionsMap.append(R.id.menu_emulation_choose_doubletap,
EmulationActivity.MENU_ACTION_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, buttonsActionsMap.append(R.id.menu_emulation_motion_controls,
EmulationActivity.MENU_ACTION_MOTION_CONTROLS); EmulationActivity.MENU_ACTION_MOTION_CONTROLS);
} }
@ -317,33 +285,10 @@ public final class EmulationActivity extends AppCompatActivity
mDeviceHasTouchScreen = getPackageManager().hasSystemFeature("android.hardware.touchscreen"); mDeviceHasTouchScreen = getPackageManager().hasSystemFeature("android.hardware.touchscreen");
mMotionListener = new MotionListener(this); mMotionListener = new MotionListener(this);
int themeId; // Set these options now so that the SurfaceView the game renders into is the right size.
if (mDeviceHasTouchScreen) enableFullscreenImmersive();
{
themeId = R.style.DolphinEmulationBase;
// Get a handle to the Window containing the UI. Toast.makeText(this, getString(R.string.emulation_menu_help), Toast.LENGTH_LONG).show();
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();
Toast.makeText(this, getString(R.string.emulation_touch_button_help), Toast.LENGTH_LONG)
.show();
}
else
{
themeId = R.style.DolphinEmulationTvBase;
}
setTheme(themeId);
Rumble.initRumble(this); Rumble.initRumble(this);
@ -360,10 +305,7 @@ public final class EmulationActivity extends AppCompatActivity
.commit(); .commit();
} }
if (mDeviceHasTouchScreen) setTitle(mSelectedTitle);
{
setTitle(mSelectedTitle);
}
} }
@Override @Override
@ -390,10 +332,20 @@ public final class EmulationActivity extends AppCompatActivity
sUserPausedEmulation = savedInstanceState.getBoolean(EXTRA_USER_PAUSED_EMULATION); sUserPausedEmulation = savedInstanceState.getBoolean(EXTRA_USER_PAUSED_EMULATION);
} }
@Override
public void onWindowFocusChanged(boolean hasFocus)
{
if (hasFocus)
{
enableFullscreenImmersive();
}
}
@Override @Override
protected void onResume() protected void onResume()
{ {
super.onResume(); super.onResume();
if (!sIsGameCubeGame && mPreferences.getInt("motionControlsEnabled", 0) != 2) if (!sIsGameCubeGame && mPreferences.getInt("motionControlsEnabled", 0) != 2)
mMotionListener.enable(); mMotionListener.enable();
} }
@ -414,29 +366,22 @@ public final class EmulationActivity extends AppCompatActivity
@Override @Override
public void onBackPressed() public void onBackPressed()
{ {
if (!mDeviceHasTouchScreen) if (!closeSubmenu())
{ {
boolean popResult = getSupportFragmentManager().popBackStackImmediate( toggleMenu();
BACKSTACK_NAME_SUBMENU, FragmentManager.POP_BACK_STACK_INCLUSIVE);
if (!popResult)
{
toggleMenu();
}
} }
else }
@Override
public boolean onKeyLongPress(int keyCode, @NonNull KeyEvent event)
{
if (keyCode == KeyEvent.KEYCODE_BACK)
{ {
if (backPressedOnce) mEmulationFragment.stopEmulation();
{ finish();
mEmulationFragment.stopEmulation(); return true;
finish();
}
else
{
backPressedOnce = true;
Toast.makeText(this, "Press back again to exit", Toast.LENGTH_LONG).show();
new Handler().postDelayed(() -> backPressedOnce = false, 3000);
}
} }
return super.onKeyLongPress(keyCode, event);
} }
@Override @Override
@ -459,14 +404,13 @@ public final class EmulationActivity extends AppCompatActivity
private void enableFullscreenImmersive() private void enableFullscreenImmersive()
{ {
// It would be nice to use IMMERSIVE_STICKY, but that doesn't show the toolbar. getWindow().getDecorView().setSystemUiVisibility(
mDecorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_STABLE |
View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN |
View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION |
View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_FULLSCREEN |
View.SYSTEM_UI_FLAG_IMMERSIVE); View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
} }
private void updateOrientation() private void updateOrientation()
@ -475,13 +419,22 @@ public final class EmulationActivity extends AppCompatActivity
ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)); ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE));
} }
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() private void toggleMenu()
{ {
boolean result = getSupportFragmentManager().popBackStackImmediate( if (!closeMenu())
BACKSTACK_NAME_MENU, FragmentManager.POP_BACK_STACK_INCLUSIVE);
mMenuVisible = false;
if (!result)
{ {
// Removing the menu failed, so that means it wasn't visible. Add it. // Removing the menu failed, so that means it wasn't visible. Add it.
Fragment fragment = MenuFragment.newInstance(mSelectedTitle); Fragment fragment = MenuFragment.newInstance(mSelectedTitle);
@ -498,35 +451,13 @@ public final class EmulationActivity extends AppCompatActivity
} }
} }
@Override public void showOverlayControlsMenu(@NonNull View anchor)
public boolean onCreateOptionsMenu(Menu menu)
{ {
// Inflate the menu; this adds items to the action bar if it is present. PopupMenu popup = new PopupMenu(this, anchor);
if (sIsGameCubeGame) Menu menu = popup.getMenu();
{
getMenuInflater().inflate(R.menu.menu_emulation, menu);
}
else
{
getMenuInflater().inflate(R.menu.menu_emulation_wii, menu);
}
mPauseEmulationButton = menu.findItem(R.id.menu_emulation_pause); int id = sIsGameCubeGame ? R.menu.menu_overlay_controls_gc : R.menu.menu_overlay_controls_wii;
mUnpauseEmulationButton = menu.findItem(R.id.menu_emulation_unpause); popup.getMenuInflater().inflate(id, menu);
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);
}
// Populate the checkbox value for joystick center on touch // Populate the checkbox value for joystick center on touch
menu.findItem(R.id.menu_emulation_joystick_rel_center) menu.findItem(R.id.menu_emulation_joystick_rel_center)
@ -534,7 +465,9 @@ public final class EmulationActivity extends AppCompatActivity
menu.findItem(R.id.menu_emulation_rumble) menu.findItem(R.id.menu_emulation_rumble)
.setChecked(mPreferences.getBoolean("phoneRumble", true)); .setChecked(mPreferences.getBoolean("phoneRumble", true));
return true; popup.setOnMenuItemClickListener(this::onOptionsItemSelected);
popup.show();
} }
@SuppressWarnings("WrongConstant") @SuppressWarnings("WrongConstant")
@ -608,13 +541,11 @@ public final class EmulationActivity extends AppCompatActivity
case MENU_ACTION_PAUSE_EMULATION: case MENU_ACTION_PAUSE_EMULATION:
sUserPausedEmulation = true; sUserPausedEmulation = true;
NativeLibrary.PauseEmulation(); NativeLibrary.PauseEmulation();
showUnpauseEmulationButton();
return; return;
case MENU_ACTION_UNPAUSE_EMULATION: case MENU_ACTION_UNPAUSE_EMULATION:
sUserPausedEmulation = false; sUserPausedEmulation = false;
NativeLibrary.UnPauseEmulation(); NativeLibrary.UnPauseEmulation();
showPauseEmulationButton();
return; return;
// Screenshot capturing // Screenshot capturing
@ -631,19 +562,12 @@ public final class EmulationActivity extends AppCompatActivity
NativeLibrary.LoadState(9); NativeLibrary.LoadState(9);
return; return;
// TV Menu only
case MENU_ACTION_SAVE_ROOT: case MENU_ACTION_SAVE_ROOT:
if (!mDeviceHasTouchScreen) showSubMenu(SaveLoadStateFragment.SaveOrLoad.SAVE);
{
showSubMenu(SaveLoadStateFragment.SaveOrLoad.SAVE);
}
return; return;
case MENU_ACTION_LOAD_ROOT: case MENU_ACTION_LOAD_ROOT:
if (!mDeviceHasTouchScreen) showSubMenu(SaveLoadStateFragment.SaveOrLoad.LOAD);
{
showSubMenu(SaveLoadStateFragment.SaveOrLoad.LOAD);
}
return; return;
// Save state slots // Save state slots
@ -718,37 +642,17 @@ public final class EmulationActivity extends AppCompatActivity
return; return;
case MENU_ACTION_EXIT: case MENU_ACTION_EXIT:
// ATV menu is built using a fragment, this will pop that fragment before emulation ends.
if (TvUtil.isLeanback(getApplicationContext()))
toggleMenu(); // Hide the menu (it will be showing since we just clicked it)
mEmulationFragment.stopEmulation(); mEmulationFragment.stopEmulation();
finish(); finish();
return; return;
} }
} }
private void showPauseEmulationButton()
{
mUnpauseEmulationButton.setVisible(false);
mPauseEmulationButton.setVisible(true);
}
private void showUnpauseEmulationButton()
{
mPauseEmulationButton.setVisible(false);
mUnpauseEmulationButton.setVisible(true);
}
public static boolean getHasUserPausedEmulation() public static boolean getHasUserPausedEmulation()
{ {
return sUserPausedEmulation; return sUserPausedEmulation;
} }
public static void setHasUserPausedEmulation(boolean value)
{
sUserPausedEmulation = value;
}
private void toggleJoystickRelCenter(boolean state) private void toggleJoystickRelCenter(boolean state)
{ {
final SharedPreferences.Editor editor = mPreferences.edit(); final SharedPreferences.Editor editor = mPreferences.edit();
@ -764,7 +668,6 @@ public final class EmulationActivity extends AppCompatActivity
Rumble.setPhoneVibrator(state, this); Rumble.setPhoneVibrator(state, this);
} }
private void editControlsPlacement() private void editControlsPlacement()
{ {
if (mEmulationFragment.isConfiguringControls()) if (mEmulationFragment.isConfiguringControls())
@ -773,6 +676,8 @@ public final class EmulationActivity extends AppCompatActivity
} }
else else
{ {
closeSubmenu();
closeMenu();
mEmulationFragment.startConfiguringControls(); mEmulationFragment.startConfiguringControls();
} }
} }
@ -781,7 +686,7 @@ public final class EmulationActivity extends AppCompatActivity
@Override @Override
public boolean dispatchKeyEvent(KeyEvent event) public boolean dispatchKeyEvent(KeyEvent event)
{ {
if (mMenuVisible) if (mMenuVisible || event.getKeyCode() == KeyEvent.KEYCODE_BACK)
{ {
return super.dispatchKeyEvent(event); return super.dispatchKeyEvent(event);
} }
@ -791,14 +696,6 @@ public final class EmulationActivity extends AppCompatActivity
switch (event.getAction()) switch (event.getAction())
{ {
case KeyEvent.ACTION_DOWN: case KeyEvent.ACTION_DOWN:
// Handling the case where the back button is pressed.
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK)
{
onBackPressed();
return true;
}
// Normal key events.
action = NativeLibrary.ButtonState.PRESSED; action = NativeLibrary.ButtonState.PRESSED;
break; break;
case KeyEvent.ACTION_UP: case KeyEvent.ACTION_UP:
@ -1176,6 +1073,52 @@ public final class EmulationActivity extends AppCompatActivity
.show(); .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);
}
@Override @Override
public boolean dispatchGenericMotionEvent(MotionEvent event) public boolean dispatchGenericMotionEvent(MotionEvent event)
{ {

View File

@ -12,7 +12,6 @@ import org.dolphinemu.dolphinemu.features.settings.model.view.InputBindingSettin
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter; import org.dolphinemu.dolphinemu.features.settings.ui.SettingsAdapter;
import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper; import org.dolphinemu.dolphinemu.utils.ControllerMappingHelper;
import org.dolphinemu.dolphinemu.utils.Log; import org.dolphinemu.dolphinemu.utils.Log;
import org.dolphinemu.dolphinemu.utils.TvUtil;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -63,8 +62,8 @@ public final class MotionAlertDialog extends AlertDialog
@Override @Override
public boolean onKeyLongPress(int keyCode, @NonNull KeyEvent event) public boolean onKeyLongPress(int keyCode, @NonNull KeyEvent event)
{ {
// Option to clear by long back is only needed on the TV interface // Intended for devices with no touchscreen or mouse
if (TvUtil.isLeanback(getContext()) && keyCode == KeyEvent.KEYCODE_BACK) if (keyCode == KeyEvent.KEYCODE_BACK)
{ {
setting.clearValue(mAdapter.getSettings()); setting.clearValue(mAdapter.getSettings());
dismiss(); dismiss();

View File

@ -1,5 +1,7 @@
package org.dolphinemu.dolphinemu.fragments; package org.dolphinemu.dolphinemu.fragments;
import android.content.pm.PackageManager;
import android.graphics.Rect;
import android.os.Bundle; import android.os.Bundle;
import android.util.SparseIntArray; import android.util.SparseIntArray;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -19,8 +21,10 @@ import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
public final class MenuFragment extends Fragment implements View.OnClickListener public final class MenuFragment extends Fragment implements View.OnClickListener
{ {
private TextView mTitleText;
private View mPauseEmulation; private View mPauseEmulation;
private View mUnpauseEmulation; private View mUnpauseEmulation;
private static final String KEY_TITLE = "title"; private static final String KEY_TITLE = "title";
private static SparseIntArray buttonsActionsMap = new SparseIntArray(); private static SparseIntArray buttonsActionsMap = new SparseIntArray();
@ -38,8 +42,12 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
.append(R.id.menu_emulation_save_root, EmulationActivity.MENU_ACTION_SAVE_ROOT); .append(R.id.menu_emulation_save_root, EmulationActivity.MENU_ACTION_SAVE_ROOT);
buttonsActionsMap buttonsActionsMap
.append(R.id.menu_emulation_load_root, EmulationActivity.MENU_ACTION_LOAD_ROOT); .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 buttonsActionsMap
.append(R.id.menu_refresh_wiimotes, EmulationActivity.MENU_ACTION_REFRESH_WIIMOTES); .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_change_disc, EmulationActivity.MENU_ACTION_CHANGE_DISC);
buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT); buttonsActionsMap.append(R.id.menu_exit, EmulationActivity.MENU_ACTION_EXIT);
} }
@ -55,6 +63,14 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
return fragment; return fragment;
} }
// This is primarily intended to account for any navigation bar at the bottom of the screen
private int getBottomPaddingRequired()
{
Rect visibleFrame = new Rect();
requireActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleFrame);
return visibleFrame.bottom - visibleFrame.top - getResources().getDisplayMetrics().heightPixels;
}
@Override @Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{ {
@ -65,10 +81,7 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
mPauseEmulation = options.findViewById(R.id.menu_pause_emulation); mPauseEmulation = options.findViewById(R.id.menu_pause_emulation);
mUnpauseEmulation = options.findViewById(R.id.menu_unpause_emulation); mUnpauseEmulation = options.findViewById(R.id.menu_unpause_emulation);
if (EmulationActivity.getHasUserPausedEmulation()) updatePauseUnpauseVisibility();
{
showUnpauseEmulationButton();
}
boolean enableSaveStates = ((EmulationActivity) getActivity()).getSettings() boolean enableSaveStates = ((EmulationActivity) getActivity()).getSettings()
.getSection(SettingsFile.FILE_NAME_DOLPHIN, Settings.SECTION_INI_CORE) .getSection(SettingsFile.FILE_NAME_DOLPHIN, Settings.SECTION_INI_CORE)
@ -82,6 +95,41 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
options.findViewById(R.id.menu_emulation_load_root).setVisibility(View.VISIBLE); 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);
}
if (EmulationActivity.isGameCubeGame())
{
options.findViewById(R.id.menu_refresh_wiimotes).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);
}
int bottomPaddingRequired = getBottomPaddingRequired();
// Provide a safe zone between the navigation bar and Exit Emulation to avoid accidental touches
float density = getResources().getDisplayMetrics().density;
if (bottomPaddingRequired >= 32 * density)
{
bottomPaddingRequired += 32 * density;
}
if (bottomPaddingRequired > rootView.getPaddingBottom())
{
rootView.setPadding(rootView.getPaddingLeft(), rootView.getPaddingTop(),
rootView.getPaddingRight(), bottomPaddingRequired);
}
for (int childIndex = 0; childIndex < options.getChildCount(); childIndex++) for (int childIndex = 0; childIndex < options.getChildCount(); childIndex++)
{ {
Button button = (Button) options.getChildAt(childIndex); Button button = (Button) options.getChildAt(childIndex);
@ -89,26 +137,24 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
button.setOnClickListener(this); button.setOnClickListener(this);
} }
TextView titleText = rootView.findViewById(R.id.text_game_title); rootView.findViewById(R.id.menu_exit).setOnClickListener(this);
mTitleText = rootView.findViewById(R.id.text_game_title);
String title = getArguments().getString(KEY_TITLE); String title = getArguments().getString(KEY_TITLE);
if (title != null) if (title != null)
{ {
titleText.setText(title); mTitleText.setText(title);
} }
return rootView; return rootView;
} }
private void showPauseEmulationButton() private void updatePauseUnpauseVisibility()
{ {
mUnpauseEmulation.setVisibility(View.GONE); boolean paused = EmulationActivity.getHasUserPausedEmulation();
mPauseEmulation.setVisibility(View.VISIBLE);
}
private void showUnpauseEmulationButton() mUnpauseEmulation.setVisibility(paused ? View.VISIBLE : View.GONE);
{ mPauseEmulation.setVisibility(paused ? View.GONE : View.VISIBLE);
mPauseEmulation.setVisibility(View.GONE);
mUnpauseEmulation.setVisibility(View.VISIBLE);
} }
@SuppressWarnings("WrongConstant") @SuppressWarnings("WrongConstant")
@ -116,21 +162,23 @@ public final class MenuFragment extends Fragment implements View.OnClickListener
public void onClick(View button) public void onClick(View button)
{ {
int action = buttonsActionsMap.get(button.getId()); int action = buttonsActionsMap.get(button.getId());
if (action == EmulationActivity.MENU_ACTION_PAUSE_EMULATION) EmulationActivity activity = (EmulationActivity) requireActivity();
if (action == EmulationActivity.MENU_ACTION_OVERLAY_CONTROLS)
{ {
EmulationActivity.setHasUserPausedEmulation(true); // We could use the button parameter as the anchor here, but this often results in a tiny menu
NativeLibrary.PauseEmulation(); // (because the button often is in the middle of the screen), so let's use mTitleText instead
showUnpauseEmulationButton(); activity.showOverlayControlsMenu(mTitleText);
}
else if (action == EmulationActivity.MENU_ACTION_UNPAUSE_EMULATION)
{
EmulationActivity.setHasUserPausedEmulation(false);
NativeLibrary.UnPauseEmulation();
showPauseEmulationButton();
} }
else if (action >= 0) else if (action >= 0)
{ {
((EmulationActivity) getActivity()).handleMenuAction(action); activity.handleMenuAction(action);
}
if (action == EmulationActivity.MENU_ACTION_PAUSE_EMULATION ||
action == EmulationActivity.MENU_ACTION_UNPAUSE_EMULATION)
{
updatePauseUnpauseVisibility();
} }
} }
} }

View File

@ -0,0 +1,7 @@
<SurfaceView xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/surface_emulation"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:focusable="false"
android:focusableInTouchMode="false"
/>

View File

@ -1,38 +0,0 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:keepScreenOn="true"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/frame_content">
<FrameLayout
android:id="@+id/frame_emulation_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<org.dolphinemu.dolphinemu.ui.NVidiaShieldWorkaroundView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:baselineAligned="false">
<FrameLayout
android:id="@+id/frame_menu"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".25"
tools:layout="@layout/fragment_ingame_menu"/>
<FrameLayout
android:id="@+id/frame_submenu"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight=".75"/>
</LinearLayout>
</FrameLayout>

View File

@ -1,6 +1,8 @@
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:keepScreenOn="true"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/frame_content"> android:id="@+id/frame_content">
<FrameLayout <FrameLayout
@ -8,4 +10,27 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>
<org.dolphinemu.dolphinemu.ui.NVidiaShieldWorkaroundView
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:baselineAligned="false">
<FrameLayout
android:id="@+id/frame_menu"
android:layout_width="260dp"
android:layout_height="match_parent"
tools:layout="@layout/fragment_ingame_menu"/>
<FrameLayout
android:id="@+id/frame_submenu"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</LinearLayout>
</FrameLayout> </FrameLayout>

View File

@ -4,6 +4,7 @@
android:orientation="vertical" android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingBottom="16dp"
android:background="@color/dolphin_blue_dark" android:background="@color/dolphin_blue_dark"
tools:layout_width="250dp"> tools:layout_width="250dp">
@ -14,7 +15,9 @@
tools:text="The Legend of Zelda: The Wind Waker" tools:text="The Legend of Zelda: The Wind Waker"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="20sp" android:textSize="20sp"
android:layout_margin="32dp"/> android:layout_marginHorizontal="32dp"
android:layout_marginTop="32dp"
android:layout_marginBottom="16dp"/>
<ScrollView <ScrollView
android:layout_width="match_parent" android:layout_width="match_parent"
@ -67,23 +70,41 @@
style="@style/InGameMenuOption" style="@style/InGameMenuOption"
android:visibility="gone"/> android:visibility="gone"/>
<Button
android:id="@+id/menu_overlay_controls"
android:text="@string/emulation_overlay_controls"
style="@style/InGameMenuOption"/>
<Button <Button
android:id="@+id/menu_refresh_wiimotes" android:id="@+id/menu_refresh_wiimotes"
android:text="@string/emulation_refresh_wiimotes" android:text="@string/emulation_refresh_wiimotes"
style="@style/InGameMenuOption"/> style="@style/InGameMenuOption"/>
<Button
android:id="@+id/menu_screen_orientation"
android:text="@string/emulation_screen_orientation"
style="@style/InGameMenuOption"/>
<Button <Button
android:id="@+id/menu_change_disc" android:id="@+id/menu_change_disc"
android:text="@string/emulation_change_disc" android:text="@string/emulation_change_disc"
style="@style/InGameMenuOption"/> style="@style/InGameMenuOption"/>
<Button
android:id="@+id/menu_exit"
android:text="@string/emulation_exit"
style="@style/InGameMenuOption"/>
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
<View
android:id="@+id/divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#FFFFFF"
android:layout_marginTop="24dp"
android:layout_marginBottom="16dp"/>
<Button
android:id="@+id/menu_exit"
android:text="@string/emulation_exit"
style="@style/InGameMenuOption"/>
</LinearLayout> </LinearLayout>

View File

@ -2,51 +2,51 @@
android:id="@+id/grid_state_slots" android:id="@+id/grid_state_slots"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:columnCount="3" android:columnCount="@integer/loadsave_state_columns"
android:rowCount="2" android:rowCount="@integer/loadsave_state_rows"
android:layout_gravity="center" android:layout_gravity="center"
android:background="#af000000"> android:background="#af000000">
<Button <Button
android:id="@+id/loadsave_state_button_1" android:id="@+id/loadsave_state_button_1"
android:layout_width="128dp" android:layout_width="128dp"
android:layout_height="128dp" android:layout_height="96dp"
android:text="@string/emulation_slot1" android:text="@string/emulation_slot1"
style="@style/OverlayInGameMenuOption"/> style="@style/OverlayInGameMenuOption"/>
<Button <Button
android:id="@+id/loadsave_state_button_2" android:id="@+id/loadsave_state_button_2"
android:layout_width="128dp" android:layout_width="128dp"
android:layout_height="128dp" android:layout_height="96dp"
android:text="@string/emulation_slot2" android:text="@string/emulation_slot2"
style="@style/OverlayInGameMenuOption"/> style="@style/OverlayInGameMenuOption"/>
<Button <Button
android:id="@+id/loadsave_state_button_3" android:id="@+id/loadsave_state_button_3"
android:layout_width="128dp" android:layout_width="128dp"
android:layout_height="128dp" android:layout_height="96dp"
android:text="@string/emulation_slot3" android:text="@string/emulation_slot3"
style="@style/OverlayInGameMenuOption"/> style="@style/OverlayInGameMenuOption"/>
<Button <Button
android:id="@+id/loadsave_state_button_4" android:id="@+id/loadsave_state_button_4"
android:layout_width="128dp" android:layout_width="128dp"
android:layout_height="128dp" android:layout_height="96dp"
android:text="@string/emulation_slot4" android:text="@string/emulation_slot4"
style="@style/OverlayInGameMenuOption"/> style="@style/OverlayInGameMenuOption"/>
<Button <Button
android:id="@+id/loadsave_state_button_5" android:id="@+id/loadsave_state_button_5"
android:layout_width="128dp" android:layout_width="128dp"
android:layout_height="128dp" android:layout_height="96dp"
android:text="@string/emulation_slot5" android:text="@string/emulation_slot5"
style="@style/OverlayInGameMenuOption"/> style="@style/OverlayInGameMenuOption"/>
<Button <Button
android:id="@+id/loadsave_state_button_6" android:id="@+id/loadsave_state_button_6"
android:layout_width="128dp" android:layout_width="128dp"
android:layout_height="128dp" android:layout_height="96dp"
android:text="@string/emulation_slot6" android:text="@string/emulation_slot6"
style="@style/OverlayInGameMenuOption"/> style="@style/OverlayInGameMenuOption"/>
</GridLayout> </GridLayout>

View File

@ -1,143 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="org.dolphinemu.dolphinemu.activities.EmulationActivity">
<item
android:id="@+id/menu_emulation_pause"
app:showAsAction="ifRoom"
android:icon="@drawable/lb_ic_pause"
android:title="@string/pause_emulation"/>
<item
android:id="@+id/menu_emulation_unpause"
app:showAsAction="ifRoom"
android:icon="@drawable/lb_ic_play"
android:title="@string/unpause_emulation"
android:visible="false"/>
<item
android:id="@+id/menu_emulation_screenshot"
app:showAsAction="ifRoom"
android:icon="@drawable/ic_screenshot"
android:title="@string/emulation_screenshot"/>
<item
android:id="@+id/menu_quicksave"
app:showAsAction="ifRoom"
android:icon="@drawable/ic_quicksave"
android:title="@string/emulation_quicksave"
android:visible="false"/>
<item
android:id="@+id/menu_quickload"
app:showAsAction="ifRoom"
android:icon="@drawable/ic_quickload"
android:title="@string/emulation_quickload"
android:visible="false"/>
<!-- Save State Slots -->
<item
android:id="@+id/menu_emulation_save_root"
app:showAsAction="never"
android:title="@string/emulation_savestate"
android:visible="false">
<menu>
<item
android:id="@+id/menu_emulation_save_1"
android:title="@string/emulation_slot1"/>
<item
android:id="@+id/menu_emulation_save_2"
android:title="@string/emulation_slot2"/>
<item
android:id="@+id/menu_emulation_save_3"
android:title="@string/emulation_slot3"/>
<item
android:id="@+id/menu_emulation_save_4"
android:title="@string/emulation_slot4"/>
<item
android:id="@+id/menu_emulation_save_5"
android:title="@string/emulation_slot5"/>
</menu>
</item>
<!-- Load State Slots -->
<item
android:id="@+id/menu_emulation_load_root"
app:showAsAction="never"
android:title="@string/emulation_loadstate"
android:visible="false">
<menu>
<item
android:id="@+id/menu_emulation_load_1"
android:title="@string/emulation_slot1"/>
<item
android:id="@+id/menu_emulation_load_2"
android:title="@string/emulation_slot2"/>
<item
android:id="@+id/menu_emulation_load_3"
android:title="@string/emulation_slot3"/>
<item
android:id="@+id/menu_emulation_load_4"
android:title="@string/emulation_slot4"/>
<item
android:id="@+id/menu_emulation_load_5"
android:title="@string/emulation_slot5"/>
</menu>
</item>
<item
android:id="@+id/menu_emulation_overlay_controls"
app:showAsAction="never"
android:title="@string/emulation_overlay_controls">
<menu>
<item
android:id="@+id/menu_emulation_edit_layout"
android:title="@string/emulation_edit_layout"/>
<item
android:id="@+id/menu_emulation_toggle_controls"
android:title="@string/emulation_toggle_controls"/>
<item
android:id="@+id/menu_emulation_adjust_scale"
android:title="@string/emulation_control_scale"/>
<item
android:id="@+id/menu_emulation_joystick_rel_center"
android:checkable="true"
android:title="@string/emulation_control_joystick_rel_center"/>
<item
android:id="@+id/menu_emulation_rumble"
android:checkable="true"
android:title="@string/emulation_control_rumble"/>
<item
android:id="@+id/menu_emulation_reset_overlay"
android:title="@string/emulation_touch_overlay_reset"/>
</menu>
</item>
<item
android:id="@+id/menu_screen_orientation"
app:showAsAction="never"
android:title="@string/emulation_screen_orientation"/>
<item
android:id="@+id/menu_change_disc"
app:showAsAction="never"
android:title="@string/emulation_change_disc"/>
<item
android:id="@+id/menu_exit"
app:showAsAction="never"
android:title="@string/emulation_exit"/>
</menu>

View File

@ -1,163 +0,0 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
tools:context="org.dolphinemu.dolphinemu.activities.EmulationActivity">
<item
android:id="@+id/menu_emulation_pause"
app:showAsAction="ifRoom"
android:icon="@drawable/lb_ic_pause"
android:title="@string/pause_emulation"/>
<item
android:id="@+id/menu_emulation_unpause"
app:showAsAction="ifRoom"
android:icon="@drawable/lb_ic_play"
android:title="@string/unpause_emulation"
android:visible="false"/>
<item
android:id="@+id/menu_emulation_screenshot"
app:showAsAction="ifRoom"
android:icon="@drawable/ic_screenshot"
android:title="@string/emulation_screenshot"/>
<item
android:id="@+id/menu_quicksave"
app:showAsAction="ifRoom"
android:icon="@drawable/ic_quicksave"
android:title="@string/emulation_quicksave"
android:visible="false"/>
<item
android:id="@+id/menu_quickload"
app:showAsAction="ifRoom"
android:icon="@drawable/ic_quickload"
android:title="@string/emulation_quickload"
android:visible="false"/>
<!-- Save State Slots -->
<item
android:id="@+id/menu_emulation_save_root"
app:showAsAction="never"
android:title="@string/emulation_savestate"
android:visible="false">
<menu>
<item
android:id="@+id/menu_emulation_save_1"
android:title="@string/emulation_slot1"/>
<item
android:id="@+id/menu_emulation_save_2"
android:title="@string/emulation_slot2"/>
<item
android:id="@+id/menu_emulation_save_3"
android:title="@string/emulation_slot3"/>
<item
android:id="@+id/menu_emulation_save_4"
android:title="@string/emulation_slot4"/>
<item
android:id="@+id/menu_emulation_save_5"
android:title="@string/emulation_slot5"/>
</menu>
</item>
<!-- Load State Slots -->
<item
android:id="@+id/menu_emulation_load_root"
app:showAsAction="never"
android:title="@string/emulation_loadstate"
android:visible="false">
<menu>
<item
android:id="@+id/menu_emulation_load_1"
android:title="@string/emulation_slot1"/>
<item
android:id="@+id/menu_emulation_load_2"
android:title="@string/emulation_slot2"/>
<item
android:id="@+id/menu_emulation_load_3"
android:title="@string/emulation_slot3"/>
<item
android:id="@+id/menu_emulation_load_4"
android:title="@string/emulation_slot4"/>
<item
android:id="@+id/menu_emulation_load_5"
android:title="@string/emulation_slot5"/>
</menu>
</item>
<item
android:id="@+id/menu_emulation_overlay_controls"
app:showAsAction="never"
android:title="@string/emulation_overlay_controls">
<menu>
<item
android:id="@+id/menu_emulation_edit_layout"
android:title="@string/emulation_edit_layout"/>
<item
android:id="@+id/menu_emulation_toggle_controls"
android:title="@string/emulation_toggle_controls"/>
<item
android:id="@+id/menu_emulation_adjust_scale"
android:title="@string/emulation_control_scale"/>
<group android:checkableBehavior="all">
<item
android:id="@+id/menu_emulation_joystick_rel_center"
android:checkable="true"
android:title="@string/emulation_control_joystick_rel_center"/>
<item
android:id="@+id/menu_emulation_rumble"
android:checkable="true"
android:title="@string/emulation_control_rumble"/>
</group>
<item
android:id="@+id/menu_emulation_choose_controller"
android:title="@string/emulation_choose_controller"/>
<item
android:id="@+id/menu_emulation_motion_controls"
android:title="@string/emulation_motion_controls"/>
<item
android:id="@+id/menu_emulation_ir_group"
android:title="@string/emulation_ir_group"
app:showAsAction="never">
<menu>
<item
android:id="@+id/menu_emulation_set_ir_sensitivity"
android:title="@string/emulation_ir_sensitivity"
app:showAsAction="ifRoom"/>
<item
android:id="@+id/menu_emulation_choose_doubletap"
android:title="@string/emulation_choose_doubletap"
app:showAsAction="ifRoom"/>
</menu>
</item>
<item
android:id="@+id/menu_emulation_reset_overlay"
android:title="@string/emulation_touch_overlay_reset"/>
</menu>
</item>
<item
android:id="@+id/menu_screen_orientation"
app:showAsAction="never"
android:title="@string/emulation_screen_orientation"/>
<item
android:id="@+id/menu_change_disc"
app:showAsAction="never"
android:title="@string/emulation_change_disc"/>
</menu>

View File

@ -0,0 +1,30 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.dolphinemu.dolphinemu.activities.EmulationActivity">
<item
android:id="@+id/menu_emulation_edit_layout"
android:title="@string/emulation_edit_layout"/>
<item
android:id="@+id/menu_emulation_toggle_controls"
android:title="@string/emulation_toggle_controls"/>
<item
android:id="@+id/menu_emulation_adjust_scale"
android:title="@string/emulation_control_scale"/>
<item
android:id="@+id/menu_emulation_joystick_rel_center"
android:checkable="true"
android:title="@string/emulation_control_joystick_rel_center"/>
<item
android:id="@+id/menu_emulation_rumble"
android:checkable="true"
android:title="@string/emulation_control_rumble"/>
<item
android:id="@+id/menu_emulation_reset_overlay"
android:title="@string/emulation_touch_overlay_reset"/>
</menu>

View File

@ -0,0 +1,53 @@
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="org.dolphinemu.dolphinemu.activities.EmulationActivity">
<item
android:id="@+id/menu_emulation_edit_layout"
android:title="@string/emulation_edit_layout"/>
<item
android:id="@+id/menu_emulation_toggle_controls"
android:title="@string/emulation_toggle_controls"/>
<item
android:id="@+id/menu_emulation_adjust_scale"
android:title="@string/emulation_control_scale"/>
<group android:checkableBehavior="all">
<item
android:id="@+id/menu_emulation_joystick_rel_center"
android:checkable="true"
android:title="@string/emulation_control_joystick_rel_center"/>
<item
android:id="@+id/menu_emulation_rumble"
android:checkable="true"
android:title="@string/emulation_control_rumble"/>
</group>
<item
android:id="@+id/menu_emulation_choose_controller"
android:title="@string/emulation_choose_controller"/>
<item
android:id="@+id/menu_emulation_motion_controls"
android:title="@string/emulation_motion_controls"/>
<item
android:id="@+id/menu_emulation_ir_group"
android:title="@string/emulation_ir_group">
<menu>
<item
android:id="@+id/menu_emulation_set_ir_sensitivity"
android:title="@string/emulation_ir_sensitivity"/>
<item
android:id="@+id/menu_emulation_choose_doubletap"
android:title="@string/emulation_choose_doubletap"/>
</menu>
</item>
<item
android:id="@+id/menu_emulation_reset_overlay"
android:title="@string/emulation_touch_overlay_reset"/>
</menu>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="loadsave_state_columns">2</integer>
<integer name="loadsave_state_rows">3</integer>
</resources>

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<integer name="loadsave_state_columns">3</integer>
<integer name="loadsave_state_rows">2</integer>
</resources>

View File

@ -1,6 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources>
<integer name="game_grid_columns">3</integer> <integer name="game_grid_columns">3</integer>
<integer name="loadsave_state_columns">1</integer>
<integer name="loadsave_state_rows">6</integer>
<!-- Default GameCube landscape layout --> <!-- Default GameCube landscape layout -->
<integer name="BUTTON_A_X">865</integer> <integer name="BUTTON_A_X">865</integer>

View File

@ -336,7 +336,7 @@
<string name="emulation_screenshot">Take Screenshot</string> <string name="emulation_screenshot">Take Screenshot</string>
<string name="emulation_savestate">Save State</string> <string name="emulation_savestate">Save State</string>
<string name="emulation_loadstate">Load State</string> <string name="emulation_loadstate">Load State</string>
<string name="emulation_exit">Exit</string> <string name="emulation_exit">Exit Emulation</string>
<string name="emulation_slot1">Slot 1</string> <string name="emulation_slot1">Slot 1</string>
<string name="emulation_slot2">Slot 2</string> <string name="emulation_slot2">Slot 2</string>
<string name="emulation_slot3">Slot 3</string> <string name="emulation_slot3">Slot 3</string>
@ -355,7 +355,7 @@
<string name="emulation_control_joystick_rel_center">Relative Stick Center</string> <string name="emulation_control_joystick_rel_center">Relative Stick Center</string>
<string name="emulation_control_rumble">Rumble</string> <string name="emulation_control_rumble">Rumble</string>
<string name="emulation_choose_controller">Choose Controller</string> <string name="emulation_choose_controller">Choose Controller</string>
<string name="emulation_touch_button_help">Swipe down from the top of the screen to access the menu.</string> <string name="emulation_menu_help">Press Back to access the menu.\nLong press Back to exit emulation.</string>
<string name="emulation_touch_overlay_reset">Reset Overlay</string> <string name="emulation_touch_overlay_reset">Reset Overlay</string>
<string name="emulation_ir_group">Touch IR Pointer</string> <string name="emulation_ir_group">Touch IR Pointer</string>
<string name="emulation_ir_sensitivity">IR Sensitivity</string> <string name="emulation_ir_sensitivity">IR Sensitivity</string>

View File

@ -29,21 +29,7 @@
<style name="DolphinDialogBase" parent="Theme.AppCompat.DayNight.Dialog.Alert" /> <style name="DolphinDialogBase" parent="Theme.AppCompat.DayNight.Dialog.Alert" />
<style name="DolphinEmulationBase" parent="Theme.AppCompat.DayNight.DarkActionBar"> <style name="DolphinEmulationBase" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="colorPrimary">@color/dolphin_blue</item>
<item name="colorPrimaryDark">@color/dolphin_blue_dark</item>
<item name="colorAccent">@color/dolphin_purple</item>
<item name="android:windowTranslucentNavigation">true</item>
<item name="android:windowBackground">@android:color/black</item>
<!-- Enable window content transitions -->
<item name="android:windowContentTransitions">true</item>
<item name="android:windowAllowEnterTransitionOverlap">true</item>
<item name="android:windowAllowReturnTransitionOverlap">true</item>
</style>
<style name="DolphinEmulationTvBase" parent="Theme.AppCompat.DayNight.NoActionBar">
<item name="colorPrimary">@color/dolphin_blue</item> <item name="colorPrimary">@color/dolphin_blue</item>
<item name="colorPrimaryDark">@color/dolphin_blue_dark</item> <item name="colorPrimaryDark">@color/dolphin_blue_dark</item>
<item name="colorAccent">@color/dolphin_purple</item> <item name="colorAccent">@color/dolphin_purple</item>