mirror of
https://github.com/theupriser/steamify-cachyos.git
synced 2026-10-03 17:41:58 +02:00
- One wizard question: "single user, no password, like SteamOS" switches to SDDM (autologin via CachyOS's own steam-set-session, no workarounds) and removes lock screen, user switching and log out (launcher shows only Sleep/Restart/Shut Down; Meta+L and Ctrl+Alt+Del unbound). Declining keeps the current login manager and KDE's defaults - Look up the newest steamdeck-kde-presets from Valve's release repos and verify its SHA-256; take over the new SteamOS 3.9 defaults - Restart plasmashell through systemd so the desktop keeps the session's dark theme; drop the bundled icon in favour of Valve's and Steam's - README and AGENTS.md updated
325 lines
17 KiB
Bash
325 lines
17 KiB
Bash
#!/bin/bash
|
|
# Valve's SteamOS Vapor desktop theme and SteamOS desktop defaults.
|
|
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
|
|
|
merge_kde_config() {
|
|
# Merge a KDE-style ini file (e.g. one of Valve's /etc/xdg defaults) into
|
|
# the user's own config with kwriteconfig6, so SteamOS defaults win over
|
|
# the distro's without touching package-owned files in /etc/xdg.
|
|
# Nested groups ("[A][B]") are supported; immutable "[$i]" groups and
|
|
# comments are skipped.
|
|
local src="$1" target="$2" line key value
|
|
local -a 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+=("--group" "${BASH_REMATCH[1]}")
|
|
rest="${BASH_REMATCH[2]}"
|
|
done
|
|
continue
|
|
fi
|
|
(( skip )) && continue
|
|
[[ "$line" == *=* ]] || continue
|
|
key="${line%%=*}"; value="${line#*=}"
|
|
kwriteconfig6 --file "$target" "${groups[@]}" --key "$key" "$value"
|
|
done < "$src"
|
|
}
|
|
|
|
install_vapor_theme() {
|
|
# Installs Valve's official SteamOS "Vapor" Plasma theme (color scheme,
|
|
# Plasma look-and-feel package, wallpapers, icons) straight from Valve's
|
|
# own SteamOS package mirror, into the current user's ~/.local/share.
|
|
# This only touches the invoking user's home directory, never system
|
|
# files, so it's independent from everything else this script does.
|
|
local mirror="https://steamdeck-packages.steamos.cloud/archlinux-mirror"
|
|
local repo file_name sha256 tmp_dir
|
|
tmp_dir="$(mktemp -d)"
|
|
|
|
# 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
|
|
kwriteconfig6 --file konsolerc --group "Desktop Entry" --key DefaultProfile Vapor.profile
|
|
mkdir -p ~/.config/gtk-3.0 ~/.config/gtk-4.0
|
|
kwriteconfig6 --file ~/.config/gtk-3.0/settings.ini --group Settings --key gtk-theme-name Vapor
|
|
kwriteconfig6 --file ~/.config/gtk-4.0/settings.ini --group Settings --key 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.
|
|
kwriteconfig6 --file ~/.config/gtk-3.0/settings.ini --group Settings --key gtk-application-prefer-dark-theme true
|
|
kwriteconfig6 --file ~/.config/gtk-4.0/settings.ini --group Settings --key gtk-application-prefer-dark-theme true
|
|
if command -v gsettings >/dev/null 2>&1; then
|
|
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"
|
|
|
|
# Launcher icon
|
|
# Same launcher icon SteamOS sets (Vapor Deck plasmoid setup script).
|
|
local icon_name="distributor-logo-steamdeck"
|
|
local conf_file="$HOME/.config/plasma-org.kde.plasma.desktop-appletsrc"
|
|
|
|
if ! find ~/.local/share/icons /usr/share/icons -iname "${icon_name}.*" 2>/dev/null | grep -q .; then
|
|
warn "Could not find '${icon_name}' installed anywhere under ~/.local/share/icons or /usr/share/icons."
|
|
warn "The launcher icon will be set anyway, but it may show as a broken icon until the file is installed."
|
|
fi
|
|
|
|
if [[ -f "$conf_file" ]]; then
|
|
info "Looking for the Application Launcher applet (Kickoff/Kicker) to set the custom icon..."
|
|
local matches=()
|
|
local current_section=""
|
|
local current_containment=""
|
|
local current_applet=""
|
|
|
|
while IFS= read -r line; do
|
|
if [[ "$line" =~ ^\[Containments\]\[([0-9]+)\]\[Applets\]\[([0-9]+)\]$ ]]; then
|
|
current_containment="${BASH_REMATCH[1]}"
|
|
current_applet="${BASH_REMATCH[2]}"
|
|
current_section="applet_root"
|
|
continue
|
|
fi
|
|
if [[ "$line" =~ ^\[ ]]; then
|
|
current_section=""
|
|
continue
|
|
fi
|
|
if [[ "$current_section" == "applet_root" && "$line" =~ ^plugin=(org\.kde\.plasma\.(kickoff|kicker|simplemenu|homerun|application-menu))$ ]]; then
|
|
matches+=( "${current_containment}:${current_applet}:${BASH_REMATCH[1]}" )
|
|
current_section=""
|
|
fi
|
|
done < "$conf_file"
|
|
|
|
if [[ ${#matches[@]} -gt 0 ]]; then
|
|
for m in "${matches[@]}"; do
|
|
IFS=':' read -r containment applet plugin <<< "$m"
|
|
info "Setting launcher icon on Containment $containment / Applet $applet ($plugin)..."
|
|
kwriteconfig6 \
|
|
--file "$conf_file" \
|
|
--group Containments --group "$containment" \
|
|
--group Applets --group "$applet" \
|
|
--group Configuration --group General \
|
|
--key icon "$icon_name"
|
|
ok "Icon set to '$icon_name'."
|
|
done
|
|
else
|
|
warn "No compatible Application Launcher applet found in panel config. Skipping icon assignment."
|
|
fi
|
|
else
|
|
warn "$conf_file not found. Skipping menu icon configuration."
|
|
fi
|
|
|
|
# SteamOS scales system 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.
|
|
if [[ -f "$conf_file" ]]; then
|
|
local tray
|
|
for tray in $(awk '
|
|
/^\[Containments\]\[[0-9]+\]\[Applets\]\[[0-9]+\]$/ { split($0, p, /[][]+/); sect = p[3] ":" p[5] }
|
|
/^\[/ && !/\]\[Applets\]\[[0-9]+\]$/ { sect = "" }
|
|
/^plugin=org\.kde\.plasma\.systemtray$/ && sect != "" { print sect }
|
|
' "$conf_file"); do
|
|
kwriteconfig6 --file "$conf_file" --group Containments --group "${tray%%:*}" \
|
|
--group Applets --group "${tray#*:}" --group General \
|
|
--key scaleIconsToFit true
|
|
done
|
|
fi
|
|
|
|
# SteamOS shows the date below the time in the panel clock.
|
|
if [[ -f "$conf_file" ]]; then
|
|
local clock
|
|
for clock in $(awk '
|
|
/^\[Containments\]\[[0-9]+\]\[Applets\]\[[0-9]+\]$/ { split($0, p, /[][]+/); sect = p[3] ":" p[5] }
|
|
/^\[/ && !/\]\[Applets\]\[[0-9]+\]$/ { sect = "" }
|
|
/^plugin=org\.kde\.plasma\.digitalclock$/ && sect != "" { print sect }
|
|
' "$conf_file"); do
|
|
kwriteconfig6 --file "$conf_file" --group Containments --group "${clock%%:*}" \
|
|
--group Applets --group "${clock#*:}" --group Configuration --group Appearance \
|
|
--key dateDisplayFormat BelowTime
|
|
done
|
|
fi
|
|
|
|
# Wallpaper
|
|
# Valve ships the wallpapers as flat JPGs in usr/share/wallpapers.
|
|
local wallpaper_path="$HOME/.local/share/wallpapers/Steam Deck Logo Default.jpg"
|
|
|
|
if [[ -f "$wallpaper_path" ]]; then
|
|
info "Applying official Steam Deck Vapor wallpaper via D-Bus script..."
|
|
local dbus_cmd="
|
|
var allDesktops = desktops();
|
|
for (var i = 0; i < allDesktops.length; i++) {
|
|
var d = allDesktops[i];
|
|
d.currentConfigGroup = ['Wallpaper', 'org.kde.image', 'General'];
|
|
d.writeConfig('Image', 'file://${wallpaper_path}');
|
|
}
|
|
"
|
|
if ! pgrep -u "$USER" -x plasmashell >/dev/null; then
|
|
:
|
|
elif command -v qdbus6 >/dev/null 2>&1; then
|
|
qdbus6 org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "$dbus_cmd" >/dev/null 2>&1 || true
|
|
else
|
|
qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "$dbus_cmd" >/dev/null 2>&1 || true
|
|
fi
|
|
|
|
if [[ -f "$conf_file" ]]; then
|
|
local desktop_sections=$(grep -E '^\[Containments\]\[[0-9]+\]$' "$conf_file" || true)
|
|
while read -r section; do
|
|
if [[ -n "$section" ]]; then
|
|
local clean_sec=$(echo "$section" | tr -d '[]')
|
|
kwriteconfig6 --file "$conf_file" --group "$clean_sec" --group Wallpaper --group org.kde.image --group General --key Image "file://${wallpaper_path}"
|
|
fi
|
|
done <<< "$desktop_sections"
|
|
fi
|
|
ok "Wallpaper path pushed to session config."
|
|
else
|
|
warn "Could not find extracted Vapor wallpaper file. Skipping."
|
|
fi
|
|
|
|
# Activate the Vapor global theme and color scheme, then restart
|
|
# plasmashell once so it picks everything up (restarting first races
|
|
# with the settings being written). The theme's own defaults use
|
|
# breeze-dark icons; there is no "Vapor" icon theme.
|
|
kwriteconfig6 --file kdeglobals --group Icons --key Theme "breeze-dark"
|
|
kwriteconfig6 --file kdeglobals --group General --key ColorScheme "Vapor"
|
|
kwriteconfig6 --file plasmarc --group Theme --key name "Vapor"
|
|
|
|
# Same panel change for the next login, in case Plasma isn't running now.
|
|
local panel
|
|
for panel in $(grep -oP '^\[PlasmaViews\]\[Panel \K[0-9]+(?=\]$)' ~/.config/plasmashellrc 2>/dev/null); do
|
|
kwriteconfig6 --file plasmashellrc --group PlasmaViews --group "Panel $panel" --key floating 0
|
|
kwriteconfig6 --file plasmashellrc --group PlasmaViews --group "Panel $panel" --group Defaults --key thickness 44
|
|
done
|
|
|
|
gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor 2>/dev/null || true
|
|
kbuildsycoca6 --noincremental 2>/dev/null || true
|
|
|
|
# Live changes need a running Plasma session; otherwise they are picked
|
|
# up from the config files above at the next Plasma login.
|
|
if pgrep -u "$USER" -x plasmashell >/dev/null; 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.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript \
|
|
'panels().forEach(function (p) {
|
|
p.widgets("org.kde.plasma.systemtray").forEach(function (w) { w.currentConfigGroup = ["General"]; w.writeConfig("scaleIconsToFit", true); });
|
|
p.widgets("org.kde.plasma.digitalclock").forEach(function (w) { w.currentConfigGroup = ["Appearance"]; w.writeConfig("dateDisplayFormat", "BelowTime"); });
|
|
})' \
|
|
>/dev/null 2>&1 || true
|
|
# SteamOS uses a solid, full-width bottom panel at Plasma's stock
|
|
# 44px height (CachyOS ships a floating 30px one).
|
|
qdbus6 org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript \
|
|
'panels().forEach(function (p) { p.floating = false; p.lengthMode = "fill"; p.height = 44; })' \
|
|
>/dev/null 2>&1 || true
|
|
sleep 2 # let plasmashell flush the scripted changes before replacing it
|
|
rm -rf ~/.cache/plasmashell* ~/.cache/org.kde.dirmodel-qml.kcache
|
|
qdbus6 org.kde.KWin /KWin org.kde.KWin.reconfigure >/dev/null 2>&1 || true
|
|
# Restart through systemd so plasmashell keeps the session's environment
|
|
# (platform theme etc.); a plain --replace from this shell may not.
|
|
if systemctl --user cat plasma-plasmashell.service >/dev/null 2>&1; then
|
|
# Also takes over from a stray instance started by an earlier --replace.
|
|
systemctl --user stop plasma-plasmashell.service
|
|
pkill -u "$USER" -x plasmashell && sleep 2
|
|
systemctl --user start plasma-plasmashell.service
|
|
else
|
|
setsid plasmashell --replace >/dev/null 2>&1 &
|
|
fi
|
|
else
|
|
info "No running Plasma session; the theme applies at your next desktop login."
|
|
fi
|
|
|
|
ok "Vapor theme assets installed. Apply it under System Settings > Appearance"
|
|
ok "> Global Theme > Vapor (Steam Deck), next time you're in a Plasma session."
|
|
}
|
|
|
|
setup_vapor_theme() {
|
|
# Step 9 (optional): ask, make sure curl/zstd exist, then install.
|
|
echo
|
|
if ask_yn "Also install Valve's official Vapor (Steam Deck) KDE theme for your desktop session?" n; then
|
|
if ! command -v curl >/dev/null 2>&1; then
|
|
warn "curl not found, installing it first..."
|
|
sudo pacman -S --needed --noconfirm curl
|
|
fi
|
|
if ! command -v unzstd >/dev/null 2>&1; then
|
|
warn "zstd not found, installing it first..."
|
|
sudo pacman -S --needed --noconfirm zstd
|
|
fi
|
|
install_vapor_theme || warn "Vapor theme install ran into a problem - see errors above. Your gamescope boot setup above is unaffected."
|
|
fi
|
|
}
|