- -h/--help prints a full usage overview (modes, config keys, keys, mouse) - Run dialog now executes the typed command directly in the new window (previously it spawned the default shell and typed the command into it, which showed up as just an empty terminal) - Virtual terminals get vt100 scrollback (config scrollback_lines, default 1000): mouse wheel scrolls history when the app doesn't capture the mouse, arrow-key fallback on the alternate screen, any keypress jumps back to the bottom; optional scrollbar on the right border (show_scrollbar) plus configurable default_window_size - Exit triggered from a connected display client (ctrl+q / panel button) now only disconnects that client — the daemon/standalone session and its programs keep running - Windows now paint the border zone in the desktop background color so rounded corners actually look rounded instead of a filled square with an inner rounded frame; popup dialogs rounded too - Integration suite extended to 19 checks (scrollback, run dialog, client-safe exit) — all passing Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
288 lines
8.6 KiB
Markdown
288 lines
8.6 KiB
Markdown
# TUI-WM
|
||
|
||
En terminal-baserad fönsterhanterare med flytande fönster, full mussuport och SSH-kompatibilitet — inspirerad av tmux men med ett modernt UX.
|
||
|
||
## Funktioner
|
||
|
||
- Flytande terminaler med fri positionering och storleksändring
|
||
- Full mussuport: vänster/höger/mitten-klick, scroll, drag, ANSI-muse-protokoll vidarebefordras till appar
|
||
- Panel (topp/botten) med klickbara knappar och dynamiska status-widgets
|
||
- Dropdown-menyer med undermenyer
|
||
- Körbar kommandodialog (`ctrl+space`)
|
||
- Dynamisk omrendering vid terminalstorlek-ändringar
|
||
- SSH-kompatibel (fungerar via vanliga ANSI escape-koder)
|
||
- Kompilerar till fristående binärer för Linux och Windows
|
||
|
||
## Teknikstack
|
||
|
||
| Komponent | Bibliotek |
|
||
|---|---|
|
||
| Terminal I/O, mus, resize | `crossterm` |
|
||
| TUI-rendering, buffersystem | `ratatui` |
|
||
| Pseudoterminal (PTY/ConPTY) | `portable-pty` |
|
||
| VT100-emulering | `vt100` |
|
||
| Konfiguration | `toml` + `serde` |
|
||
| Språk | Rust |
|
||
|
||
## Bygga projektet
|
||
|
||
### Förutsättningar
|
||
|
||
- [Rust toolchain](https://rustup.rs/) (`rustup`, `cargo`)
|
||
- För Windows-cross-kompilering från Linux: `mingw-w64`
|
||
|
||
### Bygga för Linux
|
||
|
||
```bash
|
||
cargo build --release --target x86_64-unknown-linux-gnu
|
||
```
|
||
|
||
### Bygga för Windows
|
||
|
||
```bash
|
||
cargo build --release --target x86_64-pc-windows-gnu
|
||
```
|
||
|
||
Binärerna hamnar i `target/<target>/release/`.
|
||
|
||
### Via VS Code
|
||
|
||
Använd `Terminal > Run Task` och välj:
|
||
- **Build Linux** — bygger för `x86_64-unknown-linux-gnu`
|
||
- **Build Windows** — bygger för `x86_64-pc-windows-gnu`
|
||
- **Build (native)** — bygger för det platform du sitter på
|
||
- **Run** — kör appen direkt
|
||
|
||
## Projektstruktur
|
||
|
||
```
|
||
TUI-WM/
|
||
├── src/
|
||
│ ├── main.rs — Startpunkt, event-loop
|
||
│ ├── app.rs — All logik: fönsterhantering, mus, event-routing
|
||
│ ├── config.rs — TOML-konfiguration och dess datatyper
|
||
│ ├── pty.rs — PTY-instans (startar och kommunicerar med shell/app)
|
||
│ └── render.rs — Ratatui-rendering av paneler och fönster
|
||
├── config.toml — Huvud-konfigfil (panels, keybinds)
|
||
├── panels/
|
||
│ └── topbar.toml — Panel-definition (knappar, status-widgets)
|
||
├── .vscode/
|
||
│ └── tasks.json
|
||
└── Cargo.toml
|
||
```
|
||
|
||
---
|
||
|
||
## Konfiguration
|
||
|
||
Toppnivå-nycklar i `config.toml`:
|
||
|
||
| Nyckel | Default | Beskrivning |
|
||
|---|---|---|
|
||
| `default_shell` | `$SHELL` | Skal för nya terminaler |
|
||
| `default_window_size` | `[82, 26]` | `[bredd, höjd]` för nya terminalfönster |
|
||
| `scrollback_lines` | `1000` | Historikrader per virtuell terminal |
|
||
| `show_scrollbar` | `true` | Scrollbar på terminalfönstrens högerkant |
|
||
| `background_image` | – | Bakgrundsbild via Kitty graphics |
|
||
| `terminal_bg_color` | genomskinlig | Terminalfönstrens bakgrundsfärg |
|
||
|
||
Konfigurationen delas upp i två nivåer:
|
||
|
||
1. **`config.toml`** — huvud-konfigfil, definierar paneler och keybinds
|
||
2. **`panels/<fil>.toml`** — extern panel-fil, definierar knapparna och status-widgets för en specifik panel
|
||
|
||
---
|
||
|
||
### Paneler
|
||
|
||
En panel är en topbar eller bottombar med knappar och status-widgets.
|
||
|
||
```toml
|
||
# config.toml
|
||
[[panel]]
|
||
position = "top" # "top" | "bottom"
|
||
file = "panels/topbar.toml" # länk till extern panel-definition (valfri)
|
||
```
|
||
|
||
Eller inline utan extern fil:
|
||
|
||
```toml
|
||
[[panel]]
|
||
position = "bottom"
|
||
|
||
[[panel.item]]
|
||
label = "Terminal"
|
||
action = { type = "spawn_terminal" }
|
||
```
|
||
|
||
---
|
||
|
||
### Knappar (items)
|
||
|
||
Varje knapp i en panel kopplas till en `action`:
|
||
|
||
```toml
|
||
# panels/topbar.toml
|
||
[[item]]
|
||
label = "Terminal"
|
||
action = { type = "spawn_terminal" }
|
||
|
||
[[item]]
|
||
label = "Exit"
|
||
action = { type = "exit" }
|
||
```
|
||
|
||
#### Tillgängliga actions
|
||
|
||
| Action | Beskrivning |
|
||
|---|---|
|
||
| `{ type = "exit" }` | Avslutar TUI-WM |
|
||
| `{ type = "spawn_terminal" }` | Startar nytt terminalfönster med systemets standard-shell |
|
||
| `{ type = "spawn_terminal", shell = "/bin/bash" }` | Startar terminal med specifikt shell/program |
|
||
| `{ type = "spawn_run_dialog" }` | Öppnar körbar kommandodialog |
|
||
| `{ type = "run_program", command = "htop" }` | Kör ett program i terminalfönster |
|
||
| `{ type = "run_script", path = "/path/to/script.sh" }` | Kör ett skript i terminalfönster |
|
||
| `{ type = "submenu", item = [...] }` | Öppnar en dropdown-undermeny |
|
||
|
||
#### Dropdown-undermeny
|
||
|
||
```toml
|
||
[[item]]
|
||
label = "Apps"
|
||
action = { type = "submenu", item = [
|
||
{ label = "htop", action = { type = "run_program", command = "htop" } },
|
||
{ label = "vim", action = { type = "run_program", command = "vim" } },
|
||
] }
|
||
```
|
||
|
||
---
|
||
|
||
### Status-widgets
|
||
|
||
Status-widgets är dynamiska textblock i panelen som kör ett kommando periodiskt.
|
||
|
||
```toml
|
||
# panels/topbar.toml
|
||
[[status]]
|
||
command = "date '+%H:%M:%S'" # shell-kommando vars stdout visas
|
||
interval = 1 # uppdateringsintervall i sekunder (default: 10)
|
||
width = 10 # teckenbredd i panelen
|
||
align = "right" # "right" (default) | "left"
|
||
```
|
||
|
||
Flera status-widgets kan definieras. Höger-dockade renderas från höger kant inåt.
|
||
|
||
---
|
||
|
||
### Keybinds
|
||
|
||
Keybinds definieras i `config.toml` och kopplas till samme `action`-typ som knappar.
|
||
|
||
```toml
|
||
[[keybind]]
|
||
key = "ctrl+space"
|
||
scope = "global" # "global" | "wm" (default)
|
||
action = { type = "spawn_run_dialog" }
|
||
|
||
[[keybind]]
|
||
key = "alt+enter"
|
||
scope = "global"
|
||
action = { type = "spawn_terminal" }
|
||
|
||
[[keybind]]
|
||
key = "ctrl+q"
|
||
scope = "wm"
|
||
action = { type = "exit" }
|
||
```
|
||
|
||
#### Scope
|
||
|
||
| Scope | Beskrivning |
|
||
|---|---|
|
||
| `global` | Aktiveras alltid, även när ett terminalfönster har fokus |
|
||
| `wm` | Aktiveras bara när inget terminalfönster är fokuserat (default) |
|
||
|
||
#### Tangenter
|
||
|
||
Format: `"modifier+modifier+key"`. Tillgängliga modifiers: `ctrl`, `alt`, `shift`.
|
||
Exempelnycklar: `a`–`z`, `0`–`9`, `space`, `enter`, `esc`, `tab`, `backspace`, `delete`, `up`, `down`, `left`, `right`, `home`, `end`, `pageup`, `pagedown`, `f1`–`f12`.
|
||
|
||
---
|
||
|
||
## Mushantering
|
||
|
||
| Åtgärd | Effekt |
|
||
|---|---|
|
||
| Vänsterklick på titel-rad | Fokuserar och börjar flytta fönstret |
|
||
| Vänsterklick på `[x]` | Stänger fönstret |
|
||
| Vänsterklick på kant/hörn | Börjar storleksändra fönstret |
|
||
| Klick i innehållsyta | Fokuserar fönstret och skickar musklick till appen i terminalen |
|
||
| Scroll inuti terminal | Vidarebefordras till appen om den fångar musen; annars scrollas terminalens egen historik (`scrollback_lines`, scrollbar på högerkanten). På alternativskärm utan mus-stöd skickas pilar |
|
||
| Höger/mitten-klick i terminal | Vidarebefordras direkt till appen |
|
||
|
||
Möss-tracking fungerar automatiskt — om appen i terminalen aktiverar ANSI mus-protokoll (t.ex. vim, htop, ncurses-appar) vidarebefordras alla mus-events korrekt med rätt encoding (SGR, UTF-8 eller default X10).
|
||
|
||
---
|
||
|
||
## Startlägen
|
||
|
||
Kör `tui-wm --help` för en komplett flagg- och tangentöversikt.
|
||
|
||
TUI-WM kan startas i tre lägen:
|
||
|
||
### Standalone (standard)
|
||
|
||
```bash
|
||
tui-wm
|
||
```
|
||
|
||
Kör fönsterhanteraren i den aktuella terminalen och startar samtidigt en Unix-socket-server. Andra program kan ansluta till socketen medan TUI-WM kör.
|
||
|
||
### Daemon (`-d`)
|
||
|
||
```bash
|
||
tui-wm -d
|
||
```
|
||
|
||
Kör headless — ingen lokal terminal-rendering. State hanteras enbart via socketen. Frames renderas internt och skickas till anslutna display-klienter. Passar för att köra TUI-WM som bakgrundstjänst.
|
||
|
||
Daemonen stängs INTE av att en klient kopplar ner eller trycker `ctrl+q` — det kopplar bara ner den klienten. Stoppa daemonen med `pkill tui-wm` eller via systemd.
|
||
|
||
### Klient (`-c`)
|
||
|
||
```bash
|
||
tui-wm -c [socket-sökväg]
|
||
```
|
||
|
||
Ansluter till en befintlig TUI-WM-server (standalone eller daemon) som display-klient. Renderar mottagna frames och vidarebefordrar tangentbords-, **mus**- och resize-events — klick, drag, scroll och hover fungerar precis som lokalt, även över SSH. Om `socket-sökväg` utelämnas används standard-sökvägen. Koppla ned med **Ctrl+Shift+Q**.
|
||
|
||
#### Tester
|
||
|
||
```bash
|
||
cargo test # enhetstester (IPC-protokollet)
|
||
python3 tests/integration.py # end-to-end: daemon + frames + musforwarding
|
||
```
|
||
|
||
---
|
||
|
||
## Socket-API
|
||
|
||
Appar som körs inne i TUI-WM får miljövariablerna `TUI_WM_SOCKET` (sökväg till socketen) och `TUI_WM_WINDOW_ID` (fönstrets ID) satta automatiskt. Via socketen kan de:
|
||
|
||
- Spawna nya terminalfönster
|
||
- Visa popup-dialoger med knappar och vänta på svar
|
||
- Lista eller stänga fönster
|
||
- Ta emot renderade frames (ANSI) för att visa TUI-WM:s skärm
|
||
|
||
Se [SOCKET_API.md](SOCKET_API.md) för fullständig protokolldokumentation med JSON-exempel och kodexempel i Bash och Python.
|
||
|
||
---
|
||
|
||
## Standardtangenter
|
||
|
||
| Tangent | Funktion |
|
||
|---|---|
|
||
| `ctrl+space` | Öppna körbar kommandodialog |
|
||
| `alt+enter` | Nytt terminalfönster |
|
||
| `ctrl+q` | Avsluta (bara när inget terminalfönster fokuseras) |
|