[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
|
var isActivityRecreated = false
|
||||||
private lateinit var nfcReader: NfcReader
|
private lateinit var nfcReader: NfcReader
|
||||||
|
|
||||||
|
private var touchDownTime: Long = 0
|
||||||
|
private val maxTapDuration = 500L
|
||||||
|
|
||||||
private val gyro = FloatArray(3)
|
private val gyro = FloatArray(3)
|
||||||
private val accel = FloatArray(3)
|
private val accel = FloatArray(3)
|
||||||
private var motionTimestamp: Long = 0
|
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() {
|
fun onEmulationStarted() {
|
||||||
emulationViewModel.setEmulationStarted(true)
|
emulationViewModel.setEmulationStarted(true)
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,8 @@ enum class IntSetting(override val key: String) : AbstractIntSetting {
|
||||||
OFFLINE_WEB_APPLET("offline_web_applet_mode"),
|
OFFLINE_WEB_APPLET("offline_web_applet_mode"),
|
||||||
LOGIN_SHARE_APPLET("login_share_applet_mode"),
|
LOGIN_SHARE_APPLET("login_share_applet_mode"),
|
||||||
WIFI_WEB_AUTH_APPLET("wifi_web_auth_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)
|
override fun getInt(needsGlobal: Boolean): Int = NativeConfig.getInt(key, needsGlobal)
|
||||||
|
|
|
@ -12,6 +12,7 @@ object Settings {
|
||||||
SECTION_SYSTEM(R.string.preferences_system),
|
SECTION_SYSTEM(R.string.preferences_system),
|
||||||
SECTION_RENDERER(R.string.preferences_graphics),
|
SECTION_RENDERER(R.string.preferences_graphics),
|
||||||
SECTION_PERFORMANCE_STATS(R.string.stats_overlay_options),
|
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_SOC_OVERLAY(R.string.soc_overlay_options),
|
||||||
SECTION_AUDIO(R.string.preferences_audio),
|
SECTION_AUDIO(R.string.preferences_audio),
|
||||||
SECTION_INPUT(R.string.preferences_controls),
|
SECTION_INPUT(R.string.preferences_controls),
|
||||||
|
|
|
@ -392,6 +392,15 @@ abstract class SettingsItem(
|
||||||
warningMessage = R.string.warning_resolution
|
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(
|
put(
|
||||||
SwitchSetting(
|
SwitchSetting(
|
||||||
|
|
|
@ -97,6 +97,7 @@ class SettingsFragmentPresenter(
|
||||||
MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
|
MenuTag.SECTION_RENDERER -> addGraphicsSettings(sl)
|
||||||
MenuTag.SECTION_PERFORMANCE_STATS -> addPerformanceOverlaySettings(sl)
|
MenuTag.SECTION_PERFORMANCE_STATS -> addPerformanceOverlaySettings(sl)
|
||||||
MenuTag.SECTION_SOC_OVERLAY -> addSocOverlaySettings(sl)
|
MenuTag.SECTION_SOC_OVERLAY -> addSocOverlaySettings(sl)
|
||||||
|
MenuTag.SECTION_INPUT_OVERLAY -> addInputOverlaySettings(sl)
|
||||||
MenuTag.SECTION_AUDIO -> addAudioSettings(sl)
|
MenuTag.SECTION_AUDIO -> addAudioSettings(sl)
|
||||||
MenuTag.SECTION_INPUT -> addInputSettings(sl)
|
MenuTag.SECTION_INPUT -> addInputSettings(sl)
|
||||||
MenuTag.SECTION_INPUT_PLAYER_ONE -> addInputPlayer(sl, 0)
|
MenuTag.SECTION_INPUT_PLAYER_ONE -> addInputPlayer(sl, 0)
|
||||||
|
@ -156,6 +157,14 @@ class SettingsFragmentPresenter(
|
||||||
menuKey = MenuTag.SECTION_SOC_OVERLAY
|
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(
|
add(
|
||||||
SubmenuSetting(
|
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>) {
|
private fun addSocOverlaySettings(sl: ArrayList<SettingsItem>) {
|
||||||
sl.apply {
|
sl.apply {
|
||||||
add(HeaderSetting(R.string.stats_overlay_customization))
|
add(HeaderSetting(R.string.stats_overlay_customization))
|
||||||
|
|
|
@ -96,6 +96,9 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
private var perfStatsUpdater: (() -> Unit)? = null
|
private var perfStatsUpdater: (() -> Unit)? = null
|
||||||
private var socUpdater: (() -> Unit)? = null
|
private var socUpdater: (() -> Unit)? = null
|
||||||
|
|
||||||
|
val handler = Handler(Looper.getMainLooper())
|
||||||
|
private var isOverlayVisible = true
|
||||||
|
|
||||||
private var _binding: FragmentEmulationBinding? = null
|
private var _binding: FragmentEmulationBinding? = null
|
||||||
|
|
||||||
private val binding get() = _binding!!
|
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
|
* 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 ->
|
return suspendCoroutine { continuation ->
|
||||||
requireActivity().runOnUiThread {
|
requireActivity().runOnUiThread {
|
||||||
MaterialAlertDialogBuilder(requireContext())
|
MaterialAlertDialogBuilder(requireContext())
|
||||||
|
@ -728,6 +734,8 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
updateShowStatsOverlay()
|
updateShowStatsOverlay()
|
||||||
updateSocOverlay()
|
updateSocOverlay()
|
||||||
|
|
||||||
|
initializeOverlayAutoHide()
|
||||||
|
|
||||||
// Re update binding when the specs values get initialized properly
|
// Re update binding when the specs values get initialized properly
|
||||||
binding.inGameMenu.getHeaderView(0).apply {
|
binding.inGameMenu.getHeaderView(0).apply {
|
||||||
val titleView = findViewById<TextView>(R.id.text_game_title)
|
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()
|
val position = IntSetting.PERF_OVERLAY_POSITION.getInt()
|
||||||
updateStatsPosition(position)
|
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()
|
val socPosition = IntSetting.SOC_OVERLAY_POSITION.getInt()
|
||||||
updateSocPosition(socPosition)
|
updateSocPosition(socPosition)
|
||||||
|
|
||||||
|
@ -1033,7 +1045,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
|
|
||||||
val status = batteryIntent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
|
val status = batteryIntent?.getIntExtra(BatteryManager.EXTRA_STATUS, -1)
|
||||||
val isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
|
val isCharging = status == BatteryManager.BATTERY_STATUS_CHARGING ||
|
||||||
status == BatteryManager.BATTERY_STATUS_FULL
|
status == BatteryManager.BATTERY_STATUS_FULL
|
||||||
|
|
||||||
if (isCharging) {
|
if (isCharging) {
|
||||||
sb.append(" ${getString(R.string.charging)}")
|
sb.append(" ${getString(R.string.charging)}")
|
||||||
|
@ -1722,4 +1734,60 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
|
||||||
private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!)
|
private val perfStatsUpdateHandler = Handler(Looper.myLooper()!!)
|
||||||
private val socUpdateHandler = 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::Category::Overlay,
|
||||||
Settings::Specialization::Paired, true,
|
Settings::Specialization::Paired, true,
|
||||||
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::Setting<bool> perf_overlay_background{linkage, false, "perf_overlay_background",
|
||||||
Settings::Category::Overlay,
|
Settings::Category::Overlay,
|
||||||
Settings::Specialization::Default, true,
|
Settings::Specialization::Default, true,
|
||||||
|
|
|
@ -497,6 +497,40 @@
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
</integer-array>
|
</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">
|
<string-array name="dynaStateEntries">
|
||||||
<item>@string/disabled</item>
|
<item>@string/disabled</item>
|
||||||
<item>1</item>
|
<item>1</item>
|
||||||
|
|
|
@ -9,6 +9,29 @@
|
||||||
<string name="notice_notification_channel_description">Shows notifications when something goes wrong.</string>
|
<string name="notice_notification_channel_description">Shows notifications when something goes wrong.</string>
|
||||||
<string name="notification_permission_not_granted">Notification permission not granted!</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 -->
|
<!-- Stats Overlay settings -->
|
||||||
<string name="enhanced_fps_suffix">(Enhanced)</string>
|
<string name="enhanced_fps_suffix">(Enhanced)</string>
|
||||||
<string name="process_ram">Process RAM: %1$d MB</string>
|
<string name="process_ram">Process RAM: %1$d MB</string>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue