diff --git a/src/pandroid/app/src/main/AndroidManifest.xml b/src/pandroid/app/src/main/AndroidManifest.xml index d1d8f56f..d555771b 100644 --- a/src/pandroid/app/src/main/AndroidManifest.xml +++ b/src/pandroid/app/src/main/AndroidManifest.xml @@ -31,7 +31,8 @@ </activity> <activity android:name=".app.GameActivity" - android:configChanges="screenSize|screenLayout|orientation|density|uiMode"> + android:supportsPictureInPicture="true" + android:configChanges="screenSize|screenLayout|smallestScreenSize|orientation|density|uiMode"> </activity> <activity android:name=".app.editor.CodeEditorActivity" diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/GameActivity.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/GameActivity.java index 946ef883..322b46b3 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/GameActivity.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/GameActivity.java @@ -12,6 +12,10 @@ import android.widget.CheckBox; import android.widget.FrameLayout; import android.widget.Toast; import androidx.annotation.Nullable; +import android.app.PictureInPictureParams; +import android.content.res.Configuration; +import android.util.DisplayMetrics; +import android.util.Rational; import com.panda3ds.pandroid.AlberDriver; import com.panda3ds.pandroid.R; import com.panda3ds.pandroid.app.game.AlberInputListener; @@ -73,11 +77,54 @@ public class GameActivity extends BaseActivity { InputHandler.reset(); InputHandler.setMotionDeadZone(InputMap.getDeadZone()); InputHandler.setEventListener(inputListener); + if (GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (!drawerFragment.isOpened()) { + setPictureInPictureParams(new PictureInPictureParams.Builder().setAutoEnterEnabled(true).build()); + } + } + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) { getTheme().applyStyle(R.style.GameActivityNavigationBar, true); } } + @Override + public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode, Configuration newConfig) { + super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig); + if (isInPictureInPictureMode) { + findViewById(R.id.overlay_controller).setVisibility(View.GONE); + } else { + if (GlobalConfig.get(GlobalConfig.KEY_SCREEN_GAMEPAD_VISIBLE)) { + findViewById(R.id.overlay_controller).setVisibility(View.VISIBLE); + } + } + } + + @Override + public void onUserLeaveHint() { + super.onUserLeaveHint(); + DisplayMetrics displayMetrics = new DisplayMetrics(); + getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); + + int widthPixels = displayMetrics.widthPixels; + int heightPixels = displayMetrics.heightPixels; + + // Calculate aspect ratio + float aspectRatio = (float) widthPixels / (float) heightPixels; + + if (GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)) { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) { + if (!drawerFragment.isOpened()) { + Rational aspectRatioRational = new Rational(widthPixels, heightPixels); + PictureInPictureParams.Builder pipBuilder = new PictureInPictureParams.Builder(); + pipBuilder.setAspectRatio(aspectRatioRational); + enterPictureInPictureMode(pipBuilder.build()); + } + } + } + } + @Override protected void onPause() { super.onPause(); diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/game/DrawerFragment.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/game/DrawerFragment.java index a1fa9eec..7ca61df4 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/game/DrawerFragment.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/game/DrawerFragment.java @@ -1,6 +1,7 @@ package com.panda3ds.pandroid.app.game; import android.graphics.Color; +import android.os.Build; import android.os.Bundle; import android.view.LayoutInflater; import android.view.MenuItem; diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/AdvancedPreferences.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/AdvancedPreferences.java index e5737f66..e50d2193 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/AdvancedPreferences.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/app/preferences/AdvancedPreferences.java @@ -3,6 +3,7 @@ package com.panda3ds.pandroid.app.preferences; import android.content.Context; import android.content.Intent; import android.os.Bundle; +import android.os.Build; import androidx.annotation.Nullable; import androidx.preference.SwitchPreferenceCompat; @@ -20,6 +21,7 @@ public class AdvancedPreferences extends BasePreferenceFragment { setActivityTitle(R.string.advanced_options); setItemClick("performanceMonitor", pref -> GlobalConfig.set(GlobalConfig.KEY_SHOW_PERFORMANCE_OVERLAY, ((SwitchPreferenceCompat) pref).isChecked())); + setItemClick("pictureInPicture", pref -> GlobalConfig.set(GlobalConfig.KEY_PICTURE_IN_PICTURE, ((SwitchPreferenceCompat) pref).isChecked())); setItemClick("shaderJit", pref -> GlobalConfig.set(GlobalConfig.KEY_SHADER_JIT, ((SwitchPreferenceCompat) pref).isChecked())); setItemClick("loggerService", pref -> { boolean checked = ((SwitchPreferenceCompat) pref).isChecked(); @@ -43,7 +45,14 @@ public class AdvancedPreferences extends BasePreferenceFragment { private void refresh() { ((SwitchPreferenceCompat) findPreference("performanceMonitor")).setChecked(GlobalConfig.get(GlobalConfig.KEY_SHOW_PERFORMANCE_OVERLAY)); + ((SwitchPreferenceCompat) findPreference("pictureInPicture")).setChecked(GlobalConfig.get(GlobalConfig.KEY_PICTURE_IN_PICTURE)); ((SwitchPreferenceCompat) findPreference("loggerService")).setChecked(GlobalConfig.get(GlobalConfig.KEY_LOGGER_SERVICE)); ((SwitchPreferenceCompat) findPreference("shaderJit")).setChecked(GlobalConfig.get(GlobalConfig.KEY_SHADER_JIT)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + findPreference("pictureInPicture").setEnabled(true); + } else { + findPreference("pictureInPicture").setEnabled(false); + findPreference("pictureInPicture").setSummary("Your device does not support this feature"); + } } } diff --git a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java index bff1f9e0..29258680 100644 --- a/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java +++ b/src/pandroid/app/src/main/java/com/panda3ds/pandroid/data/config/GlobalConfig.java @@ -20,6 +20,7 @@ public class GlobalConfig { public static final Key<Boolean> KEY_SHADER_JIT = new Key<>("emu.shader_jit", false); public static final Key<Boolean> KEY_SHOW_PERFORMANCE_OVERLAY = new Key<>("dev.performanceOverlay", false); + public static final Key<Boolean> KEY_PICTURE_IN_PICTURE = new Key<>("dev.pictureInPicture", false); public static final Key<Boolean> KEY_LOGGER_SERVICE = new Key<>("dev.loggerService", false); public static final Key<Integer> KEY_APP_THEME = new Key<>("app.theme", THEME_ANDROID); public static final Key<Boolean> KEY_SCREEN_GAMEPAD_VISIBLE = new Key<>("app.screen_gamepad.visible", true); diff --git a/src/pandroid/app/src/main/res/values/strings.xml b/src/pandroid/app/src/main/res/values/strings.xml index 20e6c5c8..c9137786 100644 --- a/src/pandroid/app/src/main/res/values/strings.xml +++ b/src/pandroid/app/src/main/res/values/strings.xml @@ -52,12 +52,16 @@ <!-- Advanced Settings --> <string name="advanced_options">Advanced options</string> <string name="pref_advanced_summary">Logger, performance statistics, etc.</string> + <string name="display">Display</string> <string name="pref_performance_monitor_title">Performance monitor</string> <string name="pref_performance_monitor_summary">Show overlay with fps, memory, etc.</string> - <string name="pref_logger_service_title">Logger</string> - <string name="pref_logger_service_summary">Store application logs to file.</string> + <string name="pref_picture_in_picture_title">Picture In Picture</string> + <string name="pref_picture_in_picture_summary">Minimize window when placed in the background.</string> + <string name="graphics">Graphics</string> <string name="pref_shader_jit_title">Shader JIT</string> <string name="pref_shader_jit_summary">Use shader recompiler.</string> - <string name="graphics">Graphics</string> + <string name="debug">Debug</string> + <string name="pref_logger_service_title">Logger</string> + <string name="pref_logger_service_summary">Store application logs to file.</string> <string name="loading">Loading</string> </resources> diff --git a/src/pandroid/app/src/main/res/xml/advanced_preferences.xml b/src/pandroid/app/src/main/res/xml/advanced_preferences.xml index e3ec5991..e11e481d 100644 --- a/src/pandroid/app/src/main/res/xml/advanced_preferences.xml +++ b/src/pandroid/app/src/main/res/xml/advanced_preferences.xml @@ -1,7 +1,11 @@ <?xml version="1.0" encoding="utf-8"?> <PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> - + + <PreferenceCategory + app:iconSpaceReserved="false" + app:title="@string/display"> + <SwitchPreferenceCompat android:key="performanceMonitor" app:title="@string/pref_performance_monitor_title" @@ -11,12 +15,14 @@ app:iconSpaceReserved="false"/> <SwitchPreferenceCompat - android:key="loggerService" - app:iconSpaceReserved="false" - app:title="@string/pref_logger_service_title" - android:defaultValue="true" - android:summaryOn="@string/pref_logger_service_summary" - android:summaryOff="@string/pref_logger_service_summary"/> + android:key="pictureInPicture" + app:title="@string/pref_picture_in_picture_title" + app:summaryOn="@string/pref_picture_in_picture_summary" + app:summaryOff="@string/pref_picture_in_picture_summary" + android:defaultValue="false" + app:iconSpaceReserved="false"/> + + </PreferenceCategory> <PreferenceCategory app:iconSpaceReserved="false" @@ -32,4 +38,16 @@ </PreferenceCategory> + <PreferenceCategory + app:iconSpaceReserved="false" + app:title="@string/debug"> + + <SwitchPreferenceCompat + android:key="loggerService" + app:iconSpaceReserved="false" + app:title="@string/pref_logger_service_title" + android:defaultValue="true" + android:summaryOn="@string/pref_logger_service_summary" + android:summaryOff="@string/pref_logger_service_summary"/> + </PreferenceCategory> </PreferenceScreen>