Compare commits

...
Author SHA1 Message Date
theupriser 53f53a77ff Merge pull request #7 from theupriser/fix/use-cachyos-vapor
Fix/use cachyos vapor
2026-09-24 10:11:31 +02:00
theupriser 6afef78721 ci: The latest tag follows the newest version tag
When v$VERSION is released, move the latest tag and release to it and replace its bundle, so the older install URL keeps giving the newest version.
2026-09-24 10:09:26 +02:00
theupriser 1604ed10d4 docs: Versioning and release rules in AGENTS.md 2026-09-24 10:08:22 +02:00
theupriser 8aab946c6f ci: A release per version (tag v0.7.0, ...) instead of overwriting "latest"
- Publish release v$VERSION with its CHANGELOG.md section; never overwrite an existing version.
- Pull requests warn when VERSION is already released.
- Install URL: releases/latest/download/setup-gamescope-boot.sh (newest release).
2026-09-24 10:07:56 +02:00
theupriser 5cbe0079cb Merge pull request #6 from theupriser/fix/use-cachyos-vapor
Fix/use cachyos vapor
2026-09-24 10:06:21 +02:00
theupriser 5c00504261 docs: Commit hashes in the changelog 2026-09-24 10:04:55 +02:00
theupriser d7231ebbd8 chore: Move the bundle tool to .github/tools/bundle.sh
Update its repo-root path and all references (workflow, README, AGENTS.md).
2026-09-24 10:04:29 +02:00
theupriser eb3169efa1 ci: Version and changelog in the release notes
- Release title shows VERSION; notes include that version's CHANGELOG.md section.
- Rename a variable in steamos-extras.sh that shellcheck confused with lib/state.sh's array in the bundle.
2026-09-24 10:02:30 +02:00
theupriser 10b51644c9 docs: Version 0.7.0 and CHANGELOG
- VERSION in the entry point, shown in the menu header and the bundle.
- CHANGELOG.md with every commit per version (older versions numbered per merged PR).
- README and AGENTS.md updated for the cachyos-vapor theme, the SteamOS extras and the LED driver.
2026-09-24 10:01:08 +02:00
theupriser 7802d90186 fix: LED driver for every kernel, kernel headers at boot, console power button, kernel overview
- The leds-valve Makefile builds against uname -r, so every other kernel
  (e.g. linux-cachyos-lts) failed: add /etc/dkms/leds-valve-dkms.conf with
  MAKE[0]="make KVERSION=${kernelver}". DKMS now builds it for every
  installed kernel and rebuilds it on kernel updates.
- ensure-kernel-headers.service installs missing -headers for newly added
  kernels at boot, which makes DKMS build the driver for them.
- Console-like power handling on mains power: power button sleeps, no
  automatic suspend (journaled powerdevilrc).
- Menu: overview per installed kernel (headers, Steam controller driver,
  LED driver built, running kernel) and whether the LEDs are loaded.
- Menu: the selected row's highlight no longer stops after the green x.
- Theme label in the menu: "Vapor look (cachyos-vapor)".
2026-09-24 10:00:32 +02:00
theupriser 978f5a14cf 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.
2026-09-24 10:00:32 +02:00
theupriser a501df25b5 Update steam-machine.sh
Add inputplumber for the downloadbar.
2026-09-23 21:44:54 +02:00
theupriser 079c48f6fe Merge pull request #5 from theupriser/fix/review-cleanup
fix: Use curl | bash in the docs: bash <(...) doesn't work in fish
2026-09-23 15:42:01 +02:00
theupriser ee5391c126 Merge pull request #4 from theupriser/fix/review-cleanup
fix: Single-file build for curl, published by GitHub Actions
2026-09-23 15:38:31 +02:00
theupriser e741246098 Merge pull request #3 from theupriser/fix/review-cleanup
Fix/review cleanup
2026-09-23 15:27:58 +02:00
theupriser 9827bea8d5 Merge pull request #2 from theupriser/fix/review-cleanup
fix: Add single user no password option with SDDM, fetch newest Vapor…
2026-09-23 14:47:52 +02:00
theupriser dcc184ed39 Merge pull request #1 from theupriser/fix/review-cleanup
fix: Fix setup bugs, add SteamOS desktop look and LED driver, split i…
2026-09-23 14:25:28 +02:00
12 changed files with 640 additions and 341 deletions

No files matched your search

