Merge pull request #3 from theupriser/fix/review-cleanup

Fix/review cleanup
This commit is contained in:
theupriser authored and GitHub committed 2026-09-23 15:27:58 +02:00
commit e741246098
13 files changed
+833 -567

No files matched your search

+33 -28
View File
@@ -13,11 +13,24 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
## Layout
- `setup-gamescope-boot.sh` - the only entry point. Pre-flight checks,
sources `lib/*.sh`, then calls the steps in order. No step logic here.
sources `lib/*.sh`, runs the menu and applies the plan. No component
logic here.
- `lib/*.sh` - one file per responsibility, each defining functions only
(no top-level side effects). See the table in `README.md`. New
functionality goes in the module it belongs to, or a new module that is
added to the `source` loop in `setup-gamescope-boot.sh`.
(no top-level side effects besides constants). See the table in
`README.md`.
- **Components.** Every menu item `<id>` (listed in `COMPONENTS` and `LABEL`
in `lib/menu.sh`) provides `<id>_status` (return 0 if on, detected from
the system, no state file needed), `<id>_enable` and `<id>_disable`, all
idempotent. `<id>_enable` is also used to re-apply. Optional
`<id>_available` is checked via `component_available` (e.g. `machine`
only on Fremont). Turn-on order is `COMPONENTS` order, turn-off reverse;
`gaming` must stay first. Dependencies live in `toggle_component`.
- **Reversibility.** Every per-user KDE setting a component changes goes
through `kset <component> <file> <group|group> <key> <value>`
(`lib/state.sh`), which records the old value once; `<id>_disable` calls
`krevert <component>`. Never call `kwriteconfig6` directly for settings a
component owns. System files are backed up with `backup_file` and restored
on disable.
## Conventions
@@ -41,12 +54,11 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
## Non-obvious behaviour to preserve
- One wizard question in `choose_setup_mode` sets `$SINGLE_USER` and
`$LOGIN_MANAGER`. "Single user, no password" = SteamOS: SDDM plus no lock
screen, user switching or log out (`setup_single_user`; the launcher's
Session dropdown is hidden via kickoff `primaryActions=3` because
restricting `action/logout` also hides Restart/Shut Down). Otherwise the
current login manager stays. Two login-manager paths:
- `apply_changes` sets `$LOGIN_MANAGER` from the menu: `sddm` when single
user mode is wanted, else `plasmalogin`. Toggling single user re-applies
`gaming` so it moves to the other login manager. Single user mode hides
the launcher's Session dropdown via kickoff `primaryActions=3` (restricting
`action/logout` also hides Restart/Shut Down). Two login-manager paths:
**sddm** (like SteamOS: `steam-set-session` writes
`/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM honours; we add
`User=`/`Relogin=` in `10-gamescope-autologin.conf`, and `/etc/sddm.conf`
@@ -75,6 +87,9 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
launches).
- Live Plasma changes (`qdbus6 ... evaluateScript`, `lookandfeeltool`) only
run when `plasmashell` is running; config-file fallbacks cover the rest.
- plasmashell writes its in-memory config back on exit: edit panel/applet/
wallpaper files only between `stop_plasmashell_for_edit` and
`restart_plasmashell_if_stopped` (`lib/common.sh`).
- LED driver: `leds-valve-dkms-git`'s Makefile builds against `uname -r`,
so the script builds explicitly for the running kernel and installs
headers for every installed kernel first. The module creates
@@ -91,21 +106,11 @@ for f in setup-gamescope-boot.sh lib/*.sh; do bash -n "$f"; done
shellcheck -S warning setup-gamescope-boot.sh lib/*.sh # if available
```
Behaviour is best verified in a CachyOS VM (QEMU/KVM, KDE Plasma install,
`plasma-login-manager`) with SSH access, reset from a disk snapshot between
runs. Notes from doing this:
- Run the script non-interactively by piping answers, e.g.
`printf "\ny\nn\nn\n" | ./setup-gamescope-boot.sh` (user, single user,
theme, reboot).
The prompt order depends on what's already installed.
- Over SSH, export the session environment before running it so the live
Plasma steps work:
`XDG_RUNTIME_DIR=/run/user/$UID WAYLAND_DISPLAY=wayland-0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/$UID/bus`.
- `spectacle -b -n -f -o shot.png` takes a screenshot to check the look.
Apps you launch over SSH lack the session's Qt platform theme and look
light; launch them with `systemd-run --user` to judge colors correctly.
- Gamescope usually won't render in a VM (no suitable Vulkan), so test the
session logic with `plasma.desktop` as the autologin session. The
gamescope boot itself and the LED driver can only be verified on real
hardware.
Behaviour is verified in a CachyOS QEMU/KVM test VM. The VM scripts and a
Claude Code skill describing the whole test workflow (snapshots, SSH, running
the wizard with scripted menu input such as `printf '2\n\ny\nn\n'`, the
per-component checks; when stdin is not a terminal the menu falls back to a
numbered prompt, which is what scripted runs use, reboot checks, the full test matrix, `--fremont` to
fake Steam Machine hardware) live in
[cachyos-gamescope-boot-dev-env](https://github.com/theupriser/cachyos-gamescope-boot-dev-env).
Gamescope itself and the real LED bar can only be verified on hardware.
+136 -121
View File
@@ -11,16 +11,22 @@ script fixes that and sets everything up for you.
## What you get
- **Boots into gaming mode** automatically - you never see a login screen,
just like SteamOS.
- **Switch to Desktop** from Steam's power menu works, and so does going
back: use the **Return to Gaming Mode** icon on the desktop, or just log
out.
- **Back to gaming mode after a restart**, like SteamOS.
- **Steam's on-screen keyboard** (Steam + X) also works on the desktop.
- *Optional:* the **SteamOS desktop look** - Valve's own Vapor theme,
wallpaper, dark mode and taskbar.
- *Optional, Steam Machine only:* a driver for the **front LED bar**.
The wizard is a menu: pick what you want, and it turns each part on or off.
Everything you turn off is put back the way it was.
1. **SteamOS conversion** - boots straight into gaming mode, **Switch to
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,
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,
dark mode and the SteamOS taskbar.
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
user switching or logging out. Typing a password with a controller is no
fun. (Needs 1.)
5. **Steam Machine support** - only shown on a Valve Steam Machine: the
driver for the front LED bar, and the hardware settings in Steam (fan,
TV control over HDMI-CEC).
## Requirements
@@ -37,31 +43,34 @@ cd <this-repo>
./setup-gamescope-boot.sh
```
Run it as yourself, not as root. It asks for your password once, then asks a
few yes/no questions:
Run it as yourself, not as root. You'll see a checklist:
- **Single user, no password, like SteamOS?** Recommended for a console.
You never see a login or lock screen, and there's no user switching or
logging out - typing a password with a controller is no fun. This
switches to SDDM, the login manager SteamOS uses. Say no to keep
CachyOS's default login manager and KDE's normal lock screen; gaming mode
still starts automatically.
- whether to install missing packages;
- the LED driver (Steam Machine only) and the SteamOS look.
```
[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 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)
At the end it offers to restart. The switch to SDDM takes effect from that
restart.
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
**Enter** to run. "now:" shows what's on at the moment. The wizard then
shows what it will change, asks your password once, and at the end offers
to restart (needed for changes to how the PC starts).
Run it again whenever you like - to change your choices, to turn things off
again, or after a CachyOS update (press `a` in the menu to re-apply
everything that's on).
Keep the whole folder: the script needs the files in `lib/` next to it.
It's safe to run again later, for example after a CachyOS update.
## Using it
- **To the desktop:** in gaming mode, open the Steam menu and choose
**Power > Switch to Desktop**.
- **Back to gaming mode:** double-click **Return to Gaming Mode** on the
desktop (or log out, if you didn't choose single user).
desktop (or log out, if you're not using single user mode).
- After a restart you always start in gaming mode.
Prefer to decide yourself where your PC starts? Run one of these in Konsole:
@@ -86,42 +95,53 @@ That takes you back to the desktop.
freshly installed driver often needs a reboot. Still dark? See
[Front LED bar](#front-led-bar-steam-machine) under technical details.
**Undo the SteamOS look:** pick another theme under **System Settings >
Colors & Themes > Global Theme**.
To remove everything the script set up, see
[Removing everything](#removing-everything).
**Undo something:** run the wizard again and untick it.
---
## Technical details
### Single user: SDDM, no locking
### How turning things on and off works
The wizard's first question. Answering yes switches to **SDDM** and turns
off everything that asks for a password or another user, per user and
without touching system files: `action/lock_screen`, `switch_user` and
At startup every component checks whether it is on (`*_status` in `lib/`).
You choose; the wizard then turns off what you unticked (in reverse order)
and turns on what you ticked. To be able to undo:
- **System files** are backed up once, next to the original, with a
`.bak-gamescope-wizard` suffix, and restored when you turn the component
off.
- **KDE settings** in your home directory are recorded with their previous
value the first time the wizard changes them, in an undo journal under
`~/.local/state/cachyos-gamescope-boot/`. Turning the component off writes
the old values back (or removes keys that didn't exist before). Setups
made by older versions of the script, without a journal, fall back to
KDE's defaults.
- **Packages** installed for the conversion (Steam, gamescope-session, ...)
are kept when you turn it off; Steam Machine support removes its own.
### Single user mode: SDDM, no locking
Turning it on switches to **SDDM** and turns off everything that asks for a
password or another user, per user: `action/lock_screen`, `switch_user` and
`start_new_session` restrictions in `kdeglobals`, no automatic locking
(`kscreenlockerrc`), Meta+L and Ctrl+Alt+Del unbound, and the launcher shows
only Sleep / Restart / Shut Down (kickoff `primaryActions=3`), which hides
the Session dropdown with Log Out. (Restricting `action/logout` would also
hide Restart and Shut Down.) Answering no restores KDE's defaults and keeps
the current login manager.
hide Restart and Shut Down.) Turning it off restores all of that and moves
the conversion back to plasma-login-manager.
**SDDM** is what SteamOS uses, and CachyOS's
`steam-set-session` supports it directly: it writes
`/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM honours. The script
installs and enables `sddm` (disabling the current display manager, active
from the next boot), writes `User=`, `Session=` and `Relogin=true` to
**SDDM** is what SteamOS uses, and CachyOS's `steam-set-session` supports it
directly: it writes `/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM
honours. The script installs and enables `sddm` (active from the next boot),
writes `User=`, `Session=` and `Relogin=true` to
`/etc/sddm.conf.d/10-gamescope-autologin.conf`, and removes any
`[Autologin]` from `/etc/sddm.conf` (read last, so it would override both).
No sync bridge or sudoers rule is needed; the shortcut just runs
`steamos-session-select gamescope`, which logs out, and `Relogin=true`
logs straight back in to gamescope. Switching an existing
plasma-login-manager setup to SDDM removes the sync bridge.
`steamos-session-select gamescope`, which logs out, and `Relogin=true` logs
straight back in to gamescope.
Keeping **plasma-login-manager** (CachyOS's default since March 2026) needs
the workarounds below.
Without single user mode, the conversion uses **plasma-login-manager**
(CachyOS's default since March 2026), which needs the workarounds below.
### Why this is needed (plasma-login-manager)
@@ -152,34 +172,35 @@ The script sets `Session=`, `User=` and `Relogin=true` in the base config,
and installs a small systemd path watcher that copies whatever CachyOS's
tools write to the conf.d fragment into the base config.
### What the script changes
### What each component changes
In order:
**SteamOS conversion** (`lib/login-manager.sh`, `lib/steam-desktop.sh`,
`lib/desktop-shortcut.sh`):
1. Checks that it runs as the user that should autologin, and asks whether
to switch to SDDM (see above).
2. Installs missing packages: `gamescope-session-cachyos`, `steam`,
`mangohud`, `xterm`, `ttf-liberation`, `wqy-zenhei`, `plasma-keyboard`.
3. *SDDM:* installs/enables SDDM and writes its autologin config.
*plasma-login-manager:* creates `/etc/plasmalogin.conf.d`, backs up and rewrites the
`[Autologin]` section of `/etc/plasmalogin.conf`, and removes stray
`zzz-steamos-autologin*.conf` files from manual troubleshooting (never
`zz-steamos-autologin.conf`, which CachyOS's tools own).
4. *plasma-login-manager only:* installs `/usr/local/bin/sync-steamos-session.sh` plus
`sync-steamos-session.path`/`.service`, which keep the base config in sync
with session switches.
5. Sets up Steam for the desktop: `STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"`
(gamepad UI with Steam Deck glyphs), `KWIN_IM_SHOW_ALWAYS=1` for the
virtual keyboard, and a `steam-desktop-autostart` systemd user service
that starts Steam silently in Plasma only.
6. *(Steam Machine, optional)* the LED driver - see below.
7. *(Optional)* the SteamOS desktop look - see below.
8. Creates the **Return to Gaming Mode** shortcut. On plasma-login-manager it
also adds a narrow sudoers rule (`/etc/sudoers.d/gamescope-session-switch`)
so it can restart the login manager without a password prompt.
- installs missing packages: `gamescope-session-cachyos`, `steam`,
`mangohud`, `xterm`, `ttf-liberation`, `wqy-zenhei`, `plasma-keyboard`;
- *SDDM (single user mode):* installs/enables SDDM and writes its autologin
config;
- *plasma-login-manager:* creates `/etc/plasmalogin.conf.d`, backs up and
rewrites the `[Autologin]` section of `/etc/plasmalogin.conf`, removes
stray `zzz-steamos-autologin*.conf` files from manual troubleshooting
(never `zz-steamos-autologin.conf`, which CachyOS's tools own), and
installs `/usr/local/bin/sync-steamos-session.sh` plus
`sync-steamos-session.path`/`.service`;
- `KWIN_IM_SHOW_ALWAYS=1` for the virtual keyboard and a
`steam-desktop-autostart` systemd user service that starts Steam silently
in Plasma only;
- the **Return to Gaming Mode** shortcut; on plasma-login-manager with a
narrow sudoers rule (`/etc/sudoers.d/gamescope-session-switch`) so it can
restart the login manager without a password prompt.
Re-running doesn't duplicate any settings. Every system file it modifies is
backed up once, next to the original, with a `.bak-gamescope-wizard` suffix.
Turning it off restores `/etc/plasmalogin.conf` from its backup, removes the
SDDM autologin, sync bridge, shortcut, sudoers rule and Steam autostart, and
switches back to plasma-login-manager.
**Steam Deck/Machine icons:** `STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"`
in `~/.config/environment.d/` (and gamescope-session's own environment
file), which makes Steam show Steam Deck button glyphs in gaming mode.
### SteamOS desktop look
@@ -191,7 +212,7 @@ SteamOS mirror and installs it into `~/.local/share` - nothing system-wide:
- Valve's SteamOS desktop defaults, merged into your own config: Noto Sans
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
screen locking, no welcome screen, light file indexing;
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).
@@ -215,30 +236,47 @@ curl -fsL $m/$r/os/x86_64/$r.db | bsdtar -tf - | grep -o '^steamdeck-kde-presets
### Front LED bar (Steam Machine)
Standard desktop kernels, including CachyOS's, lack Valve's `leds-valve`
driver, so the Steam Machine's front LED bar goes dark or "breathes". On
Fremont hardware (DMI `Valve`/`Fremont`) the script offers to:
The **Steam Machine support** component, only shown on Fremont hardware
(DMI `Valve`/`Fremont`, or `OEM`/`F7F` on early units):
- install an AUR helper (`yay`) if neither `yay` nor `paru` is present;
- install the kernel headers for every installed kernel;
- install `leds-valve-dkms-git` from the AUR, build it for the running
kernel, and load it at every boot (`/etc/modules-load.d/leds-valve.conf`);
- optionally install the experimental `openrgb-git`, which can drive the bar.
- installs an AUR helper (`yay`) if neither `yay` nor `paru` is present;
- installs the kernel headers for every installed kernel;
- 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
boot (`/etc/modules-load.d/leds-valve.conf`);
- 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;
- installs and enables `steamos-manager`, the service Steam in gaming mode
uses for hardware settings (fan, HDMI-CEC, performance); it recognises the
Steam Machine from its DMI data.
The LEDs appear as `/sys/class/leds/valve-leds*`. Steam itself only drives
the bar (e.g. download progress) in real SteamOS Game Mode.
Turning it off removes all of that again (the AUR helper is kept).
The driver's Makefile builds against the running kernel, so after a kernel
update, boot the new kernel and re-run the script (or
`sudo dkms install leds-valve-dkms/0.1 -k "$(uname -r)"`).
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
kernel and re-apply (`a` in the menu) or run
`sudo dkms install leds-valve-dkms/0.1 -k "$(uname -r)"`.
Troubleshooting:
```bash
dkms status
ls /sys/class/leds | grep valve
ls -l /sys/class/leds/valve-leds*/
sudo dmesg | grep -i valve
cat /var/lib/dkms/leds-valve-dkms/0.1/build/make.log
journalctl --user -b | grep -i led
```
**BIOS updates** are not part of the wizard. Valve ships the Steam Machine
BIOS as `F7F0108.cab` in its `fremont-hw-support` package for fwupd. To
install it by hand (keep the machine on mains power and don't interrupt it):
```bash
sudo dmidecode -s bios-version # current version
sudo pacman -S fwupd
curl -LO https://steamdeck-packages.steamos.cloud/archlinux-mirror/holo-3.9/os/x86_64/fremont-hw-support-20260807.1-1-any.pkg.tar.zst
mkdir fhw && tar -I zstd -xf fremont-hw-support-*.pkg.tar.zst -C fhw
sudo fwupdmgr install fhw/usr/share/fwupd/remotes.d/fremont/firmware/F7F0108.cab
```
### Manual session control
@@ -255,48 +293,25 @@ immediately, which can turn into a loop - hence the Ctrl+Alt+F3 escape above.
### Removing everything
```bash
# SDDM: go back to plasma-login-manager
sudo rm /etc/sddm.conf.d/10-gamescope-autologin.conf
sudo systemctl disable sddm && sudo systemctl enable plasmalogin
# plasma-login-manager: restore the original login config
sudo cp /etc/plasmalogin.conf.bak-gamescope-wizard /etc/plasmalogin.conf
# session sync watcher
sudo systemctl disable --now sync-steamos-session.path
sudo rm /etc/systemd/system/sync-steamos-session.path
sudo rm /etc/systemd/system/sync-steamos-session.service
sudo rm /usr/local/bin/sync-steamos-session.sh
sudo systemctl daemon-reload
# shortcut and its sudoers rule
sudo rm /etc/sudoers.d/gamescope-session-switch
rm ~/Desktop/"Return to Gaming Mode.desktop"
# Steam desktop autostart and environment
systemctl --user disable --now steam-desktop-autostart.service
rm ~/.config/systemd/user/steam-desktop-autostart.service
rm ~/.config/environment.d/99-gamescope-steam-glyphs.conf \
~/.config/environment.d/99-kde-virtual-keyboard.conf
# LED driver (Steam Machine)
sudo rm /etc/modules-load.d/leds-valve.conf
sudo pacman -R leds-valve-dkms-git
```
Run the wizard and untick everything. Afterwards the PC boots to the normal
CachyOS login screen again; packages installed for the conversion (Steam,
gamescope-session, ...) stay installed.
### Project layout
| File | Responsibility |
|---|---|
| `setup-gamescope-boot.sh` | Entry point: user and sudo checks, step order, summary, reboot |
| `lib/common.sh` | Output helpers, yes/no prompts, backups |
| `setup-gamescope-boot.sh` | Entry point: checks, menu, apply, summary, restart |
| `lib/menu.sh` | The menu: detect, toggle, plan and apply changes |
| `lib/state.sh` | Undo journal for KDE settings (`kset`/`krevert`) |
| `lib/common.sh` | Output helpers, prompts, backups, plasmashell handling |
| `lib/packages.sh` | Required packages, AUR helper (yay/paru) |
| `lib/login-manager.sh` | SDDM or plasmalogin choice and autologin, session sync bridge |
| `lib/steam-desktop.sh` | Steam in the Plasma session: gamepad UI flags, virtual keyboard, autostart |
| `lib/led-driver.sh` | Fremont detection, kernel headers, LED driver, OpenRGB |
| `lib/vapor-theme.sh` | Vapor theme, Valve's SteamOS defaults, panel, dark mode |
| `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/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/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 |
Notes for contributors and AI coding agents are in [`AGENTS.md`](AGENTS.md).
+22
View File
@@ -45,3 +45,25 @@ backup_file() {
info "Backed up $f -> ${f}.bak-gamescope-wizard"
fi
}
# plasmashell keeps its config in memory and writes it back on exit, so
# edits to its files (panels, applets, wallpaper) must be made while it is
# stopped. It is restarted through systemd so it keeps the session's
# environment (platform theme etc.); a plain --replace from this shell
# may not, which gives a light-themed desktop.
stop_plasmashell_for_edit() {
PLASMASHELL_WAS_RUNNING=false
if pgrep -u "$USER" -x plasmashell >/dev/null; then
PLASMASHELL_WAS_RUNNING=true
systemctl --user stop plasma-plasmashell.service 2>/dev/null
pkill -u "$USER" -x plasmashell && sleep 2
fi
}
restart_plasmashell_if_stopped() {
if [[ "${PLASMASHELL_WAS_RUNNING:-false}" == true ]]; then
rm -rf ~/.cache/plasmashell* ~/.cache/org.kde.dirmodel-qml.kcache
systemctl --user start plasma-plasmashell.service 2>/dev/null ||
{ setsid plasmashell >/dev/null 2>&1 & }
fi
}
+7
View File
@@ -68,3 +68,10 @@ EOF
ok "Desktop shortcut created successfully."
}
remove_desktop_shortcut() {
local desktop_dir
desktop_dir="$(xdg-user-dir DESKTOP 2>/dev/null || echo "$HOME/Desktop")"
rm -f "$desktop_dir/Return to Gaming Mode.desktop"
sudo rm -f /etc/sudoers.d/gamescope-session-switch
}
+62 -35
View File
@@ -1,58 +1,86 @@
#!/bin/bash
# plasma-login-manager autologin into gamescope, and the session sync bridge.
# Booting into gaming mode: autologin into gamescope with SDDM or
# plasma-login-manager (plus the session sync bridge the latter needs).
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
BASE_CONF="/etc/plasmalogin.conf"
choose_setup_mode() {
# Step 1: one question decides both the login manager and locking.
# "Single user, no password" is SteamOS: SDDM (which CachyOS's session
# tools support directly, no workarounds) plus no lock screen, user
# switching or log out. Otherwise keep the current login manager
# (CachyOS's default plasma-login-manager gets the sync bridge below)
# and KDE's normal locking. Sets SINGLE_USER and LOGIN_MANAGER.
local current
current="$(systemctl show -p Id --value display-manager 2>/dev/null | sed 's/\.service$//')"
info "Detected display manager: ${current:-none}"
echo "SteamOS is a single-user console without passwords: no login screen, no"
echo "lock screen, no user switching or logging out - typing a password with a"
echo "controller is no fun. It uses the SDDM login manager for that."
if ask_yn "Single user, no password, like SteamOS? (switches to SDDM)" y; then
SINGLE_USER=true
LOGIN_MANAGER="sddm"
return
fi
SINGLE_USER=false
if [[ "$current" == "sddm" ]]; then
LOGIN_MANAGER="sddm"
return
fi
LOGIN_MANAGER="plasmalogin"
if [[ "$current" != "plasmalogin" ]]; then
warn "The workarounds are built for plasma-login-manager, but '${current:-unknown}' is active."
ask_yn "Continue anyway?" n || exit 0
fi
# The "SteamOS conversion" menu item: gaming mode boot, the Return to
# Gaming Mode shortcut and Steam on the desktop (lib/steam-desktop.sh).
gaming_status() {
# Autologin into gamescope is configured for this user.
case "$(current_display_manager)" in
sddm) [[ -f /etc/sddm.conf.d/10-gamescope-autologin.conf ]] ;;
plasmalogin)
sed -n '/^\[Autologin\]/,/^\[/p' "$BASE_CONF" 2>/dev/null | grep -qx "User=$USER" &&
[[ -f /etc/systemd/system/sync-steamos-session.path ]] ;;
*) return 1 ;;
esac
}
setup_login_manager() {
# Steps 3-8 for whichever login manager was chosen in step 1.
gaming_enable() {
# LOGIN_MANAGER (sddm with single user, else plasmalogin) is set by the
# menu. Re-running with the other value switches over cleanly.
install_required_packages || return 1
case "$LOGIN_MANAGER" in
sddm)
switch_to_sddm || exit 1
switch_to_sddm || return 1
configure_sddm_autologin
remove_session_sync
;;
plasmalogin)
remove_sddm_autologin
switch_to_plasmalogin || return 1
configure_autologin
install_session_sync
;;
esac
create_desktop_shortcut
steam_enable
}
gaming_disable() {
# Back to a normal desktop boot with CachyOS's default login manager.
# Packages (steam, gamescope-session-cachyos, ...) are kept.
info "Turning off booting into gaming mode..."
remove_sddm_autologin
remove_session_sync
restore_plasmalogin_config
switch_to_plasmalogin
remove_desktop_shortcut
steam_disable
ok "The PC boots to the normal login screen again (from the next boot)."
}
switch_to_plasmalogin() {
[[ "$(current_display_manager)" == plasmalogin ]] && return 0
info "Switching the login manager to plasma-login-manager..."
sudo pacman -S --needed --noconfirm plasma-login-manager || { err "Installing plasma-login-manager failed."; return 1; }
local current
current="$(systemctl show -p Id --value display-manager 2>/dev/null)"
[[ -n "$current" && "$current" != plasmalogin.service ]] && sudo systemctl disable "$current"
sudo systemctl enable -f plasmalogin.service || { err "Enabling plasmalogin failed."; return 1; }
ok "plasma-login-manager is the login manager from the next boot on."
}
remove_sddm_autologin() {
sudo rm -f /etc/sddm.conf.d/10-gamescope-autologin.conf
}
restore_plasmalogin_config() {
# Put back the original /etc/plasmalogin.conf from the first run's
# backup, or at least drop our [Autologin] section.
if [[ -f "${BASE_CONF}.bak-gamescope-wizard" ]]; then
sudo cp -a "${BASE_CONF}.bak-gamescope-wizard" "$BASE_CONF"
elif [[ -f "$BASE_CONF" ]]; then
sudo awk '/^\[Autologin\]/ { skip=1; next } /^\[/ { skip=0 } !skip { print }' "$BASE_CONF" |
sudo tee "${BASE_CONF}.tmp" > /dev/null && sudo mv "${BASE_CONF}.tmp" "$BASE_CONF"
fi
}
switch_to_sddm() {
# Takes effect at the next boot; the running session is left alone.
[[ "$(current_display_manager)" == sddm ]] && return 0
info "Installing and enabling SDDM..."
sudo pacman -S --needed --noconfirm sddm || { err "Installing sddm failed."; return 1; }
local current
@@ -62,7 +90,6 @@ switch_to_sddm() {
fi
sudo systemctl enable -f sddm.service || { err "Enabling sddm failed."; return 1; }
ok "SDDM is the login manager from the next boot on."
echo
}
configure_sddm_autologin() {
+177
View File
@@ -0,0 +1,177 @@
#!/bin/bash
# Interactive menu: detects which components are on, lets the user pick what
# they want, then turns components on or off to match.
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
# Menu order. Components are turned on in this order and off in reverse;
# gaming must come first (single user builds on it).
COMPONENTS=(gaming theme glyphs single machine)
declare -A LABEL=(
[gaming]="SteamOS conversion: boot into gaming mode, Steam on the desktop"
[theme]="Install SteamOS theme: Vapor look, dark mode, SteamOS taskbar"
[glyphs]="Install Steam Deck/Machine icons: Deck button icons in gaming mode"
[single]="Single user mode: no password, lock screen or log out (SDDM)"
[machine]="Steam Machine support: LED bar driver, hardware settings in Steam"
)
declare -A CURRENT WANTED
component_available() {
[[ "$1" != machine ]] || machine_available
}
detect_components() {
local c any=false
for c in "${COMPONENTS[@]}"; do
component_available "$c" || continue
if "${c}_status"; then CURRENT[$c]=1; any=true; else CURRENT[$c]=0; fi
WANTED[$c]=${CURRENT[$c]}
done
# First run: preselect the full SteamOS experience.
if [[ "$any" == false ]]; then
for c in "${COMPONENTS[@]}"; do
component_available "$c" && WANTED[$c]=1
done
fi
}
toggle_component() {
local c="$1"
WANTED[$c]=$(( 1 - WANTED[$c] ))
# Single user mode only makes sense on top of the SteamOS conversion.
if [[ "$c" == single && "${WANTED[single]}" == 1 ]]; then WANTED[gaming]=1; fi
if [[ "$c" == gaming && "${WANTED[gaming]}" == 0 ]]; then WANTED[single]=0; fi
}
show_menu() {
local i=0 c now want
echo
printf " ${c_bold}%-3s %-6s %-6s %s${c_reset}\n" "#" "Now" "Want" "Component"
MENU_ITEMS=()
for c in "${COMPONENTS[@]}"; do
component_available "$c" || continue
i=$((i + 1)); MENU_ITEMS[$i]=$c
now="off"; [[ "${CURRENT[$c]}" == 1 ]] && now="${c_green}on${c_reset} "
want="[ ]"; [[ "${WANTED[$c]}" == 1 ]] && want="[x]"
printf " %-3s %-6b %-6s %s\n" "$i" "$now " "$want" "${LABEL[$c]}"
done
echo
}
run_menu() {
# Sets REAPPLY. Returns 1 if the user quit. A checkbox list on a
# terminal; a plain numbered prompt when input is piped (scripted runs).
REAPPLY=false
if [[ -t 0 && -t 1 ]]; then
run_menu_tui
else
run_menu_lines
fi
}
draw_menu_tui() {
local cursor="$1" i=0 c box state line
printf '\033[H\033[2J'
echo -e "${c_bold}CachyOS Steam Deck-style Gamescope Boot Wizard${c_reset}"
echo "Pick what you want. Anything you untick is put back the way it was."
echo
MENU_ITEMS=()
for c in "${COMPONENTS[@]}"; do
component_available "$c" || continue
MENU_ITEMS[$i]=$c
box="[ ]"; [[ "${WANTED[$c]}" == 1 ]] && box="[${c_green}x${c_reset}]"
state="off"; [[ "${CURRENT[$c]}" == 1 ]] && state="${c_green}on${c_reset}"
line="$box ${LABEL[$c]}"
if (( i == cursor )); then
echo -e " ${c_cyan}>${c_reset} ${c_bold}${line}${c_reset} (now: ${state})"
else
echo -e " ${line} (now: ${state})"
fi
i=$((i + 1))
done
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"
}
run_menu_tui() {
local cursor=0 key rest count
tput civis 2>/dev/null
trap 'tput cnorm 2>/dev/null' EXIT
while true; do
draw_menu_tui "$cursor"
count=${#MENU_ITEMS[@]}
IFS= read -rsn1 key
if [[ "$key" == $'\e' ]]; then
IFS= read -rsn2 -t 0.05 rest
key+="$rest"
fi
case "$key" in
$'\e[A'|k) (( cursor = (cursor + count - 1) % count )) ;;
$'\e[B'|j) (( cursor = (cursor + 1) % count )) ;;
" ") toggle_component "${MENU_ITEMS[$cursor]}" ;;
"") break ;;
a|A) REAPPLY=true; break ;;
q|Q) tput cnorm 2>/dev/null; echo; return 1 ;;
esac
done
tput cnorm 2>/dev/null
echo
return 0
}
run_menu_lines() {
local reply
while true; do
show_menu
read -rp "$(echo -e "${c_bold}Type a number to toggle, Enter to continue, a = also re-apply what's on, q = quit:${c_reset} ")" reply || return 1
case "$reply" in
"") return 0 ;;
a|A) REAPPLY=true; return 0 ;;
q|Q) return 1 ;;
*)
if [[ "$reply" =~ ^[0-9]+$ && -n "${MENU_ITEMS[$reply]:-}" ]]; then
toggle_component "${MENU_ITEMS[$reply]}"
else
warn "Unknown choice: $reply"
fi
;;
esac
done
}
plan_changes() {
# Fills TO_DISABLE (reverse order) and TO_ENABLE. Switching single user
# on or off moves gaming mode to the other login manager, so gaming
# mode is re-applied then too.
TO_DISABLE=(); TO_ENABLE=()
local c i
for (( i = ${#COMPONENTS[@]} - 1; i >= 0; i-- )); do
c=${COMPONENTS[$i]}
component_available "$c" || continue
[[ "${CURRENT[$c]}" == 1 && "${WANTED[$c]}" == 0 ]] && TO_DISABLE+=("$c")
done
for c in "${COMPONENTS[@]}"; do
component_available "$c" || continue
[[ "${WANTED[$c]}" == 1 ]] || continue
if [[ "${CURRENT[$c]}" == 0 || "$REAPPLY" == true ]] ||
[[ "$c" == gaming && "${CURRENT[single]}" != "${WANTED[single]}" ]]; then
TO_ENABLE+=("$c")
fi
done
}
apply_changes() {
local c failed=()
LOGIN_MANAGER=plasmalogin
[[ "${WANTED[single]}" == 1 ]] && LOGIN_MANAGER=sddm
for c in "${TO_DISABLE[@]}"; do
echo; echo -e "${c_bold}Turning off: ${LABEL[$c]}${c_reset}"
"${c}_disable" || failed+=("$c")
done
for c in "${TO_ENABLE[@]}"; do
echo; echo -e "${c_bold}Turning on: ${LABEL[$c]}${c_reset}"
"${c}_enable" || failed+=("$c")
done
FAILED=("${failed[@]}")
}
+2 -7
View File
@@ -60,13 +60,8 @@ install_required_packages() {
mapfile -t MISSING < <(pacman -T gamescope-session-cachyos steam mangohud xterm ttf-liberation wqy-zenhei plasma-keyboard)
if [[ ${#MISSING[@]} -gt 0 ]]; then
info "Missing packages: ${MISSING[*]}"
if ask_yn "Install them now?"; then
sudo pacman -S --needed --noconfirm "${MISSING[@]}" || { err "Package installation failed."; exit 1; }
else
err "Cannot continue without these packages."
exit 1
fi
info "Installing missing packages: ${MISSING[*]}"
sudo pacman -S --needed --noconfirm "${MISSING[@]}" || { err "Package installation failed."; return 1; }
else
ok "All required packages already installed."
fi
+68
View File
@@ -0,0 +1,68 @@
#!/bin/bash
# Single user, no password, like SteamOS: no lock screen, user switching or
# log out, since typing a password with a controller is miserable. Goes
# together with SDDM (see lib/login-manager.sh). All changes are journaled
# per user (lib/state.sh), so turning it off restores KDE's previous state.
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
single_status() {
[[ "$(kreadconfig6 --file kdeglobals --group "KDE Action Restrictions" --key action/lock_screen)" == false ]]
}
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
for action in lock_screen switch_user start_new_session; do
kset single kdeglobals "KDE Action Restrictions" "action/$action" false
done
# Never lock on idle or resume.
kset single kscreenlockerrc Daemon Autolock false
kset single kscreenlockerrc Daemon LockOnResume false
kset single kscreenlockerrc Daemon Timeout 0
# The restrictions don't cover the shortcuts: unbind Meta+L and the
# 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
restart_plasmashell_if_stopped
ok "Single user: no lock screen, user switching or log out."
}
single_disable() {
info "Restoring the lock screen, user switching and logging out..."
stop_plasmashell_for_edit
if has_journal single; then
krevert single
else
# Set up by a version of this script without the undo journal:
# fall back to KDE's defaults for everything it changes.
local action applet key
for action in lock_screen switch_user start_new_session; do
kwriteconfig6 --file kdeglobals --group "KDE Action Restrictions" --key "action/$action" --delete
done
for key in Autolock LockOnResume Timeout; do
kwriteconfig6 --file kscreenlockerrc --group Daemon --key "$key" --delete
done
kwriteconfig6 --file kglobalshortcutsrc --group ksmserver --key "Lock Session" $'Screensaver\tMeta+L,Screensaver\tMeta+L,Lock Session'
kwriteconfig6 --file kglobalshortcutsrc --group ksmserver --key "Log Out" 'Ctrl+Alt+Del,Ctrl+Alt+Del,Show Logout Screen'
for applet in $(plasma_applets org.kde.plasma.kickoff); do
kwriteconfig6 --file plasma-org.kde.plasma.desktop-appletsrc --group Containments --group "${applet%%:*}" \
--group Applets --group "${applet#*:}" --group Configuration --group General --key primaryActions --delete
kwriteconfig6 --file plasma-org.kde.plasma.desktop-appletsrc --group Containments --group "${applet%%:*}" \
--group Applets --group "${applet#*:}" --group Configuration --group General --key systemFavorites --delete
done
fi
restart_plasmashell_if_stopped
ok "KDE's normal lock screen and user switching are back."
}
+79
View File
@@ -0,0 +1,79 @@
#!/bin/bash
# Undo journal for per-user KDE settings, so every component can be turned
# off again exactly: the first time a component changes a key, the key's
# previous value is recorded, and reverting the component puts it back (or
# deletes the key if it didn't exist before).
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
STATE_DIR="${XDG_STATE_HOME:-$HOME/.local/state}/cachyos-gamescope-boot"
UNSET=$'\x01'
kset() {
# kset <component> <file> <group[|group...]> <key> <value>
# kwriteconfig6, recording the old value in the component's journal.
# <value> "--delete" removes the key.
local component="$1" file="$2" groups="$3" key="$4" value="$5"
local journal="$STATE_DIR/$component.journal" old id
local -a gargs=() g
local groups_item
IFS='|' read -ra g <<< "$groups"
for groups_item in "${g[@]}"; do gargs+=(--group "$groups_item"); done
mkdir -p "$STATE_DIR"
id="$(printf '%s\t%s\t%s' "$file" "$groups" "$key")"
if ! grep -qxF -- "$id" <(cut -f1-3 "$journal" 2>/dev/null); then
old="$(kreadconfig6 --file "$file" "${gargs[@]}" --key "$key" --default "$UNSET")"
printf '%s\t%s\n' "$id" "$(printf '%s' "$old" | base64 -w0)" >> "$journal"
fi
if [[ "$value" == "--delete" ]]; then
kwriteconfig6 --file "$file" "${gargs[@]}" --key "$key" --delete
else
kwriteconfig6 --file "$file" "${gargs[@]}" --key "$key" "$value"
fi
}
krevert() {
# krevert <component>: restore every key the component changed, newest
# first, then forget the journal.
local component="$1"
local journal="$STATE_DIR/$component.journal"
local file groups key old groups_item
local -a g
[[ -f "$journal" ]] || return 0
while IFS=$'\t' read -r file groups key old; do
local -a gargs=()
IFS='|' read -ra g <<< "$groups"
for groups_item in "${g[@]}"; do gargs+=(--group "$groups_item"); done
old="$(printf '%s' "$old" | base64 -d)"
if [[ "$old" == "$UNSET" ]]; then
kwriteconfig6 --file "$file" "${gargs[@]}" --key "$key" --delete
else
kwriteconfig6 --file "$file" "${gargs[@]}" --key "$key" "$old"
fi
done < <(tac "$journal")
rm -f "$journal"
}
has_journal() {
[[ -s "$STATE_DIR/$1.journal" ]]
}
state_set() {
# state_set <component> <name> <value>: remember a value for later.
mkdir -p "$STATE_DIR"
kwriteconfig6 --file "$STATE_DIR/$1.state" --group State --key "$2" "$3"
}
state_get() {
# state_get <component> <name> [default]
kreadconfig6 --file "$STATE_DIR/$1.state" --group State --key "$2" --default "${3:-}"
}
state_clear() {
rm -f "$STATE_DIR/$1.state"
}
current_display_manager() {
systemctl show -p Id --value display-manager 2>/dev/null | sed 's/\.service$//'
}
+32 -76
View File
@@ -1,24 +1,14 @@
#!/bin/bash
# Steam in the Plasma desktop session: gamepad UI args, virtual keyboard,
# autostart, and no screen locking (like SteamOS).
# autostart. Part of the SteamOS conversion (gaming_enable/gaming_disable).
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
setup_steam_desktop() {
# Step 8b: always runs.
steam_enable() {
info "Applying non-optional SteamOS environment & keyboard fixes..."
local steam_env_dir gs_env systemd_user_dir
local steam_env_dir systemd_user_dir
steam_env_dir="$HOME/.config/environment.d"
mkdir -p "$steam_env_dir"
# 1. Force Gamescope Steam to boot into Deck mode and load Deck glyphs
echo "STEAM_GAMEPADUI_ARGS=\"-gamepadui -steamos3\"" > "$steam_env_dir/99-gamescope-steam-glyphs.conf"
gs_env="$HOME/.config/gamescope-session/environment"
if [[ -d "$HOME/.config/gamescope-session" ]]; then
touch "$gs_env"
sed -i '/^STEAM_GAMEPADUI_ARGS=/d' "$gs_env"
echo "STEAM_GAMEPADUI_ARGS=\"-gamepadui -steamos3\"" >> "$gs_env"
fi
# 2. Prevent KDE Wayland from blocking the virtual keyboard overlay
echo "KWIN_IM_SHOW_ALWAYS=1" > "$steam_env_dir/99-kde-virtual-keyboard.conf"
@@ -54,70 +44,36 @@ EOF
ok "Steam UI parameters and keyboard autostart deployed successfully."
}
setup_single_user() {
# With SINGLE_USER (chosen in step 1), like SteamOS: one user and no
# password prompts, since typing a password with a controller is
# miserable. Hides Lock / Switch User / Log Out
# everywhere (launcher, Meta+L, Ctrl+Alt+Del) and never locks on idle or
# resume; "Return to Gaming Mode" is the way out of the desktop. Declining
# restores KDE's defaults.
local action allow=true
[[ "$SINGLE_USER" == true ]] && allow=false
for action in lock_screen switch_user start_new_session; do
kwriteconfig6 --file kdeglobals --group "KDE Action Restrictions" --key "action/$action" "$allow"
done
if [[ "$allow" == false ]]; then
kwriteconfig6 --file kscreenlockerrc --group Daemon --key Autolock false
kwriteconfig6 --file kscreenlockerrc --group Daemon --key LockOnResume false
kwriteconfig6 --file kscreenlockerrc --group Daemon --key Timeout 0
# The action restriction hides Lock in menus but not the Meta+L
# shortcut; unbind it (format: current,default,description).
kwriteconfig6 --file kglobalshortcutsrc --group ksmserver --key "Lock Session" \
$'none,Screensaver\tMeta+L,Lock Session'
kwriteconfig6 --file kglobalshortcutsrc --group ksmserver --key "Log Out" \
'none,Ctrl+Alt+Del,Show Logout Screen'
set_launcher_leave_buttons single
ok "Screen locking, user switching and logging out disabled."
else
kwriteconfig6 --file kscreenlockerrc --group Daemon --key Autolock --delete
kwriteconfig6 --file kscreenlockerrc --group Daemon --key LockOnResume --delete
kwriteconfig6 --file kscreenlockerrc --group Daemon --key Timeout --delete
kwriteconfig6 --file kglobalshortcutsrc --group ksmserver --key "Lock Session" \
$'Screensaver\tMeta+L,Screensaver\tMeta+L,Lock Session'
kwriteconfig6 --file kglobalshortcutsrc --group ksmserver --key "Log Out" \
'Ctrl+Alt+Del,Ctrl+Alt+Del,Show Logout Screen'
set_launcher_leave_buttons default
ok "Keeping KDE's normal screen locking and user switching."
fi
steam_disable() {
info "Removing Steam desktop autostart..."
systemctl --user disable --now steam-desktop-autostart.service 2>/dev/null
rm -f "$HOME/.config/systemd/user/steam-desktop-autostart.service" \
"$HOME/.config/environment.d/99-kde-virtual-keyboard.conf"
systemctl --user daemon-reload
ok "Steam desktop settings removed (takes full effect at next login)."
}
set_launcher_leave_buttons() {
# "single": only Sleep / Restart / Shut Down buttons in the launcher, no
# Session dropdown (that's where Log Out lives). Restricting the
# "logout" action instead would also hide Restart and Shut Down.
# "default": Plasma's own buttons.
local mode="$1" applet
for applet in $(plasma_applets org.kde.plasma.kickoff); do
local -a grp=(--file plasma-org.kde.plasma.desktop-appletsrc --group Containments
--group "${applet%%:*}" --group Applets --group "${applet#*:}"
--group Configuration --group General)
if [[ "$mode" == single ]]; then
kwriteconfig6 "${grp[@]}" --key primaryActions 3
kwriteconfig6 "${grp[@]}" --key systemFavorites 'suspend,reboot,shutdown'
else
kwriteconfig6 "${grp[@]}" --key primaryActions --delete
kwriteconfig6 "${grp[@]}" --key systemFavorites --delete
fi
done
if pgrep -u "$USER" -x plasmashell >/dev/null; then
local js
if [[ "$mode" == single ]]; then
js="w.writeConfig('primaryActions', 3); w.writeConfig('systemFavorites', 'suspend,reboot,shutdown');"
else
js="w.writeConfig('primaryActions', 0); w.writeConfig('systemFavorites', 'suspend,hibernate,reboot,shutdown');"
fi
qdbus6 org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript \
"panels().forEach(function (p) { p.widgets('org.kde.plasma.kickoff').forEach(function (w) { w.currentConfigGroup = ['General']; $js w.reloadConfig(); }); })" \
>/dev/null 2>&1 || true
# "Steam Deck/Machine icons" menu item: Steam's gamepad UI in SteamOS 3
# mode, which shows Steam Deck button glyphs in gaming mode.
glyphs_status() {
[[ -f "$HOME/.config/environment.d/99-gamescope-steam-glyphs.conf" ]]
}
glyphs_enable() {
local gs_env="$HOME/.config/gamescope-session/environment"
mkdir -p "$HOME/.config/environment.d"
echo 'STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"' > "$HOME/.config/environment.d/99-gamescope-steam-glyphs.conf"
if [[ -d "$HOME/.config/gamescope-session" ]]; then
touch "$gs_env"
sed -i '/^STEAM_GAMEPADUI_ARGS=/d' "$gs_env"
echo 'STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"' >> "$gs_env"
fi
ok "Steam Deck/Machine icons on (from the next gaming mode start)."
}
glyphs_disable() {
rm -f "$HOME/.config/environment.d/99-gamescope-steam-glyphs.conf"
[[ -f "$HOME/.config/gamescope-session/environment" ]] &&
sed -i '/^STEAM_GAMEPADUI_ARGS=/d' "$HOME/.config/gamescope-session/environment"
ok "Steam's default button icons are back (from the next gaming mode start)."
}
+45 -17
View File
@@ -1,5 +1,6 @@
#!/bin/bash
# Valve Fremont (Steam Machine) front LED bar driver.
# "Steam Machine support" menu item, only on Valve Fremont hardware: the
# front LED bar driver, LED access for Steam, and steamos-manager.
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
detect_valve_fremont() {
@@ -92,22 +93,49 @@ install_valve_led_driver() {
warn " ls /sys/class/leds/ | grep valve ; sudo dmesg | grep -i valve"
fi
echo
info "Steam only pushes download progress to the LED bar in real SteamOS Game Mode."
if ask_yn "Also install the experimental OpenRGB build (openrgb-git), which can drive the LED bar?" n; then
"$aur_helper" -S "${flags[@]}" openrgb-git &&
ok "openrgb-git installed. Launch OpenRGB to detect and configure the front panel."
fi
}
setup_led_driver() {
# Step 8c: only on Fremont hardware, and only if the user wants it.
if detect_valve_fremont; then
info "Detected Valve Fremont hardware (Steam Machine)."
if ask_yn "Set up the front-panel LED bar driver (leds-valve) so it isn't stuck dark/breathing?" y; then
ensure_aur_helper || warn "Couldn't set up an AUR helper automatically. You can install one yourself later and run: yay -S leds-valve-dkms-git"
install_valve_led_driver || warn "LED driver setup ran into a problem - see errors above. Your gamescope boot setup above is unaffected."
fi
echo
fi
LED_UDEV_RULE="/etc/udev/rules.d/70-valve-leds-user.rules"
machine_available() { detect_valve_fremont; }
machine_status() {
pacman -Qi leds-valve-dkms-git >/dev/null 2>&1 && pacman -Qi steamos-manager >/dev/null 2>&1
}
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; }
install_valve_led_driver || { warn "LED driver setup ran into a problem - see errors above."; return 1; }
# 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
# doesn't cover the Steam Machine's LED bar).
info "Letting $TARGET_USER control the LED bar..."
sudo tee "$LED_UDEV_RULE" > /dev/null << EOF
# Let the console user (and Steam) control the Steam Machine's front LED bar.
SUBSYSTEM=="leds", KERNEL=="valve-leds*", RUN+="/usr/bin/find /sys%p -maxdepth 1 -type f -exec /usr/bin/chown $TARGET_USER {} +"
EOF
sudo udevadm control --reload
sudo udevadm trigger --subsystem-match=leds --action=add
# steamos-manager is what Steam in gaming mode talks to for hardware
# settings (fan, HDMI-CEC TV control, performance); it knows the Steam
# Machine from its DMI data.
info "Installing steamos-manager (Steam Machine hardware settings in Steam)..."
sudo pacman -S --needed --noconfirm steamos-manager || { err "Installing steamos-manager failed."; return 1; }
sudo systemctl enable --now steamos-manager.service
systemctl --user enable steamos-manager.service 2>/dev/null
ok "Steam Machine support on."
}
machine_disable() {
info "Removing Steam Machine support..."
systemctl --user 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 rm -f "$LED_UDEV_RULE" /etc/modules-load.d/leds-valve.conf
sudo udevadm control --reload
sudo modprobe -r leds-valve 2>/dev/null
sudo pacman -Rns --noconfirm leds-valve-dkms-git 2>/dev/null
ok "Steam Machine support removed (the AUR helper, if installed, is kept)."
}
+119 -174
View File
@@ -4,22 +4,22 @@
merge_kde_config() {
# Merge a KDE-style ini file (e.g. one of Valve's /etc/xdg defaults) into
# the user's own config with kwriteconfig6, so SteamOS defaults win over
# the 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 -a groups=()
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=()
skip=0; groups=""
[[ "$line" == *'[$'* ]] && { skip=1; continue; }
local rest="$line"
while [[ "$rest" =~ ^\[([^]]*)\](.*)$ ]]; do
groups+=("--group" "${BASH_REMATCH[1]}")
groups+="${groups:+|}${BASH_REMATCH[1]}"
rest="${BASH_REMATCH[2]}"
done
continue
@@ -27,7 +27,7 @@ merge_kde_config() {
(( skip )) && continue
[[ "$line" == *=* ]] || continue
key="${line%%=*}"; value="${line#*=}"
kwriteconfig6 --file "$target" "${groups[@]}" --key "$key" "$value"
kset theme "$target" "$groups" "$key" "$value"
done < "$src"
}
@@ -113,15 +113,19 @@ install_vapor_theme() {
[[ -f "${tmp_dir}/etc/xdg/$f" ]] && merge_kde_config "${tmp_dir}/etc/xdg/$f" "$f"
done
[[ -f "${tmp_dir}/etc/xdg/kded5rc" ]] && merge_kde_config "${tmp_dir}/etc/xdg/kded5rc" kded6rc
kwriteconfig6 --file konsolerc --group "Desktop Entry" --key DefaultProfile Vapor.profile
kset theme konsolerc "Desktop Entry" DefaultProfile Vapor.profile
mkdir -p ~/.config/gtk-3.0 ~/.config/gtk-4.0
kwriteconfig6 --file ~/.config/gtk-3.0/settings.ini --group Settings --key gtk-theme-name Vapor
kwriteconfig6 --file ~/.config/gtk-4.0/settings.ini --group Settings --key gtk-theme-name Vapor
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.
kwriteconfig6 --file ~/.config/gtk-3.0/settings.ini --group Settings --key gtk-application-prefer-dark-theme true
kwriteconfig6 --file ~/.config/gtk-4.0/settings.ini --group Settings --key gtk-application-prefer-dark-theme true
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
@@ -130,138 +134,52 @@ install_vapor_theme() {
info "Cleaning up temporary files..."
rm -rf "$tmp_dir"
# Launcher icon
# 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).
local icon_name="distributor-logo-steamdeck"
local conf_file="$HOME/.config/plasma-org.kde.plasma.desktop-appletsrc"
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
if ! find ~/.local/share/icons /usr/share/icons -iname "${icon_name}.*" 2>/dev/null | grep -q .; then
warn "Could not find '${icon_name}' installed anywhere under ~/.local/share/icons or /usr/share/icons."
warn "The launcher icon will be set anyway, but it may show as a broken icon until the file is installed."
fi
if [[ -f "$conf_file" ]]; then
info "Looking for the Application Launcher applet (Kickoff/Kicker) to set the custom icon..."
local matches=()
local current_section=""
local current_containment=""
local current_applet=""
while IFS= read -r line; do
if [[ "$line" =~ ^\[Containments\]\[([0-9]+)\]\[Applets\]\[([0-9]+)\]$ ]]; then
current_containment="${BASH_REMATCH[1]}"
current_applet="${BASH_REMATCH[2]}"
current_section="applet_root"
continue
fi
if [[ "$line" =~ ^\[ ]]; then
current_section=""
continue
fi
if [[ "$current_section" == "applet_root" && "$line" =~ ^plugin=(org\.kde\.plasma\.(kickoff|kicker|simplemenu|homerun|application-menu))$ ]]; then
matches+=( "${current_containment}:${current_applet}:${BASH_REMATCH[1]}" )
current_section=""
fi
done < "$conf_file"
if [[ ${#matches[@]} -gt 0 ]]; then
for m in "${matches[@]}"; do
IFS=':' read -r containment applet plugin <<< "$m"
info "Setting launcher icon on Containment $containment / Applet $applet ($plugin)..."
kwriteconfig6 \
--file "$conf_file" \
--group Containments --group "$containment" \
--group Applets --group "$applet" \
--group Configuration --group General \
--key icon "$icon_name"
ok "Icon set to '$icon_name'."
done
else
warn "No compatible Application Launcher applet found in panel config. Skipping icon assignment."
fi
else
warn "$conf_file not found. Skipping menu icon configuration."
fi
# SteamOS scales system tray icons to the panel height. Valve's setup
# script targets Plasma 5's separate tray containment; in Plasma 6 the
# setting lives on the systemtray applet itself.
if [[ -f "$conf_file" ]]; then
local tray
for tray in $(awk '
/^\[Containments\]\[[0-9]+\]\[Applets\]\[[0-9]+\]$/ { split($0, p, /[][]+/); sect = p[3] ":" p[5] }
/^\[/ && !/\]\[Applets\]\[[0-9]+\]$/ { sect = "" }
/^plugin=org\.kde\.plasma\.systemtray$/ && sect != "" { print sect }
' "$conf_file"); do
kwriteconfig6 --file "$conf_file" --group Containments --group "${tray%%:*}" \
--group Applets --group "${tray#*:}" --group General \
--key scaleIconsToFit true
# 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
# SteamOS shows the date below the time in the panel clock.
if [[ -f "$conf_file" ]]; then
local clock
for clock in $(awk '
/^\[Containments\]\[[0-9]+\]\[Applets\]\[[0-9]+\]$/ { split($0, p, /[][]+/); sect = p[3] ":" p[5] }
/^\[/ && !/\]\[Applets\]\[[0-9]+\]$/ { sect = "" }
/^plugin=org\.kde\.plasma\.digitalclock$/ && sect != "" { print sect }
' "$conf_file"); do
kwriteconfig6 --file "$conf_file" --group Containments --group "${clock%%:*}" \
--group Applets --group "${clock#*:}" --group Configuration --group Appearance \
--key dateDisplayFormat BelowTime
done
fi
# 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
# Wallpaper
# Valve ships the wallpapers as flat JPGs in usr/share/wallpapers.
local wallpaper_path="$HOME/.local/share/wallpapers/Steam Deck Logo Default.jpg"
if [[ -f "$wallpaper_path" ]]; then
info "Applying official Steam Deck Vapor wallpaper via D-Bus script..."
local dbus_cmd="
var allDesktops = desktops();
for (var i = 0; i < allDesktops.length; i++) {
var d = allDesktops[i];
d.currentConfigGroup = ['Wallpaper', 'org.kde.image', 'General'];
d.writeConfig('Image', 'file://${wallpaper_path}');
}
"
if ! pgrep -u "$USER" -x plasmashell >/dev/null; then
:
elif command -v qdbus6 >/dev/null 2>&1; then
qdbus6 org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "$dbus_cmd" >/dev/null 2>&1 || true
else
qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "$dbus_cmd" >/dev/null 2>&1 || true
fi
if [[ -f "$conf_file" ]]; then
local desktop_sections=$(grep -E '^\[Containments\]\[[0-9]+\]$' "$conf_file" || true)
while read -r section; do
if [[ -n "$section" ]]; then
local clean_sec=$(echo "$section" | tr -d '[]')
kwriteconfig6 --file "$conf_file" --group "$clean_sec" --group Wallpaper --group org.kde.image --group General --key Image "file://${wallpaper_path}"
fi
done <<< "$desktop_sections"
fi
ok "Wallpaper path pushed to session config."
else
warn "Could not find extracted Vapor wallpaper file. Skipping."
fi
# Activate the Vapor global theme and color scheme, then restart
# plasmashell once so it picks everything up (restarting first races
# with the settings being written). The theme's own defaults use
# breeze-dark icons; there is no "Vapor" icon theme.
kwriteconfig6 --file kdeglobals --group Icons --key Theme "breeze-dark"
kwriteconfig6 --file kdeglobals --group General --key ColorScheme "Vapor"
kwriteconfig6 --file plasmarc --group Theme --key name "Vapor"
# Same panel change for the next login, in case Plasma isn't running now.
# 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
kwriteconfig6 --file plasmashellrc --group PlasmaViews --group "Panel $panel" --key floating 0
kwriteconfig6 --file plasmashellrc --group PlasmaViews --group "Panel $panel" --group Defaults --key thickness 44
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
@@ -269,56 +187,83 @@ install_vapor_theme() {
# Live changes need a running Plasma session; otherwise they are picked
# up from the config files above at the next Plasma login.
if pgrep -u "$USER" -x plasmashell >/dev/null; then
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.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript \
'panels().forEach(function (p) {
p.widgets("org.kde.plasma.systemtray").forEach(function (w) { w.currentConfigGroup = ["General"]; w.writeConfig("scaleIconsToFit", true); });
p.widgets("org.kde.plasma.digitalclock").forEach(function (w) { w.currentConfigGroup = ["Appearance"]; w.writeConfig("dateDisplayFormat", "BelowTime"); });
})' \
>/dev/null 2>&1 || true
# SteamOS uses a solid, full-width bottom panel at Plasma's stock
# 44px height (CachyOS ships a floating 30px one).
qdbus6 org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript \
'panels().forEach(function (p) { p.floating = false; p.lengthMode = "fill"; p.height = 44; })' \
>/dev/null 2>&1 || true
sleep 2 # let plasmashell flush the scripted changes before replacing it
rm -rf ~/.cache/plasmashell* ~/.cache/org.kde.dirmodel-qml.kcache
qdbus6 org.kde.KWin /KWin org.kde.KWin.reconfigure >/dev/null 2>&1 || true
# Restart through systemd so plasmashell keeps the session's environment
# (platform theme etc.); a plain --replace from this shell may not.
if systemctl --user cat plasma-plasmashell.service >/dev/null 2>&1; then
# Also takes over from a stray instance started by an earlier --replace.
systemctl --user stop plasma-plasmashell.service
pkill -u "$USER" -x plasmashell && sleep 2
systemctl --user start plasma-plasmashell.service
else
setsid plasmashell --replace >/dev/null 2>&1 &
fi
else
info "No running Plasma session; the theme applies at your next desktop login."
fi
ok "Vapor theme assets installed. Apply it under System Settings > Appearance"
ok "> Global Theme > Vapor (Steam Deck), next time you're in a Plasma session."
ok "SteamOS desktop look installed."
}
setup_vapor_theme() {
# Step 9 (optional): ask, make sure curl/zstd exist, then install.
echo
if ask_yn "Also install Valve's official Vapor (Steam Deck) KDE theme for your desktop session?" n; then
if ! command -v curl >/dev/null 2>&1; then
warn "curl not found, installing it first..."
sudo pacman -S --needed --noconfirm curl
fi
if ! command -v unzstd >/dev/null 2>&1; then
warn "zstd not found, installing it first..."
sudo pacman -S --needed --noconfirm zstd
fi
install_vapor_theme || warn "Vapor theme install ran into a problem - see errors above. Your gamescope boot setup above is unaffected."
theme_status() {
[[ "$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage)" == com.valve.vapor.desktop ]]
}
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
}
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)"
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
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
fi
restart_plasmashell_if_stopped
state_clear theme
ok "Previous desktop look restored."
}
+51 -109
View File
@@ -2,46 +2,21 @@
#
# setup-gamescope-boot.sh
#
# Wizard to configure a CachyOS (KDE Plasma + plasma-login-manager) install
# to always boot into a Steam Deck-style gamescope session, with the
# ability to switch to Plasma desktop and back, Deck-style, and have it
# reset to gamescope on the next boot/logout.
# Wizard that makes a CachyOS (KDE Plasma) install behave like SteamOS:
# boot into a Steam Deck-style gamescope session, switch to the Plasma
# desktop and back, and reset to gamescope on the next boot/logout.
#
# Covers three real bugs found on CachyOS as of Sep 2026:
# 1. steam-set-session never writes User= to plasmalogin's autologin
# config, so plasma-login-manager never actually autologs in.
# 2. steam-set-session fails outright if /etc/plasmalogin.conf.d is
# missing, breaking "Switch to Desktop" from inside gamescope.
# 3. /etc/plasmalogin.conf (the base config) hardcodes Session=plasma
# and takes priority over anything written to
# /etc/plasmalogin.conf.d/*.conf, so session switches never stick
# without a bridge that copies the conf.d value back into the base
# file, plus Relogin=true so ending a session re-triggers autologin
# instead of dropping to the greeter.
#
# Safe to re-run: it is idempotent and backs up files before editing.
#
# Automatically configures a permanent background systemd autostart for Steam
# and Wayland overrides so the Steam Controller virtual keyboard (Steam+X)
# always works in desktop mode.
#
# Optionally also offers to install the official Valve "Vapor" KDE Plasma
# theme (colors, icons, wallpapers, Plasma look-and-feel package) used on
# real SteamOS, pulled directly from Valve's own package mirror, so the
# desktop side matches the gamescope side visually.
#
# On Valve Fremont hardware (DMI sys_vendor=Valve, product_name=Fremont --
# i.e. the Steam Machine), also offers to install the
# leds-valve DKMS driver from the AUR so the front LED bar is exposed under
# /sys/class/leds instead of sitting dark or "breathing" under a standard
# desktop kernel, plus the option to pull in an experimental OpenRGB build
# that has native support for driving it.
# It opens with a menu that detects which components are on and turns
# them on or off to match what the user picks; turning one off restores
# what was there before (system files from .bak-gamescope-wizard backups,
# KDE settings from the undo journal in lib/state.sh). Components live in
# lib/, see README.md. Safe to re-run.
set -uo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
for lib in common packages login-manager steam-desktop led-driver vapor-theme desktop-shortcut; do
for lib in common state packages login-manager single-user steam-desktop steam-machine vapor-theme desktop-shortcut menu; do
# shellcheck source=/dev/null
source "$SCRIPT_DIR/lib/$lib.sh"
done
@@ -49,92 +24,59 @@ done
require_root_helper
echo -e "${c_bold}CachyOS Steam Deck-style Gamescope Boot Wizard${c_reset}"
echo "This sets your machine up to always boot into gamescope (like SteamOS),"
echo "with working Switch-to-Desktop and switch-back, surviving reboots."
echo
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."
if ! command -v pacman >/dev/null 2>&1; then
err "This doesn't look like an Arch/CachyOS system (no pacman found). Aborting."
exit 1
fi
# Ask for the sudo password once up front and keep it fresh, instead of
# prompting at random points during the run.
# Everything per-user (autologin user, Steam, theme, shortcut) is for the
# user running the script.
TARGET_USER="$(id -un)"
detect_components
run_menu || { info "Nothing changed."; exit 0; }
plan_changes
if [[ ${#TO_DISABLE[@]} -eq 0 && ${#TO_ENABLE[@]} -eq 0 ]]; then
ok "Everything is already the way you want it."
exit 0
fi
echo
echo -e "${c_bold}This will:${c_reset}"
for c in "${TO_DISABLE[@]}"; do echo " - turn off: ${LABEL[$c]}"; done
for c in "${TO_ENABLE[@]}"; do
if [[ "${CURRENT[$c]}" == 1 ]]; then echo " - re-apply: ${LABEL[$c]}"; else echo " - turn on: ${LABEL[$c]}"; fi
done
ask_yn "Go ahead?" y || { info "Nothing changed."; exit 0; }
# Ask for the sudo password once and keep it fresh, instead of prompting at
# random points during the run.
sudo -n true 2>/dev/null || sudo -v || exit 1
while true; do sudo -n true; sleep 50; kill -0 "$$" 2>/dev/null || exit; done 2>/dev/null &
TARGET_USER="${SUDO_USER:-$USER}"
read -rp "$(echo -e "${c_bold}Which user should autologin into gamescope?${c_reset} [${TARGET_USER}] ")" input_user
TARGET_USER="${input_user:-$TARGET_USER}"
apply_changes
if ! id "$TARGET_USER" >/dev/null 2>&1; then
err "User '$TARGET_USER' does not exist on this system."
exit 1
echo
detect_components
echo -e "${c_bold}Done. Current state:${c_reset}"
for c in "${COMPONENTS[@]}"; do
component_available "$c" || continue
if [[ "${CURRENT[$c]}" == 1 ]]; then echo -e " ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " off ${LABEL[$c]}"; fi
done
if [[ ${#FAILED[@]} -gt 0 ]]; then
warn "These had problems (see above): ${FAILED[*]}"
fi
if [[ "$TARGET_USER" != "$(id -un)" ]]; then
# Environment, systemd user units, theme and shortcut are all written
# into the invoking user's home and user session.
err "Run this script as '$TARGET_USER' itself so per-user settings land in the right home."
exit 1
fi
ok "Using user: $TARGET_USER"
echo
choose_setup_mode
echo
install_required_packages
echo
setup_login_manager
setup_steam_desktop
echo
setup_single_user
echo
setup_led_driver
setup_vapor_theme
echo
create_desktop_shortcut
echo
# ---------- 11. Summary + reboot ----------
echo -e "${c_bold}Setup complete.${c_reset}"
echo "What this did:"
echo " - Installed gamescope-session-cachyos, steam, mangohud and friends (if missing)"
if [[ "$LOGIN_MANAGER" == "sddm" ]]; then
echo " - Made SDDM the login manager, autologging '$TARGET_USER' into gamescope"
echo " with Relogin=true, like SteamOS (active from the next boot)"
else
echo " - Created /etc/plasmalogin.conf.d (fixes Switch-to-Desktop crash)"
echo " - Set $BASE_CONF to autologin '$TARGET_USER' into gamescope, with Relogin=true"
echo " - Installed a sync bridge + systemd watcher so Steam's Switch-to-Desktop"
echo " (and cachyos-gamescope-autologin.service resetting back to gamescope"
echo " on logout) both actually take effect"
echo " - Added /etc/sudoers.d/gamescope-session-switch so the desktop shortcut works"
fi
echo " - Configured permanent silent Steam autostart so Steam+X works everywhere"
echo " - Injected -steamos3 flag to force original Steam Deck overlay glyphs"
echo " - Optionally installed Valve's Vapor (Steam Deck) KDE theme, if you chose to"
echo " - On Valve Fremont hardware, optionally set up the leds-valve front LED bar driver"
echo
echo "Backups of any files this script modified were saved with a"
echo ".bak-gamescope-wizard suffix next to the original."
echo
echo "To manually flip sessions any time:"
echo " steamos-session-select gamescope # boot straight into gamescope now"
echo " steamos-session-select plasma # boot straight into desktop now"
echo " steamos-session-select persistent # remember last-used session across reboots"
echo " steamos-session-select oneshot # always start in gamescope regardless (default Deck behavior)"
echo
if ask_yn "Reboot now to test it?" n; then
sudo reboot
else
info "Skipping reboot. Run 'sudo reboot' whenever you're ready to test."
# Login manager changes only take effect after a restart.
if [[ " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " == *" gaming "* || " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " == *" single "* ]]; then
if ask_yn "Restart now so the changes take effect?" n; then
sudo reboot
else
info "Restart whenever you're ready."
fi
fi