breadmon/README.md
Breadway aec2fa5290
Some checks failed
check / check (push) Failing after 1s
dev release / build (push) Failing after 1s
Wire breadmon into the bread event fabric (app id mon)
After a successful hyprctl apply, publish bread.mon.applied
{ "profile": <string or null> }. BreadClient is fail-silent: if
breadd is down, apply behaves exactly as before.

Document the contract in EVENTS.md.
2026-08-15 22:16:36 +08:00

114 lines
4.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# breadmon
A terminal UI monitor manager for Hyprland. Lets you position, configure, and mirror displays interactively, then apply a live layout on [BOS](https://git.breadway.dev/breadway/bos)-patched Hyprland.
breadmon is **not** the Display panel in `bos-settings`. That panel edits `~/.config/hypr/monitors.json` (Hyprland's login/reload layout store). breadmon keeps its own named snapshots as TOML under `~/.config/breadmon/profiles/` and applies them live through BOS Hyprland. The two stores are independent — changing one does not update the other.
## Requirements
- **[BOS (Bread OS)](https://git.breadway.dev/breadway/bos)'s patched Hyprland build** for live apply. The `a` key runs `hyprctl eval 'hl.monitor({...})'` — a BOS-specific Lua extension. Vanilla/upstream Hyprland has no `eval` request and no `hl.monitor()`, so apply will fail there with an explicit error instead of the raw hyprctl response. Viewing, arranging, and saving profiles work on any Hyprland; only live apply needs BOS.
- The `hyprctl` binary must be on `PATH`
- Rust toolchain (to build from source)
## Install
Via [bakery](https://git.breadway.dev/Breadway/bread-ecosystem), the bread ecosystem package manager:
```
bakery install breadmon
```
Or build from source:
```
cargo build --release
```
The binary is written to `target/release/breadmon`.
## Usage
```
breadmon
```
The TUI opens with four tabs, switchable by number key or mouse click:
| Key | Tab |
|-----|-----|
| `1` / F1 | Layout |
| `2` / F2 | Config |
| `3` / F3 | Mirror |
| `4` / F4 | Profiles |
### Layout
A scaled canvas showing all connected monitors. The selected monitor is highlighted.
| Key | Action |
|-----|--------|
| `hjkl` / arrow keys | Move selected monitor 1 px |
| `Shift+hjkl` | Move selected monitor 10 px |
| `Tab` / `n` | Cycle to next monitor |
| `Shift+Tab` / `p` | Cycle to previous monitor |
| `0` | Auto-arrange monitors left-to-right with no gaps |
| `[` / `]` | Zoom canvas out / in |
| Mouse drag | Drag monitor to reposition |
Monitors snap to each other's edges when dragged or nudged within 10 px.
### Config
Per-monitor settings for the currently selected display.
| Key | Action |
|-----|--------|
| `jk` / `Tab` | Move between fields |
| `hl` / scroll | Cycle field value |
| `,` / `.` | Scale 0.1 / +0.1 |
| `[` / `]` | Switch to previous / next monitor |
| `Enter` | Commit scale edit and apply |
| `Esc` | Discard pending edits |
Fields: Resolution, Refresh rate, Scale, Transform (rotation/flip), VRR, DPMS, Mirror of.
The header shows the monitor's PPI and a suggested fractional scale when physical dimensions are available.
### Mirror
Finds the best common mode between two monitors and sets one to mirror the other. Use `Tab` to move focus between source and target, `hl` to cycle the selection, `Enter` to confirm.
### Profiles
Named snapshots of the current monitor configuration, stored as TOML files.
| Key | Action |
|-----|--------|
| `jk` | Navigate profile list |
| `Enter` | Load selected profile |
| `d d` | Delete selected profile (double-press within 3 s) |
| `Tab` | Move focus to name input / save button |
Profiles are saved to `~/.config/breadmon/profiles/`.
### Global keys
| Key | Action |
|-----|--------|
| `a` | Apply current configuration via `hyprctl eval 'hl.monitor({...})'` (BOS-patched Hyprland only) |
| `s` | Save current configuration as a profile |
| `r` | Refresh monitor list from Hyprland |
| `Ctrl+Z` | Undo last change (up to 20 steps) |
| `q` / `Ctrl+C` | Quit (prompts once if there are unsaved changes) |
breadmon also listens on Hyprland's event socket and reloads the monitor list automatically when a display is connected or disconnected.
## Config
Profiles are plain TOML files under `~/.config/breadmon/profiles/`. Each file records the monitor name, mode, position, scale, transform, VRR, DPMS, and mirror source. They are created and managed through the Profiles tab; there is no hand-written config file.
This is not `~/.config/hypr/monitors.json`. That file is the persistent Hyprland layout edited by the `bos-settings` Display panel and applied on login/reload. breadmon never reads or writes it.
## bread event integration
breadmon works the same with or without `breadd`. After a successful live apply (`hyprctl eval 'hl.monitor({...})'` on BOS-patched Hyprland — not the `bos-settings` Display panel), it publishes `bread.mon.applied`. If breadd is down, the emit is a silent no-op; apply itself is unchanged. See [EVENTS.md](EVENTS.md) for the bus contract. `bread` is not a bakery dependency.