mirror of
https://github.com/theupriser/steamify-cachyos.git
synced 2026-10-03 17:41:58 +02:00
fix: Replace the question flow with a menu that turns components on and off
- Menu detects what is on and applies only the changes: SteamOS conversion, SteamOS theme, Steam Deck/Machine icons, single user mode, and Steam Machine support (only on Fremont hardware) - Everything is reversible: KDE settings go through an undo journal (lib/state.sh), system files are restored from their backups - Steam Machine support: LED driver, udev rule giving the user the LED files, steamos-manager for Steam's hardware settings; OpenRGB dropped - Edit Plasma files only while plasmashell is stopped so it can't overwrite them - README and AGENTS.md describe the menu, the component model and the test environment
This commit is contained in:
1 parent
a0bc385765
commit
b91fa4bc83
13 files changed
+773
-567
No files matched your search
@@ -13,11 +13,24 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
|||||||
## Layout
|
## Layout
|
||||||
|
|
||||||
- `setup-gamescope-boot.sh` - the only entry point. Pre-flight checks,
|
- `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
|
- `lib/*.sh` - one file per responsibility, each defining functions only
|
||||||
(no top-level side effects). See the table in `README.md`. New
|
(no top-level side effects besides constants). See the table in
|
||||||
functionality goes in the module it belongs to, or a new module that is
|
`README.md`.
|
||||||
added to the `source` loop in `setup-gamescope-boot.sh`.
|
- **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
|
## Conventions
|
||||||
|
|
||||||
@@ -41,12 +54,11 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
|||||||
|
|
||||||
## Non-obvious behaviour to preserve
|
## Non-obvious behaviour to preserve
|
||||||
|
|
||||||
- One wizard question in `choose_setup_mode` sets `$SINGLE_USER` and
|
- `apply_changes` sets `$LOGIN_MANAGER` from the menu: `sddm` when single
|
||||||
`$LOGIN_MANAGER`. "Single user, no password" = SteamOS: SDDM plus no lock
|
user mode is wanted, else `plasmalogin`. Toggling single user re-applies
|
||||||
screen, user switching or log out (`setup_single_user`; the launcher's
|
`gaming` so it moves to the other login manager. Single user mode hides
|
||||||
Session dropdown is hidden via kickoff `primaryActions=3` because
|
the launcher's Session dropdown via kickoff `primaryActions=3` (restricting
|
||||||
restricting `action/logout` also hides Restart/Shut Down). Otherwise the
|
`action/logout` also hides Restart/Shut Down). Two login-manager paths:
|
||||||
current login manager stays. Two login-manager paths:
|
|
||||||
**sddm** (like SteamOS: `steam-set-session` writes
|
**sddm** (like SteamOS: `steam-set-session` writes
|
||||||
`/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM honours; we add
|
`/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM honours; we add
|
||||||
`User=`/`Relogin=` in `10-gamescope-autologin.conf`, and `/etc/sddm.conf`
|
`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).
|
launches).
|
||||||
- Live Plasma changes (`qdbus6 ... evaluateScript`, `lookandfeeltool`) only
|
- Live Plasma changes (`qdbus6 ... evaluateScript`, `lookandfeeltool`) only
|
||||||
run when `plasmashell` is running; config-file fallbacks cover the rest.
|
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`,
|
- LED driver: `leds-valve-dkms-git`'s Makefile builds against `uname -r`,
|
||||||
so the script builds explicitly for the running kernel and installs
|
so the script builds explicitly for the running kernel and installs
|
||||||
headers for every installed kernel first. The module creates
|
headers for every installed kernel first. The module creates
|
||||||
@@ -91,21 +106,10 @@ 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
|
shellcheck -S warning setup-gamescope-boot.sh lib/*.sh # if available
|
||||||
```
|
```
|
||||||
|
|
||||||
Behaviour is best verified in a CachyOS VM (QEMU/KVM, KDE Plasma install,
|
Behaviour is verified in a CachyOS QEMU/KVM test VM. The VM scripts and a
|
||||||
`plasma-login-manager`) with SSH access, reset from a disk snapshot between
|
Claude Code skill describing the whole test workflow (snapshots, SSH, running
|
||||||
runs. Notes from doing this:
|
the wizard with scripted menu input such as `printf '2\n\ny\nn\n'`, the
|
||||||
|
per-component checks, reboot checks, the full test matrix, `--fremont` to
|
||||||
- Run the script non-interactively by piping answers, e.g.
|
fake Steam Machine hardware) live in
|
||||||
`printf "\ny\nn\nn\n" | ./setup-gamescope-boot.sh` (user, single user,
|
[cachyos-gamescope-boot-dev-env](https://github.com/theupriser/cachyos-gamescope-boot-dev-env).
|
||||||
theme, reboot).
|
Gamescope itself and the real LED bar can only be verified on hardware.
|
||||||
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.
|
|
||||||
@@ -11,16 +11,22 @@ script fixes that and sets everything up for you.
|
|||||||
|
|
||||||
## What you get
|
## What you get
|
||||||
|
|
||||||
- **Boots into gaming mode** automatically - you never see a login screen,
|
The wizard is a menu: pick what you want, and it turns each part on or off.
|
||||||
just like SteamOS.
|
Everything you turn off is put back the way it was.
|
||||||
- **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
|
1. **SteamOS conversion** - boots straight into gaming mode, **Switch to
|
||||||
out.
|
Desktop** in Steam works and so does going back (the **Return to Gaming
|
||||||
- **Back to gaming mode after a restart**, like SteamOS.
|
Mode** icon on the desktop), you're back in gaming mode after a restart,
|
||||||
- **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.
|
||||||
- *Optional:* the **SteamOS desktop look** - Valve's own Vapor theme,
|
2. **SteamOS theme** - Valve's own Vapor look for the desktop: wallpaper,
|
||||||
wallpaper, dark mode and taskbar.
|
dark mode and the SteamOS taskbar.
|
||||||
- *Optional, Steam Machine only:* a driver for the **front LED bar**.
|
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
|
## Requirements
|
||||||
|
|
||||||
@@ -37,31 +43,34 @@ cd <this-repo>
|
|||||||
./setup-gamescope-boot.sh
|
./setup-gamescope-boot.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
Run it as yourself, not as root. It asks for your password once, then asks a
|
Run it as yourself, not as root. You'll see a menu like this:
|
||||||
few yes/no questions:
|
|
||||||
|
|
||||||
- **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
|
# Now Want Component
|
||||||
logging out - typing a password with a controller is no fun. This
|
1 off [x] SteamOS conversion: boot into gaming mode, Steam on the desktop
|
||||||
switches to SDDM, the login manager SteamOS uses. Say no to keep
|
2 off [x] Install SteamOS theme: Vapor look, dark mode, SteamOS taskbar
|
||||||
CachyOS's default login manager and KDE's normal lock screen; gaming mode
|
3 off [x] Install Steam Deck/Machine icons: Deck button icons in gaming mode
|
||||||
still starts automatically.
|
4 off [x] Single user mode: no password, lock screen or log out (SDDM)
|
||||||
- whether to install missing packages;
|
```
|
||||||
- the LED driver (Steam Machine only) and the SteamOS look.
|
|
||||||
|
|
||||||
At the end it offers to restart. The switch to SDDM takes effect from that
|
**Now** shows what's on at the moment, **Want** what you'd like. Type a
|
||||||
restart.
|
number and press Enter to tick or untick it, then press Enter on an empty
|
||||||
|
line to continue. The wizard 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 (type `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.
|
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
|
## Using it
|
||||||
|
|
||||||
- **To the desktop:** in gaming mode, open the Steam menu and choose
|
- **To the desktop:** in gaming mode, open the Steam menu and choose
|
||||||
**Power > Switch to Desktop**.
|
**Power > Switch to Desktop**.
|
||||||
- **Back to gaming mode:** double-click **Return to Gaming Mode** on the
|
- **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.
|
- After a restart you always start in gaming mode.
|
||||||
|
|
||||||
Prefer to decide yourself where your PC starts? Run one of these in Konsole:
|
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
|
freshly installed driver often needs a reboot. Still dark? See
|
||||||
[Front LED bar](#front-led-bar-steam-machine) under technical details.
|
[Front LED bar](#front-led-bar-steam-machine) under technical details.
|
||||||
|
|
||||||
**Undo the SteamOS look:** pick another theme under **System Settings >
|
**Undo something:** run the wizard again and untick it.
|
||||||
Colors & Themes > Global Theme**.
|
|
||||||
|
|
||||||
To remove everything the script set up, see
|
|
||||||
[Removing everything](#removing-everything).
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Technical details
|
## 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
|
At startup every component checks whether it is on (`*_status` in `lib/`).
|
||||||
off everything that asks for a password or another user, per user and
|
You choose; the wizard then turns off what you unticked (in reverse order)
|
||||||
without touching system files: `action/lock_screen`, `switch_user` and
|
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
|
`start_new_session` restrictions in `kdeglobals`, no automatic locking
|
||||||
(`kscreenlockerrc`), Meta+L and Ctrl+Alt+Del unbound, and the launcher shows
|
(`kscreenlockerrc`), Meta+L and Ctrl+Alt+Del unbound, and the launcher shows
|
||||||
only Sleep / Restart / Shut Down (kickoff `primaryActions=3`), which hides
|
only Sleep / Restart / Shut Down (kickoff `primaryActions=3`), which hides
|
||||||
the Session dropdown with Log Out. (Restricting `action/logout` would also
|
the Session dropdown with Log Out. (Restricting `action/logout` would also
|
||||||
hide Restart and Shut Down.) Answering no restores KDE's defaults and keeps
|
hide Restart and Shut Down.) Turning it off restores all of that and moves
|
||||||
the current login manager.
|
the conversion back to plasma-login-manager.
|
||||||
|
|
||||||
**SDDM** is what SteamOS uses, and CachyOS's
|
**SDDM** is what SteamOS uses, and CachyOS's `steam-set-session` supports it
|
||||||
`steam-set-session` supports it directly: it writes
|
directly: it writes `/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM
|
||||||
`/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM honours. The script
|
honours. The script installs and enables `sddm` (active from the next boot),
|
||||||
installs and enables `sddm` (disabling the current display manager, active
|
writes `User=`, `Session=` and `Relogin=true` to
|
||||||
from the next boot), writes `User=`, `Session=` and `Relogin=true` to
|
|
||||||
`/etc/sddm.conf.d/10-gamescope-autologin.conf`, and removes any
|
`/etc/sddm.conf.d/10-gamescope-autologin.conf`, and removes any
|
||||||
`[Autologin]` from `/etc/sddm.conf` (read last, so it would override both).
|
`[Autologin]` from `/etc/sddm.conf` (read last, so it would override both).
|
||||||
No sync bridge or sudoers rule is needed; the shortcut just runs
|
No sync bridge or sudoers rule is needed; the shortcut just runs
|
||||||
`steamos-session-select gamescope`, which logs out, and `Relogin=true`
|
`steamos-session-select gamescope`, which logs out, and `Relogin=true` logs
|
||||||
logs straight back in to gamescope. Switching an existing
|
straight back in to gamescope.
|
||||||
plasma-login-manager setup to SDDM removes the sync bridge.
|
|
||||||
|
|
||||||
Keeping **plasma-login-manager** (CachyOS's default since March 2026) needs
|
Without single user mode, the conversion uses **plasma-login-manager**
|
||||||
the workarounds below.
|
(CachyOS's default since March 2026), which needs the workarounds below.
|
||||||
|
|
||||||
### Why this is needed (plasma-login-manager)
|
### 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
|
and installs a small systemd path watcher that copies whatever CachyOS's
|
||||||
tools write to the conf.d fragment into the base config.
|
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
|
- installs missing packages: `gamescope-session-cachyos`, `steam`,
|
||||||
to switch to SDDM (see above).
|
`mangohud`, `xterm`, `ttf-liberation`, `wqy-zenhei`, `plasma-keyboard`;
|
||||||
2. Installs missing packages: `gamescope-session-cachyos`, `steam`,
|
- *SDDM (single user mode):* installs/enables SDDM and writes its autologin
|
||||||
`mangohud`, `xterm`, `ttf-liberation`, `wqy-zenhei`, `plasma-keyboard`.
|
config;
|
||||||
3. *SDDM:* installs/enables SDDM and writes its autologin config.
|
- *plasma-login-manager:* creates `/etc/plasmalogin.conf.d`, backs up and
|
||||||
*plasma-login-manager:* creates `/etc/plasmalogin.conf.d`, backs up and rewrites the
|
rewrites the `[Autologin]` section of `/etc/plasmalogin.conf`, removes
|
||||||
`[Autologin]` section of `/etc/plasmalogin.conf`, and removes stray
|
stray `zzz-steamos-autologin*.conf` files from manual troubleshooting
|
||||||
`zzz-steamos-autologin*.conf` files from manual troubleshooting (never
|
(never `zz-steamos-autologin.conf`, which CachyOS's tools own), and
|
||||||
`zz-steamos-autologin.conf`, which CachyOS's tools own).
|
installs `/usr/local/bin/sync-steamos-session.sh` plus
|
||||||
4. *plasma-login-manager only:* installs `/usr/local/bin/sync-steamos-session.sh` plus
|
`sync-steamos-session.path`/`.service`;
|
||||||
`sync-steamos-session.path`/`.service`, which keep the base config in sync
|
- `KWIN_IM_SHOW_ALWAYS=1` for the virtual keyboard and a
|
||||||
with session switches.
|
`steam-desktop-autostart` systemd user service that starts Steam silently
|
||||||
5. Sets up Steam for the desktop: `STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"`
|
in Plasma only;
|
||||||
(gamepad UI with Steam Deck glyphs), `KWIN_IM_SHOW_ALWAYS=1` for the
|
- the **Return to Gaming Mode** shortcut; on plasma-login-manager with a
|
||||||
virtual keyboard, and a `steam-desktop-autostart` systemd user service
|
narrow sudoers rule (`/etc/sudoers.d/gamescope-session-switch`) so it can
|
||||||
that starts Steam silently in Plasma only.
|
restart the login manager without a password prompt.
|
||||||
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.
|
|
||||||
|
|
||||||
Re-running doesn't duplicate any settings. Every system file it modifies is
|
Turning it off restores `/etc/plasmalogin.conf` from its backup, removes the
|
||||||
backed up once, next to the original, with a `.bak-gamescope-wizard` suffix.
|
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
|
### 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
|
- Valve's SteamOS desktop defaults, merged into your own config: Noto Sans
|
||||||
fonts, no Xwayland input-permission prompt for Steam Input, the window
|
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
|
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
|
- 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;
|
scaled to fit, date below the time, and the SteamOS launcher icon;
|
||||||
- dark mode for GTK, libadwaita and portal-aware apps (Firefox, Flatpaks).
|
- 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)
|
### Front LED bar (Steam Machine)
|
||||||
|
|
||||||
Standard desktop kernels, including CachyOS's, lack Valve's `leds-valve`
|
The **Steam Machine support** component, only shown on Fremont hardware
|
||||||
driver, so the Steam Machine's front LED bar goes dark or "breathes". On
|
(DMI `Valve`/`Fremont`, or `OEM`/`F7F` on early units):
|
||||||
Fremont hardware (DMI `Valve`/`Fremont`) the script offers to:
|
|
||||||
|
|
||||||
- install an AUR helper (`yay`) if neither `yay` nor `paru` is present;
|
- installs an AUR helper (`yay`) if neither `yay` nor `paru` is present;
|
||||||
- install the kernel headers for every installed kernel;
|
- installs the kernel headers for every installed kernel;
|
||||||
- install `leds-valve-dkms-git` from the AUR, build it for the running
|
- installs `leds-valve-dkms-git` from the AUR - Valve's own driver from the
|
||||||
kernel, and load it at every boot (`/etc/modules-load.d/leds-valve.conf`);
|
SteamOS kernel - builds it for the running kernel, and loads it at every
|
||||||
- optionally install the experimental `openrgb-git`, which can drive the bar.
|
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
|
Turning it off removes all of that again (the AUR helper is kept).
|
||||||
the bar (e.g. download progress) in real SteamOS Game Mode.
|
|
||||||
|
|
||||||
The driver's Makefile builds against the running kernel, so after a kernel
|
The LEDs appear as `/sys/class/leds/valve-leds*`. The driver's Makefile
|
||||||
update, boot the new kernel and re-run the script (or
|
builds against the running kernel, so after a kernel update, boot the new
|
||||||
`sudo dkms install leds-valve-dkms/0.1 -k "$(uname -r)"`).
|
kernel and re-apply (`a` in the menu) or run
|
||||||
|
`sudo dkms install leds-valve-dkms/0.1 -k "$(uname -r)"`.
|
||||||
|
|
||||||
Troubleshooting:
|
Troubleshooting:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
dkms status
|
dkms status
|
||||||
ls /sys/class/leds | grep valve
|
ls -l /sys/class/leds/valve-leds*/
|
||||||
sudo dmesg | grep -i valve
|
sudo dmesg | grep -i valve
|
||||||
cat /var/lib/dkms/leds-valve-dkms/0.1/build/make.log
|
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
|
### Manual session control
|
||||||
@@ -255,48 +293,25 @@ immediately, which can turn into a loop - hence the Ctrl+Alt+F3 escape above.
|
|||||||
|
|
||||||
### Removing everything
|
### Removing everything
|
||||||
|
|
||||||
```bash
|
Run the wizard and untick everything. Afterwards the PC boots to the normal
|
||||||
# SDDM: go back to plasma-login-manager
|
CachyOS login screen again; packages installed for the conversion (Steam,
|
||||||
sudo rm /etc/sddm.conf.d/10-gamescope-autologin.conf
|
gamescope-session, ...) stay installed.
|
||||||
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
|
|
||||||
```
|
|
||||||
|
|
||||||
### Project layout
|
### Project layout
|
||||||
|
|
||||||
| File | Responsibility |
|
| File | Responsibility |
|
||||||
|---|---|
|
|---|---|
|
||||||
| `setup-gamescope-boot.sh` | Entry point: user and sudo checks, step order, summary, reboot |
|
| `setup-gamescope-boot.sh` | Entry point: checks, menu, apply, summary, restart |
|
||||||
| `lib/common.sh` | Output helpers, yes/no prompts, backups |
|
| `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/packages.sh` | Required packages, AUR helper (yay/paru) |
|
||||||
| `lib/login-manager.sh` | SDDM or plasmalogin choice and autologin, session sync bridge |
|
| `lib/login-manager.sh` | SteamOS conversion: SDDM or plasmalogin autologin, sync bridge |
|
||||||
| `lib/steam-desktop.sh` | Steam in the Plasma session: gamepad UI flags, virtual keyboard, autostart |
|
| `lib/steam-desktop.sh` | Steam in the Plasma session; Steam Deck/Machine icons |
|
||||||
| `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/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/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).
|
Notes for contributors and AI coding agents are in [`AGENTS.md`](AGENTS.md).
|
||||||
|
|
||||||
|
|||||||
@@ -45,3 +45,25 @@ backup_file() {
|
|||||||
info "Backed up $f -> ${f}.bak-gamescope-wizard"
|
info "Backed up $f -> ${f}.bak-gamescope-wizard"
|
||||||
fi
|
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
|
||||||
|
}
|
||||||
@@ -68,3 +68,10 @@ EOF
|
|||||||
|
|
||||||
ok "Desktop shortcut created successfully."
|
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
@@ -1,58 +1,86 @@
|
|||||||
#!/bin/bash
|
#!/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.
|
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||||
|
|
||||||
BASE_CONF="/etc/plasmalogin.conf"
|
BASE_CONF="/etc/plasmalogin.conf"
|
||||||
|
|
||||||
choose_setup_mode() {
|
# The "SteamOS conversion" menu item: gaming mode boot, the Return to
|
||||||
# Step 1: one question decides both the login manager and locking.
|
# Gaming Mode shortcut and Steam on the desktop (lib/steam-desktop.sh).
|
||||||
# "Single user, no password" is SteamOS: SDDM (which CachyOS's session
|
gaming_status() {
|
||||||
# tools support directly, no workarounds) plus no lock screen, user
|
# Autologin into gamescope is configured for this user.
|
||||||
# switching or log out. Otherwise keep the current login manager
|
case "$(current_display_manager)" in
|
||||||
# (CachyOS's default plasma-login-manager gets the sync bridge below)
|
sddm) [[ -f /etc/sddm.conf.d/10-gamescope-autologin.conf ]] ;;
|
||||||
# and KDE's normal locking. Sets SINGLE_USER and LOGIN_MANAGER.
|
plasmalogin)
|
||||||
local current
|
sed -n '/^\[Autologin\]/,/^\[/p' "$BASE_CONF" 2>/dev/null | grep -qx "User=$USER" &&
|
||||||
current="$(systemctl show -p Id --value display-manager 2>/dev/null | sed 's/\.service$//')"
|
[[ -f /etc/systemd/system/sync-steamos-session.path ]] ;;
|
||||||
info "Detected display manager: ${current:-none}"
|
*) return 1 ;;
|
||||||
|
esac
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_login_manager() {
|
gaming_enable() {
|
||||||
# Steps 3-8 for whichever login manager was chosen in step 1.
|
# 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
|
case "$LOGIN_MANAGER" in
|
||||||
sddm)
|
sddm)
|
||||||
switch_to_sddm || exit 1
|
switch_to_sddm || return 1
|
||||||
configure_sddm_autologin
|
configure_sddm_autologin
|
||||||
remove_session_sync
|
remove_session_sync
|
||||||
;;
|
;;
|
||||||
plasmalogin)
|
plasmalogin)
|
||||||
|
remove_sddm_autologin
|
||||||
|
switch_to_plasmalogin || return 1
|
||||||
configure_autologin
|
configure_autologin
|
||||||
install_session_sync
|
install_session_sync
|
||||||
;;
|
;;
|
||||||
esac
|
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() {
|
switch_to_sddm() {
|
||||||
# Takes effect at the next boot; the running session is left alone.
|
# Takes effect at the next boot; the running session is left alone.
|
||||||
|
[[ "$(current_display_manager)" == sddm ]] && return 0
|
||||||
info "Installing and enabling SDDM..."
|
info "Installing and enabling SDDM..."
|
||||||
sudo pacman -S --needed --noconfirm sddm || { err "Installing sddm failed."; return 1; }
|
sudo pacman -S --needed --noconfirm sddm || { err "Installing sddm failed."; return 1; }
|
||||||
local current
|
local current
|
||||||
@@ -62,7 +90,6 @@ switch_to_sddm() {
|
|||||||
fi
|
fi
|
||||||
sudo systemctl enable -f sddm.service || { err "Enabling sddm failed."; return 1; }
|
sudo systemctl enable -f sddm.service || { err "Enabling sddm failed."; return 1; }
|
||||||
ok "SDDM is the login manager from the next boot on."
|
ok "SDDM is the login manager from the next boot on."
|
||||||
echo
|
|
||||||
}
|
}
|
||||||
|
|
||||||
configure_sddm_autologin() {
|
configure_sddm_autologin() {
|
||||||
|
|||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
#!/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.
|
||||||
|
REAPPLY=false
|
||||||
|
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
|
||||||
|
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
@@ -60,13 +60,8 @@ install_required_packages() {
|
|||||||
mapfile -t MISSING < <(pacman -T gamescope-session-cachyos steam mangohud xterm ttf-liberation wqy-zenhei plasma-keyboard)
|
mapfile -t MISSING < <(pacman -T gamescope-session-cachyos steam mangohud xterm ttf-liberation wqy-zenhei plasma-keyboard)
|
||||||
|
|
||||||
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
if [[ ${#MISSING[@]} -gt 0 ]]; then
|
||||||
info "Missing packages: ${MISSING[*]}"
|
info "Installing missing packages: ${MISSING[*]}"
|
||||||
if ask_yn "Install them now?"; then
|
sudo pacman -S --needed --noconfirm "${MISSING[@]}" || { err "Package installation failed."; return 1; }
|
||||||
sudo pacman -S --needed --noconfirm "${MISSING[@]}" || { err "Package installation failed."; exit 1; }
|
|
||||||
else
|
|
||||||
err "Cannot continue without these packages."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
else
|
else
|
||||||
ok "All required packages already installed."
|
ok "All required packages already installed."
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -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."
|
||||||
|
}
|
||||||
@@ -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
@@ -1,24 +1,14 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# Steam in the Plasma desktop session: gamepad UI args, virtual keyboard,
|
# 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.
|
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||||
|
|
||||||
setup_steam_desktop() {
|
steam_enable() {
|
||||||
# Step 8b: always runs.
|
|
||||||
info "Applying non-optional SteamOS environment & keyboard fixes..."
|
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"
|
steam_env_dir="$HOME/.config/environment.d"
|
||||||
mkdir -p "$steam_env_dir"
|
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
|
# 2. Prevent KDE Wayland from blocking the virtual keyboard overlay
|
||||||
echo "KWIN_IM_SHOW_ALWAYS=1" > "$steam_env_dir/99-kde-virtual-keyboard.conf"
|
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."
|
ok "Steam UI parameters and keyboard autostart deployed successfully."
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_single_user() {
|
steam_disable() {
|
||||||
# With SINGLE_USER (chosen in step 1), like SteamOS: one user and no
|
info "Removing Steam desktop autostart..."
|
||||||
# password prompts, since typing a password with a controller is
|
systemctl --user disable --now steam-desktop-autostart.service 2>/dev/null
|
||||||
# miserable. Hides Lock / Switch User / Log Out
|
rm -f "$HOME/.config/systemd/user/steam-desktop-autostart.service" \
|
||||||
# everywhere (launcher, Meta+L, Ctrl+Alt+Del) and never locks on idle or
|
"$HOME/.config/environment.d/99-kde-virtual-keyboard.conf"
|
||||||
# resume; "Return to Gaming Mode" is the way out of the desktop. Declining
|
systemctl --user daemon-reload
|
||||||
# restores KDE's defaults.
|
ok "Steam desktop settings removed (takes full effect at next login)."
|
||||||
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
set_launcher_leave_buttons() {
|
# "Steam Deck/Machine icons" menu item: Steam's gamepad UI in SteamOS 3
|
||||||
# "single": only Sleep / Restart / Shut Down buttons in the launcher, no
|
# mode, which shows Steam Deck button glyphs in gaming mode.
|
||||||
# Session dropdown (that's where Log Out lives). Restricting the
|
glyphs_status() {
|
||||||
# "logout" action instead would also hide Restart and Shut Down.
|
[[ -f "$HOME/.config/environment.d/99-gamescope-steam-glyphs.conf" ]]
|
||||||
# "default": Plasma's own buttons.
|
}
|
||||||
local mode="$1" applet
|
|
||||||
for applet in $(plasma_applets org.kde.plasma.kickoff); do
|
glyphs_enable() {
|
||||||
local -a grp=(--file plasma-org.kde.plasma.desktop-appletsrc --group Containments
|
local gs_env="$HOME/.config/gamescope-session/environment"
|
||||||
--group "${applet%%:*}" --group Applets --group "${applet#*:}"
|
mkdir -p "$HOME/.config/environment.d"
|
||||||
--group Configuration --group General)
|
echo 'STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"' > "$HOME/.config/environment.d/99-gamescope-steam-glyphs.conf"
|
||||||
if [[ "$mode" == single ]]; then
|
if [[ -d "$HOME/.config/gamescope-session" ]]; then
|
||||||
kwriteconfig6 "${grp[@]}" --key primaryActions 3
|
touch "$gs_env"
|
||||||
kwriteconfig6 "${grp[@]}" --key systemFavorites 'suspend,reboot,shutdown'
|
sed -i '/^STEAM_GAMEPADUI_ARGS=/d' "$gs_env"
|
||||||
else
|
echo 'STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"' >> "$gs_env"
|
||||||
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
|
|
||||||
fi
|
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)."
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/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.
|
# Sourced by setup-gamescope-boot.sh; not meant to be run on its own.
|
||||||
|
|
||||||
detect_valve_fremont() {
|
detect_valve_fremont() {
|
||||||
@@ -92,22 +93,49 @@ install_valve_led_driver() {
|
|||||||
warn " ls /sys/class/leds/ | grep valve ; sudo dmesg | grep -i valve"
|
warn " ls /sys/class/leds/ | grep valve ; sudo dmesg | grep -i valve"
|
||||||
fi
|
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() {
|
LED_UDEV_RULE="/etc/udev/rules.d/70-valve-leds-user.rules"
|
||||||
# Step 8c: only on Fremont hardware, and only if the user wants it.
|
|
||||||
if detect_valve_fremont; then
|
machine_available() { detect_valve_fremont; }
|
||||||
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
|
machine_status() {
|
||||||
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"
|
pacman -Qi leds-valve-dkms-git >/dev/null 2>&1 && pacman -Qi steamos-manager >/dev/null 2>&1
|
||||||
install_valve_led_driver || warn "LED driver setup ran into a problem - see errors above. Your gamescope boot setup above is unaffected."
|
}
|
||||||
fi
|
|
||||||
echo
|
machine_enable() {
|
||||||
fi
|
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
@@ -4,22 +4,22 @@
|
|||||||
|
|
||||||
merge_kde_config() {
|
merge_kde_config() {
|
||||||
# Merge a KDE-style ini file (e.g. one of Valve's /etc/xdg defaults) into
|
# 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.
|
# the distro's without touching package-owned files in /etc/xdg.
|
||||||
# Nested groups ("[A][B]") are supported; immutable "[$i]" groups and
|
# Nested groups ("[A][B]") are supported; immutable "[$i]" groups and
|
||||||
# comments are skipped.
|
# comments are skipped.
|
||||||
local src="$1" target="$2" line key value
|
local src="$1" target="$2" line key value
|
||||||
local -a groups=()
|
local groups=""
|
||||||
local skip=0
|
local skip=0
|
||||||
while IFS= read -r line || [[ -n "$line" ]]; do
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
||||||
line="${line%$'\r'}"
|
line="${line%$'\r'}"
|
||||||
[[ -z "$line" || "$line" == \#* ]] && continue
|
[[ -z "$line" || "$line" == \#* ]] && continue
|
||||||
if [[ "$line" == \[* ]]; then
|
if [[ "$line" == \[* ]]; then
|
||||||
skip=0; groups=()
|
skip=0; groups=""
|
||||||
[[ "$line" == *'[$'* ]] && { skip=1; continue; }
|
[[ "$line" == *'[$'* ]] && { skip=1; continue; }
|
||||||
local rest="$line"
|
local rest="$line"
|
||||||
while [[ "$rest" =~ ^\[([^]]*)\](.*)$ ]]; do
|
while [[ "$rest" =~ ^\[([^]]*)\](.*)$ ]]; do
|
||||||
groups+=("--group" "${BASH_REMATCH[1]}")
|
groups+="${groups:+|}${BASH_REMATCH[1]}"
|
||||||
rest="${BASH_REMATCH[2]}"
|
rest="${BASH_REMATCH[2]}"
|
||||||
done
|
done
|
||||||
continue
|
continue
|
||||||
@@ -27,7 +27,7 @@ merge_kde_config() {
|
|||||||
(( skip )) && continue
|
(( skip )) && continue
|
||||||
[[ "$line" == *=* ]] || continue
|
[[ "$line" == *=* ]] || continue
|
||||||
key="${line%%=*}"; value="${line#*=}"
|
key="${line%%=*}"; value="${line#*=}"
|
||||||
kwriteconfig6 --file "$target" "${groups[@]}" --key "$key" "$value"
|
kset theme "$target" "$groups" "$key" "$value"
|
||||||
done < "$src"
|
done < "$src"
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -113,15 +113,19 @@ install_vapor_theme() {
|
|||||||
[[ -f "${tmp_dir}/etc/xdg/$f" ]] && merge_kde_config "${tmp_dir}/etc/xdg/$f" "$f"
|
[[ -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
|
[[ -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
|
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
|
kset theme ~/.config/gtk-3.0/settings.ini Settings gtk-theme-name Vapor
|
||||||
kwriteconfig6 --file ~/.config/gtk-4.0/settings.ini --group Settings --key 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
|
# Vapor is a dark theme: tell GTK, libadwaita and portal-aware apps
|
||||||
# (Firefox, Steam's web views, Flatpaks) to use their dark variants too.
|
# (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
|
kset theme ~/.config/gtk-3.0/settings.ini Settings 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-4.0/settings.ini Settings gtk-application-prefer-dark-theme true
|
||||||
if command -v gsettings >/dev/null 2>&1; then
|
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 color-scheme prefer-dark 2>/dev/null || true
|
||||||
gsettings set org.gnome.desktop.interface gtk-theme Vapor 2>/dev/null || true
|
gsettings set org.gnome.desktop.interface gtk-theme Vapor 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
@@ -130,138 +134,52 @@ install_vapor_theme() {
|
|||||||
info "Cleaning up temporary files..."
|
info "Cleaning up temporary files..."
|
||||||
rm -rf "$tmp_dir"
|
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).
|
# Same launcher icon SteamOS sets (Vapor Deck plasmoid setup script).
|
||||||
local icon_name="distributor-logo-steamdeck"
|
for applet in $(plasma_applets org.kde.plasma.kickoff); do
|
||||||
local conf_file="$HOME/.config/plasma-org.kde.plasma.desktop-appletsrc"
|
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
|
# Wallpaper: Valve ships them as flat JPGs in usr/share/wallpapers.
|
||||||
warn "Could not find '${icon_name}' installed anywhere under ~/.local/share/icons or /usr/share/icons."
|
local wallpaper="$HOME/.local/share/wallpapers/Steam Deck Logo Default.jpg" containment
|
||||||
warn "The launcher icon will be set anyway, but it may show as a broken icon until the file is installed."
|
if [[ -f "$wallpaper" ]]; then
|
||||||
fi
|
for containment in $(grep -oP '^\[Containments\]\[\K[0-9]+(?=\]$)' ~/.config/"$appletsrc" 2>/dev/null); do
|
||||||
|
grep -q "^\[Containments\]\[$containment\]\[Wallpaper\]" ~/.config/"$appletsrc" || continue
|
||||||
if [[ -f "$conf_file" ]]; then
|
kset theme "$appletsrc" "Containments|$containment|Wallpaper|org.kde.image|General" Image "file://$wallpaper"
|
||||||
info "Looking for the Application Launcher applet (Kickoff/Kicker) to set the custom icon..."
|
|
||||||
local matches=()
|
|
||||||
local current_section=""
|
|
||||||
local current_containment=""
|
|
||||||
local current_applet=""
|
|
||||||
|
|
||||||
while IFS= read -r line; do
|
|
||||||
if [[ "$line" =~ ^\[Containments\]\[([0-9]+)\]\[Applets\]\[([0-9]+)\]$ ]]; then
|
|
||||||
current_containment="${BASH_REMATCH[1]}"
|
|
||||||
current_applet="${BASH_REMATCH[2]}"
|
|
||||||
current_section="applet_root"
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if [[ "$line" =~ ^\[ ]]; then
|
|
||||||
current_section=""
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
if [[ "$current_section" == "applet_root" && "$line" =~ ^plugin=(org\.kde\.plasma\.(kickoff|kicker|simplemenu|homerun|application-menu))$ ]]; then
|
|
||||||
matches+=( "${current_containment}:${current_applet}:${BASH_REMATCH[1]}" )
|
|
||||||
current_section=""
|
|
||||||
fi
|
|
||||||
done < "$conf_file"
|
|
||||||
|
|
||||||
if [[ ${#matches[@]} -gt 0 ]]; then
|
|
||||||
for m in "${matches[@]}"; do
|
|
||||||
IFS=':' read -r containment applet plugin <<< "$m"
|
|
||||||
info "Setting launcher icon on Containment $containment / Applet $applet ($plugin)..."
|
|
||||||
kwriteconfig6 \
|
|
||||||
--file "$conf_file" \
|
|
||||||
--group Containments --group "$containment" \
|
|
||||||
--group Applets --group "$applet" \
|
|
||||||
--group Configuration --group General \
|
|
||||||
--key icon "$icon_name"
|
|
||||||
ok "Icon set to '$icon_name'."
|
|
||||||
done
|
|
||||||
else
|
|
||||||
warn "No compatible Application Launcher applet found in panel config. Skipping icon assignment."
|
|
||||||
fi
|
|
||||||
else
|
|
||||||
warn "$conf_file not found. Skipping menu icon configuration."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# SteamOS scales system tray icons to the panel height. Valve's setup
|
|
||||||
# script targets Plasma 5's separate tray containment; in Plasma 6 the
|
|
||||||
# setting lives on the systemtray applet itself.
|
|
||||||
if [[ -f "$conf_file" ]]; then
|
|
||||||
local tray
|
|
||||||
for tray in $(awk '
|
|
||||||
/^\[Containments\]\[[0-9]+\]\[Applets\]\[[0-9]+\]$/ { split($0, p, /[][]+/); sect = p[3] ":" p[5] }
|
|
||||||
/^\[/ && !/\]\[Applets\]\[[0-9]+\]$/ { sect = "" }
|
|
||||||
/^plugin=org\.kde\.plasma\.systemtray$/ && sect != "" { print sect }
|
|
||||||
' "$conf_file"); do
|
|
||||||
kwriteconfig6 --file "$conf_file" --group Containments --group "${tray%%:*}" \
|
|
||||||
--group Applets --group "${tray#*:}" --group General \
|
|
||||||
--key scaleIconsToFit true
|
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# SteamOS shows the date below the time in the panel clock.
|
# Vapor color scheme and Plasma style; the theme's own defaults use
|
||||||
if [[ -f "$conf_file" ]]; then
|
# breeze-dark icons (there is no "Vapor" icon theme).
|
||||||
local clock
|
kset theme kdeglobals KDE LookAndFeelPackage com.valve.vapor.desktop
|
||||||
for clock in $(awk '
|
kset theme kdeglobals Icons Theme breeze-dark
|
||||||
/^\[Containments\]\[[0-9]+\]\[Applets\]\[[0-9]+\]$/ { split($0, p, /[][]+/); sect = p[3] ":" p[5] }
|
kset theme kdeglobals General ColorScheme Vapor
|
||||||
/^\[/ && !/\]\[Applets\]\[[0-9]+\]$/ { sect = "" }
|
kset theme plasmarc Theme name Vapor
|
||||||
/^plugin=org\.kde\.plasma\.digitalclock$/ && sect != "" { print sect }
|
|
||||||
' "$conf_file"); do
|
|
||||||
kwriteconfig6 --file "$conf_file" --group Containments --group "${clock%%:*}" \
|
|
||||||
--group Applets --group "${clock#*:}" --group Configuration --group Appearance \
|
|
||||||
--key dateDisplayFormat BelowTime
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Wallpaper
|
# SteamOS uses a solid, full-width bottom panel at Plasma's stock 44px
|
||||||
# Valve ships the wallpapers as flat JPGs in usr/share/wallpapers.
|
# height (CachyOS ships a floating 30px one).
|
||||||
local wallpaper_path="$HOME/.local/share/wallpapers/Steam Deck Logo Default.jpg"
|
|
||||||
|
|
||||||
if [[ -f "$wallpaper_path" ]]; then
|
|
||||||
info "Applying official Steam Deck Vapor wallpaper via D-Bus script..."
|
|
||||||
local dbus_cmd="
|
|
||||||
var allDesktops = desktops();
|
|
||||||
for (var i = 0; i < allDesktops.length; i++) {
|
|
||||||
var d = allDesktops[i];
|
|
||||||
d.currentConfigGroup = ['Wallpaper', 'org.kde.image', 'General'];
|
|
||||||
d.writeConfig('Image', 'file://${wallpaper_path}');
|
|
||||||
}
|
|
||||||
"
|
|
||||||
if ! pgrep -u "$USER" -x plasmashell >/dev/null; then
|
|
||||||
:
|
|
||||||
elif command -v qdbus6 >/dev/null 2>&1; then
|
|
||||||
qdbus6 org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "$dbus_cmd" >/dev/null 2>&1 || true
|
|
||||||
else
|
|
||||||
qdbus org.kde.plasmashell /PlasmaShell org.kde.PlasmaShell.evaluateScript "$dbus_cmd" >/dev/null 2>&1 || true
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -f "$conf_file" ]]; then
|
|
||||||
local desktop_sections=$(grep -E '^\[Containments\]\[[0-9]+\]$' "$conf_file" || true)
|
|
||||||
while read -r section; do
|
|
||||||
if [[ -n "$section" ]]; then
|
|
||||||
local clean_sec=$(echo "$section" | tr -d '[]')
|
|
||||||
kwriteconfig6 --file "$conf_file" --group "$clean_sec" --group Wallpaper --group org.kde.image --group General --key Image "file://${wallpaper_path}"
|
|
||||||
fi
|
|
||||||
done <<< "$desktop_sections"
|
|
||||||
fi
|
|
||||||
ok "Wallpaper path pushed to session config."
|
|
||||||
else
|
|
||||||
warn "Could not find extracted Vapor wallpaper file. Skipping."
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Activate the Vapor global theme and color scheme, then restart
|
|
||||||
# plasmashell once so it picks everything up (restarting first races
|
|
||||||
# with the settings being written). The theme's own defaults use
|
|
||||||
# breeze-dark icons; there is no "Vapor" icon theme.
|
|
||||||
kwriteconfig6 --file kdeglobals --group Icons --key Theme "breeze-dark"
|
|
||||||
kwriteconfig6 --file kdeglobals --group General --key ColorScheme "Vapor"
|
|
||||||
kwriteconfig6 --file plasmarc --group Theme --key name "Vapor"
|
|
||||||
|
|
||||||
# Same panel change for the next login, in case Plasma isn't running now.
|
|
||||||
local panel
|
local panel
|
||||||
for panel in $(grep -oP '^\[PlasmaViews\]\[Panel \K[0-9]+(?=\]$)' ~/.config/plasmashellrc 2>/dev/null); do
|
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
|
kset theme plasmashellrc "PlasmaViews|Panel $panel" floating 0
|
||||||
kwriteconfig6 --file plasmashellrc --group PlasmaViews --group "Panel $panel" --group Defaults --key thickness 44
|
kset theme plasmashellrc "PlasmaViews|Panel $panel|Defaults" thickness 44
|
||||||
done
|
done
|
||||||
|
|
||||||
gtk-update-icon-cache -f -t ~/.local/share/icons/hicolor 2>/dev/null || true
|
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
|
# Live changes need a running Plasma session; otherwise they are picked
|
||||||
# up from the config files above at the next Plasma login.
|
# 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..."
|
info "Applying the theme to the running Plasma session..."
|
||||||
lookandfeeltool -a com.valve.vapor.desktop >/dev/null 2>&1 || true
|
lookandfeeltool -a com.valve.vapor.desktop >/dev/null 2>&1 || true
|
||||||
# lookandfeeltool leaves the distro's color scheme active; apply it explicitly.
|
# lookandfeeltool leaves the distro's color scheme active; apply it explicitly.
|
||||||
plasma-apply-colorscheme Vapor >/dev/null 2>&1 || true
|
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.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
|
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
|
else
|
||||||
info "No running Plasma session; the theme applies at your next desktop login."
|
info "No running Plasma session; the theme applies at your next desktop login."
|
||||||
fi
|
fi
|
||||||
|
ok "SteamOS desktop look installed."
|
||||||
ok "Vapor theme assets installed. Apply it under System Settings > Appearance"
|
|
||||||
ok "> Global Theme > Vapor (Steam Deck), next time you're in a Plasma session."
|
|
||||||
}
|
}
|
||||||
|
|
||||||
setup_vapor_theme() {
|
theme_status() {
|
||||||
# Step 9 (optional): ask, make sure curl/zstd exist, then install.
|
[[ "$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage)" == com.valve.vapor.desktop ]]
|
||||||
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
|
theme_enable() {
|
||||||
warn "curl not found, installing it first..."
|
command -v curl >/dev/null 2>&1 || sudo pacman -S --needed --noconfirm curl
|
||||||
sudo pacman -S --needed --noconfirm curl
|
command -v unzstd >/dev/null 2>&1 || sudo pacman -S --needed --noconfirm zstd
|
||||||
fi
|
# Stop plasmashell first: the panel and wallpaper edits go to files it
|
||||||
if ! command -v unzstd >/dev/null 2>&1; then
|
# would otherwise overwrite with its in-memory config on exit.
|
||||||
warn "zstd not found, installing it first..."
|
stop_plasmashell_for_edit
|
||||||
sudo pacman -S --needed --noconfirm zstd
|
install_vapor_theme
|
||||||
fi
|
local rc=$?
|
||||||
install_vapor_theme || warn "Vapor theme install ran into a problem - see errors above. Your gamescope boot setup above is unaffected."
|
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
|
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
@@ -2,46 +2,21 @@
|
|||||||
#
|
#
|
||||||
# setup-gamescope-boot.sh
|
# setup-gamescope-boot.sh
|
||||||
#
|
#
|
||||||
# Wizard to configure a CachyOS (KDE Plasma + plasma-login-manager) install
|
# Wizard that makes a CachyOS (KDE Plasma) install behave like SteamOS:
|
||||||
# to always boot into a Steam Deck-style gamescope session, with the
|
# boot into a Steam Deck-style gamescope session, switch to the Plasma
|
||||||
# ability to switch to Plasma desktop and back, Deck-style, and have it
|
# desktop and back, and reset to gamescope on the next boot/logout.
|
||||||
# reset to gamescope on the next boot/logout.
|
|
||||||
#
|
#
|
||||||
# Covers three real bugs found on CachyOS as of Sep 2026:
|
# It opens with a menu that detects which components are on and turns
|
||||||
# 1. steam-set-session never writes User= to plasmalogin's autologin
|
# them on or off to match what the user picks; turning one off restores
|
||||||
# config, so plasma-login-manager never actually autologs in.
|
# what was there before (system files from .bak-gamescope-wizard backups,
|
||||||
# 2. steam-set-session fails outright if /etc/plasmalogin.conf.d is
|
# KDE settings from the undo journal in lib/state.sh). Components live in
|
||||||
# missing, breaking "Switch to Desktop" from inside gamescope.
|
# lib/, see README.md. Safe to re-run.
|
||||||
# 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.
|
|
||||||
|
|
||||||
set -uo pipefail
|
set -uo pipefail
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
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
|
# shellcheck source=/dev/null
|
||||||
source "$SCRIPT_DIR/lib/$lib.sh"
|
source "$SCRIPT_DIR/lib/$lib.sh"
|
||||||
done
|
done
|
||||||
@@ -49,92 +24,59 @@ 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}"
|
||||||
echo "This sets your machine up to always boot into gamescope (like SteamOS),"
|
echo "Turn the SteamOS-style parts on or off. The menu shows what is on now;"
|
||||||
echo "with working Switch-to-Desktop and switch-back, surviving reboots."
|
echo "anything you turn off is put back the way it was."
|
||||||
echo
|
|
||||||
|
|
||||||
if ! command -v pacman >/dev/null 2>&1; then
|
if ! command -v pacman >/dev/null 2>&1; then
|
||||||
err "This doesn't look like an Arch/CachyOS system (no pacman found). Aborting."
|
err "This doesn't look like an Arch/CachyOS system (no pacman found). Aborting."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ask for the sudo password once up front and keep it fresh, instead of
|
# Everything per-user (autologin user, Steam, theme, shortcut) is for the
|
||||||
# prompting at random points during the run.
|
# 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
|
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 &
|
while true; do sudo -n true; sleep 50; kill -0 "$$" 2>/dev/null || exit; done 2>/dev/null &
|
||||||
|
|
||||||
TARGET_USER="${SUDO_USER:-$USER}"
|
apply_changes
|
||||||
read -rp "$(echo -e "${c_bold}Which user should autologin into gamescope?${c_reset} [${TARGET_USER}] ")" input_user
|
|
||||||
TARGET_USER="${input_user:-$TARGET_USER}"
|
|
||||||
|
|
||||||
if ! id "$TARGET_USER" >/dev/null 2>&1; then
|
echo
|
||||||
err "User '$TARGET_USER' does not exist on this system."
|
detect_components
|
||||||
exit 1
|
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
|
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
|
echo
|
||||||
|
|
||||||
choose_setup_mode
|
# Login manager changes only take effect after a restart.
|
||||||
echo
|
if [[ " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " == *" gaming "* || " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " == *" single "* ]]; then
|
||||||
|
if ask_yn "Restart now so the changes take effect?" n; then
|
||||||
install_required_packages
|
sudo reboot
|
||||||
echo
|
else
|
||||||
|
info "Restart whenever you're ready."
|
||||||
setup_login_manager
|
fi
|
||||||
|
|
||||||
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."
|
|
||||||
fi
|
fi
|
||||||
Reference in new issue
Block a user