Files
greetd-moongreet/CLAUDE.md
T
nevaforget 86d0f5e56d docs: translate CLAUDE.md to English
Per the committed=English rule.
2026-06-16 10:46:13 +02:00

4.8 KiB
Raw Blame History

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 test for 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 rejection
  • sessions.rs — Wayland/X11 sessions from .desktop files
  • power.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 messages
  • fingerprint.rs — fprintd D-Bus probe (gio::DBusProxy) — device detection and enrollment check for UI feedback
  • config.rs — TOML config ([appearance] background, gtk-theme, cursor-theme, cursor-size, fingerprint-enabled) + wallpaper fallback + blur validation (finite, clamp 0200) + cursor-size validation (range 1256)
  • 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 (no set_monitor), KeyboardMode::Exclusive, systemd-journal-logger
  • resources/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_blocking instead of raw threads
  • Socket cancellation: Arc<Mutex<Option<UnixStream>>> + AtomicBool for clean cancellation
  • Avatar cache: HashMap<String, gdk::Texture> in Rc<RefCell<GreeterState>>
  • GPU blur via GskBlurNode: Snapshot::push_blur() + GskRenderer::render_texture() in the connect_realize callback — no CPU blur, no disk cache, no image crate. The blurred texture is cached across all monitors via Rc<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 in GreeterState, 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_THEME env reliably — the cursor is set via gtk::Settings::set_gtk_cursor_theme_name(), analogous to gtk-theme. Same validation (is_valid_gtk_theme) against path traversal.
  • Journal logging: systemd-journal-logger instead of file logging — journalctl -t moongreet, debug level via the MOONGREET_DEBUG env var
  • File permissions: cache directories 0o700 via DirBuilder::mode(), cache files 0o600
  • Testable persistence: save_*_to/load_*_from variants with a configurable path for unit tests
  • Shared wallpaper texture: the gdk::Texture is decoded once in load_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