diff --git a/AGENTS.md b/AGENTS.md index 950c19f..a106b13 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -58,7 +58,9 @@ gamescope and the Plasma desktop. Primary target: the Valve Steam Machine 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"). + (`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. 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 `_repair` checks diff --git a/CHANGELOG.md b/CHANGELOG.md index ee4cfe3..e072c3c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ one per merged pull request. - **feat: single user mode also works on NVIDIA PCs, without the SteamOS conversion: it switches to SDDM and logs in to the Plasma session by itself (/etc/sddm.conf.d/zzz-steamify-autologin.conf), and no longer ticks the conversion where that isn't offered (lib/single-user.sh)** - **fix: "Add as non-Steam game" isn't offered on NVIDIA PCs (there is no gaming mode there for it to give the controller; shown when already on, so it can be turned off)** - **feat: Extended controller support (extended_controller_support, off by default): the Xbox wireless dongle (xone-dkms, xone-dongle-firmware) and Xbox controllers over Bluetooth with rumble, button mapping and battery level (xpadneo-dkms), from the CachyOS repo, built for every installed kernel; a PC with the AUR's xone-dkms-git keeps it; off removes only what Steamify installed (lib/controllers.sh, tests/controllers-test.sh)** +- **feat: a new opt-in option (unticked by default, e.g. Extended controller support) shows the "new" badge in the menu and the app without being ticked for you (feature_new_optin); it counts "Gaming on NVIDIA" as its parent where the conversion isn't offered** - **test: tests/nvidia-test.sh runs it against a fake RTX 5080 beside an iGPU, a stub pacman and systemctl, and a temp home (no root, VM or hardware); verified on a real RTX 5080: gamescope's session, a nested gamescope and a KWin-only session all showed artifacts or stutter, Big Picture on the Plasma desktop did not** ## 2.9.6 - 2026-09-30 diff --git a/lib/backend.sh b/lib/backend.sh index 1e7e8a1..31afcc6 100644 --- a/lib/backend.sh +++ b/lib/backend.sh @@ -53,7 +53,7 @@ backend_status() { 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+=",\"new\":$({ feature_new "$c" || feature_new_optin "$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:-}" ]] && diff --git a/lib/menu.sh b/lib/menu.sh index 95ccf42..4cb8d4c 100644 --- a/lib/menu.sh +++ b/lib/menu.sh @@ -124,7 +124,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"; then b="${c_green}(new)${c_reset}"; fi + elif feature_new "$1" || feature_new_optin "$1"; then b="${c_green}(new)${c_reset}"; fi if [[ -n "$b" ]]; then if [[ "$l" == *:* ]]; then l="${l%%:*} $b:${l#*:}" else l+=" $b"; fi @@ -132,16 +132,30 @@ menu_label() { printf '%s' "$l" } -feature_new() { - # 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 "* ]] && +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_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 "* ]] +} + component_selectable() { # Greyed out and not tickable when it has nothing to do. case "$1" in diff --git a/tests/controllers-test.sh b/tests/controllers-test.sh index 2d7134e..3b85599 100644 --- a/tests/controllers-test.sh +++ b/tests/controllers-test.sh @@ -61,4 +61,24 @@ check "packages you had before stay" 'pacman -Q xpadneo-dkms xone-dkms xone-dong check "offered on every PC" 'component_available extended_controller_support' check "not preselected: it builds kernel modules for every kernel" '[[ " ${NO_PRESELECT[*]} " == *" extended_controller_support "* ]]' check "a top-level item with a label" '[[ -z "${PARENT[extended_controller_support]:-}" && -n "${LABEL[extended_controller_support]}" ]]' + +# The "new" badge: an opt-in option added after setup shows it, but is never ticked for you. +component_selectable() { return 0; } +declare -A CURRENT=([gaming]=1 [nvidia]=0 [extended_controller_support]=0 [vram]=0 [boot]=0) +rm -f "$STATE_DIR/features.state" +check "new opt-in option (conversion on, no record): the new badge" 'feature_new_optin extended_controller_support' +check "...but it is not ticked for you (not a new default option)" '! feature_new extended_controller_support' +check "...and the menu label says (new)" '[[ "$(menu_label extended_controller_support)" == *"(new)"* ]]' +check "a new default option is still ticked for you, and is not the opt-in kind" 'feature_new vram && ! feature_new_optin vram' +check "Boot into never gets the badge (it is a choice row)" '! feature_new_optin boot' +state_set_features() { kwriteconfig6 --file "$STATE_DIR/features.state" --group State --key "$1" "$2"; } +state_set_features extended_controller_support off +check "once a run recorded it as off, the badge is gone" '! feature_new_optin extended_controller_support' +rm -f "$STATE_DIR/features.state" +CURRENT[gaming]=0; CURRENT[nvidia]=1 +check "on an NVIDIA PC (Gaming on NVIDIA on, no conversion) it shows too" 'feature_new_optin extended_controller_support' +CURRENT[nvidia]=0 +check "with neither the conversion nor Gaming on NVIDIA on (a fresh PC) nothing is new" '! feature_new_optin extended_controller_support && ! feature_new vram' +CURRENT[gaming]=1; CURRENT[extended_controller_support]=1 +check "already on: not new" '! feature_new_optin extended_controller_support' exit $fail