android: Reshape the layout to fit rotation

This commit is contained in:
Abandoned Cart 2023-06-05 20:33:09 -04:00
commit 32f869a1df
3 changed files with 68 additions and 29 deletions

View file

@ -21,6 +21,7 @@ import android.hardware.SensorManager
import android.hardware.display.DisplayManager import android.hardware.display.DisplayManager
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.util.DisplayMetrics
import android.util.Rational import android.util.Rational
import android.view.Display import android.view.Display
import android.view.InputDevice import android.view.InputDevice
@ -28,6 +29,7 @@ import android.view.KeyEvent
import android.view.MotionEvent import android.view.MotionEvent
import android.view.Surface import android.view.Surface
import android.view.View import android.view.View
import android.view.WindowManager
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import androidx.activity.viewModels import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
@ -76,6 +78,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
private val settingsViewModel: SettingsViewModel by viewModels() private val settingsViewModel: SettingsViewModel by viewModels()
var screenDimensions : IntArray = intArrayOf()
override fun onDestroy() { override fun onDestroy() {
stopForegroundService(this) stopForegroundService(this)
super.onDestroy() super.onDestroy()
@ -103,6 +107,8 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
setContentView(R.layout.activity_emulation) setContentView(R.layout.activity_emulation)
window.decorView.setBackgroundColor(getColor(android.R.color.black)) window.decorView.setBackgroundColor(getColor(android.R.color.black))
screenDimensions = getDisplayParams()
// Find or create the EmulationFragment // Find or create the EmulationFragment
emulationFragment = emulationFragment =
supportFragmentManager.findFragmentById(R.id.frame_emulation_fragment) as EmulationFragment? supportFragmentManager.findFragmentById(R.id.frame_emulation_fragment) as EmulationFragment?
@ -124,7 +130,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) {
WindowInfoTracker.getOrCreate(this@EmulationActivity) WindowInfoTracker.getOrCreate(this@EmulationActivity)
.windowLayoutInfo(this@EmulationActivity) .windowLayoutInfo(this@EmulationActivity)
.collect { emulationFragment?.updateCurrentLayout(this@EmulationActivity, it) } .collect { emulationFragment?.updateFoldableLayout(this@EmulationActivity, it) }
} }
} }
@ -312,6 +318,13 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
return this.apply { aspectRatio?.let { setAspectRatio(it) } } return this.apply { aspectRatio?.let { setAspectRatio(it) } }
} }
private fun getDisplayParams(): IntArray {
return with (getSystemService(WINDOW_SERVICE) as WindowManager) {
val metrics = maximumWindowMetrics.bounds
intArrayOf(metrics.width(), metrics.height())
}
}
private fun PictureInPictureParams.Builder.getPictureInPictureActionsBuilder() : PictureInPictureParams.Builder { private fun PictureInPictureParams.Builder.getPictureInPictureActionsBuilder() : PictureInPictureParams.Builder {
val pictureInPictureActions : MutableList<RemoteAction> = mutableListOf() val pictureInPictureActions : MutableList<RemoteAction> = mutableListOf()
val pendingFlags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE val pendingFlags = PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE

View file

@ -223,16 +223,39 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
else -> { rotation } else -> { rotation }
} }
} }
getScaledOrDefaultView(newConfig)
NativeLibrary.notifyOrientationChange(emulatorLayout, rotation) NativeLibrary.notifyOrientationChange(emulatorLayout, rotation)
} }
} }
} }
private fun getScaledOrDefaultView(config: Configuration?) {
emulationActivity?.let {
val orientation = config?.orientation ?: resources.configuration.orientation
if (orientation == Configuration.ORIENTATION_PORTRAIT && !it.isInPictureInPictureMode) {
if (it.screenDimensions.isNotEmpty()) {
binding.surfaceEmulation.layoutParams.width = it.screenDimensions[0]
binding.overlayContainer.layoutParams.width = it.screenDimensions[0]
binding.surfaceEmulation.layoutParams.height = it.screenDimensions[1]
binding.overlayContainer.layoutParams.height = it.screenDimensions[1]
}
} else {
binding.surfaceEmulation.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
binding.overlayContainer.layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT
binding.surfaceEmulation.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
binding.overlayContainer.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
}
binding.surfaceEmulation.requestLayout()
binding.overlayContainer.requestLayout()
}
}
fun isEmulationStatePaused() : Boolean { fun isEmulationStatePaused() : Boolean {
return this::emulationState.isInitialized && emulationState.isPaused return this::emulationState.isInitialized && emulationState.isPaused
} }
fun onPictureInPictureEnter() { fun onPictureInPictureEnter() {
getScaledOrDefaultView(null)
if (binding.drawerLayout.isOpen) { if (binding.drawerLayout.isOpen) {
binding.drawerLayout.close() binding.drawerLayout.close()
} }
@ -257,6 +280,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
if (EmulationMenuSettings.showOverlay) { if (EmulationMenuSettings.showOverlay) {
binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.isVisible = true } binding.surfaceInputOverlay.post { binding.surfaceInputOverlay.isVisible = true }
} }
getScaledOrDefaultView(null)
} }
private fun refreshInputOverlay() { private fun refreshInputOverlay() {
@ -319,7 +343,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
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
@ -339,7 +363,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
binding.overlayContainer.updatePadding(0, 0, 0, 0) binding.overlayContainer.updatePadding(0, 0, 0, 0)
updateScreenLayout() updateScreenLayout()
} }
binding.surfaceInputOverlay.requestLayout() binding.surfaceEmulation.requestLayout()
binding.inGameMenu.requestLayout() binding.inGameMenu.requestLayout()
binding.overlayContainer.requestLayout() binding.overlayContainer.requestLayout()
} }

View file

@ -17,6 +17,7 @@
android:id="@+id/surface_emulation" android:id="@+id/surface_emulation"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="center"
android:focusable="false" android:focusable="false"
android:focusableInTouchMode="false" /> android:focusableInTouchMode="false" />
@ -26,34 +27,35 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_gravity="bottom"> android:layout_gravity="bottom">
<!-- This is the onscreen input overlay --> <!-- This is the onscreen input overlay -->
<org.yuzu.yuzu_emu.overlay.InputOverlay <org.yuzu.yuzu_emu.overlay.InputOverlay
android:id="@+id/surface_input_overlay" android:id="@+id/surface_input_overlay"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:focusable="true" android:layout_gravity="bottom"
android:focusableInTouchMode="true" /> android:focusable="true"
android:focusableInTouchMode="true" />
<TextView <TextView
android:id="@+id/show_fps_text" android:id="@+id/show_fps_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="left" android:layout_gravity="left"
android:clickable="false" android:clickable="false"
android:focusable="false" android:focusable="false"
android:shadowColor="@android:color/black" android:shadowColor="@android:color/black"
android:textColor="@android:color/white" android:textColor="@android:color/white"
android:textSize="12sp" android:textSize="12sp"
tools:ignore="RtlHardcoded" /> tools:ignore="RtlHardcoded" />
<Button <Button
style="@style/Widget.Material3.Button.ElevatedButton" style="@style/Widget.Material3.Button.ElevatedButton"
android:id="@+id/done_control_config" android:id="@+id/done_control_config"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:text="@string/emulation_done" android:text="@string/emulation_done"
android:visibility="gone" /> android:visibility="gone" />
</FrameLayout> </FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>