- users::User: drop the unused `uid` field and its getuid() assignment.
The compiler dead_code warning is gone, and the synthetic `u32::MAX`
sentinel in the panel fallback is obsolete too.
- panel: surface a log::warn! when dirs::home_dir() returns None instead
of silently falling back to an empty PathBuf that would make avatars
look for .face in the current working directory.
- Apply three clippy suggestions: two collapsible if-let + && chains in
users::get_avatar_path_with and config::resolve_background_path_with,
and a redundant closure in panel::execute_action's spawn_blocking.
- main: require MOONSET_DEBUG=1 to escalate log verbosity — mere
presence of the var must not dump path info into the journal.
- power: RAII DoneGuard sets done=true on every wait() exit path, so the
timeout thread no longer sleeps its full 30 s holding a spawn_blocking
slot when child.wait() errors. A separate timed_out AtomicBool marks
our own SIGKILL so we do not misclassify an external OOM-kill. Memory
ordering on the flags is now Release/Acquire.
- i18n: detect_locale now reads LC_ALL, LC_MESSAGES, LANG in POSIX
priority order before falling back to /etc/locale.conf, so systems
installed in English with LC_ALL=de_DE.UTF-8 pick up the correct UI.
- panel: execute_action desensitizes button_box on entry and re-enables
it on error paths, so double-click or keyboard repeat cannot fire the
same power action twice.
- config: accept_wallpaper helper applies an extension allowlist (jpg,
jpeg, png, webp) plus symlink rejection and a 10 MB size cap, applied
to both the user-configured path and the Moonarch ecosystem fallback.
Bounds worst-case decode latency and narrows the gdk-pixbuf parser
attack surface.
Piping stdout without draining while blocking in child.wait() risks deadlock
if a command writes more than one OS pipe buffer (~64 KB on Linux). Current
callers (systemctl, niri msg, loginctl) stay well under that, but the
structure was fragile. stdout is now discarded; stderr continues to be
captured for error reporting.
After cancelling a confirmation prompt, the focused widget was removed
from the tree without restoring focus to the action buttons. With
layer-shell exclusive keyboard mode, GTK does not recover focus
automatically — the UI became keyboard-unreachable.
- Replace canonicalize() with symlink_metadata + is_file + !is_symlink for avatar
lookup (prevents symlink traversal to arbitrary files)
- Fix blur padding offset from (0,0) to (-pad,-pad) to prevent edge darkening
- Add MAX_BLUR_DIMENSION (1920px) downscale before GPU blur
- Validate blur per config source (invalid user value preserves system default)
- Wallpaper: use symlink_metadata + is_file + !is_symlink in resolve_background_path
Colloid-Catppuccin theme loaded via ~/.config/gtk-4.0/gtk.css at
PRIORITY_USER (800) was overriding moonset's PRIORITY_APPLICATION (600),
causing action buttons to lose their circular border-radius.
- Use STYLE_PROVIDER_PRIORITY_USER for app CSS provider
- Replace border-radius: 50% with 9999px (GTK4 CSS percentage quirk)
GskBlurNode samples pixels outside texture bounds as transparent,
causing visible darkening at wallpaper edges. Fix renders the texture
with 3x-sigma padding before blur, then clips back to original size.
Three parallel audits (quality, performance, security) identified issues
across the codebase. This commit addresses all remaining findings:
- Replace busy-loop polling in run_command with child.wait() + timeout thread
- Canonicalize ~/.face and AccountsService avatar paths to prevent symlink abuse
- Add detect_locale_with() DI function for testable locale detection
- Move config I/O from activate() to main() to avoid blocking GTK main loop
- Validate background_blur range (0–200), reject invalid values with warning
- Remove embedded wallpaper from GResource — moonarch provides it via filesystem
(binary size ~3.2MB → ~1.3MB)
Replace env_logger with systemd-journal-logger for consistent logging
across moonset/moonlock/moongreet. Add MOONSET_DEBUG env var and debug
statements across all modules. Also includes shared blur cache for
multi-monitor and detached moonlock spawn for lock action.
Replace image crate + disk cache blur with GPU-side GskBlurNode,
symmetric with moonlock and moongreet. Removes ~15 transitive
dependencies and ~160 lines of caching code. Blur now happens once
on the GPU at widget realization — zero startup latency, no cache
management needed.
Without this, app.quit() destroys windows instantly, creating a jarring
pop-out. Now all windows fade out over 250ms (matching the fade-in)
before the app exits. Uses the same CSS opacity transition — just
removes the "visible" class and defers quit via glib timeout.
First launch with blur blurs and saves to ~/.cache/moonset/. Subsequent
starts load the cached PNG directly (~9x faster). Cache invalidates
when wallpaper path, size, mtime, or sigma changes.
Feature-parity with Python v0.2.0. Same CSS, same UI, same actions.
Single 3.1 MB binary with embedded resources (CSS, wallpaper, avatar).
Modules: power.rs, i18n.rs, config.rs, users.rs, panel.rs, main.rs
45 unit tests passing. Python sources retained as reference.