diff --git a/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt b/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt index 239e3d5f5..3df0052db 100644 --- a/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt +++ b/app/src/main/java/com/droiddeck/launcher/SessionActivity.kt @@ -135,6 +135,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback { private var frameGenEngine by mutableStateOf(FrameGen.ENGINE_OFF) private var frameGenMultiplier by mutableStateOf(2) private var fexPreset by mutableStateOf("") + private var suspendPolicy by mutableStateOf(SessionPrefs.SUSPEND_MANUAL) private var oscMode by mutableStateOf(SessionPrefs.OSC_AUTO) private var shapeMode by mutableStateOf(SessionPrefs.SHAPE_AUTO) private var secondScreenMode by mutableStateOf(SecondScreenMode.NONE) @@ -260,7 +261,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback { fillScreen = if (SessionState.mode == SessionService.MODE_STEAM) fillScreen else null, frameGenEngine = frameGenEngine, frameGenMultiplier = frameGenMultiplier, lsfgReady = LsfgNative.isInstalled(this@SessionActivity), - oscMode = oscMode, touchMode = touchMode, + oscMode = oscMode, suspendPolicy = suspendPolicy, touchMode = touchMode, touchAuto = if (usingTouchpad()) "touchpad" else "direct", shapeMode = shapeMode, fexPreset = fexPreset, secondScreenMode = secondScreenMode, @@ -283,6 +284,11 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback { backActionsInverted = inverted }, onOsc = { v -> SessionPrefs.setOscMode(this@SessionActivity, v); readPrefs(); updateOnScreenControls() }, + onSuspendPolicy = { policy -> + SessionPrefs.setSuspendPolicy(this@SessionActivity, SessionState.mode, policy) + suspendPolicy = policy + SessionService.suspendPolicyChanged(this@SessionActivity) + }, onTouch = { v -> SessionPrefs.setTouchMode(this@SessionActivity, v); readPrefs() }, onShape = { v -> SessionPrefs.setShapeMode(this@SessionActivity, v); readPrefs() }, onFexPreset = { v -> SessionPrefs.setFexPreset(this@SessionActivity, v); readPrefs() }, @@ -391,6 +397,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback { frameGenEngine = FrameGen.engine(this) frameGenMultiplier = FrameGen.multiplier(this) fexPreset = SessionPrefs.fexPreset(this) + suspendPolicy = SessionPrefs.suspendPolicy(this, SessionState.mode) oscMode = SessionPrefs.oscMode(this) shapeMode = SessionPrefs.shapeMode(this) backActionsInverted = SessionPrefs.backActionsInverted(this) diff --git a/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt b/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt index 4e69e65ad..9357991ea 100644 --- a/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt +++ b/app/src/main/java/com/droiddeck/launcher/session/SessionService.kt @@ -144,6 +144,13 @@ class SessionService : Service() { updateSuspendPolicy() return START_NOT_STICKY } + ACTION_SUSPEND_POLICY_CHANGED -> { + if (!SessionState.running) return START_NOT_STICKY + suspendPolicy = SessionPrefs.suspendPolicy(this, SessionState.mode) + suspendAttemptFailed = false + updateSuspendPolicy() + return START_NOT_STICKY + } ACTION_RESUME -> { activityVisible = true screenOn = (getSystemService(Context.POWER_SERVICE) as? PowerManager)?.isInteractive ?: screenOn @@ -1016,6 +1023,7 @@ class SessionService : Service() { const val ACTION_RESUME = "com.droiddeck.launcher.RESUME_SESSION" const val ACTION_HOME_GUIDE = "com.droiddeck.launcher.HOME_GUIDE" const val ACTION_AGENT_START = "com.droiddeck.launcher.AGENT_START" + private const val ACTION_SUSPEND_POLICY_CHANGED = "com.droiddeck.launcher.SUSPEND_POLICY_CHANGED" private const val ACTION_ACTIVITY_VISIBLE = "com.droiddeck.launcher.ACTIVITY_VISIBLE" private const val ACTION_ACTIVITY_HIDDEN = "com.droiddeck.launcher.ACTIVITY_HIDDEN" private const val ACTION_TRACK_AUXILIARY = "com.droiddeck.launcher.TRACK_AUXILIARY" @@ -1070,6 +1078,11 @@ class SessionService : Service() { context.startService(Intent(context, SessionService::class.java).setAction(ACTION_RESUME)) } + fun suspendPolicyChanged(context: Context) { + if (!SessionState.running) return + context.startService(Intent(context, SessionService::class.java).setAction(ACTION_SUSPEND_POLICY_CHANGED)) + } + /** Let the session service clean up the PTY's proot tree if the control screen closes. */ fun stopTerminalProcess(context: Context, pid: Int) { if (pid > 1) context.startService( diff --git a/app/src/main/java/com/droiddeck/launcher/ui/SessionOverlay.kt b/app/src/main/java/com/droiddeck/launcher/ui/SessionOverlay.kt index db5d83889..fc949bda6 100644 --- a/app/src/main/java/com/droiddeck/launcher/ui/SessionOverlay.kt +++ b/app/src/main/java/com/droiddeck/launcher/ui/SessionOverlay.kt @@ -87,7 +87,7 @@ import com.droiddeck.launcher.input.SecondScreenMode import kotlinx.coroutines.flow.collect private val drawerPageTitles = listOf("Now", "Controls", "Session") -private val drawerPageEntries = listOf("hud", "touch", "shape") +private val drawerPageEntries = listOf("hud", "touch", "suspend") private class DrawerFocus { private val requesters = HashMap() @@ -194,6 +194,7 @@ class DrawerActions( val frameGenMultiplier: Int, val lsfgReady: Boolean, val oscMode: String, + val suspendPolicy: String, val backActionsInverted: Boolean, val touchMode: String, val touchAuto: String, @@ -213,6 +214,7 @@ class DrawerActions( val onSteamMenu: (() -> Unit)?, val onQam: (() -> Unit)?, val onOsc: (String) -> Unit, + val onSuspendPolicy: (String) -> Unit, val onBackActionsInverted: (Boolean) -> Unit, val onTouch: (String) -> Unit, val onShape: (String) -> Unit, @@ -475,6 +477,21 @@ fun SessionDrawer(open: Boolean, page: Int, controllerActive: Boolean, onPageCha } } } + SettingsGroup("Session behavior") { + ChoiceRow( + host, "suspend", "Background behavior", + "Applies now and to future sessions in this mode.", + listOf( + SessionPrefs.SUSPEND_AUTO to "Auto", + SessionPrefs.SUSPEND_MANUAL to "Manual", + SessionPrefs.SUSPEND_NEVER to "Never", + ), + a.suspendPolicy, + note = "Auto pauses in the background and resumes when visible. Manual pauses there and waits for Resume. Never keeps the session running.", + chipModifier = focus.track(page, "suspend"), + onPick = a.onSuspendPolicy, + ) + } SettingsGroup("Next session") { ChoiceRow(host, "shape", "Screen ratio", null, SessionPrefs.shapeChoices, a.shapeMode,