diff --git a/README.md b/README.md index ec0b71c..65157ff 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,8 @@ You need a Steam Frame with an internet connection, a keyboard (Bluetooth, or th After the restart, Launch a program → Desktop opens the multi-screen desktop, with its screens arranged around where you're facing. Frametop Display Settings and Frametop Input Settings are in the desktop's application menu, under Settings. +If you work in the desktop for long stretches, stop Steam from putting the headset to sleep while it's plugged in: in Steam, open Settings → Power, and under When Plugged In and Idle set Sleep after to Never. By default Steam suspends the Frame after an hour without input, even while it charges. The displays still turn off a few seconds after you take the headset off. + ### Add a Bluetooth mouse or keyboard 1. Pair it in Steam, under Settings → Bluetooth. diff --git a/docs/design.md b/docs/design.md index 428cad2..0a8a28a 100644 --- a/docs/design.md +++ b/docs/design.md @@ -100,6 +100,10 @@ Keyboards aren't grabbed by default, because a grabbed keyboard's keys went into The session is modeled on SteamOS's `steamos-nested-desktop` and runs beside it. It has its own runtime directory, config (`~/.config/frametop`), and state, so it never disturbs the stock desktop's layout or panels. It runs on a private D-Bus from `dbus-run-session`, which has two consequences. KDE only launches apps in systemd scopes when systemd is on the session bus, so everything started in the desktop lands in its systemd unit, and stopping the unit would kill all of it; `session/keep-apps.sh` moves those programs out first. And tools that need the real user bus, like podman and `distrobox-host-exec`, have to be pointed at it explicitly. +The VR launcher starts the session from the Steam client, and the client's environment came along: `LD_LIBRARY_PATH` pointing at Steam's own runtime, whose `libavcodec` has no H.264 decoder, so VLC in the desktop couldn't play most videos, plus the client's overlay and launch settings. The session script drops the client's variables before it starts anything. SteamOS's global Mesa settings (`/usr/share/deckard/mesavars.sh`) stay, and the gamescope session's Vulkan layer (`ENABLE_GAMESCOPE_WSI`) is only kept for the gamescope backend. + +Steam, not systemd, suspends the Frame: after `system_idle_suspend_ac_sec` (an hour by default) without input on AC power, it logs `Switching to power state: k_ESystemPowerState_Sleep` and suspends, even while charging. It's a Steam setting (Settings → Power → When Plugged In and Idle → Sleep after), so the README recommends setting it to Never. SteamVR's standby, which turns the displays off when the headset comes off, is separate. + Flatpak apps need `XDG_DATA_DIRS` to include Flatpak's exports, or Plasma opens Discover instead of launching them, so the session sources `/etc/profile.d/flatpak.sh`. A podman container's monitor process (conmon) stays in the cgroup of whatever started the container, and `distrobox enter` starts it on demand. When a Frametop service happened to start the `dev` container, stopping that service stopped the container and everything in it, including the desktop's compositor. `scripts/container-up.sh` starts the container in a systemd scope of its own before anything enters it. diff --git a/docs/reference.md b/docs/reference.md index 1d54e29..d0d564f 100644 --- a/docs/reference.md +++ b/docs/reference.md @@ -16,6 +16,8 @@ desktops.sh start | stop | restart | status | log [lines] `session/frametop-session.sh` runs the desktop. It starts ft-screens in the `dev` container (log: `/tmp/frametop-screens.log`), then KWin and Plasma on the host inside it. Only one desktop runs at a time. `desktops.sh start` runs it in its own systemd unit, `frametop-desktop`. It keeps its Plasma config in `~/.config/frametop`, separate from the stock desktop's. +When the VR launcher starts the desktop, it inherits the Steam client's environment. The session script drops the client's runtime from it (`LD_LIBRARY_PATH`, the `STEAM_*` settings, and the Steam overlay's Vulkan layer), so apps in the desktop use the system's libraries, including its video codecs, just as they would after a normal login. + Settings are in two files, and Frametop Display Settings edits both. The screens (resolution, width in metres, scale, curve, which one has the taskbar) and their layout are in `~/.config/frametop-layout.json`. The backend, remote desktop, and pointer settings are in `~/.config/frametop.conf`; `session/frametop.conf.example` lists every key. Restarting the desktop closes its windows. Before the unit stops, `session/keep-apps.sh` moves every program started in the desktop into a systemd scope of its own, so background work such as servers, tmux, and builds keeps running. An app that shuts down its own helper processes when its window closes will still lose them; run that kind of work outside the desktop, for example as a systemd user service. diff --git a/install.sh b/install.sh index 7803288..910a0b1 100755 --- a/install.sh +++ b/install.sh @@ -50,7 +50,7 @@ if on_frame 'test -x ~/.local/bin/distrobox'; then echo "already installed: $(on_frame '~/.local/bin/distrobox version | head -1')" else on_frame 'set -e; mkdir -p ~/dev/src -# A tested release, so an upstream change can't break new installs. +# A tested release, so upstream changes cannot break new installs. [ -d ~/dev/src/distrobox ] || git clone --depth 1 --branch 1.8.2.5 https://github.com/89luca89/distrobox.git ~/dev/src/distrobox cd ~/dev/src/distrobox && ./install --prefix ~/.local' fi @@ -89,6 +89,10 @@ cat <<'EOF' SteamVR has to restart once, to load the 3D mouse driver and to start the input relay before it. Restarting SteamVR closes everything open in VR, including this terminal if it's in a VR desktop. Rebooting the headset works too. + +Recommended: stop Steam from putting the headset to sleep while it's plugged in. In Steam, +open Settings > Power, and under "When Plugged In and Idle" set "Sleep after" to Never. +The displays still turn off when you take the headset off. EOF if ask "Restart SteamVR now?" n; then on_frame 'systemctl --user restart steamvr.service' diff --git a/session/frametop-session.sh b/session/frametop-session.sh index 16bd50f..bc3d431 100755 --- a/session/frametop-session.sh +++ b/session/frametop-session.sh @@ -16,6 +16,19 @@ set -eu here=$(dirname "$(readlink -f "$0")") + +# Started from the VR launcher, the desktop inherits the Steam client's environment. Apps in +# it should see the system as a normal login does, so drop the client's runtime: its +# LD_LIBRARY_PATH put Steam's own libraries ahead of the system's (Steam's libavcodec has no +# H.264 decoder, so VLC couldn't play most videos), and its overlay and launch settings are +# meant for games. SteamOS's own defaults (/usr/share/deckard/mesavars.sh) stay. +for var in $(compgen -e); do + case $var in + LD_LIBRARY_PATH | LD_PRELOAD | STEAM_* | Steam* | SRT_* | PRESSURE_VESSEL_* | MANGOHUD_* | \ + ENABLE_VK_LAYER_VALVE_steam_overlay_* | STEAMVIDEOTOKEN) unset "$var" ;; + esac +done + conf=$HOME/.config/frametop.conf BACKEND=screens SCREENS=2 WIDTH=1920 HEIGHT=1080 PHYS_WIDTH=1.6 REMOTE=0 # shellcheck disable=SC1090 @@ -46,7 +59,6 @@ if [ "${1:-}" != --inner ]; then # Plasma can't find them and opens Discover instead. export XDG_DATA_DIRS=${XDG_DATA_DIRS:-/usr/local/share:/usr/share} set +u; . /etc/profile.d/flatpak.sh; set -u - unset LD_PRELOAD # Arrange the screens in the saved layout once they're up (layout; skipped # when auto-arrange is off). setsid "$here/../layout/ft-layout" apply --wait 90 > /tmp/frametop-layout.log 2>&1 < /dev/null & @@ -80,8 +92,11 @@ if [ "${1:-}" != --inner ]; then exit fi -# Inside the host compositor (ft-screens or gamescope) from here on. -unset LD_PRELOAD XDG_DESKTOP_PORTAL_DIR +# Inside the host compositor (ft-screens or gamescope) from here on. The desktop isn't a +# gamescope client with ft-screens, so the gamescope session's Vulkan layer stays off, and +# the gamescope session's portal config isn't Plasma's. +[ "$backend" = gamescope ] || unset ENABLE_GAMESCOPE_WSI +unset XDG_DESKTOP_PORTAL_DIR [ "$backend" = gamescope ] || screens=${FT_SCREEN_COUNT:-$screens} host_runtime=$XDG_RUNTIME_DIR