v0.1.8 — fix Gaming Mode 60 Hz launch on NVIDIA + HDMI
Reported by clutchmuffin: TUI saved e.g. CUSTOM_REFRESH_RATES=165 but Gaming Mode always launched at 60 Hz. Two stacked bugs: 1. Settings TUI wrote ~/.config/environment.d/gamescope-session-plus.conf but never reloaded systemd's user env, so the running user manager (and therefore gamescope-session-plus@.service) still had the old values until next login. Now flush_pending calls `systemctl --user import-environment` / `unset-environment` for the keys it just touched. 2. CUSTOM_REFRESH_RATES was written as a single scalar. Gamescope's --custom-refresh-rates is a list of *switchable* rates, not a launch-rate selector — and with no safe 60 Hz fallback in the list, some DRM/NVIDIA paths drop to the EDID-preferred 60 Hz on first launch. TUI now writes a comma list (e.g. 60,165). show_state and confirm_risky_save de-list to the highest member for display / validation. Adds a troubleshooting README entry documenting the Steam BPM client-side rate persistence as the canonical first-launch workaround. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ba86b8c777
commit
4fa77a6238
3 changed files with 59 additions and 3 deletions
24
README.md
24
README.md
|
|
@ -1,6 +1,6 @@
|
||||||
# DeckShift
|
# DeckShift
|
||||||
|
|
||||||
**Version 0.1.6** — Steam Deck-style gaming mode for [Omarchy](https://omarchy.com). Press `Super+Shift+S` to enter Gaming Mode (Steam Big Picture in Gamescope), `Super+Shift+R` to return to your desktop.
|
**Version 0.1.8** — Steam Deck-style gaming mode for [Omarchy](https://omarchy.com). Press `Super+Shift+S` to enter Gaming Mode (Steam Big Picture in Gamescope), `Super+Shift+R` to return to your desktop.
|
||||||
|
|
||||||
Lineage: forked from [Super-Shift-S-Omarchy-Deck-Mode](https://git.no-signal.uk/nosignal/Super-Shift-S-Omarchy-Deck-Mode), briefly renamed Omarchy Deck, then renamed DeckShift.
|
Lineage: forked from [Super-Shift-S-Omarchy-Deck-Mode](https://git.no-signal.uk/nosignal/Super-Shift-S-Omarchy-Deck-Mode), briefly renamed Omarchy Deck, then renamed DeckShift.
|
||||||
|
|
||||||
|
|
@ -10,6 +10,16 @@ Lineage: forked from [Super-Shift-S-Omarchy-Deck-Mode](https://git.no-signal.uk/
|
||||||
|
|
||||||
## What's New
|
## What's New
|
||||||
|
|
||||||
|
### v0.1.8 — Settings TUI now reaches gamescope without re-login
|
||||||
|
|
||||||
|
- The Settings TUI used to write `~/.config/environment.d/gamescope-session-plus.conf` and rely on the user logging out before the change reached `gamescope-session-plus@.service`. Saving the TUI now calls `systemctl --user import-environment` for the keys it just wrote, so the next Gaming Mode launch picks up the new values immediately.
|
||||||
|
- Refresh-rate writes are now a comma list with `60` as the floor (e.g. `60,165`) rather than a single value. Gamescope's `--custom-refresh-rates` is a list of switchable rates, not a launch-rate selector — keeping `60` in the list guarantees a safe fallback if the high-rate mode isn't enumerated on first launch.
|
||||||
|
- Fixes a reported regression where Gaming Mode always launched at 60 Hz on NVIDIA + HDMI even though the TUI showed the user's chosen rate.
|
||||||
|
|
||||||
|
### v0.1.7 — Foot terminal compatibility
|
||||||
|
|
||||||
|
- Internal: confirmed DeckShift Settings TUI works unchanged with Omarchy's new `foot` terminal (in addition to kitty / ghostty / alacritty). No code changes required — Omarchy's stock floating-window rule already lists foot's native class.
|
||||||
|
|
||||||
### v0.1.6 — Omarchy-only, simpler portal recovery
|
### v0.1.6 — Omarchy-only, simpler portal recovery
|
||||||
|
|
||||||
- Dropped the non-Omarchy fallback in `deckshift-portal-recovery` — DeckShift targets Omarchy only, so the helper now just calls `omarchy-restart-walker` directly.
|
- Dropped the non-Omarchy fallback in `deckshift-portal-recovery` — DeckShift targets Omarchy only, so the helper now just calls `omarchy-restart-walker` directly.
|
||||||
|
|
@ -477,6 +487,18 @@ If you're on AC and using Omarchy, this is expected — see the *Performance Mod
|
||||||
- Older Gen8/9 Intel iGPUs (Skylake, Kaby Lake) struggle with Vulkan workloads. Lower the launch resolution via the Settings TUI (`deckshift-settings`) — 720p / 1080p makes a big difference.
|
- Older Gen8/9 Intel iGPUs (Skylake, Kaby Lake) struggle with Vulkan workloads. Lower the launch resolution via the Settings TUI (`deckshift-settings`) — 720p / 1080p makes a big difference.
|
||||||
- If you have a discrete GPU that should take over, check its driver is loaded: `lspci -k | grep -A2 VGA`
|
- If you have a discrete GPU that should take over, check its driver is loaded: `lspci -k | grep -A2 VGA`
|
||||||
|
|
||||||
|
**Gaming Mode launches at 60 Hz even though I picked a higher rate in the TUI**
|
||||||
|
|
||||||
|
`--custom-refresh-rates` is gamescope's list of *switchable* rates, not a launch-rate selector. On embedded/DRM output (especially NVIDIA + HDMI) gamescope picks the connector's EDID-preferred mode at first launch, which is usually 60 Hz even when higher modes are enumerated. Two-step fix:
|
||||||
|
|
||||||
|
1. Confirm the env var actually reached the session:
|
||||||
|
```bash
|
||||||
|
systemctl --user show-environment | grep REFRESH
|
||||||
|
journalctl --user -u "gamescope-session-plus@*" -b --no-pager | grep -m1 -- '--custom-refresh-rates'
|
||||||
|
```
|
||||||
|
In v0.1.8+ this should work without re-login — the Settings TUI now calls `systemctl --user import-environment` on save. If you're on an older release, log out and back in once after saving in the TUI.
|
||||||
|
2. Once Steam Big Picture is up, set the rate explicitly: Settings → Display → Refresh Rate → your rate. Steam persists this client-side, so every subsequent Gaming Mode launch will go straight to that rate.
|
||||||
|
|
||||||
### Log Locations
|
### Log Locations
|
||||||
|
|
||||||
| Component | Command |
|
| Component | Command |
|
||||||
|
|
|
||||||
|
|
@ -109,6 +109,19 @@ flush_pending() {
|
||||||
echo "${key}=${value}" >> "$CONF"
|
echo "${key}=${value}" >> "$CONF"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# environment.d/*.conf is parsed by `systemd --user` at user-manager startup,
|
||||||
|
# so edits made here don't reach gamescope-session-plus@.service until the
|
||||||
|
# next login unless we nudge systemd. import-environment pulls the keys we
|
||||||
|
# just wrote into the running user manager scope so the next Gaming Mode
|
||||||
|
# launch sees them without a re-login.
|
||||||
|
if [[ ${#PENDING_SET[@]} -gt 0 ]]; then
|
||||||
|
# shellcheck disable=SC2046
|
||||||
|
systemctl --user import-environment $(printf '%s ' "${!PENDING_SET[@]}") 2>/dev/null || true
|
||||||
|
fi
|
||||||
|
if [[ ${#PENDING_UNSET[@]} -gt 0 ]]; then
|
||||||
|
systemctl --user unset-environment "${!PENDING_UNSET[@]}" 2>/dev/null || true
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
@ -225,6 +238,12 @@ show_state() {
|
||||||
width=$(effective SCREEN_WIDTH)
|
width=$(effective SCREEN_WIDTH)
|
||||||
height=$(effective SCREEN_HEIGHT)
|
height=$(effective SCREEN_HEIGHT)
|
||||||
refresh=$(effective CUSTOM_REFRESH_RATES)
|
refresh=$(effective CUSTOM_REFRESH_RATES)
|
||||||
|
# Stored as a comma list (e.g. "60,165") so gamescope has a safe 60 Hz
|
||||||
|
# fallback. The user only cares about the rate they picked — the highest
|
||||||
|
# member of the list.
|
||||||
|
if [[ "$refresh" == *,* ]]; then
|
||||||
|
refresh=$(tr ',' '\n' <<<"$refresh" | sort -nr | head -1)
|
||||||
|
fi
|
||||||
vk_adapter=$(effective VULKAN_ADAPTER)
|
vk_adapter=$(effective VULKAN_ADAPTER)
|
||||||
dri_prime=$(effective DRI_PRIME)
|
dri_prime=$(effective DRI_PRIME)
|
||||||
prime_offload=$(effective __NV_PRIME_RENDER_OFFLOAD)
|
prime_offload=$(effective __NV_PRIME_RENDER_OFFLOAD)
|
||||||
|
|
@ -385,7 +404,17 @@ choose_refresh_rate() {
|
||||||
rate=${choice%% *}
|
rate=${choice%% *}
|
||||||
fi
|
fi
|
||||||
[[ -z "$rate" ]] && return 0
|
[[ -z "$rate" ]] && return 0
|
||||||
pending_set CUSTOM_REFRESH_RATES "$rate"
|
|
||||||
|
# gamescope-session-plus passes this env value to gamescope as
|
||||||
|
# --custom-refresh-rates, which is a list of *switchable* rates the user can
|
||||||
|
# cycle between in Steam Big Picture. Writing a single value (e.g. "165") can
|
||||||
|
# leave gamescope without a safe 60 Hz fallback if the monitor's EDID
|
||||||
|
# preferred mode is 60 Hz and the high-rate mode isn't enumerated on first
|
||||||
|
# launch — most visibly on NVIDIA HDMI outputs. Always include 60 as the
|
||||||
|
# floor so Steam can fall back and the user can switch up to their pick.
|
||||||
|
local rate_list="$rate"
|
||||||
|
[[ "$rate" != "60" ]] && rate_list="60,${rate}"
|
||||||
|
pending_set CUSTOM_REFRESH_RATES "$rate_list"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Keys this menu owns. Cleared at the start of every selection so switching
|
# Keys this menu owns. Cleared at the start of every selection so switching
|
||||||
|
|
@ -526,6 +555,11 @@ confirm_risky_save() {
|
||||||
w=$(effective SCREEN_WIDTH)
|
w=$(effective SCREEN_WIDTH)
|
||||||
h=$(effective SCREEN_HEIGHT)
|
h=$(effective SCREEN_HEIGHT)
|
||||||
rate=$(effective CUSTOM_REFRESH_RATES)
|
rate=$(effective CUSTOM_REFRESH_RATES)
|
||||||
|
# Check the user's actual pick (highest of the comma list) against monitor
|
||||||
|
# support — not the bare list, which won't match a single mode line.
|
||||||
|
if [[ "$rate" == *,* ]]; then
|
||||||
|
rate=$(tr ',' '\n' <<<"$rate" | sort -nr | head -1)
|
||||||
|
fi
|
||||||
|
|
||||||
local -a warnings=()
|
local -a warnings=()
|
||||||
if [[ -n "$w" && -n "$h" ]] && ! resolution_supported "$w" "$h"; then
|
if [[ -n "$w" && -n "$h" ]] && ! resolution_supported "$w" "$h"; then
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,7 @@ set -Euo pipefail
|
||||||
# -u: Treat unset variables as errors (catches typos in variable names)
|
# -u: Treat unset variables as errors (catches typos in variable names)
|
||||||
# -o pipefail: A pipeline fails if ANY command in it fails, not just the last one
|
# -o pipefail: A pipeline fails if ANY command in it fails, not just the last one
|
||||||
|
|
||||||
DECKSHIFT_VERSION="0.1.7"
|
DECKSHIFT_VERSION="0.1.8"
|
||||||
|
|
||||||
# Resolve the directory this script lives in so we can find sibling files like
|
# Resolve the directory this script lives in so we can find sibling files like
|
||||||
# bin/deckshift-settings and applications/deckshift-settings.desktop when
|
# bin/deckshift-settings and applications/deckshift-settings.desktop when
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue