[android] over(lay)haul 1: Auto-hide overlay setting
All checks were successful
eden-license / license-header (pull_request) Successful in 37s
All checks were successful
eden-license / license-header (pull_request) Successful in 37s
This commit is contained in:
parent
4c5d03f5de
commit
af7f98f5be
9 changed files with 193 additions and 3 deletions
|
@ -66,6 +66,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||
var isActivityRecreated = false
|
||||
private lateinit var nfcReader: NfcReader
|
||||
|
||||
private var touchDownTime: Long = 0
|
||||
private val maxTapDuration = 500L
|
||||
|
||||
private val gyro = FloatArray(3)
|
||||
private val accel = FloatArray(3)
|
||||
private var motionTimestamp: Long = 0
|
||||
|
@ -476,6 +479,38 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
|
|||
}
|
||||
}
|
||||
|
||||
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
||||
val navHostFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) as? NavHostFragment
|
||||
val emulationFragment = navHostFragment?.childFragmentManager?.fragments?.firstOrNull() as? org.yuzu.yuzu_emu.fragments.EmulationFragment
|
||||
|
||||
emulationFragment?.let { fragment ->
|
||||
when (event.action) {
|
||||
MotionEvent.ACTION_DOWN -> {
|
||||
touchDownTime = System.currentTimeMillis()
|
||||
// show overlay immediately on touch and cancel timer
|
||||
if (!emulationViewModel.drawerOpen.value) {
|
||||
fragment.handler.removeCallbacksAndMessages(null)
|
||||
fragment.showOverlay()
|
||||
}
|
||||
}
|
||||
MotionEvent.ACTION_UP -> {
|
||||
if (!emulationViewModel.drawerOpen.value) {
|
||||
val touchDuration = System.currentTimeMillis() - touchDownTime
|
||||
|
||||
if (touchDuration <= maxTapDuration) {
|
||||
fragment.handleScreenTap(false)
|
||||
} else {
|
||||
// just start the auto-hide timer without toggling visibility
|
||||
fragment.handleScreenTap(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.dispatchTouchEvent(event)
|
||||
}
|
||||
|
||||
fun onEmulationStarted() {
|
||||
emulationViewModel.setEmulationStarted(true)
|
||||
}
|
||||
|
|
|
@ -59,7 +59,8 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
|||
OFFLINE_WEB_APPLET("offline_web_applet_mode"),
|
||||
LOGIN_SHARE_APPLET("login_share_applet_mode"),
|
||||
WIFI_WEB_AUTH_APPLET("wifi_web_auth_applet_mode"),
|
||||
MY_PAGE_APPLET("my_page_applet_mode")
|
||||
MY_PAGE_APPLET("my_page_applet_mode"),
|
||||
INPUT_OVERLAY_AUTO_HIDE("input_overlay_auto_hide")
|
||||
;
|
||||
|
||||
override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal)
|
||||
|
|
|
@ -12,6 +12,7 @@ object Settings {
|
|||
SECTION_SYSTEM(R.string.preferences_system),
|
||||
SECTION_RENDERER(R.string.preferences_graphics),
|
||||
SECTION_PERFORMANCE_STATS(R.string.stats_overlay_options),
|
||||
SECTION_INPUT_OVERLAY(R.string.input_overlay_options),
|
||||
SECTION_SOC_OVERLAY(R.string.soc_overlay_options),
|
||||
SECTION_AUDIO(R.string.preferences_audio),
|
||||
SECTION_INPUT(R.string.preferences_controls),
|
||||
|
|
|
@ -392,6 +392,15 @@ abstract class SettingsItem(
|
|||
warningMessage = R.string.warning_resolution
|
||||
)
|
||||
)
|
||||
put(
|
||||
SingleChoiceSetting(
|
||||
IntSetting.INPUT_OVERLAY_AUTO_HIDE,
|
||||
titleId = R.string.overlay_auto_hide,
|
||||
descriptionId = R.string.overlay_auto_hide_description,
|
||||
choicesId = R.array.overlayAutoHideEntries,
|
||||
valuesId = R.array.overlayAutoHideValues,
|
||||
)
|
||||
)
|
||||
|
||||
put(
|
||||
SwitchSetting(
|
||||
|
|
|
@ -97,6 +97,7 @@ class SettingsFragmentPresenter(
|
|||
MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
|
||||
MenuTag.SECTION_PERFORMANCE_STATS -> addPerformanceOverlaySettings(sl)
|
||||
MenuTag.SECTION_SOC_OVERLAY -> addSocOverlaySettings(sl)
|
||||
MenuTag.SECTION_INPUT_OVERLAY -> addInputOverlaySettings(sl)
|
||||
MenuTag.SECTION_AUDIO -> addAudioSettings(sl)
|
||||
MenuTag.SECTION_INPUT -> addInputSettings(sl)
|
||||
MenuTag.SECTION_INPUT_PLAYER_ONE -> addInputPlayer(sl, 0)
|
||||
|
@ -156,6 +157,14 @@ class SettingsFragmentPresenter(
|
|||
menuKey = MenuTag.SECTION_SOC_OVERLAY
|
||||
)
|
||||
)
|
||||
add(
|
||||
SubmenuSetting(
|
||||
titleId = R.string.input_overlay_options,
|
||||
iconId = R.drawable.ic_controller,
|
||||
descriptionId = R.string.input_overlay_options_description,
|
||||
menuKey = MenuTag.SECTION_INPUT_OVERLAY
|
||||
)
|
||||
)
|
||||
}
|
||||
add(
|
||||
SubmenuSetting(
|
||||
|
@ -265,6 +274,12 @@ class SettingsFragmentPresenter(
|
|||
}
|
||||
}
|
||||
|
||||
private fun addInputOverlaySettings(sl: ArrayList<SettingsItem>) {
|
||||
sl.apply {
|
||||
add(IntSetting.INPUT_OVERLAY_AUTO_HIDE.key)
|
||||
}
|
||||
}
|
||||
|
||||
private fun addSocOverlaySettings(sl: ArrayList<SettingsItem>) {
|
||||
sl.apply {
|
||||
add(HeaderSetting(R.string.stats_overlay_customization))
|
||||
|
|
|
@ -96,6 +96,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
private var perfStatsUpdater: (() -> Unit)? = null
|
||||
private var socUpdater: (() -> Unit)? = null
|
||||
|
||||
val handler = Handler(Looper.getMainLooper())
|
||||
private var isOverlayVisible = true
|
||||
|
||||
private var _binding: FragmentEmulationBinding? = null
|
||||
|
||||
private val binding get() = _binding!!
|
||||
|
@ -452,7 +455,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
/**
|
||||
* Ask user if they want to launch with default settings when custom settings fail
|
||||
*/
|
||||
private suspend fun askUserToLaunchWithDefaultSettings(gameTitle: String, errorMessage: String): Boolean {
|
||||
private suspend fun askUserToLaunchWithDefaultSettings(
|
||||
gameTitle: String,
|
||||
errorMessage: String
|
||||
): Boolean {
|
||||
return suspendCoroutine { continuation ->
|
||||
requireActivity().runOnUiThread {
|
||||
MaterialAlertDialogBuilder(requireContext())
|
||||
|
@ -728,6 +734,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
updateShowStatsOverlay()
|
||||
updateSocOverlay()
|
||||
|
||||
initializeOverlayAutoHide()
|
||||
|
||||
// Re update binding when the specs values get initialized properly
|
||||
binding.inGameMenu.getHeaderView(0).apply {
|
||||
val titleView = findViewById<TextView>(R.id.text_game_title)
|
||||
|
@ -910,6 +918,10 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
val position = IntSetting.PERF_OVERLAY_POSITION.getInt()
|
||||
updateStatsPosition(position)
|
||||
|
||||
// if the overlay auto-hide setting is changed while paused,
|
||||
// we need to reinitialize the auto-hide timer
|
||||
initializeOverlayAutoHide()
|
||||
|
||||
val socPosition = IntSetting.SOC_OVERLAY_POSITION.getInt()
|
||||
updateSocPosition(socPosition)
|
||||
|
||||
|
@ -1033,7 +1045,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
|
||||
val status = batteryIntent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
|
||||
val isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
|
||||
status == BatteryManager.BATTERY_STATUS_FULL
|
||||
status == BatteryManager.BATTERY_STATUS_FULL
|
||||
|
||||
if (isCharging) {
|
||||
sb.append(" ${getString(R.string.charging)}")
|
||||
|
@ -1722,4 +1734,60 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
|||
private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!)
|
||||
private val socUpdateHandler = Handler(Looper.myLooper()!!)
|
||||
}
|
||||
|
||||
private fun startOverlayAutoHideTimer(seconds: Int) {
|
||||
handler.removeCallbacksAndMessages(null)
|
||||
|
||||
handler.postDelayed({
|
||||
if (isOverlayVisible) {
|
||||
hideOverlay()
|
||||
}
|
||||
}, seconds * 1000L)
|
||||
}
|
||||
|
||||
|
||||
fun handleScreenTap(isLongTap: Boolean) {
|
||||
val autoHideSeconds = IntSetting.INPUT_OVERLAY_AUTO_HIDE.getInt()
|
||||
|
||||
if (!BooleanSetting.SHOW_INPUT_OVERLAY.getBoolean()) {
|
||||
return
|
||||
}
|
||||
|
||||
if (autoHideSeconds == 0) {
|
||||
showOverlay()
|
||||
return
|
||||
}
|
||||
|
||||
// Show overlay for quick taps when it's hidden
|
||||
if (!isOverlayVisible && !isLongTap) {
|
||||
showOverlay()
|
||||
}
|
||||
|
||||
startOverlayAutoHideTimer(autoHideSeconds)
|
||||
}
|
||||
|
||||
private fun initializeOverlayAutoHide() {
|
||||
val autoHideSeconds = IntSetting.INPUT_OVERLAY_AUTO_HIDE.getInt()
|
||||
if (autoHideSeconds > 0) {
|
||||
handler.postDelayed({
|
||||
// since the timer starts only after touch input, we need to always force hide it
|
||||
hideOverlay()
|
||||
}, autoHideSeconds * 1000L)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun showOverlay() {
|
||||
if (!isOverlayVisible) {
|
||||
isOverlayVisible = true
|
||||
ViewUtils.showView(binding.surfaceInputOverlay, 500)
|
||||
}
|
||||
}
|
||||
|
||||
private fun hideOverlay() {
|
||||
if (isOverlayVisible) {
|
||||
isOverlayVisible = false
|
||||
ViewUtils.hideView(binding.surfaceInputOverlay, 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,10 @@ namespace AndroidSettings {
|
|||
Settings::Category::Overlay,
|
||||
Settings::Specialization::Paired, true,
|
||||
true};
|
||||
|
||||
Settings::Setting<u32> perf_overlay_border{linkage, 0, "input_overlay_auto_hide",
|
||||
Settings::Category::Overlay,
|
||||
Settings::Specialization::Default, true, true,};
|
||||
Settings::Setting<bool> perf_overlay_background{linkage, false, "perf_overlay_background",
|
||||
Settings::Category::Overlay,
|
||||
Settings::Specialization::Default, true,
|
||||
|
|
|
@ -497,6 +497,40 @@
|
|||
<item>1</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="overlayAutoHideEntries">
|
||||
<item>@string/overlay_auto_hide_never</item>
|
||||
<item>@string/overlay_auto_hide_instant</item>
|
||||
<item>@string/overlay_auto_hide_5s</item>
|
||||
<item>@string/overlay_auto_hide_10s</item>
|
||||
<item>@string/overlay_auto_hide_15s</item>
|
||||
<item>@string/overlay_auto_hide_20s</item>
|
||||
<item>@string/overlay_auto_hide_25s</item>
|
||||
<item>@string/overlay_auto_hide_30s</item>
|
||||
<item>@string/overlay_auto_hide_35s</item>
|
||||
<item>@string/overlay_auto_hide_40s</item>
|
||||
<item>@string/overlay_auto_hide_45s</item>
|
||||
<item>@string/overlay_auto_hide_50s</item>
|
||||
<item>@string/overlay_auto_hide_55s</item>
|
||||
<item>@string/overlay_auto_hide_60s</item>
|
||||
</string-array>
|
||||
|
||||
<integer-array name="overlayAutoHideValues">
|
||||
<item>0</item>
|
||||
<item>1</item>
|
||||
<item>5</item>
|
||||
<item>10</item>
|
||||
<item>15</item>
|
||||
<item>20</item>
|
||||
<item>25</item>
|
||||
<item>30</item>
|
||||
<item>35</item>
|
||||
<item>40</item>
|
||||
<item>45</item>
|
||||
<item>50</item>
|
||||
<item>55</item>
|
||||
<item>60</item>
|
||||
</integer-array>
|
||||
|
||||
<string-array name="dynaStateEntries">
|
||||
<item>@string/disabled</item>
|
||||
<item>1</item>
|
||||
|
|
|
@ -9,6 +9,29 @@
|
|||
<string name="notice_notification_channel_description">Shows notifications when something goes wrong.</string>
|
||||
<string name="notification_permission_not_granted">Notification permission not granted!</string>
|
||||
|
||||
<!-- Input Overlay -->
|
||||
<string name="overlay_auto_hide">Overlay Auto Hide</string>
|
||||
<string name="overlay_auto_hide_description">Automatically hide the touch controls overlay after the specified time of inactivity. Select "Never" to keep the overlay always visible.</string>
|
||||
|
||||
<string name="overlay_auto_hide_never">Never</string>
|
||||
<string name="overlay_auto_hide_instant">Instantly</string>
|
||||
<string name="overlay_auto_hide_5s">5 seconds</string>
|
||||
<string name="overlay_auto_hide_10s">10 seconds</string>
|
||||
<string name="overlay_auto_hide_15s">15 seconds</string>
|
||||
<string name="overlay_auto_hide_20s">20 seconds</string>
|
||||
<string name="overlay_auto_hide_25s">25 seconds</string>
|
||||
<string name="overlay_auto_hide_30s">30 seconds</string>
|
||||
<string name="overlay_auto_hide_35s">35 seconds</string>
|
||||
<string name="overlay_auto_hide_40s">40 seconds</string>
|
||||
<string name="overlay_auto_hide_45s">45 seconds</string>
|
||||
<string name="overlay_auto_hide_50s">50 seconds</string>
|
||||
<string name="overlay_auto_hide_55s">55 seconds</string>
|
||||
<string name="overlay_auto_hide_60s">1 minute</string>
|
||||
|
||||
<string name="input_overlay_options">Input Overlay</string>
|
||||
<string name="input_overlay_options_description">Configure on-screen controls</string>
|
||||
|
||||
|
||||
<!-- Stats Overlay settings -->
|
||||
<string name="enhanced_fps_suffix">(Enhanced)</string>
|
||||
<string name="process_ram">Process RAM: %1$d MB</string>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue