Compare commits

...
16 Commits
Author SHA1 Message Date
theupriser 93a26a0d16 Merge pull request #75 from theupriser/chore/tests-to-dev
Sync git.upriser.nl mirror / sync (push) Skipped
Single-file build / bundle (push) Successful in 15s
chore: the tests live in steamify-cachyos-dev; changelog hashes for 2.11.0
2026-10-02 14:38:12 +02:00
theupriser f05078d932 docs: changelog hashes for 2.11.0, and the tests move
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 14:37:42 +02:00
theupriser 4d387b2f86 chore: the tests live in steamify-cachyos-dev, remove tests/ 2026-10-02 14:37:02 +02:00
theupriser 19089a1eda Merge pull request #74 from theupriser/feature/silent-steam-start
Sync git.upriser.nl mirror / sync (push) Skipped
Single-file build / bundle (push) Successful in 12s
feat: Start Steam silently in desktop mode (opt-in), Steam Deck icons under the conversion, installer fixes
2026-10-02 14:34:56 +02:00
theupriser 2f7b53f64b fix: the Steam Machine serial number step is not fatal in the installer chroot (read-only /sys); the tmpfiles.d file applies at boot
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 12:22:20 +02:00
theupriser bd8f387cf5 fix: STEAMIFY_NO_DOWNLOAD finds the bundle through BASH_SOURCE (a bundle has no SCRIPT_DIR: the install failed with an unbound variable)
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 11:38:25 +02:00
theupriser 45a23aff34 feat: STEAMIFY_NO_DOWNLOAD: the first login runs the ISO's Steamify bundle instead of the newest release
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 11:11:18 +02:00
theupriser f3810a9fdd fix: the SteamOS theme drops the blank Discover pin from the taskbar (also on the first login of an ISO install)
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 10:52:04 +02:00
theupriser 188799e951 fix: the SteamOS conversion no longer lists the silent start in what it changes (it is its own opt-in option)
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 10:43:25 +02:00
theupriser 079e725ba8 feat: "Start Steam silently in desktop mode" is opt-in (it was always on); an existing systemd unit counts as on and is migrated by the update
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 10:16:40 +02:00
theupriser 7869b472be feat: Steam Deck/Machine icons is a sub-option of the SteamOS conversion (it only changes gaming mode)
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 10:15:59 +02:00
theupriser fbdad5a785 feat: the silent option is Steam's own autostart entry (~/.config/autostart/steam.desktop with -silent), so its "Run Steam when my computer starts" follows it; the systemd unit is gone
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 09:28:03 +02:00
theupriser 349492423e feat: "Start Steam silently in desktop mode" is always shown, also on a Steam Machine
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-02 09:10:26 +02:00
theupriser 613149a807 docs: changelog for the silent start option
Sync git.upriser.nl mirror / sync (push) Skipped
2026-10-01 23:04:18 +02:00
theupriser 2e51d1d3f3 feat: "Start Steam silently" sub-option for the SteamOS conversion (silent) and Gaming on NVIDIA (nvsilent) 2026-10-01 23:04:18 +02:00
theupriser e5110ada40 chore: bump VERSION to 2.11.0 2026-10-01 23:02:37 +02:00
18 changed files with 177 additions and 464 deletions

No files matched your search

