mirror of
https://github.com/theupriser/steamify-cachyos.git
synced 2026-10-03 17:41:58 +02:00
Compare commits
149
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c96bed448 | ||
|
|
e3f7cc9773 | ||
|
|
353de489d7 | ||
|
|
d8b2e812c5 | ||
|
|
3a0692fdf2 | ||
|
|
e86ddcc4af | ||
|
|
389bc3346e | ||
|
|
c6c1150836 | ||
|
|
98e2effcff | ||
|
|
431515b60f | ||
|
|
34c9cfdb32 | ||
|
|
8ddb7ebf3d | ||
|
|
32c33e4abf | ||
|
|
2dd0f3ac47 | ||
|
|
57995bcd1f | ||
|
|
d57e8d8448 | ||
|
|
5a34633986 | ||
|
|
479b70b337 | ||
|
|
2e0881b4fa | ||
|
|
cce31e19c2 | ||
|
|
bd4fa3a6f4 | ||
|
|
8ffa0f2449 | ||
|
|
8a2601d73d | ||
|
|
572417bd7b | ||
|
|
cf73229756 | ||
|
|
febdab5b53 | ||
|
|
90cdfd6666 | ||
|
|
6f598d18fd | ||
|
|
9bbe5fa602 | ||
|
|
ceeb949e6b | ||
|
|
03a8b8c4ba | ||
|
|
e699a3f8eb | ||
|
|
7bef834b16 | ||
|
|
86b9744227 | ||
|
|
b0947d7a2f | ||
|
|
3f97c85c3c | ||
|
|
fd162c1e2e | ||
|
|
54ebddfe98 | ||
|
|
fe93dd3e67 | ||
|
|
ef585c0db1 | ||
|
|
32795bd5a5 | ||
|
|
3c8ca65902 | ||
|
|
11a91ef85c | ||
|
|
163f7908c4 | ||
|
|
e121b06fd8 | ||
|
|
19ca966913 | ||
|
|
56fb9080a7 | ||
|
|
6df19eba3e | ||
|
|
7694c97d68 | ||
|
|
a5e644d71a | ||
|
|
929ecfb349 | ||
|
|
4cc87aaea6 | ||
|
|
36d0a9d780 | ||
|
|
cb6361b49b | ||
|
|
c510f9e2e5 | ||
|
|
05a7d50c3f | ||
|
|
badfd846d8 | ||
|
|
ff364ffd69 | ||
|
|
2b3f1de75a | ||
|
|
6d7d5861d6 | ||
|
|
444ce29e57 | ||
|
|
23ef5ef7ab | ||
|
|
178ee3405e | ||
|
|
601c05329d | ||
|
|
8ae9673eb2 | ||
|
|
dbafc43f2e | ||
|
|
ae8ed85fee | ||
|
|
00bcaea712 | ||
|
|
a898d23b13 | ||
|
|
3e53257fe2 | ||
|
|
a1eab9ac79 | ||
|
|
c9c16b9eec | ||
|
|
b17addd60f | ||
|
|
ac613f05b3 | ||
|
|
3a0eefab11 | ||
|
|
96558a9ca8 | ||
|
|
7c48b3d806 | ||
|
|
396459b511 | ||
|
|
43a9541104 | ||
|
|
e09fe1609b | ||
|
|
9dcac5cf08 | ||
|
|
f91dd1f0b1 | ||
|
|
0411429654 | ||
|
|
1aa5e955fe | ||
|
|
ce75e895c4 | ||
|
|
9aef0a986a | ||
|
|
f7aa2412df | ||
|
|
87162efaa2 | ||
|
|
c79a3bbda5 | ||
|
|
ba11f58d9e | ||
|
|
45ff036f09 | ||
|
|
de02f267f4 | ||
|
|
0f123004d0 | ||
|
|
3048b35dd8 | ||
|
|
f7837f82b9 | ||
|
|
3eb41eef5a | ||
|
|
41422e5bb4 | ||
|
|
6c2e203563 | ||
|
|
1522e5632d | ||
|
|
1d994ae359 | ||
|
|
700f3e514b | ||
|
|
d78652c862 | ||
|
|
727e6a2302 | ||
|
|
c4bd1ca39c | ||
|
|
a449a9e467 | ||
|
|
388b1286c9 | ||
|
|
508f22acaf | ||
|
|
3f8e0372d1 | ||
|
|
bd90e29e7a | ||
|
|
4895de3a46 | ||
|
|
0f503dd112 | ||
|
|
d7cf0c0491 | ||
|
|
5ab83d6e6f | ||
|
|
2e107e537e | ||
|
|
986b3c8c07 | ||
|
|
afc05b0b23 | ||
|
|
b0553aecf7 | ||
|
|
69a420b8aa | ||
|
|
1c34a97598 | ||
|
|
be874b8594 | ||
|
|
f01aa93d0e | ||
|
|
852205317a | ||
|
|
77b94c29a2 | ||
|
|
c0014ee623 | ||
|
|
d39731a8b9 | ||
|
|
99a95abf1f | ||
|
|
429e840a9f | ||
|
|
45a8757f58 | ||
|
|
54fc9e362b | ||
|
|
b70c9d614f | ||
|
|
40c9ee638b | ||
|
|
2f9b2a54e1 | ||
|
|
53f53a77ff | ||
|
|
6afef78721 | ||
|
|
1604ed10d4 | ||
|
|
8aab946c6f | ||
|
|
5cbe0079cb | ||
|
|
5c00504261 | ||
|
|
d7231ebbd8 | ||
|
|
eb3169efa1 | ||
|
|
10b51644c9 | ||
|
|
7802d90186 | ||
|
|
978f5a14cf | ||
|
|
a501df25b5 | ||
|
|
079c48f6fe | ||
|
|
ee5391c126 | ||
|
|
e741246098 | ||
|
|
9827bea8d5 | ||
|
|
dcc184ed39 |
No files matched your search
@@ -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
|
||||
+23
-112
@@ -5,16 +5,18 @@
|
||||
# release are moved to it, so both of these always get the newest version:
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/download/steamify.sh | bash
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/download/latest/steamify.sh | bash
|
||||
# Each release also has the app: steamify-app.tar.gz (ui/, steamify.sh,
|
||||
# Each release also has the app (v2): steamify-app.tar.gz (ui/, steamify.sh,
|
||||
# lib/, patches/, services/, the icon) and its launcher, run with:
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/download/steamify-app.sh | bash
|
||||
# Pushes to release/** build and check it like pull requests; only main publishes.
|
||||
# A push to feat/v2-ui (the app, not released yet) updates the pre-release
|
||||
# v2-ui-preview instead, whose launcher gets that build:
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/download/v2-ui-preview/steamify-app.sh | bash
|
||||
# Pull requests only build and check it, and warn when VERSION is already released.
|
||||
name: Single-file build
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main, 'release/**']
|
||||
branches: [main, feat/v2-ui]
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
|
||||
@@ -40,39 +42,12 @@ 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
|
||||
|
||||
# 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).
|
||||
- name: shellcheck the bundle
|
||||
uses: ludeeus/action-shellcheck@2.0.0
|
||||
env:
|
||||
# SC2034/SC2154: variables used across the inlined modules.
|
||||
SHELLCHECK_OPTS: -e SC2034 -e SC2154
|
||||
with:
|
||||
severity: warning
|
||||
scandir: dist
|
||||
ignore_names: steamify-app.sh
|
||||
- name: shellcheck the app launcher
|
||||
uses: ludeeus/action-shellcheck@2.0.0
|
||||
with:
|
||||
severity: warning
|
||||
scandir: dist
|
||||
ignore_names: steamify.sh
|
||||
shellcheck -S warning -e SC2034,SC2154 dist/steamify.sh
|
||||
shellcheck -S warning dist/steamify-app.sh
|
||||
python3 -m py_compile ui/steamify-ui
|
||||
|
||||
# The build as an artifact on GitHub and on the mirror (Gitea); releases stay GitHub's.
|
||||
# Gitea's artifact server doesn't speak upload-artifact@v4's protocol, and GitHub fails a workflow
|
||||
# that merely mentions the deprecated @v3: Gitea gets christopherhx's fork of v4 for Gitea.
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: github.server_url == 'https://github.com'
|
||||
with:
|
||||
name: steamify
|
||||
path: |
|
||||
dist/steamify.sh
|
||||
dist/steamify-app.tar.gz
|
||||
dist/steamify-app.sh
|
||||
- uses: christopherhx/gitea-upload-artifact@v4
|
||||
if: github.server_url != 'https://github.com'
|
||||
with:
|
||||
name: steamify
|
||||
path: |
|
||||
@@ -82,7 +57,6 @@ jobs:
|
||||
|
||||
- name: Version
|
||||
id: version
|
||||
if: github.server_url == 'https://github.com'
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
@@ -97,7 +71,6 @@ jobs:
|
||||
|
||||
- name: Publish the v${{ steps.version.outputs.version }} release
|
||||
if: >-
|
||||
github.server_url == 'https://github.com' &&
|
||||
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
|
||||
steps.version.outputs.released == 'false'
|
||||
env:
|
||||
@@ -134,84 +107,22 @@ jobs:
|
||||
fi
|
||||
gh release upload latest dist/steamify.sh dist/steamify-app.sh dist/steamify-app.tar.gz assets/steam-gaming-settings.svg --clobber
|
||||
|
||||
# The mirror (Gitea) publishes its own release per version too, the same way: never overwrites one,
|
||||
# notes from the changelog. gh can't talk to Gitea: its API for the check, a Gitea release action to
|
||||
# publish. The token is the run's own (repository write); a secret RELEASE_TOKEN overrides it.
|
||||
- name: Version (mirror)
|
||||
id: mirror_version
|
||||
if: github.server_url != 'https://github.com'
|
||||
- name: Publish the v2-ui-preview pre-release
|
||||
if: github.event_name == 'push' && github.ref == 'refs/heads/feat/v2-ui'
|
||||
env:
|
||||
TOKEN: ${{ secrets.RELEASE_TOKEN || github.token }}
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: |
|
||||
version="$(grep -oP '^VERSION=\K.*' steamify.sh)"
|
||||
echo "version=$version" >> "$GITHUB_OUTPUT"
|
||||
if curl -fsS -o /dev/null -H "Authorization: token $TOKEN" \
|
||||
"${{ github.server_url }}/api/v1/repos/${{ github.repository }}/releases/tags/v$version"; then
|
||||
echo "released=true" >> "$GITHUB_OUTPUT"
|
||||
echo "::warning::v$version is already released on this server and won't be overwritten."
|
||||
# Its launcher downloads this pre-release, not the newest release.
|
||||
sed -i 's/STEAMIFY_RELEASE:-latest/STEAMIFY_RELEASE:-v2-ui-preview/' dist/steamify-app.sh
|
||||
grep -q 'STEAMIFY_RELEASE:-v2-ui-preview' dist/steamify-app.sh
|
||||
git tag -f v2-ui-preview "$GITHUB_SHA" && git push -f origin v2-ui-preview
|
||||
notes="Preview of the Steamify app (v2) from feat/v2-ui ($(git describe --always), $(git log -1 --format='%cs %s')). Not a release.
|
||||
Run it with:
|
||||
|
||||
curl -fsSL https://github.com/${{ github.repository }}/releases/download/v2-ui-preview/steamify-app.sh | bash"
|
||||
if gh release view v2-ui-preview >/dev/null 2>&1; then
|
||||
gh release edit v2-ui-preview --title "Steamify app (v2) preview" --notes "$notes" --prerelease --latest=false
|
||||
else
|
||||
echo "released=false" >> "$GITHUB_OUTPUT"
|
||||
gh release create v2-ui-preview --target "$GITHUB_SHA" --title "Steamify app (v2) preview" --notes "$notes" --prerelease --latest=false
|
||||
fi
|
||||
|
||||
- name: Release notes (mirror)
|
||||
if: >-
|
||||
github.server_url != 'https://github.com' &&
|
||||
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
|
||||
steps.mirror_version.outputs.released == 'false'
|
||||
env:
|
||||
VERSION: ${{ steps.mirror_version.outputs.version }}
|
||||
run: |
|
||||
changes="$(awk -v v="$VERSION" '
|
||||
$0 ~ "^## " { if (found) exit; if (index($0, "## " v " ") == 1) { found = 1; next } }
|
||||
found' CHANGELOG.md)"
|
||||
cat > dist/release-notes.md <<NOTES
|
||||
Single-file build of v$VERSION ($(git describe --always), $(git log -1 --format=%cs)).
|
||||
Run this version with:
|
||||
|
||||
curl -fsSL ${{ github.server_url }}/${{ github.repository }}/releases/download/v$VERSION/steamify.sh | bash
|
||||
|
||||
## Changes in v$VERSION
|
||||
$changes
|
||||
NOTES
|
||||
|
||||
- name: Publish the v${{ steps.mirror_version.outputs.version }} release (mirror)
|
||||
if: >-
|
||||
github.server_url != 'https://github.com' &&
|
||||
github.event_name != 'pull_request' && github.ref == 'refs/heads/main' &&
|
||||
steps.mirror_version.outputs.released == 'false'
|
||||
uses: akkuman/gitea-release-action@v1.3.7
|
||||
with:
|
||||
token: ${{ secrets.RELEASE_TOKEN || github.token }}
|
||||
tag_name: v${{ steps.mirror_version.outputs.version }}
|
||||
target_commitish: ${{ github.sha }}
|
||||
name: Steamify CachyOS v${{ steps.mirror_version.outputs.version }}
|
||||
body_path: dist/release-notes.md
|
||||
files: |
|
||||
dist/steamify.sh
|
||||
dist/steamify-app.sh
|
||||
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.
|
||||
- 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/')) &&
|
||||
steps.version.outputs.released == 'false'
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.ISO_DISPATCH_TOKEN }}
|
||||
run: |
|
||||
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 release upload v2-ui-preview dist/steamify-app.sh dist/steamify-app.tar.gz --clobber
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -1,2 +0,0 @@
|
||||
# The modules share variables across files once bundled (see AGENTS.md).
|
||||
disable=SC2034,SC2154
|
||||
@@ -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.
|
||||
@@ -122,56 +98,15 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
+ subject; a commit can't contain its own hash, so fill it in with the
|
||||
next commit). The section heading must be `## <VERSION> - <date>`: CI
|
||||
cuts the release notes out of the changelog by that heading.
|
||||
- **Branches: one release branch per version.** Work for a release goes
|
||||
into `release/X.Y.Z` (e.g. `release/2.7.0`), branched from `main` when
|
||||
that version starts. That branch bumps `VERSION` to `X.Y.Z` and adds the
|
||||
`## X.Y.Z - <date>` changelog section (first commit on it).
|
||||
- Every change gets its own branch from the release branch:
|
||||
`feature/<name>` (new behaviour) or `bugfix/<name>` (a fix), and a
|
||||
pull request **into the release branch**, not into `main`. Its commits
|
||||
add their changelog lines to that version's section.
|
||||
- When the release is done and tested (the test plan in
|
||||
steamify-cachyos-dev, `TESTPLAN.md`), the release branch gets a pull
|
||||
request **into `main`**. Merging it publishes the release (below).
|
||||
- A fix for a released version: a new `release/X.Y.Z+1` from `main`,
|
||||
with the `bugfix/` branch into it; don't reopen an old release branch.
|
||||
- Up to the release branch, the agent manages it: create the
|
||||
`feature/`/`bugfix/` branches, commit, push, and merge them into the
|
||||
release branch itself once tested (with `gh`: `gh pr create --base
|
||||
release/X.Y.Z` + `gh pr merge --merge`; no review needed). Without
|
||||
`gh` (`command -v gh`), ask the user to install it (Ubuntu:
|
||||
`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.
|
||||
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.
|
||||
- A push to `main` publishes release `v$VERSION` (tag + bundle + that
|
||||
- Every PR that should be released bumps `VERSION` and adds its section.
|
||||
A push to `main` publishes release `v$VERSION` (tag + bundle + that
|
||||
changelog section) and marks it latest. An existing version is never
|
||||
overwritten: without a bump nothing is released, and pull requests show
|
||||
a warning when `VERSION` is a version that's already released (so a
|
||||
release branch that forgot its bump shows it on every PR).
|
||||
a warning.
|
||||
- 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 +227,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
|
||||
@@ -339,38 +269,6 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine
|
||||
latter only starts with `kcgroupsrc [Foreground Booster] autostart=true`
|
||||
(set with `kset`). Disable removes only the packages it installed
|
||||
(`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))
|
||||
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,
|
||||
via `--root=/`), and the theme, when the layout is still `/etc/skel`'s,
|
||||
removes it so Plasma builds Vapor's layout at the first login. What needs
|
||||
that layout (single user's launcher) runs then, from a one-time autostart
|
||||
(`lib/first-login.sh`, `--first-login`) that also opens the app.
|
||||
`--options <id>,...` (exactly these on, the rest off; an item on brings its
|
||||
parent) and `--boot gamescope|desktop` (desktop only with `gaming`) (2.7.0,
|
||||
`defaults_options` in `lib/menu.sh`); the ISO's installer page passes them.
|
||||
Items this PC can't use are left off with a warning, not an error.
|
||||
`steamify.sh --boot gamescope|desktop` on its own (2.7.0, for scripts) only
|
||||
switches `boot` on an installed conversion: `WANTED` is `CURRENT` plus
|
||||
that, so no updates or removals a normal run would pick.
|
||||
- What Steam's System settings show (SteamOS conversion, 2.9.0): the OS name
|
||||
stays CachyOS's everywhere (legal clarity; Steam's OS Name is
|
||||
`lsb_release -d`, not touched). `/etc/os-release` gets `VERSION_ID=steamos-X.Y`
|
||||
(Steam's OS Version: Valve's newest jupiter repo; offline, the previous
|
||||
value), `VERSION_CODENAME=steam-machine`, `VARIANT="Steamify <version>"` and
|
||||
`VARIANT_ID=steamify-<version>` (Steam shows VARIANT_ID as OS Variant),
|
||||
refreshed by `os_version_refresh` after every run that changes something; a
|
||||
pacman hook (`zz-steamify-os-release`) runs after cachyos-hooks. KDE's About
|
||||
this System would show VERSION_ID after the name: `kcm-about-distrorc`
|
||||
`UseOSReleaseVersion=true` (kset) makes it show os-release's VERSION, which
|
||||
CachyOS doesn't have. Never `NAME` or `PRETTY_NAME`: limine-snapper-sync
|
||||
finds the boot entries by the OS name ("Target OS name ... not found in
|
||||
/boot/limine.conf"); `/etc/default/limine` gets `TARGET_OS_NAME="CachyOS"`
|
||||
when it has none, as a guard. The serial number (tmpfiles rule) is Steam
|
||||
Machine support's, so Fremont only.
|
||||
- `Relogin=true` means a gamescope that fails to start is relaunched in a
|
||||
tight loop; keep that in mind when changing session handling.
|
||||
|
||||
|
||||
+1
-113
@@ -5,121 +5,9 @@ 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)**
|
||||
- `cfe3ce7` **chore: Version 2.9.3**
|
||||
|
||||
## 2.9.2 - 2026-09-29
|
||||
|
||||
- **feat(ci): a Gitea mirror publishes its own release per version (akkuman/gitea-release-action; never overwrites one, notes from the changelog, links to the mirror)**
|
||||
- **fix(ci): the build also runs on a Gitea mirror (act_runner): shellcheck through ludeeus/action-shellcheck, which brings its own binary; the artifact goes up there with christopherhx/gitea-upload-artifact (GitHub refuses a workflow that mentions the deprecated upload-artifact@v3); releases are only published on GitHub**
|
||||
- `fe4f3f4` **chore: Version 2.9.2**
|
||||
|
||||
## 2.9.1 - 2026-09-29
|
||||
|
||||
- `c87e6c7` **docs: changelog for the CEC driver cache**
|
||||
- `fc05725` **fix: HDMI-CEC: an older cached CEC driver is removed when a new pin is downloaded**
|
||||
- `90bc5e4` **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); turning CEC on again needs no network**
|
||||
- `d99ff65` **chore: Version 2.9.1**
|
||||
|
||||
## 2.9.0 - 2026-09-28
|
||||
|
||||
- `d30d505` **chore: Version 2.9.0**
|
||||
- `66ea63c` **docs: KDE Plasma only: other desktops and display managers "are not supported" (README, was "don't work yet")**
|
||||
- `9b86cd1` **docs: KDE Plasma only: other desktops don't work yet (README)**
|
||||
- `d73e71d` **docs: README, TECHNICAL and TROUBLESHOOTING for 2.9.0: Steam's System settings, serial number and Wi-Fi backend, --defaults --list, the Steamify ISO**
|
||||
- `a72d848` **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)**
|
||||
- `27a4070` **fix: Steam's OS Variant shows Steamify's version (VARIANT_ID=steamify-2.9.0; Steam shows VARIANT_ID, not VARIANT)**
|
||||
- `44bfe07` **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")**
|
||||
- `435f69c` **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)**
|
||||
- `ce71b34` **feat: Steam's System settings and About this System like on SteamOS: OS name "CachyOS with Steamify" (lsb-release, kept through CachyOS updates by a pacman hook), Steamify as OS variant and version (os-release VARIANT/VERSION_ID; NAME/PRETTY_NAME stay CachyOS's for limine, TARGET_OS_NAME pinned), "CachyOS Linux with Steamify" in About this System; on a Steam Machine the serial number and Steam's Wi-Fi backend setting (existing installs get it as an update)**
|
||||
- `07a94cd` **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)**
|
||||
|
||||
## 2.8.0 - 2026-09-28
|
||||
|
||||
- **chore: Version 2.8.0**
|
||||
- **feat: steamify.sh --defaults --list: what --defaults can set up here, as JSON, for an installer page**
|
||||
|
||||
## 2.7.0 - 2026-09-28
|
||||
|
||||
- `4f6e6fd` **feat: --defaults takes --skip <ids> and --boot gamescope|desktop, for the Steam Machine ISO's installer pages**
|
||||
- `5bf9da4` **fix: HDMI-CEC enables cec-audio-control.socket (the TV remote's volume keys); existing installs get it as an update**
|
||||
- `14aa7c0` **fix: the app's progress screen says "Boot into desktop", not "Boot into Boot into"**
|
||||
- `c4ec755` **feat: --defaults --options <ids> (exactly these on) replaces --skip; steamify.sh --boot gamescope|desktop on its own switches where an installed conversion starts**
|
||||
- `eadbdda` **docs: release branches (release/X.Y.Z, feature/ and bugfix/ branches into it, the release into main); CI builds release/** pushes**
|
||||
- `bee18b7` **docs: the agent merges feature/bugfix branches into the release branch; the release into main stays the user's**
|
||||
- `501c0ba` **docs: gh or git for merging into the release branch**
|
||||
- `b1adacb` **docs: gh is required for the release-branch pull requests; ask the user to install it**
|
||||
- `ced4a45` **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**
|
||||
- **fix: turning the theme off no longer brings back single user's launcher restriction when single user was turned off in between**
|
||||
|
||||
## 2.6.0 - 2026-09-27
|
||||
|
||||
- `b948c20` **feat: --defaults applies the default setup without the menu, also from an installer (no session): the base for a Steam Machine ISO**
|
||||
|
||||
## 2.5.2 - 2026-09-27
|
||||
|
||||
- `0c96bed` **docs: README screenshot at 2.5.2: everything on, nothing to update**
|
||||
- **docs: README screenshot at 2.5.2: everything on, nothing to update**
|
||||
|
||||
## 2.5.1 - 2026-09-27
|
||||
|
||||
|
||||
@@ -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"
|
||||
@@ -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 |
|
||||
|---|---|
|
||||
|  |  |
|
||||

|
||||
|
||||
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,10 @@ 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 +33,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 +52,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
|
||||
|
||||
@@ -89,8 +62,7 @@ What Steamify can do on a Valve Steam Machine:
|
||||
([details](TECHNICAL.md#hdmi-cec)).
|
||||
- **Steam Machine support** - the front **LED bar** works, Steam's
|
||||
**hardware settings** (fan, performance) work, and the power button puts
|
||||
it to sleep like a console. Steam's System settings show the serial
|
||||
number, and Steam's **Wi-Fi backend** setting works.
|
||||
it to sleep like a console.
|
||||
- **Power-off fix** - on by default: shutting down really turns the Steam
|
||||
Machine off, also with the newest CachyOS kernel
|
||||
([details](TECHNICAL.md#power-off-fix-steam-machine)).
|
||||
@@ -101,11 +73,6 @@ What Steamify can do on a Valve Steam Machine:
|
||||
## Requirements
|
||||
|
||||
- CachyOS with the KDE Plasma desktop (the default CachyOS Desktop edition)
|
||||
|
||||
> **KDE Plasma only.** Steamify works with KDE Plasma and its login managers
|
||||
> (plasma-login-manager or SDDM). Other desktops (GNOME, Hyprland, Cosmic,
|
||||
> ...) and other display managers are not supported: the switching between gaming mode
|
||||
> and the desktop, the theme and the shortcuts are all built for Plasma.
|
||||
- Your normal user account, with permission to use `sudo`
|
||||
|
||||
## Installation
|
||||
@@ -116,11 +83,6 @@ Open **Konsole** on your Plasma desktop and run:
|
||||
curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/download/steamify.sh | bash
|
||||
```
|
||||
|
||||
Installing CachyOS on a Steam Machine? The
|
||||
[Steamify CachyOS ISO](https://github.com/theupriser/steamify-cachyos-live-iso)
|
||||
has Steamify built into the installer: pick the options there, and the
|
||||
first boot is already set up.
|
||||
|
||||
Prefer to look at the script first? Clone the repository and run
|
||||
[`./steamify.sh`](steamify.sh) (keep the whole folder: it needs
|
||||
[`lib/`](lib/)).
|
||||
@@ -163,14 +125,6 @@ steamos-session-select persistent # start where you left off last time
|
||||
steamos-session-select oneshot # always start in gaming mode (default)
|
||||
```
|
||||
|
||||
Where the PC starts after a restart can also be set from a script, once the
|
||||
SteamOS conversion is on (only that changes; `sudo` may ask for your password):
|
||||
|
||||
```bash
|
||||
steamify.sh --boot desktop # start in the desktop from the next boot on
|
||||
steamify.sh --boot gamescope # start in gaming mode again (default)
|
||||
```
|
||||
|
||||
## Something wrong?
|
||||
|
||||
Stuck on a black screen in gaming mode: press **Ctrl+Alt+F3**, log in, and run
|
||||
@@ -187,51 +141,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
|
||||
|
||||
+10
-138
@@ -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.
|
||||
@@ -121,13 +111,9 @@ Turning it off restores `/etc/plasmalogin.conf` from its backup, removes the
|
||||
SDDM autologin, sync bridge, shortcut, sudoers rule and Steam autostart, and
|
||||
switches back to plasma-login-manager.
|
||||
|
||||
The conversion also sets what Steam's System settings show, see
|
||||
[below](#what-steams-system-settings-show).
|
||||
|
||||
**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
|
||||
|
||||
@@ -153,33 +139,6 @@ taken from the newest `steamdeck-kde-presets` on Valve's SteamOS mirror
|
||||
Turning it off restores your previous look and panel layout, and removes `cachyos-vapor` again
|
||||
if the wizard installed it (and nothing else, like `cachyos-handheld`, needs it).
|
||||
|
||||
## What Steam's System settings show
|
||||
|
||||
With the SteamOS conversion on, `/etc/os-release` gets:
|
||||
|
||||
| Key | Value | Shown in Steam as |
|
||||
|---|---|---|
|
||||
| `VERSION_ID` | `steamos-3.9`: the newest SteamOS release in Valve's repo (offline: the previous value) | OS Version |
|
||||
| `VERSION_CODENAME` | `steam-machine` | OS Codename |
|
||||
| `VARIANT` / `VARIANT_ID` | `Steamify 2.9.0` / `steamify-2.9.0` | OS Variant (`VARIANT_ID`) |
|
||||
|
||||
The OS name stays CachyOS everywhere: Steam's OS Name comes from
|
||||
`lsb_release -d`, which isn't touched, and `NAME`/`PRETTY_NAME` stay
|
||||
CachyOS's. limine-snapper-sync finds the boot entries by that name, so
|
||||
changing it would break snapshot boot entries; `/etc/default/limine` gets
|
||||
`TARGET_OS_NAME="CachyOS"` as a guard when it has none.
|
||||
|
||||
KDE's About this System would show `VERSION_ID` after the name
|
||||
("CachyOS Linux steamos-3.9"); `UseOSReleaseVersion=true` in
|
||||
`~/.config/kcm-about-distrorc` makes it show `VERSION`, which CachyOS doesn't
|
||||
have, so it keeps saying "CachyOS Linux".
|
||||
|
||||
CachyOS's own hooks (`cachyos-hooks`) reset os-release on updates of
|
||||
`filesystem`; the pacman hook `zz-steamify-os-release` runs after them and
|
||||
sets the keys again (`/usr/local/libexec/steamify-os-release`). The values are
|
||||
refreshed after every Steamify run that changes something. Turning the
|
||||
conversion off removes the hook and runs CachyOS's `cachyos-branding` again.
|
||||
|
||||
## Front LED bar (Steam Machine)
|
||||
|
||||
The **Steam Machine support** component, only shown on Fremont hardware
|
||||
@@ -197,14 +156,7 @@ The **Steam Machine support** component, only shown on Fremont hardware
|
||||
- installs and enables `steamos-manager`, the service Steam in gaming mode
|
||||
uses for hardware settings (fan, performance, and the HDMI-CEC settings
|
||||
when [HDMI-CEC](#hdmi-cec) is on); it recognises the Steam Machine from its
|
||||
DMI data;
|
||||
- makes the serial number readable for Steam, which shows it in its System
|
||||
settings (`/etc/tmpfiles.d/steamify-serial.conf`: `product_serial` is
|
||||
root-only by default);
|
||||
- makes Steam's Wi-Fi backend setting work: steamos-manager switches it in
|
||||
`/etc/NetworkManager/conf.d/99-valve-wifi-backend.conf`, which is created
|
||||
with `wifi.backend=wpa_supplicant` (NetworkManager's default) when no
|
||||
backend is set anywhere yet.
|
||||
DMI data.
|
||||
|
||||
Turning it off removes all of that again (the AUR helper is kept).
|
||||
|
||||
@@ -217,54 +169,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
|
||||
@@ -276,9 +180,7 @@ SHA-256 in Valve's package index:
|
||||
- `cecd`, Valve's CEC daemon (a user service started with the desktop and
|
||||
gaming mode): TV remote keys become normal key presses (arrows, Enter,
|
||||
Back), and it turns the TV on and off with the PC;
|
||||
- `cec-audio-control`: volume of the TV or receiver (the TV remote's volume
|
||||
keys); its user socket is enabled by Steamify, since SteamOS enables it
|
||||
through a preset that pacman doesn't apply;
|
||||
- `cec-audio-control`: volume of the TV or receiver;
|
||||
- `inputattach-cec-units` (with `linuxconsole` from CachyOS for
|
||||
`inputattach`): attaches USB CEC adapters (Pulse-Eight, RainShadow).
|
||||
|
||||
@@ -347,7 +249,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 +395,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
|
||||
@@ -516,33 +418,6 @@ steamos-session-select persistent # remember the last-used session across reboo
|
||||
steamos-session-select oneshot # always start in gamescope (default, like a Deck)
|
||||
```
|
||||
|
||||
`steamify.sh --boot gamescope|desktop` sets where the PC starts after a
|
||||
restart (the menu's Boot into row) from a script: it needs the SteamOS
|
||||
conversion and changes nothing else, not even the updates a normal run would
|
||||
apply. Exit code 1 without the conversion or with another value.
|
||||
|
||||
## Install-time mode (`--defaults`)
|
||||
|
||||
For an installer (the Steam Machine ISO), without a session or prompts
|
||||
(passwordless sudo required):
|
||||
|
||||
```bash
|
||||
steamify.sh --defaults # what the menu would preselect
|
||||
steamify.sh --defaults --options gaming,theme,cec,machine --boot desktop
|
||||
steamify.sh --defaults --list # what --defaults can set up here, as JSON
|
||||
```
|
||||
|
||||
`--options` turns on exactly the listed items (the menu's ids: `gaming`,
|
||||
`theme`, `glyphs`, `single`, `launcher`, `notify`, `vram`, `cec`, `machine`,
|
||||
`poweroff`), everything else off; an item that's on brings its parent
|
||||
(single user the conversion, the power-off fix Steam Machine support). An
|
||||
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`).
|
||||
|
||||
With `Relogin=true`, a gamescope session that fails to start is restarted
|
||||
immediately, which can turn into a loop - see
|
||||
[TROUBLESHOOTING.md](TROUBLESHOOTING.md) for the way out.
|
||||
@@ -570,14 +445,11 @@ immediately, which can turn into a loop - see
|
||||
| `lib/fremont-poweroff.sh` | Steam Machine support: the power-off fix (DKMS module from `patches/`) |
|
||||
| `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
|
||||
|
||||
@@ -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:
|
||||
@@ -25,14 +18,6 @@ restarted right away (`Relogin=true`), which is why it can loop.
|
||||
Run the wizard again and press `a` in the menu to re-apply everything that's
|
||||
on (also useful after a CachyOS update). To undo a part, untick it.
|
||||
|
||||
## "Target OS name ... not found in /boot/limine.conf"
|
||||
|
||||
limine-snapper-sync finds the boot entries by the OS name. Steamify never
|
||||
changes that name (it only adds version keys to `/etc/os-release`), and pins
|
||||
`TARGET_OS_NAME="CachyOS"` in `/etc/default/limine`. If you see this message,
|
||||
check that `PRETTY_NAME` in `/etc/os-release` still says `CachyOS`, or set
|
||||
`TARGET_OS_NAME` in `/etc/default/limine` to the name your boot entries use.
|
||||
|
||||
## The LED bar on the Steam Machine stays dark
|
||||
|
||||
Restart once more; a freshly installed driver often needs a reboot. The menu
|
||||
|
||||
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
-28
@@ -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
|
||||
@@ -182,7 +177,6 @@ backend_apply() {
|
||||
if backend_run_component "$c" enable; then is_action "$c" || feature_record "$c" enable; else failed+=("$c"); fi
|
||||
done
|
||||
feature_record_unticked
|
||||
os_version_refresh
|
||||
[[ " ${TO_DISABLE[*]} ${TO_ENABLE[*]} " =~ \ (gaming|single|boot|kpin)\ ]] && RESTART_FOR_LOGIN=true
|
||||
backend_event finished "\"failed\":$(json_list "${failed[@]}"),\"restart\":$(restart_needed && echo true || echo false)"
|
||||
}
|
||||
|
||||
+7
-7
@@ -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
@@ -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.
|
||||
|
||||
+46
-44
@@ -26,10 +26,6 @@ CEC_DKMS_VER=1
|
||||
CEC_DKMS_SRC="/usr/src/$CEC_DKMS_NAME-$CEC_DKMS_VER"
|
||||
CEC_DRIVER_URL="https://raw.githubusercontent.com/evlaV/linux-integration/10c8c8800ccd3ae359203b4eefb6479f613b3b8e/drivers/media/cec/platform/cros-ec/cros-ec-cec.c"
|
||||
CEC_DRIVER_SHA256=e89fd4e87fceb32d713ffc59b64794779b3c2b3c012b0e2f2e9f0c40b42f4373
|
||||
# Downloaded once, then kept: raw.githubusercontent.com rate-limits (HTTP 429) repeated downloads
|
||||
# from one address, and turning CEC off and on again needs no network then. Named after its
|
||||
# checksum, so a new pin (a new commit and checksum above) downloads its file once by itself.
|
||||
CEC_DRIVER_CACHE="/var/cache/steamify/cros-ec-cec-${CEC_DRIVER_SHA256:0:12}.c"
|
||||
|
||||
cec_link_steamos_manager() {
|
||||
# On a Steam Machine: steamos-manager writes cecd's config from Steam's
|
||||
@@ -38,11 +34,11 @@ cec_link_steamos_manager() {
|
||||
# called by Steam Machine support, which installs steamos-manager after
|
||||
# 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
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable steamos-manager-configure-cecd.service 2>/dev/null
|
||||
systemctl --user start steamos-manager-configure-cecd.service 2>/dev/null
|
||||
systemctl --user restart cecd.service 2>/dev/null
|
||||
systemctl --user restart steamos-manager.service 2>/dev/null
|
||||
return 0
|
||||
}
|
||||
|
||||
@@ -55,10 +51,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
|
||||
systemctl --user stop cecd.service 2>/dev/null
|
||||
sudo modprobe -r cros_ec_cec 2>/dev/null
|
||||
sudo modprobe cros_ec_cec 2>/dev/null
|
||||
systemctl --user start cecd.service 2>/dev/null
|
||||
}
|
||||
|
||||
cec_driver_enable() {
|
||||
@@ -68,20 +64,13 @@ 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
|
||||
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
|
||||
info "Downloading Valve's Steam Machine CEC driver..."
|
||||
if ! curl -fsL --retry 2 "$CEC_DRIVER_URL" -o "$tmp/cros-ec-cec.c" ||
|
||||
! echo "$CEC_DRIVER_SHA256 $tmp/cros-ec-cec.c" | sha256sum -c --quiet -; then
|
||||
rm -rf "$tmp"
|
||||
err "Downloading Valve's CEC driver failed (or its checksum didn't match)."
|
||||
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 install -Dm644 "$tmp/cros-ec-cec.c" "$CEC_DRIVER_CACHE"
|
||||
tmp="$(mktemp -d)"
|
||||
info "Downloading Valve's Steam Machine CEC driver..."
|
||||
if ! curl -fsL "$CEC_DRIVER_URL" -o "$tmp/cros-ec-cec.c" ||
|
||||
! echo "$CEC_DRIVER_SHA256 $tmp/cros-ec-cec.c" | sha256sum -c --quiet -; then
|
||||
rm -rf "$tmp"
|
||||
err "Downloading Valve's CEC driver failed (or its checksum didn't match)."
|
||||
return 1
|
||||
fi
|
||||
# So it finds amdgpu's HDMI port (see the patch for why).
|
||||
patch_file cros-ec-cec-single-port.patch | patch -s -d "$tmp" -p1 ||
|
||||
@@ -113,8 +102,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 +129,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")
|
||||
@@ -149,13 +154,10 @@ cec_enable() {
|
||||
sudo tee "$CEC_STEAM_ENV" >/dev/null
|
||||
printf '%s\n' "# Written by Steamify: overrides STEAM_ENABLE_CEC=0 from the gaming mode script." \
|
||||
'[Service]' "EnvironmentFile=-$CEC_STEAM_ENV" | sudo tee "$CEC_STEAM_DROPIN" >/dev/null
|
||||
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
|
||||
systemctl --user daemon-reload
|
||||
cec_link_steamos_manager
|
||||
if compgen -G "/dev/cec*" >/dev/null; then
|
||||
best_effort user_systemctl restart cecd.service
|
||||
systemctl --user 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,20 +168,20 @@ 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[@]}"
|
||||
systemctl --user disable --now cecd.service cec-audio-control.socket cec-audio-control.service 2>/dev/null
|
||||
systemctl --user 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")"
|
||||
user_systemctl daemon-reload
|
||||
sudo rmdir "$(dirname "$CEC_ORDER_DROPIN")" "$(dirname "$CEC_STEAM_DROPIN")" "$(dirname "$CEC_STEAM_ENV")" 2>/dev/null
|
||||
systemctl --user 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
|
||||
user_systemctl is-active -q steamos-manager.service 2>/dev/null &&
|
||||
user_systemctl restart steamos-manager.service
|
||||
systemctl --user is-active -q steamos-manager.service 2>/dev/null &&
|
||||
systemctl --user restart steamos-manager.service
|
||||
ok "HDMI-CEC removed."
|
||||
}
|
||||
|
||||
@@ -187,5 +189,5 @@ cec_overview() {
|
||||
# For the menu's kernel overview.
|
||||
local dev="none"
|
||||
compgen -G "/dev/cec*" >/dev/null && dev="$(cd /dev && echo cec*)"
|
||||
echo "CEC devices: $dev cecd: $(user_systemctl is-active cecd 2>/dev/null)"
|
||||
echo "CEC devices: $dev cecd: $(systemctl --user is-active cecd 2>/dev/null)"
|
||||
}
|
||||
+3
-65
@@ -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
|
||||
@@ -82,30 +44,6 @@ require_root_helper() {
|
||||
fi
|
||||
}
|
||||
|
||||
user_session() {
|
||||
# A running user systemd and session bus. Not in the installer's chroot,
|
||||
# where the ISO applies Steamify for a user who has never logged in.
|
||||
[[ -S "${XDG_RUNTIME_DIR:-/nonexistent}/bus" ]]
|
||||
}
|
||||
|
||||
user_systemctl() {
|
||||
# systemctl --user, also without a session: then only the unit files
|
||||
# change (enable/disable through --root); starting and stopping is left
|
||||
# to the first login, which starts what's enabled anyway.
|
||||
if user_session; then systemctl --user "$@"; return; fi
|
||||
local a verb="" args=()
|
||||
for a in "$@"; do
|
||||
[[ "$a" == --now ]] && continue
|
||||
[[ -z "$verb" && "$a" != -* ]] && verb="$a"
|
||||
args+=("$a")
|
||||
done
|
||||
case "$verb" in
|
||||
enable|disable|is-enabled|mask|unmask) systemctl --user --root=/ "${args[@]}" ;;
|
||||
is-active) return 1 ;;
|
||||
*) return 0 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
plasma_applets() {
|
||||
# Print "containment:applet" for every applet of plugin $1 in the
|
||||
# user's Plasma layout, for kwriteconfig6 --group paths.
|
||||
@@ -135,7 +73,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 +81,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
|
||||
}
|
||||
@@ -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."
|
||||
}
|
||||
+29
-30
@@ -2,46 +2,41 @@
|
||||
# "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.
|
||||
local sudoers_tmp
|
||||
sudoers_tmp="$(mktemp)"
|
||||
cat > "$sudoers_tmp" << EOF
|
||||
$TARGET_USER ALL=(root) NOPASSWD: /usr/bin/systemctl start sync-steamos-session.service, /usr/bin/systemctl restart plasmalogin
|
||||
EOF
|
||||
if sudo visudo -cf "$sudoers_tmp" >/dev/null; then
|
||||
sudo install -m 0440 -o root -g root "$sudoers_tmp" /etc/sudoers.d/gamescope-session-switch
|
||||
ok "Installed /etc/sudoers.d/gamescope-session-switch for the shortcut."
|
||||
else
|
||||
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.
|
||||
# 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'"
|
||||
shortcut_install_sudoers
|
||||
local sudoers_tmp
|
||||
sudoers_tmp="$(mktemp)"
|
||||
cat > "$sudoers_tmp" << EOF
|
||||
$TARGET_USER ALL=(root) NOPASSWD: /usr/bin/systemctl start sync-steamos-session.service, /usr/bin/systemctl restart plasmalogin
|
||||
EOF
|
||||
if sudo visudo -cf "$sudoers_tmp" >/dev/null; then
|
||||
sudo install -m 0440 -o root -g root "$sudoers_tmp" /etc/sudoers.d/gamescope-session-switch
|
||||
ok "Installed /etc/sudoers.d/gamescope-session-switch for the shortcut."
|
||||
else
|
||||
warn "Generated sudoers rule failed validation; the shortcut will not be able to restart plasmalogin."
|
||||
fi
|
||||
rm -f "$sudoers_tmp"
|
||||
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."
|
||||
}
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
#!/bin/bash
|
||||
# The ISO applies Steamify in the installer, before the user ever logged
|
||||
# in (steamify.sh --defaults without a session). What needs Plasma's first
|
||||
# layout is finished at the first desktop login, by a one-time autostart
|
||||
# that then opens the app, next to CachyOS Hello.
|
||||
# Sourced by steamify.sh; not meant to be run on its own.
|
||||
|
||||
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
|
||||
rm -f "$FIRST_LOGIN_ENTRY" "\$0"
|
||||
[[ -x "$WIZARD_APP_LAUNCHER" ]] && exec "$WIZARD_APP_LAUNCHER"
|
||||
EOF2
|
||||
printf '%s\n' '[Desktop Entry]' 'Type=Application' 'Name=Steamify first login' \
|
||||
"Exec=$FIRST_LOGIN_SCRIPT" 'OnlyShowIn=KDE;' 'X-KDE-autostart-phase=2' 'NoDisplay=true' |
|
||||
install_executable "$FIRST_LOGIN_ENTRY" 644
|
||||
}
|
||||
|
||||
first_login_run() {
|
||||
# plasmashell has just laid out the desktop from the look-and-feel
|
||||
# package; wait for its config, then put single user's launcher
|
||||
# settings on the new launcher.
|
||||
local _
|
||||
for _ in $(seq 30); do
|
||||
[[ -n "$(plasma_applets org.kde.plasma.kickoff)" ]] && break
|
||||
sleep 2
|
||||
done
|
||||
stop_plasmashell_for_edit
|
||||
taskbar_drop_discover
|
||||
single_status && single_launcher
|
||||
restart_plasmashell_if_stopped
|
||||
return 0
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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
|
||||
}
|
||||
+11
-91
@@ -18,78 +18,6 @@ gaming_status() {
|
||||
esac
|
||||
}
|
||||
|
||||
# What Steam shows in its System settings besides the OS name (which stays
|
||||
# CachyOS's, for legal clarity and because limine-snapper-sync finds the boot
|
||||
# entries by it): the SteamOS release as the OS version, steam-machine as the
|
||||
# codename, Steamify with its version as the variant (os-release VERSION_ID,
|
||||
# VERSION_CODENAME, VARIANT_ID; see patches/steamify-os-release.sh).
|
||||
OS_NAME_SCRIPT=/usr/local/libexec/steamify-os-release
|
||||
OS_NAME_HOOK=/etc/pacman.d/hooks/zz-steamify-os-release.hook
|
||||
# limine's tools take the OS name from TARGET_OS_NAME, else os-release's
|
||||
# PRETTY_NAME: pinned to CachyOS, the boot entries never depend on os-release.
|
||||
LIMINE_DEFAULTS=/etc/default/limine
|
||||
|
||||
steamos_release() {
|
||||
# The SteamOS release Steamify follows: Valve's newest jupiter-X.Y repo
|
||||
# (where the SteamOS extras come from), as an os-release ID (no spaces or
|
||||
# capitals: steamos-3.9). Offline (e.g. in the installer): the one set
|
||||
# before, if any.
|
||||
local v
|
||||
v="$(valve_newest_repo jupiter 15)"
|
||||
if [[ -n "$v" ]]; then echo "steamos-${v#jupiter-}"
|
||||
else sed -n 's/^VERSION_ID=\(steamos-.*\)$/\1/p' /etc/os-release 2>/dev/null; fi
|
||||
}
|
||||
|
||||
os_name_enable() {
|
||||
# 2.9.0 pre-releases renamed the OS itself; the name stays CachyOS's.
|
||||
if grep -q '^DISTRIB_DESCRIPTION=.*with Steamify' /etc/lsb-release 2>/dev/null &&
|
||||
[[ -x /usr/share/libalpm/scripts/cachyos-branding ]]; then
|
||||
sudo /usr/share/libalpm/scripts/cachyos-branding lsb-release
|
||||
fi
|
||||
[[ -n "$(kreadconfig6 --file kcm-about-distrorc --group General --key Name 2>/dev/null)" ]] &&
|
||||
kset gaming kcm-about-distrorc General Name --delete
|
||||
# About this System: os-release's VERSION (CachyOS has none) instead of
|
||||
# VERSION_ID, which is the SteamOS release now.
|
||||
kset gaming kcm-about-distrorc General UseOSReleaseVersion true
|
||||
patch_file steamify-os-release.sh | fill VERSION="$VERSION" STEAMOS="$(steamos_release)" |
|
||||
sudo install -Dm755 /dev/stdin "$OS_NAME_SCRIPT" &&
|
||||
patch_file steamify-os-release.hook | fill SCRIPT="$OS_NAME_SCRIPT" |
|
||||
sudo install -Dm644 /dev/stdin "$OS_NAME_HOOK" &&
|
||||
sudo "$OS_NAME_SCRIPT" || { err "Setting Steamify's version for Steam failed."; return 1; }
|
||||
if [[ -f "$LIMINE_DEFAULTS" ]] && ! grep -q '^TARGET_OS_NAME=' "$LIMINE_DEFAULTS"; then
|
||||
backup_file "$LIMINE_DEFAULTS"
|
||||
printf '%s\n' 'TARGET_OS_NAME="CachyOS"' | sudo tee -a "$LIMINE_DEFAULTS" > /dev/null
|
||||
state_set gaming limine_target 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
os_name_disable() {
|
||||
sudo rm -f "$OS_NAME_HOOK" "$OS_NAME_SCRIPT"
|
||||
[[ -f /etc/os-release ]] && sudo sed -i -e '/^VARIANT=/d' -e '/^VARIANT_ID=/d' -e '/^VERSION_ID=/d' -e '/^VERSION_CODENAME=/d' /etc/os-release
|
||||
# CachyOS's own values back, the way its hooks write them.
|
||||
if [[ -x /usr/share/libalpm/scripts/cachyos-branding ]]; then
|
||||
sudo /usr/share/libalpm/scripts/cachyos-branding os-release
|
||||
# Undoes 2.9.0 pre-releases, which changed lsb-release's name too.
|
||||
sudo /usr/share/libalpm/scripts/cachyos-branding lsb-release
|
||||
fi
|
||||
if [[ -n "$(state_get gaming limine_target)" ]]; then
|
||||
sudo sed -i '/^TARGET_OS_NAME="CachyOS"$/d' "$LIMINE_DEFAULTS"
|
||||
state_set gaming limine_target ""
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
os_version_refresh() {
|
||||
# After every run that changed something (sudo is at hand then): Steam's
|
||||
# OS version follows Steamify's, not just the one that set it up. Silent:
|
||||
# the app reads the backend's stdout as JSON.
|
||||
gaming_status 2>/dev/null || return 0
|
||||
grep -qx "VARIANT_ID=steamify-$VERSION" /etc/os-release 2>/dev/null && return 0
|
||||
os_name_enable > /dev/null 2>&1
|
||||
return 0
|
||||
}
|
||||
|
||||
gaming_enable() {
|
||||
# LOGIN_MANAGER (sddm with single user, else plasmalogin) is set by the
|
||||
# menu. Re-running with the other value switches over cleanly.
|
||||
@@ -109,7 +37,6 @@ gaming_enable() {
|
||||
esac
|
||||
create_desktop_shortcut
|
||||
steam_enable
|
||||
os_name_enable || return 1
|
||||
}
|
||||
|
||||
gaming_disable() {
|
||||
@@ -122,8 +49,6 @@ gaming_disable() {
|
||||
switch_to_plasmalogin
|
||||
remove_desktop_shortcut
|
||||
steam_disable
|
||||
krevert gaming
|
||||
os_name_disable
|
||||
ok "The PC boots to the normal login screen again (from the next boot)."
|
||||
}
|
||||
|
||||
@@ -167,20 +92,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 +107,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 +130,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
|
||||
|
||||
+45
-196
@@ -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.1.0 [boot]=2.1.0 [theme]=2.1.0 [glyphs]=2.1.0 [single]=2.1.0
|
||||
[launcher]=2.1.0 [cec]=2.1.0 [machine]=2.2.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
|
||||
@@ -227,128 +179,25 @@ detect_components() {
|
||||
fi
|
||||
}
|
||||
|
||||
defaults_options() {
|
||||
# defaults_options [--options <id>[,<id>...]] [--boot gamescope|desktop]:
|
||||
# what --defaults sets up, from the Steam Machine ISO's installer page.
|
||||
# --options: exactly these items on, every other off (without it, the
|
||||
# menu's preselection). An item that's on brings its parent (single user
|
||||
# the conversion, like ticking it in the menu); one this PC can't use is
|
||||
# left off with a warning. --boot desktop needs the conversion. Returns 1
|
||||
# on an unknown option, item or value.
|
||||
local c ids list=false boot=""
|
||||
while [[ $# -gt 0 ]]; do
|
||||
# Both take a value: without one, shift 2 fails and never shifts, so
|
||||
# the loop would spin forever.
|
||||
[[ "$1" == --options || "$1" == --boot ]] && [[ $# -lt 2 ]] && { err "$1 needs a value"; return 1; }
|
||||
case "$1" in
|
||||
--options)
|
||||
list=true
|
||||
IFS=, read -ra ids <<< "$2"
|
||||
shift 2 ;;
|
||||
--boot)
|
||||
case "$2" in
|
||||
gamescope|desktop) boot="$2" ;;
|
||||
*) err "--boot takes gamescope or desktop"; return 1 ;;
|
||||
esac
|
||||
shift 2 ;;
|
||||
*) err "Unknown option: $1"; return 1 ;;
|
||||
esac
|
||||
done
|
||||
if [[ "$list" == true ]]; then
|
||||
for c in "${ids[@]}"; do
|
||||
[[ -n "$c" ]] || continue
|
||||
[[ -n "${LABEL[$c]:-}" ]] || { err "Unknown item: $c"; return 1; }
|
||||
[[ "$c" == boot ]] && { err "Where to start is --boot, not an item."; return 1; }
|
||||
is_action "$c" && { err "$c can't be part of the install."; return 1; }
|
||||
done
|
||||
for c in "${COMPONENTS[@]}"; do WANTED[$c]=0; done
|
||||
for c in "${ids[@]}"; do
|
||||
[[ -n "$c" ]] || continue
|
||||
if component_available "$c" && component_selectable "$c"; then
|
||||
WANTED[$c]=1
|
||||
else
|
||||
warn "Leaving out ${LABEL[$c]%%:*}: not available on this PC."
|
||||
fi
|
||||
done
|
||||
is_wanted single && component_available gaming && 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[boot]=1 ;;
|
||||
gamescope) WANTED[boot]=0 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
defaults_list() {
|
||||
# --defaults --list: what --defaults can set up on this PC, as one JSON
|
||||
# array, for an installer page (the Steam Machine ISO builds its Steamify
|
||||
# page from it, so new items show up without a new ISO). Per item: id,
|
||||
# label, hint, kind (toggle, or choice for boot: on = desktop), parent,
|
||||
# on (preselected like a first run) and selectable. Actions, retired
|
||||
# items and items this PC can't use (e.g. no Steam account yet) are
|
||||
# left out. Read-only: no sudo, no state.
|
||||
local c kind on sel items=""
|
||||
for c in "${COMPONENTS[@]}"; do
|
||||
component_available "$c" || continue
|
||||
is_action "$c" && continue
|
||||
[[ "$c" == kpin || "$c" == hdmi ]] && continue
|
||||
kind=toggle; [[ "$c" == boot ]] && kind=choice
|
||||
sel=false; component_selectable "$c" && sel=true
|
||||
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}"
|
||||
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 +209,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 +257,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 +266,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 +295,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 +357,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 +369,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}"
|
||||
@@ -533,6 +383,5 @@ apply_changes() {
|
||||
if "${c}_enable"; then is_action "$c" || feature_record "$c" enable; else failed+=("$c"); fi
|
||||
done
|
||||
feature_record_unticked
|
||||
os_version_refresh
|
||||
FAILED=("${failed[@]}")
|
||||
}
|
||||
-267
@@ -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
@@ -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
-49
@@ -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."
|
||||
@@ -101,54 +101,7 @@ single_launcher() {
|
||||
done
|
||||
}
|
||||
|
||||
single_launcher_drop() {
|
||||
# The theme's layout backup is taken when it's turned on: with single
|
||||
# user on then, it holds single's launcher keys, and restoring it after
|
||||
# single was turned off brings them back. Drop exactly single's values
|
||||
# (a launcher set up differently by the user is left alone).
|
||||
local applet
|
||||
local -a kick_args
|
||||
for applet in $(plasma_applets org.kde.plasma.kickoff); do
|
||||
kick_args=(--file plasma-org.kde.plasma.desktop-appletsrc --group Containments --group "${applet%%:*}"
|
||||
--group Applets --group "${applet#*:}" --group Configuration --group General)
|
||||
[[ "$(kreadconfig6 "${kick_args[@]}" --key primaryActions)" == 3 ]] &&
|
||||
kwriteconfig6 "${kick_args[@]}" --key primaryActions --delete
|
||||
[[ "$(kreadconfig6 "${kick_args[@]}" --key systemFavorites)" == 'suspend,reboot,shutdown' ]] &&
|
||||
kwriteconfig6 "${kick_args[@]}" --key systemFavorites --delete
|
||||
done
|
||||
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 +127,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
@@ -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
|
||||
systemctl --user 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
|
||||
|
||||
+16
-44
@@ -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"
|
||||
user_systemctl daemon-reload
|
||||
}
|
||||
# Reload user systemd context and activate the background loop
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user 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..."
|
||||
systemctl --user disable --now steam-desktop-autostart.service 2>/dev/null
|
||||
rm -f "$HOME/.config/systemd/user/steam-desktop-autostart.service" \
|
||||
"$HOME/.config/environment.d/99-kde-virtual-keyboard.conf"
|
||||
systemctl --user daemon-reload
|
||||
ok "Steam desktop settings removed (takes full effect at next login)."
|
||||
}
|
||||
|
||||
|
||||
+6
-2
@@ -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
|
||||
systemd-run --user --collect -q steam -silent >/dev/null 2>&1
|
||||
if systemctl --user is-enabled -q steam-desktop-autostart.service 2>/dev/null; then
|
||||
systemctl --user 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"
|
||||
|
||||
+191
-89
@@ -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
|
||||
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)..."
|
||||
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."
|
||||
return 0
|
||||
fi
|
||||
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; }
|
||||
}
|
||||
|
||||
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"
|
||||
@@ -229,49 +378,6 @@ machine_status() {
|
||||
pacman -Qi leds-valve-dkms-git >/dev/null 2>&1 && pacman -Qi steamos-manager >/dev/null 2>&1
|
||||
}
|
||||
|
||||
# Steam (steamwebhelper) reads the serial number for its System settings
|
||||
# straight from DMI, which the kernel makes root-only; SteamOS makes it
|
||||
# readable. A tmpfiles rule does that at every boot.
|
||||
SERIAL_TMPFILES=/etc/tmpfiles.d/steamify-serial.conf
|
||||
|
||||
# Steam's Wi-Fi backend switch goes through steamos-manager, which reads and
|
||||
# writes the backend in this file (SteamOS ships it); without it, it fails
|
||||
# with "Wi-Fi backend not found in config". wpa_supplicant is what
|
||||
# NetworkManager uses on CachyOS anyway. Not written when someone set a
|
||||
# backend themselves.
|
||||
WIFI_BACKEND_CONF=/etc/NetworkManager/conf.d/99-valve-wifi-backend.conf
|
||||
|
||||
wifi_backend_enable() {
|
||||
[[ -f "$WIFI_BACKEND_CONF" ]] && return 0
|
||||
grep -rqs '^wifi.backend=' /etc/NetworkManager/NetworkManager.conf /etc/NetworkManager/conf.d && return 0
|
||||
printf '%s\n' "# Written by Steamify: Steam's Wi-Fi backend setting (steamos-manager)." \
|
||||
'[device]' 'wifi.backend=wpa_supplicant' | sudo install -Dm644 /dev/stdin "$WIFI_BACKEND_CONF" ||
|
||||
{ err "Writing the Wi-Fi backend setting failed."; return 1; }
|
||||
state_set machine wifi_backend 1
|
||||
}
|
||||
|
||||
wifi_backend_disable() {
|
||||
[[ -n "$(state_get machine wifi_backend)" ]] || return 0
|
||||
sudo rm -f "$WIFI_BACKEND_CONF"
|
||||
state_clear machine
|
||||
}
|
||||
|
||||
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 ||
|
||||
{ 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
|
||||
return 0
|
||||
}
|
||||
|
||||
machine_enable() {
|
||||
# The pinned kernel first when it's wanted too, so DKMS builds the LED
|
||||
# driver for it once, instead of for the current kernel and then again.
|
||||
@@ -297,11 +403,9 @@ EOF
|
||||
# for hardware and controller settings; it knows the Steam Machine from its DMI data.
|
||||
info "Installing hardware manager packages (steamos-manager & inputplumber)..."
|
||||
sudo pacman -S --needed --noconfirm steamos-manager inputplumber || { err "Installing hardware manager packages failed."; return 1; }
|
||||
serial_enable || return 1
|
||||
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
|
||||
systemctl --user 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 +422,17 @@ 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
|
||||
serial_disable
|
||||
wifi_backend_disable
|
||||
systemctl --user 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
|
||||
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
@@ -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
|
||||
|
||||
@@ -12,8 +12,8 @@ NOTIFY_NAME=steamify-update-check
|
||||
|
||||
notify_status() {
|
||||
[[ -f "$NOTIFY_SCRIPT" ]] &&
|
||||
user_systemctl is-enabled -q "$NOTIFY_NAME.timer" 2>/dev/null &&
|
||||
user_systemctl is-enabled -q "$NOTIFY_NAME.service" 2>/dev/null
|
||||
systemctl --user is-enabled -q "$NOTIFY_NAME.timer" 2>/dev/null &&
|
||||
systemctl --user is-enabled -q "$NOTIFY_NAME.service" 2>/dev/null
|
||||
}
|
||||
|
||||
notify_seen() {
|
||||
@@ -40,19 +40,19 @@ notify_enable() {
|
||||
mkdir -p "$NOTIFY_UNITS"
|
||||
service_file "$NOTIFY_NAME.service" NOTIFY_SCRIPT="$NOTIFY_SCRIPT" > "$NOTIFY_UNITS/$NOTIFY_NAME.service"
|
||||
service_file "$NOTIFY_NAME.timer" > "$NOTIFY_UNITS/$NOTIFY_NAME.timer"
|
||||
user_systemctl daemon-reload
|
||||
user_systemctl enable "$NOTIFY_NAME.service" >/dev/null 2>&1 &&
|
||||
user_systemctl enable --now "$NOTIFY_NAME.timer" >/dev/null 2>&1 ||
|
||||
systemctl --user daemon-reload
|
||||
systemctl --user enable "$NOTIFY_NAME.service" >/dev/null 2>&1 &&
|
||||
systemctl --user enable --now "$NOTIFY_NAME.timer" >/dev/null 2>&1 ||
|
||||
{ err "Enabling the update check failed."; return 1; }
|
||||
state_set notify seen "$VERSION"
|
||||
ok "Update notifications on: you'll get a notification when there's a new Steamify."
|
||||
}
|
||||
|
||||
notify_disable() {
|
||||
user_systemctl disable --now "$NOTIFY_NAME.timer" "$NOTIFY_NAME.service" >/dev/null 2>&1
|
||||
systemctl --user disable --now "$NOTIFY_NAME.timer" "$NOTIFY_NAME.service" >/dev/null 2>&1
|
||||
rm -f "$NOTIFY_UNITS/$NOTIFY_NAME.service" "$NOTIFY_UNITS/$NOTIFY_NAME.timer" "$NOTIFY_SCRIPT"
|
||||
rmdir "$STEAMIFY_BIN" 2>/dev/null || true
|
||||
user_systemctl daemon-reload
|
||||
systemctl --user daemon-reload
|
||||
state_clear notify
|
||||
ok "Update notifications off."
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
+16
-63
@@ -47,27 +47,18 @@ theme_status() {
|
||||
[[ "$(kreadconfig6 --file kdeglobals --group KDE --key LookAndFeelPackage)" == "$VAPOR_LOOKANDFEEL" ]]
|
||||
}
|
||||
|
||||
theme_install_package() {
|
||||
pacman -Q cachyos-vapor >/dev/null 2>&1 && return 0
|
||||
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() {
|
||||
# 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
|
||||
if [[ -e "$layout" ]] && ! cmp -s "$layout" "/etc/skel/.config/${layout##*/}"; then
|
||||
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
|
||||
fi
|
||||
if [[ -z "${WAYLAND_DISPLAY:-}${DISPLAY:-}" ]]; then
|
||||
err "Run this from the Plasma desktop: applying the Vapor layout needs a running Plasma session."
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
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 +76,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,55 +86,23 @@ 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
|
||||
extras_enable || warn "SteamOS desktop extras not installed (see above); the theme itself is on."
|
||||
ok "Vapor theme set; Plasma lays out the Vapor desktop at the first login."
|
||||
return 0
|
||||
fi
|
||||
info "Applying the Vapor theme with its desktop and window layout..."
|
||||
# --resetLayout is "Desktop and window layout" in System Settings: the
|
||||
# SteamOS panel, launcher icon and wallpaper. It needs plasmashell up.
|
||||
lookandfeeltool -a "$VAPOR_LOOKANDFEEL" --resetLayout >/dev/null 2>&1 ||
|
||||
{ err "lookandfeeltool failed."; return 1; }
|
||||
# The new layout has a new launcher, without single user's settings, and the default taskbar pins.
|
||||
sleep 3
|
||||
stop_plasmashell_for_edit
|
||||
taskbar_drop_discover
|
||||
single_status && single_launcher
|
||||
restart_plasmashell_if_stopped
|
||||
# The new layout has a new launcher, without single user's settings.
|
||||
if single_status; then
|
||||
sleep 3
|
||||
stop_plasmashell_for_edit
|
||||
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..."
|
||||
@@ -163,11 +120,7 @@ theme_disable() {
|
||||
fi
|
||||
# After the tools above, so keys that weren't set before are removed again.
|
||||
krevert theme
|
||||
if single_status; then
|
||||
single_launcher
|
||||
else
|
||||
single_launcher_drop
|
||||
fi
|
||||
single_status && single_launcher
|
||||
restart_plasmashell_if_stopped
|
||||
qdbus6 org.kde.KWin /KWin org.kde.KWin.reconfigure >/dev/null 2>&1 || true
|
||||
|
||||
|
||||
+6
-12
@@ -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; }
|
||||
@@ -107,7 +101,7 @@ vram_selectable() { vram_supported || vram_status; }
|
||||
vram_status() {
|
||||
pacman -Q "${VRAM_PKGS[@]}" >/dev/null 2>&1 &&
|
||||
systemctl is-enabled -q dmemcg-booster-system.service 2>/dev/null &&
|
||||
user_systemctl is-enabled -q dmemcg-booster-user.service 2>/dev/null
|
||||
systemctl --user is-enabled -q dmemcg-booster-user.service 2>/dev/null
|
||||
}
|
||||
|
||||
vram_enable() {
|
||||
@@ -121,18 +115,18 @@ vram_enable() {
|
||||
fi
|
||||
sudo systemctl enable --now dmemcg-booster-system.service >/dev/null 2>&1 ||
|
||||
{ err "Starting dmemcg-booster failed."; return 1; }
|
||||
user_systemctl enable --now dmemcg-booster-user.service >/dev/null 2>&1 ||
|
||||
systemctl --user enable --now dmemcg-booster-user.service >/dev/null 2>&1 ||
|
||||
{ err "Starting dmemcg-booster for $USER failed."; return 1; }
|
||||
kset vram kcgroupsrc "Foreground Booster" autostart true
|
||||
# Started by the Plasma session from now on; start it in this one too.
|
||||
[[ "${XDG_CURRENT_DESKTOP:-}" == KDE ]] &&
|
||||
user_systemctl start plasma-foreground-booster.service >/dev/null 2>&1
|
||||
systemctl --user start plasma-foreground-booster.service >/dev/null 2>&1
|
||||
ok "VRAM booster on: the game in front keeps its VRAM."
|
||||
}
|
||||
|
||||
vram_disable() {
|
||||
local pkgs
|
||||
user_systemctl disable --now plasma-foreground-booster.service dmemcg-booster-user.service >/dev/null 2>&1
|
||||
systemctl --user disable --now plasma-foreground-booster.service dmemcg-booster-user.service >/dev/null 2>&1
|
||||
sudo systemctl disable --now dmemcg-booster-system.service >/dev/null 2>&1
|
||||
krevert vram
|
||||
pkgs="$(state_get vram installed_pkgs)"
|
||||
|
||||
+35
-3
@@ -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
|
||||
|
||||
@@ -13,7 +13,4 @@ read and reviewed on their own. `lib/*.sh` reads them with `patch_file
|
||||
| `steamify-fremont-poweroff.dkms.conf`, `steamify-cros-ec-cec.dkms.conf` | `lib/fremont-poweroff.sh`, `lib/cec.sh` | The DKMS modules' `dkms.conf` (`fill NAME=... VERSION=...`) |
|
||||
| `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=...`) |
|
||||
@@ -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
|
||||
@@ -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():
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -1,14 +0,0 @@
|
||||
# Installed by Steamify CachyOS (SteamOS conversion): runs after
|
||||
# cachyos-hooks' os-release/cachyos-branding hooks (hooks run in file name
|
||||
# order).
|
||||
[Trigger]
|
||||
Operation = Install
|
||||
Operation = Upgrade
|
||||
Type = Package
|
||||
Target = filesystem
|
||||
Target = cachyos-hooks
|
||||
|
||||
[Action]
|
||||
Description = Steamify: the OS variant and version Steam shows
|
||||
When = PostTransaction
|
||||
Exec = @SCRIPT@
|
||||
@@ -1,14 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Installed by Steamify CachyOS (SteamOS conversion): what Steam shows in its
|
||||
# System settings besides the OS name, which stays CachyOS's: the SteamOS
|
||||
# release Steamify follows as the OS version (VERSION_ID, e.g. steamos-3.9),
|
||||
# steam-machine as the codename, and Steamify with its version as the variant
|
||||
# (VARIANT_ID, which Steam shows). KDE's About this System would show
|
||||
# VERSION_ID after the name: the conversion sets its UseOSReleaseVersion, so it
|
||||
# shows os-release's VERSION instead, which CachyOS doesn't have. NAME and
|
||||
# PRETTY_NAME are never touched: limine-snapper-sync finds the boot entries by
|
||||
# the OS name. The zz-steamify-os-release hook runs this after cachyos-hooks.
|
||||
sed -i -e '/^VARIANT=/d' -e '/^VARIANT_ID=/d' -e '/^VERSION_ID=/d' -e '/^VERSION_CODENAME=/d' /etc/os-release
|
||||
printf '%s\n' 'VARIANT="Steamify @VERSION@"' 'VARIANT_ID=steamify-@VERSION@' 'VERSION_CODENAME=steam-machine' >> /etc/os-release
|
||||
[ -n "@STEAMOS@" ] && echo 'VERSION_ID=@STEAMOS@' >> /etc/os-release
|
||||
exit 0
|
||||
@@ -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
|
||||
@@ -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
@@ -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) |
|
||||
+3
-3
@@ -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
|
||||
|
||||
+16
-90
@@ -15,39 +15,21 @@
|
||||
set -uo pipefail
|
||||
|
||||
# Release version, see CHANGELOG.md.
|
||||
VERSION=2.11.1
|
||||
VERSION=2.5.2
|
||||
|
||||
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 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
|
||||
# --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
|
||||
BACKEND=false
|
||||
[[ "${1:-}" == --backend ]] && BACKEND=true
|
||||
|
||||
if [[ "$MODE" != backend && "$MODE" != list ]]; then
|
||||
if [[ "$BACKEND" == 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 +46,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 +105,14 @@ 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; }
|
||||
}
|
||||
|
||||
run_defaults() {
|
||||
# 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
|
||||
REAPPLY=false
|
||||
sudo -n true 2>/dev/null || { err "--defaults needs sudo without a password."; return 1; }
|
||||
detect_components
|
||||
defaults_options "${@:2}" || return 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
|
||||
ok "Done; the changes take effect after a restart."
|
||||
}
|
||||
|
||||
run_boot_only() {
|
||||
local mode="${2:-}" c
|
||||
RESTART_FOR_LOGIN=false
|
||||
REAPPLY=false
|
||||
case "$mode" in
|
||||
gamescope|desktop) ;;
|
||||
*) err "--boot takes gamescope or desktop"; return 1 ;;
|
||||
esac
|
||||
detect_components
|
||||
is_current gaming || { err "--boot needs the SteamOS conversion; turn it on first."; return 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
|
||||
plan_changes
|
||||
if [[ ${#TO_DISABLE[@]} -eq 0 && ${#TO_ENABLE[@]} -eq 0 ]]; then
|
||||
ok "Already starting in $mode."
|
||||
return 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
|
||||
shift
|
||||
backend_main "$@"
|
||||
exit $?
|
||||
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 +143,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 +168,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
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -35,15 +35,9 @@ Item {
|
||||
border.width: step.st === "wait" || step.st === "run" ? 2 : 0; border.color: step.st === "run" ? Theme.accent : "#343f50"
|
||||
Text { anchors.centerIn: parent; text: step.st === "ok" ? "✓" : (step.st === "fail" ? "!" : ""); color: step.st === "ok" ? Theme.good : Theme.bad
|
||||
font.pixelSize: 13; font.weight: Font.Bold }
|
||||
// Only this dot turns while the step runs: ✓ and ! never rotate
|
||||
// (an animator leaves its item at whatever angle it stopped).
|
||||
Item { anchors.fill: parent; visible: step.st === "run"
|
||||
Rectangle { width: 6; height: 6; radius: 3; color: Theme.accent; x: parent.width / 2 - 3; y: -3 }
|
||||
RotationAnimator on rotation { running: step.st === "run"; from: 0; to: 360; duration: 1000; loops: Animation.Infinite } } }
|
||||
RotationAnimator on rotation { running: step.st === "run"; from: 0; to: 360; duration: 1000; loops: Animation.Infinite } }
|
||||
Row { width: 380; anchors.verticalCenter: parent.verticalCenter; spacing: 10
|
||||
// Boot into's label is its prefix already: "Boot into desktop", not "Boot into Boot into".
|
||||
Text { text: step.modelData.id === "boot" ? (Texts.actions[step.modelData.action] || [])[3] + Texts.actions[step.modelData.action][0].toLowerCase()
|
||||
: (Texts.actions[step.modelData.action] || [])[3] + Texts.label(step.modelData.id)
|
||||
Text { text: (Texts.actions[step.modelData.action] || [])[3] + Texts.label(step.modelData.id)
|
||||
color: step.st === "wait" ? Theme.faint : Theme.textHi; font.family: Theme.body; font.pixelSize: 16; font.weight: Font.DemiBold
|
||||
anchors.verticalCenter: parent.verticalCenter; elide: Text.ElideRight
|
||||
width: Math.min(implicitWidth, parent.width - (badge.visible ? badge.width + parent.spacing : 0)) }
|
||||
|
||||
+1
-16
@@ -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"] },
|
||||
|
||||
+4
-4
@@ -1,12 +1,12 @@
|
||||
#!/bin/bash
|
||||
# Steamify CachyOS - get and start the app, for `curl | bash`:
|
||||
# Steamify CachyOS - get and start the app (v2), for `curl | bash`:
|
||||
# curl -fsSL https://github.com/theupriser/steamify-cachyos/releases/latest/download/steamify-app.sh | bash
|
||||
# Downloads the newest release's app package (steamify-app.tar.gz: the app,
|
||||
# steamify.sh, lib/, patches/ and services/) to ~/.local/share/steamify/app, installs PySide6 if
|
||||
# it's missing, adds a launcher entry, and starts the app.
|
||||
# STEAMIFY_RELEASE=<tag> takes that release instead of the newest.
|
||||
# STEAMIFY_BRANCH=<branch> takes that branch's source instead (for testing
|
||||
# before a build).
|
||||
# STEAMIFY_RELEASE=<tag> takes that release instead of the newest (the
|
||||
# v2-ui-preview build's copy of this script sets it). STEAMIFY_BRANCH=<branch>
|
||||
# takes that branch's source instead (for testing before a build).
|
||||
set -euo pipefail
|
||||
|
||||
REPO="theupriser/steamify-cachyos"
|
||||
|
||||
Reference in new issue
Block a user