diff --git a/README.md b/README.md
index 387029c..647fb1a 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
A setup script that makes a CachyOS desktop install (running KDE Plasma +
`plasma-login-manager`) always boot into a **Steam Deck-style gamescope
-session** — the same "always boots into Big Picture, switch to desktop and
+session** - the same "always boots into Big Picture, switch to desktop and
back on demand" experience SteamOS gives you on a real Deck or the Valve
Steam Machine.
@@ -22,7 +22,7 @@ which is meant to work exactly like it does on real SteamOS. On a
hood) only ever writes a `Session=` key to the autologin config file. On
SDDM this is fine, because SDDM's `User=` is set once by the installer and
never touched again. `plasma-login-manager` needs *both* `Session=` and
- `User=` present to autologin at all — without `User=`, it just falls back
+ `User=` present to autologin at all - without `User=`, it just falls back
to showing the greeter every boot.
2. **Missing `/etc/plasmalogin.conf.d` directory.**
@@ -38,24 +38,29 @@ which is meant to work exactly like it does on real SteamOS. On a
to reset you back to gamescope after a desktop session) only ever writes
to `/etc/plasmalogin.conf.d/zz-steamos-autologin.conf`. But the *base*
`/etc/plasmalogin.conf` file takes priority over that fragment, and it
- ships with `Session=plasma` baked in — so none of those session switches
+ ships with `Session=plasma` baked in - so none of those session switches
ever actually stick, no matter what the fragment says.
This script fixes all three: it ensures the conf.d directory exists, sets the
base config's `Session=`, `User=`, and `Relogin=true` correctly, and installs
a small `systemd` path-watcher that keeps the base config in sync with
-whatever CachyOS's own tools write to the conf.d fragment — so switching
+whatever CachyOS's own tools write to the conf.d fragment - so switching
sessions from inside Steam or the desktop actually works, in both
directions, and resets to gamescope on the next boot by default (matching
real Deck/SteamOS behavior).
+It also optionally offers to install Valve's official **Vapor** KDE Plasma
+theme - the same colors, icons, wallpapers, and Plasma look-and-feel package
+used on real SteamOS - pulled directly from Valve's own SteamOS package
+mirror, so your desktop session matches the gamescope side visually.
+
## Requirements
- CachyOS (or an Arch-based system) with `pacman`
- KDE Plasma installed
- `plasma-login-manager` as the active display manager
*(the script will warn and ask for confirmation if it detects SDDM or
- something else instead — most of these workarounds are specific to
+ something else instead - most of these workarounds are specific to
`plasma-login-manager`)*
- A regular user account with `sudo` access
@@ -68,7 +73,7 @@ chmod +x setup-gamescope-boot.sh
./setup-gamescope-boot.sh
```
-Run it as your normal user, **not** as root — it calls `sudo` internally for
+Run it as your normal user, **not** as root - it calls `sudo` internally for
the specific commands that need it.
The script will:
@@ -80,24 +85,38 @@ The script will:
3. Create `/etc/plasmalogin.conf.d` if it doesn't exist.
4. Back up and rewrite `/etc/plasmalogin.conf`'s `[Autologin]` section.
5. Remove any stray manual override files from earlier troubleshooting
- attempts (only files matching `zzz-steamos-autologin*.conf` — it never
+ attempts (only files matching `zzz-steamos-autologin*.conf` - it never
touches `zz-steamos-autologin.conf`, which CachyOS's own tools own).
6. Install a sync script (`/usr/local/bin/sync-steamos-session.sh`) and a
`systemd` path unit that keeps the base config aligned with session
switches made through Steam or `steamos-session-select`.
-7. Ask whether to reboot immediately to test it.
+7. Ask whether you'd also like to install Valve's **Vapor** (Steam Deck) KDE
+ theme. If you say yes, it downloads the official `steamdeck-kde-presets`
+ package straight from Valve's SteamOS mirror and installs the color
+ scheme, Plasma look-and-feel package, wallpapers, and icons into your
+ user's `~/.local/share`. This step only touches your home directory -
+ nothing system-wide - and installing `curl`/`zstd` first if either is
+ missing. Apply it afterwards from **System Settings > Appearance >
+ Global Theme > Vapor (Steam Deck)** the next time you're in a Plasma
+ session.
-It's **safe to re-run** — every step checks current state first, and any
+ If you keep a folder named `icons/` next to the script (e.g. custom Steam
+ Deck logo assets), it'll also copy those into the right Plasma icon
+ directories automatically. This is entirely optional - the theme installs
+ fine without it.
+8. Ask whether to reboot immediately to test the gamescope setup.
+
+It's **safe to re-run** - every step checks current state first, and any
file it modifies gets backed up once with a `.bak-gamescope-wizard` suffix
before the first change.
## After running it
Boot straight into gamescope: it should happen automatically. From inside
-gamescope, Steam's **Power → Switch to Desktop** should now work. From the
+gamescope, Steam's **Power > Switch to Desktop** should now work. From the
desktop, logging out should drop you back into gamescope automatically
(thanks to CachyOS's own `cachyos-gamescope-autologin.service`, which this
-script doesn't replace — it just makes sure the setting it writes actually
+script doesn't replace - it just makes sure the setting it writes actually
takes effect).
You can also switch sessions manually at any time:
@@ -132,7 +151,7 @@ sudo systemctl daemon-reload
- This works around current CachyOS/`plasma-login-manager` behavior as of
September 2026. If CachyOS fixes `steam-set-session` upstream to write
`User=` and to target whichever base config the login manager actually
- reads, this script becomes unnecessary — check for updates before running
+ reads, this script becomes unnecessary - check for updates before running
it on a freshly reinstalled system.
- Tested on a Valve Steam Machine (desktop AMD APU + discrete GPU) running
CachyOS Desktop edition. Should apply to any CachyOS desktop install using
@@ -140,11 +159,17 @@ sudo systemctl daemon-reload
hardware, which typically ship with SDDM instead.
- If you find CachyOS has patched the underlying issue, please open an issue
or PR here so the script can detect that and skip the workaround.
+- The Vapor theme step depends on Valve's `steamdeck-kde-presets` package
+ staying available at its current URL and version
+ (`steamdeck-kde-presets-0.29-1-any.pkg.tar.zst` on
+ `steamdeck-packages.steamos.cloud`). If Valve ships a newer version or
+ changes the mirror layout, update `pkg_ver` near the top of
+ `install_vapor_theme()` in the script.
## Related upstream reports
-- [CachyOS/gamescope-session#9](https://github.com/CachyOS/gamescope-session/issues/9) — "Switch to Desktop" hang due to missing `/etc/plasmalogin.conf.d`
+- [CachyOS/gamescope-session#9](https://github.com/CachyOS/gamescope-session/issues/9) - "Switch to Desktop" hang due to missing `/etc/plasmalogin.conf.d`
## License
-MIT — do whatever you want with it.
+MIT - do whatever you want with it.
diff --git a/icons/helper.png b/icons/helper.png
new file mode 100644
index 0000000..85af063
Binary files /dev/null and b/icons/helper.png differ
diff --git a/icons/steam-gaming-return.png b/icons/steam-gaming-return.png
new file mode 100644
index 0000000..90fb2c4
Binary files /dev/null and b/icons/steam-gaming-return.png differ
diff --git a/icons/steam-gaming-return.svg b/icons/steam-gaming-return.svg
new file mode 100644
index 0000000..c2a004e
--- /dev/null
+++ b/icons/steam-gaming-return.svg
@@ -0,0 +1,233 @@
+
+
diff --git a/icons/steamdeck-gaming-return.png b/icons/steamdeck-gaming-return.png
new file mode 100644
index 0000000..539e028
Binary files /dev/null and b/icons/steamdeck-gaming-return.png differ
diff --git a/icons/steamdeck-gaming-return.svg b/icons/steamdeck-gaming-return.svg
new file mode 100644
index 0000000..5cff1ce
--- /dev/null
+++ b/icons/steamdeck-gaming-return.svg
@@ -0,0 +1,7 @@
+
+
diff --git a/setup-gamescope-boot.sh b/setup-gamescope-boot.sh
index 58fb1de..bb42151 100755
--- a/setup-gamescope-boot.sh
+++ b/setup-gamescope-boot.sh
@@ -20,6 +20,11 @@
# instead of dropping to the greeter.
#
# Safe to re-run: it is idempotent and backs up files before editing.
+#
+# Optionally also offers to install the official Valve "Vapor" KDE Plasma
+# theme (colors, icons, wallpapers, Plasma look-and-feel package) used on
+# real SteamOS, pulled directly from Valve's own package mirror, so the
+# desktop side matches the gamescope side visually.
set -uo pipefail
@@ -27,10 +32,10 @@ set -uo pipefail
c_reset="\033[0m"; c_bold="\033[1m"; c_green="\033[32m"; c_yellow="\033[33m"; c_red="\033[31m"; c_cyan="\033[36m"
-info() { echo -e "${c_cyan}==>${c_reset} $*"; }
-ok() { echo -e "${c_green}✔${c_reset} $*"; }
-warn() { echo -e "${c_yellow}!${c_reset} $*"; }
-err() { echo -e "${c_red}✘ $*${c_reset}" >&2; }
+info() { echo -e "${c_cyan}[INFO]${c_reset} $*"; }
+ok() { echo -e "${c_green}[OK]${c_reset} $*"; }
+warn() { echo -e "${c_yellow}[WARN]${c_reset} $*"; }
+err() { echo -e "${c_red}[ERROR] $*${c_reset}" >&2; }
ask_yn() {
local prompt="$1" default="${2:-y}" reply
local hint="[Y/n]"; [[ "$default" == "n" ]] && hint="[y/N]"
@@ -57,6 +62,187 @@ backup_file() {
fi
}
+create_desktop_shortcut() {
+ # Determine the home directory of the target user
+ local user_home
+ user_home=$(eval echo "~$TARGET_USER")
+
+ # Locate the correct Desktop directory
+ local desktop_dir
+ if [[ -f "$user_home/.config/user-dirs.dirs" ]]; then
+ desktop_dir=$(grep '^XDG_DESKTOP_DIR=' "$user_home/.config/user-dirs.dirs" | cut -d '"' -f 2)
+ desktop_dir="${desktop_dir/\$HOME/$user_home}"
+ fi
+ desktop_dir="${desktop_dir:-$user_home/Desktop}"
+
+ # Ensure secure icon path and desktop directories exist
+ local secure_icon_dir="$user_home/.local/share/icons/hicolor/scalable/apps"
+ mkdir -p "$secure_icon_dir"
+ mkdir -p "$desktop_dir"
+
+ # 1. Safely copy the icon to the user's permanent theme directory
+ local script_dir
+ script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
+
+ if [[ -f "$script_dir/icons/steam-gaming-return.svg" ]]; then
+ info "Copying icon asset to permanent system theme path..."
+ cp "$script_dir/icons/steam-gaming-return.svg" "$secure_icon_dir/steam-gaming-return.svg"
+ chown "$TARGET_USER:$TARGET_USER" "$secure_icon_dir/steam-gaming-return.svg"
+ else
+ warn "Icon asset not found at $script_dir/icons/steam-gaming-return.svg - Shortcut will use fallback fallback."
+ fi
+
+ # 2. Generate the .desktop shortcut with instant session switcher strings
+ local shortcut_path="$desktop_dir/Return to Gaming Mode.desktop"
+ info "Creating 'Return to Gaming Mode' desktop shortcut at: $shortcut_path"
+
+ cat << EOF > "$shortcut_path"
+[Desktop Entry]
+Name=Return to Gaming Mode
+Comment=Switch session back to Gamescope
+Exec=steamos-session-select gamescope && sudo systemctl start sync-steamos-session.service && sudo systemctl restart plasmalogin
+Icon=steam-gaming-return
+Terminal=false
+Type=Application
+Categories=System;
+EOF
+
+ # Fix permissions for the target user and KDE Plasma desktop ecosystem
+ chmod +x "$shortcut_path"
+ chown "$TARGET_USER:$TARGET_USER" "$shortcut_path"
+
+ # Refresh the system icon cache so Plasma detects the standalone asset immediately
+ gtk-update-icon-cache -f -t "$user_home/.local/share/icons/hicolor" 2>/dev/null || true
+
+ ok "Desktop shortcut created successfully."
+}
+
+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 pkg_ver="0.29"
+ local domain="https://steamdeck-packages.steamos.cloud"
+ local path_dir="archlinux-mirror/jupiter-main/os/x86_64"
+ local file_name="steamdeck-kde-presets-${pkg_ver}-1-any.pkg.tar.zst"
+ local url="${domain}/${path_dir}/${file_name}"
+ local tmp_dir
+ tmp_dir="$(mktemp -d)"
+
+ info "Downloading official SteamOS Vapor presets (v${pkg_ver})..."
+ if ! curl -fL "$url" -o "${tmp_dir}/presets.tar.zst"; then
+ err "Download failed. Valve may have moved/renamed this package;"
+ err "check ${domain} for the current version and update pkg_ver in the script."
+ 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/scalable/apps \
+ ~/.local/share/icons/hicolor/48x48/apps
+
+ 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/
+
+ # ---------- Integrated: Copy project icon to system icons ----------
+ local script_dir
+ script_dir="$(cd "$(dirname "${BASH_SOURCE}")" && pwd)"
+ local target_icon_name="steamdeck-gaming-return.svg"
+
+ if [[ -d "$script_dir/icons" ]]; then
+ info "Copying local Steam Deck logo assets from project icons folder into system paths..."
+ cp "$script_dir/icons/$target_icon_name" ~/.local/share/icons/hicolor/scalable/apps/ 2>/dev/null || true
+ cp "$script_dir/icons/$target_icon_name" ~/.local/share/icons/hicolor/48x48/apps/ 2>/dev/null || true
+ else
+ warn "No local './icons' folder found next to the script - skipping custom menu icon assignment."
+ fi
+
+ local metadata_dir="$HOME/.local/share/plasma/look-and-feel/com.valve.vapor.desktop"
+ if [[ -d "$metadata_dir" ]]; then
+ info "Patching look-and-feel metadata for Plasma 6 compatibility..."
+ mkdir -p "$metadata_dir/contents"
+ echo '{"KPlugin": {"Id": "com.valve.vapor.desktop", "Name": "Vapor (Steam Deck)", "ServiceTypes": ["Plasma/LookAndFeel"]}}' > "$metadata_dir/metadata.json"
+ fi
+
+ info "Cleaning up temporary files..."
+ rm -rf "$tmp_dir"
+
+ # ---------- Integrated: Update Application Launcher Icon ----------
+ local conf_file="$HOME/.config/plasma-org.kde.plasma.desktop-appletsrc"
+
+ 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 "$target_icon_name"
+ ok "Icon set to '$target_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
+ # ------------------------------------------------------
+
+ info "Refreshing Plasma environment and icon caches..."
+ gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor 2>/dev/null || true
+ kbuildsycoca6 --noincremental 2>/dev/null || true
+ rm -rf ~/.cache/plasmashell* ~/.cache/org.kde.dirmodel-qml.kcache
+ setsid plasmashell --replace >/dev/null 2>&1 &
+
+ 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."
+ ok "The Application Launcher menu icon has also been updated to the Steam Deck style."
+}
+
+
# ---------- start ----------
require_root_helper
@@ -238,7 +424,30 @@ ok "Done. Current base config:"
sudo cat "$BASE_CONF"
echo
-# ---------- 9. Summary + reboot ----------
+# ---------- 9. Optional: Vapor (Steam Deck) KDE theme ----------
+
+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 curl
+ fi
+ if ! command -v unzstd >/dev/null 2>&1; then
+ warn "zstd not found, installing it first..."
+ sudo pacman -S --needed zstd
+ fi
+ install_vapor_theme || warn "Vapor theme install ran into a problem - see errors above. Your gamescope boot setup above is unaffected."
+fi
+echo
+
+
+# ---------- 10. Create Return to Gaming Mode Desktop Shortcut ----------
+
+create_desktop_shortcut
+echo
+
+
+# ---------- 11. Summary + reboot ----------
echo -e "${c_bold}Setup complete.${c_reset}"
echo "What this did:"
@@ -248,6 +457,7 @@ echo " - Set $BASE_CONF to autologin '$TARGET_USER' into gamescope, with Relogi
echo " - Installed a sync bridge + systemd watcher so Steam's Switch-to-Desktop"
echo " (and cachyos-gamescope-autologin.service resetting back to gamescope"
echo " on logout) both actually take effect"
+echo " - Optionally installed Valve's Vapor (Steam Deck) KDE theme, if you chose to"
echo
echo "Backups of any files this script modified were saved with a"
echo ".bak-gamescope-wizard suffix next to the original."