Skip to content

Development

locainin edited this page Aug 12, 2026 · 12 revisions

Development

Workspace layout

  • crates/unixnotis-daemon: D-Bus daemon and store.
  • crates/unixnotis-center: Control-center panel UI.
  • crates/unixnotis-popups: Popup UI.
  • crates/unixnotis-ui: Shared GTK/UI components and CSS loader.
  • crates/unixnotis-core: Shared models and configuration.
  • crates/unixnotis-installer: Installer, service-manager integration, trial mode, and reset flow.
  • crates/noticenterctl: CLI control tool.

Internal module layout

  • crates/unixnotis-center/src/control/: D-Bus client, reconnect backoff, commands, seed state, and subscriptions.
  • crates/unixnotis-center/src/diagnostics/: panel debug and performance-probe reporting.
  • crates/unixnotis-center/src/media/: grouped media API, MPRIS transport, runtime state, and artwork policy.
  • crates/unixnotis-center/src/runtime/: application startup and runtime coordination.
  • crates/unixnotis-center/src/ui/notifications/: notification models, rows, store mutations, and list views.
  • crates/unixnotis-center/src/ui/panel/: panel shell, actions, keyboard behavior, search, layout, notices, and visibility.
  • crates/unixnotis-center/src/ui/reload/: config/CSS refresh and reload-notice lifecycle.
  • crates/unixnotis-center/src/ui/media/ and ui/widgets/: media presentation and configurable widget presentation.
  • crates/unixnotis-popups/src/app/: popup startup, reload coalescing, and runtime glue.
  • crates/unixnotis-popups/src/dbus/: popup D-Bus connection, retry, seed, commands, and types.
  • crates/unixnotis-popups/src/ui/: reload handling, icon resolution, popup reconciliation, state, and window geometry.
  • crates/unixnotis-core/src/config/panel/: panel configuration, section order, and action metadata.
  • crates/unixnotis-core/src/config/layout/: shared anchor/margin primitives and popup layout.
  • crates/unixnotis-core/src/config/loading/: bounded config I/O, current-schema validation, diagnostics, and theme/script file provisioning.
  • crates/unixnotis-core/src/config/runtime/sanitize/: runtime sanitization passes.
  • crates/unixnotis-core/src/config/widgets/: slider, toggle, stat, card, and plugin schemas.
  • crates/unixnotis-core/src/config/appearance/icon_assets/: bounded icon path validation and raster/SVG decoding policy.
  • crates/unixnotis-core/src/model/: notification, image, inline-reply, and D-Bus view models.
  • crates/unixnotis-ui/src/css/: CSS loading, provider stacking, and watcher helpers.
  • crates/unixnotis-ui/src/icons/: shared desktop application icon indexing.
  • crates/unixnotis-daemon/src/daemon/auth/: control-plane caller authorization and trusted binary checks.
  • crates/unixnotis-daemon/src/daemon/control/: panel control, timed DND, inline replies, inhibitors, queries, and clear-all helpers.
  • crates/unixnotis-daemon/src/daemon/notifications/: freedesktop notification server, payload, sender, and limit helpers.
  • crates/unixnotis-daemon/src/daemon/notifications/ingress/payload/: bounded notification construction split into build, expiration, sanitization, visual materialization, and mirrored tests.
  • crates/unixnotis-daemon/src/daemon/notifications/ingress/payload/visuals.rs keeps conversation avatars, decorative application visuals, and message content separate; clients receive bounded pixels rather than sender-controlled filesystem paths.
  • crates/unixnotis-center/src/media/runtime/: owner-deduplicated MPRIS discovery, snapshot selection, refresh scheduling, and bounded artwork policy.
  • crates/unixnotis-daemon/src/child_process/: center and popup child supervision.
  • crates/unixnotis-daemon/src/sound/: backend detection, sound-source resolution, and playback limits.
  • crates/unixnotis-daemon/src/trial_mode/: temporary takeover and restoration of another notification daemon.
  • crates/noticenterctl/src/app/: local-versus-control command routing.
  • crates/noticenterctl/src/css_check/: active-theme validation, dependency-aware cache, lint, and geometry checks.
  • crates/noticenterctl/src/doctor/: config, CSS, D-Bus, service-manager, and bounded-log checks.
  • crates/noticenterctl/src/preset/: archive, export, import, inspect, and portability checks.
  • crates/unixnotis-installer/src/actions/: install, config backup/restore, environment sync, Hyprland, binary discovery, and build acceleration.
  • crates/unixnotis-installer/src/service_manager/: backend implementations and installation orchestration for systemd, dinit, runit, and s6.
  • crates/unixnotis-installer/src/actions/environment/: compositor-session validation and service-manager environment synchronization.
  • crates/unixnotis-core/src/model/attribution.rs and daemon attribution modules: desktop association, assurance, interaction policy, and diagnostic explanations.
  • unixnotis-svg-renderer: bounded SVG rasterization helper used for local artwork; it is a constrained helper, not a general filesystem sandbox.