+9
View File
@@ -5,6 +5,15 @@ All notable changes, per version and per commit. Versions follow
`steamify.sh`. Versions before 0.7.0 were numbered afterwards, `steamify.sh`. Versions before 0.7.0 were numbered afterwards,
one per merged pull request. one per merged pull request.
## 2.11.0 - 2026-10-01
- `2e51d1d`, `3494924`, `fbdad5a`, `079e725`, `188799e` **feat: "Start Steam silently" sub-option: under the SteamOS conversion (`silent`, opt-in now: it was always on before; an existing one is moved from its systemd unit to the autostart entry by the "update") and under Gaming on NVIDIA (`nvsilent`, opt-in, not together with Big Picture); the SteamOS one is called "Start Steam silently in desktop mode" and is always shown, also on a Steam Machine; it is Steam's own autostart entry (`~/.config/autostart/steam.desktop`), so Steam's setting "Run Steam when my computer starts" follows it**
- `2f7b53f` **fix: the Steam Machine's serial number step no longer fails inside the ISO's installer (`/sys` is read-only in its chroot; the tmpfiles.d file applies at the next boot anyway), which made `machine` report an error and the install log end with `exit: 1`**
- `45a23af`, `bd8f387` **feat: `STEAMIFY_NO_DOWNLOAD` (the ISO's `steamify.nodownload` kernel parameter): the installed system's first login runs the Steamify bundle of the ISO instead of downloading the newest release (to test an unreleased Steamify)**
- `f3810a9` **fix: the SteamOS theme no longer leaves a blank Discover pin in the taskbar (Plasma's default taskbar pins Discover, which CachyOS doesn't install); the taskbar gets CachyOS's own pins (System Settings, files, browser), also on the ISO's first login**
- `7869b47` **feat: "Steam Deck/Machine icons" (`glyphs`) is a sub-option of the SteamOS conversion, like "Start Steam silently in desktop mode": it only changes gaming mode**
- `4d387b2` **chore: the Steamify unit tests (`controllers-test.sh`, `nvidia-test.sh`) and the NVIDIA hardware test live in steamify-cachyos-dev (`tests/`) now; `tests/` is removed here**
## 2.10.0 - 2026-10-01 ## 2.10.0 - 2026-10-01
- `d6db4f6` **feat: "Gaming on NVIDIA" (nvidia) replaces the SteamOS conversion on PCs with an NVIDIA GPU, where gamescope's gaming mode shows a corrupted picture (NVIDIA bug 5240452): Steam is installed when missing and starts at login on the Plasma desktop; the sub-option "Steam starts in Big Picture" (bigpicture) starts it in Big Picture, unticked in its normal window, on an empty Plasma session so windows of the last session don't cover it. On a supported card (RTX 20 series or newer) it also sets the NVIDIA kernel parameters and early modules. The conversion and its options are hidden there unless already on** - `d6db4f6` **feat: "Gaming on NVIDIA" (nvidia) replaces the SteamOS conversion on PCs with an NVIDIA GPU, where gamescope's gaming mode shows a corrupted picture (NVIDIA bug 5240452): Steam is installed when missing and starts at login on the Plasma desktop; the sub-option "Steam starts in Big Picture" (bigpicture) starts it in Big Picture, unticked in its normal window, on an empty Plasma session so windows of the last session don't cover it. On a supported card (RTX 20 series or newer) it also sets the NVIDIA kernel parameters and early modules. The conversion and its options are hidden there unless already on**
+17 -11
View File
@@ -108,9 +108,11 @@ tools write to the conf.d fragment into the base config.
(never `zz-steamos-autologin.conf`, which CachyOS's tools own), and (never `zz-steamos-autologin.conf`, which CachyOS's tools own), and
installs `/usr/local/bin/sync-steamos-session.sh` plus installs `/usr/local/bin/sync-steamos-session.sh` plus
`sync-steamos-session.path`/`.service`; `sync-steamos-session.path`/`.service`;
- `KWIN_IM_SHOW_ALWAYS=1` for the virtual keyboard and a - `KWIN_IM_SHOW_ALWAYS=1` for the virtual keyboard; the sub-option `silent`
`steam-desktop-autostart` systemd user service that starts Steam silently ("Start Steam silently in desktop mode", opt-in, always shown) writes
in Plasma only; `~/.config/autostart/steam.desktop` (the system steam.desktop with `-silent` in its Exec line). That is the
file Steam's own setting "Run Steam when my computer starts" creates and removes, so the setting shows it. An older
`steam-desktop-autostart` user unit is removed;
- the **Return to Gaming Mode** shortcut; on plasma-login-manager with a - the **Return to Gaming Mode** shortcut; on plasma-login-manager with a
narrow sudoers rule (`/etc/sudoers.d/gamescope-session-switch`) so it can narrow sudoers rule (`/etc/sudoers.d/gamescope-session-switch`) so it can
restart the login manager without a password prompt. restart the login manager without a password prompt.
@@ -124,7 +126,8 @@ The conversion also sets what Steam's System settings show, see
**Steam Deck/Machine icons:** `STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"` **Steam Deck/Machine icons:** `STEAM_GAMEPADUI_ARGS="-gamepadui -steamos3"`
in `~/.config/environment.d/` (and gamescope-session's own environment in `~/.config/environment.d/` (and gamescope-session's own environment
file), which makes Steam show Steam Deck button glyphs in gaming mode. file), which makes Steam show Steam Deck button glyphs in gaming mode. It is a sub-option of the SteamOS conversion (`gaming`):
it does nothing without gaming mode, ticking it ticks the conversion and turning the conversion off turns it off.
## SteamOS desktop look ## SteamOS desktop look
@@ -224,7 +227,7 @@ DKMS modules, built for every installed kernel, so `install_kernel_headers` (`li
headers first. A PC that already has the AUR's `xone-dkms-git` keeps it: it provides the same driver and conflicts with the repo's headers first. A PC that already has the AUR's `xone-dkms-git` keeps it: it provides the same driver and conflicts with the repo's
`xone-dkms`. Status is the three packages being installed. Off removes only what Steamify installed (state `xone-dkms`. Status is the three packages being installed. Off removes only what Steamify installed (state
`extended_controller_support`, `installed_pkgs`); the headers stay. The drivers load when the device shows up: the dongle is `extended_controller_support`, `installed_pkgs`); the headers stay. The drivers load when the device shows up: the dongle is
plugged in again, or the controller reconnected. `tests/controllers-test.sh` tests it with a stub `pacman`. plugged in again, or the controller reconnected. Its test is in steamify-cachyos-dev (`tests/controllers-test.sh`).
## Gaming on NVIDIA ## Gaming on NVIDIA
@@ -242,7 +245,8 @@ Steam at login): it installs `steam` when missing (recorded in state `nvidia`, r
unit `steamify-steam-autostart.service` (`services/`, `ExecStart=/usr/bin/steam @ARGS@`, Plasma only). Its sub-option unit `steamify-steam-autostart.service` (`services/`, `ExecStart=/usr/bin/steam @ARGS@`, Plasma only). Its sub-option
`bigpicture` ("Steam starts in Big Picture", ticked along with it) rewrites the unit with `-gamepadui` and sets `bigpicture` ("Steam starts in Big Picture", ticked along with it) rewrites the unit with `-gamepadui` and sets
`ksmserverrc [General] loginMode=emptySession` (`kset`, undone with `krevert bigpicture`), so windows of the last session `ksmserverrc [General] loginMode=emptySession` (`kset`, undone with `krevert bigpicture`), so windows of the last session
(Discord, a browser) aren't restored on top of Big Picture; unticked, Steam starts in its normal window. The PC always boots into the desktop: there is no gamescope session. Takes effect at the next (Discord, a browser) aren't restored on top of Big Picture; unticked, Steam starts in its normal window. The opt-in sub-option `nvsilent` ("Start Steam silently") rewrites the unit with `-silent`
(tray only); it and `bigpicture` exclude each other. The PC always boots into the desktop: there is no gamescope session. Takes effect at the next
login. login.
On a supported card (RTX 20 series or newer: not on chwd's legacy lists `/var/lib/chwd/ids/nvidia-*.ids`, the VRAM booster's On a supported card (RTX 20 series or newer: not on chwd's legacy lists `/var/lib/chwd/ids/nvidia-*.ids`, the VRAM booster's
@@ -255,7 +259,7 @@ and boot entries are rebuilt and checked for the parameters. The early-load drop
has the NVIDIA modules (mkinitcpio fails on a missing module, and `limine-mkinitcpio` then skips that kernel's boot entry): has the NVIDIA modules (mkinitcpio fails on a missing module, and `limine-mkinitcpio` then skips that kernel's boot entry):
a pacman hook (`/etc/pacman.d/hooks/85-steamify-nvidia-initramfs.hook`, after DKMS, before the initramfs is built) runs a pacman hook (`/etc/pacman.d/hooks/85-steamify-nvidia-initramfs.hook`, after DKMS, before the initramfs is built) runs
`/usr/local/libexec/steamify-nvidia-initramfs` at every kernel or driver change and decides again. Turning it off removes `/usr/local/libexec/steamify-nvidia-initramfs` at every kernel or driver change and decides again. Turning it off removes
all of it. `tests/nvidia-hardware-test.sh check|apply|visual` is for a real NVIDIA PC (writes `~/steamify-nvidia-report.txt`). `tests/nvidia-test.sh` tests it against a fake GPU, a stub `pacman` and `systemctl`, and a temp home. all of it. The tests are in steamify-cachyos-dev: `tests/nvidia-test.sh` (a fake GPU, a stub `pacman` and `systemctl`, a temp home) and `tests/nvidia-hardware-test.sh` (a real NVIDIA PC).
Tried and dropped (notes in steamify-cachyos-dev, `nvidia/HARDWARE-RESULTS.md`): a gamescope session that opens Big Picture in Plasma (it needed the `start-gamescope-session` Tried and dropped (notes in steamify-cachyos-dev, `nvidia/HARDWARE-RESULTS.md`): a gamescope session that opens Big Picture in Plasma (it needed the `start-gamescope-session`
command shadowed in `/usr/local/bin`, and showed the desktop for a few seconds, then a Steam window with a black border); command shadowed in `/usr/local/bin`, and showed the desktop for a few seconds, then a Steam window with a black border);
@@ -343,8 +347,7 @@ desktop through its desktop layout (A = Enter, B = Esc, Y = Space, X =
Steam's keyboard), in gaming mode as a gamepad. Steam's keyboard), in gaming mode as a gamepad.
Steam reads the list only at startup and writes it back on exit, so Steam is Steam reads the list only at startup and writes it back on exit, so Steam is
closed (`steam -shutdown`) for the edit and started again (through closed (`steam -shutdown`) for the edit and started again (`steam -silent`). That's refused in gaming
`steam-desktop-autostart.service` when it's there). That's refused in gaming
mode and when Steamify itself was started from Steam (`SteamGameId`), since mode and when Steamify itself was started from Steam (`SteamGameId`), since
closing Steam would end it. An entry for the start script that's already closing Steam would end it. An entry for the start script that's already
there (added by hand, or with the path from before 2.5.0) is updated, not there (added by hand, or with the path from before 2.5.0) is updated, not
@@ -489,7 +492,8 @@ In the home folder, everything is under `steamify`:
| `~/.local/share/steamify/bin/` | The shortcut's start scripts (`run-app`, `run-wizard`) and `steamify-notifier` | | `~/.local/share/steamify/bin/` | The shortcut's start scripts (`run-app`, `run-wizard`) and `steamify-notifier` |
| `~/.local/share/icons/hicolor/scalable/apps/steamify.svg` | The shortcut's icon | | `~/.local/share/icons/hicolor/scalable/apps/steamify.svg` | The shortcut's icon |
| `~/.local/share/applications/steamify-*.desktop` | The launcher entries | | `~/.local/share/applications/steamify-*.desktop` | The launcher entries |
| `~/.config/systemd/user/` | `steamify-update-check.*`, `steam-desktop-autostart.service` | | `~/.config/autostart/steam.desktop` | the `silent` option (Steam's "Run Steam when my computer starts") |
| `~/.config/systemd/user/` | `steamify-update-check.*` |
System-wide: `/usr/local/lib/steamify/` (kernel headers script), System-wide: `/usr/local/lib/steamify/` (kernel headers script),
`/usr/src/steamify-*` (DKMS modules), `/var/cache/steamify/kernel` (the old `/usr/src/steamify-*` (DKMS modules), `/var/cache/steamify/kernel` (the old
@@ -535,7 +539,9 @@ steamify.sh --defaults --list # what --defaults can se
item this PC can't use (e.g. `vram` without a VRAM region) is left off with item this PC can't use (e.g. `vram` without a VRAM region) is left off with
a warning. `--boot desktop` needs `gaming`. Unknown options, ids, `boot` or a warning. `--boot desktop` needs `gaming`. Unknown options, ids, `boot` or
`bios` in the list: exit code 1 before anything changes. What needs a `bios` in the list: exit code 1 before anything changes. What needs a
Plasma session waits for the first login (`lib/first-login.sh`). Plasma session waits for the first login (`lib/first-login.sh`). The same step (and the online theme path) replaces Plasma's default taskbar pins, which include Discover
(not installed on CachyOS: a blank icon), by CachyOS's own (`taskbar_drop_discover` in `lib/vapor-theme.sh`; skipped when Discover is
installed or the taskbar already has its own `launchers`).
With `Relogin=true`, a gamescope session that fails to start is restarted With `Relogin=true`, a gamescope session that fails to start is restarted
immediately, which can turn into a loop - see immediately, which can turn into a loop - see
+6 -1
View File
@@ -50,6 +50,7 @@ backend_status() {
items+="${items:+,}{\"id\":$(json_str "$c"),\"label\":$(json_str "${LABEL[$c]%%:*}")" items+="${items:+,}{\"id\":$(json_str "$c"),\"label\":$(json_str "${LABEL[$c]%%:*}")"
items+=",\"hint\":$(json_str "$( [[ "${LABEL[$c]}" == *:* ]] && echo "${LABEL[$c]#*: }")")" items+=",\"hint\":$(json_str "$( [[ "${LABEL[$c]}" == *:* ]] && echo "${LABEL[$c]#*: }")")"
items+=",\"kind\":\"$kind\",\"parent\":$(json_str "$parent")" items+=",\"kind\":\"$kind\",\"parent\":$(json_str "$parent")"
items+=",\"needs\":\"\""
items+=",\"on\":$( [[ "$now" == 1 ]] && echo true || echo false)" items+=",\"on\":$( [[ "$now" == 1 ]] && echo true || echo false)"
items+=",\"wanted\":$( [[ "${WANTED[$c]:-0}" == 1 ]] && echo true || echo false)" items+=",\"wanted\":$( [[ "${WANTED[$c]:-0}" == 1 ]] && echo true || echo false)"
items+=",\"update\":$(feature_outdated "$c" && echo true || echo false)" items+=",\"update\":$(feature_outdated "$c" && echo true || echo false)"
@@ -154,7 +155,11 @@ backend_apply() {
WANTED[boot]=0 WANTED[boot]=0
fi fi
[[ "${WANTED[bigpicture]:-0}" == 1 ]] && WANTED[nvidia]=1 [[ "${WANTED[bigpicture]:-0}" == 1 ]] && WANTED[nvidia]=1
[[ "${WANTED[nvidia]:-0}" == 0 ]] && WANTED[bigpicture]=0 [[ "${WANTED[nvsilent]:-0}" == 1 ]] && WANTED[nvidia]=1
[[ "${WANTED[bigpicture]:-0}" == 1 ]] && WANTED[nvsilent]=0
[[ "${WANTED[nvidia]:-0}" == 0 ]] && { WANTED[bigpicture]=0; WANTED[nvsilent]=0; }
[[ "${WANTED[silent]:-0}" == 1 || "${WANTED[glyphs]:-0}" == 1 ]] && component_available gaming && WANTED[gaming]=1
[[ "${WANTED[gaming]:-0}" == 0 ]] && { WANTED[silent]=0; WANTED[glyphs]=0; }
[[ "${WANTED[poweroff]:-0}" == 1 ]] && WANTED[machine]=1 [[ "${WANTED[poweroff]:-0}" == 1 ]] && WANTED[machine]=1
[[ "${WANTED[machine]:-0}" == 0 ]] && WANTED[poweroff]=0 [[ "${WANTED[machine]:-0}" == 0 ]] && WANTED[poweroff]=0
[[ "${WANTED[kpin]:-0}" == 1 ]] && WANTED[machine]=1 [[ "${WANTED[kpin]:-0}" == 1 ]] && WANTED[machine]=1
+17 -6
View File
@@ -7,13 +7,25 @@
FIRST_LOGIN_ENTRY="${XDG_CONFIG_HOME:-$HOME/.config}/autostart/steamify-first-login.desktop" FIRST_LOGIN_ENTRY="${XDG_CONFIG_HOME:-$HOME/.config}/autostart/steamify-first-login.desktop"
FIRST_LOGIN_SCRIPT="$STEAMIFY_BIN/first-login" FIRST_LOGIN_SCRIPT="$STEAMIFY_BIN/first-login"
FIRST_LOGIN_BUNDLE="$STEAMIFY_BIN/first-login-steamify.sh"
first_login_schedule() { first_login_schedule() {
# The newest release's Steamify runs at the first login. STEAMIFY_NO_DOWNLOAD (the ISO was started with
# steamify.nodownload, to test an unreleased Steamify): this very bundle runs instead.
# (Only a single-file bundle can be copied; SCRIPT_DIR doesn't exist in one.)
local run self="${BASH_SOURCE[0]:-}"
if [[ -n "${STEAMIFY_NO_DOWNLOAD:-}" && -f "$self" ]] && grep -q '^# Single-file build' "$self"; then
install_executable "$FIRST_LOGIN_BUNDLE" 755 < "$self"
run="bash \"$FIRST_LOGIN_BUNDLE\" --first-login; rm -f \"$FIRST_LOGIN_BUNDLE\""
else
run="curl -fsSL --max-time 30 \"$WIZARD_URL\" | bash -s -- --first-login"
fi
install_executable "$FIRST_LOGIN_SCRIPT" 755 << EOF2 install_executable "$FIRST_LOGIN_SCRIPT" 755 << EOF2
#!/bin/bash #!/bin/bash
# Installed by Steamify CachyOS: runs once, at the first desktop login. # Installed by Steamify CachyOS: runs once, at the first desktop login.
set -o pipefail set -o pipefail
curl -fsSL --max-time 30 "$WIZARD_URL" | bash -s -- --first-login mkdir -p ~/.cache
{ $run; } > ~/.cache/steamify-first-login.log 2>&1
rm -f "$FIRST_LOGIN_ENTRY" "\$0" rm -f "$FIRST_LOGIN_ENTRY" "\$0"
[[ -x "$WIZARD_APP_LAUNCHER" ]] && exec "$WIZARD_APP_LAUNCHER" [[ -x "$WIZARD_APP_LAUNCHER" ]] && exec "$WIZARD_APP_LAUNCHER"
EOF2 EOF2
@@ -31,10 +43,9 @@ first_login_run() {
[[ -n "$(plasma_applets org.kde.plasma.kickoff)" ]] && break [[ -n "$(plasma_applets org.kde.plasma.kickoff)" ]] && break
sleep 2 sleep 2
done done
if single_status; then stop_plasmashell_for_edit
stop_plasmashell_for_edit taskbar_drop_discover
single_launcher single_status && single_launcher
restart_plasmashell_if_stopped restart_plasmashell_if_stopped
fi
return 0 return 0
} }
+18 -8
View File
@@ -5,19 +5,19 @@
# Menu order. Components are turned on in this order and off in reverse; # Menu order. Components are turned on in this order and off in reverse;
# gaming must come first (single user builds on it). # gaming must come first (single user builds on it).
COMPONENTS=(gaming boot nvidia bigpicture theme glyphs single launcher steamgame notify extended_controller_support vram cec machine poweroff kpin hdmi bios) COMPONENTS=(gaming boot silent glyphs nvidia bigpicture nvsilent theme single launcher steamgame notify extended_controller_support vram cec machine poweroff kpin hdmi bios)
# One-off actions rather than on/off components: never preselected, never # One-off actions rather than on/off components: never preselected, never
# re-applied, not listed as on or off. # re-applied, not listed as on or off.
ACTIONS=(bios) ACTIONS=(bios)
# Sub-options, shown indented under their parent and only while it's ticked. # Sub-options, shown indented under their parent and only while it's ticked.
declare -A PARENT=([boot]=gaming [bigpicture]=nvidia [steamgame]=launcher [poweroff]=machine [kpin]=machine [hdmi]=machine [bios]=machine) declare -A PARENT=([boot]=gaming [silent]=gaming [glyphs]=gaming [bigpicture]=nvidia [nvsilent]=nvidia [steamgame]=launcher [poweroff]=machine [kpin]=machine [hdmi]=machine [bios]=machine)
# Never preselected on a first run: booting into the desktop is a choice, # Never preselected on a first run: booting into the desktop is a choice,
# gamescope is the default; HDMI-CEC is opt-in (it can wake the machine or # gamescope is the default; HDMI-CEC is opt-in (it can wake the machine or
# upset other devices on the TV, even on SteamOS), except on a Steam Machine, # upset other devices on the TV, even on SteamOS), except on a Steam Machine,
# which has CEC like on SteamOS. HDMI refresh boost needs someone at the # which has CEC like on SteamOS. HDMI refresh boost needs someone at the
# screen to confirm each step. Extended controller support builds kernel modules for # screen to confirm each step. Extended controller support builds kernel modules for
# every installed kernel: opt-in. # every installed kernel: opt-in.
NO_PRESELECT=(boot cec kpin hdmi extended_controller_support) NO_PRESELECT=(boot silent nvsilent cec kpin hdmi extended_controller_support)
# Feature versions: the Steamify version in which what a component's enable # Feature versions: the Steamify version in which what a component's enable
# sets up last changed; set it to the new VERSION whenever you change one. # sets up last changed; set it to the new VERSION whenever you change one.
# Each successful run records it (state "features"); a component that's on # Each successful run records it (state "features"); a component that's on
@@ -26,7 +26,7 @@ NO_PRESELECT=(boot cec kpin hdmi extended_controller_support)
# FEATURE_BASELINE. # FEATURE_BASELINE.
FEATURE_BASELINE=2.1.0 FEATURE_BASELINE=2.1.0
declare -A FEATURE_VERSION=( declare -A FEATURE_VERSION=(
[gaming]=2.9.0 [boot]=2.1.0 [nvidia]=2.10.0 [bigpicture]=2.10.0 [theme]=2.1.0 [glyphs]=2.1.0 [single]=2.1.0 [gaming]=2.9.0 [boot]=2.1.0 [silent]=2.11.0 [nvidia]=2.10.0 [bigpicture]=2.10.0 [nvsilent]=2.11.0 [theme]=2.1.0 [glyphs]=2.1.0 [single]=2.1.0
[launcher]=2.1.0 [cec]=2.7.0 [machine]=2.9.0 [poweroff]=2.2.0 [vram]=2.3.0 [notify]=2.5.0 [steamgame]=2.5.1 [extended_controller_support]=2.10.0 [launcher]=2.1.0 [cec]=2.7.0 [machine]=2.9.0 [poweroff]=2.2.0 [vram]=2.3.0 [notify]=2.5.0 [steamgame]=2.5.1 [extended_controller_support]=2.10.0
[kpin]=2.1.0 [hdmi]=2.1.0 [kpin]=2.1.0 [hdmi]=2.1.0
) )
@@ -35,6 +35,8 @@ declare -A LABEL=(
[gaming]="SteamOS conversion: boot into gaming mode, Steam on the desktop" [gaming]="SteamOS conversion: boot into gaming mode, Steam on the desktop"
[boot]="Boot into the desktop instead of gaming mode" [boot]="Boot into the desktop instead of gaming mode"
[nvidia]="Gaming on NVIDIA: Steam on the desktop, started at login" [nvidia]="Gaming on NVIDIA: Steam on the desktop, started at login"
[silent]="Start Steam silently in desktop mode: in the tray at login on the desktop, no window"
[nvsilent]="Start Steam silently: in the tray at login, no window (untick: Steam's normal window)"
[bigpicture]="Steam starts in Big Picture: the controller-friendly Steam (untick: Steam's normal window)" [bigpicture]="Steam starts in Big Picture: the controller-friendly Steam (untick: Steam's normal window)"
[theme]="Install SteamOS theme: Vapor look (cachyos-vapor)" [theme]="Install SteamOS theme: Vapor look (cachyos-vapor)"
[glyphs]="Install Steam Deck/Machine icons: Deck button icons in gaming mode" [glyphs]="Install Steam Deck/Machine icons: Deck button icons in gaming mode"
@@ -57,9 +59,9 @@ component_available() {
case "$1" in case "$1" in
# gamescope's own session is broken on NVIDIA: the conversion is replaced by "Gaming on NVIDIA" there (shown # gamescope's own session is broken on NVIDIA: the conversion is replaced by "Gaming on NVIDIA" there (shown
# anyway when it's already on, so it can be turned off). # anyway when it's already on, so it can be turned off).
gaming|boot|glyphs) ! nvidia_present || gaming_status ;; gaming|boot|silent|glyphs) ! nvidia_present || gaming_status ;;
nvidia) nvidia_available ;; nvidia) nvidia_available ;;
bigpicture) bigpicture_available ;; bigpicture|nvsilent) bigpicture_available ;;
machine|poweroff) machine_available ;; machine|poweroff) machine_available ;;
vram) vram_available ;; vram) vram_available ;;
# Steamify in the Steam library is for gaming mode's controller: not needed for Big Picture on the desktop (NVIDIA PCs; # Steamify in the Steam library is for gaming mode's controller: not needed for Big Picture on the desktop (NVIDIA PCs;
@@ -83,6 +85,8 @@ menu_visible() {
# Shown in the menu. A sub-option ("Boot into", the kernel pin) only # Shown in the menu. A sub-option ("Boot into", the kernel pin) only
# while its parent is ticked. # while its parent is ticked.
component_available "$1" || return 1 component_available "$1" || return 1
# Silent start is hidden while Steam starts in Big Picture.
[[ "$1" == nvsilent && "${WANTED[bigpicture]:-0}" == 1 ]] && return 1
[[ -z "${PARENT[$1]:-}" || "${WANTED[${PARENT[$1]}]:-0}" == 1 ]] [[ -z "${PARENT[$1]:-}" || "${WANTED[${PARENT[$1]}]:-0}" == 1 ]]
} }
@@ -282,7 +286,7 @@ defaults_list() {
[[ "$c" == cec ]] && machine_available && on=true [[ "$c" == cec ]] && machine_available && on=true
items+="${items:+,}{\"id\":$(json_str "$c"),\"label\":$(json_str "${LABEL[$c]%%:*}")" items+="${items:+,}{\"id\":$(json_str "$c"),\"label\":$(json_str "${LABEL[$c]%%:*}")"
items+=",\"hint\":$(json_str "$( [[ "${LABEL[$c]}" == *:* ]] && echo "${LABEL[$c]#*: }")")" items+=",\"hint\":$(json_str "$( [[ "${LABEL[$c]}" == *:* ]] && echo "${LABEL[$c]#*: }")")"
items+=",\"kind\":\"$kind\",\"parent\":$(json_str "${PARENT[$c]:-}"),\"on\":$on,\"selectable\":$sel}" items+=",\"kind\":\"$kind\",\"parent\":$(json_str "${PARENT[$c]:-}"),\"needs\":\"\",\"hideWhen\":$(json_str "$([[ "$c" == nvsilent ]] && echo bigpicture)"),\"on\":$on,\"selectable\":$sel}"
done done
printf '[%s]\n' "$items" printf '[%s]\n' "$items"
} }
@@ -299,7 +303,13 @@ toggle_component() {
if [[ "$c" == boot && "${WANTED[boot]}" == 1 ]]; then WANTED[gaming]=1; fi if [[ "$c" == boot && "${WANTED[boot]}" == 1 ]]; then WANTED[gaming]=1; fi
# Big Picture is opt-out: ticked along with "Gaming on NVIDIA". # Big Picture is opt-out: ticked along with "Gaming on NVIDIA".
if [[ "$c" == nvidia ]]; then WANTED[bigpicture]=${WANTED[nvidia]}; fi if [[ "$c" == nvidia ]]; then WANTED[bigpicture]=${WANTED[nvidia]}; fi
if [[ "$c" == bigpicture && "${WANTED[bigpicture]}" == 1 ]]; then WANTED[nvidia]=1; fi if [[ "$c" == bigpicture && "${WANTED[bigpicture]}" == 1 ]]; then WANTED[nvidia]=1; WANTED[nvsilent]=0; fi
# Silent and Big Picture exclude each other.
if [[ "$c" == nvsilent && "${WANTED[nvsilent]}" == 1 ]]; then WANTED[nvidia]=1; WANTED[bigpicture]=0; fi
if [[ "$c" == nvidia && "${WANTED[nvidia]}" == 0 ]]; then WANTED[nvsilent]=0; fi
if [[ "$c" == gaming && "${WANTED[gaming]}" == 0 ]]; then WANTED[silent]=0; WANTED[glyphs]=0; fi
if [[ "$c" == silent && "${WANTED[silent]}" == 1 ]]; then WANTED[gaming]=1; fi
if [[ "$c" == glyphs && "${WANTED[glyphs]}" == 1 ]]; then WANTED[gaming]=1; fi
# The power-off fix is opt-out: ticked along with Steam Machine support. # The power-off fix is opt-out: ticked along with Steam Machine support.
if [[ "$c" == machine ]]; then WANTED[poweroff]=${WANTED[machine]}; fi if [[ "$c" == machine ]]; then WANTED[poweroff]=${WANTED[machine]}; fi
if [[ "$c" == poweroff && "${WANTED[poweroff]}" == 1 ]]; then WANTED[machine]=1; fi if [[ "$c" == poweroff && "${WANTED[poweroff]}" == 1 ]]; then WANTED[machine]=1; fi
+19 -1
View File
@@ -57,7 +57,8 @@ nvidia_enable() {
state_set nvidia installed_pkgs steam state_set nvidia installed_pkgs steam
fi fi
# Keeps what the Big Picture option set up; a first run starts Steam normally. # Keeps what the Big Picture option set up; a first run starts Steam normally.
local unit_args=""; bigpicture_status && unit_args=-gamepadui local unit_args=""
if bigpicture_status; then unit_args=-gamepadui; elif nvsilent_status; then unit_args=-silent; fi
nvidia_write_unit "$unit_args" || return 1 nvidia_write_unit "$unit_args" || return 1
user_systemctl enable "$NVIDIA_UNIT" >/dev/null 2>&1 || { err "Enabling $NVIDIA_UNIT failed."; return 1; } user_systemctl enable "$NVIDIA_UNIT" >/dev/null 2>&1 || { err "Enabling $NVIDIA_UNIT failed."; return 1; }
nvidia_kernel_enable || return 1 nvidia_kernel_enable || return 1
@@ -96,6 +97,23 @@ bigpicture_disable() {
nvidia_write_unit "" && ok "Steam starts in its normal window at your next login." nvidia_write_unit "" && ok "Steam starts in its normal window at your next login."
} }
# Sub-option: Steam starts silently (tray only, no window). Big Picture and
# a silent start exclude each other (the menus untick one when the other is
# ticked); a first run with both gets Big Picture.
nvsilent_status() { grep -qs -- '-silent' "$(nvidia_unit_file)"; }
nvsilent_enable() {
[[ -f "$(nvidia_unit_file)" ]] || return 0
bigpicture_status && return 0
nvidia_write_unit -silent || return 1
ok "Steam starts silently at your next login."
}
nvsilent_disable() {
nvsilent_status || return 0
nvidia_write_unit "" && ok "Steam starts in its normal window at your next login."
}
# --- Kernel parameters and early modules (a supported card only) # --- Kernel parameters and early modules (a supported card only)
nvidia_supported() { nvidia_supported() {
+43 -15
View File
@@ -5,35 +5,63 @@
steam_enable() { steam_enable() {
info "Applying non-optional SteamOS environment & keyboard fixes..." info "Applying non-optional SteamOS environment & keyboard fixes..."
local steam_env_dir systemd_user_dir local steam_env_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"
# 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"
# 3. Setup robust background systemd service for Steam autostart on Desktop Mode ok "Steam UI parameters and keyboard fix deployed successfully."
systemd_user_dir="$HOME/.config/systemd/user" }
mkdir -p "$systemd_user_dir"
service_file steam-desktop-autostart.service > "$systemd_user_dir/steam-desktop-autostart.service" # Sub-option of the SteamOS conversion: Steam starts silently (in the tray,
# no window) on the Plasma desktop. It is Steam's own autostart entry, the file
# Steam's setting "Run Steam when my computer starts" creates and removes, so
# that setting shows what Steamify did (and the other way around). Steam's copy
# is the system steam.desktop; ours has -silent in its Exec line.
STEAM_AUTOSTART="${XDG_CONFIG_HOME:-$HOME/.config}/autostart/steam.desktop"
STEAM_SYSTEM_DESKTOP=/usr/share/applications/steam.desktop
# Clean out old .desktop shortcut so they don't fight silent_status() {
rm -f "$HOME/.config/autostart/steam.desktop" # The old systemd unit counts as on too (until it is migrated by an update of this option).
grep -qs '^Exec=.*-silent' "$STEAM_AUTOSTART" ||
[[ -f "$HOME/.config/systemd/user/steam-desktop-autostart.service" ]]
}
# Reload user systemd context and activate the background loop silent_old_unit_remove() {
# Before 2.11.0 the option was a systemd user unit: it would start Steam a second time.
local unit="$HOME/.config/systemd/user/steam-desktop-autostart.service"
[[ -f "$unit" ]] || return 0
user_systemctl disable --now steam-desktop-autostart.service 2>/dev/null
rm -f "$unit"
user_systemctl daemon-reload user_systemctl daemon-reload
user_systemctl enable --now steam-desktop-autostart.service }
ok "Steam UI parameters and keyboard autostart deployed successfully." silent_enable() {
silent_old_unit_remove
mkdir -p "$(dirname "$STEAM_AUTOSTART")"
if [[ -f "$STEAM_SYSTEM_DESKTOP" ]]; then
sed 's|^Exec=/usr/bin/steam %U$|Exec=/usr/bin/steam -silent %U|' "$STEAM_SYSTEM_DESKTOP" > "$STEAM_AUTOSTART"
fi
silent_status || printf '%s\n' '[Desktop Entry]' 'Name=Steam' 'Exec=/usr/bin/steam -silent %U' \
'Icon=steam' 'Terminal=false' 'Type=Application' 'Categories=Network;FileTransfer;Game;' > "$STEAM_AUTOSTART"
ok "Steam starts silently on the desktop from the next login."
}
silent_disable() {
silent_old_unit_remove
silent_status && rm -f "$STEAM_AUTOSTART"
ok "Steam no longer starts by itself on the desktop."
} }
steam_disable() { steam_disable() {
info "Removing Steam desktop autostart..." info "Removing Steam desktop settings..."
user_systemctl disable --now steam-desktop-autostart.service 2>/dev/null # The autostart entry is the `silent` option's: removed with it, and here
rm -f "$HOME/.config/systemd/user/steam-desktop-autostart.service" \ # too for when the conversion goes off by itself.
"$HOME/.config/environment.d/99-kde-virtual-keyboard.conf" silent_status && silent_disable
user_systemctl daemon-reload silent_old_unit_remove
rm -f "$HOME/.config/environment.d/99-kde-virtual-keyboard.conf"
ok "Steam desktop settings removed (takes full effect at next login)." ok "Steam desktop settings removed (takes full effect at next login)."
} }
+2 -6
View File
@@ -56,7 +56,7 @@ steamgame_steam_busy() {
steamgame_edit() { steamgame_edit() {
# steamgame_edit <function>: runs it with Steam closed, then starts Steam # steamgame_edit <function>: runs it with Steam closed, then starts Steam
# again if it was running (through our autostart unit when that's there). # again if it was running (silently, in the tray).
local was_running=false i local was_running=false i
if pgrep -x steam >/dev/null; then if pgrep -x steam >/dev/null; then
steamgame_steam_busy && return 1 steamgame_steam_busy && return 1
@@ -72,11 +72,7 @@ steamgame_edit() {
fi fi
"$1"; local rc=$? "$1"; local rc=$?
if [[ "$was_running" == true ]]; then if [[ "$was_running" == true ]]; then
if user_systemctl is-enabled -q steam-desktop-autostart.service 2>/dev/null; then systemd-run --user --collect -q steam -silent >/dev/null 2>&1
user_systemctl start steam-desktop-autostart.service
else
systemd-run --user --collect -q steam -silent >/dev/null 2>&1
fi
info "Steam is starting again." info "Steam is starting again."
fi fi
return "$rc" return "$rc"
+5 -2
View File
@@ -407,9 +407,12 @@ wifi_backend_disable() {
serial_enable() { serial_enable() {
printf '%s\n' "# Written by Steamify: Steam shows the serial number, like on SteamOS." \ printf '%s\n' "# Written by Steamify: Steam shows the serial number, like on SteamOS." \
'z /sys/class/dmi/id/product_serial 0444 - - -' | sudo tee "$SERIAL_TMPFILES" > /dev/null && 'z /sys/class/dmi/id/product_serial 0444 - - -' | sudo tee "$SERIAL_TMPFILES" > /dev/null ||
sudo systemd-tmpfiles --create "$SERIAL_TMPFILES" ||
{ err "Making the serial number readable for Steam failed."; return 1; } { err "Making the serial number readable for Steam failed."; return 1; }
# The file applies at every boot; now too, unless /sys is read-only (the ISO's installer runs in a chroot).
sudo systemd-tmpfiles --create "$SERIAL_TMPFILES" 2>/dev/null ||
info "The serial number becomes readable for Steam at the next boot."
return 0
} }
serial_disable() { serial_disable() {
+22 -7
View File
@@ -106,17 +106,32 @@ theme_enable() {
# SteamOS panel, launcher icon and wallpaper. It needs plasmashell up. # SteamOS panel, launcher icon and wallpaper. It needs plasmashell up.
lookandfeeltool -a "$VAPOR_LOOKANDFEEL" --resetLayout >/dev/null 2>&1 || lookandfeeltool -a "$VAPOR_LOOKANDFEEL" --resetLayout >/dev/null 2>&1 ||
{ err "lookandfeeltool failed."; return 1; } { err "lookandfeeltool failed."; return 1; }
# The new layout has a new launcher, without single user's settings. # The new layout has a new launcher, without single user's settings, and the default taskbar pins.
if single_status; then sleep 3
sleep 3 stop_plasmashell_for_edit
stop_plasmashell_for_edit taskbar_drop_discover
single_launcher single_status && single_launcher
restart_plasmashell_if_stopped restart_plasmashell_if_stopped
fi
extras_enable || warn "SteamOS desktop extras not installed (see above); the theme itself is on." extras_enable || warn "SteamOS desktop extras not installed (see above); the theme itself is on."
ok "Vapor theme active." ok "Vapor theme active."
} }
taskbar_drop_discover() {
# Plasma's default taskbar pins Discover, which CachyOS doesn't install: the pin shows as a
# blank icon. Pin what CachyOS's own layout pins (/etc/skel) instead. Not when Discover is
# installed, and only on a taskbar that still has the default pins (no launchers key).
# Edit only while plasmashell is stopped.
[[ -e /usr/share/applications/org.kde.discover.desktop ]] && return 0
local applet grp
for applet in $(plasma_applets org.kde.plasma.icontasks); do
grp="Containments|${applet%%:*}|Applets|${applet#*:}|Configuration|General"
[[ -n "$(kreadconfig6 --file plasma-org.kde.plasma.desktop-appletsrc --group Containments --group "${applet%%:*}" \
--group Applets --group "${applet#*:}" --group Configuration --group General --key launchers)" ]] && continue
kset theme plasma-org.kde.plasma.desktop-appletsrc "$grp" launchers \
'applications:systemsettings.desktop,preferred://filemanager,preferred://browser'
done
}
theme_disable() { theme_disable() {
extras_disable extras_disable
info "Restoring the previous desktop look and layout..." info "Restoring the previous desktop look and layout..."
-1
View File
@@ -12,6 +12,5 @@ in the shell code.
| `steamify-boot-desktop.service` | `lib/boot-session.sh` (Boot into: desktop) | Sets the Plasma session before the login manager starts | | `steamify-boot-desktop.service` | `lib/boot-session.sh` (Boot into: desktop) | Sets the Plasma session before the login manager starts |
| `sync-steamos-session.path`, `.service` | `lib/login-manager.sh` (SteamOS conversion, plasma-login-manager) | The sync bridge: copies Steam's session choice into `plasmalogin.conf` | | `sync-steamos-session.path`, `.service` | `lib/login-manager.sh` (SteamOS conversion, plasma-login-manager) | The sync bridge: copies Steam's session choice into `plasmalogin.conf` |
| `steamify-steam-autostart.service` | `lib/nvidia.sh` (Gaming on NVIDIA) | Steam at login on the Plasma desktop, normal or in Big Picture (user unit) | | `steamify-steam-autostart.service` | `lib/nvidia.sh` (Gaming on NVIDIA) | Steam at login on the Plasma desktop, normal or in Big Picture (user unit) |
| `steam-desktop-autostart.service` | `lib/steam-desktop.sh` (SteamOS conversion) | Steam in the background on the Plasma desktop (user unit) |
| `ensure-kernel-headers.service` | `lib/steam-machine.sh` (Steam Machine support) | Installs missing kernel headers at boot, so DKMS builds for every kernel | | `ensure-kernel-headers.service` | `lib/steam-machine.sh` (Steam Machine support) | Installs missing kernel headers at boot, so DKMS builds for every kernel |
| `steamify-update-check.service`, `.timer` | `lib/update-notifier.sh` (Update notifications) | The daily and login check for a new release (user units) | | `steamify-update-check.service`, `.timer` | `lib/update-notifier.sh` (Update notifications) | The daily and login check for a new release (user units) |
-15
View File
@@ -1,15 +0,0 @@
[Unit]
Description=Steam Background Autostart for Virtual Keyboard
After=graphical-session.target
PartOf=graphical-session.target
[Service]
Type=simple
# Only in the Plasma desktop session; gamescope-session starts its own Steam.
ExecCondition=/bin/sh -c '[ "$XDG_CURRENT_DESKTOP" = KDE ]'
ExecStart=/usr/bin/steam -silent
Restart=on-failure
RestartSec=5
[Install]
WantedBy=graphical-session.target
+1 -1
View File
@@ -15,7 +15,7 @@
set -uo pipefail set -uo pipefail
# Release version, see CHANGELOG.md. # Release version, see CHANGELOG.md.
VERSION=2.10.0 VERSION=2.11.0
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
-84
View File
@@ -1,84 +0,0 @@
#!/bin/bash
# Tests lib/controllers.sh (extended controller support: xone, the Xbox wireless dongle, and xpadneo, Xbox Bluetooth) with a stub pacman
# and a temp home. No root, VM or hardware needed: bash tests/controllers-test.sh
cd "$(dirname "$0")/.." || exit 1
T="$(mktemp -d)"; trap 'rm -rf "$T"' EXIT
fail=0
check() { if eval "$2"; then echo "ok $1"; else echo "FAIL $1"; fail=1; fi; }
SCRIPT_DIR="$PWD"; HOME="$T/home"; mkdir -p "$HOME"
source lib/common.sh; source lib/state.sh; source lib/controllers.sh; source lib/menu.sh
# Runs as the user, and refuses anything under the real system folders: a test must never touch them.
sudo() { local a; for a in "$@"; do case "$a" in /etc/*|/usr/*|/boot/*|/var/*) echo "REFUSED sudo $*" >&2; return 1 ;; esac; done; "$@"; }
info() { :; }; ok() { :; }; warn() { :; }; err() { echo "ERR $*"; }
kwriteconfig6() { local f="" k="" v=""; while [[ $# -gt 0 ]]; do case "$1" in --file) f="$2"; shift ;; --key) k="$2"; shift ;; --group) shift ;; *) v="$1" ;; esac; shift; done; mkdir -p "$(dirname "$f")"; sed -i "/^$k=/d" "$f" 2>/dev/null; printf '%s=%s\n' "$k" "$v" >> "$f"; }
kreadconfig6() { local f="" k=""; while [[ $# -gt 0 ]]; do case "$1" in --file) f="$2"; shift ;; --key) k="$2"; shift ;; --group|--default) shift ;; esac; shift; done; sed -n "s/^$k=//p" "$f" 2>/dev/null; }
# A pretend package database.
PKGS=""; PACMAN_LOG="$T/pacman.log"; : > "$PACMAN_LOG"; PACMAN_FAIL=0
pacman() {
case "$1" in
-Q) local p; for p in "${@:2}"; do [[ " $PKGS " == *" $p "* ]] || return 1; done ;;
-S) [[ $PACMAN_FAIL == 1 ]] && return 1; echo "S ${*:4}" >> "$PACMAN_LOG"; PKGS+=" ${*:4}" ;;
-Rns) echo "R ${*:3}" >> "$PACMAN_LOG"; local p; for p in ${*:3}; do PKGS=" ${PKGS// $p / } "; done ;;
esac
}
HEADERS=0; install_kernel_headers() { HEADERS=$((HEADERS + 1)); }
check "off to begin with" '! extended_controller_support_status'
extended_controller_support_enable
check "installs the repo's xpadneo-dkms, xone-dkms and the dongle firmware" 'pacman -Q xpadneo-dkms xone-dkms xone-dongle-firmware'
check "kernel headers are made sure of first" '[[ $HEADERS == 1 ]]'
check "what we installed is recorded" '[[ "$(state_get extended_controller_support installed_pkgs)" == "xpadneo-dkms xone-dkms xone-dongle-firmware" ]]'
check "it is on" extended_controller_support_status
n="$(wc -l < "$PACMAN_LOG")"; extended_controller_support_enable
check "a second run installs nothing again" '[[ "$(wc -l < "$PACMAN_LOG")" == "$n" ]]'
extended_controller_support_disable
check "off: the three packages are removed again" '! pacman -Q xpadneo-dkms 2>/dev/null && ! pacman -Q xone-dkms 2>/dev/null && ! pacman -Q xone-dongle-firmware 2>/dev/null && [[ -z "$(state_get extended_controller_support installed_pkgs)" ]]'
# The AUR's xone-dkms-git conflicts with the repo's xone-dkms: it counts, and is kept.
PKGS=" xone-dkms-git xone-dongle-firmware xpadneo-dkms"; : > "$PACMAN_LOG"
check "xone-dkms-git counts as xone: already on" extended_controller_support_status
extended_controller_support_enable; extended_controller_support_disable
check "with xone-dkms-git: nothing installed and nothing removed" '[[ ! -s "$PACMAN_LOG" ]] && pacman -Q xone-dkms-git xpadneo-dkms xone-dongle-firmware'
PKGS=" xone-dkms-git"
extended_controller_support_enable
check "xone-dkms-git present: only the missing ones are installed, never xone-dkms" 'grep -q "^S xpadneo-dkms xone-dongle-firmware$" "$PACMAN_LOG" && ! pacman -Q xone-dkms 2>/dev/null'
extended_controller_support_disable
check "and off removes only those two, xone-dkms-git stays" 'pacman -Q xone-dkms-git && ! pacman -Q xpadneo-dkms 2>/dev/null'
# A failed install is an error and records nothing.
PKGS=""; PACMAN_FAIL=1
check "a failed pacman is an error" '! extended_controller_support_enable >/dev/null'
check "...and records nothing" '[[ -z "$(state_get extended_controller_support installed_pkgs)" ]]'
PACMAN_FAIL=0
# Packages that were already there are never removed by turning it off.
PKGS=" xpadneo-dkms xone-dkms xone-dongle-firmware"; : > "$PACMAN_LOG"
extended_controller_support_enable; extended_controller_support_disable
check "packages you had before stay" 'pacman -Q xpadneo-dkms xone-dkms xone-dongle-firmware && [[ ! -s "$PACMAN_LOG" ]]'
# The menu.
check "offered on every PC" 'component_available extended_controller_support'
check "not preselected: it builds kernel modules for every kernel" '[[ " ${NO_PRESELECT[*]} " == *" extended_controller_support "* ]]'
check "a top-level item with a label" '[[ -z "${PARENT[extended_controller_support]:-}" && -n "${LABEL[extended_controller_support]}" ]]'
# The "new" badge: an opt-in option added after setup shows it, but is never ticked for you.
component_selectable() { return 0; }
declare -A CURRENT=([gaming]=1 [nvidia]=0 [extended_controller_support]=0 [vram]=0 [boot]=0)
rm -f "$STATE_DIR/features.state"
check "new opt-in option (conversion on, no record): the new badge" 'feature_new_optin extended_controller_support'
check "...but it is not ticked for you (not a new default option)" '! feature_new extended_controller_support'
check "...and the menu label says (new)" '[[ "$(menu_label extended_controller_support)" == *"(new)"* ]]'
check "a new default option is still ticked for you, and is not the opt-in kind" 'feature_new vram && ! feature_new_optin vram'
check "Boot into never gets the badge (it is a choice row)" '! feature_new_optin boot'
state_set_features() { kwriteconfig6 --file "$STATE_DIR/features.state" --group State --key "$1" "$2"; }
state_set_features extended_controller_support off
check "once a run recorded it as off, the badge is gone" '! feature_new_optin extended_controller_support'
rm -f "$STATE_DIR/features.state"
CURRENT[gaming]=0; CURRENT[nvidia]=1
check "on an NVIDIA PC (Gaming on NVIDIA on, no conversion) it shows too" 'feature_new_optin extended_controller_support'
CURRENT[nvidia]=0
check "with neither the conversion nor Gaming on NVIDIA on (a fresh PC) nothing is new" '! feature_new_optin extended_controller_support && ! feature_new vram'
CURRENT[gaming]=1; CURRENT[extended_controller_support]=1
check "already on: not new" '! feature_new_optin extended_controller_support'
exit $fail
-95
View File
@@ -1,95 +0,0 @@
#!/bin/bash
# Test of the NVIDIA fix on a real PC with an NVIDIA GPU (the unit test fakes
# one: tests/nvidia-test.sh). Run from the Steamify checkout:
# bash tests/nvidia-hardware-test.sh check read-only: what is detected, what the live kernel uses, what apply would change
# bash tests/nvidia-hardware-test.sh apply really applies the fix (sudo), then reboot and run check again
# bash tests/nvidia-hardware-test.sh visual after trying gaming mode: was the picture clean? (asks you)
# Every run appends to ~/steamify-nvidia-report.txt: paste that file when asking for help.
cd "$(dirname "$0")/.." || exit 1
# patch_file (lib/common.sh) reads the hook script from $SCRIPT_DIR/patches.
SCRIPT_DIR="$PWD"
REPORT="${NVIDIA_REPORT:-$HOME/steamify-nvidia-report.txt}"
source lib/common.sh; source lib/hdmi-refresh.sh; source lib/vram-booster.sh; source lib/nvidia.sh
mode="${1:-check}"
fail=0
say() { echo "$*" | tee -a "$REPORT"; }
pass() { say "PASS $*"; }
bad() { say "FAIL $*"; fail=1; }
note() { say " $*"; }
root_cat() { cat "$1" 2>/dev/null || sudo cat "$1" 2>/dev/null || echo "(unreadable)"; }
say ""; say "===== $(date '+%F %T') mode=$mode kernel=$(uname -r)"
report_system() {
say "-- GPU and software"
lspci -nn 2>/dev/null | grep -iE 'vga|3d|display' | while read -r l; do note "$l"; done
command -v nvidia-smi >/dev/null && note "driver: $(nvidia-smi --query-gpu=name,driver_version --format=csv,noheader 2>&1 | head -n 1)"
for p in nvidia-open nvidia-utils nvidia-dkms gamescope gamescope-session-cachyos linux-cachyos-nvidia-open; do
v="$(pacman -Q "$p" 2>/dev/null)" && note "$v"
done
note "boot loader file: $(nvidia_boot_file || true)"
note "cmdline: $(cat /proc/cmdline)"
}
check_state() {
say "-- Steamify's view"
if nvidia_present; then pass "a supported NVIDIA GPU (RTX 20 series or newer) with its driver is detected"
elif nvidia_legacy_gpu; then bad "the NVIDIA GPU is older than RTX 20 (on chwd's legacy lists in $VRAM_CHWD_IDS): the fix is not applied"
else bad "no NVIDIA GPU with its driver detected: the fix does nothing here"; fi
for c in /sys/class/drm/card[0-9]*/device; do
[[ "$(cat "$c/vendor" 2>/dev/null)" == 0x10de ]] && note "NVIDIA PCI device id $(cat "$c/device") $(vram_nvidia_legacy_id "$(cat "$c/device")" && echo '(on a chwd legacy list)' || echo '(not on a legacy list: RTX 20 or newer)')"
done
ls "$VRAM_CHWD_IDS"/nvidia-*.ids >/dev/null 2>&1 || note "no chwd legacy lists found: every NVIDIA card counts as supported"
local p
for p in $NVIDIA_PARAMS; do
if grep -qw -- "$p" /proc/cmdline; then pass "$p is on the running kernel's command line"
elif nvidia_param_set "$p"; then bad "$p is in the boot loader's file but not booted yet: reboot"
else bad "$p is missing (run: bash tests/nvidia-hardware-test.sh apply)"; fi
done
say "-- the live NVIDIA driver"
local m
for m in modeset fbdev; do
v="$(root_cat /sys/module/nvidia_drm/parameters/$m)"
if [[ "$v" == Y ]]; then pass "nvidia_drm $m = Y"; else bad "nvidia_drm $m = $v (want Y)"; fi
done
lsmod | grep -q '^nvidia_drm' && pass "nvidia_drm is loaded" || bad "nvidia_drm is not loaded"
local c found=0
for c in /sys/class/drm/card[0-9]*/device; do
[[ "$(cat "$c/vendor" 2>/dev/null)" == 0x10de ]] || continue
found=1; note "NVIDIA card: ${c%/device} driver=$(basename "$(readlink -f "$c/driver" 2>/dev/null)")"
for s in "${c%/device}"/card*-*/status; do [[ -f "$s" ]] && note " $(basename "$(dirname "$s")"): $(cat "$s")"; done
done
[[ $found == 1 ]] || bad "no NVIDIA card in /sys/class/drm"
say "-- initramfs"
if nvidia_modules_everywhere; then note "every installed kernel has nvidia_drm: the early-load drop-in is used"
else note "not every installed kernel has nvidia_drm: the early-load drop-in is skipped (parameters still apply)"; fi
nvidia_initramfs_ok && note "NVIDIA modules are in the initramfs config" || note "NVIDIA modules are not in the initramfs config"
say "-- what apply would change"
if nvidia_params_missing; then note "adds $NVIDIA_PARAMS to $(nvidia_boot_file)"; else note "kernel parameters: nothing to change"; fi
if ! nvidia_initramfs_ok && nvidia_modules_everywhere; then note "writes $NVIDIA_INITRAMFS_CONF"; fi
}
case "$mode" in
check)
report_system; check_state ;;
apply)
report_system
say "-- applying"
if nvidia_enable 2>&1 | tee -a "$REPORT"; [[ ${PIPESTATUS[0]} == 0 ]]; then pass "nvidia_enable finished"
else bad "nvidia_enable failed (output above)"; fi
say "Now reboot, then run: bash tests/nvidia-hardware-test.sh check" ;;
visual)
report_system
say "-- try gaming mode now (log in to it or reboot into it), look at the screen, then answer"
read -rp "Is the gaming mode picture clean (no corruption, no flicker)? [y/n/partly] " a
read -rp "What did you see (one line, e.g. 'garbled colours at start, fine after login')? " what
say "visual result: $a: $what"
[[ "$a" == y ]] && pass "picture clean" || bad "picture not clean ($a)"
say "-- gamescope and NVIDIA lines from this boot's log"
{ journalctl -b --no-pager 2>/dev/null || sudo journalctl -b --no-pager 2>/dev/null; } |
grep -iE 'gamescope|nvidia|drm|nvrm|wlserver|vulkan' | tail -n 80 | tee -a "$REPORT" | tail -n 5
note "(more in $REPORT)" ;;
*) echo "usage: $0 check|apply|visual"; exit 2 ;;
esac
say ""; say "Report: $REPORT"
exit $fail
-206
View File
@@ -1,206 +0,0 @@
#!/bin/bash
# Tests lib/nvidia.sh ("Gaming on NVIDIA" and its Big Picture option) and the menu rules around it, against a fake RTX 5080
# (PCI 10de:2c02) beside an Intel iGPU, a stub modinfo, pacman and systemctl, and a temp home. No root, VM or NVIDIA
# hardware needed: bash tests/nvidia-test.sh
cd "$(dirname "$0")/.." || exit 1
T="$(mktemp -d)"; trap 'rm -rf "$T"' EXIT
fail=0
check() { if eval "$2"; then echo "ok $1"; else echo "FAIL $1"; fail=1; fi; }
SCRIPT_DIR="$PWD"; HOME="$T/home"; mkdir -p "$HOME"
source lib/common.sh; source lib/state.sh; source lib/login-manager.sh; source lib/single-user.sh; source lib/hdmi-refresh.sh; source lib/vram-booster.sh; source lib/nvidia.sh; source lib/menu.sh
# Runs as the user, and refuses anything under the real system folders: a test must never touch them.
sudo() { local a; for a in "$@"; do case "$a" in /etc/*|/usr/*|/boot/*|/var/*) echo "REFUSED sudo $*" >&2; return 1 ;; esac; done; "$@"; }
info() { :; }; ok() { :; }; warn() { :; }; err() { echo "ERR $*"; }
# KDE's config tools on plain files under the temp home (a relative file name is relative to ~/.config, as in KDE).
kwriteconfig6() {
local f="" k="" v="" del=0
while [[ $# -gt 0 ]]; do case "$1" in --file) f="$2"; shift ;; --key) k="$2"; shift ;; --group) shift ;; --delete) del=1 ;; *) v="$1" ;; esac; shift; done
[[ "$f" == /* ]] || f="$HOME/.config/$f"; mkdir -p "$(dirname "$f")"
if [[ $del == 1 ]]; then sed -i "/^$k=/d" "$f" 2>/dev/null; else sed -i "/^$k=/d" "$f" 2>/dev/null; printf '%s=%s\n' "$k" "$v" >> "$f"; fi
}
kreadconfig6() {
local f="" k="" d="" r
while [[ $# -gt 0 ]]; do case "$1" in --file) f="$2"; shift ;; --key) k="$2"; shift ;; --default) d="$2"; shift ;; --group) shift ;; esac; shift; done
[[ "$f" == /* ]] || f="$HOME/.config/$f"
r="$(sed -n "s/^$k=//p" "$f" 2>/dev/null)"; printf '%s\n' "${r:-$d}"
}
# A pretend package database and systemd: what the tests assert on.
PKGS=""; PACMAN_LOG="$T/pacman.log"; : > "$PACMAN_LOG"; ENABLED=0
pacman() {
case "$1" in
-Q) [[ " $PKGS " == *" $2 "* ]] ;;
-S) echo "S $*" >> "$PACMAN_LOG"; PKGS+=" ${*: -1}" ;;
-Rns) echo "R $*" >> "$PACMAN_LOG"; PKGS=" ${PKGS//${*: -1}/} " ;;
esac
}
user_systemctl() {
case "$1" in
enable) ENABLED=1 ;;
disable) ENABLED=0 ;;
is-enabled) [[ $ENABLED == 1 ]] ;;
esac
return 0
}
FAKE_DRIVER=1; modinfo() { [[ "$FAKE_DRIVER" == 1 ]]; }
GAMING_ON=0; gaming_status() { [[ "$GAMING_ON" == 1 ]]; }
UNIT="$HOME/.config/systemd/user/$NVIDIA_UNIT"
mkdir -p "$T/drm/card0/device" "$T/drm/card1/device"
echo 0x8086 > "$T/drm/card0/device/vendor"; echo 0x030000 > "$T/drm/card0/device/class"
echo 0x10de > "$T/drm/card1/device/vendor"; echo 0x030000 > "$T/drm/card1/device/class"
echo 0x2c02 > "$T/drm/card1/device/device"
NVIDIA_DRM_DIR="$T/drm"
backup_file() { [[ -f "$1.bak" ]] || cp "$1" "$1.bak"; }
REBUILDS=0; nvidia_rebuild_boot() { REBUILDS=$((REBUILDS + 1)); }
: > "$T/cmdline"; NVIDIA_CMDLINE="$T/cmdline" # the running kernel's command line: without the parameters
NVIDIA_INITRAMFS_CONF="$T/90-steamify-nvidia.conf"
NVIDIA_SCRIPT="$T/libexec/steamify-nvidia-initramfs"; NVIDIA_HOOK="$T/hooks/85-steamify-nvidia-initramfs.hook"
mkdir -p "$T/mods/6.1.0-cachyos/kernel"; : > "$T/mods/6.1.0-cachyos/kernel/nvidia-drm.ko.zst"; : > "$T/mods/6.1.0-cachyos/pkgbase"
NVIDIA_MODULES_DIR="$T/mods"
NVIDIA_LIMINE_CONF="$T/none/limine.conf"; NVIDIA_SDBOOT_DIR="$T/none/entries"; NVIDIA_GRUB_CFG="$T/none/grub.cfg" # not generated here: not checked
mkdir -p "$T/chwd"; VRAM_CHWD_IDS="$T/chwd"
# The component's kernel step edits this boot loader file (systemd-boot's) in the tests, never a real one.
printf 'LINUX_OPTIONS="quiet"\n' > "$T/sdboot-manage.conf"; nvidia_boot_file() { echo "$T/sdboot-manage.conf"; }
# --- detection
check "finds the NVIDIA card as card1 beside an iGPU" nvidia_present
FAKE_DRIVER=0; check "no nvidia_drm module (nouveau): not an NVIDIA PC" '! nvidia_present'
FAKE_DRIVER=1; NVIDIA_DRM_DIR="$T/none"; check "no NVIDIA GPU: not an NVIDIA PC" '! nvidia_present'
NVIDIA_DRM_DIR="$T/drm"
# --- which items the menu shows
check "NVIDIA PC: the SteamOS conversion and its gamescope options are hidden" '! component_available gaming && ! component_available boot && ! component_available glyphs'
check "NVIDIA PC: Gaming on NVIDIA and Big Picture are shown" 'component_available nvidia && component_available bigpicture'
GAMING_ON=1
check "NVIDIA PC with the conversion already on: it is shown, so it can be turned off" 'component_available gaming && component_available boot'
check "...and Gaming on NVIDIA is hidden (both would start Steam)" '! component_available nvidia && ! component_available bigpicture'
GAMING_ON=0; NVIDIA_DRM_DIR="$T/none"
check "no NVIDIA: the conversion is shown as before" 'component_available gaming && component_available boot'
check "...and Gaming on NVIDIA is hidden" '! component_available nvidia && ! component_available bigpicture'
NVIDIA_DRM_DIR="$T/drm"
# --- "Add as non-Steam game" is for gaming mode's controller: not offered on an NVIDIA PC (unless already on)
steamgame_available() { return 0; }; STEAMGAME_ON=0; steamgame_status() { [[ "$STEAMGAME_ON" == 1 ]]; }
check "NVIDIA PC: Add as non-Steam game is hidden" '! component_available steamgame'
STEAMGAME_ON=1; check "...unless it is already on (so it can be turned off)" 'component_available steamgame'; STEAMGAME_ON=0
NVIDIA_DRM_DIR="$T/none"; check "no NVIDIA: it is offered as before" 'component_available steamgame'
steamgame_available() { return 1; }; check "no NVIDIA, no Steam account yet: still not offered" '! component_available steamgame'
steamgame_available() { return 0; }; NVIDIA_DRM_DIR="$T/drm"
# --- turning it on
check "off to begin with" '! nvidia_status && ! bigpicture_status'
nvidia_enable
check "Steam is installed when missing, and recorded as ours" 'grep -q "^S " "$PACMAN_LOG" && [[ "$(state_get nvidia installed_pkgs)" == steam ]]'
check "the autostart unit is written: Steam without arguments" 'grep -q "^ExecStart=/usr/bin/steam $" "$UNIT"'
check "it is on" 'nvidia_status && ! bigpicture_status'
n="$(wc -l < "$PACMAN_LOG")"; nvidia_enable
check "a second run installs nothing again" '[[ "$(wc -l < "$PACMAN_LOG")" == "$n" ]]'
# --- Big Picture
bigpicture_enable
check "Big Picture: Steam starts with -gamepadui" 'grep -q "^ExecStart=/usr/bin/steam -gamepadui$" "$UNIT" && bigpicture_status'
nvidia_enable
check "turning Gaming on NVIDIA on again keeps Big Picture" 'bigpicture_status'
check "Big Picture: Plasma starts with an empty session" '[[ "$(kreadconfig6 --file ksmserverrc --group General --key loginMode)" == emptySession ]]'
bigpicture_disable
check "Big Picture off: Steam's normal window again" '! bigpicture_status && nvidia_status'
check "...and the session setting is back as it was (not set)" '[[ -z "$(kreadconfig6 --file ksmserverrc --group General --key loginMode)" ]]'
# --- turning it off
bigpicture_enable; nvidia_disable
check "off: the unit is gone and Steam, which we installed, is removed" '! nvidia_status && [[ ! -e "$UNIT" ]] && ! pacman -Q steam && [[ -z "$(state_get nvidia installed_pkgs)" ]]'
check "Big Picture without the unit does nothing" 'bigpicture_enable && bigpicture_disable && [[ ! -e "$UNIT" ]]'
# --- Steam that was there already is never removed
PKGS=" steam"; : > "$PACMAN_LOG"
nvidia_enable; nvidia_disable
check "Steam installed before is kept, and not installed again" '[[ ! -s "$PACMAN_LOG" ]] && pacman -Q steam'
# --- kernel parameters and early modules (a supported card only: RTX 20 series or newer)
check "RTX 5080 (2c02) is supported: no chwd legacy lists" nvidia_supported
printf '1c03\n1b80\n' > "$T/chwd/nvidia-580.ids" # a GTX 1060 and a GTX 1080: chwd's 580xx legacy list
check "RTX 5080 is not on a legacy list" 'nvidia_supported && ! nvidia_legacy_gpu'
echo 0x1c03 > "$T/drm/card1/device/device"
check "GTX 1060 (older than RTX 20): no kernel setup, but still an NVIDIA PC" '! nvidia_supported && nvidia_legacy_gpu && nvidia_present'
echo 0x2c02 > "$T/drm/card1/device/device"
for loader in limine limineplus sdboot grub; do
case $loader in
limine) F="$T/limine"; printf 'KERNEL_CMDLINE[default]="quiet splash"\n' > "$F" ;;
# CachyOS writes its line as "+=" and may already have nvidia_drm.modeset=1 in it.
limineplus) F="$T/limine"; printf 'KERNEL_CMDLINE[default]+="quiet splash nvidia_drm.modeset=1"\n' > "$F" ;;
sdboot) F="$T/sdboot-manage.conf"; printf 'LINUX_OPTIONS="quiet splash"\n' > "$F" ;;
grub) F="$T/grub"; printf 'GRUB_CMDLINE_LINUX_DEFAULT="quiet splash"\n' > "$F" ;;
esac
nvidia_boot_file() { echo "$F"; }
rm -f "$NVIDIA_INITRAMFS_CONF"; REBUILDS=0; ORIG="$(cat "$F")"
nvidia_kernel_enable
check "$loader: parameters added" 'grep -q "nvidia-drm.modeset=1" "$F" && grep -q "nvidia-drm.fbdev=1" "$F"'
check "$loader: initramfs drop-in written" 'grep -q nvidia_drm "$NVIDIA_INITRAMFS_CONF"'
check "$loader: script and pacman hook installed" '[[ -x "$NVIDIA_SCRIPT" ]] && grep -q "^Exec = $NVIDIA_SCRIPT sync" "$NVIDIA_HOOK"'
check "$loader: backup made, rebuilt once" '[[ -f "$F.bak" && $REBUILDS == 1 ]]'
SUM="$(cat "$F")"; nvidia_kernel_enable
check "$loader: second run changes nothing" '[[ "$(cat "$F")" == "$SUM" && $REBUILDS == 1 ]]'
nvidia_kernel_disable
check "$loader: disable restores the file, drops the drop-in, script and hook" '[[ "$(cat "$F")" == "$ORIG" && ! -f "$NVIDIA_INITRAMFS_CONF" && ! -e "$NVIDIA_SCRIPT" && ! -e "$NVIDIA_HOOK" ]]'
done
# A missing patches/ file must be an error, never an empty script or hook.
( SCRIPT_DIR="$T/no-patches"; NVIDIA_SCRIPT="$T/empty/script"; NVIDIA_HOOK="$T/empty/hook"; ! nvidia_hook_install 2>/dev/null && [[ ! -s "$T/empty/script" ]] ) && echo "ok a missing patch file is an error, nothing empty installed" || { echo "FAIL a missing patch file is an error, nothing empty installed"; fail=1; }
# The pacman hook's script decides again at every kernel change.
syncit() { NVIDIA_INITRAMFS_CONF="$NVIDIA_INITRAMFS_CONF" NVIDIA_MODULES_DIR="$NVIDIA_MODULES_DIR" bash "$NVIDIA_SCRIPT" sync; }
nvidia_hook_install; rm -f "$NVIDIA_INITRAMFS_CONF"
syncit; check "hook script: every kernel has the modules -> drop-in written" '[[ -f "$NVIDIA_INITRAMFS_CONF" ]]'
mkdir -p "$T/mods/6.6.0-lts/kernel"; : > "$T/mods/6.6.0-lts/pkgbase"
syncit; check "hook script: a new kernel without modules -> drop-in removed" '[[ ! -f "$NVIDIA_INITRAMFS_CONF" ]]'
: > "$T/mods/6.6.0-lts/kernel/nvidia-drm.ko.zst"
syncit; check "hook script: the modules arrive (DKMS built) -> drop-in back" '[[ -f "$NVIDIA_INITRAMFS_CONF" ]]'
rm -rf "$T/mods/6.6.0-lts"; mkdir -p "$T/mods/5.0.0-leftover"; : > "$T/mods/5.0.0-leftover/modules.dep"
syncit; check "hook script: a leftover folder of a removed kernel is ignored" '[[ -f "$NVIDIA_INITRAMFS_CONF" ]]'
rm -rf "$T/mods/5.0.0-leftover"; nvidia_kernel_disable
# A second kernel without the NVIDIA modules: no early-load drop-in, parameters still set.
mkdir -p "$T/mods/6.6.0-lts/kernel"; : > "$T/mods/6.6.0-lts/pkgbase"; F="$T/sdboot-manage.conf"; printf 'LINUX_OPTIONS="quiet"\n' > "$F"
nvidia_boot_file() { echo "$F"; }; rm -f "$NVIDIA_INITRAMFS_CONF"; REBUILDS=0; nvidia_kernel_enable
check "kernel without nvidia modules: no drop-in, parameters set" '[[ ! -f "$NVIDIA_INITRAMFS_CONF" ]] && grep -q "nvidia-drm.fbdev=1" "$F"'
rm -rf "$T/mods/6.6.0-lts"
# Generated boot entries without the parameters (the initramfs build failed): an error.
printf 'linux /vmlinuz root=/dev/sda1\n' > "$T/grub.cfg"; NVIDIA_GRUB_CFG="$T/grub.cfg"
F="$T/grub"; printf 'GRUB_CMDLINE_LINUX_DEFAULT="quiet"\n' > "$F"; nvidia_boot_file() { echo "$F"; }; rm -f "$NVIDIA_INITRAMFS_CONF"
check "boot entries without the parameters: error" '! nvidia_kernel_enable >/dev/null'
NVIDIA_GRUB_CFG="$T/none/grub.cfg"
# A config file without the setting to edit: an error, not "applied".
F="$T/sdboot-manage.conf"; printf '#LINUX_OPTIONS=""\n' > "$F"; nvidia_boot_file() { echo "$F"; }; REBUILDS=0
check "no setting to edit: error, nothing rebuilt" '! nvidia_kernel_enable >/dev/null && [[ $REBUILDS == 0 ]]'
FAKE_DRIVER=0; NVIDIA_DRM_DIR="$T/drm"; printf 'LINUX_OPTIONS="quiet"\n' > "$T/sdboot"; F="$T/sdboot"; REBUILDS=0; nvidia_kernel_enable
check "no NVIDIA driver: nothing touched" '[[ "$(cat "$F")" == "LINUX_OPTIONS=\"quiet\"" && $REBUILDS == 0 ]]'
# --- single user mode on NVIDIA: its own login step (SDDM, autologin into Plasma) without the conversion
FAKE_DRIVER=1; NVIDIA_DRM_DIR="$T/drm" # an earlier section ended without the driver
SW="$T/switches.log"; : > "$SW"; TARGET_USER=tester; SINGLE_AUTOLOGIN="$T/sddm.conf.d/zzz-steamify-autologin.conf"
switch_to_sddm() { echo sddm >> "$SW"; }; switch_to_plasmalogin() { echo plasmalogin >> "$SW"; }
remove_sddm_base_autologin() { :; } # would look at the real /etc/sddm.conf
GAMING_ON=0
check "single user mode is offered on NVIDIA without the conversion..." 'component_available single'
GAMING_ON=1; check "...and with it" 'component_available single'; GAMING_ON=0
single_login_enable
check "single user: SDDM, autologin of the user into the Plasma session" 'grep -qx "User=tester" "$SINGLE_AUTOLOGIN" && grep -qx "Session=plasma.desktop" "$SINGLE_AUTOLOGIN" && grep -qx "Relogin=true" "$SINGLE_AUTOLOGIN" && grep -qx sddm "$SW"'
c1="$(cat "$SINGLE_AUTOLOGIN")"; single_login_enable
check "single user login: a second run changes nothing" '[[ "$(cat "$SINGLE_AUTOLOGIN")" == "$c1" ]]'
single_login_disable
check "single user off: the file is gone and plasma-login-manager is the login manager again" '[[ ! -e "$SINGLE_AUTOLOGIN" ]] && grep -qx plasmalogin "$SW"'
: > "$SW"; GAMING_ON=1; single_login_enable
check "with the conversion on, single user mode leaves the login to it" '[[ ! -e "$SINGLE_AUTOLOGIN" && ! -s "$SW" ]]'
GAMING_ON=0
# --- the menu rules
declare -A WANTED=([nvidia]=1 [bigpicture]=1 [gaming]=0 [boot]=0 [single]=0 [machine]=0 [poweroff]=0 [launcher]=0 [steamgame]=0)
component_selectable() { return 0; }
toggle_component nvidia
check "unticking Gaming on NVIDIA unticks Big Picture" '[[ "${WANTED[nvidia]}" == 0 && "${WANTED[bigpicture]}" == 0 ]]'
toggle_component bigpicture
check "ticking Big Picture ticks Gaming on NVIDIA" '[[ "${WANTED[nvidia]}" == 1 && "${WANTED[bigpicture]}" == 1 ]]'
WANTED[single]=0; WANTED[gaming]=0; toggle_component single
check "ticking single user mode does not tick the conversion where it isn't offered" '[[ "${WANTED[single]}" == 1 && "${WANTED[gaming]}" == 0 ]]'
check "Big Picture follows Gaming on NVIDIA in the menu" '[[ " ${COMPONENTS[*]} " == *" nvidia bigpicture "* && "${PARENT[bigpicture]}" == nvidia ]]'
exit $fail
+11 -4
View File
@@ -38,7 +38,9 @@ Item {
readonly property var status: backend.status || ({}) readonly property var status: backend.status || ({})
readonly property var items: status.items || [] readonly property var items: status.items || []
readonly property var rows: items.filter(function (i) { return !i.parent || want[i.parent]; }) // Hidden: Big Picture excludes a silent start.
function hidden(i) { return i.id === "nvsilent" && want.bigpicture; }
readonly property var rows: items.filter(function (i) { return (!i.parent || want[i.parent]) && !hidden(i); })
readonly property var bios: status.bios || null readonly property var bios: status.bios || null
signal passwordRequested() signal passwordRequested()
@@ -76,10 +78,14 @@ Item {
w[id] = !w[id]; w[id] = !w[id];
// The same rules as the terminal menu (toggle_component). // The same rules as the terminal menu (toggle_component).
var hasGaming = items.some(function (i) { return i.id === "gaming"; }); var hasGaming = items.some(function (i) { return i.id === "gaming"; });
if (id === "gaming" && !w.gaming) w.single = false; if (id === "gaming" && !w.gaming) { w.single = false; w.silent = false; w.glyphs = false; }
if (id === "single" && w.single && hasGaming) w.gaming = true; if (id === "single" && w.single && hasGaming) w.gaming = true;
if (id === "nvidia") w.bigpicture = w.nvidia; if (id === "nvidia") w.bigpicture = w.nvidia;
if (id === "bigpicture" && w.bigpicture) w.nvidia = true; if (id === "bigpicture" && w.bigpicture) { w.nvidia = true; w.nvsilent = false; }
if (id === "nvsilent" && w.nvsilent) { w.nvidia = true; w.bigpicture = false; }
if (id === "nvidia" && !w.nvidia) w.nvsilent = false;
if (id === "silent" && w.silent) w.gaming = true;
if (id === "glyphs" && w.glyphs) w.gaming = true;
if (id === "machine") w.poweroff = w.machine; if (id === "machine") w.poweroff = w.machine;
if (id === "poweroff" && w.poweroff) w.machine = true; if (id === "poweroff" && w.poweroff) w.machine = true;
if (id === "machine" && !w.machine) w.kpin = false; if (id === "machine" && !w.machine) w.kpin = false;
@@ -93,6 +99,7 @@ Item {
for (var i = 0; i < items.length; i++) { for (var i = 0; i < items.length; i++) {
var it = items[i]; var it = items[i];
if (it.kind !== "toggle") continue; if (it.kind !== "toggle") continue;
if (hidden(it)) { if (it.on) p.push({ id: it.id, action: "off" }); continue; }
if (it.parent && !want[it.parent]) { if (it.on) p.push({ id: it.id, action: "off" }); continue; } if (it.parent && !want[it.parent]) { if (it.on) p.push({ id: it.id, action: "off" }); continue; }
if (want[it.id] && !it.on) p.push({ id: it.id, action: "on", isNew: !!it["new"] }); if (want[it.id] && !it.on) p.push({ id: it.id, action: "on", isNew: !!it["new"] });
else if (!want[it.id] && it.on) p.push({ id: it.id, action: "off" }); else if (!want[it.id] && it.on) p.push({ id: it.id, action: "off" });
@@ -109,7 +116,7 @@ Item {
function wantedIds() { function wantedIds() {
var ids = []; var ids = [];
for (var i = 0; i < items.length; i++) for (var i = 0; i < items.length; i++)
if (items[i].kind === "toggle" && want[items[i].id] && (!items[i].parent || want[items[i].parent])) ids.push(items[i].id); if (items[i].kind === "toggle" && want[items[i].id] && !hidden(items[i]) && (!items[i].parent || want[items[i].parent])) ids.push(items[i].id);
return ids; return ids;
} }
+7 -1
View File
@@ -6,16 +6,22 @@ QtObject {
readonly property var items: ({ readonly property var items: ({
gaming: { label: "SteamOS conversion", hint: "Boot into gaming mode, Steam on the desktop", gaming: { label: "SteamOS conversion", hint: "Boot into gaming mode, Steam on the desktop",
body: "Boots straight into gaming mode. Switch to Desktop in Steam works, and Return to Gaming Mode on the desktop brings you back.", body: "Boots straight into gaming mode. Switch to Desktop in Steam works, and Return to Gaming Mode on the desktop brings you back.",
changes: ["Autologin into gamescope", "Return to Gaming Mode shortcut", "Steam starts silently on the desktop"] }, changes: ["Autologin into gamescope", "Return to Gaming Mode shortcut"] },
boot: { label: "Boot into", hint: "Where the PC starts", boot: { label: "Boot into", hint: "Where the PC starts",
body: "Where the PC starts after a restart. Switching back and forth works the same either way.", body: "Where the PC starts after a restart. Switching back and forth works the same either way.",
changes: ["Desktop: the Plasma session is set before login", "Gaming: the SteamOS default"] }, changes: ["Desktop: the Plasma session is set before login", "Gaming: the SteamOS default"] },
silent: { label: "Start Steam silently in desktop mode", hint: "In the tray at login on the desktop, no window",
body: "Steam starts by itself when you log in to the Plasma desktop, in the tray without a window. Gaming mode starts its own Steam.",
changes: ["Steam is started with -silent (a systemd user service, desktop only)", "Off: the service is removed again"] },
nvidia: { label: "Gaming on NVIDIA", hint: "Steam on the desktop, started at login", nvidia: { label: "Gaming on NVIDIA", hint: "Steam on the desktop, started at login",
body: "gamescope's own gaming mode shows a corrupted picture on NVIDIA graphics cards (an open NVIDIA driver bug), so it isn't offered here. This puts Steam on the Plasma desktop instead and starts it when you log in.", body: "gamescope's own gaming mode shows a corrupted picture on NVIDIA graphics cards (an open NVIDIA driver bug), so it isn't offered here. This puts Steam on the Plasma desktop instead and starts it when you log in.",
changes: ["Steam is installed when it's missing", "Steam starts at login (a systemd user service)", "Off: the service is removed again; Steam is only removed if Steamify installed it"] }, changes: ["Steam is installed when it's missing", "Steam starts at login (a systemd user service)", "Off: the service is removed again; Steam is only removed if Steamify installed it"] },
bigpicture: { label: "Steam starts in Big Picture", hint: "The controller-friendly Steam, or the normal window", bigpicture: { label: "Steam starts in Big Picture", hint: "The controller-friendly Steam, or the normal window",
body: "Steam opens in Big Picture at login, which works well with a controller on the TV. Untick it for Steam's normal window.", body: "Steam opens in Big Picture at login, which works well with a controller on the TV. Untick it for Steam's normal window.",
changes: ["Steam is started with -gamepadui", "Plasma starts with an empty session, so old windows don't cover Big Picture", "Off: Steam starts in its normal window"] }, changes: ["Steam is started with -gamepadui", "Plasma starts with an empty session, so old windows don't cover Big Picture", "Off: Steam starts in its normal window"] },
nvsilent: { label: "Start Steam silently", hint: "In the tray at login, no window",
body: "Steam starts in the tray at login without a window. Not together with Big Picture: ticking one unticks the other.",
changes: ["Steam is started with -silent", "Off: Steam starts in its normal window"] },
theme: { label: "SteamOS theme", hint: "Vapor look for the desktop, Add to Steam", theme: { label: "SteamOS theme", hint: "Vapor look for the desktop, Add to Steam",
body: "The Vapor look of SteamOS for the desktop, with its panel, launcher icon and wallpaper.", body: "The Vapor look of SteamOS for the desktop, with its panel, launcher icon and wallpaper.",
changes: ["cachyos-vapor global theme", "Add to Steam in right-click menus", "Nested Desktop, Steam keyboard window rule"] }, changes: ["cachyos-vapor global theme", "Add to Steam in right-click menus", "Nested Desktop, Steam keyboard window rule"] },