lite-game-center (8.0-0010-linuxlite) hematite; urgency=medium

  * Fixed: clicking "Switch back to PulseAudio" on the PipeWire tile
    when PipeWire is already active was firing switch-to-pipewire again
    (the install verb was captured at construction by a lambda, before
    the tile could know it was in the applied state). Added a per-spec
    "verb_when_applied" field — primary button now fires the reverse
    verb on toggle tiles when already applied. Tile-by-verb registry
    also tracks the alt verb so the INSTALLING badge appears in both
    directions.

  * PipeWire verb's end-of-run log clarified — was "Audio may glitch
    briefly while apps reconnect" (which understates it); now tells the
    user the cleanest path is log out + log back in (no reboot needed),
    and explicitly names the apps likely to need a manual restart.

  * Pick-your-stack grid relaid as a single 1×3 row to match the new
    tile count (was 2×2 with one empty slot after the ProtonPlus drop).
    Same divmod-style attach as the Tweaks row right below it; visually
    symmetric now.

  * Dropped the "Steam + ProtonPlus" tile (2026-05-15, in-place edit).
    ProtonPlus is still useful for power users who want a GUI to pin
    multiple Proton versions per game, but on real-world testing the
    app proved too buggy and not yet mature enough to be a "click and
    walk away" tile alongside Steam + Proton-GE. We don't want a
    flagship one-click tile that lands users on something unstable —
    that's the opposite of what Lite Game Center is for. The
    protonplus deb remains in hematite/main for users who explicitly
    want it via `apt install protonplus`; we've just removed the
    in-app surfacing. Full Setup no longer installs it. Pick-your-
    stack drops from a 2×2 grid to a 1×3 row. Status strip drops the
    ProtonPlus pill. Verbs install-steam-protonplus and remove-
    steam-protonplus are gone from the helper. Suggests: protonplus
    removed from DEBIAN/control. No version bump.

  * System Gaming Tweaks: added xone-dongle-firmware to the bundle so
    Xbox Wireless Adapter (2.4 GHz dongle) users get the Microsoft-
    signed firmware blobs the xone driver needs. The package's postinst
    fetches from catalog.s.download.windowsupdate.com at install time
    (subject to Microsoft's Terms of Use), SHA-256-verifies every blob,
    and is idempotent + network-failure-non-fatal. We surface a multi-
    line heads-up in the log BEFORE the install kicks off so the user
    understands what's about to happen — same "no surprises" pattern
    as the PipeWire-swap tile's "What changes" callout. The package
    only matters to Xbox Wireless Adapter dongle owners; BT and
    USB-wired Xbox controller users see the heads-up, get the
    one-MB-or-so install, and never use the firmware.

  * System Gaming Tweaks tile gains a controller + mouse driver
    bundle. The xpadneo-dkms install was generalised into a new
    `apt_install_optional` helper that pre-checks `apt-cache show`
    and prints a one-line "what this covers" note in the log. Now
    installs (or skips cleanly if not in the active repo):
      - xpadneo-dkms — Xbox One/Series/Elite over Bluetooth
      - xone-dkms    — Xbox One/Series over USB + 2.4 GHz dongle
      - dualsensectl — PS5 DualSense LED, mic, adaptive triggers
      - steam-devices — udev rules for non-Steam controller access
      - piper        — GTK4 GUI for gaming mouse DPI/buttons/RGB
                       (Logitech G, SteelSeries, ROCCAT etc. via
                       libratbag)
    The tile's "Includes" pill row and tagline are updated to surface
    all five so users can see what's in the bundle. Featured Full
    Setup's pill row likewise updated.

  * Helper: Full Setup's NVIDIA Gaming Tweaks gate is now consistent
    with the standalone tile's `requires_check`. Previously the verb
    used `lspci | grep NVIDIA Corporation` (just card presence), so
    Pascal/Maxwell/Kepler machines running Nouveau/NVK would still
    get the __GL_* env-var configs written despite the env vars being
    silent no-ops without the proprietary driver. Now gated on
    `nvidia-smi --query-gpu=driver_version` succeeding — same check
    the GUI tile uses. When proprietary isn't loaded, the verb logs
    "(NVIDIA Gaming Tweaks skipped — proprietary NVIDIA driver not
    loaded; the __GL_* env vars would be no-ops here.)" and moves on.

  * Helper: System Gaming Tweaks tile pre-checks `apt-cache show
    xpadneo-dkms` before attempting install, so machines where the
    package isn't in repos (resolute's main archive doesn't include
    it as of 2026-05-15) skip cleanly with a clear "not in repos on
    this release" note instead of generating two lines of "E: Package
    'xpadneo-dkms' has no installation candidate" log spam. When
    xpadneo-dkms eventually lands in hematite/main, the tile picks
    it up automatically with no Game Center change needed.

  * Progress dialog: log auto-scroll fixed. GTK4's scroll_to_iter() on
    a freshly-inserted line races the TextView's layout — by the time
    the call lands the new line's geometry isn't computed, so the
    scroll silently no-ops. Replaced with the "ScrolledWindow vadj
    changed" pattern: a connect-once handler on the vertical
    adjustment's `changed` signal pins the value to upper - page_size
    whenever the inner TextView's size grows, which is exactly what
    happens on every new insert. Reliable across GTK 4.10 → 4.22+.
    Also wired `value-changed` so manual user-scrolls upward (32 px
    slack from the bottom) flip sticky-bottom off — you can read older
    output without being yanked back, then scroll to the bottom again
    to re-engage tail mode.

  * Persistent install log at ~/.local/share/lite-gamecenter/install.log.
    The footer originally claimed this path existed; it didn't — the
    log was only ever in the live ProgressWindow's TextView, which
    died with the dialog. Now the helper appends every session to the
    file: a "===  ISO-timestamp  verb=...  user=..." header, followed
    by all the helper status lines AND raw apt output (`exec > >(tee
    -a "$LOG_FILE")` at the top of the script, after pkexec env
    parsing). Log file is created if missing and chowned to the
    target user; everything is best-effort so a write-failure on a
    weird mount doesn't break installs.

  * "Open Log" button added in two places:
      1. Main window header bar (between the refresh button and the
         brand label) — text-x-generic-symbolic icon with the full
         path as tooltip.
      2. Progress dialog action row — labelled "Open Log", next to
         "Copy to clipboard".
    Both call xdg-open on the log path so the user's preferred .txt
    handler (Mousepad / gedit / VSCode / etc.) is respected. The path
    is pre-created with a friendly placeholder header on first click
    so the button works before any install has run.

  * Helper: Lutris + Wine-GE verb no longer apt-installs wine-staging
    (E: Package 'wine-staging' has no installation candidate on
    resolute). The package was dropped from Ubuntu's main archive
    during the WoW64 transition and now only lives in the WineHQ
    third-party repo. We deliberately do NOT add WineHQ — Wine-GE
    (downloaded as a tarball into ~/.local/share/lutris/runners/wine/
    a few lines later) is the only Wine that Lutris uses for games
    anyway, so the package-level wine-staging was vestigial scaffolding
    from a noble-era assumption. winetricks is now also best-effort:
    if it's not in the repos on this release, the tile logs a note
    and continues. The system 'wine' package is irrelevant to
    Lutris-managed prefixes.

  * Helper: Full Setup verb now treats Lutris failure as non-fatal
    (same as ProtonPlus) — a Wine-GE tarball glitch or transient
    GitHub-API hiccup no longer aborts the System Tweaks step that
    follows. The user gets "(Lutris skipped — see message above)"
    plus all the tweaks they asked for.

  * Helper: GE-Proton / Wine-GE tarball extract was failing on
    `tar: ...: Cannot open: Permission denied` because mktemp -d
    creates a 0700 directory owned by root, and we drop privilege to
    $TARGET_USER for the extract — the user couldn't traverse into
    the root-owned tmpdir to read the (root-then-chowned) tarball.
    Fix: `chmod 755 "$tmpdir"` after mktemp so the as_user step can
    reach the tarball. Tarball itself stays root-owned until chowned.

  * Progress dialog: forced libadwaita to use FORCE_DARK colour scheme
    at app activate so the dialog's HeaderBar title, AlertDialog text
    and any other unstyled-by-us widgets don't render dark-on-dark in
    sessions where Adwaita defaults to light. All dialog labels +
    HeaderBar title + Close button are now explicitly brand-blue
    (#5BA8E8) via the .lgc-prog-window CSS scope. Progress bar fill
    is now a brand blue→purple gradient matching the Full Setup
    featured tile, instead of the default orange.

  * Progress dialog: added a "Copy to clipboard" button next to Close
    (always enabled, not gated on completion — users can grab partial
    output during long installs or apparent hangs for support
    threads). Copies the entire log preceded by a 4-line header
    showing the dialog's title + subtitle so the receiving forum/bug-
    report reader gets context, not just an apt fragment. Button
    flashes "Copied ✓" for 1.2s as confirmation.

  * Progress dialog: indeterminate pulse replaced with real download
    progress driven by apt's APT::Status-Fd structured status stream.
    Helper runs `apt-get install -o APT::Status-Fd=3 ...` with fd 3
    piped to a process-substitution `sed` that tags each status line
    with @@PROG@@; the GUI's append_line() filters those out of the
    visible log and routes them to a new _handle_apt_progress() parser
    that recognises both dlstatus (overall download %) and pmstatus
    (per-package install) lines.
  * Title line shows e.g. "Downloading  ·  47.3%  ·  12.4 MB/s" during
    the download phase. MB/s is synthesised from apt's "Need to get
    X MB" line (regex-sniffed off regular stdout) combined with the
    dlstatus percent and a monotonic-time download-start anchor —
    accurate to within a second or two without needing apt to emit
    bytes/sec itself.
  * Once the first pmstatus event arrives, bar locks at 100% and the
    title narrates "Installing  ·  <pkg>" per package — pmstatus's
    per-package percent doesn't map cleanly onto overall progress and
    a jumping bar would mislead.

  * Progress dialog: log text bumped from #c5cdd6/11px to #e8eef3/12px
    for clearly readable contrast on the dark surface, plus 14px
    padding for breathing room. Per-line TextTag colour-coding so the
    eye picks out structure inside a wall of dpkg output:
       blue+bold  → helper status ("→" steps, "==" headings)
       green+bold → "✓" success ticks
       red+bold   → ERROR / FAILED / "E:" apt errors
       amber      → apt's "Get:/Hit:/Ign:/Fetched" download markers
       dim grey   → apt's "Unpacking / Setting up / Preparing" phase
    Auto-scroll switched from scroll_mark_onscreen() (unreliable —
    cursor mark wasn't always at end after insert) to scroll_to_iter()
    on a freshly-fetched end iter; latest line is always visible.

  * Helper: Steam Essentials verb now prints an up-front heads-up
    explaining the ~1-minute quiet period during the 350 MB
    steam-launcher download from Valve's CDN. apt's download phase
    only emits one Get: line for a single large package then nothing
    until done — the heads-up sets expectations so users don't think
    the install has hung.

  * .desktop: GenericName changed from "Gaming setup" to the brand
    name "Lite Game Center" — matches the lite-software-sources
    convention. Name + GenericName + Comment expanded from 9 locales
    to the full LL standard 22-locale set (af/ar/de/es/fa/fi/fr/he/hi/
    hr/it/ja/ko/nl/pl/pt/pt_BR/ru/sr/sv/uk/zh_CN). Brand name is
    rendered in the local script where idiomatic (e.g. ライトゲームセンター
    in ja, 라이트 게임 센터 in ko, 精简游戏中心 in zh_CN) rather than the
    less-helpful "leave it as English" treatment we had on the 9-locale
    set.

  * Status pill strip: replaced libadwaita's .card class (which renders
    white in light contexts and washed out the pills against it) with
    our own .lgc-status-strip dark surface (#161b22 + #2d3741 border).
    Each pill now also carries a soft state-coloured glow (12-14px
    box-shadow): green for OK pills, amber for warn pills, dim grey for
    missing, soft blue for default. Gives the strip readable contrast
    on the dark page and lifts the pills off the surface so they don't
    look flat.

  * NVIDIA Gaming Tweaks tile now greys out on machines without the
    proprietary NVIDIA driver (e.g. a GTX 1070 on resolute running
    Nouveau/NVK, where the __GL_* env vars would be silent no-ops).
    Status row shows "REQUIREMENT NOT MET", Install button is disabled
    with the label "Requires NVIDIA proprietary driver". Detection is
    `nvidia-smi --query-gpu=driver_version`-succeeded (i.e. the
    proprietary userspace is loaded), not just lspci-sees-NVIDIA.
    Architecturally added as a generic `requires_check(state)` hook on
    the tile spec so future tiles can express their own preconditions
    the same way.

  * Initial build. Python 3 + GTK 4 + libadwaita single-window app at
    /usr/bin/lite-game-center, branded with lite-gamecenter (menu icon)
    and lite_game_center_app_logo.svg (in-app hero).
  * One Featured tile ("The Full Setup") + 7 modular tiles split into
    two sections:
      - Pick your stack (2×2 grid): Steam Essentials, Steam + Proton-GE,
        Steam + ProtonPlus, Lutris + Wine-GE.
      - Tweaks & Optimisations (3×1 row): NVIDIA Gaming Tweaks, System
        Gaming Tweaks, Switch to PipeWire (Audio).
  * Live status strip at top — Steam, Vulkan, Proton-GE, ProtonPlus,
    Lutris, NVIDIA driver (conditional), Audio server, Running kernel.
  * Kernel CTA chip — only renders when uname -r isn't linuxlite-gaming;
    links straight into Lite Kernel Manager.
  * pkexec helper at /usr/lib/lite-game-center/lite-game-center-helper.
    auth_admin_keep so multi-step verbs (Full Setup) prompt once. Verbs
    are allowlisted in the dispatcher; no shell-out from helper to
    untrusted strings.
  * Per-user filesystem work (GE-Proton + Wine-GE tarball extracts into
    ~/.steam/ and ~/.local/share/lutris/) goes through `runuser -u
    $LITE_GAMECENTER_USER` so root never owns user files.
  * Every install verb has a paired remove-* verb. Removals are
    deliberately conservative (don't strip xpadneo-dkms while a
    controller might be using it; keep Vulkan; keep GameMode).
  * Ships config drop-ins for sysctl, ulimits, MangoHud preset,
    GameMode tuning, PulseAudio low-latency, PipeWire low-latency, and
    NVIDIA env vars at /usr/share/lite-game-center/configs/.
  * Audio-server swap (PipeWire) is opt-in via its own tile with an
    inline "What changes" disclosure listing the 2 s audio gap, the
    reversibility path, and the JACK/Bluetooth heads-up.
  * No Snap, no Flatpak. ProtonPlus is staged for a forthcoming
    hematite/main .deb; the tile will surface a clear error until that
    package lands in the repo.

 -- Jerry Bezencon <valtam@linuxliteos.com>  Fri, 15 May 2026 20:00:00 +1200
