diff --git a/lib/desktop-shortcut.sh b/lib/desktop-shortcut.sh index bd85c86..b96bf8a 100644 --- a/lib/desktop-shortcut.sh +++ b/lib/desktop-shortcut.sh @@ -43,9 +43,10 @@ EOF # SteamOS itself uses Valve's "gaming-return" icon (Steam logo with a # 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" - [[ -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" # 2. Generate the .desktop shortcut with instant session switcher strings @@ -69,6 +70,14 @@ EOF ok "Desktop shortcut created successfully." } +set_shortcut_icon() { + # set_shortcut_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() { local desktop_dir desktop_dir="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Desktop")" diff --git a/lib/single-user.sh b/lib/single-user.sh index 6a2237e..8a3ac8e 100644 --- a/lib/single-user.sh +++ b/lib/single-user.sh @@ -9,12 +9,25 @@ single_status() { [[ "$(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() { info "Turning off the lock screen, user switching and logging out..." stop_plasmashell_for_edit # Hides Lock / Switch User in menus. - local action applet + local action for action in lock_screen switch_user start_new_session; do kset single kdeglobals "KDE Action Restrictions" "action/$action" false done @@ -26,14 +39,7 @@ single_enable() { # 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 "Log Out" 'none,Ctrl+Alt+Del,Show Logout Screen' - # Launcher: only Sleep / Restart / Shut Down, no Session dropdown (where - # 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 + single_launcher restart_plasmashell_if_stopped ok "Single user: no lock screen, user switching or log out." diff --git a/lib/steamos-extras.sh b/lib/steamos-extras.sh new file mode 100644 index 0000000..0ea146e --- /dev/null +++ b/lib/steamos-extras.sh @@ -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 : download and extract the newest + # steamdeck-kde-presets into . 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 +} diff --git a/lib/vapor-theme.sh b/lib/vapor-theme.sh index 4c59874..ae6d4b8 100644 --- a/lib/vapor-theme.sh +++ b/lib/vapor-theme.sh @@ -1,269 +1,135 @@ #!/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. -merge_kde_config() { - # Merge a KDE-style ini file (e.g. one of Valve's /etc/xdg defaults) into - # the user's own config (journaled, see lib/state.sh), 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 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" -} +VAPOR_LOOKANDFEEL=com.valve.vapor.desktop +VAPOR_DEFAULTS=/usr/share/plasma/look-and-feel/$VAPOR_LOOKANDFEEL/contents/defaults +# Files the "Desktop and window layout" part replaces wholesale (panels, +# widgets, wallpaper); backed up as-is rather than journaled key by key. +THEME_LAYOUT_FILES=(plasma-org.kde.plasma.desktop-appletsrc plasmashellrc kdedefaults) -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 - 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" +current_colorscheme() { + # CachyOS ships its dark Breeze colors inline in kdeglobals without a + # ColorScheme name, so fall back to the scheme matching ColorSchemeHash. + local name hash f + name="$(kreadconfig6 --file kdeglobals --group General --key ColorScheme)" + if [[ -z "$name" ]]; then + hash="$(kreadconfig6 --file kdeglobals --group General --key ColorSchemeHash)" + for f in ~/.local/share/color-schemes/*.colors /usr/share/color-schemes/*.colors; do + [[ -f "$f" && -n "$hash" ]] || continue + [[ "$(sha1sum < "$f")" == "$hash "* ]] && { name="$(basename "$f" .colors)"; break; } done fi + echo "${name:-BreezeLight}" +} - # Vapor color scheme and Plasma style; the theme's own defaults use - # breeze-dark icons (there is no "Vapor" icon theme). - kset theme kdeglobals KDE LookAndFeelPackage com.valve.vapor.desktop - kset theme kdeglobals Icons Theme breeze-dark - kset theme kdeglobals General ColorScheme Vapor - kset theme plasmarc Theme name Vapor - - # SteamOS uses a solid, full-width bottom panel at Plasma's stock 44px - # height (CachyOS ships a floating 30px one). - local panel - for panel in $(grep -oP '^\[PlasmaViews\]\[Panel \K[0-9]+(?=\]$)' ~/.config/plasmashellrc 2>/dev/null); do - kset theme plasmashellrc "PlasmaViews|Panel $panel" floating 0 - kset theme plasmashellrc "PlasmaViews|Panel $panel|Defaults" 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 [[ "${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." +journal_vapor_defaults() { + # Write every setting from Vapor's defaults file ("[file][group]" + + # key=value) through the undo journal, so disable restores the user's + # icons, cursor, splash, window decoration etc. The color scheme is + # left to plasma-apply-colorscheme. + local line file groups key rest + while IFS= read -r line || [[ -n "$line" ]]; do + if [[ "$line" =~ ^\[([^]]+)\](.*)$ ]]; then + file="${BASH_REMATCH[1]}"; rest="${BASH_REMATCH[2]}"; groups="" + while [[ "$rest" =~ ^\[([^]]*)\](.*)$ ]]; do + groups+="${groups:+|}${BASH_REMATCH[1]}"; rest="${BASH_REMATCH[2]}" + done + elif [[ "$line" == *=* && -n "$groups" ]]; then + key="${line%%=*}" + [[ "$key" == ColorScheme ]] && continue + kset theme "$file" "$groups" "$key" "${line#*=}" + fi + done < "$VAPOR_DEFAULTS" } theme_status() { - [[ "$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage)" == com.valve.vapor.desktop ]] + [[ "$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage)" == "$VAPOR_LOOKANDFEEL" ]] } theme_enable() { - command -v curl >/dev/null 2>&1 || sudo pacman -S --needed --noconfirm curl - command -v unzstd >/dev/null 2>&1 || sudo pacman -S --needed --noconfirm zstd - # Stop plasmashell first: the panel and wallpaper edits go to files it - # would otherwise overwrite with its in-memory config on exit. - stop_plasmashell_for_edit - install_vapor_theme - local rc=$? - restart_plasmashell_if_stopped - (( rc == 0 )) || warn "Vapor theme install ran into a problem - see errors above." - return $rc + if ! pacman -Q cachyos-vapor >/dev/null 2>&1; then + info "Installing cachyos-vapor..." + sudo pacman -S --needed --noconfirm cachyos-vapor || { err "Installing cachyos-vapor failed."; return 1; } + # Only remove it again on disable if we were the ones installing it. + state_set theme installed_pkg 1 + fi + if [[ -z "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]]; then + err "Run this from the Plasma desktop: applying the Vapor layout needs a running Plasma session." + return 1 + 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() { - info "Restoring the previous desktop look..." - local lookandfeel colorscheme - lookandfeel="$(state_get theme lookandfeel org.kde.breeze.desktop)" - colorscheme="$(state_get theme colorscheme BreezeLight)" + extras_disable + info "Restoring the previous desktop look and layout..." + plasma-apply-colorscheme "$(state_get theme colorscheme BreezeLight)" >/dev/null 2>&1 || true + 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 - if has_journal theme; then - krevert theme - else - # Installed by a version of this script without the undo journal: - # 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 + if [[ -d "$backup" ]]; then + for f in "${THEME_LAYOUT_FILES[@]}"; do + rm -rf ~/.config/"$f" + [[ -e "$backup/$f" ]] && cp -a "$backup/$f" ~/.config/ done - kwriteconfig6 --file konsolerc --group "Desktop Entry" --key DefaultProfile --delete - 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 + rm -rf "$backup" 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 + 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 ok "Previous desktop look restored." } diff --git a/setup-gamescope-boot.sh b/setup-gamescope-boot.sh index 3e9476f..201b643 100755 --- a/setup-gamescope-boot.sh +++ b/setup-gamescope-boot.sh @@ -16,7 +16,7 @@ set -uo pipefail 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 source "$SCRIPT_DIR/lib/$lib.sh" done