204 lines
10 KiB
Plaintext
204 lines
10 KiB
Plaintext
# Sway session for the Steam TV box.
|
|
# Installed to /home/<KIOSK_USERNAME>/.config/sway/config by build-steam-tv-box-iso.sh.
|
|
#
|
|
# Every `exec` below inherits the environment set by /usr/local/bin/kiosk-session,
|
|
# which sources /etc/steamtv-agent/config.env — that is how GPU_VENDOR and the MQTT
|
|
# settings get here without this file being templated.
|
|
#
|
|
# THE SHAPE OF THIS SESSION, IN ONE PARAGRAPH: the box powers on, greetd autologins,
|
|
# sway starts, and the only thing it launches is Steam in Big Picture. The browser,
|
|
# Spotify and the player do not exist yet. The first time somebody leaves Big Picture —
|
|
# by quitting Steam, by exiting Big Picture mode, by pressing a workspace key, or via
|
|
# Home Assistant — the media session is brought up behind them. See steam-session and
|
|
# session-watcher, which are the two halves of that.
|
|
|
|
set $mod Mod4
|
|
set $ws_steam 1:steam
|
|
set $ws_games 2:games
|
|
set $ws_web 3:web
|
|
set $ws_media 4:media
|
|
set $ws_music 5:music
|
|
|
|
# Workspace names are a contract with steamtv_agent/sway_control.py,
|
|
# steamtv_agent/session_mode.py, /usr/local/bin/media-session and
|
|
# /usr/local/bin/session-watcher — changing one side means changing all of them.
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Output / input
|
|
# ---------------------------------------------------------------------------
|
|
output * bg #0b0b10 solid_color
|
|
|
|
input type:keyboard {
|
|
xkb_layout @KEYBOARD_LAYOUT@
|
|
}
|
|
|
|
# A gamepad is not an input device to the compositor — it goes straight to Steam and to
|
|
# games via evdev, so there is nothing to configure here for it. What does need
|
|
# configuring is a mouse/trackball on the coffee table, if there is one.
|
|
input type:pointer {
|
|
accel_profile adaptive
|
|
}
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Look — no bars, no borders, no gaps. This is a television.
|
|
# ---------------------------------------------------------------------------
|
|
default_border none
|
|
default_floating_border none
|
|
hide_edge_borders both
|
|
gaps inner 0
|
|
gaps outer 0
|
|
# Games and Big Picture must never be tiled next to something else; every workspace
|
|
# here holds exactly one thing that fills the screen.
|
|
for_window [class="^[Ss]team$"] fullscreen enable
|
|
for_window [class="^gamescope$"] fullscreen enable
|
|
for_window [app_id="^gamescope$"] fullscreen enable
|
|
for_window [app_id="mpv"] fullscreen enable
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Remote control (administration, not play)
|
|
# ---------------------------------------------------------------------------
|
|
# exec_always so a `swaymsg reload` re-establishes it. start-wayvnc refuses to run
|
|
# until /etc/wayvnc/wayvnc-password has been set on this machine.
|
|
#
|
|
# Worth being explicit: this is for fixing the box, not for playing over. wayvnc streams
|
|
# the compositor, so a game rendering at 120fps arrives as a slideshow — that is not a
|
|
# defect to work around, it is what a screen-scraping protocol does.
|
|
exec_always /usr/local/bin/start-wayvnc
|
|
|
|
# The workspace-focus half of the leave-Big-Picture detection. Its own exit-on-
|
|
# sway-death behaviour makes exec_always safe across a reload: the old watcher's pipe
|
|
# closes with the old sway, and reload starts one watcher, not a second.
|
|
exec_always /usr/local/bin/session-watcher
|
|
|
|
# steamtv-agent is NOT started here. systemd owns it (steamtv-agent.service, enabled by
|
|
# 0700-steamtv-agent.hook.chroot) so that it is up and connected to Mosquitto whether or
|
|
# not a graphical session ever came up, and so it survives a sway restart. Starting it
|
|
# from sway too would give two competing MQTT clients.
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# The default application
|
|
# ---------------------------------------------------------------------------
|
|
# This is the whole boot behaviour: land on 1:steam and start Big Picture. steam-session
|
|
# blocks on the Steam client and starts the media session when it exits.
|
|
#
|
|
# No `assign [class="steam"]` rule: Steam maps several windows (splash, client, an
|
|
# optional gamescope surface) and an assign rule would scatter them across workspaces
|
|
# mid-launch. Switching workspace first and letting them map where focus already is
|
|
# gets the same result without the race.
|
|
exec swaymsg workspace $ws_steam
|
|
exec /usr/local/bin/steam-session
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Idle
|
|
# ---------------------------------------------------------------------------
|
|
# Never lock: this is a shared living-room machine, and a lock screen would make the TV
|
|
# unusable to anyone not holding a keyboard.
|
|
#
|
|
# 20 minutes, and only the display — noticeably longer than the thin client's 15,
|
|
# because "nobody has touched an input device" is a much weaker signal here. Watching a
|
|
# two-hour film, or a cutscene, or a turn in a slow strategy game are all legitimately
|
|
# input-free, and the inhibit rules below are what keep the screen alive through them.
|
|
exec swayidle -w \
|
|
timeout 1200 'swaymsg "output * power off"' \
|
|
resume 'swaymsg "output * power on"'
|
|
|
|
# Anything playing keeps the screen on. Steam gets `focus` rather than `fullscreen`
|
|
# because Big Picture is fullscreen essentially always, and a game that alt-tabs itself
|
|
# briefly should not start the idle countdown.
|
|
for_window [class="^[Ss]team$"] inhibit_idle focus
|
|
for_window [class="^gamescope$"] inhibit_idle focus
|
|
for_window [app_id="^gamescope$"] inhibit_idle focus
|
|
for_window [app_id="mpv"] inhibit_idle visible
|
|
for_window [app_id="firefox-esr"] inhibit_idle fullscreen
|
|
for_window [app_id="com.spotify.Client"] inhibit_idle focus
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Local keys. A gamepad drives Steam and games; these are for the keyboard on the back
|
|
# of the remote, and for standing in front of the machine.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# Maintenance shell. A deliberately obscure chord (not $mod+Return, which is the
|
|
# ordinary local-terminal key below) so it is not something a visitor bumps into,
|
|
# floating so it overlays whatever is running instead of tiling against it.
|
|
bindsym $mod+Shift+Ctrl+m exec foot --title maintenance-shell
|
|
for_window [title="maintenance-shell"] floating enable, resize set width 900 height 550, move position center
|
|
|
|
bindsym $mod+Return exec foot
|
|
bindsym $mod+q kill
|
|
bindsym $mod+f fullscreen toggle
|
|
bindsym $mod+Shift+c reload
|
|
|
|
# Getting back into Steam after "Exit Steam" — the counterpart to steam-session's
|
|
# deliberate refusal to relaunch it in a loop. Idempotent, so holding the key does
|
|
# nothing worse than focusing the client.
|
|
bindsym $mod+s exec /usr/local/bin/steam-big-picture
|
|
# And bringing the media half up by hand, for the case where somebody wants Spotify
|
|
# without leaving the game.
|
|
bindsym $mod+m exec /usr/local/bin/media-session start
|
|
# Prism/Minecraft. This goes through Steam (steam://rungameid/…) so Steam Input is
|
|
# active for it — see prism-launch. Which is also why its window lands on 1:steam and
|
|
# not 2:games when Steam is running: it *is* a Steam game as far as the client is
|
|
# concerned, and Big Picture shows it in the library.
|
|
bindsym $mod+p exec /usr/local/bin/prism-launch
|
|
|
|
bindsym $mod+1 workspace $ws_steam
|
|
bindsym $mod+2 workspace $ws_games
|
|
bindsym $mod+3 workspace $ws_web
|
|
bindsym $mod+4 workspace $ws_media
|
|
bindsym $mod+5 workspace $ws_music
|
|
bindsym $mod+Left focus left
|
|
bindsym $mod+Right focus right
|
|
bindsym $mod+Up focus up
|
|
bindsym $mod+Down focus down
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Remote control — the standardised media-key set.
|
|
#
|
|
# Same device class as the thin client's: a wireless USB remote that presents as two
|
|
# HID keyboards (TV controls on the front, a small keyboard on the back). Nothing to
|
|
# configure per-device; the front buttons arrive as the XF86* keysyms below.
|
|
#
|
|
# DELIBERATELY NOT BOUND: plain arrows and Return. Steam's Big Picture, mpv and every
|
|
# web page need them, and a remote's D-pad and OK button send exactly those. Stealing
|
|
# them at the compositor would make Big Picture unnavigable with the remote — which is
|
|
# most of what the remote is for here. Window focus stays on $mod+arrows above.
|
|
#
|
|
# `wev` from the maintenance shell prints the keysym for any button that is not bound.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# Transport. `playerctl -p mpv,spotify` matches the two players this image runs; the
|
|
# order is the priority when both are alive. Steam's own media has no MPRIS bus and is
|
|
# not a target — a game's audio is not something you "pause".
|
|
bindsym XF86AudioPlay exec playerctl -p mpv,spotify play-pause
|
|
bindsym XF86AudioPause exec playerctl -p mpv,spotify pause
|
|
bindsym XF86AudioStop exec playerctl -p mpv,spotify stop
|
|
bindsym XF86AudioNext exec playerctl -p mpv,spotify next
|
|
bindsym XF86AudioPrev exec playerctl -p mpv,spotify previous
|
|
bindsym XF86AudioForward exec playerctl -p mpv,spotify position 30+
|
|
bindsym XF86AudioRewind exec playerctl -p mpv,spotify position 10-
|
|
|
|
# Volume. Sinks, not players — the volume rocker should move the room's volume whether
|
|
# the noise is coming from Spotify or from a game, and a game is the common case here.
|
|
bindsym XF86AudioRaiseVolume exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+
|
|
bindsym XF86AudioLowerVolume exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-
|
|
bindsym XF86AudioMute exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle
|
|
|
|
# Navigation.
|
|
bindsym XF86ChannelUp workspace next
|
|
bindsym XF86ChannelDown workspace prev
|
|
# Home goes back to the games, because on this box that is home.
|
|
bindsym XF86HomePage exec /usr/local/bin/steam-big-picture
|
|
bindsym XF86Back workspace back_and_forth
|
|
bindsym XF86Forward workspace back_and_forth
|
|
|
|
# Power. **The display, not the machine** — same reasoning as the thin client, and more
|
|
# so here: `poweroff` from the sofa would drop whatever game is running, unsaved.
|
|
bindsym XF86PowerOff exec display-toggle
|
|
bindsym XF86Sleep exec display-toggle
|
|
bindsym XF86ScreenSaver exec display-toggle
|
|
|
|
# Deliberately no exit binding: `swaymsg exit` would drop to a black VT and greetd would
|
|
# autologin straight back in. Use SSH or the maintenance shell to administer.
|
|
|
|
workspace $ws_steam
|