Nested gaming session for dual-screen devices (Thor phase 2)#80
Nested gaming session for dual-screen devices (Thor phase 2)#80brycesub wants to merge 9 commits into
Conversation
With the bottom panel enabled in the kernel, the top screen becomes DSI-2 and a second backlight (ae94000.dsi.0) appears that Steam picks up for brightness control instead of the top panel's. - ayn-thor.conf: primary connector is DSI-2; declare the primary backlight, secondary connector, and both touchscreen device names - steamos-priv-write: accept backlight brightness writes and steer them to ARMADA_PRIMARY_BACKLIGHT, rescaling between brightness ranges (bottom is 0-255, top is 0-4096) - desktop-bootstrap/setup-dual-screen: one-time desktop layout for dual-screen devices - primary on top at priority 1, secondary centered below, each touchscreen pinned to its own output (KWin otherwise maps both to the same screen) Requires the armada-packages kernel with the Thor bottom panel enabled; on the old kernel DSI-2 does not exist and gamescope falls back to the only connected output, so ordering is safe. Fixes virtudude#28 (phase 1: no bottom-screen UI in gaming mode yet) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMbeBSJJG1pNfdqkUcG1gn
Gamescope only lights up the primary panel, but the secondary touchscreen still feeds it input - fingers resting on the dark glass move Steam's cursor. Inhibit the device (via /sys/class/input/*/inhibited, made wheel-writable like the other session-managed sysfs knobs) when the gaming session starts and re-enable it when the desktop session starts. A future Armada Control toggle could expose this as a user choice. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMbeBSJJG1pNfdqkUcG1gn
|
Pushed the refresh-rate bridge, closing the known limitation in the PR description: 🤖 Generated with Claude Code |
|
Will take me some time to review and test all this but appreciate the work! Very exciting for the Thor. |
|
Found during end-to-end image testing: the persistent desktop session brings KDE powerdevil's idle suspend with it, and systemd suspend wedges on these devices (stuck Follow-up needed before this ships as the Thor default: powerdevil defaults that disable idle suspend on nested devices (or wire the desktop session into the fake-suspend flow). I'll push a commit for this. 🤖 Generated with Claude Code |
kscreen-doctor -o -j prints the human-readable listing after the JSON document, so json.loads raised JSONDecodeError and the script died before applying the layout or pinning the touchscreens. On first boot that left both touchscreens mapped to the same output: taps on the top screen landed on the bottom desktop, where a stray double-tap on the Return to Game Mode icon logged the session out. Request JSON alone and parse only the first document so trailing text can never take the script down again. Verified on an AYN Thor: layout applied, both touchscreens pinned to their own panel. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LeRkgMBMwWNcnwMk4j5kVx
With ARMADA_GAMING_SESSION=nested (Thor), gaming mode runs as a nested gamescope fullscreen on the primary screen inside the persistent desktop session, with the plasma desktop live on the secondary screen. Mode switches become near-instant: SwitchToDesktopMode just ends the nested gamescope (the desktop is already underneath) and SwitchToGameMode launches it via a transient user unit. steamos-manager handles the switch in its session-bus instance only; the embedded session-swap path is unchanged for single-screen devices and for the system-bus instance. Validated on AYN Thor: instant switch both directions through Steam's UI, game performance indistinguishable from embedded gaming mode. Part of virtudude#28 phase 2 (design doc in docs/superpowers/specs/) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMbeBSJJG1pNfdqkUcG1gn
armada-session-default resets the SDDM session to "gamemode" each boot; on ARMADA_GAMING_SESSION=nested devices that session is now the plasma session, and desktop-bootstrap launches the nested gamescope on a fresh session start. Boot lands in gaming mode with the desktop already live on the secondary screen, and the embedded gamescope session is no longer used on these devices. Known limitation: nested gaming runs at the mode KWin selected for the primary output (120Hz on Thor); Steam's per-game refresh switching is not bridged yet. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMbeBSJJG1pNfdqkUcG1gn
Steam communicates refresh switching by setting GAMESCOPE_DYNAMIC_REFRESH on gamescope's Xwayland root; the embedded DRM backend applies it but nested gamescope cannot modeset the host output. nested-refresh-bridge watches the atom on the nested Xwayland (stdbuf -oL: xprop block-buffers into pipes) and applies the nearest supported panel rate via kscreen-doctor, restoring the max rate when dynamic refresh is disabled or the gaming session ends. nested-gaming exports STEAM_DISPLAY_REFRESH_LIMITS so Steam offers the refresh UI, and Steam's in-between requests (e.g. 90 on a 60/120 panel) snap to the nearest mode, ties to the higher. Validated on hardware via the exact atom writes Steam performs: 60 -> panel 60Hz, 90 -> 120Hz, 0 -> 120Hz. Closes the known limitation from the previous commit. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMbeBSJJG1pNfdqkUcG1gn
Pairs with the armada-packages gamescope patch that reads GAMESCOPE_NESTED_REFRESH_RATES: without it Steam's refresh slider collapses to the single current rate because the nested backend cannot enumerate the host output's modes. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMbeBSJJG1pNfdqkUcG1gn
Pass --prefer-output with the device's primary connector; the armada gamescope patch makes the nested Wayland backend fullscreen onto that output instead of whichever one the host compositor considered active. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMbeBSJJG1pNfdqkUcG1gn
PowerDevil's idle detection does not count gamepad input as activity; with the persistent desktop session hosting nested gaming it suspends the device mid-game (fake-suspend blanks both screens and everything looks wedged until the power button or a reboot). This also explains an intermittent all-black-screens report during prototype testing. Ship a system default that disables automatic suspend on AC and battery; suspend stays available through the power button (powerbuttond -> fake-suspend), and users can re-enable idle suspend in System Settings. Low-battery behavior keeps the upstream default. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XMbeBSJJG1pNfdqkUcG1gn
09fafb4 to
920ef43
Compare
Phase 2 of AYN Thor dual-screen support (#28): gaming mode with both screens live — Steam on the top screen, a full plasma desktop on the bottom — and near-instant mode switching.
Builds on #78 (its two commits are included here; this PR reduces to the two
thor-nested-gamingcommits once #78 merges). Also needs virtudude/armada-packages#2 (gamescopewl_touchpatch), or the top screen loses touch in nested mode.Architecture
With
ARMADA_GAMING_SESSION=nested(set for Thor), the compositor stack is inverted: KWin stays the only DRM master driving both panels, and gaming mode runs as a nested gamescope fullscreen window on the primary screen (/usr/libexec/armada/nested-gaming).steamos-manager's session-bus instance handles Steam'sSwitchToDesktopMode/SwitchToGameModeby stopping/starting the nested gamescope — the desktop is already underneath, so switching is near-instant (no SDDM session swap, no logout). Single-screen devices and the system-bus instance keep the existing session-swap path.armada-session-defaultstill resets to "gamemode" each boot; on nested devices that session is nowarmada-plasma, anddesktop-bootstraplaunches the nested gamescope on fresh session start. Boot lands in gaming mode with the desktop live on the bottom screen.Validated on hardware (AYN Thor)
Refresh switching
Steam's per-game refresh switching works through
nested-refresh-bridge: it watches theGAMESCOPE_DYNAMIC_REFRESHatom Steam sets on the nested Xwayland root and applies the nearest supported panel mode via kscreen-doctor (restoring the max rate when dynamic refresh is off or the session ends).Design doc:
docs/superpowers/specs/(phase 2) — happy to include it in the PR if wanted.🤖 Generated with Claude Code
https://claude.ai/code/session_01XMbeBSJJG1pNfdqkUcG1gn