chore(readme): more splitting + added "just install"

This commit is contained in:
Lemmy
2026-04-27 08:43:52 -04:00
parent f50a5d9bb1
commit 13f390e203
5 changed files with 239 additions and 173 deletions
+27 -16
View File
@@ -1,18 +1,27 @@
# Noctalia Configuration
# Configuration
Config file: `$XDG_CONFIG_HOME/noctalia/config.toml` (defaults to `~/.config/noctalia/config.toml`)
Noctalia has two configuration layers:
Changes are hot-reloaded via inotify — no restart required.
- Declarative user config lives in `$XDG_CONFIG_HOME/noctalia/` or `~/.config/noctalia/`.
Noctalia reads every `*.toml` file in that directory, sorted alphabetically, and deep-merges them into one config.
A single `config.toml` is the simplest setup, but splitting config into files such as `bar.toml`, `theme.toml`,
or `widgets.toml` is also supported.
- GUI-managed overrides live in `$XDG_STATE_HOME/noctalia/settings.toml` or
`~/.local/state/noctalia/settings.toml`. This file is written by Noctalia itself for settings changed through the
UI, IPC-backed controls, setup flows, and other runtime actions that need persistence.
A ready-to-use starting config with all defaults is at [`example.toml`](example.toml).
Load order is built-in defaults first, then declarative config files, then `settings.toml`.
Because the state file is applied last, GUI overrides win over matching values in `config.toml`.
Notification daemon toggle: use `[notification].enable_daemon` (documented in [`config/services.md`](config/services.md)).
Weather location visibility toggle: use `[shell].show_location` (documented in [`config/shell.md`](config/shell.md)).
Wallpaper automation: use `[wallpaper.automation]` (documented in [`config/wallpaper.md`](config/wallpaper.md)).
Wallpaper single-color fallback/fill: use `[wallpaper].fill_color` (documented in [`config/wallpaper.md`](config/wallpaper.md)).
Bar creation order: use `[bar].order` (documented in [`config/bar.md`](config/bar.md)).
Use the declarative config directory for hand-authored, dotfile-managed configuration. Treat `settings.toml` as an
app-managed override layer: inspect or delete it when you want to understand or clear GUI changes, but do not rely on
it as the primary place for curated config. Keeping the override file outside `~/.config` also allows the GUI to save
changes when the config directory is read-only, such as on NixOS.
---
Both layers are watched for changes and hot-reloaded. If neither declarative config nor state overrides exist,
Noctalia falls back to built-in defaults in code.
A ready-to-use starting config with all defaults is at [example.toml](example.toml).
## Reference
@@ -20,9 +29,11 @@ Bar creation order: use `[bar].order` (documented in [`config/bar.md`](config/ba
|---------|-------------|
| [Bar](config/bar.md) | Bar layout, per-monitor overrides, auto-hide, widget capsule styling |
| [Widgets](config/widgets.md) | Widget definitions and all built-in widget types |
| [Dock](config/dock.md) | Application dock — pinned apps, auto-hide, IPC |
| [Desktop Widgets](config/desktop-widgets.md) | Desktop overlay widgets — edit mode, state file format |
| [Wallpaper](config/wallpaper.md) | Wallpaper picker and overview backdrop |
| [Theme](config/theme.md) | Color schemes, modes, wallpaper-derived palettes, app templates |
| [Services](config/services.md) | Audio, Sound cues, Brightness, Night Light, Weather, Idle, Notifications |
| [Shell](config/shell.md) | Global UI settings, OSD, Keybinds, Hooks |
| [Scripted Widgets](config/scripted-widgets.md) | Custom Luau-driven bar widgets |
| [Dock](config/dock.md) | Application dock, pinned apps, auto-hide, IPC |
| [Desktop Widgets](config/desktop-widgets.md) | Desktop overlay widgets, edit mode, state file format |
| [Wallpaper](config/wallpaper.md) | Wallpaper picker, overview backdrop, automation |
| [Theme](config/theme.md) | Color schemes, modes, wallpaper-derived palettes |
| [Theming Templates](config/theming-templates.md) | App theme template generation and export paths |
| [Services](config/services.md) | Audio, sound cues, brightness, night light, weather, idle, notifications |
| [Shell](config/shell.md) | Global UI settings, OSD, keybinds, hooks |
+175
View File
@@ -0,0 +1,175 @@
Contributing
===
This file collects contributor-facing details for Noctalia: design goals, stack notes, code style, source layout,
runtime asset behavior, and debugging helpers.
For dependencies and normal build commands, start with [README.md](README.md).
## Design Principles
- Direct Wayland + OpenGL ES only -- no toolkit overhead
- Minimal scene graph, domain-specific to shell UI
- Packaging should work across all major Linux distros: Arch, NixOS, Fedora, Gentoo, Debian, Void, OpenSuse
## Stack
| Layer | Library |
|-------|---------|
| Wayland core | `libwayland-client`, `wayland-scanner`, `wayland-protocols` |
| Surfaces | `xdg-shell`, `zwlr-layer-shell-v1` |
| Multi-monitor | `zxdg-output-unstable-v1` |
| Active window metadata | `zwlr-foreign-toplevel-management-unstable-v1` |
| Workspaces | `ext-workspace-v1`, `dwl-ipc-unstable-v2` |
| Clipboard | `ext-data-control-v1`, `wlr-data-control-unstable-v1` |
| Activation | `xdg-activation-v1` |
| Lockscreen | `ext-session-lock-v1` |
| Idle | `ext-idle-notify-v1`, `idle-inhibit-unstable-v1` |
| Cursor | `wp-cursor-shape-v1` |
| Keyboard | `xkbcommon` |
| Rendering | `EGL`, `OpenGL ES 3`, `wayland-egl` |
| Text | `cairo`, `pango`, `pangocairo`, `freetype`, `fontconfig` |
| Images | `Wuffs` (vendored), `nanosvg` (vendored), `stb_image_resize2` (vendored), `libwebp` |
| IPC | `sdbus-c++` |
| Audio | `libpipewire`, `dr_wav` (vendored) |
| Authentication | `PAM` |
| HTTP | `libcurl` |
| Config | `tomlplusplus` (vendored) |
| JSON | `nlohmann/json` (vendored) |
| Math expressions | `tinyexpr` (vendored) |
| Scripting | `Luau` (vendored) |
| Theme generation | Material Color Utilities (vendored) |
## Runtime Assets
`meson install` installs the binary and shipped assets separately using the normal prefix layout:
```text
/usr/local/bin/noctalia
/usr/local/share/noctalia/assets/...
```
With a different Meson `prefix`/`datadir`, the same structure is preserved under that prefix.
Noctalia needs the `assets/` tree at runtime. Copying only the bare `noctalia` binary is not enough.
Portable bundle layouts are also supported:
```text
bundle/
noctalia
assets/
```
```text
bundle/
bin/noctalia
share/noctalia/assets/
```
Runtime asset lookup order:
1. `NOCTALIA_ASSETS_DIR`
2. `assets/` next to the executable
3. `assets/` one level above the executable
4. install-style `../share/noctalia/assets` relative to the executable
5. the compiled install path from Meson (`<prefix>/<datadir>/noctalia/assets`)
6. the source-tree `assets/` directory as a development fallback
An asset root is only accepted if it contains the expected shipped files such as `emoji.json`, `fonts/tabler.ttf`,
`templates/builtin.toml`, and `translations/en.json`.
## Code Style
This project uses [clang-format](https://clang.llvm.org/docs/ClangFormat.html) for formatting. Run `just format`
before committing.
### Naming Conventions
| | Convention | Example |
|---|---|---|
| Files | snake_case | `widget_factory.cpp` |
| Directories | snake_case | `shell/widgets/` |
| Types / Classes | PascalCase | `WidgetFactory` |
| Functions / Methods | camelCase | `createWidget()` |
| Variables / Parameters | camelCase | `busName` |
| Private members | m_camelCase | `m_changeCallback` |
| Macros / Enum values | SCREAMING_SNAKE_CASE | `MAX_SIZE` |
D-Bus wire-protocol string literals, such as `player["bus_name"]`, stay snake_case because they are wire names, not
C++ identifiers.
## Project Layout
```text
src/
main.cpp Entry point
app/ Application bootstrap, main loop
auth/ PAM authentication (lockscreen)
config/ Configuration and state persistence (TOML)
core/ Logger, timer manager, shared utilities
dbus/ DBus service implementations
debug/ Debug service (runtime log toggling)
idle/ Idle manager and inhibitor
ipc/ IPC client/service (dev.noctalia.* commands)
launcher/ Launcher providers (apps, emoji, math, usage)
net/ HTTP client (libcurl)
notification/ Notification manager
pipewire/ PipeWire audio service and spectrum analyzer
render/
animation/ Animation manager and easing
core/ EGL/GLES renderer, image decoders
programs/ Shader programs per NodeType
scene/ Scene graph nodes (Rect, Text, Image, Icon, InputArea, ...)
text/ Cairo/Pango text rendering
shell/
bar/ Bar surface and instance
clipboard/ Clipboard history panel
control_center/ Control center panel and tabs
launcher/ Application launcher panel
lockscreen/ Session lockscreen surface
notification/ Notification popup
osd/ On-screen display (volume, brightness, ...)
overview/ Workspace overview
panel/ Panel base and manager
session/ Session menu (logout, reboot, ...)
tray/ System tray (StatusNotifierItem)
wallpaper/ Wallpaper surface and instance
widget/ Widget base and factory
widgets/ Widget implementations
system/ System monitor (CPU, RAM, temperature)
time/ Time service and polling
ui/
controls/ Low-level UI building blocks (Button, Input, Label, Flex, ...)
util/ Generic helpers (fuzzy matching, ...)
wayland/ Wayland connection, seat, toplevels, clipboard, ...
compositors/ Compositor-specific workspace backends (ext-workspace, sway, mango, dwl, ...)
third_party/
tomlplusplus/ TOML parser (vendored)
wuffs/ Raster image decoding (vendored)
nanosvg/ SVG rasterization (vendored)
stb/ Image resizing (vendored)
tinyexpr/ Math expression evaluator (vendored)
nlohmann/ JSON parser (vendored, header-only)
dr_wav/ WAV decoder (vendored)
luau/ Scripted widget runtime (vendored)
material_color_utilities/ Material Design color generation (vendored)
```
## Debugging
All debug commands use the `dev.noctalia.Debug` D-Bus service, available at runtime.
```sh
# Enable verbose debug logs
gdbus call --session --dest dev.noctalia.Debug --object-path /dev/noctalia/Debug --method dev.noctalia.Debug.SetVerboseLogs true
# Disable verbose debug logs
gdbus call --session --dest dev.noctalia.Debug --object-path /dev/noctalia/Debug --method dev.noctalia.Debug.SetVerboseLogs false
# Check current verbose log state
gdbus call --session --dest dev.noctalia.Debug --object-path /dev/noctalia/Debug --method dev.noctalia.Debug.GetVerboseLogs
# Emit an internal notification (app_name, summary, body, timeout_ms, urgency 0-2)
gdbus call --session --dest dev.noctalia.Debug --object-path /dev/noctalia/Debug --method dev.noctalia.Debug.EmitInternalNotification "Noctalia" "Test" "Hello from debug" 5000 1
```
+33 -156
View File
@@ -1,39 +1,9 @@
Noctalia
===
A lightweight Wayland shell and bar with no Qt or GTK dependency.
A lightweight Wayland shell and bar built directly on Wayland + OpenGL ES, with no Qt or GTK dependency.
## Design Principles
- Direct Wayland + OpenGL ES only -- no toolkit overhead
- Minimal scene graph, domain-specific to shell UI
- Packaging should work across all major Linux distros: Arch, NixOS, Fedora, Gentoo, Debian, Void, OpenSuse
## Stack
| Layer | Library |
|-------|---------|
| Wayland core | `libwayland-client`, `wayland-scanner`, `wayland-protocols` |
| Surfaces | `xdg-shell`, `zwlr-layer-shell-v1` |
| Multi-monitor | `zxdg-output-unstable-v1` |
| Active window metadata | `zwlr-foreign-toplevel-management-unstable-v1` |
| Workspaces | `ext-workspace-v1`, `dwl-ipc-unstable-v2` |
| Clipboard | `ext-data-control-v1`, `wlr-data-control-unstable-v1` |
| Activation | `xdg-activation-v1` |
| Lockscreen | `ext-session-lock-v1` |
| Idle | `ext-idle-notify-v1`, `idle-inhibit-unstable-v1` |
| Cursor | `wp-cursor-shape-v1` |
| Keyboard | `xkbcommon` |
| Rendering | `EGL`, `OpenGL ES 3`, `wayland-egl` |
| Text | `cairo`, `pango`, `pangocairo`, `freetype`, `harfbuzz`, `fontconfig` |
| Images | `Wuffs` (vendored), `nanosvg` (vendored), `libwebp` |
| IPC | `sdbus-c++` |
| Audio | `libpipewire` |
| Authentication | `PAM` |
| HTTP | `libcurl` |
| Config | `tomlplusplus` (vendored) |
| JSON | `nlohmann/json` (vendored) |
| Math expressions | `tinyexpr` (vendored) |
Noctalia is in early development. Expect breaking configuration and behavior changes while the project is still taking shape.
## Dependencies
@@ -43,12 +13,11 @@ A lightweight Wayland shell and bar with no Qt or GTK dependency.
sudo dnf install meson gcc-c++ just \
wayland-devel wayland-protocols-devel \
libEGL-devel mesa-libGLES-devel \
freetype-devel harfbuzz-devel fontconfig-devel \
freetype-devel fontconfig-devel \
cairo-devel pango-devel \
libxkbcommon-devel \
sdbus-cpp-devel pipewire-devel \
pam-devel libcurl-devel libwebp-devel \
libasan libubsan
pam-devel libcurl-devel libwebp-devel
```
### Arch
@@ -56,12 +25,11 @@ sudo dnf install meson gcc-c++ just \
```sh
sudo pacman -S meson gcc just \
wayland wayland-protocols \
libglvnd freetype2 harfbuzz fontconfig \
libglvnd freetype2 fontconfig \
cairo pango \
libxkbcommon \
sdbus-cpp libpipewire \
pam curl libwebp \
gcc-libs
pam curl libwebp
```
### Debian / Ubuntu
@@ -70,60 +38,59 @@ sudo pacman -S meson gcc just \
sudo apt install meson g++ just \
libwayland-dev wayland-protocols \
libegl-dev libgles-dev \
libfreetype-dev libharfbuzz-dev libfontconfig-dev \
libfreetype-dev libfontconfig-dev \
libcairo2-dev libpango1.0-dev \
libxkbcommon-dev \
libsdbus-c++-dev libpipewire-0.3-dev \
libpam0g-dev libcurl4-openssl-dev libwebp-dev \
libasan8 libubsan1
libpam0g-dev libcurl4-openssl-dev libwebp-dev
```
Vendored (no system package needed): `Wuffs`, `nanosvg`, `tomlplusplus`, `tinyexpr`, `nlohmann/json`.
Vendored dependencies, with no system package needed: `Wuffs`, `nanosvg`, `tomlplusplus`, `tinyexpr`,
`nlohmann/json`, `Luau`, `dr_wav`, `stb_image_resize2`, and Material Color Utilities.
System packages required beyond the Wayland/GL stack: `libwebp` (VP8 lossy WebP; wuffs handles all other formats).
System packages required beyond the Wayland/GL stack: `libwebp` handles WebP decoding and thumbnail encoding. Wuffs
handles the other supported raster image formats.
Sanitizer runtime packages are only needed for ASan/UBSan builds configured with `just configure asan`.
## Build
Requires [just](https://github.com/casey/just) and [meson](https://mesonbuild.com/).
```sh
# Debug (default) — builds in build-debug/
# Debug build in build-debug/
just configure
just build
just run
# Optimized release (-march=native, LTO, gc-sections) — builds in build-release/
# Optimized release build in build-release/
just configure release
just build release
just run release
# Clean rebuild
just rebuild # debug
just rebuild release # release
just rebuild
just rebuild release
```
<details>
<summary>Manual Meson</summary>
## Installation
After building, install with `just`:
```sh
meson setup build-debug # or: --buildtype=release -Db_lto=true
meson compile -C build-debug
./build-debug/noctalia
sudo just install release
```
</details>
## Installation / Packaging
Use `sudo just install` instead if you configured the default debug build.
`meson install` now installs the binary and shipped assets separately using the normal prefix layout:
Meson installs the binary and shipped assets using the normal prefix layout:
```text
/usr/local/bin/noctalia
/usr/local/share/noctalia/assets/...
```
With a different Meson `prefix`/`datadir`, the same structure is preserved under that prefix.
For packagers, the important point is that Noctalia needs the `assets/` tree at runtime. Copying only the bare `noctalia` binary is not enough.
Noctalia needs the shipped `assets/` tree at runtime. Copying only the `noctalia` binary is not enough.
Portable bundle layouts are also supported:
@@ -139,103 +106,7 @@ bundle/
share/noctalia/assets/
```
Runtime asset lookup order:
1. `NOCTALIA_ASSETS_DIR`
2. `assets/` next to the executable
3. `assets/` one level above the executable
4. install-style `../share/noctalia/assets` relative to the executable
5. the compiled install path from Meson (`<prefix>/<datadir>/noctalia/assets`)
6. the source-tree `assets/` directory as a development fallback
An asset root is only accepted if it contains the expected shipped files such as `emoji.json`, `fonts/tabler.ttf`, `templates/builtin.toml`, and `translations/en.json`.
## Code Style
This project uses [clang-format](https://clang.llvm.org/docs/ClangFormat.html) for formatting. Run `just format` before committing.
### Naming Conventions
| | Convention | Example |
|---|---|---|
| Files | snake_case | `widget_factory.cpp` |
| Directories | snake_case | `shell/widgets/` |
| Types / Classes | PascalCase | `WidgetFactory` |
| Functions / Methods | camelCase | `createWidget()` |
| Variables / Parameters | camelCase | `busName` |
| Private members | m_camelCase | `m_changeCallback` |
| Macros / Enum values | SCREAMING_SNAKE_CASE | `MAX_SIZE` |
## Project Layout
```
src/
main.cpp Entry point
app/ Application bootstrap, main loop
auth/ PAM authentication (lockscreen)
config/ Configuration and state persistence (TOML)
core/ Logger, timer manager, shared utilities
dbus/ DBus service implementations
debug/ Debug service (runtime log toggling)
idle/ Idle manager and inhibitor
ipc/ IPC client/service (dev.noctalia.* commands)
launcher/ Launcher providers (apps, emoji, math, usage)
net/ HTTP client (libcurl)
notification/ Notification manager
pipewire/ PipeWire audio service and spectrum analyzer
render/
animation/ Animation manager and easing
core/ EGL/GLES renderer, image decoders
programs/ Shader programs per NodeType
scene/ Scene graph nodes (Rect, Text, Image, Icon, InputArea, ...)
text/ Cairo/Pango text rendering
shell/
bar/ Bar surface and instance
clipboard/ Clipboard history panel
control_center/ Control center panel and tabs
launcher/ Application launcher panel
lockscreen/ Session lockscreen surface
notification/ Notification popup
osd/ On-screen display (volume, brightness, ...)
overview/ Workspace overview
panel/ Panel base and manager
session/ Session menu (logout, reboot, ...)
tray/ System tray (StatusNotifierItem)
wallpaper/ Wallpaper surface and instance
widget/ Widget base and factory
widgets/ Widget implementations
system/ System monitor (CPU, RAM, temperature)
time/ Time service and polling
ui/
controls/ Low-level UI building blocks (Button, Input, Label, Flex, ...)
util/ Generic helpers (fuzzy matching, ...)
wayland/ Wayland connection, seat, toplevels, clipboard, ...
compositors/ Compositor-specific workspace backends (ext-workspace, sway, mango, dwl, ...)
third_party/
tomlplusplus/ TOML parser (vendored)
wuffs/ Raster image decoding (vendored)
nanosvg/ SVG rasterization (vendored)
tinyexpr/ Math expression evaluator (vendored)
nlohmann/ JSON parser (vendored, header-only)
```
## Debugging
All debug commands use the `dev.noctalia.Debug` D-Bus service, available at runtime.
```sh
# Enable verbose debug logs
gdbus call --session --dest dev.noctalia.Debug --object-path /dev/noctalia/Debug --method dev.noctalia.Debug.SetVerboseLogs true
# Disable verbose debug logs
gdbus call --session --dest dev.noctalia.Debug --object-path /dev/noctalia/Debug --method dev.noctalia.Debug.SetVerboseLogs false
# Check current verbose log state
gdbus call --session --dest dev.noctalia.Debug --object-path /dev/noctalia/Debug --method dev.noctalia.Debug.GetVerboseLogs
# Emit an internal notification (app_name, summary, body, timeout_ms, urgency 0-2)
gdbus call --session --dest dev.noctalia.Debug --object-path /dev/noctalia/Debug --method dev.noctalia.Debug.EmitInternalNotification "Noctalia" "Test" "Hello from debug" 5000 1
```
See [CONTRIBUTING.md](CONTRIBUTING.md#runtime-assets) for the full runtime asset lookup order.
## Configuration
@@ -260,4 +131,10 @@ changes when the config directory is read-only, such as on NixOS.
Both layers are watched for changes and hot-reloaded. If neither declarative config nor state overrides exist,
Noctalia falls back to built-in defaults in code.
See [CONFIG.md](CONFIG.md) for the full configuration reference, including shell IPC command examples.
A ready-to-use starting config with all defaults is at [example.toml](example.toml). See [CONFIG.md](CONFIG.md) for the
full configuration reference.
## Contributing
Developer notes, architecture overview, code style, project layout, and debugging commands live in
[CONTRIBUTING.md](CONTRIBUTING.md).
+3
View File
@@ -24,6 +24,9 @@ build m=mode:
run m=mode:
./build-{{m}}/noctalia
install m=mode:
meson install -C build-{{m}}
format:
find src \( -name '*.cpp' -o -name '*.h' \) -print0 | xargs -0 clang-format -i
find src \( -name '*.cpp' -o -name '*.h' \) -print0 | xargs -0 grep -ZlP '\s+$' | xargs -0 -r sed -i 's/[[:space:]]*$//'
+1 -1
View File
@@ -133,7 +133,7 @@ stb_dep = declare_dependency(
include_directories: include_directories('third_party/stb', is_system: true),
)
# ── System: libwebp (VP8 lossy WebP; wuffs only handles VP8L lossless) ────────
# ── System: libwebp (WebP decode and thumbnail encode) ───────────────────────
libwebp_dep = dependency('libwebp', required: true)
# ── Vendored: Luau (Roblox's Lua fork) ────────────────────────────────────────