+4 -4
View File
@@ -1,13 +1,13 @@
#!/bin/bash #!/bin/bash
# Build a single-file version of the wizard for `curl | bash` use: # Build a single-file version of the wizard for `curl | bash` use:
# tools/bundle.sh [output] (default: dist/setup-gamescope-boot.sh) # .github/tools/bundle.sh [output] (default: dist/setup-gamescope-boot.sh)
# #
# Inlines lib/*.sh in the order setup-gamescope-boot.sh sources them and # Inlines lib/*.sh in the order setup-gamescope-boot.sh sources them and
# wraps the entry point's body in main(), so bash has read the whole file # wraps the entry point's body in main(), so bash has read the whole file
# before anything runs. That lets the bundle reattach stdin to the terminal # before anything runs. That lets the bundle reattach stdin to the terminal
# when it was piped in by curl, so the interactive menu still works. # when it was piped in by curl, so the interactive menu still works.
set -euo pipefail set -euo pipefail
cd "$(dirname "$0")/.." cd "$(dirname "$0")/../.."
out="${1:-dist/setup-gamescope-boot.sh}" out="${1:-dist/setup-gamescope-boot.sh}"
entry=setup-gamescope-boot.sh entry=setup-gamescope-boot.sh
@@ -17,12 +17,12 @@ mkdir -p "$(dirname "$out")"
libs=$(grep -oP '^for lib in \K.*(?=; do$)' "$entry") libs=$(grep -oP '^for lib in \K.*(?=; do$)' "$entry")
[[ -n "$libs" ]] || { echo "bundle: can't find the lib source loop in $entry" >&2; exit 1; } [[ -n "$libs" ]] || { echo "bundle: can't find the lib source loop in $entry" >&2; exit 1; }
version="$(git describe --always --dirty 2>/dev/null || echo unknown)" version="v$(grep -oP '^VERSION=\K.*' "$entry"), $(git describe --always --dirty 2>/dev/null || echo unknown)"
{ {
# Header comment and `set` line of the entry point, up to the source loop. # Header comment and `set` line of the entry point, up to the source loop.
sed -n '1,/^SCRIPT_DIR=/p' "$entry" | sed '$d' sed -n '1,/^SCRIPT_DIR=/p' "$entry" | sed '$d'
echo "# Single-file build ($version), generated by tools/bundle.sh - edit the" echo "# Single-file build ($version), generated by .github/tools/bundle.sh - edit the"
echo "# sources in the repository instead: https://github.com/theupriser/cachyos-gamescope-boot" echo "# sources in the repository instead: https://github.com/theupriser/cachyos-gamescope-boot"
echo echo
for lib in $libs; do for lib in $libs; do
+49 -15
View File
@@ -1,7 +1,11 @@
# Builds the single-file wizard (tools/bundle.sh) and publishes it as the # Builds the single-file wizard (.github/tools/bundle.sh) and publishes it as a
# asset of the rolling "latest" release, for: # release per version: tag v$VERSION (VERSION in setup-gamescope-boot.sh),
# with that version's CHANGELOG.md section as notes. A released version is
# never overwritten; the newest one is marked latest, and the "latest" tag and
# release are moved to it, so both of these always get the newest version:
# curl -fsSL https://github.com/theupriser/cachyos-gamescope-boot/releases/latest/download/setup-gamescope-boot.sh | bash
# curl -fsSL https://github.com/theupriser/cachyos-gamescope-boot/releases/download/latest/setup-gamescope-boot.sh | bash # curl -fsSL https://github.com/theupriser/cachyos-gamescope-boot/releases/download/latest/setup-gamescope-boot.sh | bash
# Pull requests only build and check it. # Pull requests only build and check it, and warn when VERSION is already released.
name: Single-file build name: Single-file build
on: on:
@@ -22,7 +26,7 @@ jobs:
fetch-depth: 0 # for the version in the bundle's header fetch-depth: 0 # for the version in the bundle's header
- name: Build - name: Build
run: tools/bundle.sh dist/setup-gamescope-boot.sh run: .github/tools/bundle.sh dist/setup-gamescope-boot.sh
- name: Check - name: Check
run: | run: |
@@ -35,20 +39,50 @@ jobs:
name: setup-gamescope-boot name: setup-gamescope-boot
path: dist/setup-gamescope-boot.sh path: dist/setup-gamescope-boot.sh
- name: Publish to the "latest" release - name: Version
if: github.event_name != 'pull_request' && github.ref == 'refs/heads/main' id: version
env: env:
GH_TOKEN: ${{ github.token }} GH_TOKEN: ${{ github.token }}
run: | run: |
notes="Single-file build of $(git describe --always) ($(git log -1 --format=%cs)). version="$(grep -oP '^VERSION=\K.*' setup-gamescope-boot.sh)"
Run it with: echo "version=$version" >> "$GITHUB_OUTPUT"
if gh release view "v$version" >/dev/null 2>&1; then
curl -fsSL https://github.com/${{ github.repository }}/releases/download/latest/setup-gamescope-boot.sh | bash" echo "released=true" >> "$GITHUB_OUTPUT"
if gh release view latest >/dev/null 2>&1; then echo "::warning::v$version is already released and won't be overwritten. Bump VERSION in setup-gamescope-boot.sh and add a CHANGELOG.md section to release this."
gh release edit latest --notes "$notes"
else else
gh release create latest --title "Latest single-file build" --notes "$notes" --latest echo "released=false" >> "$GITHUB_OUTPUT"
fi
- name: Publish the v${{ steps.version.outputs.version }} release
if: >-
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
steps.version.outputs.released == 'false'
env:
GH_TOKEN: ${{ github.token }}
VERSION: ${{ steps.version.outputs.version }}
run: |
# This version's section of CHANGELOG.md, without its heading.
changes="$(awk -v v="$VERSION" '
$0 ~ "^## " { if (found) exit; if (index($0, "## " v " ") == 1) { found = 1; next } }
found' CHANGELOG.md)"
notes="Single-file build of v$VERSION ($(git describe --always), $(git log -1 --format=%cs)).
Run the newest version with:
curl -fsSL https://github.com/${{ github.repository }}/releases/latest/download/setup-gamescope-boot.sh | bash
## Changes in v$VERSION
$changes"
gh release create "v$VERSION" dist/setup-gamescope-boot.sh \
--target "$GITHUB_SHA" --title "v$VERSION" --notes "$notes" --latest
# "latest" follows the newest version tag, for the older install URL
# (.../releases/download/latest/...). Only moved when a new version
# is released, never for a push without a VERSION bump.
git tag -f latest "$GITHUB_SHA" && git push -f origin latest
latest_notes="Always the newest version, currently v$VERSION (see its release for the changes)."
if gh release view latest >/dev/null 2>&1; then
gh release edit latest --title "Latest (v$VERSION)" --notes "$latest_notes" --latest=false
else
gh release create latest --title "Latest (v$VERSION)" --notes "$latest_notes" --latest=false
fi fi
# Move the tag to this commit and replace the asset.
git tag -f latest && git push -f origin latest
gh release upload latest dist/setup-gamescope-boot.sh --clobber gh release upload latest dist/setup-gamescope-boot.sh --clobber
+42 -10
View File
@@ -31,12 +31,13 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
`krevert <component>`. Never call `kwriteconfig6` directly for settings a `krevert <component>`. Never call `kwriteconfig6` directly for settings a
component owns. System files are backed up with `backup_file` and restored component owns. System files are backed up with `backup_file` and restored
on disable. on disable.
- **Single-file build.** `tools/bundle.sh` inlines `lib/*.sh` in the order of - **Single-file build.** `.github/tools/bundle.sh` inlines `lib/*.sh` in the order of
the entry point's `for lib in ...; do` source loop and wraps everything the entry point's `for lib in ...; do` source loop and wraps everything
after that loop in `main()`. Keep that loop on one line, keep all logic in after that loop in `main()`. Keep that loop on one line, keep all logic in
functions, and don't rely on `SCRIPT_DIR` for anything but sourcing. functions, and don't rely on `SCRIPT_DIR` for anything but sourcing.
CI (`.github/workflows/bundle.yml`) publishes the bundle to the `latest` CI (`.github/workflows/bundle.yml`) publishes the bundle as release
release on pushes to `main`. `v$VERSION` on pushes to `main`; an existing version is never overwritten,
so bump `VERSION` for every release.
## Conventions ## Conventions
@@ -58,6 +59,22 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
- Comments explain *why* (the CachyOS/Plasma quirk being worked around), - Comments explain *why* (the CachyOS/Plasma quirk being worked around),
not what the next line does. not what the next line does.
- **Versioning and releases.** SemVer in `VERSION` (`setup-gamescope-boot.sh`,
shown in the menu header and the bundle header).
- Every commit gets an entry in `CHANGELOG.md` under its version (short hash
+ subject; a commit can't contain its own hash, so fill it in with the
next commit). The section heading must be `## <VERSION> - <date>`: CI
cuts the release notes out of the changelog by that heading.
- Every PR that should be released bumps `VERSION` and adds its section.
A push to `main` publishes release `v$VERSION` (tag + bundle + that
changelog section) and marks it latest. An existing version is never
overwritten: without a bump nothing is released, and pull requests show
a warning.
- Users install through `releases/latest/download/setup-gamescope-boot.sh`
(GitHub's newest release). The `latest` tag and release follow the newest
version tag too (moved, asset replaced, when a new version is released),
so the older URL `releases/download/latest/...` keeps working.
## Non-obvious behaviour to preserve ## Non-obvious behaviour to preserve
- `apply_changes` sets `$LOGIN_MANAGER` from the menu: `sddm` when single - `apply_changes` sets `$LOGIN_MANAGER` from the menu: `sddm` when single
@@ -80,11 +97,21 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
- The Steam desktop autostart unit is guarded with - The Steam desktop autostart unit is guarded with
`ExecCondition=... XDG_CURRENT_DESKTOP = KDE`, so it doesn't start a `ExecCondition=... XDG_CURRENT_DESKTOP = KDE`, so it doesn't start a
second Steam inside gamescope. second Steam inside gamescope.
- Vapor theme: install Valve's files as shipped. Don't rewrite Valve's - Vapor theme: comes from the `cachyos-vapor` package (system-wide, in
`metadata.json`; the icon theme is `breeze-dark` (there is no "Vapor" `/usr/share`); only remove it on disable if we installed it. It is applied
icon theme); wallpapers are flat JPGs in `usr/share/wallpapers`. with `lookandfeeltool --resetLayout` ("Desktop and window layout"), which
`lookandfeeltool` does not switch the color scheme, so replaces the panel/desktop layout: the layout files are backed up to
`plasma-apply-colorscheme Vapor` is applied explicitly. `$STATE_DIR/theme-layout` and restored, and every key from Vapor's
`contents/defaults` goes through `kset` first. `plasma-apply-colorscheme`
runs with the `ColorScheme` key cleared, since it skips a scheme already
named there. The layout reset drops single user's launcher settings, so
`single_launcher` is re-applied.
- SteamOS extras (`lib/steamos-extras.sh`, part of the theme): downloaded from
Valve's newest `steamdeck-kde-presets` (repo db gives name + SHA-256) into
`/usr/local`, never `/usr`. `gaming-return.svg` is a symlink in the package:
install `steam-gaming-return.svg` under that name. The shortcut's icon is
switched with `set_shortcut_icon`, since the conversion is created before
the theme. An existing KWallet is never replaced or removed.
- Plasma 6 has no separate systemtray containment: tray settings live on - Plasma 6 has no separate systemtray containment: tray settings live on
the systemtray applet itself (Valve's setup script targets Plasma 5). the systemtray applet itself (Valve's setup script targets Plasma 5).
- Restart plasmashell via `systemctl --user` (`plasma-plasmashell.service`), - Restart plasmashell via `systemctl --user` (`plasma-plasmashell.service`),
@@ -97,8 +124,13 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
wallpaper files only between `stop_plasmashell_for_edit` and wallpaper files only between `stop_plasmashell_for_edit` and
`restart_plasmashell_if_stopped` (`lib/common.sh`). `restart_plasmashell_if_stopped` (`lib/common.sh`).
- LED driver: `leds-valve-dkms-git`'s Makefile builds against `uname -r`, - LED driver: `leds-valve-dkms-git`'s Makefile builds against `uname -r`,
so the script builds explicitly for the running kernel and installs not DKMS's target kernel: `/etc/dkms/leds-valve-dkms.conf` sets
headers for every installed kernel first. The module creates `MAKE[0]="make KVERSION=${kernelver}"` (written before the AUR install).
Without it, other kernels build against the running kernel's tree and
fail (CachyOS kernels are clang-built; DKMS adds `LLVM=1` only for the
target's tree). Headers for every installed kernel are installed first,
and `ensure-kernel-headers.service` installs missing ones at boot (a
pacman hook can't run pacman), which triggers DKMS's install hook. The module creates
`/sys/class/leds/valve-leds*`. `/sys/class/leds/valve-leds*`.
- `Relogin=true` means a gamescope that fails to start is relaunched in a - `Relogin=true` means a gamescope that fails to start is relaunched in a
tight loop; keep that in mind when changing session handling. tight loop; keep that in mind when changing session handling.
+97
View File
@@ -0,0 +1,97 @@
# Changelog
All notable changes, per version and per commit. Versions follow
[Semantic Versioning](https://semver.org/); the current one is `VERSION` in
`setup-gamescope-boot.sh`. Versions before 0.7.0 were numbered afterwards,
one per merged pull request.
## 0.7.0 - 2026-09-24
The SteamOS theme comes from CachyOS's `cachyos-vapor` package, applied with
Vapor's own desktop layout, and gains the SteamOS desktop extras. The Steam
Machine LED driver works on every installed kernel and survives kernel updates.
- `978f5a1` **feat: SteamOS theme from cachyos-vapor with its desktop layout, plus SteamOS desktop extras**
- Installs `cachyos-vapor` instead of extracting Valve's `steamdeck-kde-presets`
into `~/.local/share`; removes it on disable if the wizard installed it.
- Applies the Vapor global theme with "Desktop and window layout": 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.
- Restores the real previous color scheme on disable (CachyOS's BreezeDark
colors have no scheme name), instead of falling back to light Breeze.
- Registers Vapor as the dark theme, so Plasma's Dark Mode toggle shows on.
- Drops the extra SteamOS desktop defaults (GTK, Konsole, gsettings, panel tweaks).
- New SteamOS desktop extras, downloaded from Valve's newest
`steamdeck-kde-presets` (checksum verified) into `/usr/local`: Add to Steam,
Nested Desktop, the SteamOS Return to Gaming Mode icon, the Steam Keyboard
window rule and an empty KWallet (only when there is no wallet yet).
- Single user mode's launcher settings are re-applied after the layout reset.
- `7802d90` **fix: LED driver for every kernel, kernel headers at boot, console power button, kernel overview**
- DKMS override (`/etc/dkms/leds-valve-dkms.conf`) so the LED driver builds
for every installed kernel (the LTS kernel failed) and on kernel updates.
- `ensure-kernel-headers.service` installs missing kernel headers at boot, so
a newly added kernel gets the LED driver too.
- Power button sleeps and no automatic suspend on mains power (Steam Machine).
- Menu shows every kernel with its headers, Steam controller driver and LED
driver, plus whether the LEDs are loaded.
- The selected menu row is highlighted in full.
- `10b5164` **docs: Version 0.7.0 and CHANGELOG**
- `VERSION` in the entry point, shown in the menu header and the bundle.
- README and AGENTS.md updated for the theme, the extras and the LED driver.
- `eb3169e` **ci: Version and changelog in the release notes**
- The `latest` release's title shows the version, and its notes include this
version's section of `CHANGELOG.md`.
- Fix a shellcheck warning in the bundle (a variable name shared with
`lib/state.sh`), which would have failed the CI check.
- `d7231eb` **chore: Move the bundle tool to .github/tools/bundle.sh**
- `5c00504` **docs: Commit hashes in the changelog**
- `8aab946` **ci: A release per version (tag v0.7.0, ...) instead of overwriting "latest"**
- Each push to `main` publishes release `v$VERSION` with that version's
changelog; an already released version is never overwritten (pull requests
get a warning when `VERSION` wasn't bumped).
- Install with `.../releases/latest/download/setup-gamescope-boot.sh`, which
always points to the newest release.
- `1604ed1` **docs: Versioning and release rules in AGENTS.md**
- **ci: The latest tag follows the newest version tag**
- When a new version is released, the `latest` tag and release move to it
(bundle replaced), so the older `.../releases/download/latest/...` URL
also always gives the newest version.
## 0.6.2 - 2026-09-23
- `a501df2` **Update steam-machine.sh**: install and enable `inputplumber`
next to `steamos-manager`.
## 0.6.1 - 2026-09-23 (#5)
- `c0bd16e` **fix: Use curl | bash in the docs**: `bash <(...)` doesn't work in fish.
## 0.6.0 - 2026-09-23 (#4)
- `d654d44` **fix: Single-file build for curl, published by GitHub Actions**:
`tools/bundle.sh` inlines `lib/*.sh`; CI publishes it to the `latest` release.
## 0.5.0 - 2026-09-23 (#3)
- `b91fa4b` **fix: Replace the question flow with a menu that turns components on and off**
- `3d7f376` **fix: Interactive checkbox menu**: arrow keys to move, Space to select, Enter to run.
## 0.4.0 - 2026-09-23 (#2)
- `a0bc385` **fix: Add single user no password option with SDDM, fetch newest Vapor presets**
## 0.3.0 - 2026-09-23 (#1)
- `4ad6c2c` **fix: Fix setup bugs, add SteamOS desktop look and LED driver, split into modules**
## 0.2.0 - 2026-09-07
- `151a3bf` **add steam keyboard to desktop**
- `1999b6e` **Automatically change theme**
## 0.1.0 - 2026-09-06
First version of the script.
- `16a7739`, `97ee6f3`, `6be1051` **commit the script**
- `e1aee45`, `25bc8c0` **change return to gaming mode logo to original logo**
+50 -40
View File
@@ -18,8 +18,8 @@ Everything you turn off is put back the way it was.
Desktop** in Steam works and so does going back (the **Return to Gaming Desktop** in Steam works and so does going back (the **Return to Gaming
Mode** icon on the desktop), you're back in gaming mode after a restart, Mode** icon on the desktop), you're back in gaming mode after a restart,
and Steam's on-screen keyboard (Steam + X) also works on the desktop. and Steam's on-screen keyboard (Steam + X) also works on the desktop.
2. **SteamOS theme** - Valve's own Vapor look for the desktop: wallpaper, 2. **SteamOS theme** - the Vapor look for the desktop (CachyOS's
dark mode and the SteamOS taskbar. `cachyos-vapor` package).
3. **Steam Deck/Machine icons** - Steam Deck button icons in gaming mode. 3. **Steam Deck/Machine icons** - Steam Deck button icons in gaming mode.
4. **Single user mode** - like SteamOS: never a login or lock screen, no 4. **Single user mode** - like SteamOS: never a login or lock screen, no
user switching or logging out. Typing a password with a controller is no user switching or logging out. Typing a password with a controller is no
@@ -38,7 +38,7 @@ Everything you turn off is put back the way it was.
Open **Konsole** on your Plasma desktop and run: Open **Konsole** on your Plasma desktop and run:
```bash ```bash
curl -fsSL https://github.com/theupriser/cachyos-gamescope-boot/releases/download/latest/setup-gamescope-boot.sh | bash curl -fsSL https://github.com/theupriser/cachyos-gamescope-boot/releases/latest/download/setup-gamescope-boot.sh | bash
``` ```
That downloads and runs the latest single-file version, and works in any That downloads and runs the latest single-file version, and works in any
@@ -55,15 +55,22 @@ Run it as yourself, not as root. You'll see a checklist:
``` ```
[x] SteamOS conversion: boot into gaming mode, Steam on the desktop (now: off) [x] SteamOS conversion: boot into gaming mode, Steam on the desktop (now: off)
> [x] Install SteamOS theme: Vapor look, dark mode, SteamOS taskbar (now: off) > [x] Install SteamOS theme: Vapor look (cachyos-vapor) (now: off)
[x] Install Steam Deck/Machine icons: Deck button icons in gaming mode (now: off) [x] Install Steam Deck/Machine icons: Deck button icons in gaming mode (now: off)
[x] Single user mode: no password, lock screen or log out (SDDM) (now: off) [x] Single user mode: no password, lock screen or log out (SDDM) (now: off)
Kernels (> = running; controller = Steam controller driver, LEDs = LED bar driver built)
6.18.52-1-cachyos-lts linux-cachyos-lts headers yes controller yes
> 7.2.7-1-cachyos linux-cachyos headers yes controller yes
Up/Down move Space select Enter run a run + re-apply what's on q quit Up/Down move Space select Enter run a run + re-apply what's on q quit
``` ```
Move with the **arrow keys**, tick or untick with **Space**, and press Move with the **arrow keys**, tick or untick with **Space**, and press
**Enter** to run. "now:" shows what's on at the moment. The wizard then **Enter** to run. "now:" shows what's on at the moment. Below the list, every
installed kernel is shown with its headers and Steam controller driver; on a
Steam Machine also whether the LED bar driver is built for it, and whether
it's loaded right now, so a kernel update is easy to check. The wizard then
shows what it will change, asks your password once, and at the end offers shows what it will change, asks your password once, and at the end offers
to restart (needed for changes to how the PC starts). to restart (needed for changes to how the PC starts).
@@ -213,35 +220,29 @@ file), which makes Steam show Steam Deck button glyphs in gaming mode.
### SteamOS desktop look ### SteamOS desktop look
Downloads Valve's official `steamdeck-kde-presets` package from Valve's Installs CachyOS's `cachyos-vapor` package (the SteamOS Vapor theme the
SteamOS mirror and installs it into `~/.local/share` - nothing system-wide: CachyOS handheld edition uses) from the CachyOS repository and switches your
desktop to its Vapor global theme, including its desktop and window layout
(like ticking "Desktop and window layout" in System Settings): Vapor colors
and Plasma style, the SteamOS panel and launcher icon, and the Steam Deck
wallpaper. Run it from the Plasma desktop: applying the layout needs a
running Plasma session.
- the Vapor global theme, color scheme, Plasma style, wallpapers and icons; It also adds the SteamOS desktop extras that `cachyos-vapor` doesn't ship,
- the Vapor GTK theme, Konsole profile and user avatars; taken from the newest `steamdeck-kde-presets` on Valve's SteamOS mirror
- Valve's SteamOS desktop defaults, merged into your own config: Noto Sans (checksum verified) and installed to `/usr/local`:
fonts, no Xwayland input-permission prompt for Steam Input, the window
rule that keeps the Steam keyboard on top and out of the taskbar, no
welcome screen, light file indexing;
- the SteamOS panel: solid (not floating), full width, 44 px high, tray icons
scaled to fit, date below the time, and the SteamOS launcher icon;
- dark mode for GTK, libadwaita and portal-aware apps (Firefox, Flatpaks).
Run inside a Plasma session, it applies everything live; otherwise it takes - **Add to Steam** in the right-click menu of apps, AppImages and `.exe`
effect at the next desktop login. files, and in the launcher: adds them to Steam as non-Steam games;
- **Nested Desktop**: add it to Steam from the launcher, then start it in
gaming mode for a Plasma desktop inside gaming mode;
- the SteamOS **Return to Gaming Mode** icon (Steam logo with a return arrow);
- a window rule that keeps the **Steam keyboard** above other windows;
- an empty, password-less **KWallet**, only if you don't have a wallet yet,
so nothing asks for a wallet password after autologin.
**Package version.** The script always takes the newest Turning it off restores your previous look and panel layout, and removes `cachyos-vapor` again
`steamdeck-kde-presets` from the highest-numbered SteamOS release repository if the wizard installed it (and nothing else, like `cachyos-handheld`, needs it).
on the mirror (`jupiter-3.9`, `jupiter-3.10`, ...). That repository's pacman
database gives the exact file name and SHA-256 checksum, which is verified
after downloading. If the lookup fails, it falls back to the known-good
3.9.4 (see `install_vapor_theme()` in `lib/vapor-theme.sh`). To check the
current version yourself:
```bash
m=https://steamdeck-packages.steamos.cloud/archlinux-mirror
r=$(curl -fsL $m/ | grep -oE 'jupiter-[0-9]+\.[0-9]+/' | tr -d / | sort -V | tail -n 1)
curl -fsL $m/$r/os/x86_64/$r.db | bsdtar -tf - | grep -o '^steamdeck-kde-presets-[^/]*' | sort -u
```
### Front LED bar (Steam Machine) ### Front LED bar (Steam Machine)
@@ -251,10 +252,12 @@ The **Steam Machine support** component, only shown on Fremont hardware
- installs an AUR helper (`yay`) if neither `yay` nor `paru` is present; - installs an AUR helper (`yay`) if neither `yay` nor `paru` is present;
- installs the kernel headers for every installed kernel; - installs the kernel headers for every installed kernel;
- installs `leds-valve-dkms-git` from the AUR - Valve's own driver from the - installs `leds-valve-dkms-git` from the AUR - Valve's own driver from the
SteamOS kernel - builds it for the running kernel, and loads it at every SteamOS kernel - builds it for every installed kernel (so the LTS kernel
boot (`/etc/modules-load.d/leds-valve.conf`); works too), and loads it at every boot (`/etc/modules-load.d/leds-valve.conf`);
- adds a udev rule (`/etc/udev/rules.d/70-valve-leds-user.rules`) that gives - adds a udev rule (`/etc/udev/rules.d/70-valve-leds-user.rules`) that gives
your user the LED files, so Steam, which runs as you, can drive the bar; your user the LED files, so Steam, which runs as you, can drive the bar;
- console-like power button: it puts the machine to sleep, and it never
suspends by itself on mains power (the launcher's Shut Down still shuts down);
- installs and enables `steamos-manager`, the service Steam in gaming mode - installs and enables `steamos-manager`, the service Steam in gaming mode
uses for hardware settings (fan, HDMI-CEC, performance); it recognises the uses for hardware settings (fan, HDMI-CEC, performance); it recognises the
Steam Machine from its DMI data. Steam Machine from its DMI data.
@@ -262,9 +265,13 @@ The **Steam Machine support** component, only shown on Fremont hardware
Turning it off removes all of that again (the AUR helper is kept). Turning it off removes all of that again (the AUR helper is kept).
The LEDs appear as `/sys/class/leds/valve-leds*`. The driver's Makefile The LEDs appear as `/sys/class/leds/valve-leds*`. The driver's Makefile
builds against the running kernel, so after a kernel update, boot the new builds against the running kernel (`uname -r`) instead of the kernel DKMS
kernel and re-apply (`a` in the menu) or run builds for, so the wizard adds a DKMS override
`sudo dkms install leds-valve-dkms/0.1 -k "$(uname -r)"`. (`/etc/dkms/leds-valve-dkms.conf`) that passes DKMS's target kernel in. With
it, DKMS rebuilds the driver whenever a kernel or its headers are installed
or upgraded. A newly added kernel doesn't come with its headers, so
`ensure-kernel-headers.service` checks at every boot and installs any
missing `-headers` package, which makes DKMS build the driver for it.
Troubleshooting: Troubleshooting:
@@ -318,15 +325,18 @@ gamescope-session, ...) stay installed.
| `lib/login-manager.sh` | SteamOS conversion: SDDM or plasmalogin autologin, sync bridge | | `lib/login-manager.sh` | SteamOS conversion: SDDM or plasmalogin autologin, sync bridge |
| `lib/steam-desktop.sh` | Steam in the Plasma session; Steam Deck/Machine icons | | `lib/steam-desktop.sh` | Steam in the Plasma session; Steam Deck/Machine icons |
| `lib/desktop-shortcut.sh` | Return to Gaming Mode shortcut and its sudoers rule | | `lib/desktop-shortcut.sh` | Return to Gaming Mode shortcut and its sudoers rule |
| `lib/vapor-theme.sh` | SteamOS theme: Vapor, Valve's defaults, panel, dark mode | | `lib/vapor-theme.sh` | SteamOS theme: installs and switches to `cachyos-vapor` |
| `lib/steamos-extras.sh` | SteamOS desktop extras from Valve's package (Add to Steam, Nested Desktop, icon, keyboard rule, KWallet) |
| `lib/single-user.sh` | Single user mode: no lock screen, user switching or log out | | `lib/single-user.sh` | Single user mode: no lock screen, user switching or log out |
| `lib/steam-machine.sh` | Steam Machine support: LED driver, LED access, steamos-manager | | `lib/steam-machine.sh` | Steam Machine support: LED driver, LED access, steamos-manager |
| `tools/bundle.sh` | Builds the single-file version (`dist/setup-gamescope-boot.sh`) | | `.github/tools/bundle.sh` | Builds the single-file version (`dist/setup-gamescope-boot.sh`) |
| `.github/workflows/bundle.yml` | Builds and checks it on every push; publishes it on `main` | | `.github/workflows/bundle.yml` | Builds and checks it on every push; publishes it on `main` |
The single-file version is generated: on every push to `main`, GitHub The single-file version is generated: on every push to `main`, GitHub
Actions runs `tools/bundle.sh`, checks the result with `bash -n` and Actions runs `.github/tools/bundle.sh`, checks the result with `bash -n` and
shellcheck, and uploads it to the rolling `latest` release. It inlines shellcheck, and publishes it as a release per version (tag `v<VERSION>`,
never overwritten; the newest is marked latest, and the `latest` tag follows
it). It inlines
`lib/*.sh` and wraps the entry point in `main()`, so bash has read the whole `lib/*.sh` and wraps the entry point in `main()`, so bash has read the whole
file before anything runs; when stdin is a pipe (`curl | bash`) it reattaches file before anything runs; when stdin is a pipe (`curl | bash`) it reattaches
the terminal for the menu (set `WIZARD_KEEP_STDIN=1` to keep piped input). the terminal for the menu (set `WIZARD_KEEP_STDIN=1` to keep piped input).
+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")"
+10 -3
View File
@@ -9,7 +9,7 @@ COMPONENTS=(gaming theme glyphs single machine)
declare -A LABEL=( declare -A LABEL=(
[gaming]="SteamOS conversion: boot into gaming mode, Steam on the desktop" [gaming]="SteamOS conversion: boot into gaming mode, Steam on the desktop"
[theme]="Install SteamOS theme: Vapor look, dark mode, SteamOS taskbar" [theme]="Install SteamOS theme: Vapor look (cachyos-vapor)"
[glyphs]="Install Steam Deck/Machine icons: Deck button icons in gaming mode" [glyphs]="Install Steam Deck/Machine icons: Deck button icons in gaming mode"
[single]="Single user mode: no password, lock screen or log out (SDDM)" [single]="Single user mode: no password, lock screen or log out (SDDM)"
[machine]="Steam Machine support: LED bar driver, hardware settings in Steam" [machine]="Steam Machine support: LED bar driver, hardware settings in Steam"
@@ -56,12 +56,16 @@ show_menu() {
printf " %-3s %-6b %-6s %s\n" "$i" "$now " "$want" "${LABEL[$c]}" printf " %-3s %-6b %-6s %s\n" "$i" "$now " "$want" "${LABEL[$c]}"
done done
echo echo
echo -e "$KERNEL_OVERVIEW"
echo
} }
run_menu() { run_menu() {
# Sets REAPPLY. Returns 1 if the user quit. A checkbox list on a # Sets REAPPLY. Returns 1 if the user quit. A checkbox list on a
# terminal; a plain numbered prompt when input is piped (scripted runs). # terminal; a plain numbered prompt when input is piped (scripted runs).
REAPPLY=false REAPPLY=false
# Built once: the TUI redraws on every key press.
KERNEL_OVERVIEW="$(kernel_overview)"
if [[ -t 0 && -t 1 ]]; then if [[ -t 0 && -t 1 ]]; then
run_menu_tui run_menu_tui
else else
@@ -72,7 +76,7 @@ run_menu() {
draw_menu_tui() { draw_menu_tui() {
local cursor="$1" i=0 c box state line local cursor="$1" i=0 c box state line
printf '\033[H\033[2J' printf '\033[H\033[2J'
echo -e "${c_bold}CachyOS Steam Deck-style Gamescope Boot Wizard${c_reset}" echo -e "${c_bold}CachyOS Steam Deck-style Gamescope Boot Wizard${c_reset} v$VERSION"
echo "Pick what you want. Anything you untick is put back the way it was." echo "Pick what you want. Anything you untick is put back the way it was."
echo echo
MENU_ITEMS=() MENU_ITEMS=()
@@ -83,13 +87,16 @@ draw_menu_tui() {
state="off"; [[ "${CURRENT[$c]}" == 1 ]] && state="${c_green}on${c_reset}" state="off"; [[ "${CURRENT[$c]}" == 1 ]] && state="${c_green}on${c_reset}"
line="$box ${LABEL[$c]}" line="$box ${LABEL[$c]}"
if (( i == cursor )); then if (( i == cursor )); then
echo -e " ${c_cyan}>${c_reset} ${c_bold}${line}${c_reset} (now: ${state})" # The green x's reset would end the bold too: re-enable it after.
echo -e " ${c_cyan}>${c_reset} ${c_bold}${line//"$c_reset"/"$c_reset$c_bold"}${c_reset} (now: ${state})"
else else
echo -e " ${line} (now: ${state})" echo -e " ${line} (now: ${state})"
fi fi
i=$((i + 1)) i=$((i + 1))
done done
echo echo
echo -e "$KERNEL_OVERVIEW"
echo
echo -e " ${c_bold}Up/Down${c_reset} move ${c_bold}Space${c_reset} select ${c_bold}Enter${c_reset} run ${c_bold}a${c_reset} run + re-apply what's on ${c_bold}q${c_reset} quit" echo -e " ${c_bold}Up/Down${c_reset} move ${c_bold}Space${c_reset} select ${c_bold}Enter${c_reset} run ${c_bold}a${c_reset} run + re-apply what's on ${c_bold}q${c_reset} quit"
} }
+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."
+122 -15
View File
@@ -51,6 +51,14 @@ install_valve_led_driver() {
# silently builds nothing, so modprobe later finds no module. # silently builds nothing, so modprobe later finds no module.
install_kernel_headers || return 1 install_kernel_headers || return 1
# The upstream Makefile builds against `uname -r` instead of the kernel
# DKMS targets, so every other installed kernel (e.g. linux-cachyos-lts)
# got the running kernel's tree and failed (wrong kernel, and gcc against
# a clang-built tree). DKMS reads this override after the package's
# dkms.conf; written before the install so its own build works too.
printf '%s\n' "# Written by cachyos-gamescope-boot: build for DKMS's target kernel." \
'MAKE[0]="make KVERSION=${kernelver}"' | sudo tee "$LED_DKMS_OVERRIDE" >/dev/null
if ! pacman -Qi leds-valve-dkms-git >/dev/null 2>&1; then if ! pacman -Qi leds-valve-dkms-git >/dev/null 2>&1; then
info "Installing leds-valve-dkms-git from the AUR via $aur_helper (non-interactive)..." info "Installing leds-valve-dkms-git from the AUR via $aur_helper (non-interactive)..."
if ! "$aur_helper" -S "${flags[@]}" leds-valve-dkms-git; then if ! "$aur_helper" -S "${flags[@]}" leds-valve-dkms-git; then
@@ -61,19 +69,20 @@ install_valve_led_driver() {
ok "leds-valve-dkms-git already installed." ok "leds-valve-dkms-git already installed."
fi fi
# Build for the running kernel explicitly. The upstream Makefile uses # Build for every installed kernel that has headers, so booting another
# `uname -r` rather than DKMS's target kernel, so building for the # one (e.g. the LTS kernel) still has the driver.
# running kernel is the one case that reliably works. local kdir kver
local kver for kdir in /usr/lib/modules/*/build; do
kver="$(uname -r)" [[ -d "$kdir" ]] || continue
if ! dkms status -k "$kver" leds-valve-dkms 2>/dev/null | grep -q installed; then kver="$(basename "$(dirname "$kdir")")"
info "Building leds-valve for running kernel $kver..." dkms status -k "$kver" leds-valve-dkms 2>/dev/null | grep -q installed && continue
info "Building leds-valve for kernel $kver..."
if ! sudo dkms install leds-valve-dkms/0.1 -k "$kver"; then if ! sudo dkms install leds-valve-dkms/0.1 -k "$kver"; then
err "DKMS build failed. See the build log:" err "DKMS build for $kver failed. See the build log:"
err " /var/lib/dkms/leds-valve-dkms/0.1/build/make.log" err " /var/lib/dkms/leds-valve-dkms/0.1/build/make.log"
return 1 return 1
fi fi
fi done
# Load now, and on every boot. # Load now, and on every boot.
echo leds-valve | sudo tee /etc/modules-load.d/leds-valve.conf >/dev/null echo leds-valve | sudo tee /etc/modules-load.d/leds-valve.conf >/dev/null
@@ -96,6 +105,87 @@ install_valve_led_driver() {
} }
LED_UDEV_RULE="/etc/udev/rules.d/70-valve-leds-user.rules" LED_UDEV_RULE="/etc/udev/rules.d/70-valve-leds-user.rules"
LED_DKMS_OVERRIDE="/etc/dkms/leds-valve-dkms.conf"
HEADERS_SCRIPT="/usr/local/lib/cachyos-gamescope-boot/ensure-kernel-headers"
HEADERS_UNIT="/etc/systemd/system/ensure-kernel-headers.service"
install_headers_boot_check() {
# DKMS's pacman hook rebuilds leds-valve for every kernel whose headers
# get installed, but a newly added kernel (e.g. linux-cachyos-bore)
# comes without them, and a pacman hook can't install packages itself.
# So check at every boot and install missing headers, which triggers
# that hook and builds the driver for the new kernel.
sudo mkdir -p "$(dirname "$HEADERS_SCRIPT")"
sudo tee "$HEADERS_SCRIPT" > /dev/null << 'EOF'
#!/bin/bash
# Installed by cachyos-gamescope-boot: install missing -headers for every
# installed kernel, so DKMS builds leds-valve for it.
set -u
missing=()
for k in $(pacman -Qqo /usr/lib/modules/*/pkgbase 2>/dev/null | sort -u); do
pacman -Q "${k}-headers" >/dev/null 2>&1 && continue
pacman -Si "${k}-headers" >/dev/null 2>&1 && missing+=("${k}-headers")
done
[[ ${#missing[@]} -eq 0 ]] && exit 0
# Another pacman is running (e.g. an update): try again next boot.
[[ -e /var/lib/pacman/db.lck ]] && { echo "pacman is busy, skipping"; exit 0; }
echo "Installing missing kernel headers: ${missing[*]}"
exec pacman -S --needed --noconfirm "${missing[@]}"
EOF
sudo chmod 755 "$HEADERS_SCRIPT"
sudo tee "$HEADERS_UNIT" > /dev/null << EOF
[Unit]
Description=Install missing kernel headers so DKMS builds leds-valve for every kernel
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=$HEADERS_SCRIPT
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable ensure-kernel-headers.service
}
reload_powerdevil() {
qdbus6 org.kde.Solid.PowerManagement /org/kde/Solid/PowerManagement \
org.kde.Solid.PowerManagement.refreshStatus >/dev/null 2>&1 || true
}
kernel_overview() {
# Per installed kernel: headers (needed to build DKMS modules), the
# in-kernel Steam controller driver, and, on a Steam Machine, whether the
# LED driver is built for it. Printed in the menu so it's easy to verify
# a kernel update or a newly added kernel got everything.
local mark="${c_green}yes${c_reset}" miss="${c_red}no ${c_reset}" leds=false
detect_valve_fremont && command -v dkms >/dev/null 2>&1 && leds=true
local kdir k pkg headers hid led running line
echo -e " ${c_bold}Kernels${c_reset} (> = running; controller = Steam controller driver, LEDs = LED bar driver built)"
for kdir in /usr/lib/modules/*/; do
k="$(basename "$kdir")"
[[ -f "$kdir/pkgbase" ]] || continue
pkg="$(< "$kdir/pkgbase")"
headers="$miss"; [[ -d "$kdir/build" ]] && headers="$mark"
hid="$miss"; compgen -G "$kdir/kernel/drivers/hid/hid-steam.ko*" >/dev/null && hid="$mark"
running=" "; [[ "$k" == "$(uname -r)" ]] && running="${c_cyan}>${c_reset} "
line="$(printf '%-23s %-18s headers %b controller %b' "$k" "$pkg" "$headers" "$hid")"
if [[ "$leds" == true ]]; then
led="$miss"; dkms status -k "$k" leds-valve-dkms 2>/dev/null | grep -q installed && led="$mark"
line+="$(printf ' LEDs %b' "$led")"
fi
echo -e " ${running}${line}"
done
if [[ "$leds" == true ]]; then
local loaded="$miss" nodes
lsmod | grep -q '^leds_valve' && loaded="$mark"
nodes="$(compgen -G '/sys/class/leds/valve-leds*' | wc -l)"
echo
echo -e " LED driver loaded: ${loaded} LED nodes: ${nodes} steamos-manager: $(systemctl is-active steamos-manager 2>/dev/null)"
fi
}
machine_available() { detect_valve_fremont; } machine_available() { detect_valve_fremont; }
@@ -106,6 +196,7 @@ machine_status() {
machine_enable() { machine_enable() {
ensure_aur_helper || { warn "Couldn't set up an AUR helper automatically. Install yay or paru, then run the wizard again."; return 1; } ensure_aur_helper || { warn "Couldn't set up an AUR helper automatically. Install yay or paru, then run the wizard again."; return 1; }
install_valve_led_driver || { warn "LED driver setup ran into a problem - see errors above."; return 1; } install_valve_led_driver || { warn "LED driver setup ran into a problem - see errors above."; return 1; }
install_headers_boot_check
# The LED files are root-only. Steam runs as the user; let it write them # The LED files are root-only. Steam runs as the user; let it write them
# in case it drives the bar directly (Valve's own privileged-write helper # in case it drives the bar directly (Valve's own privileged-write helper
@@ -118,13 +209,22 @@ EOF
sudo udevadm control --reload sudo udevadm control --reload
sudo udevadm trigger --subsystem-match=leds --action=add sudo udevadm trigger --subsystem-match=leds --action=add
# steamos-manager is what Steam in gaming mode talks to for hardware # steamos-manager and inputplumber are what Steam in gaming mode talks to
# settings (fan, HDMI-CEC TV control, performance); it knows the Steam # for hardware and controller settings; it knows the Steam Machine from its DMI data.
# Machine from its DMI data. info "Installing hardware manager packages (steamos-manager & inputplumber)..."
info "Installing steamos-manager (Steam Machine hardware settings in Steam)..." sudo pacman -S --needed --noconfirm steamos-manager inputplumber || { err "Installing hardware manager packages failed."; return 1; }
sudo pacman -S --needed --noconfirm steamos-manager || { err "Installing steamos-manager failed."; return 1; } sudo systemctl enable --now inputplumber.service
sudo systemctl enable --now steamos-manager.service sudo systemctl enable --now steamos-manager.service
systemctl --user enable steamos-manager.service 2>/dev/null systemctl --user enable steamos-manager.service 2>/dev/null
# Console-like power handling, as SteamOS's powerdevilrc (mains-power
# part; there is no battery): the power button sleeps instead of showing
# the logout screen, and the machine never suspends on its own (e.g.
# during a long download). The launcher's Shut Down still shuts down.
kset machine powerdevilrc "AC|SuspendAndShutdown" PowerButtonAction 1
kset machine powerdevilrc "AC|SuspendAndShutdown" AutoSuspendAction 0
kset machine powerdevilrc "AC|Display" LockBeforeTurnOffDisplay false
reload_powerdevil
ok "Steam Machine support on." ok "Steam Machine support on."
} }
@@ -132,10 +232,17 @@ machine_disable() {
info "Removing Steam Machine support..." info "Removing Steam Machine support..."
systemctl --user disable --now steamos-manager.service 2>/dev/null systemctl --user disable --now steamos-manager.service 2>/dev/null
sudo systemctl disable --now steamos-manager.service 2>/dev/null sudo systemctl disable --now steamos-manager.service 2>/dev/null
sudo pacman -Rns --noconfirm steamos-manager 2>/dev/null sudo systemctl disable --now inputplumber.service 2>/dev/null
sudo pacman -Rns --noconfirm steamos-manager inputplumber 2>/dev/null
sudo rm -f "$LED_UDEV_RULE" /etc/modules-load.d/leds-valve.conf sudo rm -f "$LED_UDEV_RULE" /etc/modules-load.d/leds-valve.conf
sudo udevadm control --reload sudo udevadm control --reload
sudo modprobe -r leds-valve 2>/dev/null sudo modprobe -r leds-valve 2>/dev/null
sudo pacman -Rns --noconfirm leds-valve-dkms-git 2>/dev/null sudo pacman -Rns --noconfirm leds-valve-dkms-git 2>/dev/null
krevert machine
reload_powerdevil
sudo systemctl disable ensure-kernel-headers.service 2>/dev/null
sudo rm -f "$LED_DKMS_OVERRIDE" "$HEADERS_UNIT" "$HEADERS_SCRIPT"
sudo rmdir "$(dirname "$HEADERS_SCRIPT")" 2>/dev/null
sudo systemctl daemon-reload
ok "Steam Machine support removed (the AUR helper, if installed, is kept)." ok "Steam Machine support removed (the AUR helper, if installed, is kept)."
} }
+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 rule="$STEAM_KEYBOARD_RULE"
rules="$(kreadconfig6 --file kwinrulesrc --group General --key rules)"
if [[ ",$rules," != *",$rule,"* ]]; then
kset theme kwinrulesrc "$rule" Description "Window settings for Steam Keyboard"
kset theme kwinrulesrc "$rule" above true
kset theme kwinrulesrc "$rule" aboverule 2
kset theme kwinrulesrc "$rule" skiptaskbar true
kset theme kwinrulesrc "$rule" skiptaskbarrule 2
kset theme kwinrulesrc "$rule" title "Steam Keyboard"
kset theme kwinrulesrc "$rule" titlematch 2
kset theme kwinrulesrc "$rule" type 16
kset theme kwinrulesrc "$rule" typerule 2
kset theme kwinrulesrc "$rule" wmclass steam
kset theme kwinrulesrc "$rule" wmclasscomplete true
kset theme kwinrulesrc "$rule" wmclassmatch 2
kset theme kwinrulesrc General rules "${rules:+$rules,}$rule"
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
}
+107 -241
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 current_colorscheme() {
local groups="" # CachyOS ships its dark Breeze colors inline in kdeglobals without a
local skip=0 # ColorScheme name, so fall back to the scheme matching ColorSchemeHash.
while IFS= read -r line || [[ -n "$line" ]]; do local name hash f
line="${line%$'\r'}" name="$(kreadconfig6 --file kdeglobals --group General --key ColorScheme)"
[[ -z "$line" || "$line" == \#* ]] && continue if [[ -z "$name" ]]; then
if [[ "$line" == \[* ]]; then hash="$(kreadconfig6 --file kdeglobals --group General --key ColorSchemeHash)"
skip=0; groups="" for f in ~/.local/share/color-schemes/*.colors /usr/share/color-schemes/*.colors; do
[[ "$line" == *'[$'* ]] && { skip=1; continue; } [[ -f "$f" && -n "$hash" ]] || continue
local rest="$line" [[ "$(sha1sum < "$f")" == "$hash "* ]] && { name="$(basename "$f" .colors)"; break; }
while [[ "$rest" =~ ^\[([^]]*)\](.*)$ ]]; do
groups+="${groups:+|}${BASH_REMATCH[1]}"
rest="${BASH_REMATCH[2]}"
done done
continue
fi fi
(( skip )) && continue echo "${name:-BreezeLight}"
[[ "$line" == *=* ]] || continue
key="${line%%=*}"; value="${line#*=}"
kset theme "$target" "$groups" "$key" "$value"
done < "$src"
} }
install_vapor_theme() { journal_vapor_defaults() {
# Installs Valve's official SteamOS "Vapor" Plasma theme (color scheme, # Write every setting from Vapor's defaults file ("[file][group]" +
# Plasma look-and-feel package, wallpapers, icons) straight from Valve's # key=value) through the undo journal, so disable restores the user's
# own SteamOS package mirror, into the current user's ~/.local/share. # icons, cursor, splash, window decoration etc. The color scheme is
# This only touches the invoking user's home directory, never system # left to plasma-apply-colorscheme.
# files, so it's independent from everything else this script does. local line file groups key rest
local mirror="https://steamdeck-packages.steamos.cloud/archlinux-mirror" while IFS= read -r line || [[ -n "$line" ]]; do
local repo file_name sha256 tmp_dir if [[ "$line" =~ ^\[([^]]+)\](.*)$ ]]; then
tmp_dir="$(mktemp -d)" file="${BASH_REMATCH[1]}"; rest="${BASH_REMATCH[2]}"; groups=""
while [[ "$rest" =~ ^\[([^]]*)\](.*)$ ]]; do
# Take the package from the newest SteamOS release repo (jupiter-3.9, groups+="${groups:+|}${BASH_REMATCH[1]}"; rest="${BASH_REMATCH[2]}"
# 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 done
[[ -f "${tmp_dir}/etc/xdg/kded5rc" ]] && merge_kde_config "${tmp_dir}/etc/xdg/kded5rc" kded6rc elif [[ "$line" == *=* && -n "$groups" ]]; then
kset theme konsolerc "Desktop Entry" DefaultProfile Vapor.profile key="${line%%=*}"
mkdir -p ~/.config/gtk-3.0 ~/.config/gtk-4.0 [[ "$key" == ColorScheme ]] && continue
kset theme ~/.config/gtk-3.0/settings.ini Settings gtk-theme-name Vapor kset theme "$file" "$groups" "$key" "${line#*=}"
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 fi
[[ -f "${tmp_dir}/etc/xdg/gtk-2.0/gtkrc" ]] && cp "${tmp_dir}/etc/xdg/gtk-2.0/gtkrc" ~/.gtkrc-2.0 done < "$VAPOR_DEFAULTS"
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
fi
# 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."
} }
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.
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 stop_plasmashell_for_edit
install_vapor_theme single_launcher
local rc=$?
restart_plasmashell_if_stopped restart_plasmashell_if_stopped
(( rc == 0 )) || warn "Vapor theme install ran into a problem - see errors above." fi
return $rc 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."
} }
+5 -2
View File
@@ -14,16 +14,19 @@
set -uo pipefail set -uo pipefail
# Release version, see CHANGELOG.md.
VERSION=0.7.0
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
require_root_helper require_root_helper
echo -e "${c_bold}CachyOS Steam Deck-style Gamescope Boot Wizard${c_reset}" echo -e "${c_bold}CachyOS Steam Deck-style Gamescope Boot Wizard${c_reset} v$VERSION"
echo "Turn the SteamOS-style parts on or off. The menu shows what is on now;" echo "Turn the SteamOS-style parts on or off. The menu shows what is on now;"
echo "anything you turn off is put back the way it was." echo "anything you turn off is put back the way it was."