Android: Use Back to open the emulation menu on all devices

https://bugs.dolphin-emu.org/issues/12029

We currently have one way of opening the menu on touch screen
devices (swiping down from the top of the screen to bring up the
action bar and selecting the menu in the action bar), and another
way of opening the menu on Android TV (pressing Back). However,
some devices that claim to support touch (or don't support
leanback? Dolphin currently conflates the two) don't actually let
you swipe down from the top of the screen in the way that Dolphin
expects, notably Chromebooks. There are also some phones where you
can swipe down from the top of the screen but this for some reason
doesn't lead to the action bar becoming visible, though we are
getting less reports about this nowadays than in the past.

This change makes us use the Back method on all devices,
since it should work on all devices with no significant drawbacks.

Unfortunately, we not only have two different ways of triggering
the menu but actually two entirely different menus, with the
non-touch menu not implementing options that only are revelant
when using a touch screen. A later commit will add the missing
features to the menu that we now use on all devices.
This commit is contained in:
JosJuice 2020-04-07 18:02:35 +02:00
parent 67761c7d31
commit cf51642c17
5 changed files with 54 additions and 123 deletions

View File

@ -6,7 +6,6 @@ import android.content.Intent;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.content.pm.ActivityInfo; import android.content.pm.ActivityInfo;
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;
@ -62,7 +61,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;
@ -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";
@ -317,33 +314,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 +334,7 @@ public final class EmulationActivity extends AppCompatActivity
.commit(); .commit();
} }
if (mDeviceHasTouchScreen) setTitle(mSelectedTitle);
{
setTitle(mSelectedTitle);
}
} }
@Override @Override
@ -390,10 +361,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,28 +395,11 @@ public final class EmulationActivity extends AppCompatActivity
@Override @Override
public void onBackPressed() public void onBackPressed()
{ {
if (!mDeviceHasTouchScreen) boolean popResult = getSupportFragmentManager().popBackStackImmediate(
BACKSTACK_NAME_SUBMENU, FragmentManager.POP_BACK_STACK_INCLUSIVE);
if (!popResult)
{ {
boolean popResult = getSupportFragmentManager().popBackStackImmediate( toggleMenu();
BACKSTACK_NAME_SUBMENU, FragmentManager.POP_BACK_STACK_INCLUSIVE);
if (!popResult)
{
toggleMenu();
}
}
else
{
if (backPressedOnce)
{
mEmulationFragment.stopEmulation();
finish();
}
else
{
backPressedOnce = true;
Toast.makeText(this, "Press back again to exit", Toast.LENGTH_LONG).show();
new Handler().postDelayed(() -> backPressedOnce = false, 3000);
}
} }
} }
@ -459,14 +423,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()
@ -631,19 +594,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,9 +674,9 @@ 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. // Hide the menu (it will be showing since we just clicked it)
if (TvUtil.isLeanback(getApplicationContext())) toggleMenu();
toggleMenu(); // Hide the menu (it will be showing since we just clicked it)
mEmulationFragment.stopEmulation(); mEmulationFragment.stopEmulation();
finish(); finish();
return; return;

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,29 @@
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="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> </FrameLayout>

View File

@ -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.</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>