Center media architecture

The center keeps the backend under crates/unixnotis-center/src/media/ separate from the GTK presentation under crates/unixnotis-center/src/ui/media/. The backend is grouped by responsibility:

  • media/api/: the small UI-facing command handle and media value models.
  • media/mpris/: player admission, discovery, process-bound player state, property listeners, command delivery, and metadata parsing.
  • media/runtime/: the reconnecting event loop, mutable player state, refresh scheduling, owner replacement, signal dispatch, cache reconciliation, and snapshot publication.
  • Browser-backed MPRIS entries are deduplicated by owner/source process identity when available; normalized title-and-artist metadata is only a bounded fallback when process identity is absent. This keeps one browser alias from becoming one card while preserving separate known processes.
  • media/art/: local and remote artwork sources plus network destination policy.

Each group owns a mirrored tests/ directory. Cross-module behavior is exposed only within its group through pub(super) boundaries; test access should not widen the public media API.

Build and test

cargo nextest is a separate Cargo subcommand. Install it once when it is not already available:

cargo install cargo-nextest --locked
cargo build --release
cargo nextest run --workspace --all-targets --all-features
cargo clippy --all-targets --all-features -- \
  -D warnings \
  -W clippy::pedantic \
  -W clippy::nursery \
  -W clippy::undocumented_unsafe_blocks \
  -W clippy::multiple_unsafe_ops_per_block \
  -W clippy::mem_forget \
  -W clippy::unnecessary_safety_comment \
  -W clippy::unnecessary_safety_doc \
  -W clippy::allow_attributes_without_reason \
  -W clippy::allow_attributes \
  -W clippy::missing_assert_message \
  -W clippy::map_err_ignore \
  -W clippy::unwrap_used \
  -W clippy::unwrap_in_result \
  -W clippy::cfg_not_test \
  -W clippy::cast_ptr_alignment \
  -W clippy::transmute_ptr_to_ptr \
  -W clippy::fn_to_numeric_cast_any \
  -W clippy::as_pointer_underscore \
  -W clippy::lossy_float_literal

GTK tests that create windows run under a Wayland/Xvfb and session-bus harness, for example:

xvfb-run -a dbus-run-session -- cargo nextest run -p unixnotis-center

The workspace requires GTK 4.18. Test placement mirrors production modules under tests/, but mod.rs files only route modules; behavior belongs in descriptive test files.

The session-environment backends, popup readiness/reconciliation, SVG helper, notification attribution pipeline, and CSS-check parser each have focused tests near their production module. Keep cross-process behavior in an integration test rather than hiding it behind a large mock.

Optional build acceleration

The installer can optionally write a local .cargo/config.toml that points to a wrapper script under .cargo/unixnotis-rustc-wrapper.sh. The wrapper uses sccache (compiler output caching) and mold (fast linker) when available, and falls back to plain rustc if either tool is missing.

Manual install on Arch:

sudo pacman -S sccache mold

Remove .cargo/config.toml and the wrapper script to disable build acceleration.

CSS validation

noticenterctl css-check

The checker covers active theme paths, bounded imports, GTK expressions, duplicate selectors, geometry pressure, and the intentional duplicate-selector range directive described in Styling.

Clippy policy

The production lint profile uses -D warnings, clippy::pedantic, clippy::nursery, and selected restriction lints for unsafe-block documentation, pointer casts, forgotten values, and lossy literals. Clippy intentionally rejects enabling clippy::restriction as a blanket group because its lints represent mutually unsuitable policies. Keep the selected list in CI and the pull request template aligned rather than adding a blanket allow. Crates must not allow the complete pedantic or nursery groups. A named lint exception requires a reason and should live at the smallest practical boundary that preserves a stable public, wire-format, GTK, D-Bus, or installer contract. Long-lived compatibility exceptions use named expect entries with reasons. An expectation that no longer matches a real diagnostic fails under -D warnings, so stale exceptions cannot remain silent.

Test placement

Test functions live under a dedicated tests/ directory. A mod.rs file may route modules, but it must not contain test functions or fixtures. Prefer a descriptive test filename when one module is enough; split by behavior only when a test file becomes difficult to scan.

GTK tests that register an application must use a process-unique application ID. Reusing one fixed ID across parallel tests can intermittently fail with an already-exported D-Bus interface.

Logging

  • general.log_level in config.toml sets the default.
  • RUST_LOG overrides the configured log level when it is valid.
  • UNIXNOTIS_DIAGNOSTIC=1 enables capped diagnostic output.
  • Normal log snippets are capped; diagnostic mode raises the cap and still strips control/newline characters before logging.

Clone this wiki locally