|
@@ -7,6 +7,7 @@ import android.annotation.SuppressLint
|
|
|
import android.app.AlertDialog
|
|
import android.app.AlertDialog
|
|
|
import android.content.Context
|
|
import android.content.Context
|
|
|
import android.content.DialogInterface
|
|
import android.content.DialogInterface
|
|
|
|
|
+import android.content.Intent
|
|
|
import android.content.SharedPreferences
|
|
import android.content.SharedPreferences
|
|
|
import android.content.pm.ActivityInfo
|
|
import android.content.pm.ActivityInfo
|
|
|
import android.content.res.Resources
|
|
import android.content.res.Resources
|
|
@@ -19,11 +20,14 @@ import android.util.TypedValue
|
|
|
import android.view.*
|
|
import android.view.*
|
|
|
import android.widget.TextView
|
|
import android.widget.TextView
|
|
|
import androidx.activity.OnBackPressedCallback
|
|
import androidx.activity.OnBackPressedCallback
|
|
|
|
|
+import androidx.activity.result.ActivityResultLauncher
|
|
|
|
|
+import androidx.activity.result.contract.ActivityResultContracts
|
|
|
import androidx.appcompat.widget.PopupMenu
|
|
import androidx.appcompat.widget.PopupMenu
|
|
|
import androidx.core.content.res.ResourcesCompat
|
|
import androidx.core.content.res.ResourcesCompat
|
|
|
import androidx.core.graphics.Insets
|
|
import androidx.core.graphics.Insets
|
|
|
import androidx.core.view.ViewCompat
|
|
import androidx.core.view.ViewCompat
|
|
|
import androidx.core.view.WindowInsetsCompat
|
|
import androidx.core.view.WindowInsetsCompat
|
|
|
|
|
+import androidx.core.view.isVisible
|
|
|
import androidx.core.view.updatePadding
|
|
import androidx.core.view.updatePadding
|
|
|
import androidx.fragment.app.Fragment
|
|
import androidx.fragment.app.Fragment
|
|
|
import androidx.lifecycle.Lifecycle
|
|
import androidx.lifecycle.Lifecycle
|
|
@@ -61,11 +65,30 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|
|
|
|
|
|
|
val args by navArgs<EmulationFragmentArgs>()
|
|
val args by navArgs<EmulationFragmentArgs>()
|
|
|
|
|
|
|
|
|
|
+ private lateinit var onReturnFromSettings: ActivityResultLauncher<Intent>
|
|
|
|
|
+
|
|
|
override fun onAttach(context: Context) {
|
|
override fun onAttach(context: Context) {
|
|
|
super.onAttach(context)
|
|
super.onAttach(context)
|
|
|
if (context is EmulationActivity) {
|
|
if (context is EmulationActivity) {
|
|
|
emulationActivity = context
|
|
emulationActivity = context
|
|
|
NativeLibrary.setEmulationActivity(context)
|
|
NativeLibrary.setEmulationActivity(context)
|
|
|
|
|
+
|
|
|
|
|
+ onReturnFromSettings = context.activityResultRegistry.register(
|
|
|
|
|
+ "SettingsResult", ActivityResultContracts.StartActivityForResult()
|
|
|
|
|
+ ) {
|
|
|
|
|
+ binding.surfaceEmulation.setAspectRatio(
|
|
|
|
|
+ when (IntSetting.RENDERER_ASPECT_RATIO.int) {
|
|
|
|
|
+ 0 -> Rational(16, 9)
|
|
|
|
|
+ 1 -> Rational(4, 3)
|
|
|
|
|
+ 2 -> Rational(21, 9)
|
|
|
|
|
+ 3 -> Rational(16, 10)
|
|
|
|
|
+ 4 -> null // Stretch
|
|
|
|
|
+ else -> Rational(16, 9)
|
|
|
|
|
+ }
|
|
|
|
|
+ )
|
|
|
|
|
+ emulationActivity?.buildPictureInPictureParams()
|
|
|
|
|
+ updateScreenLayout()
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
throw IllegalStateException("EmulationFragment must have EmulationActivity parent")
|
|
throw IllegalStateException("EmulationFragment must have EmulationActivity parent")
|
|
|
}
|
|
}
|
|
@@ -129,7 +152,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
R.id.menu_settings -> {
|
|
R.id.menu_settings -> {
|
|
|
- SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "")
|
|
|
|
|
|
|
+ SettingsActivity.launch(
|
|
|
|
|
+ requireContext(), onReturnFromSettings, SettingsFile.FILE_NAME_CONFIG, ""
|
|
|
|
|
+ )
|
|
|
true
|
|
true
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -162,7 +187,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|
|
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
|
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
|
|
|
WindowInfoTracker.getOrCreate(requireContext())
|
|
WindowInfoTracker.getOrCreate(requireContext())
|
|
|
.windowLayoutInfo(requireActivity())
|
|
.windowLayoutInfo(requireActivity())
|
|
|
- .collect { updateCurrentLayout(requireActivity() as EmulationActivity, it) }
|
|
|
|
|
|
|
+ .collect { updateFoldableLayout(requireActivity() as EmulationActivity, it) }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -204,6 +229,37 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|
|
super.onDetach()
|
|
super.onDetach()
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ fun isEmulationStatePaused() : Boolean {
|
|
|
|
|
+ return this::emulationState.isInitialized && emulationState.isPaused
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fun onPictureInPictureEnter() {
|
|
|
|
|
+ if (binding.drawerLayout.isOpen) {
|
|
|
|
|
+ binding.drawerLayout.close()
|
|
|
|
|
+ }
|
|
|
|
|
+ if (EmulationMenuSettings.showOverlay) {
|
|
|
|
|
+ binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.isVisible = false }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fun onPictureInPicturePause() {
|
|
|
|
|
+ if (!emulationState.isPaused) {
|
|
|
|
|
+ emulationState.pause()
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fun onPictureInPicturePlay() {
|
|
|
|
|
+ if (emulationState.isPaused) {
|
|
|
|
|
+ emulationState.run(false)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ fun onPictureInPictureLeave() {
|
|
|
|
|
+ if (EmulationMenuSettings.showOverlay) {
|
|
|
|
|
+ binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.isVisible = true }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private fun refreshInputOverlay() {
|
|
private fun refreshInputOverlay() {
|
|
|
binding.surfaceInputOverlay.refreshControls()
|
|
binding.surfaceInputOverlay.refreshControls()
|
|
|
}
|
|
}
|
|
@@ -243,15 +299,33 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ @SuppressLint("SourceLockedOrientationActivity")
|
|
|
|
|
+ private fun updateScreenLayout() {
|
|
|
|
|
+ emulationActivity?.let {
|
|
|
|
|
+ when (IntSetting.RENDERER_SCREEN_LAYOUT.int) {
|
|
|
|
|
+ Settings.LayoutOption_MobileLandscape -> {
|
|
|
|
|
+ it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
|
|
|
|
|
+ }
|
|
|
|
|
+ Settings.LayoutOption_MobilePortrait -> {
|
|
|
|
|
+ it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
|
|
|
|
|
+ }
|
|
|
|
|
+ Settings.LayoutOption_Default -> {
|
|
|
|
|
+ it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
|
|
|
|
+ }
|
|
|
|
|
+ else -> { it.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
private val Number.toPx get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()
|
|
private val Number.toPx get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()
|
|
|
|
|
|
|
|
- fun updateCurrentLayout(emulationActivity: EmulationActivity, newLayoutInfo: WindowLayoutInfo) {
|
|
|
|
|
|
|
+ fun updateFoldableLayout(emulationActivity: EmulationActivity, newLayoutInfo: WindowLayoutInfo) {
|
|
|
val isFolding = (newLayoutInfo.displayFeatures.find { it is FoldingFeature } as? FoldingFeature)?.let {
|
|
val isFolding = (newLayoutInfo.displayFeatures.find { it is FoldingFeature } as? FoldingFeature)?.let {
|
|
|
if (it.isSeparating) {
|
|
if (it.isSeparating) {
|
|
|
emulationActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
|
emulationActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
|
|
|
if (it.orientation == FoldingFeature.Orientation.HORIZONTAL) {
|
|
if (it.orientation == FoldingFeature.Orientation.HORIZONTAL) {
|
|
|
- binding.surfaceEmulation.layoutParams.height = it.bounds.top
|
|
|
|
|
- binding.inGameMenu.layoutParams.height = it.bounds.bottom
|
|
|
|
|
|
|
+ binding.emulationContainer.layoutParams.height = it.bounds.top
|
|
|
|
|
+ // Prevent touch regions from being displayed in the hinge
|
|
|
binding.overlayContainer.layoutParams.height = it.bounds.bottom - 48.toPx
|
|
binding.overlayContainer.layoutParams.height = it.bounds.bottom - 48.toPx
|
|
|
binding.overlayContainer.updatePadding(0, 0, 0, 24.toPx)
|
|
binding.overlayContainer.updatePadding(0, 0, 0, 24.toPx)
|
|
|
}
|
|
}
|
|
@@ -259,14 +333,12 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|
|
it.isSeparating
|
|
it.isSeparating
|
|
|
} ?: false
|
|
} ?: false
|
|
|
if (!isFolding) {
|
|
if (!isFolding) {
|
|
|
- binding.surfaceEmulation.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
|
|
|
|
- binding.inGameMenu.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
|
|
|
|
|
|
+ binding.emulationContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
|
|
binding.overlayContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
|
binding.overlayContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
|
|
|
binding.overlayContainer.updatePadding(0, 0, 0, 0)
|
|
binding.overlayContainer.updatePadding(0, 0, 0, 0)
|
|
|
- emulationActivity.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
|
|
|
|
|
|
|
+ updateScreenLayout()
|
|
|
}
|
|
}
|
|
|
- binding.surfaceInputOverlay.requestLayout()
|
|
|
|
|
- binding.inGameMenu.requestLayout()
|
|
|
|
|
|
|
+ binding.emulationContainer.requestLayout()
|
|
|
binding.overlayContainer.requestLayout()
|
|
binding.overlayContainer.requestLayout()
|
|
|
}
|
|
}
|
|
|
|
|
|