feat: SteamOS theme from cachyos-vapor with its desktop layout, plus SteamOS desktop extras

- Install CachyOS's cachyos-vapor package instead of extracting Valve's
  steamdeck-kde-presets into ~/.local/share, and remove it again on disable
  if the wizard installed it.
- Apply the Vapor global theme with "Desktop and window layout"
  (lookandfeeltool --resetLayout): Steam Deck wallpaper, SteamOS panel and
  launcher icon. Layout files are backed up and restored, every key from
  Vapor's defaults goes through the undo journal.
- Restore the real previous color scheme (CachyOS's inline BreezeDark colors
  have no scheme name), and clear ColorScheme before plasma-apply-colorscheme,
  which otherwise skips an already named scheme.
- Register Vapor as the dark theme, so Plasma's Dark Mode toggle shows on.
- Drop the SteamOS desktop defaults (GTK, Konsole, gsettings, panel tweaks).
- New lib/steamos-extras.sh, downloaded from Valve's newest
  steamdeck-kde-presets (checksum verified) into /usr/local: Add to Steam,
  Nested Desktop, the gaming-return icon for Return to Gaming Mode, the
  Steam Keyboard window rule and an empty KWallet (only without a wallet).
- single_launcher: re-apply single user's launcher settings after the
  layout reset replaces the launcher.
This commit is contained in:
theupriser committed 2026-09-24 10:00:32 +02:00
1 parent 4719fd8e64
commit 130998345a
5 files changed
+266 -257

No files matched your search

