Skip to content

Releases: jfreed-dev/niri-screensaver

v0.6.1

03 Jun 21:17
8eeb28d

Choose a tag to compare

Added

  • Bats unit tests + kcov coverage. A test/ suite asserts the bash scripts'
    pure functions — effect-arg building, load_config defaulting, logo
    resolution/picking, toggle state, the kill-debounce (#4), battery gating, and
    mirror-mode argument assembly. Both bin scripts now guard main "$@" so they
    can be sourced for testing. A new CI job runs the suite under kcov and
    uploads line coverage to Codecov; make unit and make coverage run it
    locally (both skip with a hint when the tool is missing, same as the linters).

Changed

  • Security and dev docs refreshed. SECURITY.md now lists 0.6.x as
    supported (was 0.3.x) and documents the CI gates that guard the codebase.
    TESTING.md and LINTING.md cover the new unit suite and the coverage job.

v0.6.0

03 Jun 19:50

Choose a tag to compare

Added

  • Multi-monitor mode: independent (default) or mirror. New
    MULTI_MONITOR_MODE config key. independent keeps the existing behavior —
    each output runs its own driver and randomizes its own effect/logo. mirror
    makes every output show the same effect: the launcher rolls one RNG seed
    (and, when RANDOM_LOGO is on, picks one shared logo) and passes them to every
    driver via argv (--seed/--logo), since niri msg action spawn runs in the
    compositor's environment and would not inherit exported vars. Each driver seeds
    tte with SEED + window, where window = wall-clock-seconds / MIRROR_INTERVAL
    (default 8s) — deriving the effect window from the shared wall clock, not a
    per-process counter, is what keeps the monitors on the same effect at the
    same time even though the surfaces spawn at different moments and animate for
    different durations. tte's deterministic RNG then renders identical
    animations on matched-resolution monitors; it degrades to "same effect,
    different layout" when resolutions differ. Surfaced in the Noctalia plugin as a
    Multi-monitor mode dropdown in the Effects section. Only applies with more
    than one output; single-monitor setups are unaffected.
  • Bar widget: left-click is now a smart toggle. Clicking the Noctalia bar
    widget previously always launched the screensaver; it now stops it if it's
    already running and launches it otherwise, so it no longer has to be killed
    from a menu or the CLI. Backed by a new quiet niri-screensaver-launch is-running command (exit 0 if running, 1 if not; also forwarded by
    niri-screensaver-ctl) that the widget probes on click. Right-click still
    opens the full Trigger / Stop / Toggle / Settings menu.
  • Bar widget: Quit and Reload menu items. The right-click menu gains
    Quit (stop the screensaver and disable it, so idle won't relaunch it
    until re-enabled) and Reload (stop the screensaver, restart the Noctalia
    shell so the systray reappears, and leave the screensaver enabled — a one-shot
    fresh start, run detached so it survives qs kill).

Fixed

  • Multi-monitor: surfaces no longer collapse onto one output under
    focus-follows-mouse.
    niri-screensaver-launch previously spread one
    Alacritty per output by cycling keyboard focus
    (niri msg action focus-monitor-next) between spawns. With niri's
    input { focus-follows-mouse }, window placement follows the pointer, not
    keyboard focus, and the pointer isn't parked until after the spawn loop — so
    every surface opened on the cursor's monitor and the others stayed blank. The
    launcher now enumerates outputs once up front and pins each spawned surface to
    its target output by window id
    (niri msg action move-window-to-monitor --id <id> <output>), which is
    independent of pointer/keyboard focus. Outputs are enumerated a single time so
    N>2 monitors and mid-launch hotplug are handled deterministically. A new
    NIRI_SCREENSAVER_SPAWN_PIN_TIMEOUT_SECS env var (default 2) bounds how long
    the launcher waits for each surface to appear before moving on. Thanks to
    @landryjeanluc for the report and root-cause analysis (#11).
  • Multi-monitor: dismissing one screen now wakes all of them. Each output
    runs its own driver in its own terminal, and a keypress only reaches the
    focused one — so on a multi-monitor setup, dismissing the active screen left
    the others still running the screensaver. The driver now broadcasts a
    terminate to its sibling instances on dismiss (dismiss_all
    terminate_sibling_drivers, which SIGTERMs the other niri-screensaver run
    processes via a /proc scan that skips its own PID). Siblings exit through
    the normal signal path and do not re-broadcast, so there is no signal storm.
    Surfaced once #11's fix made surfaces actually spread across outputs.

v0.5.9

22 May 23:41
3bf4514

Choose a tag to compare

Fixed

  • A white cursor block briefly flashed at the end of each effect, just before
    the screensaver transitioned to the next one. tte re-shows the terminal
    cursor when an effect finishes, undoing our tput civis, and it lingered
    until the next loop iteration re-hid it. The driver now passes
    --no-restore-cursor to tte (when supported and CURSOR_HIDE is on) so the
    cursor stays hidden across the whole run.

v0.5.8

21 May 17:24

Choose a tag to compare

Added

  • Sleep-on-battery threshold. New BATTERY_MIN_PERCENT config key
    (default 0 = disabled). When set, niri-screensaver-launch skips
    auto-launch if the machine is running on battery below that percentage,
    to save power. Plugged in (any AC/Mains adapter online) or no battery
    present (desktop) never skips; launch force overrides the check.
    Surfaced in the Noctalia plugin as a new Power settings section
    ("Skip on battery below %"), and reported in niri-screensaver-ctl status when enabled. Battery state is read from
    /sys/class/power_supply/* by type (so adapter/battery naming is
    irrelevant); multiple batteries use the most-drained one.

Fixed

  • niri-screensaver-ctl effects listed every TTE effect twice. tte -h
    prints the {beams,...} choices block twice (usage line + positional
    args); get_effects now takes only the first occurrence (grep -m1).

v0.5.7

19 May 03:15

Choose a tag to compare

Documentation

  • README "Creating your own" logo subsection now covers layout
    (centering behavior, trailing-whitespace gotcha, blank-line padding,
    icon+wordmark stacking) and includes a small size reference table.
    Existing tool recipes (figlet, jp2a, chafa, patorjk web
    generator) and the LOGO_FILE=... niri-screensaver-ctl test preview
    workflow are retained.
  • noctalia-plugin/README.md Settings table rebuilt with a Widget
    column reflecting actual control types (toggle / spinbox / dropdown /
    text + Browse / button), and the previously-missing LOGO_FILE,
    SHOW_NOW_PLAYING, and NOW_PLAYING_DURATION rows added. New
    "Logos" section in the plugin README covers the dropdown's auto-
    refresh behavior, the effective-dir resolution order, and a concise
    layout/size primer that cross-links to the upstream README for the
    full guide.

Added

  • Noctalia plugin: dropdown selector for the logo file in the Logo
    settings section. Lists *.txt files from the effective logo
    directory (the logoDir override if set, else the installed
    share/logos/) and auto-refreshes when files are added or removed
    — no Noctalia restart needed. Disabled when "Random logo per cycle"
    is on, since the random picker overrides any specific selection.
    Previously the logoPath setting had no UI and was only editable by
    hand-editing the Noctalia settings JSON.
  • Noctalia plugin: fade-in / fade-out effect controls are now
    NComboBox dropdowns populated at startup from
    niri-screensaver-ctl effects (deduped + sorted). First entry
    (none) clears the fade. Eliminates the silent-no-op when a typo'd
    effect name slipped past the free-text inputs.
  • Noctalia plugin: "Logo directory" now uses NTextInputButton
    text input on the left, folder icon on the right that opens
    Noctalia's NFilePicker in folder-select mode. The picker starts at
    your current logoDir if set, otherwise at the detected install
    path. Picking a folder fills the text input; the input stays
    editable for paste / type workflows.
  • Noctalia plugin: Logo section moved above Effects in the Settings
    panel (matches typical edit frequency); within Logo, the file
    dropdown is now first, then Random toggle, then directory. .txt
    extensions are stripped from dropdown display names; combobox
    minimumWidth bumped to 320px to fit the longest shipped logo
    names without truncation.

Changed

  • Default seeded logo is now niri-name-with-icon.txt (was
    framework-name-with-icon.txt). Only affects fresh installs where
    ~/.config/niri-screensaver/logo.txt does not yet exist; existing
    installs keep whatever logo was previously copied. To pick up the new
    default, delete ~/.config/niri-screensaver/logo.txt and re-run
    niri-screensaver-ctl (or symlink any other logo from
    share/logos/ — all are still installed).

v0.5.6

19 May 02:13

Choose a tag to compare

Changed

  • AUR PKGBUILD optdepends descriptions trimmed across both packages.
    Dropped parenthetical / env-var noise: playerctl no longer carries
    (SHOW_NOW_PLAYING=true), wlrctl no longer carries (recommended),
    and the ydotool / figlet blurbs are slightly shorter. The env
    var docs belong in the README, not in a pacman info pane. Cleaner
    output from pacman -Qi and pacman -Si. Also reduces the volume
    of false errors produced by CachyOS's shelly package manager,
    which has a parser bug that splits optdep descriptions on
    whitespace and treats each token as a separate package name
    (standard pacman / paru / yay were never affected).

v0.5.5

19 May 01:37

Choose a tag to compare

Fixed

  • AUR .install post-install messages and the README "Wire it into
    Noctalia" Option A now recommend cp -r instead of ln -sfn for
    the plugin into ~/.config/noctalia/plugins/niri-screensaver. With
    a symlink, the plugin loads fine, but Noctalia's
    PluginService.savePluginSettings() writes via sh -c "mkdir -p '<dir>' && cat > '<settings.json>' << HEREDOC ...", and that cat > fails
    with permission denied because /usr/share/niri-screensaver/noctalia-plugin/
    is root:root 755. The write is fire-and-forget via
    Quickshell.execDetached, so the user sees no error — they just
    notice their plugin Settings changes silently revert on Noctalia
    restart. Caught by an end-to-end install test on a fresh AUR install.
    Tradeoff of cp -r is that plugin updates from pacman -Syu don't
    auto-flow into the user copy; the new note in both the post-install
    message and the README tells users to re-run cp -r after upgrades.

v0.5.4 — shellcheck SC2015 fix + AUR scaffold polish

19 May 00:57

Choose a tag to compare

Changed

  • install.sh cache-refresh guards rewritten with explicit
    if cmd; then action || true; fi rather than
    cmd && action || true to satisfy stricter shellcheck (SC2015).
    Runtime behavior is identical — both forms no-op when the tool
    isn't installed and don't break the install on cache-refresh
    failure. Only the lint pattern changed. Caught by CI on a newer
    shellcheck version than the one shipped locally.
  • AUR packaging scaffold (packaging/aur/) received pre-publish
    polish per a full pass against AUR_submission_guidelines:
    0BSD LICENSE per package dir (gates eligibility for official-
    repo promotion), whitelist .gitignore in the publish recipe
    (fail-closed against future file types accidentally landing in
    the AUR repo), obfuscated maintainer email, and a corrected
    first-time publish recipe using git -c init.defaultBranch=master clone since AUR only accepts pushes to master. None of this
    changes runtime behavior — strictly publishing hygiene.

v0.5.3 — fix .desktop Test action under launchers

19 May 00:40

Choose a tag to compare

Fixed

  • .desktop "Preview an effect inline" action wrapped in
    alacritty -e ... so it works when invoked from a desktop
    launcher (Fuzzel, Anyrun, GNOME Activities, etc.). The
    underlying niri-screensaver-ctl test needs a TTY for tte
    to render; without the wrapper, launcher invocations silently
    no-op. CLI use was always fine. Alacritty is already a hard
    runtime dep, so no new dependency.

v0.5.2 — desktop entry + hicolor icon

19 May 00:33

Choose a tag to compare

Added

  • Desktop integration: share/applications/niri-screensaver.desktop
    and share/icons/hicolor/scalable/apps/niri-screensaver.svg. The
    .desktop entry exposes the primary niri-screensaver-ctl launch
    action plus two Actions= entries (Preview an effect inline,
    Enable/disable screensaver) so launchers like Fuzzel/Anyrun/Walker
    can right-click to the secondary actions. Icon is a charcoal-stroke
    variant of the existing plugin SVG so it stays visible across
    light and dark GTK/Qt themes (the plugin's stroke="white"
    version is intentional for Noctalia tinting and stays as-is). Both
    install.sh and the AUR PKGBUILDs ship them to their respective
    XDG paths and refresh gtk-update-icon-cache /
    update-desktop-database post-install (silent no-op if those
    tools aren't installed).
  • AUR PKGBUILDs scaffolded under packaging/aur/ — both
    niri-screensaver (stable, tracks tags; pkgver=0.5.1 with the
    v0.5.1 tarball sha256 baked in) and niri-screensaver-git (HEAD,
    with a pkgver() that derives from git describe). Each ships a
    $pkgname.install post-install hook that points the user at the
    niri window-rule snippet, the Noctalia plugin symlink command, and
    the inline noctalia-customCommand.json fallback.
    Pre-generated .SRCINFO files included so AUR sync is a clean copy.
    packaging/aur/.gitignore excludes makepkg build artifacts (pkg/,
    src/, *.pkg.tar.*, fetched tarballs, etc.) so a stray
    git add -A from the repo root doesn't accidentally commit them.
    packaging/aur/README.md documents first-time publish and per-release
    update flow, including the structurally identical .gitignore that
    belongs in each AUR-side repo. All declared deps (alacritty,
    niri, jq, python-terminaltexteffects) plus optdeps
    (noctalia-shell, playerctl, wlrctl, ydotool, figlet)
    verified present in Arch repos or AUR. End-to-end test build
    confirmed: makepkg --verifysource passes, makepkg -d produces a
    92K niri-screensaver-0.5.1-1-any.pkg.tar.zst with the expected
    41-file layout, and the -git PKGBUILD's pkgver() resolves
    correctly to <tag>.r<count>.g<short-hash>.
  • CI: .github/workflows/release.yml auto-creates a GitHub Release
    on any v* tag push. Pulls the matching ## [X.Y.Z] section out of
    CHANGELOG.md via awk and feeds it to gh release create --notes-file. Falls back to the bare tag name if no matching section
    exists. Backfilled releases for v0.4.0/v0.5.0/v0.5.1 so the
    "Releases" sidebar reflects the actual ship history. Future cuts
    only require git tag vX.Y.Z && git push origin vX.Y.Z.