- Bump banner version 0.1.3 → 0.1.6.
- Drop the "moving toward distro-portability" / "cross-distro is the
next direction" notes — DeckShift is Omarchy-only.
- Add What's New entries for v0.1.4 (portal-recovery race fix),
v0.1.5 (clipboard via Walker restart), v0.1.6 (Omarchy-only cleanup).
- Combine the screen-sharing and clipboard symptoms into a single
troubleshooting block (same root cause) and replace the old racy
manual-restart command with `touch /tmp/.deckshift-just-returned
&& /usr/local/bin/deckshift-portal-recovery`, with a note explaining
why the marker is required.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
DeckShift targets Omarchy only — the fallback added in 74b1a5b was
unnecessary defensive coding. Helper now just calls
omarchy-restart-walker directly. Also updated the file header to
remove the stale "distro-portability is the next direction" note.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
After v0.1.4 fixed the portal race, a user reported that the clipboard
also broke after returning from Gaming Mode. Symptom: paste does
nothing, Walker's clipboard history is empty.
Same root cause as the portal stack: Walker's elephant backend holds
the wl-clipboard listener, which is bound to the dead Hyprland's
Wayland socket after the SDDM restart. Fixed by appending a Walker
restart to deckshift-portal-recovery, using the existing
omarchy-restart-walker helper when present and falling back to direct
systemctl --user restart of elephant.service +
app-walker@autostart.service when not (keeps the helper portable for
the planned non-Omarchy targets).
Reported and validated by the same user as the v0.1.4 fix.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The previous portal-recovery helper restarted xdg-desktop-portal-hyprland,
xdg-desktop-portal, pipewire, pipewire-pulse, and wireplumber in a single
systemctl --user restart call. That introduced a race where the portals
could come back up before wireplumber had finished rebuilding the node
graph, so the screencast portal would bind to nothing and "Share desktop"
would silently fail intermittently.
Reported by a user on the issue tracker: the cure is to (1) push the
live session env into D-Bus + systemd --user so D-Bus-activated portals
target the new Wayland socket, (2) stop portals first, (3) kill any
gamescope-era zombies (SIGTERM then SIGKILL for stragglers — SIGKILL
alone leaves stale D-Bus name registrations), (4) restart the pipewire
stack and wait for wireplumber, (5) bring portals back up last.
The exec-once marker guard and the initial 2s sleep are preserved so
this stays a no-op on normal logins and so the env-import sees a
populated WAYLAND_DISPLAY.
Bumps DECKSHIFT_VERSION from the stale 0.1.1 string in the file (last
shipped tag is 0.1.3) to 0.1.4.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Chromium/Firefox "Share desktop" / "Share window" silently broke after
the SDDM-restart cycle: xdg-desktop-portal-hyprland stays bound to the
killed Hyprland instance, so the new compositor's screencasts get no
frames. Tab sharing kept working because Chromium captures tabs
internally, bypassing the portal.
switch-to-desktop now drops /tmp/.deckshift-just-returned before the
SDDM restart. A new helper (/usr/local/bin/deckshift-portal-recovery),
exec-once'd from ~/.config/hypr/autostart.conf, checks for that marker
on every Hyprland start and bounces the portal + pipewire user services
when present. No marker = no-op.
README troubleshooting updated with both this and the suspend-access
fix from the previous commit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
switch-to-gaming masks sleep/suspend/hibernate targets with --runtime
(symlinks in /run/systemd/system/). switch-to-desktop's plain `unmask`
plus a missing daemon-reload left logind's CanSuspend cache stale, so
`systemctl suspend` returned polkit "Access denied" back on desktop.
Add the --runtime unmask and a daemon-reload, plus matching NOPASSWD
sudoers entries so the desktop-side script can actually run them.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Bump header to v0.1.3
- Restructured "What's New" with v0.1.3, v0.1.2, and v0.1.1/v0.1.0 sections
- Settings TUI table now lists both [hybrid-nvidia] and [hybrid-amd] options
- New top-level "Recovery from a Black Screen" section with TTY-fallback
commands (loginctl terminate-user, systemctl restart sddm)
- "Performance Mode" section explains the saved-state save/restore and the
Omarchy + AC caveat (omarchy-powerprofiles-init re-applies performance on
every Hyprland session start when plugged in)
- New "Hybrid laptop note" under NVIDIA-Specific Notes explaining why
direct-NVIDIA mode black-screens on eDP-1 and pointing to [hybrid-nvidia]
- Configuration section clarifies the installer no longer writes display
keys — those are owned exclusively by the Settings TUI
- Updated "What Gets Installed" with gum/jq deps and saved-state file
- Updated Uninstalling section to cover ~/.cache/deckshift, polkit reload,
etc.
Symptom: after exiting Gaming Mode (Super+Shift+R or Steam→Power→Switch
to Desktop) the laptop stayed pinned at CPU governor=performance and
power profile=performance until manually reset. Drained battery, ran hot.
Root causes:
- The wrapper's trap-based restore raced with `systemctl restart sddm`
in switch-to-desktop. SDDM teardown could SIGKILL the wrapper before
`restore_balanced_mode` finished its writes.
- restore_balanced_mode hardcoded "powersave" / "balanced" — wrong on
systems whose default is schedutil or power-saver.
- powerprofilesctl was called without sudo and without a polkit auth
rule, so it silently failed when the session had no auth agent.
Fix:
- On entry, gamescope-session-nm-wrapper writes the user's actual
pre-Gaming-Mode CPU governor + power profile to ~/.cache/deckshift/
saved-state.
- On exit, switch-to-desktop reads that file FIRST (synchronous, before
any pkill / sddm-restart) and applies the restore. Wrapper's trap
still runs as a backup.
- Restore reads from the saved-state file rather than guessing.
- powerprofilesctl is now invoked via `sudo -n` and added to the
NOPASSWD allowlist (%video ALL=(ALL) NOPASSWD: powerprofilesctl set *)
so the call always succeeds without a polkit prompt.
Verified on Acer Nitro (AMD APU + NVIDIA hybrid):
Before: stuck at performance/performance after exit.
After: back to powersave/balanced on Switch-to-Desktop, both via the
synchronous restore in switch-to-desktop and the wrapper trap.
Settings TUI (bin/deckshift-settings):
- Don't crash when the saved OUTPUT_CONNECTOR is no longer plugged in
(stale connector → empty mode list → grep + pipefail killed the script)
- Add [hybrid-nvidia] GPU mode for NVIDIA dGPU + AMD/Intel iGPU laptops:
sets __NV_PRIME_RENDER_OFFLOAD / __VK_LAYER_NV_optimus / __GLX_VENDOR_LIBRARY_NAME
so games inside gamescope render on NVIDIA while gamescope itself runs on
the iGPU (necessary on hybrid laptops where eDP is wired to the iGPU)
- Add [hybrid-amd] GPU mode for AMD dGPU + AMD/Intel iGPU laptops: sub-menu
to pick the dGPU, then sets DRI_PRIME + MESA_VK_DEVICE_SELECT
- Single GPU-mode line in the status panel covering all five states
(auto / NVIDIA direct / AMD direct / hybrid-nvidia / hybrid-amd)
- Switch GPU selection to clear-then-set so mode-switching never leaves
stale flags behind
Installer (deckshift.sh):
- Drop monitor / resolution / refresh selection from the installer entirely;
display keys are owned by the TUI now. Avoids stale OUTPUT_CONNECTOR
values when the configured display is later unplugged
- Switch gamescope-session-plus.conf writer from heredoc-overwrite to
per-key set/unset (sed-based, mirrors flush_pending in the TUI) so the
installer is idempotent and re-runs preserve user-set display values
- Strip stale opposite-GPU keys when re-running on a changed GPU
(e.g. NVIDIA → AMD swap clears VULKAN_ADAPTER / GBM_BACKEND)
- Fix switch-to-desktop: replace racy `stop sddm` + disowned `start sddm`
with a single atomic `systemctl restart sddm`. The disowned start was
getting killed by user-session teardown before SDDM came back up,
leaving the user on a black screen after Super+Shift+R
Two issues found during first-run-machine test:
- Steam was installed but never auto-launched, so the first-run client
update never happened — Gaming Mode failed to enter Big Picture
cleanly. Now follows omarchy-install-gaming-steam's pattern: setsid
gtk-launch steam &, disown, runs in parallel with the rest of the
install.
- Walker didn't pick up the deckshift-settings.desktop entry until the
next manual elephant restart. setup_settings_tui now calls
omarchy-restart-walker after update-desktop-database, which restarts
elephant.service + the walker autostart unit.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Steam Deck-style gaming mode for Linux + Hyprland. Lineage:
Super-Shift-S-Omarchy-Deck-Mode → Omarchy Deck → DeckShift (renamed for
distro-portability — distro-agnostic features on the roadmap).
Currently targets Omarchy (Arch + Hyprland + SDDM + iwd). Includes:
- Press Super+Shift+S to enter Gaming Mode (Gamescope + Steam Big
Picture), Super+Shift+R to return to desktop
- NVIDIA GSP-aware driver branch selection (legacy nvidia-580xx-utils
for Maxwell/Pascal/Volta cards)
- AMD support (vulkan-radeon, libvdpau)
- Intel support (vulkan-intel, intel-media-driver) with generation-aware
performance warning before continuing
- Idempotent package installs via Omarchy's omarchy-pkg-add
- Optional Xbox Bluetooth controller support (xpadneo-dkms)
- Settings TUI launched from Walker (deckshift-settings) for adjusting
monitor / GPU / resolution / refresh rate after install:
* Buffered changes — explicit Save and exit / Cancel
* hyprctl-based mode detection with monitor-capability filtering
* Save-time warning if values exceed monitor capability
* Esc returns to main menu without crashing
- Multilib check removed (Omarchy ships with multilib enabled)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>