Compare commits

..
Author SHA1 Message Date
theupriser 7d6df21627 Merge pull request #61 from theupriser/release/2.9.3
Single-file build / bundle (push) Successful in 13s
Release 2.9.3
2026-09-29 22:04:49 +02:00
theupriser 3cad70dcc4 docs: changelog hash for 2.9.3
Single-file build / bundle (push) Successful in 24s
2026-09-29 22:03:09 +02:00
theupriser b8742a5642 Merge pull request #60 from theupriser/feature/iso-release-on-steamify-release
feat(ci): a new Steamify release starts the Steamify ISO's release
2026-09-29 21:57:25 +02:00
theupriser 7f5d29c997 feat(ci): a new Steamify release starts the Steamify ISO's release (iso-release.yml in the ISO repo, feat/steamify; secret ISO_DISPATCH_TOKEN) 2026-09-29 21:56:42 +02:00
theupriser cfe3ce7bd0 chore: Version 2.9.3 2026-09-29 21:55:45 +02:00
theupriser 3e4133c14a Merge pull request #58 from theupriser/release/2.9.2
Single-file build / bundle (push) Successful in 14s
Release/2.9.2
2026-09-29 20:31:12 +02:00
theupriser c4b8db85dc Merge pull request #57 from theupriser/feature/gitea-release
Single-file build / bundle (push) Successful in 13s
feat(ci): a Gitea mirror publishes its own releases
2026-09-29 20:30:00 +02:00
theupriser 350011877b feat(ci): a Gitea mirror publishes its own release per version (never overwrites one, notes from the changelog) 2026-09-29 20:29:19 +02:00
theupriser b1d79d48a6 Merge pull request #55 from theupriser/release/2.9.2
Single-file build / bundle (push) Successful in 20s
chore: Version 2.9.2
2026-09-29 20:25:44 +02:00
theupriser 5b42036786 Merge pull request #56 from theupriser/bugfix/ci-shellcheck-gitea
fix(ci): the build also runs on a Gitea mirror
2026-09-29 20:25:10 +02:00
theupriser 4a64232fad fix(ci): Gitea gets christopherhx/gitea-upload-artifact@v4 (GitHub fails a workflow that mentions upload-artifact@v3) 2026-09-29 20:24:23 +02:00
theupriser 4ec92f4d89 fix(ci): the build also runs on a Gitea mirror: shellcheck through ludeeus/action-shellcheck (brings its own binary), the artifact with upload-artifact@v3 there, releases only on GitHub 2026-09-29 20:23:20 +02:00
theupriser fe4f3f43be chore: Version 2.9.2 2026-09-29 20:23:04 +02:00
theupriser 4bacc3b2e6 Merge pull request #54 from theupriser/release/2.9.1
Release/2.9.1
2026-09-29 19:51:54 +02:00
theupriser cc0ca1c35e Merge pull request #53 from theupriser/bugfix/cec-driver-cache
fix: HDMI-CEC: Valve's CEC driver is downloaded once and cached
2026-09-29 19:26:24 +02:00
theupriser 580cc71b57 docs: changelog hashes 2026-09-29 19:26:16 +02:00
theupriser c87e6c763f docs: changelog for the CEC driver cache 2026-09-29 19:19:05 +02:00
theupriser fc05725a91 fix: HDMI-CEC: an older cached CEC driver is removed when a new pin is downloaded 2026-09-29 19:18:55 +02:00
theupriser 90bc5e4408 fix: HDMI-CEC: Valve's CEC driver is downloaded once and kept in /var/cache/steamify (GitHub rate-limits repeated downloads with HTTP 429, which left CEC off) 2026-09-29 19:16:06 +02:00
theupriser d99ff652dc chore: Version 2.9.1 2026-09-29 19:15:42 +02:00
theupriser 2aa3068b60 Merge pull request #51 from theupriser/release/2.9.0
Release 2.9.0: docs (KDE Plasma only)
2026-09-28 20:42:12 +02:00
theupriser 1a6ddcfc0d Merge pull request #52 from theupriser/feature/changelog-hash-fix
docs: changelog hash fix
2026-09-28 19:48:45 +02:00
theupriser 11668db91c docs: changelog hash for 66ea63c (was the merge commit's) 2026-09-28 19:48:36 +02:00
theupriser 3316c1de28 Merge pull request #50 from theupriser/feature/changelog-hashes
docs: changelog hashes
2026-09-28 19:47:55 +02:00
theupriser d9365dac81 docs: changelog hashes 2026-09-28 19:47:47 +02:00
theupriser 853a3926ee Merge pull request #49 from theupriser/feature/docs-not-supported
docs: other desktops are not supported
2026-09-28 19:47:35 +02:00
theupriser 66ea63cf7e docs: KDE Plasma only: other desktops and display managers "are not supported" (README, was "don't work yet") 2026-09-28 19:47:28 +02:00
theupriser f560f332a9 Merge pull request #48 from theupriser/feature/docs-kde-only
docs: KDE Plasma only
2026-09-28 19:46:43 +02:00
theupriser 9b86cd1a6c docs: KDE Plasma only: other desktops don't work yet (README) 2026-09-28 19:46:36 +02:00
theupriser a72a4def71 Merge pull request #47 from theupriser/release/2.9.0
Release 2.9.0: docs
2026-09-28 19:38:41 +02:00
theupriser ea051c77f6 docs: changelog hash for d73e71d 2026-09-28 19:38:10 +02:00
theupriser 4e829c6111 Merge pull request #46 from theupriser/feature/docs-2.9.0
docs: 2.9.0 in README, TECHNICAL and TROUBLESHOOTING
2026-09-28 19:37:15 +02:00
theupriser d73e71d4eb docs: README, TECHNICAL and TROUBLESHOOTING for 2.9.0: Steam's System settings, serial number and Wi-Fi backend, --defaults --list, the Steamify ISO 2026-09-28 19:37:08 +02:00
theupriser 8f2d2be2aa Merge pull request #45 from theupriser/release/2.9.0
Release 2.9.0
2026-09-28 19:35:41 +02:00
theupriser 53b72c8e33 Merge pull request #44 from theupriser/feature/steamos-version
feat: Steam's OS Version steamos-3.9, OS Codename steam-machine
2026-09-28 19:31:35 +02:00
theupriser 3b4f3b2313 docs: changelog hash for a72d848 2026-09-28 19:31:28 +02:00
theupriser a72d848e78 feat: Steam's OS Version is the SteamOS release Steamify follows (steamos-3.9), its OS Codename steam-machine; About this System keeps "CachyOS Linux" (UseOSReleaseVersion) 2026-09-28 19:28:10 +02:00
theupriser 3a58c72d16 Merge pull request #43 from theupriser/bugfix/variant-version
fix: Steam's OS Variant shows Steamify's version
2026-09-28 19:22:31 +02:00
theupriser 27a40702ce fix: Steam's OS Variant shows Steamify's version (VARIANT_ID=steamify-2.9.0; Steam shows VARIANT_ID, not VARIANT) 2026-09-28 19:22:25 +02:00
theupriser 8ab066f034 Merge pull request #42 from theupriser/bugfix/no-version-id
fix: No VERSION_ID in os-release (About this System showed CachyOS Linux 2.9.0)
2026-09-28 19:17:10 +02:00
theupriser 44bfe071d6 fix: No VERSION_ID in os-release: About this System said "CachyOS Linux 2.9.0"; the version is in VARIANT ("Steamify 2.9.0") 2026-09-28 19:17:01 +02:00
theupriser e281d5e879 Merge pull request #41 from theupriser/feature/os-codename
feat: Steamify as OS variant, SteamOS release as codename; the OS name stays CachyOS
2026-09-28 19:14:50 +02:00
theupriser 435f69c151 feat: Steam's System settings: the OS name stays CachyOS (no renaming, also not in About this System), Steamify <version> as the variant, the SteamOS release it follows as the codename (steamos-3.9) 2026-09-28 19:14:43 +02:00
theupriser 9319cbca1e Merge pull request #40 from theupriser/bugfix/progress-checkmarks
fix(ui): The progress screen's checkmarks stand upright
2026-09-28 19:05:09 +02:00
theupriser cf6bee1c86 Merge release/2.9.0 into bugfix/progress-checkmarks 2026-09-28 19:05:02 +02:00
theupriser 16487ba00c Merge pull request #39 from theupriser/feature/steam-system-info
feat: Steam's System settings and About this System like on SteamOS
2026-09-28 19:04:29 +02:00
theupriser 07a94cd274 fix(ui): The progress screen's ✓ and ! stand upright: only a dot on the circle spins while a step runs (they kept the spinner's last angle) 2026-09-28 19:03:56 +02:00
theupriser ce71b34b0d feat: Steam's System settings and About this System like on SteamOS: OS name, Steamify as OS variant and version, serial number and Wi-Fi backend on a Steam Machine 2026-09-28 19:03:54 +02:00
theupriser d30d505f7d chore: Version 2.9.0 2026-09-28 19:03:28 +02:00
theupriser 9755cc3ac3 Merge pull request #38 from theupriser/bugfix/changelog-2.8.0-list
docs: CHANGELOG: 2.8.0's --defaults --list entry was missing
2026-09-28 13:02:11 +02:00
theupriser 6f26e74229 docs: CHANGELOG: 2.8.0's --defaults --list entry was missing 2026-09-28 13:01:00 +02:00
theupriser 2a01583b8f Merge pull request #37 from theupriser/release/2.8.0
Release 2.8.0
2026-09-28 12:46:15 +02:00
theupriser c40aa1f7d9 Merge pull request #36 from theupriser/feature/defaults-list
feat: steamify.sh --defaults --list
2026-09-28 12:45:27 +02:00
theupriser d204efb59d feat: steamify.sh --defaults --list: what --defaults can set up here, as JSON, for an installer page 2026-09-28 11:40:10 +02:00
theupriser 12f6cc0b3a chore: Version 2.8.0 2026-09-28 11:35:47 +02:00
theupriser b01e2c5221 Merge pull request #35 from theupriser/release/2.7.0
Release 2.7.0
2026-09-28 10:57:45 +02:00
theupriser affb5f79b0 Merge pull request #34 from theupriser/bugfix/theme-off-single-launcher
fix: theme off no longer brings back single user's launcher restriction
2026-09-28 10:53:19 +02:00
theupriser 58e43d4c4a fix: turning the theme off no longer brings back single user's launcher restriction when single user was turned off in between 2026-09-28 10:52:28 +02:00
theupriser 23f265b02f Merge pull request #33 from theupriser/feature/remove-v2-ui-preview
chore: remove the v2 app preview
2026-09-28 10:47:10 +02:00
theupriser ced4a45d2f chore: the v2 app preview is gone (it is the released app): no preview pre-release step in CI, no mention in steamify-app.sh 2026-09-28 10:46:23 +02:00
theupriser 6ad686a8b2 fix: Merge branch 'feature/gh-required' into release/2.7.0 2026-09-28 10:19:06 +02:00
theupriser b1adacbcb3 docs: gh is required for the release-branch pull requests; ask the user to install it 2026-09-28 10:18:59 +02:00
theupriser 8dd2db3a97 fix: Merge branch 'feature/release-branches' into release/2.7.0 2026-09-28 10:18:06 +02:00
theupriser 501c0ba425 docs: gh or git for merging into the release branch 2026-09-28 10:17:59 +02:00
theupriser bee18b76a8 docs: the agent merges feature/bugfix branches into the release branch; the release into main stays the user's 2026-09-28 10:17:41 +02:00
theupriser eadbdda271 docs: release branches (release/X.Y.Z, feature/ and bugfix/ branches into it, the release into main); CI builds release/** pushes 2026-09-28 10:14:20 +02:00
theupriser c4ec755a4a feat: --defaults --options <ids> (exactly these on) replaces --skip; steamify.sh --boot gamescope|desktop on its own switches where an installed conversion starts 2026-09-28 10:06:45 +02:00
theupriser 14aa7c0b54 fix: the app's progress screen says "Boot into desktop", not "Boot into Boot into" 2026-09-28 10:06:32 +02:00
theupriser 5bf9da411d fix: HDMI-CEC enables cec-audio-control.socket (the TV remote's volume keys); existing installs get it as an update 2026-09-28 10:06:23 +02:00
theupriser 4f6e6fd0aa feat: --defaults takes --skip <ids> and --boot gamescope|desktop, for the Steam Machine ISO's installer pages 2026-09-27 21:59:08 +02:00
theupriser a79eeedbc4 Merge pull request #32 from theupriser/feat/defaults-mode
feat: --defaults applies the default setup without the menu, also fro…
2026-09-27 21:25:03 +02:00
theupriser b948c2020b feat: --defaults applies the default setup without the menu, also from an installer (no session): the base for a Steam Machine ISO
systemctl --user goes through user_systemctl, which only changes unit files
without a session; the theme lets Plasma build Vapor's layout at the first
login when the layout is still /etc/skel's; a one-time first-login autostart
sets up single user's launcher and opens the app.
2026-09-27 19:21:28 +02:00
theupriser 0c96bed448 Merge pull request #31 from theupriser/docs/screenshot-2.5.2
docs: README screenshot at 2.5.2: everything on, nothing to update
2026-09-27 18:53:56 +02:00
theupriser e3f7cc9773 docs: README screenshot at 2.5.2: everything on, nothing to update 2026-09-27 18:53:23 +02:00
theupriser 353de489d7 Merge pull request #30 from theupriser/feat/apply-disabled
2.5.1: Add as non-Steam game, controller and apply button
2026-09-27 18:49:20 +02:00
theupriser d8b2e812c5 fix: Add as non-Steam game asks Steam to close again every 15 s (a Steam that was still starting ignored it) 2026-09-27 18:42:12 +02:00
theupriser 3a0692fdf2 docs: README screenshot at 2.5.1 with Add as non-Steam game 2026-09-27 18:17:41 +02:00
theupriser e86ddcc4af feat: Add as non-Steam game: Steamify in the Steam library, under the shortcut; controller works when started from Steam 2026-09-27 18:16:14 +02:00
theupriser 389bc3346e fix(ui): B never quits (Steam sends Esc for it), Ctrl+Q does; started from Steam, the hints show the Steam Controller's buttons 2026-09-27 17:56:57 +02:00
theupriser c6c1150836 fix(ui): Enter selects (a Steam Controller's A in Steam's desktop layout); Ctrl+Enter reviews and applies 2026-09-27 17:54:55 +02:00
theupriser 98e2effcff fix(ui): Started from Steam, the app runs without Steam's overlay (Qt aborted) and stays in the foreground, so Steam Input gives it the controller 2026-09-27 17:44:38 +02:00
theupriser 431515b60f feat(ui): Review & apply greyed out while nothing would change; the Done screen shows why a run stopped 2026-09-27 17:11:46 +02:00
theupriser 34c9cfdb32 Merge pull request #29 from theupriser/feat/update-notifier
Feat/update notifier
2026-09-27 17:02:15 +02:00
theupriser 8ddb7ebf3d docs: README: what the VRAM booster says with NVIDIA's closed driver; shorter unsupported text in the app 2026-09-27 17:00:07 +02:00
theupriser 32c33e4abf fix: An option left unticked stays off: it came back ticked as "new" on the next run (since 2.3.0) 2026-09-27 16:54:27 +02:00
theupriser 2dd0f3ac47 feat: VRAM booster with NVIDIA says what to do: update, switch to the open driver (chwd command), or not supported by the card 2026-09-27 16:31:39 +02:00
theupriser 57995bcd1f docs: VRAM booster works with NVIDIA's open kernel modules (driver 615+); only the closed driver is greyed out 2026-09-27 16:25:05 +02:00
theupriser d57e8d8448 docs: AGENTS.md and changelog for the vidmem detection 2026-09-27 16:20:57 +02:00
theupriser 5a34633986 feat: VRAM booster also for drivers that name their region vidmem (or numbered), NVIDIA included once its driver registers it 2026-09-27 16:20:36 +02:00
theupriser 479b70b337 feat: Everything in the home folder under steamify (state, scripts, icon), moved once from the old name 2026-09-27 16:11:32 +02:00
theupriser 2e0881b4fa fix: fill takes values literally; the notifier path is quoted in its unit 2026-09-27 16:05:20 +02:00
theupriser cce31e19c2 refactor: DKMS confs in patches/; an existing leds-valve DKMS override is kept and restored 2026-09-27 16:00:39 +02:00
theupriser bd4fa3a6f4 refactor: The session sync and kernel headers scripts in patches/ 2026-09-27 15:59:17 +02:00
theupriser 8ffa0f2449 refactor: systemd units in services/, read with service_file like patches/ 2026-09-27 15:58:41 +02:00
theupriser 8a2601d73d docs: README screenshot at 2.5.0 with Update notifications; AGENTS.md: retake it when rows change 2026-09-27 15:57:11 +02:00
theupriser 572417bd7b fix: Open Steamify from the notification starts the app (own scope), the same way it was last used (app or terminal) 2026-09-27 15:54:26 +02:00
theupriser cf73229756 feat: Update notifications: a notification and tray icon when there's a new Steamify 2026-09-27 14:06:48 +02:00
theupriser febdab5b53 Merge pull request #28 from theupriser/docs/readme-screenshot
2.4.1: Screenshot of the app's menu in the README
2026-09-27 13:53:41 +02:00
theupriser 90cdfd6666 chore: Version 2.4.1 2026-09-27 13:53:11 +02:00
theupriser 6f598d18fd docs: README screenshot shows every option 2026-09-27 13:52:59 +02:00
theupriser 9bbe5fa602 docs: Screenshot of the app's menu in the README 2026-09-27 13:52:59 +02:00
theupriser ceeb949e6b Merge pull request #27 from theupriser/refactor/qml-screens
2.4.0: One QML file per screen, HDMI setup removed
2026-09-27 13:49:43 +02:00
theupriser 03a8b8c4ba chore: Version 2.4.0 2026-09-27 13:48:13 +02:00
theupriser e699a3f8eb refactor(ui): One QML file per screen; the HDMI boost's setup screens and backend commands removed 2026-09-27 13:48:02 +02:00
theupriser 7bef834b16 Merge pull request #26 from theupriser/feat/vram-booster
2.3.0: VRAM booster, New badge
2026-09-27 13:05:19 +02:00
theupriser 86b9744227 feat: VRAM booster greyed out with an NVIDIA card, with why 2026-09-27 13:02:13 +02:00
theupriser b0947d7a2f feat: VRAM booster only for GPUs with at least 2 GB of their own VRAM 2026-09-27 12:55:40 +02:00
theupriser 3f97c85c3c feat: VRAM booster for every supported GPU, not only the Steam Machine 2026-09-27 12:51:47 +02:00
theupriser fd162c1e2e feat: New badge for default sub-options added in this version 2026-09-27 12:49:49 +02:00
theupriser 54ebddfe98 feat: VRAM booster for the Steam Machine 2026-09-27 12:48:01 +02:00
theupriser fe93dd3e67 Merge pull request #25 from theupriser/feat/fremont-poweroff
Feat/fremont poweroff
2026-09-27 12:41:38 +02:00
theupriser ef585c0db1 docs: Changelog entries per commit for 2.2.0 2026-09-27 12:36:25 +02:00
theupriser 32795bd5a5 feat(ui): Update badge on the progress screen 2026-09-27 12:35:40 +02:00
theupriser 3c8ca65902 fix(ui): Never write the sudo password to a file; Update label on the progress screen
The askpass helper reads the password from a named pipe that the app
feeds from memory each time sudo asks, instead of from a file.
2026-09-27 12:33:47 +02:00
theupriser 11a91ef85c feat: Update badge on components that get a newer version 2026-09-27 12:31:29 +02:00
theupriser 163f7908c4 feat: Feature versions are Steamify versions; Steam Machine support is 2.2.0 2026-09-27 12:27:55 +02:00
theupriser e121b06fd8 fix: Remove whatever is left of HDMI refresh boost, pin or no pin 2026-09-27 12:27:08 +02:00
theupriser 19ca966913 docs: Drop the kernel pin and HDMI refresh boost descriptions 2026-09-27 12:25:08 +02:00
theupriser 56fb9080a7 docs: Power-off fix texts cover every affected kernel, not just 7.2 2026-09-27 12:23:54 +02:00
theupriser 6df19eba3e feat: Power-off fix as its own sub-option, drop the kernel pin, feature versions
The power-off fix becomes an opt-out sub-option of Steam Machine
support. The kernel pin is no longer offered: an existing pin (and HDMI
refresh boost, which needs it) is unticked so a normal run removes it.
Components record a feature version on each successful run; installs
with an older version are ticked and updated, and new default
sub-options are ticked where their parent is on.
2026-09-27 12:20:56 +02:00
theupriser 7694c97d68 feat: Power-off fix for the Steam Machine; the kernel pin is optional
Kernels >= 7.2 keep the firmware's S4/S5 wake bit on GPIO pin 18, so the
Steam Machine starts again right after powering off. Steam Machine
support now builds a DKMS module (patches/steamify-fremont-poweroff.c)
that clears it before power-off, for every kernel. The kernel pin is no
longer ticked by default. Module sources and patches move to patches/,
embedded by the single-file build.
2026-09-27 12:13:23 +02:00
theupriser a5e644d71a Merge pull request #24 from theupriser/feat/hdmi-per-display
Feat/hdmi per display
2026-09-26 16:49:56 +02:00
theupriser 929ecfb349 feat(ui): Manage button for HDMI refresh boost
The item's switch becomes a Set up / Manage button. Manage lists the
saved displays, removes one with its Remove button, and sets up the
connected display when it has no saved rates.
2026-09-26 16:48:21 +02:00
theupriser 4cc87aaea6 feat: HDMI refresh boost per display, with a Saved displays screen
Rates are saved per display (EDID ID) and loaded by the hotplug script
for whichever display is connected. The item is on only while the
connected display is boosted; unticking removes just that one. The app
lists the saved displays and removes any of them (hdmi-forget).
2026-09-26 16:13:45 +02:00
theupriser 36d0a9d780 feat: HDMI refresh boost only for the display it was set up for
The EDID override moves off the kernel command line to a hotplug script
(boot unit + udev rule) that loads it only while the display it was
tested on is connected, identified over DDC; other displays get their
own EDID.
2026-09-26 16:04:02 +02:00
theupriser cb6361b49b Merge pull request #23 from theupriser/fix/fremont-cec
fix: HDMI-CEC on the Steam Machine
2026-09-26 11:30:29 +02:00
theupriser c510f9e2e5 fix: HDMI-CEC on the Steam Machine 2026-09-26 11:29:34 +02:00
theupriser 05a7d50c3f Merge pull request #22 from theupriser/docs/disclaimer
docs: Non-affiliation disclaimer in the README
2026-09-26 10:54:06 +02:00
theupriser badfd846d8 docs: Non-affiliation disclaimer in the README 2026-09-26 10:53:42 +02:00
theupriser ff364ffd69 Merge pull request #21 from theupriser/feat/app-shortcut
feat: The Steamify shortcut opens the app
2026-09-25 21:33:14 +02:00
theupriser 2b3f1de75a feat: The Steamify shortcut opens the app
Steamify CachyOS on the desktop and in the launcher starts the newest app
(in Konsole the first time, while PySide6 still has to be installed); the
terminal menu is Steamify Terminal in the launcher. A shortcut from before
2.0.1 is ticked in the menu, so a normal run replaces it. steamify-app.sh
leaves the shortcut's launcher entry (same id) alone.
2026-09-25 21:32:24 +02:00
theupriser 6d7d5861d6 Merge pull request #20 from theupriser/feat/v2-ui
Feat/v2 UI
2026-09-25 21:24:11 +02:00
theupriser 444ce29e57 Merge remote-tracking branch 'origin/main' into feat/v2-ui
# Conflicts:
#	AGENTS.md
#	CHANGELOG.md
#	lib/hdmi-refresh.sh
#	steamify.sh
2026-09-25 21:21:31 +02:00
theupriser 23ef5ef7ab feat(ui): HDMI refresh boost in the app
Set up… opens a screen with the display, its resolution and the rates on
offer. The display's own faster mode is switched to right away; the other
rates can each be tried live (wait for the picture, keep within 15 s or it
switches back) and ticked; Install installs the ticked ones through
apply --hdmi. All rates are loaded when the screen opens, so a try is only a
mode switch. Also fixes switching back to a rate like 59.97 Hz.
2026-09-25 21:21:13 +02:00
theupriser 178ee3405e fix(ui): The details panel scrolls instead of overflowing
Long texts (e.g. HDMI refresh boost) ran out of the card. The details are
in a Flickable now, which starts at the top for each item.
2026-09-25 20:42:08 +02:00
theupriser 601c05329d chore: Version 2.0.0 for the v2 app 2026-09-25 20:39:57 +02:00
theupriser 8ae9673eb2 Merge pull request #19 from theupriser/feat/hdmi-refresh-boost
Feat/hdmi refresh boost
2026-09-25 20:39:13 +02:00
theupriser dbafc43f2e feat(ui): HDMI refresh boost in the app, off only
The app gets its texts and the same rules as the menu: unticking Steam
Machine support or the kernel pin unticks it. It can't be turned on from
the app, as each step needs someone at the keyboard to confirm the picture.
2026-09-25 20:39:00 +02:00
theupriser ae8ed85fee feat: HDMI refresh boost and Update BIOS under Steam Machine support
Both are sub-options of Steam Machine support now, shown only while it is
ticked. Unticking it unticks them; unticking the kernel pin unticks the
HDMI refresh boost, which only works with the pinned kernel.
2026-09-25 20:37:56 +02:00
theupriser 00bcaea712 feat: HDMI refresh boost and Update BIOS under Steam Machine support
Both are sub-options of Steam Machine support now, shown only while it is
ticked. Unticking it unticks them; unticking the kernel pin unticks the
HDMI refresh boost, which only works with the pinned kernel.
2026-09-25 20:37:47 +02:00
theupriser a898d23b13 feat: HDMI refresh boost (Steam Machine, pinned kernel)
The pinned 7.1.6 kernel doesn't read the extra EDID block (HDMI Forum
EEODB) where monitors list their fast modes, and does no HDMI 2.1, so HDMI
displays often stay at 60 Hz. The new menu item reads the display's EDID
over DDC, calculates the highest rate that fits HDMI 2.0 at the desktop
resolution (rounded down to ten, plus the hundred below as a safe option),
tests each step live with a confirmation, and makes the confirmed ones
permanent through drm.edid_firmware (Limine, sdboot-manage or GRUB).
2026-09-25 20:33:46 +02:00
theupriser 3e53257fe2 feat: HDMI refresh boost (Steam Machine, pinned kernel)
The pinned 7.1.6 kernel doesn't read the extra EDID block (HDMI Forum
EEODB) where monitors list their fast modes, and does no HDMI 2.1, so HDMI
displays often stay at 60 Hz. The new menu item reads the display's EDID
over DDC, calculates the highest rate that fits HDMI 2.0 at the desktop
resolution (rounded down to ten, plus the hundred below as a safe option),
tests each step live with a confirmation, and makes the confirmed ones
permanent through drm.edid_firmware (Limine, sdboot-manage or GRUB).
2026-09-25 20:32:46 +02:00
theupriser a1eab9ac79 feat: Preview builds of feat/v2-ui; the app stretches to the window
Pushes to feat/v2-ui publish the pre-release v2-ui-preview (never latest);
its steamify-app.sh downloads that build (STEAMIFY_RELEASE). The app's
1280x720 layout now stretches to the window's shape, so the bars reach the
edges; re-apply resets when back on the menu.
2026-09-25 16:04:59 +02:00
theupriser c9c16b9eec fix(ui): Review and progress lists scroll; progress follows the running step 2026-09-25 16:02:19 +02:00
theupriser b17addd60f fix: Quote the backend's done event for shellcheck 2026-09-25 16:00:12 +02:00
theupriser ac613f05b3 feat: GitHub builds the app; run it with curl
steamify-app.tar.gz (ui/, steamify.sh, lib/, icon) and its launcher
steamify-app.sh in every release: it installs to ~/.local/share/steamify/app,
installs PySide6 if needed, adds a launcher entry and starts the app.
STEAMIFY_BRANCH=<branch> runs a branch before it's released.
2026-09-25 15:59:47 +02:00
theupriser 3a0eefab11 fix(ui): Applying got stuck: the ticked items came in as a JS value
Convert QML's array; if starting fails anyway, show the done screen with
the reason instead of staying on the progress screen.
2026-09-25 15:56:41 +02:00
theupriser 96558a9ca8 feat(ui): BIOS check runs invisibly, then the warnings, then the progress bar 2026-09-25 15:55:15 +02:00
theupriser 7c48b3d806 feat: BIOS update in the app, with both warnings
bios_enable split into bios_prepare (download, checksum, fwupd check) and
bios_flash; the terminal flow is unchanged. The app: check, warning 1,
warning 2 (type UPDATE, or hold A/OK for 5 seconds), flash, restart.
2026-09-25 15:53:30 +02:00
theupriser 396459b511 fix(ui): Controls aligned on the right, sub-items fold instead of the list jumping 2026-09-25 15:48:38 +02:00
theupriser 43a9541104 feat: Steamify app (v2 UI), first working version
ui/steamify-ui (PySide6 + QML): menu, review, password, applying and done
screens from the design, scaled to the window. Controller via evdev,
keyboard, TV remote (cecd). steamify.sh --backend status|apply (lib/backend.sh)
drives the same components; sudo asks through an askpass helper.
2026-09-25 15:46:02 +02:00
theupriser e09fe1609b Merge pull request #18 from theupriser/fix/no-lock-before-restart
fix: No lock screen in single user mode before a restart
2026-09-25 14:10:52 +02:00
theupriser 9dcac5cf08 fix: No lock screen in single user mode before a restart
The screen locker only read kscreenlockerrc at the next login, so the PC
still locked after idling until then. Reload it over D-Bus.
2026-09-25 14:01:00 +02:00
theupriser f91dd1f0b1 Merge pull request #16 from theupriser/fix/cec-steam-ui
Fix/cec steam UI
2026-09-25 13:18:52 +02:00
theupriser 0411429654 chore: Version 1.1.3 2026-09-25 13:17:02 +02:00
theupriser 1aa5e955fe fix: Repair HDMI-CEC set up by 1.1.0/1.1.1
It only counts as on with the steam-launcher drop-in; installed without it,
the menu ticks it, so a normal run adds it.
2026-09-25 13:16:48 +02:00
theupriser ce75e895c4 fix: Show the HDMI-CEC settings in Steam
CachyOS's gaming mode script sets STEAM_ENABLE_CEC=0. A drop-in for
steam-launcher.service overrides it with a later EnvironmentFile=.
2026-09-25 13:16:48 +02:00
theupriser 9aef0a986a Merge pull request #15 from theupriser/fix/cec-steam-settings
fix: Steam's HDMI-CEC settings reach cecd on a first run
2026-09-25 12:19:54 +02:00
theupriser f7aa2412df fix: Steam's HDMI-CEC settings reach cecd on a first run
HDMI-CEC runs before Steam Machine support, which installs steamos-manager,
so its configure-cecd unit couldn't be enabled. Link them from Steam Machine
support too.
2026-09-25 11:13:53 +02:00
theupriser 87162efaa2 Merge pull request #14 from theupriser/perf/pin-kernel-first
Perf/pin kernel first
2026-09-25 10:09:27 +02:00
theupriser c79a3bbda5 fix: No LED warnings when the kernel pin just replaced the running kernel 2026-09-25 10:08:06 +02:00
theupriser ba11f58d9e perf: Pinned kernel before the LED driver; steamos-manager after cecd
With the kernel pin ticked, install 7.1.6-1 before the LED driver, so DKMS
builds it once. steamos-manager checks for cecd only at its start: order it
after cecd.
2026-09-25 10:04:18 +02:00
theupriser 45ff036f09 Merge pull request #13 from theupriser/feat/hdmi-cec
Feat/hdmi cec
2026-09-25 09:53:29 +02:00
theupriser de02f267f4 docs: README's Steam Machine part lists its features, HDMI-CEC included 2026-09-25 09:50:55 +02:00
theupriser 0f123004d0 docs: CEC.md, which PCs have HDMI-CEC and how to add it 2026-09-25 09:47:22 +02:00
theupriser 3048b35dd8 feat: HDMI-CEC ticked by default on a Steam Machine 2026-09-25 09:18:28 +02:00
theupriser f7837f82b9 fix: Restart steamos-manager after HDMI-CEC changes
It only offers Steam its HDMI-CEC settings when cecd was there at its start.
2026-09-25 09:17:05 +02:00
theupriser 3eb41eef5a feat: HDMI-CEC with Valve's cecd, on any PC
Opt-in menu item: cecd, cec-audio-control and inputattach-cec-units from
Valve's holo repository (SHA-256 checked). Works with any /dev/cec*.
2026-09-25 09:11:44 +02:00
theupriser 41422e5bb4 chore: Version 1.0.0 2026-09-25 08:44:49 +02:00
theupriser 6c2e203563 fix: No second sudo password prompt while installing yay
makepkg -si installs with sudo -k, which forgets the cached password.
Build with makepkg, install with sudo pacman -U.
2026-09-25 08:35:54 +02:00
theupriser 1522e5632d feat: No more KDE wallet password prompts in single user mode
Valve's empty, password-less wallet, like SteamOS. The user's wallet is
moved aside and restored when single user mode is off; the single user
wallet is kept and reused next time.
2026-09-25 08:27:50 +02:00
theupriser 1d994ae359 docs: Add LICENSE.md (MIT) 2026-09-25 08:22:11 +02:00
theupriser 700f3e514b docs: README links to the files it mentions; drop setup-gamescope-boot.sh
The release no longer publishes the bundle under its pre-0.9.0 name.
2026-09-25 08:18:40 +02:00
theupriser d78652c862 docs: Shorter README, with a Steam Machine section
How it works moved to TECHNICAL.md, problems to TROUBLESHOOTING.md.
2026-09-25 08:17:07 +02:00
theupriser 727e6a2302 feat: Kernel files from our own release, checked before install
The kernel-7.1.6-1 release is the first download source. Every file must
match the SHA-256 in the script and have a valid CachyOS signature.
2026-09-25 08:08:28 +02:00
theupriser c4bd1ca39c feat: Pin the kernel to 7.1.6-1 on a Steam Machine
Sub-option of Steam Machine support, ticked along with it: newer CachyOS
kernels make the Steam Machine reboot instead of shutting down. Packages
are kept in /var/cache/steamify/kernel and reinstalled from there; else
pacman's cache, the CachyOS archive or mirror, or PINNED_KERNEL_URL.
2026-09-25 07:58:02 +02:00
theupriser a449a9e467 Enhance kernel installation and header management
Updated kernel installation process to include header symlink setup and improved logging messages.
2026-09-24 22:01:54 +02:00
theupriser 388b1286c9 Implement kernel installation and locking function
Adds a function to install and pin a specific CachyOS kernel with verification and locking.
2026-09-24 21:39:15 +02:00
theupriser 508f22acaf Merge pull request #11 from theupriser/feat/boot-into-desktop
Feat/boot into desktop
2026-09-24 13:35:24 +02:00
theupriser 3f8e0372d1 fix: Messages say which way it boots
"boot into: gamescope (from the next boot)" instead of "turn off: Boot into the desktop instead of gaming mode"; also in the progress line and the Done overview.
2026-09-24 13:30:56 +02:00
theupriser bd90e29e7a feat: Left/Right arrows choose on the "Boot into" row
Left = gamescope, right = desktop (Space still switches); the row says ←/→ choose and the key help lists Left/Right.
2026-09-24 13:28:14 +02:00
theupriser 4895de3a46 feat: "Boot into" is a sub-option of the conversion
Shown indented under the SteamOS conversion, and only while it's ticked.
2026-09-24 13:27:02 +02:00
theupriser 0f503dd112 feat: Boot into gamescope or the desktop
- Menu row "Boot into: [gamescope] / desktop" under the conversion; gamescope is the default.
- Desktop: steamify-boot-desktop.service sets the autologin session to Plasma at every boot, before the login manager; switching back and forth keeps working.
- VERSION 0.10.0.
2026-09-24 13:24:52 +02:00
theupriser d7cf0c0491 Merge pull request #10 from theupriser/bugfix/dkms-for-leds
Bugfix/dkms for leds
2026-09-24 12:57:33 +02:00
theupriser 5ab83d6e6f feat: Restart question on quit is "Restart now? [Y/n]"
When a restart is needed, q asks with yes as the default; n goes back to the menu and the next q asks again. Ctrl+C quits without restarting; scripted input that runs out never restarts.
2026-09-24 12:55:51 +02:00
theupriser 2e107e537e fix: LED driver for every kernel on a fresh install
The DKMS override was written to /etc/dkms before dkms was installed, when that folder doesn't exist yet: the write failed silently and other kernels (e.g. LTS) built against the running one and failed. Create the folder first and stop on a failed write. VERSION 0.9.1.
2026-09-24 12:55:38 +02:00
theupriser 986b3c8c07 Merge pull request #9 from theupriser/fix/use-cachyos-vapor
Fix/use cachyos vapor
2026-09-24 12:41:23 +02:00
theupriser afc05b0b23 feat: The shortcut's window closes itself after a countdown
- 10-second countdown after the wizard ends (Enter closes right away); after an error it waits for Enter.
- pipefail, so a failed download counts as an error.
2026-09-24 12:40:48 +02:00
theupriser b0553aecf7 docs: Shorter README intro 2026-09-24 12:34:43 +02:00
theupriser 69a420b8aa feat: The script is now steamify.sh
- setup-gamescope-boot.sh renamed to steamify.sh; all references updated.
- Releases publish the bundle as steamify.sh and, for older install commands, setup-gamescope-boot.sh.
- The Steamify shortcut runs steamify.sh.
2026-09-24 12:33:43 +02:00
theupriser 1c34a97598 chore: Repository renamed to steamify-cachyos
All URLs point to github.com/theupriser/steamify-cachyos (the old ones redirect). The script and internal names (state dir, shortcut files) keep their names so old download URLs and existing installs keep working.
2026-09-24 12:27:45 +02:00
theupriser be874b8594 feat: Rename to Steamify CachyOS
Menu header, shortcut, release titles, README and AGENTS.md. Repository, script and URLs keep the name cachyos-gamescope-boot.
2026-09-24 12:24:50 +02:00
theupriser f01aa93d0e feat: Wizard shortcut on the desktop and in the launcher
- Menu item: desktop icon + launcher entry that run the newest release in Konsole.
- Icon: Valve's return icon with a gear (assets/steam-gaming-settings.svg), published with each release.
- Desktop files are written already executable, so Plasma runs them.
- VERSION 0.9.0.
2026-09-24 11:46:25 +02:00
theupriser 852205317a Merge pull request #8 from theupriser/fix/use-cachyos-vapor
Fix/use cachyos vapor
2026-09-24 10:57:03 +02:00
theupriser 77b94c29a2 fix: Merge remote-tracking branch 'origin/main' into fix/use-cachyos-vapor 2026-09-24 10:55:55 +02:00
theupriser c0014ee623 docs: 0.7.0 was released on its own (#6, #7) 2026-09-24 10:55:55 +02:00
theupriser d39731a8b9 docs: Last commit hash in the changelog 2026-09-24 10:55:27 +02:00
theupriser 99a95abf1f fix: Kernel legend only mentions the LEDs on a Steam Machine 2026-09-24 10:54:33 +02:00
theupriser 429e840a9f fix: Shorter BIOS labels so the menu fits 80 columns 2026-09-24 10:51:53 +02:00
theupriser 45a8757f58 fix: BIOS dry run also walks through the restart choices
A dry run counts as staged, so [m]/[r] and the restart question on q show up; restarting only prints in dry-run mode.
2026-09-24 10:48:39 +02:00
theupriser 54fc9e362b feat: Menu comes back after each run, BIOS dry run, version 0.8.0
- After a run the menu returns; [m] back to the menu or [r] restart now when a restart is needed; q quits.
- A staged BIOS update greys the item out until the restart.
- WIZARD_BIOS_DRY_RUN=1: whole BIOS flow without the device check, never flashes.
- VERSION 0.8.0; CHANGELOG: BIOS work moved to 0.8.0; README: BIOS update step by step.
2026-09-24 10:40:16 +02:00
theupriser b70c9d614f fix: shellcheck in the bundle, and the docs for the BIOS checks
- Rename a variable in lib/bios.sh that clashed with lib/state.sh's array in the bundle.
- README, AGENTS.md and CHANGELOG.md for the greyed-out item, the device check and the aligned warning box.
2026-09-24 10:30:24 +02:00
theupriser 40c9ee638b fix: BIOS update only when newer, device check first, aligned warnings
- Greyed out and not tickable unless Valve has a newer BIOS (component_selectable).
- Download, SHA-256 and a fwupd device check (get-details) before the warnings.
- Warning box with a solid block frame (a coloured row of # renders narrower in Konsole); menu Now column aligned.
2026-09-24 10:29:46 +02:00
theupriser 2f9b2a54e1 feat: Opt-in BIOS update for the Steam Machine
- Menu item (Fremont only, never preselected) with the current and newest BIOS version.
- Two warnings and two confirmations (y/N, then typing UPDATE); checksum-verified download
  of Valve's fremont-hw-support; installed with fwupd, written at the next restart.
- Menu actions: one-off items that are never preselected, re-applied or listed as on/off.
2026-09-24 10:22:15 +02:00
theupriser 53f53a77ff Merge pull request #7 from theupriser/fix/use-cachyos-vapor
Fix/use cachyos vapor
2026-09-24 10:11:31 +02:00
theupriser 6afef78721 ci: The latest tag follows the newest version tag
When v$VERSION is released, move the latest tag and release to it and replace its bundle, so the older install URL keeps giving the newest version.
2026-09-24 10:09:26 +02:00
theupriser 1604ed10d4 docs: Versioning and release rules in AGENTS.md 2026-09-24 10:08:22 +02:00
theupriser 8aab946c6f ci: A release per version (tag v0.7.0, ...) instead of overwriting "latest"
- Publish release v$VERSION with its CHANGELOG.md section; never overwrite an existing version.
- Pull requests warn when VERSION is already released.
- Install URL: releases/latest/download/setup-gamescope-boot.sh (newest release).
2026-09-24 10:07:56 +02:00
theupriser 5cbe0079cb Merge pull request #6 from theupriser/fix/use-cachyos-vapor
Fix/use cachyos vapor
2026-09-24 10:06:21 +02:00
theupriser 5c00504261 docs: Commit hashes in the changelog 2026-09-24 10:04:55 +02:00
theupriser d7231ebbd8 chore: Move the bundle tool to .github/tools/bundle.sh
Update its repo-root path and all references (workflow, README, AGENTS.md).
2026-09-24 10:04:29 +02:00
theupriser eb3169efa1 ci: Version and changelog in the release notes
- Release title shows VERSION; notes include that version's CHANGELOG.md section.
- Rename a variable in steamos-extras.sh that shellcheck confused with lib/state.sh's array in the bundle.
2026-09-24 10:02:30 +02:00
theupriser 10b51644c9 docs: Version 0.7.0 and CHANGELOG
- VERSION in the entry point, shown in the menu header and the bundle.
- CHANGELOG.md with every commit per version (older versions numbered per merged PR).
- README and AGENTS.md updated for the cachyos-vapor theme, the SteamOS extras and the LED driver.
2026-09-24 10:01:08 +02:00
theupriser 7802d90186 fix: LED driver for every kernel, kernel headers at boot, console power button, kernel overview
- The leds-valve Makefile builds against uname -r, so every other kernel
  (e.g. linux-cachyos-lts) failed: add /etc/dkms/leds-valve-dkms.conf with
  MAKE[0]="make KVERSION=${kernelver}". DKMS now builds it for every
  installed kernel and rebuilds it on kernel updates.
- ensure-kernel-headers.service installs missing -headers for newly added
  kernels at boot, which makes DKMS build the driver for them.
- Console-like power handling on mains power: power button sleeps, no
  automatic suspend (journaled powerdevilrc).
- Menu: overview per installed kernel (headers, Steam controller driver,
  LED driver built, running kernel) and whether the LEDs are loaded.
- Menu: the selected row's highlight no longer stops after the green x.
- Theme label in the menu: "Vapor look (cachyos-vapor)".
2026-09-24 10:00:32 +02:00
theupriser 978f5a14cf feat: SteamOS theme from cachyos-vapor with its desktop layout, plus SteamOS desktop extras
- Install CachyOS's cachyos-vapor package instead of extracting Valve's
  steamdeck-kde-presets into ~/.local/share, and remove it again on disable
  if the wizard installed it.
- Apply the Vapor global theme with "Desktop and window layout"
  (lookandfeeltool --resetLayout): Steam Deck wallpaper, SteamOS panel and
  launcher icon. Layout files are backed up and restored, every key from
  Vapor's defaults goes through the undo journal.
- Restore the real previous color scheme (CachyOS's inline BreezeDark colors
  have no scheme name), and clear ColorScheme before plasma-apply-colorscheme,
  which otherwise skips an already named scheme.
- Register Vapor as the dark theme, so Plasma's Dark Mode toggle shows on.
- Drop the SteamOS desktop defaults (GTK, Konsole, gsettings, panel tweaks).
- New lib/steamos-extras.sh, downloaded from Valve's newest
  steamdeck-kde-presets (checksum verified) into /usr/local: Add to Steam,
  Nested Desktop, the gaming-return icon for Return to Gaming Mode, the
  Steam Keyboard window rule and an empty KWallet (only without a wallet).
- single_launcher: re-apply single user's launcher settings after the
  layout reset replaces the launcher.
2026-09-24 10:00:32 +02:00
theupriser a501df25b5 Update steam-machine.sh
Add inputplumber for the downloadbar.
2026-09-23 21:44:54 +02:00
theupriser 079c48f6fe Merge pull request #5 from theupriser/fix/review-cleanup
fix: Use curl | bash in the docs: bash <(...) doesn't work in fish
2026-09-23 15:42:01 +02:00
theupriser ee5391c126 Merge pull request #4 from theupriser/fix/review-cleanup
fix: Single-file build for curl, published by GitHub Actions
2026-09-23 15:38:31 +02:00
theupriser e741246098 Merge pull request #3 from theupriser/fix/review-cleanup
Fix/review cleanup
2026-09-23 15:27:58 +02:00
theupriser 9827bea8d5 Merge pull request #2 from theupriser/fix/review-cleanup
fix: Add single user no password option with SDDM, fetch newest Vapor…
2026-09-23 14:47:52 +02:00
theupriser dcc184ed39 Merge pull request #1 from theupriser/fix/review-cleanup
fix: Fix setup bugs, add SteamOS desktop look and LED driver, split i…
2026-09-23 14:25:28 +02:00
50 changed files with 544 additions and 1590 deletions

No files matched your search

-15
View File
@@ -1,15 +0,0 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
indent_style = space
indent_size = 4
[*.{yml,yaml,qml}]
indent_size = 2
[Makefile]
indent_style = tab
+8 -14
View File
@@ -40,7 +40,7 @@ jobs:
- name: Check
run: |
bash -n dist/steamify.sh
python3 -c 'import ast, sys; [ast.parse(open(f).read(), f) for f in sys.argv[1:]]' ui/steamify-ui patches/*.py
python3 -m py_compile ui/steamify-ui
# shellcheck through an action that brings its own binary: GitHub's runner has it installed,
# Gitea's act_runner image doesn't. One file per run, as before (the exceptions are the bundle's).
@@ -192,18 +192,14 @@ jobs:
dist/steamify-app.tar.gz
assets/steam-gaming-settings.svg
# A new version starts the Steamify ISO's release of the ISO repo: its iso-1-github-tag.yml (always run from
# master) names the ISO after the newest Steamify release, tags it, and the Gitea mirror builds and attaches the ISO.
# The branch here decides the kind of build (the workflow's input `kind`):
# main (publishes the release) -> release: a real ISO (tag v<steamify>-<date>)
# release/** (a version not yet released) -> dev: a pre-release (tag v<steamify>-dev.<date>)
# Needs a fine-grained token for that repo (Actions: read and write) as the secret ISO_DISPATCH_TOKEN;
# without it, this is skipped.
# A new Steamify release starts the Steamify ISO's release with it (a test build from the ISO repo's
# feat/steamify, until that is its master): its iso-release.yml names it after this version, tags it,
# and the Gitea mirror builds and attaches the ISO. Needs a fine-grained token for that repo
# (Actions: read and write) as the secret ISO_DISPATCH_TOKEN; without it, this is skipped.
- name: Start the Steamify ISO's release
if: >-
github.server_url == 'https://github.com' &&
github.event_name != 'pull_request' &&
(github.ref == 'refs/heads/main' || startsWith(github.ref, 'refs/heads/release/')) &&
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
steps.version.outputs.released == 'false'
env:
GH_TOKEN: ${{ secrets.ISO_DISPATCH_TOKEN }}
@@ -211,7 +207,5 @@ jobs:
if [ -z "$GH_TOKEN" ]; then
echo "::notice::No ISO_DISPATCH_TOKEN: the Steamify ISO isn't released with this version."; exit 0
fi
# A release branch builds the ISO with its own code (and VERSION): steamify_ref. main builds the release it just published.
if [ "$GITHUB_REF" = refs/heads/main ]; then kind=release; sref=""; else kind=dev; sref="$GITHUB_REF_NAME"; fi
gh workflow run iso-1-github-tag.yml -R theupriser/steamify-cachyos-live-iso --ref master -f kind="$kind" -f steamify_ref="$sref"
echo "Started the Steamify ISO's release (theupriser/steamify-cachyos-live-iso, master, kind $kind, Steamify ${sref:-the newest release})"
gh workflow run iso-release.yml -R theupriser/steammachine-cachyos-live-iso --ref feat/steamify
echo "Started the Steamify ISO's release (theupriser/steammachine-cachyos-live-iso, feat/steamify)"
-26
View File
@@ -1,26 +0,0 @@
name: Sync git.upriser.nl mirror
# Trigger the Gitea pull-mirror immediately instead of waiting for its interval,
# so Gitea builds/tests right after any branch or tag lands on GitHub (the mirror has no sync interval of its own).
on:
push:
branches: ['**']
tags: ['*']
workflow_dispatch:
jobs:
sync:
# Gitea also reads .github/workflows on the mirror; only run on GitHub
if: github.server_url == 'https://github.com'
runs-on: ubuntu-latest
steps:
- name: Trigger mirror-sync
env:
GITEA_URL: ${{ secrets.GIT_UPRISER_URL }}
GIT_UPRISER_TOKEN: ${{ secrets.GIT_UPRISER_TOKEN }}
# Gitea "owner/repo"; defaults to the same path as on GitHub
GITEA_REPO: ${{ vars.GITEA_REPO || github.repository }}
run: |
curl --fail-with-body -sS --retry 5 --retry-delay 10 --retry-all-errors -X POST \
-H "Authorization: token ${GIT_UPRISER_TOKEN}" \
"${GITEA_URL%/}/api/v1/repos/${GITEA_REPO}/mirror-sync"
-60
View File
@@ -1,60 +0,0 @@
# Lint: shell, Python and QML. Separate from bundle.yml (which builds and
# releases) so a style problem shows up as its own check. Runs on GitHub and on
# the Gitea mirror; the same checks locally: make check.
name: Lint
on:
push:
branches: [main, 'release/**']
pull_request:
workflow_dispatch:
permissions:
contents: read
jobs:
shell:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# The sources, not only the bundle (bundle.yml checks that): .shellcheckrc
# lists the exceptions (variables shared across modules).
- name: shellcheck the modules
uses: ludeeus/action-shellcheck@2.0.0
with:
severity: warning
scandir: lib
additional_files: steamify.sh ui/steamify-app.sh .github/tools/bundle.sh
# steamify-os-release.sh is a template (@STEAMOS@ is filled in at install time).
- name: shellcheck the helper scripts
uses: ludeeus/action-shellcheck@2.0.0
with:
severity: warning
scandir: patches
ignore_names: steamify-os-release.sh
python:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: ruff (ruff.toml)
uses: astral-sh/ruff-action@v4.1.0
with:
args: check ui/steamify-ui patches
qml:
runs-on: ubuntu-latest
# Not blocking until it has run once on the runner image (Qt packages).
continue-on-error: true
steps:
- uses: actions/checkout@v4
- name: Install qmllint and the QML modules the app imports
run: |
sudo apt-get update -qq
sudo apt-get install -y -qq qt6-declarative-dev-tools qml6-module-qtquick qml6-module-qtquick-controls qml6-module-qtquick-window
# "unqualified" (a screen reading `app` from its parent) is how the screens get their
# AppState, so it is off; everything else must be clean.
- name: qmllint
run: |
lint="$(command -v qmllint6 || echo /usr/lib/qt6/bin/qmllint)"
"$lint" --unqualified disable --max-warnings 0 ui/qml/*.qml
-2
View File
@@ -1,2 +0,0 @@
# The modules share variables across files once bundled (see AGENTS.md).
disable=SC2034,SC2154
+7 -52
View File
@@ -47,20 +47,13 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
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 are the `REQUIRES`, `FOLLOWS` and `EXCLUDES` tables in `lib/menu.sh`, used by `toggle_component` (the menu) and `normalize_wanted` (the app).
- **NVIDIA** (`lib/nvidia.sh`): gamescope's session is broken on NVIDIA, so the SteamOS conversion (`gaming`, `boot`, `single`,
`glyphs`) is hidden there (unless already on) and `nvidia` + its sub-option `bigpicture` ("Gaming on NVIDIA") replace it:
Steam on the Plasma desktop, started at login. Never reintroduce a gamescope session for NVIDIA without re-testing on the
hardware (notes: steamify-cachyos-dev, `nvidia/`). It can't be tested without the hardware: keep the branch behind
`.no-release-yet` until it was.
`gaming` must stay first. Dependencies live in `toggle_component`.
- **Feature versions.** Set `FEATURE_VERSION[<id>]` (`lib/menu.sh`) to the new
`VERSION` whenever what `<id>_enable` sets up changes (a new component gets
one too): installs recorded with an older version
are ticked and re-applied ("update" in the plan and the app). New default
options are ticked for installs whose parent (top-level: `gaming`) is on
(`feature_new`, shown as "new"). New opt-in options (`NO_PRESELECT`) get the
same "new" badge without being ticked (`feature_new_optin`). Both count "Gaming
on NVIDIA" as a parent where the conversion isn't offered.
(`feature_new`, shown as "new").
Options shown but left unticked in a confirmed run are recorded as
`off` (`feature_record_unticked`), or `feature_new` would tick them again.
Status still comes from the system; don't add ad-hoc `<id>_repair` checks
@@ -75,13 +68,6 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
the entry point's `for lib in ...; do` source loop and wraps everything
after that loop in `main()`. Keep that loop on one line, keep all logic in
functions, and don't rely on `SCRIPT_DIR` for anything but sourcing.
The workflow is one file for GitHub and a Gitea mirror (`github.server_url`): build and check run on both
(shellcheck through `ludeeus/action-shellcheck`, which brings its own binary; the artifact with
`upload-artifact@v4` on GitHub and `christopherhx/gitea-upload-artifact@v4` elsewhere: never mention
`upload-artifact@v3`, GitHub fails a workflow for a deprecated version even in a skipped step); the
release is `gh` on GitHub and `akkuman/gitea-release-action` on Gitea. A new release on GitHub also starts the
Steamify ISO's release (`gh workflow run iso-1-github-tag.yml` in steamify-cachyos-live-iso, secret
`ISO_DISPATCH_TOKEN`; skipped without it): the ISO repo's GitHub tag names it, the Gitea mirror builds it.
CI (`.github/workflows/bundle.yml`) publishes the bundle as release
`v$VERSION` on pushes to `main`; an existing version is never overwritten,
so bump `VERSION` for every release.
@@ -90,16 +76,6 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
- Bash, `set -uo pipefail` (no `-e`): check exit codes of steps that matter
explicitly (`|| { err ...; exit 1; }` or `|| return 1`).
- **Failure and quiet steps.** A function returns 0 when what it was asked
to do is in place and 1 when it isn't (after `err`); a step that is only an
extra (an icon cache, a service that may not exist) warns or stays silent and
doesn't change the return value. Never `cmd 2>/dev/null` on a step that
changes the system: use `best_effort cmd...` (same exit status, its errors go
to `$STATE_DIR/log/steamify.log`). `2>/dev/null` stays for probes (`pacman -Q`,
`grep -q`, `is-active`) whose failure is the answer.
- **Temp dirs.** `make_tmpdir <variable>` (not `$(mktemp -d)`, whose
subshell can't register it): the entry point's `on_exit` removes them, also
when a run stops half way. That handler is the only `EXIT` trap.
- Use the helpers from `lib/common.sh` (`info`, `ok`, `warn`, `err`,
`ask_yn`, `backup_file`) for all output and prompts.
- Runs as the normal user; use `sudo` per command, never require root.
@@ -143,20 +119,7 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
`sudo apt install gh`, then `gh auth login`) instead of working around
it. Only the
release branch's pull request into `main` is the user's: never commit
or merge to `main`, the user merges that one. Never work directly on
`main` or a `release/*` branch either: edits, even uncommitted ones,
go on a `feature/`/`bugfix/` branch (create it before editing; the
release branch only gets the version-bump commit and merged PRs).
Don't push a new `release/*` branch before it's needed: a push can
start CI builds (a dev ISO).
A machine without a git identity: pass the repo's author per command
(`git -c user.name=... -c user.email=... commit`, taken from `git
log`) instead of changing the git config.
A `.no-release-yet` file at the root of a feature/bugfix branch means
it must not be merged into the release branch yet (work in progress,
untested on hardware). When the feature is complete, ask the user
whether it may be released; on a yes, delete the file, then open the
pull request and merge it.
or merge to `main`, the user merges that one.
Keep a feature/bugfix branch up to date by merging (or rebasing on)
its release branch, the release branch by merging `main` when that
moved.
@@ -166,12 +129,9 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
a warning when `VERSION` is a version that's already released (so a
release branch that forgot its bump shows it on every PR).
- A release that adds, removes or renames a menu row also retakes the
README screenshots (`assets/screenshot-menu-steam-machine.png` and
`assets/screenshot-menu-nvidia.png`, side by side in the README): the app from the branch on a Steam Machine and on a PC
with an NVIDIA card, every row visible and each window only as tall as its options need, the header showing the new
`VERSION`, 1600 px wide. Size the window with a KWin script (match the `steamify-ui` class exactly: a title match also hits
Konsole and editor windows) and crop the full-screen capture to the client rectangle; mind the display scale (the Steam
Machine runs at 1.75).
README screenshot (`assets/screenshot-menu.png`): the app from the
branch on a Steam Machine, every row visible (window 1280 wide, tall
enough), the header showing the new `VERSION`, scaled to 1600 px wide.
- Users install through `releases/latest/download/steamify.sh`
(GitHub's newest release). The `latest` tag and release follow the newest
version tag too (moved, asset replaced, when a new version is released),
@@ -292,11 +252,6 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
kernel only pairs that with a named lookup ("Port C") when the CEC driver
registered first, which never happens since amdgpu loads from the
initramfs. Without it `/dev/cec0` exists but stays at `f.f.f.f`.
The source comes from one raw.githubusercontent.com download, which GitHub rate-limits (HTTP 429 after a
day of test installs, per address): it's kept in `/var/cache/steamify/cros-ec-cec-<sha256:12>.c` and reused
while its checksum matches. The name carries the checksum, so a new pin (commit + SHA-256 in `lib/cec.sh`)
downloads its own file once and removes the old one. The repo is an unofficial mirror of Valve's kernel
without releases: if it ever disappears, ship the file with Steamify. The test VMs share the host's cache.
- Power-off fix (`poweroff`, `lib/fremont-poweroff.sh`, a default sub-option
of `machine`): recent kernels (7.2 and the 6.x/7.0/7.1 updates with the
backport) keep the firmware's S4/S5 wake bit on GPIO
@@ -341,7 +296,7 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
(`state_get vram installed_pkgs`).
- Install-time mode (`steamify.sh --defaults`, 2.6.0): applies what the menu
would preselect, no menu or prompts (needs passwordless sudo). The Steam
Machine ISO ([steamify-cachyos-live-iso](https://github.com/theupriser/steamify-cachyos-live-iso))
Machine ISO ([steammachine-cachyos-live-iso](https://github.com/theupriser/steammachine-cachyos-live-iso))
runs it in the installer for a user who has never logged in: no session
bus, user systemd or plasmashell. So every `systemctl --user` goes through
`user_systemctl` (`lib/common.sh`; without a session only unit files change,
-59
View File
@@ -5,65 +5,6 @@ All notable changes, per version and per commit. Versions follow
`steamify.sh`. Versions before 0.7.0 were numbered afterwards,
one per merged pull request.
## Unreleased
- **refactor: Valve's package mirror in one module (`lib/valve-mirror.sh`: newest repo, package database fields, checksummed download); the SteamOS extras, CEC driver, BIOS lookup and os-release version used four copies**
- **refactor: the rules between menu items are three tables (`REQUIRES`, `FOLLOWS`, `EXCLUDES` in `lib/menu.sh`) used by the menu's toggles and, as `normalize_wanted`, by the app's selection (it had its own copy of the rules). The app now also ticks the Steamify shortcut for "Add as non-Steam game" and unticks the game entry with it, like the menu**
- **refactor: the entry point picks its mode once (`MODE`) and `--defaults` and `--boot` are functions with one failure report, instead of four booleans and two copies of the apply-and-report code; `NO_COLOR` gives plain output**
- **refactor: `is_wanted` and `is_current` instead of repeated `[[ "${WANTED[x]}" == 1 ]]` checks in the menu, the app's backend and the entry point**
- **refactor: the start of every item's JSON (id, label, hint, kind, parent) is built in one place (`json_item_head`) for the app and the installer page, and `json_bool` replaces the `&& echo true || echo false` copies**
- **ci: a Lint workflow runs shellcheck on the modules and helper scripts, ruff on the app and `patches/*.py` (`ruff.toml`) and qmllint on the QML (not blocking until it has run once on the runner); `make lint` runs the same locally**
- **refactor: `best_effort` for the steps whose failure doesn't matter (stopping or disabling units, removing packages, `modprobe -r`, ...): same behaviour, but their errors go to `~/.local/state/steamify/log/steamify.log` instead of `/dev/null`; temp dirs are registered with `make_tmpdir` and removed by the one exit handler (also when a run is interrupted), which replaces the menu's own `EXIT` trap**
- **refactor: the retired kernel pin moved out of `lib/steam-machine.sh` into `lib/kernel-pin.sh`**
- **refactor: the shortcut's two start scripts are files in `patches/` (`steamify-start.sh`, `steamify-app-start.sh`) instead of heredocs in `launcher_enable`, and the 83-line LED driver install is split into steps (`led_write_dkms_override`, `led_install_package`, `led_build_all_kernels`, `led_load_module`); what gets installed is byte-identical**
- **fix: the daily update check no longer crashes on a release tag that isn't a plain version number (`TypeError` comparing it, found by the new unit tests); it is simply never offered**
- **refactor: `theme_enable` and `create_desktop_shortcut` split into steps; the Return to Gaming Mode shortcut is written with its mode already set (`install_executable`), like the other shortcuts, instead of chmod afterwards**
- **test: the menu rules, the plan and the app's and installer's JSON are checked against a golden file (`tests/menu-test.sh` in steamify-cachyos-dev); `make check`, `.editorconfig`, `.shellcheckrc`**
- **docs: README lists the sources and projects Steamify builds on, with licences and thanks**
## 2.11.1 - 2026-10-02
- `d70aeb8` **docs: new README screenshots of the app (2.11 menu) on a Steam Machine and on an NVIDIA PC, and the README names the opt-in "Start Steam silently in desktop mode" and the icons as an option of the conversion**
## 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
- `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**
- `d1373e2` **feat: single user mode also works on NVIDIA PCs, without the SteamOS conversion**
- `5811f5c` **fix: "Add as non-Steam game" isn't offered on NVIDIA PCs (shown when already on, so it can be turned off)**
- `83248a8` **feat: Extended controller support (extended_controller_support, off by default): the Xbox wireless dongle (xone) and Xbox controllers over Bluetooth with rumble and battery level (xpadneo), built for every installed kernel; off removes only what Steamify installed**
- `01a77b7` **feat: a new opt-in option (unticked by default) shows the "new" badge in the menu and the app**
- `f1983a9` **docs: README screenshots of the 2.10.0 app, side by side: on a Steam Machine and on a PC with an NVIDIA card**
## 2.9.6 - 2026-09-30
- **fix(ci): a dev ISO from a release branch is built with that branch's own Steamify (input steamify_ref of the ISO workflow), not the newest published release: release/2.9.6 kept producing 2.9.5 ISOs**
- **docs: changelog hashes for 2.9.6**
- `9a2965d` **fix(ci): the ISO workflow always runs from master; main asks for a release ISO, a release branch for a dev ISO (input `kind` of iso-1-github-tag.yml; feat/steamify is no longer needed)**
- `c42d545` **fix(ci): a version published from main starts a real ISO release, a release branch a dev ISO (it always started the dev one)**
- `b3bed43` **chore: Version 2.9.6**
## 2.9.5 - 2026-09-30
- `70ecb56` **ci: trigger a mirror sync**
- `a7276cf` **ci: sync the git.upriser.nl mirror on every branch and tag**
- `b3549d4` **ci: sync the mirror on release branch pushes too**
- `a232a55` **feat(ci): sync the git.upriser.nl mirror on every push to main and every tag (git-upriser-sync.yml calls the mirror-sync API: the Gitea mirror builds at once instead of at its interval; secrets GIT_UPRISER_URL and GIT_UPRISER_TOKEN, retried, skipped on Gitea itself)**
- `3676c64` **docs: link the renamed steamify-cachyos-live-iso repo (the release dispatches the ISO workflow iso-1-github-tag.yml there)**
- `971e792` **chore: Version 2.9.5**
## 2.9.4 - 2026-09-29
- `619ef1f` **docs: AGENTS.md and TECHNICAL.md: the CEC driver cache, the one workflow for GitHub and a Gitea mirror, and that a new release starts the Steamify ISO's release**
- `b624053` **chore: Version 2.9.4**
## 2.9.3 - 2026-09-29
- `7f5d29c` **feat(ci): a new Steamify release starts the Steamify ISO's release (a test build from the ISO repo's feat/steamify; secret ISO_DISPATCH_TOKEN)**
-34
View File
@@ -1,34 +0,0 @@
# Local checks, the same as CI's: make check
SH := steamify.sh $(wildcard lib/*.sh) ui/steamify-app.sh .github/tools/bundle.sh
# The unit tests live in ../steamify-cachyos-dev/tests (REPO points at this checkout).
DEV ?= ../steamify-cachyos-dev
# Not the hardware test: it is for a real NVIDIA PC and writes a report in $$HOME.
TESTS := $(filter-out %-hardware-test.sh,$(wildcard $(DEV)/tests/*-test.sh))
.PHONY: check syntax lint lint-sh lint-py lint-qml test bundle fmt-check
check: syntax lint test bundle
syntax:
@for f in $(SH); do bash -n "$$f" || exit 1; done
python3 -c 'import ast, sys; [ast.parse(open(f).read(), f) for f in sys.argv[1:]]' ui/steamify-ui patches/*.py
lint: lint-sh lint-py lint-qml
lint-sh:
@command -v shellcheck >/dev/null && shellcheck -S warning $(SH) || echo "shellcheck not installed: skipped"
lint-py:
@command -v ruff >/dev/null && ruff check ui/steamify-ui patches || echo "ruff not installed: skipped"
lint-qml:
@Q="$$(command -v qmllint6 || command -v qmllint || ls /usr/lib/qt6/bin/qmllint 2>/dev/null)"; \
[ -n "$$Q" ] && "$$Q" --unqualified disable --max-warnings 0 ui/qml/*.qml || echo "qmllint not installed: skipped"
test:
@for t in $(TESTS); do echo "== $$t"; REPO="$(CURDIR)" bash "$$t" || exit 1; done
bundle:
.github/tools/bundle.sh dist/steamify.sh
fmt-check:
@command -v shfmt >/dev/null && shfmt -d -i 4 -ci $(SH) || echo "shfmt not installed: skipped"
+4 -72
View File
@@ -1,14 +1,6 @@
# Steamify CachyOS
The Steamify app's menu. On a Steam Machine (or any PC with an AMD or Intel
graphics card) it offers the full SteamOS conversion, on the left. On a PC with
an NVIDIA graphics card gamescope's gaming mode shows a corrupted picture, so the
menu offers **Gaming on NVIDIA** instead (Steam on the desktop, started at login,
optionally in Big Picture), on the right.
| On a Steam Machine | On a PC with an NVIDIA graphics card |
|---|---|
| ![The Steamify app's menu on a Steam Machine](assets/screenshot-menu-steam-machine.png) | ![The Steamify app's menu on a PC with an NVIDIA graphics card](assets/screenshot-menu-nvidia.png) |
![The Steamify app's menu on a Steam Machine](assets/screenshot-menu.png)
Turn a CachyOS desktop PC into a SteamOS-style console: it boots straight
into Steam's Big Picture (gamescope), and you can switch to the KDE Plasma
@@ -27,24 +19,14 @@ Steam Machine.
on the desktop too.
- **Boot into: gamescope / desktop** - where the PC starts. Gaming mode is
the default.
- **Start Steam silently in desktop mode** (off by default) - Steam starts
at login on the desktop, in the tray without a window. It is Steam's own
autostart entry, so Steam's setting "Run Steam when my computer starts"
follows it (the Linux Steam client has no silent option of its own).
- Steam's **System** settings show the SteamOS release Steamify follows
as OS Version (e.g. `steamos-3.9`), `steam-machine` as OS Codename and
Steamify's version as OS Variant. The OS name stays CachyOS
([details](TECHNICAL.md#what-steams-system-settings-show)).
- **NVIDIA graphics cards:** gamescope's gaming mode shows a corrupted
picture there (an open NVIDIA driver bug), so the conversion isn't
offered. **Gaming on NVIDIA** takes its place: Steam on the desktop,
installed if it's missing and started at login, in **Big Picture** or its
normal window as you choose
([details](TECHNICAL.md#gaming-on-nvidia)).
2. **SteamOS theme** - the Vapor look of SteamOS for the desktop, with
**Add to Steam** in right-click menus
([details](TECHNICAL.md#steamos-desktop-look)).
3. **Steam Deck/Machine icons** - Steam Deck button icons in gaming mode (an option of the SteamOS conversion).
3. **Steam Deck/Machine icons** - Steam Deck button icons in gaming mode.
4. **Single user mode** - like SteamOS: never a login or lock screen, and no
KDE wallet password prompts (e.g. from Brave). Typing a password with a
controller is no fun
@@ -55,7 +37,7 @@ Steam Machine.
With **Add as non-Steam game** (on by default) it's in your Steam library
too: started from Steam it gets your controller (a Steam Controller only
talks to Steam), in gaming mode as well. Steam closes for a moment while
it's added, so that's done from the desktop. Not offered on PCs with an NVIDIA graphics card, which have no gaming mode.
it's added, so that's done from the desktop.
6. **Update notifications** - on by default: a notification and a tray icon
when there's a new Steamify, with Open Steamify and Skip this version. It
never updates anything by itself
@@ -74,11 +56,6 @@ Steam Machine.
the Steam Machine) or a USB CEC adapter; most graphics cards, NVIDIA
included, don't have it. See [CEC.md](CEC.md) for which PCs do, and how to
add it to your own build ([details](TECHNICAL.md#hdmi-cec)).
9. **Extended controller support** (off by default) - the Xbox wireless
dongle (xone) and Xbox controllers over Bluetooth with rumble, the right
button mapping and the battery level (xpadneo). Both are installed from the
CachyOS repo and built for every installed kernel
([details](TECHNICAL.md#extended-controller-support)).
## Steam Machine
@@ -117,7 +94,7 @@ curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/downlo
```
Installing CachyOS on a Steam Machine? The
[Steamify CachyOS ISO](https://github.com/theupriser/steamify-cachyos-live-iso)
[Steamify CachyOS ISO](https://github.com/theupriser/steammachine-cachyos-live-iso)
has Steamify built into the installer: pick the options there, and the
first boot is already set up.
@@ -187,51 +164,6 @@ Contributing (or an AI agent)? Read [AGENTS.md](AGENTS.md).
MIT - do whatever you want with it. See [LICENSE.md](LICENSE.md).
## Sources and credits
Steamify is glue around other people's work. It installs, configures or
downloads the following, and doesn't claim any of it:
| Project | What Steamify uses it for |
|---|---|
| [CachyOS](https://cachyos.org) | The distribution it targets, and its packages: `cachyos-vapor` (the Vapor theme), the gamescope session packages (`gamescope-session-cachyos` and the autologin helpers), `dmemcg-booster` and `plasma-foreground-booster` (VRAM booster), and the `xone` / `xpadneo` DKMS packages (extended controller support) |
| [Valve / SteamOS](https://github.com/ValveSoftware/SteamOS) | The behaviour it imitates: SteamOS's session switching (`steam-set-session`, `steamos-manager`) and the Steam Deck UI. Downloaded from Valve's package mirror at install time, never shipped here: `steamdeck-kde-presets` (the SteamOS extras, installed under `/usr/local`), the Steam Machine BIOS package and its checksums, and the SteamOS release number shown in Steam's System settings. The gear icon (`assets/steam-gaming-settings.svg`) is Valve's *Return to Gaming Mode* icon (GPL-2.0) with a gear |
| [Steam](https://store.steampowered.com), [gamescope](https://github.com/ValveSoftware/gamescope) and [MangoHud](https://github.com/flightlessmango/MangoHud) | The client, the compositor the gaming session is built on, and the overlay; installed through CachyOS's packages |
| [evlaV/linux-integration](https://github.com/evlaV/linux-integration) | An unofficial mirror of Valve's kernel: its `cros_ec_cec` driver (GPL-2.0) for the Steam Machine's HDMI-CEC, downloaded at a pinned commit and checksum, then patched by `patches/cros-ec-cec-single-port.patch` |
| `leds-valve-dkms-git` (AUR) | The Steam Machine's front LED bar driver |
| [KDE Plasma](https://kde.org/plasma-desktop/), SDDM, plasma-login-manager | The desktop and the login managers whose settings it edits (`kwriteconfig6`, `lookandfeeltool`) |
| [DKMS](https://github.com/dell/dkms), [fwupd](https://fwupd.org), [yay](https://github.com/Jguer/yay) / [paru](https://github.com/Morganamilo/paru) | Building kernel modules, flashing the BIOS, and installing AUR packages (yay is built from the AUR's `yay-bin` when neither is installed) |
| [PySide6 / Qt](https://doc.qt.io/qtforpython-6/) | The graphical app |
Licences: Steamify itself is MIT. `patches/steamify-fremont-poweroff.c` is a
kernel module and therefore GPL-2.0 (see its SPDX header), and the CEC
driver it patches is GPL-2.0 too. Each of the projects above keeps its own
licence.
The problems other people found first are credited where they were used: the
[SteamOS](https://github.com/ValveSoftware/SteamOS/issues/2626) and
[CachyOS gamescope-session](https://github.com/CachyOS/gamescope-session/issues/9)
issues linked in [TECHNICAL.md](TECHNICAL.md).
### Mentions
Thanks to:
- The **CachyOS** team and packagers, for a distribution that makes this
possible and for the gamescope session packages Steamify builds on.
- **Valve**, for SteamOS, its public package repositories, Steam and
gamescope.
- **evlaV** for the public `linux-integration` mirror of Valve's kernel, the
source of the Steam Machine's CEC driver.
- The maintainers of **`leds-valve-dkms-git`**, **xone**, **xpadneo**,
**dmemcg-booster** and **plasma-foreground-booster**.
- The **KDE**, **Arch Linux** and **AUR** communities, and the authors of
**yay** and **paru**.
- Everyone who reported problems or tested on real hardware.
If something here is missing or wrongly credited, open an issue or a pull
request and it will be fixed.
## Disclaimer
Steamify CachyOS is an unofficial community project. It is not affiliated
+9 -72
View File
@@ -43,14 +43,6 @@ user wallet, with anything saved in it meanwhile, is kept as
`kdewallet.kwl.steamify-single-user` and used again the next time it's on.
Passwords aren't shared between the two wallets.
**Without the conversion (NVIDIA PCs, where gamescope's session is broken)** nothing else logs in by itself, so single user mode
does that too: `single_login_enable` (`lib/single-user.sh`) switches to SDDM and writes
`/etc/sddm.conf.d/zzz-steamify-autologin.conf` (`User=`, `Session=plasma.desktop`, `Relogin=true`; named to sort after
`steam-set-session`'s `zz-steamos-autologin.conf`, which may still say gamescope from an earlier conversion), and drops any
`[Autologin]` from `/etc/sddm.conf`. Turning it off removes the file and goes back to plasma-login-manager. With the
conversion on, the conversion does the login as before. Ticking single user mode only ticks the conversion where the
conversion is offered.
**SDDM** is what SteamOS uses, and CachyOS's `steam-set-session` supports it
directly: it writes `/etc/sddm.conf.d/zz-steamos-autologin.conf`, which SDDM
honours. The script installs and enables `sddm` (active from the next boot),
@@ -108,11 +100,9 @@ tools write to the conf.d fragment into the base config.
(never `zz-steamos-autologin.conf`, which CachyOS's tools own), and
installs `/usr/local/bin/sync-steamos-session.sh` plus
`sync-steamos-session.path`/`.service`;
- `KWIN_IM_SHOW_ALWAYS=1` for the virtual keyboard; the sub-option `silent`
("Start Steam silently in desktop mode", opt-in, always shown) writes
`~/.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;
- `KWIN_IM_SHOW_ALWAYS=1` for the virtual keyboard and a
`steam-desktop-autostart` systemd user service that starts Steam silently
in Plasma only;
- the **Return to Gaming Mode** shortcut; on plasma-login-manager with a
narrow sudoers rule (`/etc/sudoers.d/gamescope-session-switch`) so it can
restart the login manager without a password prompt.
@@ -126,8 +116,7 @@ The conversion also sets what Steam's System settings show, see
**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. 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.
file), which makes Steam show Steam Deck button glyphs in gaming mode.
## SteamOS desktop look
@@ -217,54 +206,6 @@ or upgraded. A newly added kernel doesn't come with its headers, so
`ensure-kernel-headers.service` checks at every boot and installs any
missing `-headers` package, which makes DKMS build the driver for it.
## Extended controller support
`extended_controller_support` (`lib/controllers.sh`, top-level, off by default, 2.10.0) installs two kernel drivers from CachyOS's own
repo (no AUR): `xone-dkms` with `xone-dongle-firmware` for the Xbox wireless dongle (the kernel has no driver for it; wired
Xbox controllers go through the same driver), and `xpadneo-dkms` for Xbox One/Series controllers over Bluetooth (without it
they work as plain gamepads but miss rumble including the triggers, the right button mapping and the battery level). Both are
DKMS modules, built for every installed kernel, so `install_kernel_headers` (`lib/steam-machine.sh`) makes sure each kernel has its
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
`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. Its test is in steamify-cachyos-dev (`tests/controllers-test.sh`).
## Gaming on NVIDIA
gamescope's own gaming mode shows a corrupted picture on NVIDIA graphics cards: NVIDIA's open bug 5240452 (flicker and
artifacts in the DRM session at modes above 2560x1440@120, seen up to driver 595 and on RTX 3070 Ti, 4090, 5090 and 5080;
no fix known). The kernel parameters `nvidia-drm.modeset=1`/`fbdev=1` and loading the NVIDIA modules early don't change it
(the driver already reports both `Y`), and gamescope started nested inside KDE artifacts too when KWin hands its fullscreen
window straight to the display. What does work on an RTX 5080: Steam's Big Picture (`steam -gamepadui`) as a normal window of
the Plasma desktop session, smooth and clean.
So with an NVIDIA GPU (PCI vendor 0x10de, display class, its driver providing `nvidia_drm`: `nvidia_present`) the SteamOS
conversion (`gaming`, and its options `boot`, `single`, `glyphs`) isn't offered, unless it is already on (so it can be turned
off). `nvidia` ("Gaming on NVIDIA", `lib/nvidia.sh`) takes its place, hidden while the conversion is on (both would start
Steam at login): it installs `steam` when missing (recorded in state `nvidia`, removed again only then) and enables the user
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
`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 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.
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
check, `vram_nvidia_legacy_id`; `nvidia_supported`) enabling it also does what NVIDIA's DRM stack wants, though it didn't cure
gamescope: `nvidia-drm.modeset=1 nvidia-drm.fbdev=1` on the kernel command line (Limine, systemd-boot or GRUB; the file is
backed up first; on Limine into the existing `KERNEL_CMDLINE[default]="..."` or `+="..."` line, never an extra appended line,
which ends up as text; the kernel treats `nvidia_drm` and `nvidia-drm` alike) and
`/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf` (`MODULES+=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)`), then the initramfs
and boot entries are rebuilt and checked for the parameters. The early-load drop-in is only there while every installed kernel
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
`/usr/local/libexec/steamify-nvidia-initramfs` at every kernel or driver change and decides again. Turning it off removes
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`
command shadowed in `/usr/local/bin`, and showed the desktop for a few seconds, then a Steam window with a black border);
a KWin session without Plasma (the mouse stuttered every second or two).
## HDMI-CEC
The **HDMI-CEC** item (on every PC; ticked by default only on a Steam
@@ -347,7 +288,8 @@ desktop through its desktop layout (A = Enter, B = Esc, Y = Space, X =
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
closed (`steam -shutdown`) for the edit and started again (`steam -silent`). That's refused in gaming
closed (`steam -shutdown`) for the edit and started again (through
`steam-desktop-autostart.service` when it's there). That's refused in gaming
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
there (added by hand, or with the path from before 2.5.0) is updated, not
@@ -492,8 +434,7 @@ 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/icons/hicolor/scalable/apps/steamify.svg` | The shortcut's icon |
| `~/.local/share/applications/steamify-*.desktop` | The launcher entries |
| `~/.config/autostart/steam.desktop` | the `silent` option (Steam's "Run Steam when my computer starts") |
| `~/.config/systemd/user/` | `steamify-update-check.*` |
| `~/.config/systemd/user/` | `steamify-update-check.*`, `steam-desktop-autostart.service` |
System-wide: `/usr/local/lib/steamify/` (kernel headers script),
`/usr/src/steamify-*` (DKMS modules), `/var/cache/steamify/kernel` (the old
@@ -539,9 +480,7 @@ 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
a warning. `--boot desktop` needs `gaming`. Unknown options, ids, `boot` or
`bios` in the list: exit code 1 before anything changes. What needs a
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`).
Plasma session waits for the first login (`lib/first-login.sh`).
With `Relogin=true`, a gamescope session that fails to start is restarted
immediately, which can turn into a loop - see
@@ -571,13 +510,11 @@ immediately, which can turn into a loop - see
| `lib/steam-game.sh` | Add as non-Steam game: Steamify in the Steam library (`patches/steam-shortcuts.py`) |
| `lib/update-notifier.sh` | Update notifications: the notifier from `patches/` and its user timer |
| `lib/first-login.sh` | `--defaults` without a session (the Steam Machine ISO's installer): the one-time first-login step that sets up single user's launcher on Plasma's new layout and opens the app |
| `lib/controllers.sh` | Extended controller support: Xbox wireless dongle (xone) and Xbox Bluetooth (xpadneo) from the CachyOS repo |
| `lib/nvidia.sh` | Gaming on NVIDIA: Steam on the desktop, started at login, optionally in Big Picture (replaces the SteamOS conversion there) |
| `lib/vram-booster.sh` | VRAM booster (`dmemcg-booster`, `plasma-foreground-booster`) |
| `services/` | The systemd units the scripts install (`service_file`, `@KEY@` placeholders); see its README |
| `patches/` | Module sources and patches the scripts build or apply (`patch_file`); see its README |
| `.github/tools/bundle.sh` | Builds the single-file version (`dist/steamify.sh`), with `patches/` and `services/` embedded |
| `.github/workflows/bundle.yml` | Builds and checks it on every push (GitHub and a Gitea mirror); publishes it on `main`, and starts the Steamify ISO's release |
| `.github/workflows/bundle.yml` | Builds and checks it on every push; publishes it on `main` |
The single-file version is generated: on every push to `main`, GitHub
Actions runs `.github/tools/bundle.sh`, checks the result with `bash -n` and
-7
View File
@@ -2,13 +2,6 @@
See [TECHNICAL.md](TECHNICAL.md) for how each part works.
## Where are the errors of the quiet steps?
Steps that may fail without it mattering (stopping a service that isn't
running, removing a package that isn't installed) don't show their errors in the
wizard. They are kept in `~/.local/state/steamify/log/steamify.log` (the last
512 KB), with the command and its exit status: attach it when you ask for help.
## Gaming mode shows a black screen or keeps restarting
Press **Ctrl+Alt+F3**, log in with your username and password, and run:
Binary file not shown.

Before

Width:  |  Height:  |  Size: 276 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 322 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 519 KiB

+22 -27
View File
@@ -31,41 +31,30 @@ json_list() {
printf '[%s]' "$out"
}
json_bool() {
# json_bool <command>...: true or false by the command's exit status.
if "$@"; then printf true; else printf false; fi
}
json_item_head() {
# json_item_head <id> <kind>: the start of an item's object (no closing
# brace) with what the app and the installer page both read: id, label,
# hint (the part of the label after the colon), kind, parent.
local c="$1" hint=""
[[ "${LABEL[$c]}" == *:* ]] && hint="${LABEL[$c]#*: }"
printf '{"id":%s,"label":%s,"hint":%s,"kind":"%s","parent":%s,"needs":""' \
"$(json_str "$c")" "$(json_str "${LABEL[$c]%%:*}")" "$(json_str "$hint")" "$2" "$(json_str "${PARENT[$c]:-}")"
}
backend_event() {
# backend_event <event> [<json fields without braces>]
printf '{"event":%s%s}\n' "$(json_str "$1")" "${2:+,$2}"
}
backend_status() {
local c first_run=true items="" kind
local c first_run=true items="" kind parent now
detect_components
for c in "${COMPONENTS[@]}"; do
component_available "$c" && ! is_action "$c" && is_current "$c" && first_run=false
component_available "$c" && ! is_action "$c" && [[ "${CURRENT[$c]}" == 1 ]] && first_run=false
done
for c in "${COMPONENTS[@]}"; do
component_available "$c" || continue
kind=toggle; is_action "$c" && kind=action; [[ "$c" == boot ]] && kind=choice
items+="${items:+,}$(json_item_head "$c" "$kind")"
items+=",\"on\":$(json_bool is_current "$c")"
items+=",\"wanted\":$(json_bool is_wanted "$c")"
items+=",\"update\":$(json_bool feature_outdated "$c")"
items+=",\"new\":$(json_bool feature_any_new "$c")"
items+=",\"selectable\":$(json_bool component_selectable "$c")"
parent="${PARENT[$c]:-}"
now="${CURRENT[$c]:-0}"
items+="${items:+,}{\"id\":$(json_str "$c"),\"label\":$(json_str "${LABEL[$c]%%:*}")"
items+=",\"hint\":$(json_str "$( [[ "${LABEL[$c]}" == *:* ]] && echo "${LABEL[$c]#*: }")")"
items+=",\"kind\":\"$kind\",\"parent\":$(json_str "$parent")"
items+=",\"on\":$( [[ "$now" == 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+=",\"new\":$(feature_new "$c" && echo true || echo false)"
items+=",\"selectable\":$(component_selectable "$c" && echo true || echo false)"
# Why it can't be turned on, for the app's explanation.
[[ "$c" == vram && -n "${VRAM_NVIDIA_CASE:-}" ]] &&
items+=",\"note\":$(json_str "$(vram_nvidia_note "$VRAM_NVIDIA_CASE")")"
@@ -75,11 +64,11 @@ backend_status() {
for f in /dev/cec*; do [[ -e "$f" ]] && cec+="${cec:+ }$(basename "$f")"; done
local bios='null'
if bios_available; then
bios="{\"current\":$(json_str "$(bios_current)"),\"newest\":$(json_str "${BIOS_NEWEST:-}"),\"selectable\":$(json_bool bios_selectable),\"dryRun\":$([[ -n "$BIOS_DRY_RUN" ]] && echo true || echo false)}"
bios="{\"current\":$(json_str "$(bios_current)"),\"newest\":$(json_str "${BIOS_NEWEST:-}"),\"selectable\":$(bios_selectable && echo true || echo false),\"dryRun\":$([[ -n "$BIOS_DRY_RUN" ]] && echo true || echo false)}"
fi
printf '{"version":%s,"firstRun":%s,"steamMachine":%s,"kernel":%s,"pinnedKernel":%s,"cecDevices":%s,"leds":%s,"bios":%s,"items":[%s]}\n' \
"$(json_str "$VERSION")" "$first_run" \
"$(json_bool detect_valve_fremont)" \
"$(detect_valve_fremont && echo true || echo false)" \
"$(json_str "$(uname -r)")" "$(json_str "${PINNED_KERNEL_VER:-}")" \
"$(json_str "$cec")" \
"$(compgen -G '/sys/class/leds/valve-leds*' | wc -l)" \
@@ -156,7 +145,13 @@ backend_apply() {
WANTED[$c]=0
for id in "${want[@]}"; do [[ "$id" == "$c" ]] && WANTED[$c]=1; done
done
normalize_wanted
# The same rules as the menu's toggles.
[[ "${WANTED[single]:-0}" == 1 ]] && WANTED[gaming]=1
[[ "${WANTED[gaming]:-0}" == 0 ]] && { WANTED[single]=0; WANTED[boot]=0; }
[[ "${WANTED[poweroff]:-0}" == 1 ]] && WANTED[machine]=1
[[ "${WANTED[machine]:-0}" == 0 ]] && WANTED[poweroff]=0
[[ "${WANTED[kpin]:-0}" == 1 ]] && WANTED[machine]=1
[[ "${WANTED[machine]:-0}" == 0 ]] && WANTED[kpin]=0
# Retired: only ever removed.
WANTED[hdmi]=0
case "$boot" in desktop) WANTED[boot]=1; WANTED[gaming]=1 ;; gamescope) WANTED[boot]=0 ;; esac
@@ -173,7 +168,7 @@ backend_apply() {
backend_sudo || return 1
LOGIN_MANAGER=plasmalogin
is_wanted single && LOGIN_MANAGER=sddm
[[ "${WANTED[single]}" == 1 ]] && LOGIN_MANAGER=sddm
local -a failed=()
for c in "${TO_DISABLE[@]}"; do
if backend_run_component "$c" disable; then feature_record "$c" disable; else failed+=("$c"); fi
+7 -7
View File
@@ -30,16 +30,16 @@ bios_lookup_newest() {
[[ -n "${BIOS_LOOKED_UP:-}" ]] && return 0
BIOS_LOOKED_UP=1; BIOS_NEWEST=""
local tmp desc
BIOS_REPO="$(valve_newest_repo "$BIOS_REPO_PREFIX" 10)"
BIOS_REPO="$(curl -fsL --max-time 10 "$VALVE_MIRROR/" | grep -oE "$BIOS_REPO_PREFIX-[0-9]+\.[0-9]+/" | tr -d / | sort -uV | tail -n 1)"
[[ -n "$BIOS_REPO" ]] || return 1
make_tmpdir tmp
if curl -fsL --max-time 30 "$(valve_repo_url "$BIOS_REPO")/$BIOS_REPO.files" -o "$tmp/files" &&
curl -fsL --max-time 30 "$(valve_repo_url "$BIOS_REPO")/$BIOS_REPO.db" -o "$tmp/db"; then
tmp="$(mktemp -d)"
if curl -fsL --max-time 30 "$VALVE_MIRROR/$BIOS_REPO/os/x86_64/$BIOS_REPO.files" -o "$tmp/files" &&
curl -fsL --max-time 30 "$VALVE_MIRROR/$BIOS_REPO/os/x86_64/$BIOS_REPO.db" -o "$tmp/db"; then
desc="$(tar -tf "$tmp/files" 2>/dev/null | grep -E '^fremont-hw-support-[0-9][^/]*/files$' | head -n 1)"
[[ -n "$desc" ]] && BIOS_CAB="$(tar -xOf "$tmp/files" "$desc" | grep -E '^usr/share/fwupd/.*\.cab$' | head -n 1)"
desc="${desc%/files}/desc"
BIOS_PKG="$(valve_desc_field "$tmp/db" "$desc" FILENAME)"
BIOS_SHA256="$(valve_desc_field "$tmp/db" "$desc" SHA256SUM)"
BIOS_PKG="$(tar -xOf "$tmp/db" "$desc" 2>/dev/null | awk '/^%FILENAME%$/ { getline; print }')"
BIOS_SHA256="$(tar -xOf "$tmp/db" "$desc" 2>/dev/null | awk '/^%SHA256SUM%$/ { getline; print }')"
[[ -n "${BIOS_CAB:-}" && -n "$BIOS_PKG" && -n "$BIOS_SHA256" ]] && BIOS_NEWEST="$(basename "$BIOS_CAB" .cab)"
fi
rm -rf "$tmp"
@@ -143,7 +143,7 @@ bios_prepare() {
{ err "Installing fwupd failed."; return 1; }
rm -rf "$BIOS_STAGE_DIR"; mkdir -p "$BIOS_STAGE_DIR"; chmod 700 "$BIOS_STAGE_DIR"
info "Downloading $BIOS_PKG ($BIOS_REPO)..."
if ! curl -fsSL "$(valve_repo_url "$BIOS_REPO")/$BIOS_PKG" -o "$BIOS_STAGE_DIR/pkg.tar.zst" ||
if ! curl -fsSL "$VALVE_MIRROR/$BIOS_REPO/os/x86_64/$BIOS_PKG" -o "$BIOS_STAGE_DIR/pkg.tar.zst" ||
! echo "$BIOS_SHA256 $BIOS_STAGE_DIR/pkg.tar.zst" | sha256sum -c --quiet - ||
! tar -I unzstd -xf "$BIOS_STAGE_DIR/pkg.tar.zst" -C "$BIOS_STAGE_DIR" "$BIOS_CAB"; then
err "Downloading or verifying $BIOS_PKG failed; the BIOS was not touched."
+1 -1
View File
@@ -31,7 +31,7 @@ boot_enable() {
boot_disable() {
info "Setting the PC to boot into gaming mode again..."
best_effort sudo systemctl disable "$BOOT_UNIT_NAME"
sudo systemctl disable "$BOOT_UNIT_NAME" 2>/dev/null
sudo rm -f "$BOOT_UNIT"
sudo systemctl daemon-reload
# Next boot into gamescope, as the conversion sets it up.
+36 -20
View File
@@ -39,10 +39,10 @@ cec_link_steamos_manager() {
# this item ran.
pacman -Q steamos-manager >/dev/null 2>&1 || return 0
user_systemctl daemon-reload
best_effort user_systemctl enable steamos-manager-configure-cecd.service
best_effort user_systemctl start steamos-manager-configure-cecd.service
best_effort user_systemctl restart cecd.service
best_effort user_systemctl restart steamos-manager.service
user_systemctl enable steamos-manager-configure-cecd.service 2>/dev/null
user_systemctl start steamos-manager-configure-cecd.service 2>/dev/null
user_systemctl restart cecd.service 2>/dev/null
user_systemctl restart steamos-manager.service 2>/dev/null
return 0
}
@@ -55,10 +55,10 @@ cec_status() { cec_installed && [[ -f "$CEC_STEAM_DROPIN" ]] && cec_driver_ok; }
cec_reload_driver() {
# cecd keeps /dev/cec0 open, so the old module can't be unloaded under it.
best_effort user_systemctl stop cecd.service
best_effort sudo modprobe -r cros_ec_cec
best_effort sudo modprobe cros_ec_cec
best_effort user_systemctl start cecd.service
user_systemctl stop cecd.service 2>/dev/null
sudo modprobe -r cros_ec_cec 2>/dev/null
sudo modprobe cros_ec_cec 2>/dev/null
user_systemctl start cecd.service 2>/dev/null
}
cec_driver_enable() {
@@ -68,7 +68,7 @@ cec_driver_enable() {
sudo pacman -S --needed --noconfirm dkms patch || { err "Installing dkms failed."; return 1; }
fi
install_kernel_headers || return 1
make_tmpdir tmp
tmp="$(mktemp -d)"
if [[ -f "$CEC_DRIVER_CACHE" ]] && echo "$CEC_DRIVER_SHA256 $CEC_DRIVER_CACHE" | sha256sum -c --quiet - 2>/dev/null; then
cp "$CEC_DRIVER_CACHE" "$tmp/cros-ec-cec.c"
else
@@ -80,7 +80,7 @@ cec_driver_enable() {
return 1
fi
# The name carries the checksum: a newer pin gets its own file, the old one goes.
best_effort sudo find "${CEC_DRIVER_CACHE%/*}" -maxdepth 1 -name 'cros-ec-cec-*.c' ! -name "${CEC_DRIVER_CACHE##*/}" -delete
sudo find "${CEC_DRIVER_CACHE%/*}" -maxdepth 1 -name 'cros-ec-cec-*.c' ! -name "${CEC_DRIVER_CACHE##*/}" -delete 2>/dev/null
sudo install -Dm644 "$tmp/cros-ec-cec.c" "$CEC_DRIVER_CACHE"
fi
# So it finds amdgpu's HDMI port (see the patch for why).
@@ -113,8 +113,24 @@ cec_repair() { cec_installed && ! cec_status; }
fetch_holo_pkg() {
# fetch_holo_pkg <dir> <package>: download the newest <package> from
# Valve's newest holo repository into <dir> and print its path.
valve_fetch_pkg holo "$2" "$1"
# Valve's newest holo repository into <dir> and print its path. The
# SHA-256 comes from Valve's package index and is verified.
local dir="$1" name="$2" repo desc file_name sha256
repo="$(curl -fsL "$VALVE_MIRROR/" | grep -oE 'holo-[0-9]+\.[0-9]+/' | tr -d / | sort -V | tail -n 1)"
if [[ ! -f "$dir/holo.db" ]]; then
[[ -n "$repo" ]] && curl -fsL "$VALVE_MIRROR/$repo/os/x86_64/$repo.db" -o "$dir/holo.db" ||
{ err "Couldn't read Valve's SteamOS package index ($VALVE_MIRROR)."; return 1; }
fi
desc="$(tar -tf "$dir/holo.db" 2>/dev/null | grep -E "^$name-[0-9][^/]*/desc$" | head -n 1)"
[[ -n "$desc" ]] || { err "No $name in Valve's $repo repository."; return 1; }
file_name="$(tar -xOf "$dir/holo.db" "$desc" | awk '/^%FILENAME%$/ { getline; print }')"
sha256="$(tar -xOf "$dir/holo.db" "$desc" | awk '/^%SHA256SUM%$/ { getline; print }')"
info "Downloading $file_name ($repo)..." >&2
curl -fsL "$VALVE_MIRROR/$repo/os/x86_64/$file_name" -o "$dir/$file_name" ||
{ err "Downloading $file_name failed."; return 1; }
echo "$sha256 $dir/$file_name" | sha256sum -c --quiet - >&2 ||
{ err "Checksum mismatch for $file_name; not using it."; return 1; }
echo "$dir/$file_name"
}
cec_enable() {
@@ -124,7 +140,7 @@ cec_enable() {
sudo pacman -S --needed --noconfirm linuxconsole || { err "Installing linuxconsole failed."; return 1; }
state_set cec installed_linuxconsole 1
fi
make_tmpdir tmp
tmp="$(mktemp -d)"
for p in "${CEC_PKGS[@]}"; do
f="$(fetch_holo_pkg "$tmp" "$p")" || { rm -rf "$tmp"; return 1; }
files+=("$f")
@@ -152,10 +168,10 @@ cec_enable() {
user_systemctl daemon-reload
# The TV remote's volume keys: SteamOS enables this socket through its
# preset, which pacman doesn't apply, so nothing else does on CachyOS.
best_effort user_systemctl enable --now cec-audio-control.socket
user_systemctl enable --now cec-audio-control.socket 2>/dev/null
cec_link_steamos_manager
if compgen -G "/dev/cec*" >/dev/null; then
best_effort user_systemctl restart cecd.service
user_systemctl restart cecd.service 2>/dev/null
ok "HDMI-CEC on ($(cd /dev && echo cec*)); Steam shows its settings from the next gaming mode start."
info "Turn on CEC on your TV too (e.g. Sony: BRAVIA Sync, Samsung: Anynet+, LG: SimpLink)."
else
@@ -166,15 +182,15 @@ cec_enable() {
cec_disable() {
info "Removing HDMI-CEC..."
best_effort user_systemctl disable --now cecd.service cec-audio-control.socket cec-audio-control.service
best_effort user_systemctl disable steamos-manager-configure-cecd.service
best_effort sudo pacman -Rns --noconfirm "${CEC_PKGS[@]}"
user_systemctl disable --now cecd.service cec-audio-control.socket cec-audio-control.service 2>/dev/null
user_systemctl disable steamos-manager-configure-cecd.service 2>/dev/null
sudo pacman -Rns --noconfirm "${CEC_PKGS[@]}" 2>/dev/null
cec_driver_disable
sudo rm -f "$CEC_ORDER_DROPIN" "$CEC_STEAM_DROPIN" "$CEC_STEAM_ENV"
best_effort sudo rmdir "$(dirname "$CEC_ORDER_DROPIN")" "$(dirname "$CEC_STEAM_DROPIN")" "$(dirname "$CEC_STEAM_ENV")"
sudo rmdir "$(dirname "$CEC_ORDER_DROPIN")" "$(dirname "$CEC_STEAM_DROPIN")" "$(dirname "$CEC_STEAM_ENV")" 2>/dev/null
user_systemctl daemon-reload
if [[ -n "$(state_get cec installed_linuxconsole)" ]]; then
best_effort sudo pacman -Rns --noconfirm linuxconsole
sudo pacman -Rns --noconfirm linuxconsole 2>/dev/null
state_clear cec
fi
sudo udevadm control --reload
+3 -41
View File
@@ -2,12 +2,7 @@
# Output helpers, prompts and small shared utilities.
# Sourced by steamify.sh; not meant to be run on its own.
# NO_COLOR (https://no-color.org): plain output, e.g. for a log file.
if [[ -n "${NO_COLOR:-}" ]]; then
c_reset=""; c_bold=""; c_green=""; c_yellow=""; c_red=""; c_cyan=""; c_dim=""
else
c_reset="\033[0m"; c_bold="\033[1m"; c_green="\033[32m"; c_yellow="\033[33m"; c_red="\033[31m"; c_cyan="\033[36m"; c_dim="\033[2m"
fi
c_reset="\033[0m"; c_bold="\033[1m"; c_green="\033[32m"; c_yellow="\033[33m"; c_red="\033[31m"; c_cyan="\033[36m"; c_dim="\033[2m"
info() { echo -e "${c_cyan}[INFO]${c_reset} $*"; }
ok() { echo -e "${c_green}[OK]${c_reset} $*"; }
@@ -39,39 +34,6 @@ ask_yn() {
[[ "$reply" =~ ^[Yy]$ ]]
}
best_effort() {
# best_effort <command>...: for a step whose failure is fine (stopping a
# unit that isn't running, removing what isn't installed). Same exit status
# and output as the command, but its errors go to the log
# (~/.local/state/steamify/log/steamify.log) instead of vanishing, so a problem
# can still be found afterwards.
local log="${STEAMIFY_LOG:-${STATE_DIR:-$HOME/.local/state/steamify}/log/steamify.log}" e rc
e="$(mktemp)" || { "$@" 2>/dev/null; return; }
"$@" 2>"$e"; rc=$?
if [[ -s "$e" ]]; then
mkdir -p "${log%/*}" 2>/dev/null
# Kept small: a run that fails the same way every time shouldn't fill the disk.
[[ "$(stat -c %s "$log" 2>/dev/null || echo 0)" -gt 524288 ]] && : > "$log"
{ echo "$(date -Is) exit $rc: $*"; sed 's/^/ /' "$e"; } >> "$log" 2>/dev/null
fi
rm -f "$e"
return $rc
}
# Temp dirs of this run, removed at exit (on_exit in steamify.sh), also when it
# stops half way: make_tmpdir <variable>.
TMP_DIRS=()
make_tmpdir() {
local d
d="$(mktemp -d)" || return 1
TMP_DIRS+=("$d")
printf -v "$1" '%s' "$d"
}
cleanup_tmpdirs() {
[[ ${#TMP_DIRS[@]} -eq 0 ]] || rm -rf "${TMP_DIRS[@]}"
}
require_root_helper() {
# Re-exec any privileged step through sudo rather than requiring the
# whole script to run as root, so $HOME/whoami stay correct for the
@@ -135,7 +97,7 @@ stop_plasmashell_for_edit() {
PLASMASHELL_WAS_RUNNING=false
if pgrep -u "$USER" -x plasmashell >/dev/null; then
PLASMASHELL_WAS_RUNNING=true
best_effort systemctl --user stop plasma-plasmashell.service
systemctl --user stop plasma-plasmashell.service 2>/dev/null
pkill -u "$USER" -x plasmashell && sleep 2
fi
}
@@ -143,7 +105,7 @@ stop_plasmashell_for_edit() {
restart_plasmashell_if_stopped() {
if [[ "${PLASMASHELL_WAS_RUNNING:-false}" == true ]]; then
rm -rf ~/.cache/plasmashell* ~/.cache/org.kde.dirmodel-qml.kcache
best_effort systemctl --user start plasma-plasmashell.service ||
systemctl --user start plasma-plasmashell.service 2>/dev/null ||
{ setsid plasmashell >/dev/null 2>&1 & }
fi
}
-43
View File
@@ -1,43 +0,0 @@
#!/bin/bash
# Extended controller support: the Xbox wireless dongle (xone, with its firmware) and Xbox controllers over Bluetooth (xpadneo).
# The kernel has no driver for the dongle, and without xpadneo a Bluetooth Xbox controller works as a plain gamepad (buttons and
# sticks) but misses rumble (trigger motors too), proper button mapping and the battery level. Both are DKMS modules from CachyOS's
# own repo, built for every installed kernel (so every kernel needs its headers). Sourced by steamify.sh; not meant to be run on
# its own.
controller_xone_pkg() {
# A PC with the AUR's xone-dkms-git already works: the repo's xone-dkms would conflict with it.
pacman -Q xone-dkms-git >/dev/null 2>&1 && echo xone-dkms-git || echo xone-dkms
}
controller_pkgs() { echo "xpadneo-dkms $(controller_xone_pkg) xone-dongle-firmware"; }
extended_controller_support_status() {
# shellcheck disable=SC2046 # a list of package names
pacman -Q $(controller_pkgs) >/dev/null 2>&1
}
extended_controller_support_enable() {
local p prev missing=()
info "Installing extended controller support (Xbox wireless dongle, Xbox Bluetooth)..."
install_kernel_headers || return 1
for p in $(controller_pkgs); do pacman -Q "$p" >/dev/null 2>&1 || missing+=("$p"); done
if ((${#missing[@]})); then
sudo pacman -S --needed --noconfirm "${missing[@]}" ||
{ err "Installing ${missing[*]} failed."; return 1; }
# What a first, half-finished run installed stays on the list.
prev="$(state_get extended_controller_support installed_pkgs)"
state_set extended_controller_support installed_pkgs "$(echo "$prev ${missing[*]}" | xargs)"
fi
ok "Extended controller support on: plug the dongle in again (or reconnect the controller) to use it."
}
extended_controller_support_disable() {
local pkgs
pkgs="$(state_get extended_controller_support installed_pkgs)"
# Only what Steamify installed; kernel headers stay.
# shellcheck disable=SC2086 # a list of package names
[[ -n "$pkgs" ]] && sudo pacman -Rns --noconfirm $pkgs >/dev/null 2>&1
state_clear extended_controller_support
ok "Extended controller support off."
}
+24 -25
View File
@@ -2,21 +2,29 @@
# "Return to Gaming Mode" desktop shortcut and the sudoers rule it needs.
# Sourced by steamify.sh; not meant to be run on its own.
shortcut_desktop_dir() {
# The target user's Desktop folder, from their user-dirs.dirs.
local user_home desktop_dir
create_desktop_shortcut() {
# Determine the home directory of the target user
local user_home
user_home="$(getent passwd "$TARGET_USER" | cut -d: -f6)"
# Locate the correct Desktop directory
local desktop_dir
if [[ -f "$user_home/.config/user-dirs.dirs" ]]; then
desktop_dir=$(grep '^XDG_DESKTOP_DIR=' "$user_home/.config/user-dirs.dirs" | cut -d '"' -f 2)
desktop_dir="${desktop_dir/\$HOME/$user_home}"
fi
echo "${desktop_dir:-$user_home/Desktop}"
}
desktop_dir="${desktop_dir:-$user_home/Desktop}"
shortcut_install_sudoers() {
# plasma-login-manager needs the sync bridge run and a restart, which the
# shortcut can't sudo for interactively (Terminal=false), so it gets a
# password-less rule scoped to exactly those two commands.
mkdir -p "$desktop_dir"
# On SDDM, steamos-session-select logging out is enough: Relogin=true
# logs straight back in to the newly selected session, like SteamOS.
# plasma-login-manager needs the sync bridge run and a restart, which
# the shortcut can't sudo for interactively (Terminal=false), so it gets
# a password-less rule scoped to exactly those two commands.
local exec_line="steamos-session-select gamescope"
if [[ "$LOGIN_MANAGER" == "plasmalogin" ]]; then
exec_line="sh -c 'steamos-session-select gamescope && sudo -n /usr/bin/systemctl start sync-steamos-session.service && sudo -n /usr/bin/systemctl restart plasmalogin'"
local sudoers_tmp
sudoers_tmp="$(mktemp)"
cat > "$sudoers_tmp" << EOF
@@ -29,19 +37,6 @@ EOF
warn "Generated sudoers rule failed validation; the shortcut will not be able to restart plasmalogin."
fi
rm -f "$sudoers_tmp"
}
create_desktop_shortcut() {
local desktop_dir
desktop_dir="$(shortcut_desktop_dir)"
mkdir -p "$desktop_dir"
# On SDDM, steamos-session-select logging out is enough: Relogin=true
# logs straight back in to the newly selected session, like SteamOS.
local exec_line="steamos-session-select gamescope"
if [[ "$LOGIN_MANAGER" == "plasmalogin" ]]; then
exec_line="sh -c 'steamos-session-select gamescope && sudo -n /usr/bin/systemctl start sync-steamos-session.service && sudo -n /usr/bin/systemctl restart plasmalogin'"
shortcut_install_sudoers
else
sudo rm -f /etc/sudoers.d/gamescope-session-switch
fi
@@ -54,11 +49,11 @@ create_desktop_shortcut() {
[[ -f /usr/local/share/icons/hicolor/scalable/actions/gaming-return.svg ]] &&
shortcut_icon="gaming-return"
# 2. Generate the .desktop shortcut with instant session switcher strings
local shortcut_path="$desktop_dir/Return to Gaming Mode.desktop"
info "Creating 'Return to Gaming Mode' desktop shortcut at: $shortcut_path"
# Written with its mode already set: Plasma opens a desktop icon it first
# saw non-executable in an editor.
install_executable "$shortcut_path" 755 << EOF
cat << EOF > "$shortcut_path"
[Desktop Entry]
Name=Return to Gaming Mode
Comment=Switch session back to Gamescope
@@ -68,6 +63,10 @@ Terminal=false
Type=Application
Categories=System;
EOF
# Fix permissions for the target user and KDE Plasma desktop ecosystem
chmod +x "$shortcut_path"
ok "Desktop shortcut created successfully."
}
+4 -15
View File
@@ -7,25 +7,13 @@
FIRST_LOGIN_ENTRY="${XDG_CONFIG_HOME:-$HOME/.config}/autostart/steamify-first-login.desktop"
FIRST_LOGIN_SCRIPT="$STEAMIFY_BIN/first-login"
FIRST_LOGIN_BUNDLE="$STEAMIFY_BIN/first-login-steamify.sh"
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
#!/bin/bash
# Installed by Steamify CachyOS: runs once, at the first desktop login.
set -o pipefail
mkdir -p ~/.cache
{ $run; } > ~/.cache/steamify-first-login.log 2>&1
curl -fsSL --max-time 30 "$WIZARD_URL" | bash -s -- --first-login
rm -f "$FIRST_LOGIN_ENTRY" "\$0"
[[ -x "$WIZARD_APP_LAUNCHER" ]] && exec "$WIZARD_APP_LAUNCHER"
EOF2
@@ -43,9 +31,10 @@ first_login_run() {
[[ -n "$(plasma_applets org.kde.plasma.kickoff)" ]] && break
sleep 2
done
if single_status; then
stop_plasmashell_for_edit
taskbar_drop_discover
single_status && single_launcher
single_launcher
restart_plasmashell_if_stopped
fi
return 0
}
+3 -3
View File
@@ -25,7 +25,7 @@ poweroff_fix_enable() {
sudo pacman -S --needed --noconfirm dkms || { err "Installing dkms failed."; return 1; }
fi
install_kernel_headers || return 1
make_tmpdir tmp
tmp="$(mktemp -d)"
patch_file "$POWEROFF_DKMS_NAME.c" > "$tmp/$POWEROFF_DKMS_NAME.c"
echo "obj-m += $POWEROFF_DKMS_NAME.o" >"$tmp/Makefile"
patch_file "$POWEROFF_DKMS_NAME.dkms.conf" | fill NAME="$POWEROFF_DKMS_NAME" VERSION="$POWEROFF_DKMS_VER" >"$tmp/dkms.conf"
@@ -43,13 +43,13 @@ poweroff_fix_enable() {
warn "Building the power-off fix for $k failed; with that kernel it may start again after shutting down."
done
echo "$POWEROFF_DKMS_NAME" | sudo tee "$POWEROFF_MODULES_LOAD" >/dev/null
best_effort sudo modprobe "$POWEROFF_DKMS_NAME"
sudo modprobe "$POWEROFF_DKMS_NAME" 2>/dev/null
return 0
}
poweroff_fix_disable() {
sudo rm -f "$POWEROFF_MODULES_LOAD"
best_effort sudo modprobe -r "$POWEROFF_DKMS_NAME"
sudo modprobe -r "$POWEROFF_DKMS_NAME" 2>/dev/null
[[ -d "$POWEROFF_DKMS_SRC" ]] || return 0
sudo dkms remove "$POWEROFF_DKMS_NAME/$POWEROFF_DKMS_VER" --all >/dev/null 2>&1
sudo rm -rf "$POWEROFF_DKMS_SRC"
-164
View File
@@ -1,164 +0,0 @@
#!/bin/bash
# "Pin the kernel" (kpin), retired: newer linux-cachyos releases rebooted the
# Steam Machine instead of shutting down, which the power-off fix
# (lib/fremont-poweroff.sh) made unnecessary. Only what removes an existing pin
# is still offered (kpin_available), a sub-option of Steam Machine support.
# Sourced by steamify.sh; not meant to be run on its own.
# Kernel pinned on a Steam Machine (optional): newer linux-cachyos releases
# rebooted it instead of shutting down, which the power-off fix now handles. The packages are kept in
# PINNED_KERNEL_DIR, so re-applying (or reinstalling after an update slipped
# through) needs no download.
PINNED_KERNEL_VER="7.1.6-1"
PINNED_KERNEL_KVER="7.1.6-1-cachyos"
PINNED_KERNEL_PKGS=(linux-cachyos linux-cachyos-headers)
PINNED_KERNEL_DIR="${PINNED_KERNEL_DIR:-/var/cache/steamify/kernel}"
# SHA-256 of each package, so a file from any source is the one reviewed
# here; its CachyOS signature is checked as well.
declare -A PINNED_KERNEL_SHA256=(
[linux-cachyos]=417fcd07102192b86e78e92ed7171d5a49378e9f57faea3fa2c7c541e9f68d08
[linux-cachyos-headers]=d069866a11d9092746e1d5133cefd8924f027da2c9bf5af38d30b3aed6ded9bf
)
# Tried in order, after the kernel dir and pacman's cache. Our own release
# always has these files; the archive keeps every release; the mirror only
# the current one. PINNED_KERNEL_URL puts another source (a directory
# holding the files) in front.
PINNED_KERNEL_SOURCES=(
${PINNED_KERNEL_URL:+"$PINNED_KERNEL_URL"}
"https://github.com/theupriser/steamify-cachyos/releases/download/kernel-$PINNED_KERNEL_VER"
"https://archive.cachyos.org/archive/cachyos"
"https://mirror.cachyos.org/repo/x86_64/cachyos"
)
pinned_kernel_installed() {
local p
for p in "${PINNED_KERNEL_PKGS[@]}"; do
[[ "$(pacman -Q "$p" 2>/dev/null)" == "$p $PINNED_KERNEL_VER" ]] || return 1
done
}
fetch_pinned_kernel_file() {
# $1 = file name. Local kernel dir first, then pacman's cache, then the
# download sources. Downloads go to a .part file so a broken one is never
# mistaken for a finished one.
local f="$1" dest="$PINNED_KERNEL_DIR/$1" src
[[ -s "$dest" ]] && return 0
if [[ -s "/var/cache/pacman/pkg/$f" ]]; then
sudo cp "/var/cache/pacman/pkg/$f" "$dest" && return 0
fi
for src in "${PINNED_KERNEL_SOURCES[@]}"; do
if sudo curl -fL --retry 2 --connect-timeout 15 -o "$dest.part" "$src/$f" 2>/dev/null; then
sudo mv "$dest.part" "$dest"
return 0
fi
warn "Couldn't get $f from $src, trying the next source..."
done
sudo rm -f "$dest.part"
return 1
}
verify_pinned_kernel_pkg() {
# $1 = package name, $2 = file. Both checks must pass: the SHA-256 from
# this script, and the CachyOS signature (pacman on its own installs a
# local file without a .sig: LocalFileSigLevel = Optional).
local sum
sum="$(sha256sum "$2" | cut -d' ' -f1)"
if [[ "$sum" != "${PINNED_KERNEL_SHA256[$1]}" ]]; then
err "$(basename "$2") doesn't match its expected checksum."
return 1
fi
if ! sudo pacman-key --verify "$2.sig" "$2" >/dev/null 2>&1; then
err "$(basename "$2") doesn't have a valid CachyOS signature."
return 1
fi
}
pin_kernel_in_pacman_conf() {
# Adds our packages to IgnorePkg in [options], keeping what's there.
local p
for p in "${PINNED_KERNEL_PKGS[@]}"; do
grep -Eq "^IgnorePkg\s*=.*(\s|=)$p(\s|$)" /etc/pacman.conf && continue
if grep -Eq '^IgnorePkg\s*=' /etc/pacman.conf; then
sudo sed -i -E "0,/^IgnorePkg\s*=/s/^(IgnorePkg\s*=.*)$/\1 $p/" /etc/pacman.conf
else
sudo sed -i -E "0,/^\[options\]/s//[options]\nIgnorePkg = $p/" /etc/pacman.conf
fi
done
}
unpin_kernel_in_pacman_conf() {
local p
for p in "${PINNED_KERNEL_PKGS[@]}"; do
sudo sed -i -E "/^IgnorePkg\s*=/s/\s$p(\s|$)/\1/" /etc/pacman.conf
done
# Drop the line if nothing is left on it.
sudo sed -i -E '/^IgnorePkg\s*=\s*$/d' /etc/pacman.conf
}
install_pinned_kernel() {
sudo mkdir -p "$PINNED_KERNEL_DIR"
pin_kernel_in_pacman_conf
if pinned_kernel_installed; then
ok "Kernel $PINNED_KERNEL_VER already installed and pinned."
return 0
fi
local p f files=()
info "Getting kernel $PINNED_KERNEL_VER (kept in $PINNED_KERNEL_DIR)..."
for p in "${PINNED_KERNEL_PKGS[@]}"; do
f="$p-$PINNED_KERNEL_VER-x86_64.pkg.tar.zst"
fetch_pinned_kernel_file "$f" && fetch_pinned_kernel_file "$f.sig" ||
{ err "Couldn't download $f from any source."; return 1; }
if ! verify_pinned_kernel_pkg "$p" "$PINNED_KERNEL_DIR/$f"; then
# Removed, so the next run fetches it again.
sudo rm -f "$PINNED_KERNEL_DIR/$f" "$PINNED_KERNEL_DIR/$f.sig"
err "Removed it; run the wizard again to download it once more."
return 1
fi
files+=("$PINNED_KERNEL_DIR/$f")
done
# pacman checks each package against the .sig next to it.
info "Installing kernel $PINNED_KERNEL_VER..."
if ! sudo pacman -U --noconfirm "${files[@]}"; then
err "Installing kernel $PINNED_KERNEL_VER failed."
return 1
fi
[[ "$(uname -r)" != "$PINNED_KERNEL_KVER" ]] && RESTART_FOR_LOGIN=true
ok "Kernel $PINNED_KERNEL_VER installed and pinned (restart to use it)."
}
remove_kernel_pin() {
# Back to CachyOS's current kernel. The packages stay in
# PINNED_KERNEL_DIR, so turning support on again doesn't download.
unpin_kernel_in_pacman_conf
pinned_kernel_installed || return 0
info "Updating the kernel back to CachyOS's current version..."
sudo pacman -Syu --noconfirm ||
{ warn "Updating the kernel failed; run: sudo pacman -Syu"; return 0; }
RESTART_FOR_LOGIN=true
}
# "Pin the kernel" menu item, a sub-option of Steam Machine support. The
# power-off fix made it unnecessary: only shown while on, to remove it.
kpin_available() { detect_valve_fremont && kpin_status; }
kpin_status() {
pinned_kernel_installed && grep -Eq '^IgnorePkg\s*=.*\slinux-cachyos(\s|$)' /etc/pacman.conf
}
kpin_enable() {
install_pinned_kernel || return 1
# The DKMS pacman hook built leds-valve for the new headers; make sure.
if pacman -Qi leds-valve-dkms-git >/dev/null 2>&1 &&
! dkms status -k "$PINNED_KERNEL_KVER" leds-valve-dkms 2>/dev/null | grep -q installed; then
sudo dkms install leds-valve-dkms/0.1 -k "$PINNED_KERNEL_KVER" ||
warn "Building the LED driver for $PINNED_KERNEL_KVER failed."
fi
}
kpin_disable() {
# Saved HDMI refresh boost EDIDs were for the pinned kernel only (newer
# ones read the whole EDID), also those of displays not connected now.
hdmi_status && hdmi_forget_all
remove_kernel_pin
}
+12 -17
View File
@@ -35,7 +35,7 @@ steamos_release() {
# capitals: steamos-3.9). Offline (e.g. in the installer): the one set
# before, if any.
local v
v="$(valve_newest_repo jupiter 15)"
v="$(curl -fsL --max-time 15 "$VALVE_MIRROR/" 2>/dev/null | grep -oE 'jupiter-[0-9]+\.[0-9]+/' | tr -d / | sort -V | tail -n 1)"
if [[ -n "$v" ]]; then echo "steamos-${v#jupiter-}"
else sed -n 's/^VERSION_ID=\(steamos-.*\)$/\1/p' /etc/os-release 2>/dev/null; fi
}
@@ -167,20 +167,6 @@ switch_to_sddm() {
ok "SDDM is the login manager from the next boot on."
}
remove_sddm_base_autologin() {
# /etc/sddm.conf is read last: an [Autologin] there would override our fragments.
if [[ -f /etc/sddm.conf ]] && grep -q '^\[Autologin\]' /etc/sddm.conf; then
backup_file /etc/sddm.conf
sudo awk '
/^\[Autologin\]/ { skip=1; next }
/^\[/ { skip=0 }
!skip { print }
' /etc/sddm.conf | sudo tee /etc/sddm.conf.tmp > /dev/null &&
sudo mv /etc/sddm.conf.tmp /etc/sddm.conf
info "Removed [Autologin] from /etc/sddm.conf (backup kept)."
fi
}
configure_sddm_autologin() {
# User= and Relogin= live in our own fragment; steam-set-session keeps
# Session= up to date in zz-steamos-autologin.conf, which sorts later
@@ -196,7 +182,16 @@ Session=gamescope-session.desktop
Relogin=true
EOF
remove_sddm_base_autologin
if [[ -f /etc/sddm.conf ]] && grep -q '^\[Autologin\]' /etc/sddm.conf; then
backup_file /etc/sddm.conf
sudo awk '
/^\[Autologin\]/ { skip=1; next }
/^\[/ { skip=0 }
!skip { print }
' /etc/sddm.conf | sudo tee /etc/sddm.conf.tmp > /dev/null &&
sudo mv /etc/sddm.conf.tmp /etc/sddm.conf
info "Removed [Autologin] from /etc/sddm.conf (backup kept)."
fi
# Start in gamescope, through CachyOS's own tool so its file is current.
sudo /usr/lib/steamos/steam-set-session gamescope-session.desktop
@@ -210,7 +205,7 @@ remove_session_sync() {
# The plasmalogin sync bridge from an earlier run isn't needed on SDDM.
if [[ -f /etc/systemd/system/sync-steamos-session.path ]]; then
info "Removing the plasma-login-manager sync bridge (not needed with SDDM)..."
best_effort sudo systemctl disable --now sync-steamos-session.path
sudo systemctl disable --now sync-steamos-session.path 2>/dev/null
sudo rm -f /etc/systemd/system/sync-steamos-session.path \
/etc/systemd/system/sync-steamos-session.service \
/usr/local/bin/sync-steamos-session.sh
+50 -118
View File
@@ -5,33 +5,18 @@
# Menu order. Components are turned on in this order and off in reverse;
# gaming must come first (single user builds on it).
COMPONENTS=(gaming boot silent glyphs nvidia bigpicture nvsilent theme single launcher steamgame notify extended_controller_support vram cec machine poweroff kpin hdmi bios)
COMPONENTS=(gaming boot theme glyphs single launcher steamgame notify vram cec machine poweroff kpin hdmi bios)
# One-off actions rather than on/off components: never preselected, never
# re-applied, not listed as on or off.
ACTIONS=(bios)
# Sub-options, shown indented under their parent and only while it's ticked.
declare -A PARENT=([boot]=gaming [silent]=gaming [glyphs]=gaming [bigpicture]=nvidia [nvsilent]=nvidia [steamgame]=launcher [poweroff]=machine [kpin]=machine [hdmi]=machine [bios]=machine)
# What ticking one item does to another, for the menu's toggles (toggle_component)
# and the app's ticks (normalize_wanted). A sub-option needs its parent: ticking it
# ticks the parent, unticking the parent unticks it (Where to boot is chosen with
# --boot, so the app's ticks never bring the conversion for it; HDMI refresh boost is
# retired and never brings Steam Machine support). Single user mode only makes sense
# on top of the SteamOS conversion (where that is offered: on NVIDIA it logs in by
# itself, see lib/single-user.sh).
declare -A REQUIRES=([single]=gaming)
for _c in "${!PARENT[@]}"; do [[ "$_c" == hdmi ]] || REQUIRES[$_c]=${PARENT[$_c]}; done
unset _c
# Opt-out sub-options are ticked and unticked along with their parent.
declare -A FOLLOWS=([nvidia]=bigpicture [machine]=poweroff [launcher]=steamgame)
# Ticking one unticks the other; in normalize_wanted the first in COMPONENTS wins.
declare -A EXCLUDES=([bigpicture]=nvsilent [nvsilent]=bigpicture)
declare -A PARENT=([boot]=gaming [steamgame]=launcher [poweroff]=machine [kpin]=machine [hdmi]=machine [bios]=machine)
# 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
# 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
# screen to confirm each step. Extended controller support builds kernel modules for
# every installed kernel: opt-in.
NO_PRESELECT=(boot silent nvsilent cec kpin hdmi extended_controller_support)
# screen to confirm each step.
NO_PRESELECT=(boot cec kpin hdmi)
# 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.
# Each successful run records it (state "features"); a component that's on
@@ -40,25 +25,20 @@ NO_PRESELECT=(boot silent nvsilent cec kpin hdmi extended_controller_support)
# FEATURE_BASELINE.
FEATURE_BASELINE=2.1.0
declare -A FEATURE_VERSION=(
[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
[gaming]=2.9.0 [boot]=2.1.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
[kpin]=2.1.0 [hdmi]=2.1.0
)
declare -A LABEL=(
[gaming]="SteamOS conversion: boot into gaming mode, Steam on the desktop"
[boot]="Boot into the desktop instead of gaming mode"
[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)"
[theme]="Install SteamOS theme: Vapor look (cachyos-vapor)"
[glyphs]="Install Steam Deck/Machine icons: Deck button icons in gaming mode"
[single]="Single user mode: no password, lock screen or log out (SDDM)"
[launcher]="Steamify shortcut: the app on the desktop, Steamify Terminal in the launcher"
[steamgame]="Add as non-Steam game: Steamify in your Steam library, for the controller and gaming mode"
[notify]="Update notifications: a notification when there's a new Steamify, never updates by itself"
[extended_controller_support]="Extended controller support: Xbox wireless dongle (xone), Xbox controllers over Bluetooth (xpadneo)"
[vram]="VRAM booster: the game in front keeps its VRAM, background apps make room"
[cec]="HDMI-CEC: use Steam with the TV remote, TV on/off with the PC (experimental)"
[machine]="Steam Machine support: LED bar driver, hardware settings in Steam"
@@ -71,24 +51,15 @@ declare -A CURRENT WANTED
component_available() {
case "$1" in
# 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).
gaming|boot|silent|glyphs) ! nvidia_present || gaming_status ;;
nvidia) nvidia_available ;;
bigpicture|nvsilent) bigpicture_available ;;
machine|poweroff) machine_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;
# shown anyway when it's already on, so it can be turned off).
steamgame) steamgame_available && { ! nvidia_present || steamgame_status; } ;;
steamgame) steamgame_available ;;
kpin) kpin_available ;;
hdmi) hdmi_available ;;
bios) bios_available ;;
esac
}
is_wanted() { [[ "${WANTED[$1]:-0}" == 1 ]]; }
is_current() { [[ "${CURRENT[$1]:-0}" == 1 ]]; }
is_action() { [[ " ${ACTIONS[*]} " == *" $1 "* ]]; }
boot_mode() {
@@ -101,8 +72,6 @@ menu_visible() {
# Shown in the menu. A sub-option ("Boot into", the kernel pin) only
# while its parent is ticked.
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 ]]
}
@@ -131,7 +100,7 @@ feature_outdated() {
# On, but set up by an older version of that feature (compared as
# versions: 2.10.0 is newer than 2.9.0).
local have want
is_current "$1" || return 1
[[ "${CURRENT[$1]:-0}" == 1 ]] || return 1
have="$(state_get features "$1" "$FEATURE_BASELINE")"
[[ "$have" == off ]] && have="$FEATURE_BASELINE"
want="${FEATURE_VERSION[$1]:-$FEATURE_BASELINE}"
@@ -144,7 +113,7 @@ menu_label() {
# last run.
local l="${LABEL[$1]}" b=""
if feature_outdated "$1"; then b="${c_yellow}(update)${c_reset}"
elif feature_new "$1" || feature_new_optin "$1"; then b="${c_green}(new)${c_reset}"; fi
elif feature_new "$1"; then b="${c_green}(new)${c_reset}"; fi
if [[ -n "$b" ]]; then
if [[ "$l" == *:* ]]; then l="${l%%:*} $b:${l#*:}"
else l+=" $b"; fi
@@ -152,30 +121,14 @@ menu_label() {
printf '%s' "$l"
}
feature_added() {
# An option added after its parent was set up (e.g. the power-off fix under
# Steam Machine support; a top-level one counts the SteamOS conversion, or
# "Gaming on NVIDIA" where that replaces it, as its parent), not on yet,
# with no record: shown as "new".
local p="${PARENT[$1]:-}" parent_on=0
if [[ -n "$p" ]]; then parent_on="${CURRENT[$p]:-0}"
elif [[ "${CURRENT[gaming]:-0}" == 1 || "${CURRENT[nvidia]:-0}" == 1 ]]; then parent_on=1; fi
[[ "$1" != gaming && "$parent_on" == 1 && "${CURRENT[$1]:-0}" == 0 ]] &&
! is_action "$1" && component_selectable "$1" &&
[[ -z "$(state_get features "$1")" ]]
}
feature_new() {
# A new default option: ticked for you (never turned on or off by itself).
feature_added "$1" && [[ " ${NO_PRESELECT[*]} " != *" $1 "* ]]
}
feature_any_new() { feature_new "$1" || feature_new_optin "$1"; }
feature_new_optin() {
# A new opt-in option (unticked by default): the "new" badge only, it stays
# unticked. Boot into is a choice row of the conversion, not an item.
feature_added "$1" && [[ "$1" != boot && " ${NO_PRESELECT[*]} " == *" $1 "* ]]
# A default option added after its parent was set up (e.g. the power-off
# fix under Steam Machine support; a top-level one counts the SteamOS
# conversion as its parent): never turned on or off.
local p="${PARENT[$1]:-gaming}"
[[ "$1" != gaming && "${CURRENT[$p]:-0}" == 1 && "${CURRENT[$1]:-0}" == 0 ]] &&
! is_action "$1" && component_selectable "$1" && [[ " ${NO_PRESELECT[*]} " != *" $1 "* ]] &&
[[ -z "$(state_get features "$1")" ]]
}
component_selectable() {
@@ -188,7 +141,6 @@ component_selectable() {
detect_components() {
local c any=false
for c in "${COMPONENTS[@]}"; do CURRENT[$c]=0; WANTED[$c]=0; done
for c in "${COMPONENTS[@]}"; do
component_available "$c" || continue
if "${c}_status"; then CURRENT[$c]=1; any=true; else CURRENT[$c]=0; fi
@@ -270,14 +222,14 @@ defaults_options() {
warn "Leaving out ${LABEL[$c]%%:*}: not available on this PC."
fi
done
is_wanted single && component_available gaming && WANTED[gaming]=1
[[ "${WANTED[single]}" == 1 ]] && WANTED[gaming]=1
for c in "${COMPONENTS[@]}"; do
[[ "${WANTED[$c]}" == 1 && -n "${PARENT[$c]:-}" ]] && WANTED[${PARENT[$c]}]=1
done
fi
case "$boot" in
desktop)
is_wanted gaming || { err "--boot desktop needs the SteamOS conversion (gaming)."; return 1; }
[[ "${WANTED[gaming]}" == 1 ]] || { err "--boot desktop needs the SteamOS conversion (gaming)."; return 1; }
WANTED[boot]=1 ;;
gamescope) WANTED[boot]=0 ;;
esac
@@ -302,53 +254,32 @@ defaults_list() {
on=false
[[ "$sel" == true && " ${NO_PRESELECT[*]} " != *" $c "* ]] && on=true
[[ "$c" == cec ]] && machine_available && on=true
items+="${items:+,}$(json_item_head "$c" "$kind"),\"hideWhen\":$(json_str "$([[ "$c" == nvsilent ]] && echo bigpicture)"),\"on\":$on,\"selectable\":$sel}"
items+="${items:+,}{\"id\":$(json_str "$c"),\"label\":$(json_str "${LABEL[$c]%%:*}")"
items+=",\"hint\":$(json_str "$( [[ "${LABEL[$c]}" == *:* ]] && echo "${LABEL[$c]#*: }")")"
items+=",\"kind\":\"$kind\",\"parent\":$(json_str "${PARENT[$c]:-}"),\"on\":$on,\"selectable\":$sel}"
done
printf '[%s]\n' "$items"
}
children_of() {
# children_of <id>: the items that need <id> (REQUIRES), one per line.
local c
for c in "${COMPONENTS[@]}"; do [[ "${REQUIRES[$c]:-}" == "$1" ]] && echo "$c"; done
return 0
}
toggle_component() {
local c="$1" p x
local c="$1"
component_selectable "$c" || return 1
WANTED[$c]=$(( 1 - WANTED[$c] ))
if is_wanted "$c"; then
p="${REQUIRES[$c]:-}"
[[ -n "$p" ]] && component_available "$p" && WANTED[$p]=1
x="${EXCLUDES[$c]:-}"
[[ -n "$x" ]] && WANTED[$x]=0
else
for x in $(children_of "$c"); do WANTED[$x]=0; done
fi
x="${FOLLOWS[$c]:-}"
[[ -n "$x" ]] && component_available "$x" && WANTED[$x]=${WANTED[$c]}
}
normalize_wanted() {
# The same rules for a whole selection (the app ticks exactly the items it
# sends): a ticked sub-option brings its parent, two that exclude each other
# keep the first, and an unticked parent takes its sub-options with it
# (only where the parent is offered: single user mode stays on NVIDIA PCs).
local c p x
for c in "${COMPONENTS[@]}"; do
p="${REQUIRES[$c]:-}"
[[ -n "$p" && "$c" != boot && "${WANTED[$c]:-0}" == 1 ]] && component_available "$p" && WANTED[$p]=1
done
for c in "${COMPONENTS[@]}"; do
x="${EXCLUDES[$c]:-}"
[[ -n "$x" && "${WANTED[$c]:-0}" == 1 ]] && WANTED[$x]=0
done
for c in "${COMPONENTS[@]}"; do
p="${REQUIRES[$c]:-}"
[[ -n "$p" && "${WANTED[$p]:-0}" == 0 ]] && component_available "$p" && WANTED[$c]=0
done
return 0
# 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; WANTED[boot]=0; fi
# Where to boot to is part of the conversion, too.
if [[ "$c" == boot && "${WANTED[boot]}" == 1 ]]; then WANTED[gaming]=1; fi
# The power-off fix is opt-out: ticked along with Steam Machine support.
if [[ "$c" == machine ]]; then WANTED[poweroff]=${WANTED[machine]}; fi
if [[ "$c" == poweroff && "${WANTED[poweroff]}" == 1 ]]; then WANTED[machine]=1; fi
if [[ "$c" == machine && "${WANTED[machine]}" == 0 ]]; then WANTED[kpin]=0; WANTED[bios]=0; fi
if [[ "$c" == kpin && "${WANTED[kpin]}" == 1 ]]; then WANTED[machine]=1; fi
if [[ "$c" == bios && "${WANTED[bios]}" == 1 ]]; then WANTED[machine]=1; fi
# Steam starts Steamify through the shortcut's start script.
# Opt-out, like the power-off fix: ticked along with the shortcut.
if [[ "$c" == launcher ]] && component_available steamgame; then WANTED[steamgame]=${WANTED[launcher]}; fi
if [[ "$c" == steamgame && "${WANTED[steamgame]}" == 1 ]]; then WANTED[launcher]=1; fi
}
show_menu() {
@@ -360,16 +291,16 @@ show_menu() {
menu_visible "$c" || continue
i=$((i + 1)); MENU_ITEMS[$i]=$c
# Pad the plain word, then colour it: colour codes would count as width.
now="off"; is_current "$c" && now="on"
now="off"; [[ "${CURRENT[$c]}" == 1 ]] && now="on"
is_action "$c" && now="-"
now="$(printf '%-6s' "$now")"
is_current "$c" && now="${now/on/${c_green}on${c_reset}}"
want="[ ]"; is_wanted "$c" && want="[x]"
[[ "${CURRENT[$c]}" == 1 ]] && now="${now/on/${c_green}on${c_reset}}"
want="[ ]"; [[ "${WANTED[$c]}" == 1 ]] && want="[x]"
if [[ "$c" == boot ]]; then
# A choice rather than a checkbox: Now/Want show the mode.
now="gaming"; is_current boot && now="desk"
is_current gaming || now="-"
want="gaming"; is_wanted boot && want="desk"
now="gaming"; [[ "${CURRENT[boot]}" == 1 ]] && now="desk"
[[ "${CURRENT[gaming]}" == 1 ]] || now="-"
want="gaming"; [[ "${WANTED[boot]}" == 1 ]] && want="desk"
printf " %-3s %-6s %-6s └ %s\n" "$i" "$now" "$want" "$(boot_choice "${WANTED[boot]}")"
elif ! component_selectable "$c"; then
local tree=""; [[ -n "${PARENT[$c]:-}" ]] && tree=" └ "
@@ -408,8 +339,8 @@ draw_menu_tui() {
for c in "${COMPONENTS[@]}"; do
menu_visible "$c" || continue
MENU_ITEMS[$i]=$c
box="[ ]"; is_wanted "$c" && box="[${c_green}x${c_reset}]"
state=" (now: off)"; is_current "$c" && state=" (now: ${c_green}on${c_reset})"
box="[ ]"; [[ "${WANTED[$c]}" == 1 ]] && box="[${c_green}x${c_reset}]"
state=" (now: off)"; [[ "${CURRENT[$c]}" == 1 ]] && state=" (now: ${c_green}on${c_reset})"
is_action "$c" && state=" (opt-in, runs once)"
line="$box ${LABEL[$c]}"
if [[ "$c" == boot ]]; then
@@ -417,9 +348,9 @@ draw_menu_tui() {
# Indented under the conversion, whose sub-option it is.
line="$(boot_choice "${WANTED[boot]}")"
line=" └ ${line/\[/[${c_green}}"; line="${line/\]/${c_reset}]}"
local mode=gamescope; is_current boot && mode=desktop
local mode=gamescope; [[ "${CURRENT[boot]}" == 1 ]] && mode=desktop
state=" (${c_bold}←/→${c_reset} choose)"
is_current gaming && state=" (now: $mode; ${c_bold}←/→${c_reset} choose)"
[[ "${CURRENT[gaming]}" == 1 ]] && state=" (now: $mode; ${c_bold}←/→${c_reset} choose)"
elif [[ -n "${PARENT[$c]:-}" ]]; then
line=" └ $line"
fi
@@ -446,6 +377,7 @@ draw_menu_tui() {
run_menu_tui() {
local cursor=0 key rest count
tput civis 2>/dev/null
trap 'tput cnorm 2>/dev/null' EXIT
while true; do
draw_menu_tui "$cursor"
count=${#MENU_ITEMS[@]}
@@ -507,7 +439,7 @@ plan_changes() {
done
for c in "${COMPONENTS[@]}"; do
component_available "$c" || continue
is_wanted "$c" || continue
[[ "${WANTED[$c]}" == 1 ]] || continue
if is_action "$c"; then TO_ENABLE+=("$c"); continue; fi
if [[ "${CURRENT[$c]}" == 0 || "$REAPPLY" == true ]] || feature_outdated "$c" ||
[[ "$c" == gaming && "${CURRENT[single]}" != "${WANTED[single]}" ]]; then
@@ -519,7 +451,7 @@ plan_changes() {
apply_changes() {
local c failed=()
LOGIN_MANAGER=plasmalogin
is_wanted single && LOGIN_MANAGER=sddm
[[ "${WANTED[single]}" == 1 ]] && LOGIN_MANAGER=sddm
for c in "${TO_DISABLE[@]}"; do
if [[ "$c" == boot ]]; then echo; echo -e "${c_bold}Boot into: gamescope${c_reset}"
-267
View File
@@ -1,267 +0,0 @@
#!/bin/bash
# Gaming on NVIDIA PCs: the SteamOS conversion (gamescope session) isn't offered there, because gamescope's DRM session shows a
# corrupted picture on NVIDIA (NVIDIA's open bug 5240452: modes above 2560x1440@120). `nvidia` is the replacement: Steam on the
# Plasma desktop, installed when missing and started at login; `bigpicture` (a sub-option) makes it start in Big Picture.
# On a supported card (RTX 20 series or newer, `nvidia_supported`) it also sets up what NVIDIA's Wayland/DRM stack wants:
# nvidia-drm.modeset=1 and fbdev=1 on the kernel command line and the NVIDIA modules in the initramfs. That didn't cure
# gamescope's picture (the driver already reported both `Y`), but it is the standard setup and may be needed.
# Sourced by steamify.sh; not meant to be run on its own.
NVIDIA_UNIT=steamify-steam-autostart.service
NVIDIA_PARAMS="nvidia-drm.modeset=1 nvidia-drm.fbdev=1"
NVIDIA_INITRAMFS_CONF=${NVIDIA_INITRAMFS_CONF:-/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf}
# The script and pacman hook that keep the initramfs file right at every kernel change.
NVIDIA_SCRIPT=${NVIDIA_SCRIPT:-/usr/local/libexec/steamify-nvidia-initramfs}
NVIDIA_HOOK=${NVIDIA_HOOK:-/etc/pacman.d/hooks/85-steamify-nvidia-initramfs.hook}
# The running kernel's command line; the tests point this at a file.
NVIDIA_CMDLINE=${NVIDIA_CMDLINE:-/proc/cmdline}
# The DRM devices in sysfs; the tests point this at a fake tree.
NVIDIA_DRM_DIR=${NVIDIA_DRM_DIR:-/sys/class/drm}
nvidia_unit_file() { echo "$HOME/.config/systemd/user/$NVIDIA_UNIT"; }
nvidia_present() {
# An NVIDIA GPU (PCI vendor 0x10de, display class) whose driver provides
# nvidia_drm. nouveau has none, and gamescope is not a problem there.
local d
for d in "$NVIDIA_DRM_DIR"/card[0-9]*/device; do
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de ]] || continue
[[ "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
modinfo nvidia_drm >/dev/null 2>&1 && return 0
done
return 1
}
# Shown on NVIDIA PCs, unless the SteamOS conversion is already on there (it
# has to be turned off first: both would start Steam at login).
nvidia_available() { nvidia_present && ! gaming_status 2>/dev/null; }
bigpicture_available() { nvidia_available; }
nvidia_status() {
pacman -Q steam >/dev/null 2>&1 && [[ -f "$(nvidia_unit_file)" ]] &&
user_systemctl is-enabled -q "$NVIDIA_UNIT" 2>/dev/null
}
nvidia_write_unit() {
# nvidia_write_unit [args]: the autostart unit, Steam started with those arguments.
local unit; unit="$(nvidia_unit_file)"
mkdir -p "$(dirname "$unit")"
service_file steamify-steam-autostart.service ARGS="$1" > "$unit" || { err "Writing $unit failed."; return 1; }
user_systemctl daemon-reload
}
nvidia_enable() {
info "Gaming on NVIDIA: Steam on the desktop, started at login..."
if ! pacman -Q steam >/dev/null 2>&1; then
sudo pacman -S --needed --noconfirm steam || { err "Installing Steam failed."; return 1; }
state_set nvidia installed_pkgs steam
fi
# Keeps what the Big Picture option set up; a first run starts Steam normally.
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
user_systemctl enable "$NVIDIA_UNIT" >/dev/null 2>&1 || { err "Enabling $NVIDIA_UNIT failed."; return 1; }
nvidia_kernel_enable || return 1
ok "Steam starts at your next login."
}
nvidia_disable() {
local pkgs unit; unit="$(nvidia_unit_file)"
user_systemctl disable --now "$NVIDIA_UNIT" >/dev/null 2>&1
rm -f "$unit"
user_systemctl daemon-reload
pkgs="$(state_get nvidia installed_pkgs)"
# Only what Steamify installed; games and the Steam folder stay.
# shellcheck disable=SC2086 # a list of package names
[[ -n "$pkgs" ]] && sudo pacman -Rns --noconfirm $pkgs >/dev/null 2>&1
state_clear nvidia
krevert bigpicture
nvidia_kernel_disable
ok "Steam no longer starts at login."
}
bigpicture_status() { grep -qs -- '-gamepadui' "$(nvidia_unit_file)"; }
bigpicture_enable() {
# The unit comes from nvidia_enable (it runs first); without it there is nothing to change.
[[ -f "$(nvidia_unit_file)" ]] || return 0
nvidia_write_unit -gamepadui || return 1
# Windows of the last session (Discord, a browser) would be restored on top of Big Picture.
kset bigpicture ksmserverrc General loginMode emptySession
ok "Steam starts in Big Picture at your next login, on an empty desktop."
}
bigpicture_disable() {
krevert bigpicture
[[ -f "$(nvidia_unit_file)" ]] || return 0
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)
nvidia_supported() {
# A supported NVIDIA GPU: PCI vendor 0x10de, display class, its kernel
# driver installed, and not older than the RTX 20 series, decided like the
# VRAM booster does (vram_nvidia_legacy_id: chwd's legacy card lists, every
# other card runs NVIDIA's open modules). Older cards are left alone.
local d
for d in "$NVIDIA_DRM_DIR"/card[0-9]*/device; do
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de ]] || continue
[[ "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
vram_nvidia_legacy_id "$(cat "$d/device" 2>/dev/null)" && continue
modinfo nvidia_drm >/dev/null 2>&1 && return 0
done
return 1
}
nvidia_legacy_gpu() {
# 0 when the only NVIDIA GPU(s) are older than RTX 20 (reported, not fixed).
local d found=0
for d in "$NVIDIA_DRM_DIR"/card[0-9]*/device; do
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de && "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
vram_nvidia_legacy_id "$(cat "$d/device" 2>/dev/null)" || return 1
found=1
done
[[ $found == 1 ]]
}
nvidia_boot_file() {
# Same boot loaders as the kernel command line elsewhere (lib/hdmi-refresh.sh).
hdmi_boot_file
}
nvidia_param_set() {
# 0 when $1 (e.g. nvidia-drm.modeset=1) is on the kernel command line or
# already in the boot loader's file (not booted yet).
# The kernel treats "nvidia_drm" and "nvidia-drm" alike: CachyOS' own
# setup may already have written the underscore spelling.
local f re; f="$(nvidia_boot_file)"; re="${1//nvidia-drm/nvidia[-_]drm}"
grep -qwE -- "$re" "$NVIDIA_CMDLINE" 2>/dev/null ||
{ [[ -n "$f" ]] && grep -qwE -- "$re" "$f" 2>/dev/null; }
}
nvidia_params_missing() {
local p
for p in $NVIDIA_PARAMS; do nvidia_param_set "$p" || return 0; done
return 1
}
nvidia_initramfs_ok() {
[[ -f "$NVIDIA_INITRAMFS_CONF" ]] || grep -qE '^MODULES=.*nvidia_drm' /etc/mkinitcpio.conf 2>/dev/null
}
nvidia_modules_everywhere() {
# 0 when every installed kernel has the nvidia_drm module (the script's own check).
patch_file steamify-nvidia-initramfs.sh | NVIDIA_MODULES_DIR="${NVIDIA_MODULES_DIR:-/usr/lib/modules}" bash -s check
}
nvidia_hook_install() {
# Never installs an empty script or hook (a piped patch_file that failed
# still lets install succeed with no input).
local script hook
script="$(patch_file steamify-nvidia-initramfs.sh)" && [[ -n "$script" ]] &&
hook="$(patch_file steamify-nvidia-initramfs.hook | fill SCRIPT="$NVIDIA_SCRIPT")" && [[ -n "$hook" ]] || return 1
printf '%s\n' "$script" | sudo install -Dm755 /dev/stdin "$NVIDIA_SCRIPT" &&
printf '%s\n' "$hook" | sudo install -Dm644 /dev/stdin "$NVIDIA_HOOK"
}
nvidia_rebuild_boot() {
local f; f="$(nvidia_boot_file)"
info "Rebuilding the initramfs and boot entries..."
case "$f" in
/etc/default/limine) sudo limine-mkinitcpio ;;
/etc/sdboot-manage.conf) sudo /usr/bin/mkinitcpio -P && sudo sdboot-manage gen ;;
/etc/default/grub) sudo /usr/bin/mkinitcpio -P && sudo grub-mkconfig -o /boot/grub/grub.cfg ;;
*) sudo /usr/bin/mkinitcpio -P ;;
esac
}
nvidia_boot_has_params() {
# 0 when the generated boot entries carry the parameters (or can't be
# checked): limine.conf, systemd-boot's entries, grub.cfg.
local target
case "$1" in
*/limine) target="${NVIDIA_LIMINE_CONF:-/boot/limine.conf}" ;;
*/sdboot-manage.conf) target="${NVIDIA_SDBOOT_DIR:-/boot/loader/entries}" ;;
*/grub) target="${NVIDIA_GRUB_CFG:-/boot/grub/grub.cfg}" ;;
*) return 0 ;;
esac
sudo test -e "$target" || return 0
sudo grep -rqs 'nvidia-drm.modeset=1' "$target"
}
nvidia_kernel_enable() {
nvidia_supported || return 0
local f changed=0 p; f="$(nvidia_boot_file)"
if nvidia_params_missing; then
if [[ -z "$f" ]]; then
warn "NVIDIA GPU found, but no supported boot loader: add '$NVIDIA_PARAMS' to the kernel command line yourself."
else
info "NVIDIA GPU found: adding $NVIDIA_PARAMS to the kernel command line (fixes a corrupted screen in gaming mode)..."
backup_file "$f"
case "$f" in
*/limine)
sudo sed -i -E "s/^(KERNEL_CMDLINE\[default\]\+?=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
*/sdboot-manage.conf)
sudo sed -i -E "s/^(LINUX_OPTIONS=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
*/grub)
sudo sed -i -E "s/^(GRUB_CMDLINE_LINUX_DEFAULT=\"[^\"]*)\"/\1 $NVIDIA_PARAMS\"/" "$f" ;;
esac
if ! grep -q "nvidia-drm.fbdev=1" "$f"; then
err "Couldn't add the NVIDIA parameters to $f (no kernel command line setting in it): add '$NVIDIA_PARAMS' yourself."
return 1
fi
changed=1
fi
fi
nvidia_hook_install || { err "Installing the NVIDIA initramfs hook failed."; return 1; }
local had=0; [[ -f "$NVIDIA_INITRAMFS_CONF" ]] && had=1
sudo env NVIDIA_INITRAMFS_CONF="$NVIDIA_INITRAMFS_CONF" NVIDIA_MODULES_DIR="${NVIDIA_MODULES_DIR:-/usr/lib/modules}" "$NVIDIA_SCRIPT" sync
if [[ -f "$NVIDIA_INITRAMFS_CONF" && $had == 0 ]]; then
info "Loading the NVIDIA modules early (initramfs)..."
changed=1
elif [[ ! -f "$NVIDIA_INITRAMFS_CONF" && $had == 1 ]]; then
warn "A kernel without the NVIDIA modules is installed: not loading them early any more (rebuilding the initramfs without them)."
changed=1
elif [[ ! -f "$NVIDIA_INITRAMFS_CONF" ]] && ! nvidia_initramfs_ok; then
warn "Not every installed kernel has the NVIDIA modules: not loading them early for now (the kernel parameters still apply; this is checked again at every kernel update)."
fi
if [[ $changed == 1 ]]; then
nvidia_rebuild_boot || { err "Rebuilding the boot entries failed."; return 1; }
if ! nvidia_boot_has_params "$f"; then
err "The boot entries don't have the NVIDIA parameters: the initramfs or boot entry build failed (see above)."
return 1
fi
ok "NVIDIA gaming mode fix applied; it takes effect after a reboot."
fi
return 0
}
nvidia_kernel_disable() {
local f changed=0; f="$(nvidia_boot_file)"
if [[ -n "$f" ]] && grep -q "$NVIDIA_PARAMS" "$f" 2>/dev/null; then
sudo sed -i "s/ \?$NVIDIA_PARAMS//" "$f"
changed=1
fi
[[ -f "$NVIDIA_INITRAMFS_CONF" ]] && { sudo rm -f "$NVIDIA_INITRAMFS_CONF"; changed=1; }
sudo rm -f "$NVIDIA_HOOK" "$NVIDIA_SCRIPT"
[[ $changed == 1 ]] && nvidia_rebuild_boot
return 0
}
+1 -1
View File
@@ -33,7 +33,7 @@ bootstrap_yay() {
sudo pacman -S --needed --noconfirm base-devel git || return 1
local tmp_dir
make_tmpdir tmp_dir
tmp_dir="$(mktemp -d)"
info "Cloning yay-bin from the AUR..."
if ! git clone --depth 1 https://aur.archlinux.org/yay-bin.git "$tmp_dir/yay-bin"; then
err "Failed to clone yay-bin from the AUR."
+1 -31
View File
@@ -42,7 +42,7 @@ single_wallet_enable() {
ok "Single user mode's wallet (no password) is back; your own is kept as kdewallet.kwl$WALLET_BACKUP."
return 0
fi
make_tmpdir tmp
tmp="$(mktemp -d)"
if ! fetch_valve_presets "$tmp"; then
rm -rf "$tmp"
warn "Couldn't get Valve's empty wallet; apps may still ask for the wallet password."
@@ -119,36 +119,7 @@ single_launcher_drop() {
return 0
}
# Without the SteamOS conversion (NVIDIA PCs: gamescope's session is broken there) nothing logs in by itself, so single user
# mode does it: SDDM, autologin into the Plasma session. Named to sort after steam-set-session's zz-steamos-autologin.conf,
# which may still say gamescope from an earlier conversion.
SINGLE_AUTOLOGIN=${SINGLE_AUTOLOGIN:-/etc/sddm.conf.d/zzz-steamify-autologin.conf}
single_login_needed() { nvidia_present && ! gaming_status; }
single_login_enable() {
single_login_needed || return 0
switch_to_sddm || return 1
info "Logging in to the desktop by itself (SDDM autologin for $TARGET_USER)..."
sudo mkdir -p "$(dirname "$SINGLE_AUTOLOGIN")"
sudo tee "$SINGLE_AUTOLOGIN" > /dev/null << EOF
[Autologin]
User=$TARGET_USER
Session=plasma.desktop
Relogin=true
EOF
remove_sddm_base_autologin
}
single_login_disable() {
[[ -f "$SINGLE_AUTOLOGIN" ]] || return 0
sudo rm -f "$SINGLE_AUTOLOGIN"
# The way back is CachyOS's own login manager, unless the conversion is on (it keeps SDDM).
gaming_status || switch_to_plasmalogin
}
single_enable() {
single_login_enable || return 1
info "Turning off the lock screen, user switching and logging out..."
stop_plasmashell_for_edit
@@ -174,7 +145,6 @@ single_enable() {
}
single_disable() {
single_login_disable
info "Restoring the lock screen, user switching and logging out..."
stop_plasmashell_for_edit
if has_journal single; then
+1 -1
View File
@@ -123,7 +123,7 @@ migrate_layout() {
"$(wizard_desktop_dir)/$WIZARD_DESKTOP_NAME"; do
[[ -f "$f" ]] && sed -i "s|$old_bin/|$STEAMIFY_BIN/|g" "$f"
done
best_effort user_systemctl daemon-reload
user_systemctl daemon-reload 2>/dev/null
fi
if [[ -f "$old_icon" ]]; then
if [[ -e "$WIZARD_ICON" ]]; then rm -f "$old_icon"; else mv "$old_icon" "$WIZARD_ICON"; fi
+15 -43
View File
@@ -5,63 +5,35 @@
steam_enable() {
info "Applying non-optional SteamOS environment & keyboard fixes..."
local steam_env_dir
local steam_env_dir systemd_user_dir
steam_env_dir="$HOME/.config/environment.d"
mkdir -p "$steam_env_dir"
# 2. Prevent KDE Wayland from blocking the virtual keyboard overlay
echo "KWIN_IM_SHOW_ALWAYS=1" > "$steam_env_dir/99-kde-virtual-keyboard.conf"
ok "Steam UI parameters and keyboard fix deployed successfully."
}
# 3. Setup robust background systemd service for Steam autostart on Desktop Mode
systemd_user_dir="$HOME/.config/systemd/user"
mkdir -p "$systemd_user_dir"
# 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
service_file steam-desktop-autostart.service > "$systemd_user_dir/steam-desktop-autostart.service"
silent_status() {
# 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" ]]
}
# Clean out old .desktop shortcut so they don't fight
rm -f "$HOME/.config/autostart/steam.desktop"
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
best_effort user_systemctl disable --now steam-desktop-autostart.service
rm -f "$unit"
# Reload user systemd context and activate the background loop
user_systemctl daemon-reload
}
user_systemctl enable --now steam-desktop-autostart.service
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."
ok "Steam UI parameters and keyboard autostart deployed successfully."
}
steam_disable() {
info "Removing Steam desktop settings..."
# The autostart entry is the `silent` option's: removed with it, and here
# too for when the conversion goes off by itself.
silent_status && silent_disable
silent_old_unit_remove
rm -f "$HOME/.config/environment.d/99-kde-virtual-keyboard.conf"
info "Removing Steam desktop autostart..."
user_systemctl disable --now steam-desktop-autostart.service 2>/dev/null
rm -f "$HOME/.config/systemd/user/steam-desktop-autostart.service" \
"$HOME/.config/environment.d/99-kde-virtual-keyboard.conf"
user_systemctl daemon-reload
ok "Steam desktop settings removed (takes full effect at next login)."
}
+5 -1
View File
@@ -56,7 +56,7 @@ steamgame_steam_busy() {
steamgame_edit() {
# steamgame_edit <function>: runs it with Steam closed, then starts Steam
# again if it was running (silently, in the tray).
# again if it was running (through our autostart unit when that's there).
local was_running=false i
if pgrep -x steam >/dev/null; then
steamgame_steam_busy && return 1
@@ -72,7 +72,11 @@ steamgame_edit() {
fi
"$1"; local rc=$?
if [[ "$was_running" == true ]]; then
if user_systemctl is-enabled -q steam-desktop-autostart.service 2>/dev/null; then
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."
fi
return "$rc"
+195 -49
View File
@@ -15,6 +15,164 @@ detect_valve_fremont() {
[[ "$vendor" == "OEM" && "$product" == "F7F" ]]
}
# Kernel pinned on a Steam Machine (optional): newer linux-cachyos releases
# rebooted it instead of shutting down, which the power-off fix now handles. The packages are kept in
# PINNED_KERNEL_DIR, so re-applying (or reinstalling after an update slipped
# through) needs no download.
PINNED_KERNEL_VER="7.1.6-1"
PINNED_KERNEL_KVER="7.1.6-1-cachyos"
PINNED_KERNEL_PKGS=(linux-cachyos linux-cachyos-headers)
PINNED_KERNEL_DIR="${PINNED_KERNEL_DIR:-/var/cache/steamify/kernel}"
# SHA-256 of each package, so a file from any source is the one reviewed
# here; its CachyOS signature is checked as well.
declare -A PINNED_KERNEL_SHA256=(
[linux-cachyos]=417fcd07102192b86e78e92ed7171d5a49378e9f57faea3fa2c7c541e9f68d08
[linux-cachyos-headers]=d069866a11d9092746e1d5133cefd8924f027da2c9bf5af38d30b3aed6ded9bf
)
# Tried in order, after the kernel dir and pacman's cache. Our own release
# always has these files; the archive keeps every release; the mirror only
# the current one. PINNED_KERNEL_URL puts another source (a directory
# holding the files) in front.
PINNED_KERNEL_SOURCES=(
${PINNED_KERNEL_URL:+"$PINNED_KERNEL_URL"}
"https://github.com/theupriser/steamify-cachyos/releases/download/kernel-$PINNED_KERNEL_VER"
"https://archive.cachyos.org/archive/cachyos"
"https://mirror.cachyos.org/repo/x86_64/cachyos"
)
pinned_kernel_installed() {
local p
for p in "${PINNED_KERNEL_PKGS[@]}"; do
[[ "$(pacman -Q "$p" 2>/dev/null)" == "$p $PINNED_KERNEL_VER" ]] || return 1
done
}
fetch_pinned_kernel_file() {
# $1 = file name. Local kernel dir first, then pacman's cache, then the
# download sources. Downloads go to a .part file so a broken one is never
# mistaken for a finished one.
local f="$1" dest="$PINNED_KERNEL_DIR/$1" src
[[ -s "$dest" ]] && return 0
if [[ -s "/var/cache/pacman/pkg/$f" ]]; then
sudo cp "/var/cache/pacman/pkg/$f" "$dest" && return 0
fi
for src in "${PINNED_KERNEL_SOURCES[@]}"; do
if sudo curl -fL --retry 2 --connect-timeout 15 -o "$dest.part" "$src/$f" 2>/dev/null; then
sudo mv "$dest.part" "$dest"
return 0
fi
warn "Couldn't get $f from $src, trying the next source..."
done
sudo rm -f "$dest.part"
return 1
}
verify_pinned_kernel_pkg() {
# $1 = package name, $2 = file. Both checks must pass: the SHA-256 from
# this script, and the CachyOS signature (pacman on its own installs a
# local file without a .sig: LocalFileSigLevel = Optional).
local sum
sum="$(sha256sum "$2" | cut -d' ' -f1)"
if [[ "$sum" != "${PINNED_KERNEL_SHA256[$1]}" ]]; then
err "$(basename "$2") doesn't match its expected checksum."
return 1
fi
if ! sudo pacman-key --verify "$2.sig" "$2" >/dev/null 2>&1; then
err "$(basename "$2") doesn't have a valid CachyOS signature."
return 1
fi
}
pin_kernel_in_pacman_conf() {
# Adds our packages to IgnorePkg in [options], keeping what's there.
local p
for p in "${PINNED_KERNEL_PKGS[@]}"; do
grep -Eq "^IgnorePkg\s*=.*(\s|=)$p(\s|$)" /etc/pacman.conf && continue
if grep -Eq '^IgnorePkg\s*=' /etc/pacman.conf; then
sudo sed -i -E "0,/^IgnorePkg\s*=/s/^(IgnorePkg\s*=.*)$/\1 $p/" /etc/pacman.conf
else
sudo sed -i -E "0,/^\[options\]/s//[options]\nIgnorePkg = $p/" /etc/pacman.conf
fi
done
}
unpin_kernel_in_pacman_conf() {
local p
for p in "${PINNED_KERNEL_PKGS[@]}"; do
sudo sed -i -E "/^IgnorePkg\s*=/s/\s$p(\s|$)/\1/" /etc/pacman.conf
done
# Drop the line if nothing is left on it.
sudo sed -i -E '/^IgnorePkg\s*=\s*$/d' /etc/pacman.conf
}
install_pinned_kernel() {
sudo mkdir -p "$PINNED_KERNEL_DIR"
pin_kernel_in_pacman_conf
if pinned_kernel_installed; then
ok "Kernel $PINNED_KERNEL_VER already installed and pinned."
return 0
fi
local p f files=()
info "Getting kernel $PINNED_KERNEL_VER (kept in $PINNED_KERNEL_DIR)..."
for p in "${PINNED_KERNEL_PKGS[@]}"; do
f="$p-$PINNED_KERNEL_VER-x86_64.pkg.tar.zst"
fetch_pinned_kernel_file "$f" && fetch_pinned_kernel_file "$f.sig" ||
{ err "Couldn't download $f from any source."; return 1; }
if ! verify_pinned_kernel_pkg "$p" "$PINNED_KERNEL_DIR/$f"; then
# Removed, so the next run fetches it again.
sudo rm -f "$PINNED_KERNEL_DIR/$f" "$PINNED_KERNEL_DIR/$f.sig"
err "Removed it; run the wizard again to download it once more."
return 1
fi
files+=("$PINNED_KERNEL_DIR/$f")
done
# pacman checks each package against the .sig next to it.
info "Installing kernel $PINNED_KERNEL_VER..."
if ! sudo pacman -U --noconfirm "${files[@]}"; then
err "Installing kernel $PINNED_KERNEL_VER failed."
return 1
fi
[[ "$(uname -r)" != "$PINNED_KERNEL_KVER" ]] && RESTART_FOR_LOGIN=true
ok "Kernel $PINNED_KERNEL_VER installed and pinned (restart to use it)."
}
remove_kernel_pin() {
# Back to CachyOS's current kernel. The packages stay in
# PINNED_KERNEL_DIR, so turning support on again doesn't download.
unpin_kernel_in_pacman_conf
pinned_kernel_installed || return 0
info "Updating the kernel back to CachyOS's current version..."
sudo pacman -Syu --noconfirm ||
{ warn "Updating the kernel failed; run: sudo pacman -Syu"; return 0; }
RESTART_FOR_LOGIN=true
}
# "Pin the kernel" menu item, a sub-option of Steam Machine support. The
# power-off fix made it unnecessary: only shown while on, to remove it.
kpin_available() { detect_valve_fremont && kpin_status; }
kpin_status() {
pinned_kernel_installed && grep -Eq '^IgnorePkg\s*=.*\slinux-cachyos(\s|$)' /etc/pacman.conf
}
kpin_enable() {
install_pinned_kernel || return 1
# The DKMS pacman hook built leds-valve for the new headers; make sure.
if pacman -Qi leds-valve-dkms-git >/dev/null 2>&1 &&
! dkms status -k "$PINNED_KERNEL_KVER" leds-valve-dkms 2>/dev/null | grep -q installed; then
sudo dkms install leds-valve-dkms/0.1 -k "$PINNED_KERNEL_KVER" ||
warn "Building the LED driver for $PINNED_KERNEL_KVER failed."
fi
}
kpin_disable() {
# Saved HDMI refresh boost EDIDs were for the pinned kernel only (newer
# ones read the whole EDID), also those of displays not connected now.
hdmi_status && hdmi_forget_all
remove_kernel_pin
}
install_kernel_headers() {
# DKMS can only build leds-valve against kernels whose headers are
# installed. CachyOS ships several kernels (linux-cachyos, -lts, -bore,
@@ -42,7 +200,24 @@ install_kernel_headers() {
sudo pacman -S --needed --noconfirm "${headers[@]}"
}
led_write_dkms_override() {
install_valve_led_driver() {
# Installs the leds-valve DKMS driver from the AUR so the front LED
# bar is exposed under /sys/class/leds/valve-leds[N].
local aur_helper
aur_helper="$(find_aur_helper)"
if [[ -z "$aur_helper" ]]; then
warn "No AUR helper available - can't install leds-valve-dkms-git."
warn "Install one yourself, then run: yay -S leds-valve-dkms-git"
return 1
fi
local -a flags
read -ra flags <<< "$(aur_noninteractive_flags "$aur_helper")"
# Headers first: without them the package installs fine but DKMS
# silently builds nothing, so modprobe later finds no module.
install_kernel_headers || return 1
# The upstream Makefile builds against `uname -r` instead of the kernel
# DKMS targets, so every other installed kernel (e.g. linux-cachyos-lts)
# got the running kernel's tree and failed (wrong kernel, and gcc against
@@ -57,22 +232,17 @@ led_write_dkms_override() {
err "Couldn't write $LED_DKMS_OVERRIDE; without it the LED driver only builds for the running kernel."
return 1
fi
}
led_install_package() {
# led_install_package <aur helper>
local aur_helper="$1"
local -a flags
read -ra flags <<< "$(aur_noninteractive_flags "$aur_helper")"
if pacman -Qi leds-valve-dkms-git >/dev/null 2>&1; then
ok "leds-valve-dkms-git already installed."
return 0
fi
if ! pacman -Qi leds-valve-dkms-git >/dev/null 2>&1; then
info "Installing leds-valve-dkms-git from the AUR via $aur_helper (non-interactive)..."
"$aur_helper" -S "${flags[@]}" leds-valve-dkms-git || { err "Installing leds-valve-dkms-git failed."; return 1; }
}
if ! "$aur_helper" -S "${flags[@]}" leds-valve-dkms-git; then
err "Installing leds-valve-dkms-git failed."
return 1
fi
else
ok "leds-valve-dkms-git already installed."
fi
led_build_all_kernels() {
# Build for every installed kernel that has headers, so booting another
# one (e.g. the LTS kernel) still has the driver.
local kdir kver
@@ -87,9 +257,7 @@ led_build_all_kernels() {
return 1
fi
done
}
led_load_module() {
# Load now, and on every boot.
echo leds-valve | sudo tee /etc/modules-load.d/leds-valve.conf >/dev/null
@@ -114,26 +282,7 @@ led_load_module() {
warn "No valve-leds nodes under /sys/class/leds/ yet. Reboot, then check with:"
warn " ls /sys/class/leds/ | grep valve ; sudo dmesg | grep -i valve"
fi
}
install_valve_led_driver() {
# Installs the leds-valve DKMS driver from the AUR so the front LED
# bar is exposed under /sys/class/leds/valve-leds[N].
local aur_helper
aur_helper="$(find_aur_helper)"
if [[ -z "$aur_helper" ]]; then
warn "No AUR helper available - can't install leds-valve-dkms-git."
warn "Install one yourself, then run: yay -S leds-valve-dkms-git"
return 1
fi
# Headers first: without them the package installs fine but DKMS
# silently builds nothing, so modprobe later finds no module.
install_kernel_headers || return 1
led_write_dkms_override || return 1
led_install_package "$aur_helper" || return 1
led_build_all_kernels || return 1
led_load_module
}
LED_UDEV_RULE="/etc/udev/rules.d/70-valve-leds-user.rules"
@@ -258,17 +407,14 @@ wifi_backend_disable() {
serial_enable() {
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; }
# The file applies at every boot; now too, unless /sys is read-only (the ISO's installer runs in a chroot).
best_effort sudo systemd-tmpfiles --create "$SERIAL_TMPFILES" ||
info "The serial number becomes readable for Steam at the next boot."
return 0
}
serial_disable() {
sudo rm -f "$SERIAL_TMPFILES"
best_effort sudo chmod 0400 /sys/class/dmi/id/product_serial
sudo chmod 0400 /sys/class/dmi/id/product_serial 2>/dev/null
return 0
}
@@ -301,7 +447,7 @@ EOF
wifi_backend_enable || return 1
sudo systemctl enable --now inputplumber.service
sudo systemctl enable --now steamos-manager.service
best_effort user_systemctl enable steamos-manager.service
user_systemctl enable steamos-manager.service 2>/dev/null
# HDMI-CEC ran before this and couldn't link cecd to steamos-manager yet.
cec_status && cec_link_steamos_manager
@@ -318,19 +464,19 @@ EOF
machine_disable() {
info "Removing Steam Machine support..."
best_effort user_systemctl disable --now steamos-manager.service
best_effort sudo systemctl disable --now steamos-manager.service
best_effort sudo systemctl disable --now inputplumber.service
best_effort sudo pacman -Rns --noconfirm steamos-manager inputplumber
user_systemctl disable --now steamos-manager.service 2>/dev/null
sudo systemctl disable --now steamos-manager.service 2>/dev/null
sudo systemctl disable --now inputplumber.service 2>/dev/null
sudo pacman -Rns --noconfirm steamos-manager inputplumber 2>/dev/null
serial_disable
wifi_backend_disable
sudo rm -f "$LED_UDEV_RULE" /etc/modules-load.d/leds-valve.conf
sudo udevadm control --reload
best_effort sudo modprobe -r leds-valve
best_effort sudo pacman -Rns --noconfirm leds-valve-dkms-git
sudo modprobe -r leds-valve 2>/dev/null
sudo pacman -Rns --noconfirm leds-valve-dkms-git 2>/dev/null
krevert machine
reload_powerdevil
best_effort sudo systemctl disable ensure-kernel-headers.service
sudo systemctl disable ensure-kernel-headers.service 2>/dev/null
led_dkms_override_remove
sudo rm -f "$HEADERS_UNIT" "$HEADERS_SCRIPT"
sudo rm -rf "$(dirname "$HEADERS_SCRIPT")" "$(dirname "$HEADERS_SCRIPT_OLD")"
+21 -7
View File
@@ -8,6 +8,7 @@
# package-owned); per-user settings go through the undo journal.
# Sourced by steamify.sh; not meant to be run on its own.
VALVE_MIRROR="https://steamdeck-packages.steamos.cloud/archlinux-mirror"
NESTED_DIR=/usr/local/share/applications/steam/holo-nested-desktop
EXTRAS_FILES=(
/usr/local/bin/holo-add-to-steam
@@ -22,12 +23,25 @@ STEAM_KEYBOARD_RULE=cachyos-gamescope-boot-steam-keyboard
fetch_valve_presets() {
# fetch_valve_presets <dir>: download and extract the newest
# steamdeck-kde-presets (from the newest SteamOS release repo, jupiter-3.9,
# jupiter-3.10, ...) into <dir>.
local dir="$1" pkg
pkg="$(valve_fetch_pkg jupiter steamdeck-kde-presets "$dir")" || return 1
tar -I unzstd -xf "$pkg" -C "$dir" usr/bin usr/share ||
{ err "Extracting $(basename "$pkg") failed."; return 1; }
# steamdeck-kde-presets into <dir>. The newest SteamOS release repo
# (jupiter-3.9, jupiter-3.10, ...) is found on the mirror; its pacman
# database gives the exact file name and SHA-256, which is verified.
local dir="$1" repo desc file_name sha256
repo="$(curl -fsL "$VALVE_MIRROR/" | grep -oE 'jupiter-[0-9]+\.[0-9]+/' | tr -d / | sort -V | tail -n 1)"
[[ -n "$repo" ]] && curl -fsL "$VALVE_MIRROR/$repo/os/x86_64/$repo.db" -o "$dir/repo.db" ||
{ err "Couldn't read Valve's SteamOS package index ($VALVE_MIRROR)."; return 1; }
desc="$(tar -tf "$dir/repo.db" 2>/dev/null | grep -E '^steamdeck-kde-presets-[0-9][^/]*/desc$' | head -n 1)"
[[ -n "$desc" ]] || { err "No steamdeck-kde-presets in Valve's $repo repository."; return 1; }
file_name="$(tar -xOf "$dir/repo.db" "$desc" | awk '/^%FILENAME%$/ { getline; print }')"
sha256="$(tar -xOf "$dir/repo.db" "$desc" | awk '/^%SHA256SUM%$/ { getline; print }')"
info "Downloading $file_name ($repo)..."
curl -fsL "$VALVE_MIRROR/$repo/os/x86_64/$file_name" -o "$dir/presets.pkg.tar.zst" ||
{ err "Downloading $file_name failed."; return 1; }
echo "$sha256 $dir/presets.pkg.tar.zst" | sha256sum -c --quiet - ||
{ err "Checksum mismatch for $file_name; not using it."; return 1; }
tar -I unzstd -xf "$dir/presets.pkg.tar.zst" -C "$dir" usr/bin usr/share ||
{ err "Extracting $file_name failed."; return 1; }
}
extras_enable() {
@@ -40,7 +54,7 @@ extras_enable() {
done
local tmp_dir src
make_tmpdir tmp_dir
tmp_dir="$(mktemp -d)"
if ! fetch_valve_presets "$tmp_dir"; then
rm -rf "$tmp_dir"
return 1
-49
View File
@@ -1,49 +0,0 @@
#!/bin/bash
# Valve's SteamOS package mirror: finding its newest repository and fetching a
# verified package from it. Used by the SteamOS extras, the Steam Machine CEC
# driver, the BIOS update and the os-release version.
# Sourced by steamify.sh; not meant to be run on its own.
VALVE_MIRROR="https://steamdeck-packages.steamos.cloud/archlinux-mirror"
valve_newest_repo() {
# valve_newest_repo <prefix> [max-seconds]: the newest <prefix>-X.Y repo
# (jupiter, holo), compared as versions: 3.10 is newer than 3.9. Prints
# nothing when the mirror can't be reached.
local -a limit=()
[[ -n "${2:-}" ]] && limit=(--max-time "$2")
curl -fsL "${limit[@]}" "$VALVE_MIRROR/" 2>/dev/null | grep -oE "$1-[0-9]+\.[0-9]+/" | tr -d / | sort -uV | tail -n 1
}
valve_repo_url() { echo "$VALVE_MIRROR/$1/os/x86_64"; }
valve_desc_field() {
# valve_desc_field <db> <desc path> <FIELD>: one value from a package's
# entry in a pacman database (FILENAME, SHA256SUM).
tar -xOf "$1" "$2" 2>/dev/null | awk -v f="%$3%" '$0 == f { getline; print }'
}
valve_fetch_pkg() {
# valve_fetch_pkg <repo prefix> <package> <dir>: download the newest
# <package> from the newest <prefix> repository into <dir> and print its
# path. The file name and SHA-256 come from the repository's database and
# the checksum is verified; the database is kept in <dir> for more calls.
local prefix="$1" name="$2" dir="$3" repo db desc file_name sha256
repo="$(valve_newest_repo "$prefix")"
db="$dir/$prefix.db"
if [[ ! -f "$db" ]]; then
[[ -n "$repo" ]] && curl -fsL "$(valve_repo_url "$repo")/$repo.db" -o "$db" ||
{ err "Couldn't read Valve's SteamOS package index ($VALVE_MIRROR)."; return 1; }
fi
desc="$(tar -tf "$db" 2>/dev/null | grep -E "^$name-[0-9][^/]*/desc$" | head -n 1)"
[[ -n "$desc" ]] || { err "No $name in Valve's $repo repository."; return 1; }
file_name="$(valve_desc_field "$db" "$desc" FILENAME)"
sha256="$(valve_desc_field "$db" "$desc" SHA256SUM)"
info "Downloading $file_name ($repo)..." >&2
curl -fsL "$(valve_repo_url "$repo")/$file_name" -o "$dir/$file_name" ||
{ err "Downloading $file_name failed."; return 1; }
echo "$sha256 $dir/$file_name" | sha256sum -c --quiet - >&2 ||
{ err "Checksum mismatch for $file_name; not using it."; return 1; }
echo "$dir/$file_name"
}
+11 -40
View File
@@ -47,27 +47,26 @@ theme_status() {
[[ "$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage)" == "$VAPOR_LOOKANDFEEL" ]]
}
theme_install_package() {
pacman -Q cachyos-vapor >/dev/null 2>&1 && return 0
theme_enable() {
if ! pacman -Q cachyos-vapor >/dev/null 2>&1; then
info "Installing cachyos-vapor..."
sudo pacman -S --needed --noconfirm cachyos-vapor || { err "Installing cachyos-vapor failed."; return 1; }
# Only remove it again on disable if we were the ones installing it.
state_set theme installed_pkg 1
}
theme_check_offline() {
fi
# Without a session (the ISO's installer), for a user who has never
# logged in: the layout still CachyOS's default from /etc/skel is
# removed (after the backup below), and Plasma builds its first layout
# from the look-and-feel package, as --resetLayout does below.
local layout=~/.config/plasma-org.kde.plasma.desktop-appletsrc
local offline=false layout=~/.config/plasma-org.kde.plasma.desktop-appletsrc
if [[ -z "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]]; then
if [[ -e "$layout" ]] && ! cmp -s "$layout" "/etc/skel/.config/${layout##*/}"; then
err "Run this from the Plasma desktop: applying the Vapor layout needs a running Plasma session."
return 1
fi
}
offline=true
fi
theme_backup_originals() {
# Only the first time, so a re-apply doesn't overwrite the originals.
local backup="$STATE_DIR/theme-layout" f
if [[ ! -d "$backup" ]]; then
@@ -85,9 +84,7 @@ theme_backup_originals() {
[[ -f "$f" ]] && kset theme "$f" Settings gtk-cursor-theme-name \
"$(kreadconfig6 --file "$f" --group Settings --key gtk-cursor-theme-name)"
done
}
theme_set_look() {
kset theme kdeglobals KDE LookAndFeelPackage "$VAPOR_LOOKANDFEEL"
# Vapor is a dark theme: register it as the dark one, or Plasma's Dark
# Mode toggle shows "off" and offers to switch to Breeze Dark.
@@ -97,17 +94,6 @@ theme_set_look() {
# scheme that is already named in the config, without writing its colors.
kset theme kdeglobals General ColorScheme --delete
plasma-apply-colorscheme Vapor >/dev/null 2>&1 || true
}
theme_enable() {
theme_install_package || return 1
local offline=false
if [[ -z "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]]; then
theme_check_offline || return 1
offline=true
fi
theme_backup_originals
theme_set_look
if [[ "$offline" == true ]]; then
rm -f ~/.config/plasma-org.kde.plasma.desktop-appletsrc ~/.config/plasmashellrc
@@ -120,32 +106,17 @@ theme_enable() {
# SteamOS panel, launcher icon and wallpaper. It needs plasmashell up.
lookandfeeltool -a "$VAPOR_LOOKANDFEEL" --resetLayout >/dev/null 2>&1 ||
{ err "lookandfeeltool failed."; return 1; }
# The new layout has a new launcher, without single user's settings, and the default taskbar pins.
# The new layout has a new launcher, without single user's settings.
if single_status; then
sleep 3
stop_plasmashell_for_edit
taskbar_drop_discover
single_status && single_launcher
single_launcher
restart_plasmashell_if_stopped
fi
extras_enable || warn "SteamOS desktop extras not installed (see above); the theme itself is on."
ok "Vapor theme active."
}
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() {
extras_disable
info "Restoring the previous desktop look and layout..."
+2 -8
View File
@@ -44,13 +44,6 @@ vram_nvidia() {
# 470xx, 390xx); every other NVIDIA card runs the open kernel modules.
VRAM_CHWD_IDS=/var/lib/chwd/ids
vram_nvidia_legacy_id() {
# vram_nvidia_legacy_id <pci device id, with or without 0x>: 0 when chwd
# lists the card for a closed legacy branch, i.e. it is older than the
# RTX 20 series. Also what lib/nvidia.sh uses to decide if a card is supported.
grep -qwi "${1#0x}" "$VRAM_CHWD_IDS"/nvidia-*.ids 2>/dev/null
}
vram_nvidia_case() {
# Why an NVIDIA card's VRAM isn't registered, so the menu can say what to
# do: "update" (open modules older than 615), "switch <chwd profile>"
@@ -69,7 +62,8 @@ vram_nvidia_case() {
esac
for d in /sys/bus/pci/devices/*; do
[[ "$(cat "$d/vendor" 2>/dev/null)" == 0x10de && "$(cat "$d/class" 2>/dev/null)" == 0x03* ]] || continue
vram_nvidia_legacy_id "$(cat "$d/device")" && { echo legacy; return; }
id="$(cat "$d/device")"; id="${id#0x}"
grep -qwi "$id" "$VRAM_CHWD_IDS"/nvidia-*.ids 2>/dev/null && { echo legacy; return; }
done
for p in 580xx 470xx 390xx; do
pacman -Q "nvidia-$p-dkms" >/dev/null 2>&1 && { echo "switch nvidia-dkms-$p"; return; }
+35 -3
View File
@@ -48,11 +48,43 @@ launcher_repair() { [[ -f "$WIZARD_APPS/$WIZARD_OLD_NAME" ]] && ! launcher_statu
launcher_enable() {
info "Adding the Steamify shortcut (the app on the desktop and in the launcher, Steamify Terminal in the launcher)..."
# Both scripts download the newest release when they run (patches/).
patch_file steamify-start.sh | fill URL="$WIZARD_URL" | install_executable "$WIZARD_LAUNCHER" 755
install_executable "$WIZARD_LAUNCHER" 755 << EOF
#!/bin/bash
# Installed by Steamify CachyOS: run its newest release.
# pipefail: a failed download must count as a failure, not an empty script.
set -o pipefail
if ! curl -fsSL --max-time 30 "$WIZARD_URL" | bash; then
echo
echo "Couldn't download or run the wizard. Are you connected to the internet?"
echo
read -rp "Press Enter to close this window... " _
exit 1
fi
# Done: close the window after a countdown (Enter closes it right away).
echo
for (( i = 10; i > 0; i-- )); do
printf '\rClosing this window in %2d seconds (Enter to close now)... ' "\$i"
read -rs -t 1 _ && break
done
echo
EOF
# The app, without a terminal. Only the first time, when PySide6 still
# has to be installed, it runs in Konsole: sudo asks for the password there.
patch_file steamify-app-start.sh | fill URL="$WIZARD_APP_URL" | install_executable "$WIZARD_APP_LAUNCHER" 755
install_executable "$WIZARD_APP_LAUNCHER" 755 << EOF
#!/bin/bash
# Installed by Steamify CachyOS: start the newest release of its app.
set -o pipefail
if [[ "\${1:-}" != --in-terminal ]] && ! python3 -c 'import PySide6.QtQml' 2>/dev/null; then
exec konsole -e "\$0" --in-terminal
fi
if ! curl -fsSL --max-time 30 "$WIZARD_APP_URL" | bash; then
msg="Couldn't download or start Steamify. Are you connected to the internet?"
if [[ "\${1:-}" == --in-terminal ]]; then echo; echo "\$msg"; read -rp "Press Enter to close this window... " _
else kdialog --title Steamify --sorry "\$msg" 2>/dev/null; fi
exit 1
fi
EOF
# The icon comes with the release; without it, Steam's own icon.
local icon=steam tmp
-2
View File
@@ -14,6 +14,4 @@ read and reviewed on their own. `lib/*.sh` reads them with `patch_file
| `steam-shortcuts.py` | `lib/steam-game.sh` (Add as non-Steam game) | Reads and writes Steam's binary `shortcuts.vdf` (find, add or update, remove) |
| `steamify-notifier.py` | `lib/update-notifier.sh` (Update notifications) | The daily check: notification and tray icon when there's a new release |
| `steamify-os-release.sh`, `steamify-os-release.hook` | `lib/login-manager.sh` (SteamOS conversion) | What Steam's System settings show besides the OS name (which stays CachyOS's): `VERSION_ID=steamos-X.Y`, `VERSION_CODENAME=steam-machine`, `VARIANT`/`VARIANT_ID` Steamify with its version, in `/etc/os-release`; the pacman hook runs it again after cachyos-hooks (`fill SCRIPT=... VERSION=... STEAMOS=...`) |
| `steamify-nvidia-initramfs.sh`, `steamify-nvidia-initramfs.hook` | `lib/nvidia.sh` (SteamOS conversion, NVIDIA fix) | The pacman hook (before the initramfs is built, after DKMS) and its script: the NVIDIA modules go into the initramfs only while every installed kernel has them, decided again at every kernel or driver change (`fill SCRIPT=...`) |
| `cros-ec-cec-single-port.patch` | `lib/cec.sh` (HDMI-CEC) | Makes Valve's Steam Machine CEC driver find amdgpu's HDMI port |
| `steamify-start.sh`, `steamify-app-start.sh` | `lib/wizard-shortcut.sh` (Steamify shortcut) | The two start scripts of the shortcut: "Steamify Terminal" runs the newest `steamify.sh` in Konsole, the app's launcher runs the newest `steamify-app.sh` (`fill URL=...`) |
-12
View File
@@ -1,12 +0,0 @@
#!/bin/bash
# Installed by Steamify CachyOS: start the newest release of its app.
set -o pipefail
if [[ "${1:-}" != --in-terminal ]] && ! python3 -c 'import PySide6.QtQml' 2>/dev/null; then
exec konsole -e "$0" --in-terminal
fi
if ! curl -fsSL --max-time 30 "@URL@" | bash; then
msg="Couldn't download or start Steamify. Are you connected to the internet?"
if [[ "${1:-}" == --in-terminal ]]; then echo; echo "$msg"; read -rp "Press Enter to close this window... " _
else kdialog --title Steamify --sorry "$msg" 2>/dev/null; fi
exit 1
fi
+2 -3
View File
@@ -51,9 +51,8 @@ def latest():
def pending(new):
# Newer than the last Steamify that ran here, and not skipped.
seen, found = version(state("seen") or "0"), version(new)
# A tag that isn't a plain version (a pre-release name) is never offered.
return seen is not None and found is not None and found > seen and new != state("skipped")
seen = version(state("seen") or "0")
return seen is not None and version(new) > seen and new != state("skipped")
def desktop():
-17
View File
@@ -1,17 +0,0 @@
# Installed by Steamify CachyOS (SteamOS conversion, NVIDIA fix): decides
# again whether the NVIDIA modules go into the initramfs, after DKMS has built
# its modules (71-dkms-install) and before the initramfs is built
# (90-mkinitcpio-install); hooks run in file name order.
[Trigger]
Operation = Install
Operation = Upgrade
Operation = Remove
Type = Path
Target = usr/lib/modules/*/vmlinuz
Target = usr/lib/modules/*/extramodules/nvidia*
Target = usr/lib/modules/*/updates/*
[Action]
Description = Steamify: NVIDIA modules in the initramfs only if every kernel has them
When = PostTransaction
Exec = @SCRIPT@ sync
-36
View File
@@ -1,36 +0,0 @@
#!/bin/bash
# Installed by Steamify CachyOS (SteamOS conversion, NVIDIA fix), run by the
# pacman hook steamify-nvidia-initramfs.hook before the initramfs is built.
# The NVIDIA modules go into the initramfs (early KMS) only while EVERY
# installed kernel has them: mkinitcpio fails on a module a kernel lacks, and
# limine-mkinitcpio then skips that kernel's boot entry, kernel parameters
# included. Decided again at every kernel or driver change, so a new kernel
# without the modules (another kernel, a failed DKMS build, a downgrade) gets
# a working initramfs and the file comes back once it has them.
# steamify-nvidia-initramfs [sync|check]
# sync (default) write or remove the drop-in to match
# check exit status 0 when every installed kernel has nvidia_drm
conf="${NVIDIA_INITRAMFS_CONF:-/etc/mkinitcpio.conf.d/90-steamify-nvidia.conf}"
mods="${NVIDIA_MODULES_DIR:-/usr/lib/modules}"
everywhere() {
local k found=0
for k in "$mods"/*/; do
[[ -f "$k/vmlinuz" || -f "$k/pkgbase" ]] || continue # an installed kernel, not a leftover folder
find "$k" -name 'nvidia-drm.ko*' -print -quit 2>/dev/null | grep -q . || return 1
found=1
done
[[ $found == 1 ]]
}
case "${1:-sync}" in
check) everywhere ;;
sync)
if everywhere; then
[[ -f "$conf" ]] || { mkdir -p "$(dirname "$conf")" &&
echo 'MODULES+=(nvidia nvidia_modeset nvidia_uvm nvidia_drm)' > "$conf"; }
else
rm -f "$conf"
fi ;;
*) echo "usage: $0 [sync|check]" >&2; exit 2 ;;
esac
-18
View File
@@ -1,18 +0,0 @@
#!/bin/bash
# Installed by Steamify CachyOS: run its newest release.
# pipefail: a failed download must count as a failure, not an empty script.
set -o pipefail
if ! curl -fsSL --max-time 30 "@URL@" | bash; then
echo
echo "Couldn't download or run the wizard. Are you connected to the internet?"
echo
read -rp "Press Enter to close this window... " _
exit 1
fi
# Done: close the window after a countdown (Enter closes it right away).
echo
for (( i = 10; i > 0; i-- )); do
printf '\rClosing this window in %2d seconds (Enter to close now)... ' "$i"
read -rs -t 1 _ && break
done
echo
-6
View File
@@ -1,6 +0,0 @@
# Python: the app (ui/steamify-ui, no .py extension) and patches/*.py.
line-length = 130
target-version = "py312"
[lint]
select = ["E", "F", "W", "B"]
+1 -1
View File
@@ -11,6 +11,6 @@ in the shell code.
|---|---|---|
| `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` |
| `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 |
| `steamify-update-check.service`, `.timer` | `lib/update-notifier.sh` (Update notifications) | The daily and login check for a new release (user units) |
@@ -1,13 +1,13 @@
[Unit]
Description=Steam at login (Steamify, NVIDIA PCs)
Description=Steam Background Autostart for Virtual Keyboard
After=graphical-session.target
PartOf=graphical-session.target
[Service]
Type=simple
# Only in the Plasma desktop session.
# Only in the Plasma desktop session; gamescope-session starts its own Steam.
ExecCondition=/bin/sh -c '[ "$XDG_CURRENT_DESKTOP" = KDE ]'
ExecStart=/usr/bin/steam @ARGS@
ExecStart=/usr/bin/steam -silent
Restart=on-failure
RestartSec=5
+56 -68
View File
@@ -15,39 +15,34 @@
set -uo pipefail
# Release version, see CHANGELOG.md.
VERSION=2.11.1
VERSION=2.9.3
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
for lib in common valve-mirror state packages login-manager single-user steam-desktop steam-machine kernel-pin fremont-poweroff vram-booster hdmi-refresh nvidia controllers cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier first-login menu backend; do
for lib in common state packages login-manager single-user steam-desktop steam-machine fremont-poweroff vram-booster hdmi-refresh cec boot-session vapor-theme steamos-extras bios desktop-shortcut wizard-shortcut steam-game update-notifier first-login menu backend; do
# shellcheck source=/dev/null
source "$SCRIPT_DIR/lib/$lib.sh"
done
require_root_helper
# What this run does, from the first argument:
# --backend ... the graphical app's machine-readable mode
BACKEND=false
[[ "${1:-}" == --backend ]] && BACKEND=true
# --defaults [--options <id>,...] [--boot gamescope|desktop]: apply what the
# menu would preselect (or exactly the listed items), without the menu or
# any prompt (the Steam Machine ISO's first login runs this; sudo must not
# ask)
# --defaults --list what --defaults can set up here, as JSON
# (an installer page is built from it); nothing else on stdout
# --boot gamescope|desktop only change where an installed conversion
# starts, everything else stays as it is (for scripts; no menu)
# --first-login the installer's one-time follow-up
# (none) the menu
MODE=menu
case "${1:-}" in
--backend) MODE=backend ;;
--defaults) MODE=defaults; [[ "${2:-}" == --list ]] && MODE=list ;;
--boot) MODE=boot ;;
--first-login) MODE=first-login ;;
esac
BACKEND=false; [[ "$MODE" == backend ]] && BACKEND=true
# menu would preselect (or exactly the listed items), without the menu or any
# prompt (the Steam Machine ISO's first login runs this; sudo must not ask).
DEFAULTS=false
[[ "${1:-}" == --defaults ]] && DEFAULTS=true
# --defaults --list: what --defaults can set up here, as JSON (an installer
# page is built from it); nothing else on stdout.
LIST=false
[[ "$DEFAULTS" == true && "${2:-}" == --list ]] && LIST=true
# --boot gamescope|desktop: only change where an installed conversion
# starts, everything else stays as it is (for scripts; no menu).
BOOT_ONLY=false
[[ "${1:-}" == --boot ]] && BOOT_ONLY=true
if [[ "$MODE" != backend && "$MODE" != list ]]; then
if [[ "$BACKEND" == false && "$LIST" == false ]]; then
echo -e "${c_bold}Steamify CachyOS${c_reset} v$VERSION"
echo "Turn the SteamOS-style parts on or off. The menu shows what is on now;"
echo "anything you turn off is put back the way it was."
@@ -64,14 +59,6 @@ TARGET_USER="$(id -un)"
migrate_layout
notify_seen
# One exit handler (a second trap would replace it): the cursor the menu hid
# and the run's temp dirs, also when the run stops half way.
on_exit() {
[[ -t 1 ]] && tput cnorm 2>/dev/null
cleanup_tmpdirs
}
trap on_exit EXIT
restart_needed() { [[ -n "${BIOS_NEEDS_RESTART:-}" || "$RESTART_FOR_LOGIN" == true ]]; }
restart_now() {
@@ -131,62 +118,63 @@ quit_prompt() {
return 0
}
report_failed() {
# Exit status for the scripted modes: 1 when a component had problems.
[[ ${#FAILED[@]} -eq 0 ]] || { warn "These had problems (see above): ${FAILED[*]}"; return 1; }
}
# The graphical app (steamify-ui) drives the same components through
# lib/backend.sh instead of the menu.
if [[ "$BACKEND" == true ]]; then
RESTART_FOR_LOGIN=false
shift
backend_main "$@"
exit $?
fi
run_defaults() {
if [[ "${1:-}" == --first-login ]]; then
first_login_run
exit 0
fi
if [[ "$LIST" == true ]]; then
defaults_list
exit 0
fi
if [[ "$DEFAULTS" == true ]]; then
RESTART_FOR_LOGIN=false
REAPPLY=false
sudo -n true 2>/dev/null || { err "--defaults needs sudo without a password."; return 1; }
sudo -n true 2>/dev/null || { err "--defaults needs sudo without a password."; exit 1; }
detect_components
defaults_options "${@:2}" || return 1
defaults_options "${@:2}" || exit 1
plan_changes
apply_changes
# Run by the installer: the rest waits for the first desktop login.
user_session || first_login_schedule
report_failed || return 1
[[ ${#FAILED[@]} -eq 0 ]] || { warn "These had problems (see above): ${FAILED[*]}"; exit 1; }
ok "Done; the changes take effect after a restart."
}
exit 0
fi
run_boot_only() {
local mode="${2:-}" c
if [[ "$BOOT_ONLY" == true ]]; then
RESTART_FOR_LOGIN=false
REAPPLY=false
case "$mode" in
case "${2:-}" in
gamescope|desktop) ;;
*) err "--boot takes gamescope or desktop"; return 1 ;;
*) err "--boot takes gamescope or desktop"; exit 1 ;;
esac
detect_components
is_current gaming || { err "--boot needs the SteamOS conversion; turn it on first."; return 1; }
[[ "${CURRENT[gaming]}" == 1 ]] || { err "--boot needs the SteamOS conversion; turn it on first."; exit 1; }
# What is on stays on, and nothing else changes: not the updates or
# removals a normal run would pick.
for c in "${COMPONENTS[@]}"; do WANTED[$c]=${CURRENT[$c]:-0}; done
WANTED[boot]=0; [[ "$mode" == desktop ]] && WANTED[boot]=1
WANTED[boot]=0; [[ "$2" == desktop ]] && WANTED[boot]=1
plan_changes
if [[ ${#TO_DISABLE[@]} -eq 0 && ${#TO_ENABLE[@]} -eq 0 ]]; then
ok "Already starting in $mode."
return 0
ok "Already starting in $2."
exit 0
fi
apply_changes
report_failed || return 1
ok "Starts in $mode from the next boot on."
}
case "$MODE" in
backend)
# The graphical app (steamify-ui) drives the same components through
# lib/backend.sh instead of the menu.
RESTART_FOR_LOGIN=false
shift
backend_main "$@"
exit $? ;;
first-login) first_login_run; exit 0 ;;
list) defaults_list; exit 0 ;;
defaults) run_defaults "$@"; exit $? ;;
boot) run_boot_only "$@"; exit $? ;;
esac
[[ ${#FAILED[@]} -eq 0 ]] || { warn "These had problems (see above): ${FAILED[*]}"; exit 1; }
ok "Starts in $2 from the next boot on."
exit 0
fi
# Menu loop: after each run the menu comes back with the new state, until
# the user quits; the restart question comes then, once, for everything.
@@ -217,7 +205,7 @@ while true; do
if [[ "$c" == boot ]]; then echo " - boot into: desktop (from the next boot)"
elif is_action "$c"; then echo " - run: ${LABEL[$c]%%:*} at your own risk (checks, then asks twice more)"
elif feature_outdated "$c"; then echo " - update: ${LABEL[$c]} (changed in this version)"
elif is_current "$c"; then echo " - re-apply: ${LABEL[$c]}"
elif [[ "${CURRENT[$c]}" == 1 ]]; then echo " - re-apply: ${LABEL[$c]}"
elif feature_new "$c"; then echo " - turn on: ${LABEL[$c]} (new in this version)"
else echo " - turn on: ${LABEL[$c]}"; fi
done
@@ -242,11 +230,11 @@ while true; do
for c in "${COMPONENTS[@]}"; do
component_available "$c" && ! is_action "$c" || continue
if [[ "$c" == boot ]]; then
is_current gaming && echo " └ boots into: $(boot_mode "${CURRENT[boot]}")"
[[ "${CURRENT[gaming]}" == 1 ]] && echo " └ boots into: $(boot_mode "${CURRENT[boot]}")"
elif [[ -n "${PARENT[$c]:-}" ]]; then
[[ "${CURRENT[${PARENT[$c]}]}" == 1 ]] || continue
if is_current "$c"; then echo -e " └ ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " └ off ${LABEL[$c]}"; fi
elif is_current "$c"; then echo -e " ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " off ${LABEL[$c]}"; fi
if [[ "${CURRENT[$c]}" == 1 ]]; then echo -e " └ ${c_green}on ${c_reset} ${LABEL[$c]}"; else echo " └ off ${LABEL[$c]}"; fi
elif [[ "${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[*]}"
+4 -14
View File
@@ -38,9 +38,7 @@ Item {
readonly property var status: backend.status || ({})
readonly property var items: status.items || []
// 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 rows: items.filter(function (i) { return !i.parent || want[i.parent]; })
readonly property var bios: status.bios || null
signal passwordRequested()
@@ -77,15 +75,8 @@ Item {
var w = Object.assign({}, want);
w[id] = !w[id];
// The same rules as the terminal menu (toggle_component).
var hasGaming = items.some(function (i) { return i.id === "gaming"; });
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 === "nvidia") w.bigpicture = w.nvidia;
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 === "gaming" && !w.gaming) w.single = false;
if (id === "single" && w.single) w.gaming = true;
if (id === "machine") w.poweroff = w.machine;
if (id === "poweroff" && w.poweroff) w.machine = true;
if (id === "machine" && !w.machine) w.kpin = false;
@@ -99,7 +90,6 @@ Item {
for (var i = 0; i < items.length; i++) {
var it = items[i];
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 (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" });
@@ -116,7 +106,7 @@ Item {
function wantedIds() {
var ids = [];
for (var i = 0; i < items.length; i++)
if (items[i].kind === "toggle" && want[items[i].id] && !hidden(items[i]) && (!items[i].parent || want[items[i].parent])) ids.push(items[i].id);
if (items[i].kind === "toggle" && want[items[i].id] && (!items[i].parent || want[items[i].parent])) ids.push(items[i].id);
return ids;
}
+1 -16
View File
@@ -6,22 +6,10 @@ QtObject {
readonly property var items: ({
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.",
changes: ["Autologin into gamescope", "Return to Gaming Mode shortcut"] },
changes: ["Autologin into gamescope", "Return to Gaming Mode shortcut", "Steam starts silently on the desktop"] },
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.",
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",
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"] },
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.",
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",
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"] },
@@ -39,9 +27,6 @@ QtObject {
notify: { label: "Update notifications", hint: "A notification when there's a new Steamify",
body: "Checks once a day and when you log in to the desktop. When there's a new Steamify you get a notification and a tray icon: open the app to see what's new and choose what to update, or skip that version. It never updates anything by itself.",
changes: ["A daily check (systemd user timer), only on the desktop", "Tray icon only while an update is waiting", "Skip this version: quiet until the next one"] },
extended_controller_support: { label: "Extended controller support", hint: "Xbox wireless dongle, Xbox controllers over Bluetooth",
body: "Drivers for Xbox controllers that Linux doesn't handle well by itself. xone makes the Xbox wireless dongle work (the kernel has no driver for it), xpadneo gives an Xbox controller over Bluetooth rumble including the triggers, the right button mapping and its battery level. They are built for every installed kernel, which takes a minute or two each.",
changes: ["xone (the dongle) with its firmware, and xpadneo (Bluetooth), from the CachyOS repo", "Kernel headers for every installed kernel, so the drivers build for each", "Off: only what Steamify installed is removed again"] },
vram: { label: "VRAM booster", hint: "The game in front keeps its VRAM",
body: "Like SteamOS 3.9: the game you're playing keeps its video memory, and background apps are moved out first. Without it a game that needs most of the video memory can spill into system RAM and stutter. Shown for GPUs whose driver supports it (AMD, Intel, NVIDIA with its open kernel modules from driver 615) on kernel 7.2 or newer.",
changes: ["dmemcg-booster (system and user service)", "plasma-foreground-booster, which tells it which window is in front", "Off: removed again, unless you had installed them yourself"] },