+11 -2
View File
@@ -43,9 +43,10 @@ EOF
# SteamOS itself uses Valve's "gaming-return" icon (Steam logo with a # SteamOS itself uses Valve's "gaming-return" icon (Steam logo with a
# return arrow; the Deck-style arrow is only used on Steam Deck # return arrow; the Deck-style arrow is only used on Steam Deck
# hardware). It comes with the Vapor theme; without it, use Steam's icon. # hardware). The theme installs it (lib/steamos-extras.sh) and updates
# the shortcut via set_shortcut_icon; without it, use Steam's icon.
local shortcut_icon="steam" local shortcut_icon="steam"
[[ -f "$user_home/.local/share/icons/hicolor/scalable/actions/gaming-return.svg" ]] && [[ -f /usr/local/share/icons/hicolor/scalable/actions/gaming-return.svg ]] &&
shortcut_icon="gaming-return" shortcut_icon="gaming-return"
# 2. Generate the .desktop shortcut with instant session switcher strings # 2. Generate the .desktop shortcut with instant session switcher strings
@@ -69,6 +70,14 @@ EOF
ok "Desktop shortcut created successfully." ok "Desktop shortcut created successfully."
} }
set_shortcut_icon() {
# set_shortcut_icon <icon>: update an existing shortcut, if any.
local shortcut
shortcut="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Desktop")/Return to Gaming Mode.desktop"
[[ -f "$shortcut" ]] && sed -i "s/^Icon=.*/Icon=$1/" "$shortcut"
return 0
}
remove_desktop_shortcut() { remove_desktop_shortcut() {
local desktop_dir local desktop_dir
desktop_dir="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Desktop")" desktop_dir="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Desktop")"
+15 -9
View File
@@ -9,12 +9,25 @@ single_status() {
[[ "$(kreadconfig6 --file kdeglobals --group "KDE Action Restrictions" --key action/lock_screen)" == false ]] [[ "$(kreadconfig6 --file kdeglobals --group "KDE Action Restrictions" --key action/lock_screen)" == false ]]
} }
single_launcher() {
# Launcher: only Sleep / Restart / Shut Down, no Session dropdown (where
# Log Out lives). Restricting action/logout instead would also hide
# Restart and Shut Down. Separate so the theme can re-apply it after
# replacing the Plasma layout. Edit only while plasmashell is stopped.
local applet grp
for applet in $(plasma_applets org.kde.plasma.kickoff); do
grp="Containments|${applet%%:*}|Applets|${applet#*:}|Configuration|General"
kset single plasma-org.kde.plasma.desktop-appletsrc "$grp" primaryActions 3
kset single plasma-org.kde.plasma.desktop-appletsrc "$grp" systemFavorites 'suspend,reboot,shutdown'
done
}
single_enable() { single_enable() {
info "Turning off the lock screen, user switching and logging out..." info "Turning off the lock screen, user switching and logging out..."
stop_plasmashell_for_edit stop_plasmashell_for_edit
# Hides Lock / Switch User in menus. # Hides Lock / Switch User in menus.
local action applet local action
for action in lock_screen switch_user start_new_session; do for action in lock_screen switch_user start_new_session; do
kset single kdeglobals "KDE Action Restrictions" "action/$action" false kset single kdeglobals "KDE Action Restrictions" "action/$action" false
done done
@@ -26,14 +39,7 @@ single_enable() {
# Ctrl+Alt+Del logout screen (format: current,default,description). # Ctrl+Alt+Del logout screen (format: current,default,description).
kset single kglobalshortcutsrc ksmserver "Lock Session" $'none,Screensaver\tMeta+L,Lock Session' kset single kglobalshortcutsrc ksmserver "Lock Session" $'none,Screensaver\tMeta+L,Lock Session'
kset single kglobalshortcutsrc ksmserver "Log Out" 'none,Ctrl+Alt+Del,Show Logout Screen' kset single kglobalshortcutsrc ksmserver "Log Out" 'none,Ctrl+Alt+Del,Show Logout Screen'
# Launcher: only Sleep / Restart / Shut Down, no Session dropdown (where single_launcher
# Log Out lives). Restricting action/logout instead would also hide
# Restart and Shut Down.
for applet in $(plasma_applets org.kde.plasma.kickoff); do
local grp="Containments|${applet%%:*}|Applets|${applet#*:}|Configuration|General"
kset single plasma-org.kde.plasma.desktop-appletsrc "$grp" primaryActions 3
kset single plasma-org.kde.plasma.desktop-appletsrc "$grp" systemFavorites 'suspend,reboot,shutdown'
done
restart_plasmashell_if_stopped restart_plasmashell_if_stopped
ok "Single user: no lock screen, user switching or log out." ok "Single user: no lock screen, user switching or log out."
+128
View File
@@ -0,0 +1,128 @@
#!/bin/bash
# SteamOS desktop extras that cachyos-vapor doesn't ship, taken from the
# newest Valve steamdeck-kde-presets package: "Add to Steam" (file
# right-click menu and launcher), Nested Desktop (Plasma as a game inside
# gaming mode), the "Return to Gaming Mode" icon, the Steam Keyboard window
# rule and an empty KWallet. Part of the SteamOS theme component
# (lib/vapor-theme.sh). System files go to /usr/local (nothing
# package-owned); per-user settings go through the undo journal.
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
VALVE_MIRROR="https://steamdeck-packages.steamos.cloud/archlinux-mirror"
NESTED_DIR=/usr/local/share/applications/steam/holo-nested-desktop
EXTRAS_FILES=(
/usr/local/bin/holo-add-to-steam
/usr/local/bin/holo-nested-desktop
/usr/local/share/kio/servicemenus/steam.desktop
/usr/local/share/plasma/kickeractions/steam.desktop
/usr/local/share/icons/hicolor/scalable/actions/gaming-return.svg
"$NESTED_DIR"
)
# Group name for our rule in kwinrulesrc; KWin accepts any unique id.
STEAM_KEYBOARD_RULE=cachyos-gamescope-boot-steam-keyboard
fetch_valve_presets() {
# fetch_valve_presets <dir>: download and extract the newest
# steamdeck-kde-presets into <dir>. The newest SteamOS release repo
# (jupiter-3.9, jupiter-3.10, ...) is found on the mirror; its pacman
# database gives the exact file name and SHA-256, which is verified.
local dir="$1" repo desc file_name sha256
repo="$(curl -fsL "$VALVE_MIRROR/" | grep -oE 'jupiter-[0-9]+\.[0-9]+/' | tr -d / | sort -V | tail -n 1)"
[[ -n "$repo" ]] && curl -fsL "$VALVE_MIRROR/$repo/os/x86_64/$repo.db" -o "$dir/repo.db" ||
{ err "Couldn't read Valve's SteamOS package index ($VALVE_MIRROR)."; return 1; }
desc="$(tar -tf "$dir/repo.db" 2>/dev/null | grep -E '^steamdeck-kde-presets-[0-9][^/]*/desc$' | head -n 1)"
[[ -n "$desc" ]] || { err "No steamdeck-kde-presets in Valve's $repo repository."; return 1; }
file_name="$(tar -xOf "$dir/repo.db" "$desc" | awk '/^%FILENAME%$/ { getline; print }')"
sha256="$(tar -xOf "$dir/repo.db" "$desc" | awk '/^%SHA256SUM%$/ { getline; print }')"
info "Downloading $file_name ($repo)..."
curl -fsL "$VALVE_MIRROR/$repo/os/x86_64/$file_name" -o "$dir/presets.pkg.tar.zst" ||
{ err "Downloading $file_name failed."; return 1; }
echo "$sha256 $dir/presets.pkg.tar.zst" | sha256sum -c --quiet - ||
{ err "Checksum mismatch for $file_name; not using it."; return 1; }
tar -I unzstd -xf "$dir/presets.pkg.tar.zst" -C "$dir" usr/bin usr/share ||
{ err "Extracting $file_name failed."; return 1; }
}
extras_enable() {
info "Installing SteamOS desktop extras (Add to Steam, Nested Desktop, icons)..."
local pkg
for pkg in curl zstd kdialog; do
# holo-add-to-steam and holo-nested-desktop show errors with kdialog.
pacman -Q "$pkg" >/dev/null 2>&1 && continue
sudo pacman -S --needed --noconfirm "$pkg" && state_set theme "installed_$pkg" 1
done
local tmp_dir src
tmp_dir="$(mktemp -d)"
if ! fetch_valve_presets "$tmp_dir"; then
rm -rf "$tmp_dir"
return 1
fi
src="$tmp_dir/usr"
sudo install -D -m 755 "$src/bin/holo-add-to-steam" /usr/local/bin/holo-add-to-steam
sudo install -D -m 755 "$src/bin/holo-nested-desktop" /usr/local/bin/holo-nested-desktop
sudo install -D -m 644 "$src/share/kio/servicemenus/steam.desktop" /usr/local/share/kio/servicemenus/steam.desktop
sudo install -D -m 644 "$src/share/plasma/kickeractions/steam.desktop" /usr/local/share/plasma/kickeractions/steam.desktop
# gaming-return.svg is a symlink in the package; SteamOS uses it for the
# Return to Gaming Mode shortcut on non-Deck hardware.
sudo install -D -m 644 "$src/share/icons/hicolor/scalable/actions/steam-gaming-return.svg" \
/usr/local/share/icons/hicolor/scalable/actions/gaming-return.svg
# Nested Desktop with its Steam library art; the entry points at the
# art under /usr/share, which is where Valve puts it.
sudo rm -rf "$NESTED_DIR"
sudo mkdir -p "$(dirname "$NESTED_DIR")"
sudo cp -r "$src/share/applications/steam/holo-nested-desktop" "$NESTED_DIR"
sudo sed -i "s|/usr/share/applications/steam/holo-nested-desktop|$NESTED_DIR|" "$NESTED_DIR/holo-nested-desktop.desktop"
# An empty, password-less wallet (Valve's), so nothing asks for a wallet
# password: with autologin nobody typed one to unlock it. Only when the
# user has no wallet yet; an existing one is never touched.
local wallet="${XDG_DATA_HOME:-$HOME/.local/share}/kwalletd"
if [[ ! -f "$wallet/kdewallet.kwl" ]]; then
mkdir -p "$wallet"
install -m 600 "$src/share/kwalletd/kdewallet.kwl" "$src/share/kwalletd/kdewallet.salt" "$wallet/"
kset theme kwalletrc Wallet "First Use" false
fi
rm -rf "$tmp_dir"
sudo gtk-update-icon-cache -q -f -t /usr/local/share/icons/hicolor 2>/dev/null || true
kbuildsycoca6 >/dev/null 2>&1 || true
set_shortcut_icon gaming-return
# Keep Steam's on-screen keyboard (Steam + X) above other windows and out
# of the taskbar, like SteamOS's kwinrulesrc.
local rules g="$STEAM_KEYBOARD_RULE"
rules="$(kreadconfig6 --file kwinrulesrc --group General --key rules)"
if [[ ",$rules," != *",$g,"* ]]; then
kset theme kwinrulesrc "$g" Description "Window settings for Steam Keyboard"
kset theme kwinrulesrc "$g" above true
kset theme kwinrulesrc "$g" aboverule 2
kset theme kwinrulesrc "$g" skiptaskbar true
kset theme kwinrulesrc "$g" skiptaskbarrule 2
kset theme kwinrulesrc "$g" title "Steam Keyboard"
kset theme kwinrulesrc "$g" titlematch 2
kset theme kwinrulesrc "$g" type 16
kset theme kwinrulesrc "$g" typerule 2
kset theme kwinrulesrc "$g" wmclass steam
kset theme kwinrulesrc "$g" wmclasscomplete true
kset theme kwinrulesrc "$g" wmclassmatch 2
kset theme kwinrulesrc General rules "${rules:+$rules,}$g"
kset theme kwinrulesrc General count "$(( $(kreadconfig6 --file kwinrulesrc --group General --key count --default 0) + 1 ))"
qdbus6 org.kde.KWin /KWin org.kde.KWin.reconfigure >/dev/null 2>&1 || true
fi
}
extras_disable() {
sudo rm -rf "${EXTRAS_FILES[@]}"
sudo gtk-update-icon-cache -q -f -t /usr/local/share/icons/hicolor 2>/dev/null || true
kbuildsycoca6 >/dev/null 2>&1 || true
set_shortcut_icon steam
local pkg
for pkg in kdialog zstd curl; do
[[ -n "$(state_get theme "installed_$pkg")" ]] && sudo pacman -R --noconfirm "$pkg" >/dev/null 2>&1
done
# The keyboard rule and kwalletrc are reverted by the theme's journal.
# The wallet itself stays: secrets may have been saved in it since.
return 0
}
+111 -245
View File
@@ -1,269 +1,135 @@
#!/bin/bash #!/bin/bash
# Valve's SteamOS Vapor desktop theme and SteamOS desktop defaults. # SteamOS Vapor desktop theme, from CachyOS's cachyos-vapor package.
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own. # Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
merge_kde_config() { VAPOR_LOOKANDFEEL=com.valve.vapor.desktop
# Merge a KDE-style ini file (e.g. one of Valve's /etc/xdg defaults) into VAPOR_DEFAULTS=/usr/share/plasma/look-and-feel/$VAPOR_LOOKANDFEEL/contents/defaults
# the user's own config (journaled, see lib/state.sh), so SteamOS defaults win over # Files the "Desktop and window layout" part replaces wholesale (panels,
# the distro's without touching package-owned files in /etc/xdg. # widgets, wallpaper); backed up as-is rather than journaled key by key.
# Nested groups ("[A][B]") are supported; immutable "[$i]" groups and THEME_LAYOUT_FILES=(plasma-org.kde.plasma.desktop-appletsrc plasmashellrc kdedefaults)
# comments are skipped.
local src="$1" target="$2" line key value
local groups=""
local skip=0
while IFS= read -r line || [[ -n "$line" ]]; do
line="${line%$'\r'}"
[[ -z "$line" || "$line" == \#* ]] && continue
if [[ "$line" == \[* ]]; then
skip=0; groups=""
[[ "$line" == *'[$'* ]] && { skip=1; continue; }
local rest="$line"
while [[ "$rest" =~ ^\[([^]]*)\](.*)$ ]]; do
groups+="${groups:+|}${BASH_REMATCH[1]}"
rest="${BASH_REMATCH[2]}"
done
continue
fi
(( skip )) && continue
[[ "$line" == *=* ]] || continue
key="${line%%=*}"; value="${line#*=}"
kset theme "$target" "$groups" "$key" "$value"
done < "$src"
}
install_vapor_theme() { current_colorscheme() {
# Installs Valve's official SteamOS "Vapor" Plasma theme (color scheme, # CachyOS ships its dark Breeze colors inline in kdeglobals without a
# Plasma look-and-feel package, wallpapers, icons) straight from Valve's # ColorScheme name, so fall back to the scheme matching ColorSchemeHash.
# own SteamOS package mirror, into the current user's ~/.local/share. local name hash f
# This only touches the invoking user's home directory, never system name="$(kreadconfig6 --file kdeglobals --group General --key ColorScheme)"
# files, so it's independent from everything else this script does. if [[ -z "$name" ]]; then
local mirror="https://steamdeck-packages.steamos.cloud/archlinux-mirror" hash="$(kreadconfig6 --file kdeglobals --group General --key ColorSchemeHash)"
local repo file_name sha256 tmp_dir for f in ~/.local/share/color-schemes/*.colors /usr/share/color-schemes/*.colors; do
tmp_dir="$(mktemp -d)" [[ -f "$f" && -n "$hash" ]] || continue
[[ "$(sha1sum < "$f")" == "$hash "* ]] && { name="$(basename "$f" .colors)"; break; }
# Take the package from the newest SteamOS release repo (jupiter-3.9,
# jupiter-3.10, ...), read from its pacman database: that gives the
# exact file name and checksum. Fall back to a known-good version.
info "Looking up the current SteamOS Vapor presets..."
repo="$(curl -fsL "$mirror/" | grep -oE 'jupiter-[0-9]+\.[0-9]+/' | tr -d / | sort -V | tail -n 1)"
if [[ -n "$repo" ]] && curl -fsL "$mirror/$repo/os/x86_64/$repo.db" -o "$tmp_dir/repo.db"; then
local desc
desc="$(tar -tf "$tmp_dir/repo.db" 2>/dev/null | grep -E '^steamdeck-kde-presets-[0-9][^/]*/desc$' | head -n 1)"
if [[ -n "$desc" ]]; then
file_name="$(tar -xOf "$tmp_dir/repo.db" "$desc" | awk '/^%FILENAME%$/ { getline; print }')"
sha256="$(tar -xOf "$tmp_dir/repo.db" "$desc" | awk '/^%SHA256SUM%$/ { getline; print }')"
fi
fi
if [[ -z "${file_name:-}" ]]; then
warn "Couldn't read Valve's package index; using the known-good version."
repo="jupiter-3.9"
file_name="steamdeck-kde-presets-3.9.4-2-any.pkg.tar.zst"
sha256=""
fi
info "Downloading $file_name ($repo)..."
if ! curl -fL "$mirror/$repo/os/x86_64/$file_name" -o "${tmp_dir}/presets.tar.zst"; then
err "Download failed. Valve may have moved/renamed this package;"
err "check $mirror for the current version."
rm -rf "$tmp_dir"
return 1
fi
if [[ -n "$sha256" ]] && ! echo "$sha256 ${tmp_dir}/presets.tar.zst" | sha256sum -c --quiet -; then
err "Checksum mismatch for $file_name; not installing it."
rm -rf "$tmp_dir"
return 1
fi
info "Extracting package contents..."
if ! tar -I unzstd -xf "${tmp_dir}/presets.tar.zst" -C "$tmp_dir"; then
err "Extraction failed (is 'zstd' installed? try: sudo pacman -S --needed zstd)"
rm -rf "$tmp_dir"
return 1
fi
info "Creating local configuration directories..."
mkdir -p ~/.local/share/color-schemes \
~/.local/share/plasma/desktoptheme \
~/.local/share/plasma/look-and-feel \
~/.local/share/wallpapers \
~/.local/share/icons/hicolor
info "Installing Steam Deck theme assets..."
[[ -d "${tmp_dir}/usr/share/color-schemes" ]] && cp -r "${tmp_dir}/usr/share/color-schemes/"* ~/.local/share/color-schemes/
[[ -d "${tmp_dir}/usr/share/plasma/desktoptheme/Vapor" ]] && cp -r "${tmp_dir}/usr/share/plasma/desktoptheme/Vapor" ~/.local/share/plasma/desktoptheme/
[[ -d "${tmp_dir}/usr/share/plasma/look-and-feel/com.valve.vapor.desktop" ]] && cp -r "${tmp_dir}/usr/share/plasma/look-and-feel/com.valve.vapor.desktop" ~/.local/share/plasma/look-and-feel/
[[ -d "${tmp_dir}/usr/share/wallpapers" ]] && cp -r "${tmp_dir}/usr/share/wallpapers/"* ~/.local/share/wallpapers/
[[ -d "${tmp_dir}/usr/share/icons/hicolor" ]] && cp -r "${tmp_dir}/usr/share/icons/hicolor/"* ~/.local/share/icons/hicolor/
# The rest of what SteamOS ships: GTK theme (Steam, Firefox, ...), Konsole
# profile and user avatars -- the same files the AUR package installs.
mkdir -p ~/.local/share/themes ~/.local/share/konsole ~/.local/share/plasma/avatars
[[ -d "${tmp_dir}/usr/share/themes/Vapor" ]] && cp -r "${tmp_dir}/usr/share/themes/Vapor" ~/.local/share/themes/
[[ -d "${tmp_dir}/usr/share/konsole" ]] && cp -r "${tmp_dir}/usr/share/konsole/"* ~/.local/share/konsole/
[[ -d "${tmp_dir}/usr/share/plasma/avatars" ]] && cp -r "${tmp_dir}/usr/share/plasma/avatars/"* ~/.local/share/plasma/avatars/
# Valve's SteamOS desktop defaults (fonts, Steam keyboard window rule,
# no welcome screen, light file indexing, GTK theme).
# Left out on purpose: autostart entries (Steam is started by our user
# unit), sddm/profile.d, and files hardcoding /home/deck or SteamOS tools.
info "Applying SteamOS desktop defaults..."
local f
# kscreenlockerrc is left to the single-user question.
for f in kdeglobals kwinrc kwinrulesrc kded5rc baloofilerc kcminputrc; do
[[ -f "${tmp_dir}/etc/xdg/$f" ]] && merge_kde_config "${tmp_dir}/etc/xdg/$f" "$f"
done
[[ -f "${tmp_dir}/etc/xdg/kded5rc" ]] && merge_kde_config "${tmp_dir}/etc/xdg/kded5rc" kded6rc
kset theme konsolerc "Desktop Entry" DefaultProfile Vapor.profile
mkdir -p ~/.config/gtk-3.0 ~/.config/gtk-4.0
kset theme ~/.config/gtk-3.0/settings.ini Settings gtk-theme-name Vapor
kset theme ~/.config/gtk-4.0/settings.ini Settings gtk-theme-name Vapor
# Vapor is a dark theme: tell GTK, libadwaita and portal-aware apps
# (Firefox, Steam's web views, Flatpaks) to use their dark variants too.
kset theme ~/.config/gtk-3.0/settings.ini Settings gtk-application-prefer-dark-theme true
kset theme ~/.config/gtk-4.0/settings.ini Settings gtk-application-prefer-dark-theme true
if command -v gsettings >/dev/null 2>&1; then
[[ -n "$(state_get theme gsettings_scheme)" ]] ||
state_set theme gsettings_scheme "$(gsettings get org.gnome.desktop.interface color-scheme 2>/dev/null)"
[[ -n "$(state_get theme gsettings_gtk)" ]] ||
state_set theme gsettings_gtk "$(gsettings get org.gnome.desktop.interface gtk-theme 2>/dev/null)"
gsettings set org.gnome.desktop.interface color-scheme prefer-dark 2>/dev/null || true
gsettings set org.gnome.desktop.interface gtk-theme Vapor 2>/dev/null || true
fi
[[ -f "${tmp_dir}/etc/xdg/gtk-2.0/gtkrc" ]] && cp "${tmp_dir}/etc/xdg/gtk-2.0/gtkrc" ~/.gtkrc-2.0
info "Cleaning up temporary files..."
rm -rf "$tmp_dir"
# Remember what to go back to when the theme is turned off again.
[[ -n "$(state_get theme lookandfeel)" ]] ||
state_set theme lookandfeel "$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage \
--default "$(kreadconfig6 --file /etc/xdg/kdeglobals --group KDE --key LookAndFeelPackage --default org.kde.breeze.desktop)")"
[[ -n "$(state_get theme colorscheme)" ]] ||
state_set theme colorscheme "$(kreadconfig6 --file kdeglobals --group General --key ColorScheme --default BreezeLight)"
local appletsrc="plasma-org.kde.plasma.desktop-appletsrc" applet
# Same launcher icon SteamOS sets (Vapor Deck plasmoid setup script).
for applet in $(plasma_applets org.kde.plasma.kickoff); do
kset theme "$appletsrc" "Containments|${applet%%:*}|Applets|${applet#*:}|Configuration|General" icon distributor-logo-steamdeck
done
# SteamOS scales tray icons to the panel height. Valve's setup script
# targets Plasma 5's separate tray containment; in Plasma 6 the setting
# lives on the systemtray applet itself.
for applet in $(plasma_applets org.kde.plasma.systemtray); do
kset theme "$appletsrc" "Containments|${applet%%:*}|Applets|${applet#*:}|General" scaleIconsToFit true
done
# SteamOS shows the date below the time.
for applet in $(plasma_applets org.kde.plasma.digitalclock); do
kset theme "$appletsrc" "Containments|${applet%%:*}|Applets|${applet#*:}|Configuration|Appearance" dateDisplayFormat BelowTime
done
# Wallpaper: Valve ships them as flat JPGs in usr/share/wallpapers.
local wallpaper="$HOME/.local/share/wallpapers/Steam Deck Logo Default.jpg" containment
if [[ -f "$wallpaper" ]]; then
for containment in $(grep -oP '^\[Containments\]\[\K[0-9]+(?=\]$)' ~/.config/"$appletsrc" 2>/dev/null); do
grep -q "^\[Containments\]\[$containment\]\[Wallpaper\]" ~/.config/"$appletsrc" || continue
kset theme "$appletsrc" "Containments|$containment|Wallpaper|org.kde.image|General" Image "file://$wallpaper"
done done
fi fi
echo "${name:-BreezeLight}"
}
# Vapor color scheme and Plasma style; the theme's own defaults use journal_vapor_defaults() {
# breeze-dark icons (there is no "Vapor" icon theme). # Write every setting from Vapor's defaults file ("[file][group]" +
kset theme kdeglobals KDE LookAndFeelPackage com.valve.vapor.desktop # key=value) through the undo journal, so disable restores the user's
kset theme kdeglobals Icons Theme breeze-dark # icons, cursor, splash, window decoration etc. The color scheme is
kset theme kdeglobals General ColorScheme Vapor # left to plasma-apply-colorscheme.
kset theme plasmarc Theme name Vapor local line file groups key rest
while IFS= read -r line || [[ -n "$line" ]]; do
# SteamOS uses a solid, full-width bottom panel at Plasma's stock 44px if [[ "$line" =~ ^\[([^]]+)\](.*)$ ]]; then
# height (CachyOS ships a floating 30px one). file="${BASH_REMATCH[1]}"; rest="${BASH_REMATCH[2]}"; groups=""
local panel while [[ "$rest" =~ ^\[([^]]*)\](.*)$ ]]; do
for panel in $(grep -oP '^\[PlasmaViews\]\[Panel \K[0-9]+(?=\]$)' ~/.config/plasmashellrc 2>/dev/null); do groups+="${groups:+|}${BASH_REMATCH[1]}"; rest="${BASH_REMATCH[2]}"
kset theme plasmashellrc "PlasmaViews|Panel $panel" floating 0 done
kset theme plasmashellrc "PlasmaViews|Panel $panel|Defaults" thickness 44 elif [[ "$line" == *=* && -n "$groups" ]]; then
done key="${line%%=*}"
[[ "$key" == ColorScheme ]] && continue
gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor 2>/dev/null || true kset theme "$file" "$groups" "$key" "${line#*=}"
kbuildsycoca6 --noincremental 2>/dev/null || true fi
done < "$VAPOR_DEFAULTS"
# Live changes need a running Plasma session; otherwise they are picked
# up from the config files above at the next Plasma login.
if [[ "${PLASMASHELL_WAS_RUNNING:-false}" == true ]]; then
info "Applying the theme to the running Plasma session..."
lookandfeeltool -a com.valve.vapor.desktop >/dev/null 2>&1 || true
# lookandfeeltool leaves the distro's color scheme active; apply it explicitly.
plasma-apply-colorscheme Vapor >/dev/null 2>&1 || true
qdbus6 org.kde.kded6 /modules/gtkconfig org.kde.gtkconfig.setGtkTheme Vapor >/dev/null 2>&1 || true
qdbus6 org.kde.KWin /KWin org.kde.KWin.reconfigure >/dev/null 2>&1 || true
else
info "No running Plasma session; the theme applies at your next desktop login."
fi
ok "SteamOS desktop look installed."
} }
theme_status() { theme_status() {
[[ "$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage)" == com.valve.vapor.desktop ]] [[ "$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage)" == "$VAPOR_LOOKANDFEEL" ]]
} }
theme_enable() { theme_enable() {
command -v curl >/dev/null 2>&1 || sudo pacman -S --needed --noconfirm curl if ! pacman -Q cachyos-vapor >/dev/null 2>&1; then
command -v unzstd >/dev/null 2>&1 || sudo pacman -S --needed --noconfirm zstd info "Installing cachyos-vapor..."
# Stop plasmashell first: the panel and wallpaper edits go to files it sudo pacman -S --needed --noconfirm cachyos-vapor || { err "Installing cachyos-vapor failed."; return 1; }
# would otherwise overwrite with its in-memory config on exit. # Only remove it again on disable if we were the ones installing it.
stop_plasmashell_for_edit state_set theme installed_pkg 1
install_vapor_theme fi
local rc=$? if [[ -z "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]]; then
restart_plasmashell_if_stopped err "Run this from the Plasma desktop: applying the Vapor layout needs a running Plasma session."
(( rc == 0 )) || warn "Vapor theme install ran into a problem - see errors above." return 1
return $rc fi
# Only the first time, so a re-apply doesn't overwrite the originals.
local backup="$STATE_DIR/theme-layout" f
if [[ ! -d "$backup" ]]; then
mkdir -p "$backup"
for f in "${THEME_LAYOUT_FILES[@]}"; do
[[ -e ~/.config/"$f" ]] && cp -a ~/.config/"$f" "$backup/"
done
fi
# Applying a color scheme or cursor rewrites more than the journal
# covers (inline colors, GTK settings): remember what to re-apply.
[[ -n "$(state_get theme colorscheme)" ]] || state_set theme colorscheme "$(current_colorscheme)"
[[ -n "$(state_get theme cursor)" ]] ||
state_set theme cursor "$(kreadconfig6 --file kcminputrc --group Mouse --key cursorTheme --default breeze_cursors)"
for f in ~/.config/gtk-3.0/settings.ini ~/.config/gtk-4.0/settings.ini; do
[[ -f "$f" ]] && kset theme "$f" Settings gtk-cursor-theme-name \
"$(kreadconfig6 --file "$f" --group Settings --key gtk-cursor-theme-name)"
done
kset theme kdeglobals KDE LookAndFeelPackage "$VAPOR_LOOKANDFEEL"
# Vapor is a dark theme: register it as the dark one, or Plasma's Dark
# Mode toggle shows "off" and offers to switch to Breeze Dark.
kset theme kdeglobals KDE DefaultDarkLookAndFeel "$VAPOR_LOOKANDFEEL"
journal_vapor_defaults
# Journal the key, then clear it: plasma-apply-colorscheme skips a
# scheme that is already named in the config, without writing its colors.
kset theme kdeglobals General ColorScheme --delete
plasma-apply-colorscheme Vapor >/dev/null 2>&1 || true
info "Applying the Vapor theme with its desktop and window layout..."
# --resetLayout is "Desktop and window layout" in System Settings: the
# SteamOS panel, launcher icon and wallpaper. It needs plasmashell up.
lookandfeeltool -a "$VAPOR_LOOKANDFEEL" --resetLayout >/dev/null 2>&1 ||
{ err "lookandfeeltool failed."; return 1; }
# The new layout has a new launcher, without single user's settings.
if single_status; then
sleep 3
stop_plasmashell_for_edit
single_launcher
restart_plasmashell_if_stopped
fi
extras_enable || warn "SteamOS desktop extras not installed (see above); the theme itself is on."
ok "Vapor theme active."
} }
theme_disable() { theme_disable() {
info "Restoring the previous desktop look..." extras_disable
local lookandfeel colorscheme info "Restoring the previous desktop look and layout..."
lookandfeel="$(state_get theme lookandfeel org.kde.breeze.desktop)" plasma-apply-colorscheme "$(state_get theme colorscheme BreezeLight)" >/dev/null 2>&1 || true
colorscheme="$(state_get theme colorscheme BreezeLight)" plasma-apply-cursortheme "$(state_get theme cursor breeze_cursors)" >/dev/null 2>&1 || true
local backup="$STATE_DIR/theme-layout" f
stop_plasmashell_for_edit stop_plasmashell_for_edit
if has_journal theme; then if [[ -d "$backup" ]]; then
krevert theme for f in "${THEME_LAYOUT_FILES[@]}"; do
else rm -rf ~/.config/"$f"
# Installed by a version of this script without the undo journal: [[ -e "$backup/$f" ]] && cp -a "$backup/$f" ~/.config/
# undo the main settings it made.
kwriteconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage --delete
kwriteconfig6 --file kdeglobals --group General --key ColorScheme --delete
kwriteconfig6 --file kdeglobals --group Icons --key Theme --delete
kwriteconfig6 --file plasmarc --group Theme --key name --delete
local f
for f in ~/.config/gtk-3.0/settings.ini ~/.config/gtk-4.0/settings.ini; do
[[ -f "$f" ]] || continue
kwriteconfig6 --file "$f" --group Settings --key gtk-theme-name --delete
kwriteconfig6 --file "$f" --group Settings --key gtk-application-prefer-dark-theme --delete
done done
kwriteconfig6 --file konsolerc --group "Desktop Entry" --key DefaultProfile --delete rm -rf "$backup"
fi
if command -v gsettings >/dev/null 2>&1; then
local v
v="$(state_get theme gsettings_scheme)"
if [[ -n "$v" ]]; then gsettings set org.gnome.desktop.interface color-scheme "$v" 2>/dev/null
else gsettings reset org.gnome.desktop.interface color-scheme 2>/dev/null; fi
v="$(state_get theme gsettings_gtk)"
if [[ -n "$v" ]]; then gsettings set org.gnome.desktop.interface gtk-theme "$v" 2>/dev/null
else gsettings reset org.gnome.desktop.interface gtk-theme 2>/dev/null; fi
fi
rm -rf ~/.local/share/plasma/look-and-feel/com.valve.vapor.desktop \
~/.local/share/plasma/desktoptheme/Vapor \
~/.local/share/themes/Vapor \
~/.local/share/color-schemes/Vapor.colors ~/.local/share/color-schemes/VGUI.colors \
~/.local/share/konsole/Vapor.profile ~/.local/share/konsole/Vapor.colorscheme \
~/.local/share/wallpapers/Steam\ Deck\ Logo*.jpg ~/.local/share/wallpapers/Troll.jpg
rm -f ~/.gtkrc-2.0
kbuildsycoca6 --noincremental 2>/dev/null || true
if [[ -n "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]]; then
lookandfeeltool -a "$lookandfeel" >/dev/null 2>&1 || true
plasma-apply-colorscheme "$colorscheme" >/dev/null 2>&1 || true
fi fi
# After the tools above, so keys that weren't set before are removed again.
krevert theme
single_status && single_launcher
restart_plasmashell_if_stopped restart_plasmashell_if_stopped
qdbus6 org.kde.KWin /KWin org.kde.KWin.reconfigure >/dev/null 2>&1 || true
if [[ -n "$(state_get theme installed_pkg)" ]]; then
# Fails, and stays installed, when another package (e.g.
# cachyos-handheld) depends on it.
sudo pacman -R --noconfirm cachyos-vapor >/dev/null 2>&1 ||
info "Keeping cachyos-vapor installed (another package needs it)."
fi
state_clear theme state_clear theme
ok "Previous desktop look restored." ok "Previous desktop look restored."
} }
+1 -1
View File
@@ -16,7 +16,7 @@ set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
for lib in common state packages login-manager single-user steam-desktop steam-machine vapor-theme desktop-shortcut menu; do for lib in common state packages login-manager single-user steam-desktop steam-machine vapor-theme steamos-extras desktop-shortcut menu; do
# shellcheck source=/dev/null # shellcheck source=/dev/null
source "$SCRIPT_DIR/lib/$lib.sh" source "$SCRIPT_DIR/lib/$lib.sh"
done done