diff --git a/app/src/main/java/emu/skyline/EmulationActivity.kt b/app/src/main/java/emu/skyline/EmulationActivity.kt index f59617aa..477516e9 100644 --- a/app/src/main/java/emu/skyline/EmulationActivity.kt +++ b/app/src/main/java/emu/skyline/EmulationActivity.kt @@ -17,6 +17,7 @@ import android.view.* import androidx.appcompat.app.AppCompatActivity import androidx.core.view.isGone import androidx.core.view.isInvisible +import androidx.core.view.updateMargins import dagger.hilt.android.AndroidEntryPoint import emu.skyline.databinding.EmuActivityBinding import emu.skyline.input.* @@ -232,15 +233,25 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo override fun onCreate(savedInstanceState : Bundle?) { super.onCreate(savedInstanceState) requestedOrientation = settings.orientation + window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES setContentView(binding.root) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + // Android might not allow child views to overlap the system bars + // Override this behavior and force content to extend into the cutout area + window.setDecorFitsSystemWindows(false) + window.insetsController?.let { it.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE it.hide(WindowInsets.Type.systemBars()) } } + if (settings.respectDisplayCutout) { + binding.perfStats.setOnApplyWindowInsetsListener(insetsOrMarginHandler) + binding.onScreenControllerToggle.setOnApplyWindowInsetsListener(insetsOrMarginHandler) + } + binding.gameView.holder.addCallback(this) binding.gameView.setAspectRatio( @@ -540,4 +551,17 @@ class EmulationActivity : AppCompatActivity(), SurfaceHolder.Callback, View.OnTo val (major, minor, patch) = BuildConfig.VERSION_NAME.split('.').map { it.toUInt() } return ((major shl 22) or (minor shl 12) or (patch)).toInt() } + + val insetsOrMarginHandler = View.OnApplyWindowInsetsListener { view, insets -> + insets.displayCutout?.let { + val defaultHorizontalMargin = view.resources.getDimensionPixelSize(R.dimen.onScreenItemHorizontalMargin) + val left = if (it.safeInsetLeft == 0) defaultHorizontalMargin else it.safeInsetLeft + val right = if (it.safeInsetRight == 0) defaultHorizontalMargin else it.safeInsetRight + + val params = view.layoutParams as ViewGroup.MarginLayoutParams + params.updateMargins(left = left, right = right) + view.layoutParams = params + } + insets + } } diff --git a/app/src/main/java/emu/skyline/input/onscreen/OnScreenEditActivity.kt b/app/src/main/java/emu/skyline/input/onscreen/OnScreenEditActivity.kt index a3d387a6..e14b0ad0 100644 --- a/app/src/main/java/emu/skyline/input/onscreen/OnScreenEditActivity.kt +++ b/app/src/main/java/emu/skyline/input/onscreen/OnScreenEditActivity.kt @@ -7,10 +7,7 @@ package emu.skyline.input.onscreen import android.os.Build import android.os.Bundle -import android.view.LayoutInflater -import android.view.View -import android.view.WindowInsets -import android.view.WindowInsetsController +import android.view.* import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat import com.google.android.material.dialog.MaterialAlertDialogBuilder @@ -90,7 +87,20 @@ class OnScreenEditActivity : AppCompatActivity() { override fun onCreate(savedInstanceState : Bundle?) { super.onCreate(savedInstanceState) + window.attributes.layoutInDisplayCutoutMode = WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES setContentView(binding.root) + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { + // Android might not allow child views to overlap the system bars + // Override this behavior and force content to extend into the cutout area + window.setDecorFitsSystemWindows(false) + + window.insetsController?.let { + it.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE + it.hide(WindowInsets.Type.systemBars()) + } + } + binding.onScreenControllerView.recenterSticks = settings.onScreenControlRecenterSticks actions.forEach { pair -> @@ -100,11 +110,6 @@ class OnScreenEditActivity : AppCompatActivity() { fabMapping[pair.first] = this }) } - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { - window.insetsController?.hide(WindowInsets.Type.navigationBars() or WindowInsets.Type.systemBars() or WindowInsets.Type.systemGestures() or WindowInsets.Type.statusBars()) - window.insetsController?.systemBarsBehavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE - } } override fun onResume() { diff --git a/app/src/main/java/emu/skyline/utils/Settings.kt b/app/src/main/java/emu/skyline/utils/Settings.kt index 9dccfa96..fe6c6cb0 100644 --- a/app/src/main/java/emu/skyline/utils/Settings.kt +++ b/app/src/main/java/emu/skyline/utils/Settings.kt @@ -44,4 +44,6 @@ class Settings @Inject constructor(@ApplicationContext private val context : Con var systemLanguage by sharedPreferences(context, 1) var orientation by sharedPreferences(context, ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE) + + var respectDisplayCutout by sharedPreferences(context, false) } diff --git a/app/src/main/res/layout/emu_activity.xml b/app/src/main/res/layout/emu_activity.xml index fca9db06..6194938b 100644 --- a/app/src/main/res/layout/emu_activity.xml +++ b/app/src/main/res/layout/emu_activity.xml @@ -4,9 +4,10 @@ xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" - android:keepScreenOn="true" android:background="@android:color/black" - tools:context=".EmulationActivity"> + android:keepScreenOn="true" + tools:context=".EmulationActivity" + tools:ignore="RtlHardcoded"> diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 6d1c25e3..090dcbfc 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -1,4 +1,5 @@ 8dp + 10dp diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5564c493..1fb6ada8 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,6 +63,9 @@ Sets the display refresh rate as high as possible (Will break most games) Sets the display refresh rate to 60Hz Aspect Ratio + Respect Display Cutout + Do not draw UI elements in the cutout area + Allow UI elements to be drawn in the cutout area Input On-Screen Controls diff --git a/app/src/main/res/xml/preferences.xml b/app/src/main/res/xml/preferences.xml index cc45c9e0..5d75c1c9 100644 --- a/app/src/main/res/xml/preferences.xml +++ b/app/src/main/res/xml/preferences.xml @@ -116,6 +116,12 @@ app:key="aspect_ratio" app:title="@string/aspect_ratio" app:useSimpleSummaryProvider="true" /> +