Commit graph

11 commits

Author SHA1 Message Date
d45f81be36 v0.1.13 — pacman hook keeps gamescope cap_sys_nice across upgrades
File capabilities live on the inode as a security.capability xattr, so
pacman drops cap_sys_nice every time it replaces /usr/bin/gamescope on
upgrade. Performance mode silently regresses (worse frame pacing / input
latency) with no error surfaced.

Installer now drops /usr/share/libalpm/hooks/deckshift-gamescope-cap.hook,
which re-applies cap_sys_nice=eip PostTransaction whenever gamescope is
installed or upgraded. Idempotent; prompted once at install time alongside
the existing cap_sys_nice grant prompt.
2026-05-19 18:03:32 +01:00
a3cb6f28e4 v0.1.12 — Patch gamescope-session-plus so refresh-rate selection actually reaches gamescope
The real bug behind every "60 Hz stuck in Gaming Mode" report:

  - DeckShift installs `gamescope` from Arch's `extra` repo (upstream
    Valve binary). That binary does NOT have `--custom-refresh-rates`.
    The flag is a ChimeraOS-fork (`gamescope-plus`) addition that
    never landed upstream, and the fork is not packaged in AUR for
    64-bit Arch.

  - The AUR `gamescope-session-git` script (OpenGamingCollective,
    ex-ChimeraOS) was written assuming gamescope-plus. It feature-
    detects via `gamescope_has_option "--custom-refresh-rates"` and
    silently drops the value when missing.

  - Net effect: CUSTOM_REFRESH_RATES from the env conf reaches the
    session script but never reaches the gamescope binary. Every
    refresh-rate selection in the DeckShift TUI since the project
    began has been a paper fix; gamescope just launched at the
    EDID-preferred mode (usually 60 Hz).

  - v0.1.8's comma-list "fix" was correct on paper but the value
    never reached the binary, so it didn't actually do anything on
    Omarchy. The Framework Desktop user wasn't reporting a hardware-
    specific bug — they were the first user to notice a bug that
    affected everyone, because their 170 Hz monitor made the regression
    obvious. On a 165 Hz Acer Nitro you'd just never notice 60 vs 165
    in Steam BPM.

Fix: ./deckshift.sh now patches the installed gamescope-session-plus
in place, adding an elif fallback that uses `--nested-refresh` (a flag
present in every gamescope version) with the highest value from the
CUSTOM_REFRESH_RATES list as the launch rate. Marked with a
DECKSHIFT-NESTED-REFRESH-FALLBACK sentinel comment for idempotency,
re-applied on every install so AUR upgrades that clobber the file
don't silently regress refresh-rate handling.

Implementation: new patch_gamescope_session_plus() function in
deckshift.sh, called from setup_session_switching() after the AUR
install completes. Uses Python regex with a function-based replacement
(re.sub with a string-form replacement was the first attempt and got
caught by Python's backslash processing turning `\n` in the `tr`
argument into a real newline — function callbacks bypass that, so the
literal `\n` reaches the shell as intended).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 19:38:33 +01:00
52c883b780 v0.1.11 — Multi-monitor handling: disable an auxiliary monitor before Gaming Mode
Reported on a Framework Desktop (AMD AI MAX 380) + Gigabyte M27Q +
LG DualUp setup: with both monitors attached, gamescope would either
land on the wrong screen or refuse to start, and writing
OUTPUT_CONNECTOR=DP-X alone wasn't enough to fix it. The workaround
shipped by the user was to manually patch /usr/share/gamescope-session-plus
to disable the other monitor before launching gamescope.

DeckShift now handles this natively, without touching the
gamescope-session-plus script (which is ChimeraOS's, not ours):

- New env var OUTPUT_CONNECTOR_TO_DISABLE (single connector or
  comma list) written to ~/.config/environment.d/gamescope-session-plus.conf
  alongside the other display keys.

- switch-to-gaming reads it and runs `hyprctl keyword monitor X,disable`
  for each listed connector BEFORE the SDDM restart, while Hyprland is
  still alive (hyprctl needs a live IPC socket). The disable is
  runtime-only — Hyprland's static config isn't touched — so when the
  user returns from Gaming Mode the new Hyprland reads its config fresh
  and the monitor comes back automatically. No re-enable step needed.

- Settings TUI exposes this as a "Hide monitor" main-menu item. The
  picker lists every connected monitor EXCEPT the gaming one (so a
  user can't accidentally pick the same connector they just set as
  OUTPUT_CONNECTOR) and includes a "(clear)" entry.

Also fixes a latent bug in v0.1.10's config-path shortening:
${CONF/#$HOME/~} was supposed to render the conf path with ~ but
bash applies tilde-expansion to the replacement side, re-expanding ~
to $HOME and making the substitution a no-op. Escaped as \~ now.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 19:12:42 +01:00
aaa2f3d768 v0.1.10 — Settings TUI layout polish
Banner, state panel, menu header, and menu items now share a single centred
panel column rather than each block centring itself independently. The TUI
feels visibly aligned in a Walker floating window of any width — no more
drifting elements off to the left while the menu floats to the right.

- Adaptive panel width: min(COLS − 6, 60), floored at 40.
- Terminal-width detection: `stty size </dev/tty` first (kernel-reported,
  always reflects the live window) with `tput cols`/80 fallback. Fixes
  off-centre rendering in freshly-spawned floating terminals whose terminfo
  hasn't caught up to the compositor's actual size yet.
- Config-file path renders as `~/...` instead of `/home/<user>/...` so it
  fits the panel.
- Unset resolution shows `<auto>` instead of `?x?` (matches the other unset
  placeholders).

Internally: `pad_block` replaces `center_block`'s widest-line-centres-block
behaviour with a single shared left margin; `cmenu` left-aligns the menu
at the panel edge so the `> ` cursor sits in the same column as the state
panel's section headers above.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 19:01:07 +01:00
3131dcab8f v0.1.9 — auto-migrate legacy CUSTOM_REFRESH_RATES on installer re-run
Pre-v0.1.8 users have a scalar CUSTOM_REFRESH_RATES=<rate> in their
gamescope-session-plus.conf that triggers the 60 Hz launch bug. v0.1.8
only fixed the TUI write path, so existing users had to re-open the TUI
and re-pick the rate to migrate. Installer now detects the legacy
scalar format and rewrites to the comma list (60,<rate>) on re-run,
then imports the new value into the running systemd user environment.
Idempotent — already-migrated configs are left alone.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 20:15:24 +01:00
4fa77a6238 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>
2026-05-17 20:11:19 +01:00
e54f45723f docs: README updates for v0.1.4–v0.1.6
- 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>
2026-05-12 21:02:51 +01:00
49046c4444 fix: restore xdg-desktop-portal after returning from Gaming Mode
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>
2026-05-09 22:11:10 +01:00
14258adba0 docs: add demo video to README
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 15:33:47 +01:00
449fd4b7a9 docs: README rewrite for v0.1.2/v0.1.3
- 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.
2026-05-06 21:08:34 +01:00
ae01a2b32f Initial commit — DeckShift v0.1.0
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>
2026-05-05 19:54:52 +01:00