feat: separate SteamVR and Cardboard tabs

This commit is contained in:
XxJSONDeruloxX committed 2026-10-15 12:16:39 -04:00
1 parent 389bef5ad3
commit fd6111fc69
7 files changed
+48 -14

No files matched your search

@@ -521,8 +521,8 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
releaseDrawerDirection()
}
}
LaunchedEffect(cardboard.enabled, steamVrSwitchedPicture) {
while (cardboard.enabled || steamVrSwitchedPicture) {
LaunchedEffect(cardboard.enabled, steamVrSwitchedPicture, drawerOpen, drawerPage) {
while (cardboard.enabled || steamVrSwitchedPicture || (drawerOpen && drawerPage == SessionDrawerPage.STEAMVR)) {
val now = kotlinx.coroutines.withContext(kotlinx.coroutines.Dispatchers.IO) {
SteamVr.status(this@SessionActivity)
}
@@ -559,6 +559,7 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback {
onCardboard = { c -> SessionPrefs.setCardboard(this@SessionActivity, c); applyCardboard(c) },
onCardboardRecenter = { headTracker?.recenter() },
steamVr = steamVrStatus,
immersiveSteamVr = com.droiddeck.launcher.session.QuestExperimental.isSupported(),
onSteamVr = { action -> steamVrAction(action) },
textureAnisotropy = if (drawerGameProfileId == null) textureAnisotropy else drawerTextureAnisotropy,
textureLodBias = if (drawerGameProfileId == null) textureLodBias else drawerTextureLodBias,
@@ -5,6 +5,8 @@ internal enum class SessionDrawerPage(val firstControl: String) {
SECOND_SCREEN("second-screen:none"),
DISPLAY("hud"),
EFFECTS("look"),
STEAMVR("steamvr"),
CARDBOARD("cardboard"),
GAMES("anisotropy"),
SESSION("suspend"),
}
@@ -42,6 +42,8 @@ import androidx.compose.material.icons.outlined.PictureInPictureAlt
import androidx.compose.material.icons.automirrored.outlined.ExitToApp
import androidx.compose.material.icons.outlined.Settings
import androidx.compose.material.icons.outlined.SportsEsports
import androidx.compose.material.icons.outlined.ViewInAr
import androidx.compose.material.icons.outlined.Vrpano
import androidx.compose.material3.Icon
import androidx.compose.material3.RadioButton
import androidx.compose.material3.RadioButtonDefaults
@@ -151,6 +153,8 @@ private val SessionDrawerPage.title: Int get() = when (this) {
SessionDrawerPage.CONTROLLER -> R.string.drawer_page_controller
SessionDrawerPage.SECOND_SCREEN -> R.string.drawer_second_screen
SessionDrawerPage.DISPLAY -> R.string.drawer_page_display
SessionDrawerPage.STEAMVR -> R.string.steamvr_title
SessionDrawerPage.CARDBOARD -> R.string.cardboard_title
SessionDrawerPage.EFFECTS -> R.string.drawer_page_effects
SessionDrawerPage.GAMES -> R.string.game_settings_title
SessionDrawerPage.SESSION -> R.string.mode_session
@@ -160,6 +164,8 @@ private val SessionDrawerPage.icon get() = when (this) {
SessionDrawerPage.CONTROLLER -> Icons.Outlined.SportsEsports
SessionDrawerPage.SECOND_SCREEN -> Icons.Outlined.ScreenShare
SessionDrawerPage.DISPLAY -> Icons.Outlined.DesktopWindows
SessionDrawerPage.STEAMVR -> Icons.Outlined.ViewInAr
SessionDrawerPage.CARDBOARD -> Icons.Outlined.Vrpano
SessionDrawerPage.EFFECTS -> Icons.Outlined.AutoFixHigh
SessionDrawerPage.GAMES -> Icons.Outlined.Layers
SessionDrawerPage.SESSION -> Icons.Outlined.Settings
@@ -209,6 +215,7 @@ class DrawerActions(
val cardboard: Cardboard = Cardboard.OFF,
val cardboardSensor: Boolean = false,
val steamVr: SteamVr.Status? = null,
val immersiveSteamVr: Boolean = false,
val textureAnisotropy: Int? = 0,
val textureLodBias: String? = TextureFiltering.LOD_BIAS_OFF,
val secondScreenMode: SecondScreenMode,
@@ -452,12 +459,13 @@ internal fun SessionDrawer(open: Boolean, requestedPage: SessionDrawerPage, cont
stringResource(R.string.display_sharpness), null, a.upscaleSharpness, 0..100, step = 5,
format = { "$it%" }, modifier = focus.track(page, "upscale-sharpness"), onChange = a.onUpscaleSharpness)
}
CardboardGroup(host, a) { key -> focus.track(page, key) }
}
SessionDrawerPage.EFFECTS -> {
ScreenEffectsGroup(host, a, advancedEffectsExpanded,
onAdvancedToggle = { advancedEffectsExpanded = !advancedEffectsExpanded }) { key -> focus.track(page, key) }
}
SessionDrawerPage.STEAMVR -> SteamVrGroup(a) { key -> focus.track(page, key) }
SessionDrawerPage.CARDBOARD -> CardboardGroup(host, a) { key -> focus.track(page, key) }
SessionDrawerPage.CONTROLLER -> {
SettingsGroup(stringResource(R.string.drawer_page_controller)) {
a.padType?.let { type ->
@@ -915,17 +923,34 @@ private fun CardboardGroup(host: MenuHost, a: DrawerActions, track: (String) ->
}
if (c.headTracking && a.cardboardSensor)
ActionRow(stringResource(R.string.cardboard_recenter), null, stringResource(R.string.cardboard_recenter_button), a.onCardboardRecenter)
}
}
@Composable
private fun SteamVrGroup(a: DrawerActions, track: (String) -> Modifier) {
SettingsGroup(stringResource(R.string.steamvr_title)) {
val vrLabel = stringResource(R.string.cardboard_steamvr)
val enterLabel = stringResource(if (a.immersiveSteamVr) R.string.steamvr_enter else R.string.cardboard_steamvr_start)
val enterHint = stringResource(if (a.immersiveSteamVr) R.string.steamvr_quest_ready_hint else R.string.cardboard_steamvr_ready_hint)
@Composable fun button(label: String, hint: String?, text: String, action: String) {
SettingsRow(label, hint) {
SecondaryButton(text, modifier = track("steamvr"), onClick = { a.onSteamVr(action) })
}
}
when (a.steamVr) {
SteamVr.Status.NOT_INSTALLED -> ActionRow(vrLabel, stringResource(R.string.cardboard_steamvr_install_hint),
stringResource(R.string.cardboard_steamvr_install), { a.onSteamVr("install") })
SteamVr.Status.NOT_INSTALLED -> button(vrLabel, stringResource(R.string.cardboard_steamvr_install_hint),
stringResource(R.string.cardboard_steamvr_install), "install")
SteamVr.Status.INSTALLING -> SettingsRow(vrLabel, stringResource(R.string.cardboard_steamvr_installing)) {}
SteamVr.Status.READY -> ActionRow(vrLabel, stringResource(R.string.cardboard_steamvr_ready_hint),
stringResource(R.string.cardboard_steamvr_start), { a.onSteamVr("start") })
SteamVr.Status.RUNNING -> ActionRow(vrLabel, stringResource(R.string.cardboard_steamvr_running_hint),
stringResource(R.string.cardboard_steamvr_stop), { a.onSteamVr("stop") })
SteamVr.Status.READY -> button(vrLabel, enterHint, enterLabel, "start")
SteamVr.Status.RUNNING -> {
if (a.immersiveSteamVr) button(vrLabel, enterHint, enterLabel, "start")
SettingsRow(vrLabel, stringResource(R.string.cardboard_steamvr_running_hint)) {
SecondaryButton(stringResource(R.string.cardboard_steamvr_stop),
modifier = track(if (a.immersiveSteamVr) "steamvr-stop" else "steamvr"), onClick = { a.onSteamVr("stop") })
}
}
SteamVr.Status.UNAVAILABLE -> SettingsRow(vrLabel, stringResource(R.string.cardboard_steamvr_unavailable)) {}
null -> {}
null -> SettingsRow(vrLabel, stringResource(R.string.steamvr_checking)) {}
}
}
}
+4
View File
@@ -595,6 +595,10 @@
<string name="cardboard_no_sensor">This device has no rotation sensor.</string>
<string name="cardboard_recenter">Recenter view</string>
<string name="cardboard_recenter_button">Recenter</string>
<string name="steamvr_title">SteamVR</string>
<string name="steamvr_enter">Enter SteamVR</string>
<string name="steamvr_quest_ready_hint">Enter immersive VR with headset tracking and Touch controllers.</string>
<string name="steamvr_checking">Checking SteamVR…</string>
<string name="cardboard_steamvr">SteamVR (experimental)</string>
<string name="cardboard_steamvr_install">Install</string>
<string name="cardboard_steamvr_install_hint">Downloads Valve\'s ARM64 SteamVR (571 MB).</string>
@@ -20,7 +20,9 @@ class SessionDrawerPageTest {
assertEquals(sessionDrawerPages(false), connected.filter { it != SessionDrawerPage.SECOND_SCREEN })
for (pages in listOf(connected, sessionDrawerPages(false))) {
assertEquals(SessionDrawerPage.EFFECTS, pages.step(SessionDrawerPage.DISPLAY, 1))
assertEquals(SessionDrawerPage.GAMES, pages.step(SessionDrawerPage.EFFECTS, 1))
assertEquals(SessionDrawerPage.STEAMVR, pages.step(SessionDrawerPage.EFFECTS, 1))
assertEquals(SessionDrawerPage.CARDBOARD, pages.step(SessionDrawerPage.STEAMVR, 1))
assertEquals(SessionDrawerPage.GAMES, pages.step(SessionDrawerPage.CARDBOARD, 1))
assertEquals(SessionDrawerPage.SESSION, pages.step(SessionDrawerPage.GAMES, 1))
}
}
+1 -1
View File
@@ -176,7 +176,7 @@ Automator show them:
| `play-steam` | Play on the Steam and Games pages |
| `setting-<key>` | every toggle and choice row, by its key (`setting-logs`, `setting-agent-commands`, ...) |
| `tab-<n>` | a page's tab strip (Setup's Overview, Controller, Session, Launcher...), by position |
| `drawer-tab-controller`, `-second_screen`, `-display`, `-effects`, `-games`, `-session` | the session drawer's pages |
| `drawer-tab-controller`, `-second_screen`, `-display`, `-effects`, `-steamvr`, `-cardboard`, `-games`, `-session` | the session drawer's pages |
| `drawer-stop`, `drawer-stop-confirm`, `drawer-stop-cancel` | stopping a session from the drawer |
## Scenarios
+2 -2
View File
@@ -67,8 +67,8 @@ Host allocation and preload-chain tests do not establish headset operation.
## Experimental immersive SteamVR
In a running Steam session, install SteamVR through DroidDeck's SteamVR controls,
then choose Start. On supported Quest devices this opens the standard app's
In a running Steam session, open the session menu's SteamVR tab, install SteamVR
once, then choose Enter SteamVR. Cardboard has its own tab and can remain off. On supported Quest devices this opens the standard app's
OpenXR activity. The guest driver receives headset poses, Touch controller input
and display timing, and returns owned stereo images with their render poses.
SteamVR haptics return through the tracking bridge. No root or separate XR APK