86d0f5e56d
Per the committed=English rule.
4.8 KiB
4.8 KiB
Moongreet
Project
Moongreet is a greetd greeter for Wayland, built with Rust + gtk4-rs + gtk4-layer-shell. Part of the Moonarch ecosystem.
Tech Stack
- Rust (edition 2024), gtk4-rs 0.11, glib 0.22
- gtk4-layer-shell 0.8 for the Wayland Layer Shell (TOP layer)
- greetd IPC over a Unix domain socket (length-prefixed JSON)
cargo testfor unit tests
Project Structure
src/— Rust source code (main.rs, greeter.rs, ipc.rs, config.rs, users.rs, sessions.rs, i18n.rs, power.rs)resources/— GResource assets (style.css, default-avatar.svg)config/— example configuration files for/etc/moongreet/and/etc/greetd/pkg/— PKGBUILD for Arch Linux packaging (makepkg -sf)
Commands
# Run tests
cargo test
# Release build
cargo build --release
# Start the greeter in a window (without greetd/Layer Shell)
MOONGREET_NO_LAYER_SHELL=1 ./target/release/moongreet
# Build and install the package
cd pkg && makepkg -sf && sudo pacman -U moongreet-git-<version>-x86_64.pkg.tar.zst
Architecture
ipc.rs— greetd socket communication (4-byte LE header + JSON)users.rs— users from /etc/passwd, avatars (AccountsService + ~/.face), symlink rejectionsessions.rs— Wayland/X11 sessions from .desktop filespower.rs— reboot/shutdown via systemctl (--no-ask-password)i18n.rs— locale detection (LANG / /etc/locale.conf) and string tables (DE/EN), all UI and login error messagesfingerprint.rs— fprintd D-Bus probe (gio::DBusProxy) — device detection and enrollment check for UI feedbackconfig.rs— TOML config ([appearance] background, gtk-theme, cursor-theme, cursor-size, fingerprint-enabled) + wallpaper fallback + blur validation (finite, clamp 0–200) + cursor-size validation (range 1–256)greeter.rs— GTK4 UI (overlay layout), login flow via greetd IPC (multi-stage auth for fprintd), faillock warning, power confirm (inline confirmation before reboot/shutdown, like moonlock), avatar cache, last-user/last-session persistence (0o700 dirs, 0o600 files)main.rs— entry point, GTK app, Layer Shell setup, one greeter window on the focused output (noset_monitor),KeyboardMode::Exclusive, systemd-journal-loggerresources/style.css— Catppuccin-inspired theme
Design Decisions
- TOP layer instead of OVERLAY: the greeter runs under greetd, not above Waybar
- GResource bundle: CSS, wallpaper and default avatar are compiled into the binary
- Async login:
glib::spawn_future_local+gio::spawn_blockinginstead of raw threads - Socket cancellation:
Arc<Mutex<Option<UnixStream>>>+AtomicBoolfor clean cancellation - Avatar cache:
HashMap<String, gdk::Texture>inRc<RefCell<GreeterState>> - GPU blur via GskBlurNode:
Snapshot::push_blur()+GskRenderer::render_texture()in theconnect_realizecallback — no CPU blur, no disk cache, noimagecrate. The blurred texture is cached across all monitors viaRc<RefCell<Option<gdk::Texture>>>(1 GPU render pass instead of N). - Fingerprint via greetd multi-stage PAM: fprintd D-Bus only as a probe (device/enrollment), the actual verification runs through PAM in the greetd auth loop.
auth_message_type: "secret"→ password, everything else →None(PAM decides). 60s socket timeout for fprintd. Device proxy cached inGreeterState, generation counter against race conditions on fast user switch. - Symmetry with moonlock/moonset: same patterns (i18n, config, users, power, GResource, GPU blur)
- Session validation: relative paths allowed (greetd resolves PATH), only
../null bytes are rejected - GTK theme validation: only alphanumeric +
_-+.allowed, prevents path traversal via config - Cursor theme via GtkSettings: GTK4 under greetd does not read the
XCURSOR_THEMEenv reliably — the cursor is set viagtk::Settings::set_gtk_cursor_theme_name(), analogous togtk-theme. Same validation (is_valid_gtk_theme) against path traversal. - Journal logging:
systemd-journal-loggerinstead of file logging —journalctl -t moongreet, debug level via theMOONGREET_DEBUGenv var - File permissions: cache directories 0o700 via
DirBuilder::mode(), cache files 0o600 - Testable persistence:
save_*_to/load_*_fromvariants with a configurable path for unit tests - Shared wallpaper texture: the
gdk::Textureis decoded once inload_background_texture()and shared by ref-count across all windows — avoids redundant JPEG decoding per monitor - Wallpaper validation: GResource branch via
resources_lookup_data()+from_bytes()(no abort on a missing path), file-size limit 50 MB, non-UTF-8 paths →None - Error-detail filtering: GDK/greetd error details only at
debug!level,warn!without internal details — prevents system-info leak into the journal