Initial commit — TANINUX (camel): management app + distro packaging

- app: GTK System Settings (tsettings) + Software Hub (thub) + TUI
- distro/: camel.toml manifest + MANIFEST.md (Arch + [tanin] repo model)
- packaging/: taninux, tanin-desktop (niri metapackage), tanin-greet,
  tanin-libadwaita, tanin-setup
- docs/, data/, LICENSE (GPL-3.0-or-later)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-18 20:18:30 +02:00
commit 10b88a67bc
167 changed files with 19624 additions and 0 deletions
+78
View File
@@ -0,0 +1,78 @@
# TANINUX — Verteilung als „Distro"
Ziel: ein Calamares-Installer, der eine fertige TANINUX-Umgebung aufsetzt.
Modell: **eigenes Binär-Repo `[tanin]` nur für eigene Pakete**, alles Standard
aus den **offiziellen Arch-Repos** (wie CachyOS/EndeavourOS).
## Pakete
| Paket | Repo | Inhalt |
|------------------|-------------|-----------------------------------------------------|
| `taninux` | `[tanin]` | App: tsettings + thub + TUI, Helper, polkit, .desktop |
| `tanin-eww` | `[tanin]` | eww Panel/Dock-Config + Scripts (→ /usr/share) |
| `tanin-setup` | `[tanin]` | seedet `~/.config` aus /usr/share + Portal/Session-Fix |
| `tanin-desktop` | `[tanin]` | **Metapackage**: depends = eigene + Arch-Pakete |
`tanin-desktop` zieht per `depends` die Arch-Pakete aus den normalen Repos und
die eigenen aus `[tanin]`. AUR bleibt Opt-in → `paru` ist `optdepends`, kein
hartes `depends` (Metapackage baut also nichts aus dem AUR).
## Dotfile-Auslieferung (wichtig)
AUR/Binär-Pakete dürfen **nicht** nach `/home` schreiben. Daher:
1. Default-Configs ins Paket nach `/usr/share/tanin/` (oder `/etc/skel/`).
2. `tanin-setup` kopiert sie beim ersten Start nach `~/.config` (idempotent,
überschreibt nichts ohne `--force`) und richtet das Session-Portal ein
(siehe „Dark Mode / Portal" unten).
## Phasen
1. **Fundament**`packaging/taninux/PKGBUILD` (fertig), LICENSE wählen,
`cd packaging/taninux && makepkg -si` lokal testen.
2. **Meta + Config**`tanin-desktop` (Skelett da), `tanin-eww`, `tanin-setup`.
3. **Eigenes Repo `[tanin]`**. Hosts:
- **Code** → `git.openbureau.ch/karim/taninux` (PKGBUILD-`source`, woher `makepkg` klont)
- **Projekt + Repo** → `taninux.kgva.ch` (PKGBUILD-`url`/Homepage **und** pacman-`Server`)
DB bauen + signieren:
```sh
repo-add -s tanin.db.tar.zst *.pkg.tar.zst # -s signiert mit Packager-Key
```
Hosten — zwei Optionen:
- **Gitea/Forgejo Arch-Registry** (falls git.openbureau.ch das kann): Pakete
pushen, `Server = https://git.openbureau.ch/api/packages/karim/arch/<repo>`.
`taninux.kgva.ch` als Reverse-Proxy/Vanity davor.
- **Statisches Verzeichnis** hinter `taninux.kgva.ch`: `*.pkg.tar.zst` + `tanin.db`.
`pacman.conf`-Snippet für User:
```ini
[tanin]
SigLevel = Optional TrustAll # später: Required + Key importieren
Server = https://taninux.kgva.ch/$arch
```
4. **Calamares / ISO** — `archiso`-Profil mit `[tanin]` vorkonfiguriert +
Calamares `packages`-Modul, das `tanin-desktop` installiert.
## Dark Mode / Portal (Session-Fix)
libadwaita-Apps (Nautilus etc.) lesen Hell/Dunkel über
`org.freedesktop.portal.Settings`. Damit das Portal startet, muss die Session
`graphical-session.target` aktivieren. `tanin-setup` legt dafür
`~/.config/systemd/user/<wm>-session.target` an und ergänzt die Compositor-
Autostarts:
```sh
exec-once = dbus-update-activation-environment --systemd --all
exec-once = systemctl --user start <wm>-session.target
```
## Hosts
- **Code:** `git.openbureau.ch/karim/taninux` (+ Repo für die eww-Config,
Absprache mit der eww-Instanz).
- **Projekt/Repo:** `taninux.kgva.ch` (Homepage + `[tanin]`-pacman-Server).
## Offene Voraussetzungen
- **LICENSE**-Datei ablegen (Vorschlag GPL-3.0-or-later):
`curl -L https://www.gnu.org/licenses/gpl-3.0.txt -o LICENSE`.
- `taninux.kgva.ch` ans Repo-Hosting hängen (Gitea-Arch-Registry oder statisch).
+122
View File
@@ -0,0 +1,122 @@
# TANINUX → eww: Akzent-Integration (Handoff)
**Für die Instanz, die an `~/eww` arbeitet.** Diese Datei ist der Vertrag, wie
die eww-Bar ihren Akzent von der TANINUX-Appearance-App bekommt.
---
## TL;DR (Kurzanleitung)
1. **Lies** `~/.local/share/taninux/gui.json`.
2. **Nimm** das Feld `accent_hex` (fertiger Hex-String, z. B. `#8aac8b`).
3. **Setz** damit deine eww-Akzentvariablen (`$accent`, `$accent-dim`, die
`$accent-08/14/22`-Washes) und mach `eww reload`.
4. **Reagiere auf Änderungen**: watch die Datei (inotify) — TANINUX schreibt sie
bei jedem Akzent-Wechsel neu.
Das war's. Der Rest hier ist Detail/Begründung.
---
## Quelle der Wahrheit
**Datei:** `~/.local/share/taninux/gui.json`
(exakt: `$XDG_DATA_HOME/taninux/gui.json`, Fallback `~/.local/share/...`)
**Schema:**
```json
{
"version": 1,
"color_scheme": "dark",
"accent": "take",
"accent_hex": "#8aac8b",
"accent_label": "Take · green"
}
```
| Feld | Bedeutung |
|----------------|------------------------------------------------------------------|
| `accent_hex` | **Das relevante Feld.** Fertiger Hex des gewählten Fuji-Akzents. |
| `accent` | interner Key (`ume`/`shinkai`/`take`/`chikyu`/`beni`). |
| `accent_label` | menschlicher Name, nur fürs Anzeigen. |
| `color_scheme` | `system` / `light` / `dark`**NICHT für deinen Akzent nötig**, siehe unten. |
Die Datei existiert erst, nachdem in TANINUX einmal ein Setting geändert wurde.
Wenn sie fehlt: Default-Akzent `ume` / `#8f8aac` annehmen.
---
## Was du in eww damit machst
Deine `~/eww/eww.scss` hat oben den Variablenblock. Akzent-relevant sind:
```scss
$accent: #a39ec4; // bright
$accent-dim: #8f8aac; // muted ← entspricht direkt accent_hex
$accent-08: rgba(163, 158, 196, 0.08);
$accent-14: rgba(163, 158, 196, 0.14);
$accent-22: rgba(163, 158, 196, 0.22);
$acc-l: $accent-dim;
```
`accent_hex` ist der **gedämpfte** Fuji-Ton (= dein bisheriges `$accent-dim`).
Mapping-Vorschlag:
- `$accent-dim` = `accent_hex` (1:1)
- `$accent` = `accent_hex` ~18 % Richtung Weiß aufgehellt (bright)
- `$accent-08/14/22` = `rgba(R, G, B, 0.08/0.14/0.22)` aus den RGB von `accent_hex`
(oder vom bright — wie es bei dir besser aussieht)
In SCSS kannst du das selbst ableiten, ohne die bright-Werte vorzuberechnen:
```scss
$accent-dim: #8aac8b; // = accent_hex aus gui.json
$accent: lighten($accent-dim, 8%);
$accent-08: rgba($accent-dim, 0.08);
$accent-14: rgba($accent-dim, 0.14);
$accent-22: rgba($accent-dim, 0.22);
```
Du musst also nur **eine Zeile** (`$accent-dim`) aus `gui.json` regenerieren.
### Die 5 Fuji-Akzente (falls du sie vorab kennen willst)
| key | label | accent_hex (dim) | bright (Referenz) |
|-----------|------------------|------------------|-------------------|
| `ume` | Ume · violet | `#8f8aac` | `#a39ec4` |
| `shinkai` | Shinkai · blue | `#8a98ac` | `#9fabbb` |
| `take` | Take · green | `#8aac8b` | `#9fbba0` |
| `chikyu` | Chikyū · yellow | `#aca98a` | `#bbb89f` |
| `beni` | Beni · red | `#ac8a8c` | `#bb9fa1` |
(Quelle der Hexes: `taninux/core/theme.py` — identisch zur TUI. `ume`-bright
entspricht deinem aktuellen `$accent`.)
---
## Hell/Dunkel — NICHT dein Akzent-Job
Das globale Hell/Dunkel läuft über `gsettings org.gnome.desktop.interface
color-scheme` (steht auf `prefer-dark`). TANINUX **steuert das nicht über
gui.json** und fasst es bewusst nicht an. Dein eww-Hell/Dunkel (`.light`-Klasse +
`-l`-Variablen) bleibt **vollständig deine Sache** — TANINUX mischt sich da nicht
ein. `color_scheme` in der JSON ist nur informativ; ignorier es für den Akzent.
---
## Reload-Trigger — bitte abstimmen
TANINUX schreibt `gui.json` bei jeder Änderung, ruft aktuell aber **kein
`eww reload`** auf. Zwei Optionen, einigt euch auf eine:
- **(A) eww-Seite watcht** `gui.json` (z. B. `inotifywait` / ein eww-`deflisten`
/ kleines Script) und macht selbst `eww reload`. → empfohlen, hält eww autark.
- **(B) TANINUX triggert** nach dem Schreiben `eww reload`. Sag Bescheid, dann
baue ich das in den Appearance-`persist()` ein (best-effort, nur wenn eww läuft).
---
## Grenzen (wichtig)
- TANINUX fasst `~/eww/**` **nicht** an. Die scss-Verdrahtung machst du.
- TANINUX besitzt zusätzlich `~/.config/gtk-4.0/libadwaita.css` (globaler
GTK4/libadwaita-Akzent via `@define-color`) — das ist für **GTK-Apps**, nicht
für eww. Nicht damit verwechseln; eww liest `gui.json`.
+145
View File
@@ -0,0 +1,145 @@
# eww ↔ TANINUX — Arbeits- & Koordinationsanleitung (für die TANINUX-Instanz)
**Lies das, bevor du irgendetwas anfasst, das die Bar/das Dock/eww betrifft.**
Es ist die verbindliche Spielregel zwischen dir (TANINUX-Instanz) und der
eww-Instanz, die `~/eww` besitzt. Es gibt sonst Chaos — wir hatten es schon.
---
## 0. Die EINE Regel
> **Fass `~/eww/**` nicht direkt an. Steuere Bar/Dock ausschließlich über
> Config-Dateien. Lass keinen Porter / Sync / Format-on-save über `~/eww`
> laufen.**
Warum so hart? Während gemeinsamer Arbeit hat *etwas auf deiner Seite*
(ein Sway-Porter o.ä.) `eww.yuck`, `eww.scss`, `launch.sh`, `dock.sh` **live
umgeschrieben — mitten zwischen Lesen und Schreiben der eww-Instanz.** Folge:
jeder Fix (Box-in-Box, Dock-Autohide, Flackern) wurde Sekunden später wieder
überschrieben. **Zwei Editoren auf derselben Datei = der einzige Fall, der
garantiert kaputtgeht.** Settings laufen über Config-Dateien → du brauchst eww
nie hand zu editieren.
---
## 1. Wenn du eww trotzdem ändern MUSST (Feature/Layout, kein Setting)
Es ist EIN Projekt — Code-Arbeit an der Bar ist kein Tabu. Aber:
1. **Niemals automatisiert** (kein Porter, kein Watcher, der `~/eww/**` schreibt).
2. **Einer nach dem anderen.** Sag der eww-Instanz Bescheid bzw. mach es selbst,
aber nicht *während* die eww-Instanz dieselbe Datei bearbeitet.
3. **eww ist bereits compositor-agnostisch** (siehe §4). **Portiere es nicht auf
Sway-only zurück** — das bricht es auf Hyprland und macht genau die Bugs.
---
## 2. Die Integrations-Schnittstelle (so steuerst du eww — ohne es anzufassen)
Drei Config-Dateien + ein Launcher. Detail-Verträge:
`eww-accent-integration.md`, `eww-panel-dock-integration.md`, `eww-integration.md`.
| Thema | Du schreibst | eww zieht nach via |
|------------------|------------------------------------------------|-----------------------------------------------------|
| **Akzentfarbe** | `~/.local/share/taninux/gui.json``accent_hex` (`#rrggbb`) | `scripts/accent.sh watch``$accent-dim` in scss, reload |
| **Hell/Dunkel** | `gsettings …interface color-scheme` (NICHT die JSON) | `scripts/colorscheme.sh` (defpoll) → `.light`-Klasse |
| **Panel & Dock** | `~/.local/share/taninux/panel.json` | `scripts/panelcfg.sh watch``eww update` (live) |
| **Dock-Pins** | `~/.config/eww/dock-pins` (Zeilen `exec\|class\|icon`) | Poll alle 2 s, automatisch |
| **Settings öffnen** | *(Ziel ist deine App)* | Control-Center-Zahnrad → `scripts/settings.sh``taninux-gtk` |
**`panel.json`-Schema** (v1, alles live, kein Reload):
```json
{
"version": 1,
"dock": { "autohide": true, "icon_size": 42, "hide_delay": 1.2 },
"bar": { "clock_format": "%H:%M %A, %d.%m.%Y",
"modules": { "music": true, "sys": true, "updates": true,
"net": true, "bt": true, "vol": true } }
}
```
- `dock.icon_size`: int 2464 · `dock.hide_delay`: 0.25.0 s · `dock.autohide`: bool
- `bar.clock_format`: strftime · `bar.modules`: bool je Modul (`music sys updates net bt vol`)
- Anwenden: Datei schreiben → Watcher zieht in ≤2 s nach. Für „sofort":
`~/eww/scripts/panelcfg.sh apply`.
- **Noch nicht im Schema:** `dock.position`, feste Bar/Dock-Größen (= Reload/
Geometrie-Neubau). Wenn du das in der GUI willst → bei der eww-Instanz anfragen,
nicht selbst in eww bauen.
**Grenze:** `gui.json`/`panel.json`/`dock-pins` gehören dir (schreib sie frei).
`~/.config/gtk-4.0/libadwaita.css` ist *dein* GTK-App-Akzent — **nicht** für eww.
`~/eww/**` gehört der eww-Instanz.
---
## 3. Wie ich das in TANINUX einordnen würde (Vorschlag)
Eine Seite **„Panel & Dock"** in *Personalization*, zwei Gruppen:
- **Top bar** — `bar.modules` (Toggles), `bar.clock_format`.
- **Dock** — `dock.autohide`, `dock.icon_size` (Slider 2464),
`dock.hide_delay`, gepinnte Apps (liest/schreibt `~/.config/eww/dock-pins`).
`core/panel.py` = Read/Write `panel.json` (+ `dock-pins`), Apply = Datei
schreiben **und optional** `~/eww/scripts/panelcfg.sh apply` feuern. Das ist
exakt die Akzent-Kette, nur mit mehr Keys. Du musst die eww-Variablennamen
**nicht** kennen.
---
## 4. Was in eww schon gebaut & getestet ist (Kontext, nicht ändern)
- **Compositor-Abstraktion** `~/eww/scripts/wm.sh`: erkennt Hyprland/Sway (`$WM`)
und kapselt alle WM-Befehle (`wm_clients/wm_focus/wm_goto_ws/wm_cursor_y/
wm_outputs/wm_lock/wm_exit/wm_blur_layer`). **dock.sh, power.sh, ws.sh,
workspaces.sh, launch.sh nutzen das.** → eww läuft auf beiden Compositoren.
- **Auto-hide ist compositor-aware:** Hyprland = **Cursor-Polling**
(`dock.sh watch`, kein GTK-Hover); Sway = **Hover-Trigger** (`dock-trigger`,
weil Sway kein cursorpos-IPC hat). `launch.sh` startet automatisch das Richtige.
- Akzent (gui.json), Hell/Dunkel (gsettings → Shibui-Weiß), Now-Playing im
Control Center, Updates-Panel, Power-Dropdown, Settings-Zahnrad,
Multi-Instanz-Rechtsklick, ESC/Klick-daneben-Dismiss — alles vorhanden.
---
## 5. NICHT wieder einbauen — die Bugs, die ständig zurückkamen
Wenn du (oder ein Porter) eww doch anfasst, **reintroduziere diese nicht:**
1. **Dock „Box-in-Box".** Ursache: ein **Drop-Shadow auf `.dock`**. Auf der
halbtransparenten, geblurrten Dock-Ebene blüht er in die Margin und rendert
als faler äußerer Kasten (bei opaken Panels passiert das nicht).
`.dock` darf **nur** `box-shadow: inset 0 1px 0 …` haben, **keinen Drop-Shadow**.
Zusätzlich: `window/.background/decoration { background: transparent;
box-shadow: none }` und `eventbox { background: transparent }` müssen bleiben.
2. **Dock flackert / bleibt offen auf Hyprland.** Ursache: GTK-Hover-Autohide
(`eventbox onhover/onhoverlost`). Kindbuttons feuern Enter/Leave (NotifyInferior)
→ Dauer-Toggle. → Auf Hyprland **Cursor-Polling** (`dock.sh watch`), NICHT Hover.
Genau deshalb ist die Sway-Hover-Variante **nicht** für Hyprland.
3. **Hell/Dunkel reagiert nicht.** Ursache: `gsettings monitor`-deflisten stirbt
in eww's Spawn-Env. → **defpoll** nutzen. Und: nach so einem Wechsel **vollen
eww-Neustart** (`launch.sh`), `eww reload` reicht nicht.
4. **Nerd-Font-Glyphen unsichtbar.** `button :text "glyph"` rendert nicht →
Glyphe als `label`-Kind im Button.
5. **Hyprland-Dispatch ist Lua.** `hyprctl dispatch "hl.dsp.focus({…})"`, nicht die
klassische Textsyntax. (In `wm.sh` schon gekapselt.)
---
## 6. Offene Sway-Punkte (wenn du DE-light auf swayfx fertigstellst)
- `swaylock` + `swayidle` installieren (für `power.sh` Lock).
- SwayFX-Dock-Blur zuverlässig: `layer_effects "gtk-layer-shell" blur enable` in
die Sway-Config (statt nur `wm_blur_layer`-Laufzeitversuch).
- eww-Keybinds (ESC-Dismiss, SUPER+A/N Panels) von `hyprland.lua` in die
Sway-Config übernehmen.
- Dann unter echtem Sway gegentesten — die `$WM=sway`-Zweige sind da, aber bisher
nur auf Hyprland verifiziert.
---
## TL;DR
1. eww nie automatisiert/parallel editieren. **Kein Porter über `~/eww`.**
2. Bar/Dock nur über `gui.json` + `panel.json` + `dock-pins` steuern.
3. eww ist schon dual (Hyprland+Sway) — **nicht** auf Sway-only zurückbauen.
4. Wenn du eww-Code wirklich brauchst: koordiniert, einer nach dem anderen,
und die §5-Bugs nicht wieder reinbauen.
+176
View File
@@ -0,0 +1,176 @@
# eww ↔ TANINUX — Integrations-Vertrag (Handover)
**Zweck:** Ab jetzt werden die **eww-Bar** (`~/eww`, symlinked nach `~/.config/eww`)
und die **TANINUX-Settings-App** *zusammen gedacht*. Dieses Dokument ist der
Vertrag: was über welche Datei fließt, wer was besitzt, und was man beim Ändern
der einen Seite auf der anderen beachten muss.
Gegenstück: `docs/eww-accent-integration.md` (der ursprüngliche Accent-Handoff
TANINUX → eww). Dieses Dokument hier ist die **vollständige, gelebte** Sicht.
---
## TL;DR — die Schnittstellen
| # | Thema | Quelle der Wahrheit (TANINUX schreibt) | eww liest / reagiert via |
|---|----------------|-----------------------------------------------------|--------------------------------------------------|
| 1 | **Akzentfarbe**| `~/.local/share/taninux/gui.json``accent_hex` | `~/eww/scripts/accent.sh watch` → setzt `$accent-dim` in `eww.scss`, `eww reload` |
| 2 | **Hell/Dunkel**| `gsettings org.gnome.desktop.interface color-scheme`| `~/eww/scripts/colorscheme.sh get` (defpoll 2 s) → `.light`-Klasse an den Panels |
| 3 | **Compositor** | *(unabhängig erkannt — keine Datei)* | `~/eww/scripts/wm.sh` erkennt `hyprland`/`sway` selbst |
| 4 | **Settings öffnen** | *(App ist das Ziel)* | eww Control-Center-Zahnrad → `~/eww/scripts/settings.sh``taninux-gtk` |
Kurz: **Akzent läuft über die JSON, Hell/Dunkel über gsettings, Compositor
erkennt jede Seite selbst.** Diese drei Achsen müssen konsistent bleiben.
---
## 1. Akzentfarbe — `gui.json` → eww
- **TANINUX schreibt** bei jeder Akzent-Änderung `~/.local/share/taninux/gui.json`,
Feld `accent_hex` (fertiger Hex, z. B. `#8f8aac`). Schema siehe
`eww-accent-integration.md`.
- **eww** hat einen Watcher `scripts/accent.sh watch` (gestartet aus
`~/eww/launch.sh`), der `gui.json` alle 2 s auf mtime-Änderung pollt und bei
Änderung:
- `accent_hex` liest (Fallback `#8f8aac`, wenn Datei/Feld fehlt/ungültig),
- damit **nur die eine Zeile** `$accent-dim:` in `~/eww/eww.scss` neu schreibt,
- `eww reload` auslöst.
- In der SCSS leiten sich **alle** Akzent-Werte aus `$accent-dim` ab:
```scss
$accent-dim: #8f8aac; // = accent_hex (von accent.sh verwaltet)
$accent: lighten($accent-dim, 8%);
$accent-08: rgba($accent, 0.08);
$accent-14: rgba($accent, 0.14);
$accent-22: rgba($accent, 0.22);
```
- **Verifiziert:** Akzent in der App auf z. B. `take`/grün stellen → Bar/Panels/
Dock tinten innerhalb ~2 s nach.
**Wenn TANINUX hier etwas ändert:** Solange `accent_hex` ein `#rrggbb` bleibt,
muss eww **nichts** angepasst werden. Neue Akzent-Keys (über die 5 Fuji-Töne
hinaus) brauchen nur einen gültigen Hex — eww ist farbagnostisch.
---
## 2. Hell/Dunkel — gsettings (NICHT die JSON)
**Klare Abgrenzung:** Hell/Dunkel läuft **global über
`gsettings org.gnome.desktop.interface color-scheme`** (`prefer-dark` /
`prefer-light` / `default`). Das `color_scheme`-Feld in `gui.json` ist für eww
**nur informativ und wird ignoriert.**
- **TANINUX** setzt beim Umschalten die gsettings-Keys (`gui/desktop.py`,
`gsettings set …`). Das ist der globale Standard und greift für alle GTK-Apps.
- **eww** pollt `scripts/colorscheme.sh get` (defpoll, 2 s) → `light`/`dark` und
hängt eine `.light`-Klasse an alle Panels/Dock (Bar bleibt immer dunkel).
Hell = „Shibui"-Weiß-Palette in `eww.scss` (`$bg-l`, `$fg-l`, …).
- **Wichtig (Lesson learned):** Ein `gsettings monitor`-Deflisten **stirbt** in
eww's Spawn-Umgebung — deshalb **defpoll**, nicht monitor. Und: ein
`deflisten→defpoll`-Wechsel braucht einen **vollen eww-Neustart**
(`launch.sh`), ein `eww reload` reicht nicht.
**Vertrag:** Damit eww dem App-Umschalter folgt, **muss TANINUX die gsettings
tatsächlich setzen** (nicht nur `gui.json.color_scheme`). Tut es das nicht,
bleibt eww auf dem alten Modus — das ist dann ein TANINUX-Bug, kein eww-Bug.
(Beobachtet: einmal stand `gui.json=light`, aber `gsettings=prefer-dark` →
eww blieb korrekterweise dunkel.)
---
## 3. Compositor-Erkennung — beide Seiten, unabhängig
Beide Apps müssen auf **Hyprland UND Sway/SwayFX** laufen. Es gibt **keine
geteilte Datei** dafür — jede Seite erkennt selbst:
- **TANINUX:** eigene Compositor-Erkennung (von dir gebaut).
- **eww:** `~/eww/scripts/wm.sh` — eine sourcebare Abstraktion. Erkennt über
`$HYPRLAND_INSTANCE_SIGNATURE` / `$SWAYSOCK` / `pgrep` und setzt `$WM`.
Bietet einheitliche Funktionen, die alle eww-Scripts nutzen:
| Funktion | Hyprland | Sway / SwayFX |
|-----------------------|---------------------------------------|---------------------------------------|
| `wm_clients` | `hyprctl clients -j` | `swaymsg -t get_tree` |
| `wm_focus <id>` | `hl.dsp.focus({window="address:…"})` | `[con_id=…] focus` |
| `wm_goto_ws` / `cycle`| `hl.dsp.focus({workspace=…})` | `workspace number …` |
| `wm_cursor_y` | `hyprctl cursorpos` | *(kein Cursor-IPC → Menü zentriert)* |
| `wm_outputs` | `hyprctl monitors` | `swaymsg -t get_outputs` |
| `wm_lock` / `wm_exit` | `hyprlock` / `hl.dsp.exit()` | `swaylock -f` / `swaymsg exit` |
| `wm_blur_layer` | `hyprctl keyword layerrule blur,…` | SwayFX `layer_effects … blur enable` |
Genutzt von: `dock.sh`, `power.sh`, `ws.sh`, `workspaces.sh`, `launch.sh`.
**Hyprland-Eigenheit:** Dispatch läuft auf diesem Setup über die **Lua-API**
(`hyprctl dispatch "hl.dsp.…()"`), nicht über die klassische Textsyntax.
`hl.dsp.focus` springt automatisch auf den Workspace des Fensters.
**Konsistenz-Regel:** Wenn TANINUX seine Compositor-Erkennung ändert (neue
Compositor, andere Detektion), sollte `wm.sh` dieselbe Logik spiegeln, damit
beide Apps nie auseinanderlaufen. Idealerweise teilt man sich später *eine*
Detektionsquelle — aktuell bewusst getrennt (keine harte Kopplung).
---
## 4. eww startet die Settings-App
Das **Zahnrad oben rechts im Control Center** öffnet die TANINUX-GUI:
`~/eww/scripts/settings.sh` → `cd ~/projects/taninux && setsid -f env
PYTHONPATH=src /usr/bin/python -m taninux.gui`.
- **System-Python**, nicht das venv — das venv hat **kein `gi`/PyGObject**
(Systempaket). Entry point laut `pyproject.toml`: `taninux-gtk =
taninux.gui.app:main`.
- Single-Instance über die GTK-App-ID `ch.gabrielevarano.Taninux` → zweiter
Klick fokussiert nur.
**Wenn TANINUX die Startweise ändert** (z. B. richtig installiertes
`taninux-gtk` mit `gi` im venv, oder ein `.desktop`/Binary auf dem PATH):
`scripts/settings.sh` entsprechend anpassen — am besten auf `taninux-gtk`,
sobald es ohne `PYTHONPATH=src`-Hack läuft.
---
## Datei- & Besitz-Karte
| Pfad | Besitzer | Rolle |
|----------------------------------------------|-----------|-------|
| `~/.local/share/taninux/gui.json` | TANINUX | Akzent (`accent_hex`) — eww liest |
| `gsettings …interface color-scheme` | TANINUX | Hell/Dunkel global — eww liest |
| `~/.config/gtk-4.0/libadwaita.css` | TANINUX | **GTK-App-Akzent** — *nicht* für eww, nicht anfassen |
| `~/eww/**` (yuck, scss, scripts) | **eww** | Bar/Panels/Dock — TANINUX fasst das **nie** an |
| `~/eww/scripts/wm.sh` | eww | Compositor-Abstraktion |
| `~/eww/scripts/accent.sh` | eww | gui.json → `$accent-dim` |
| `~/eww/scripts/colorscheme.sh` | eww | gsettings → light/dark |
| `~/eww/scripts/settings.sh` | eww | startet TANINUX-GUI |
**Goldene Regel:** TANINUX schreibt **nie** in `~/eww/**`; eww schreibt **nie**
in TANINUX-Dateien (außer es liest `gui.json` und startet die GUI). Die
SCSS-Verdrahtung gehört eww, die Settings-Logik gehört TANINUX.
---
## Checkliste beim Ändern
**TANINUX-Seite ändert Akzent-Format?** → nur prüfen, dass `accent_hex` ein
`#rrggbb` bleibt. Sonst nichts.
**TANINUX-Seite ändert Hell/Dunkel-Mechanik?** → muss weiterhin `gsettings
color-scheme` setzen. eww hängt daran.
**Neuer Compositor unterstützt?** → `wm.sh` um einen `$WM`-Zweig erweitern
(dieselben Funktionen implementieren). Sonst läuft die Bar dort nicht.
**Settings-Startweg ändert sich?** → `~/eww/scripts/settings.sh` anpassen.
---
## Status (Stand dieser Übergabe)
- ✅ Akzent live aus `gui.json` (getestet: ume/violet ↔ take/green).
- ✅ Hell/Dunkel live aus gsettings (Shibui-Hell-Palette, Bar bleibt dunkel).
- ✅ Compositor-Abstraktion `wm.sh` — auf **Hyprland verifiziert**; Sway-Zweige
implementiert (final unter Sway noch gegenzutesten).
- ✅ Settings-Zahnrad startet `taninux-gtk` (System-Python).
- ⚠️ Für Sway fehlen noch **`swaylock` + `swayidle`** (Pakete installieren).
- ⚠️ SwayFX-Blur fürs Dock: `wm_blur_layer` versucht `layer_effects` live;
zuverlässiger ist die Regel in der SwayFX-Config (`layer_effects
"gtk-layer-shell" blur enable`).
+134
View File
@@ -0,0 +1,134 @@
# TANINUX → eww: Panel & Dock — Settings-Vertrag (Handover)
**Für die TANINUX-Instanz, die die „Panel & Dock"-Seite baut.** Analog zur
Akzent-Kette: **TANINUX schreibt EINE Config-Datei, eww konsumiert sie.** Die
eww-Seite (Variablen, `:style`/`:visible`, Watcher) ist **bereits gebaut** — du
brauchst nur die Datei zu schreiben.
Gegenstücke: `eww-accent-integration.md` (Akzent), `eww-integration.md` (Gesamtvertrag).
---
## 1. Wo die Werte liegen
**Datei:** `~/.local/share/taninux/panel.json`
(`$XDG_DATA_HOME/taninux/panel.json`, Fallback `~/.local/share/...`) — JSON,
**eine** Datei, neben `gui.json`. Existiert mit Defaults; eww seedet sie zur Not.
```json
{
"version": 1,
"dock": {
"autohide": true,
"icon_size": 42,
"hide_delay": 1.2
},
"bar": {
"clock_format": "%H:%M %A, %d.%m.%Y",
"modules": {
"music": true, "sys": true, "updates": true,
"net": true, "bt": true, "vol": true
}
}
}
```
---
## 2. Die Knöpfe (Keys, Typ, erlaubte Werte)
| Key | Typ | Werte / Range | Wirkung in eww | Live? |
|----------------------|----------------|--------------------------|-------------------------------------------------|-------|
| `dock.autohide` | bool | `true` / `false` | `false` = Dock immer sichtbar; `true` = Hover-Trigger | live |
| `dock.icon_size` | int | **24 64** (px) | Icon-Größe im Dock (`:style min-width/height`) | live |
| `dock.hide_delay` | number | **0.2 5.0** (Sekunden) | Nachhall, bis das Dock nach Verlassen schließt | next-hide |
| `bar.clock_format` | string | strftime (z.B. `%H:%M`) | Format der Uhr in der Bar-Mitte | ≤10 s |
| `bar.modules` | object<bool> | Keys: `music sys updates net bt vol` | Welche Rechts-Module die Bar zeigt | live |
| `updates.include_aur`| bool | `true`/`false` (Default false) | AUR im Update-Scope (Zähler+Liste). Opt-in, braucht paru | poll |
- **`updates.include_aur`** (Top-Level-Sektion `updates`): TANINUX-Hub macht AUR
zum Opt-in (Default Repo+Flatpak). `scripts/updates.sh` soll diesen Key lesen
und nur dann `paru -Qua` mitzählen/-listen. JSON-Schema der Liste bleibt
`[{name, old, new}]` (gern + `src`). Beispiel-Lesen:
`inc=$(jq -r '.updates.include_aur // false' "$PANEL_JSON")`.
- **`bar.modules`** ist ein Objekt `{ "<modul>": true/false }` (nicht Liste) —
fehlt ein Key, gilt er als sichtbar. Module: `music` (Now-Playing-Mini),
`sys` (CPU/RAM), `updates` (Update-Zähler), `net`, `bt`, `vol`.
- Clamping macht eww defensiv (icon_size 2464, ungültiges → Default). Trotzdem
bitte in der GUI validieren (Spin 2464, Slider 0.25.0).
**Noch nicht im v1 (bewusst):** `dock.position` (left/bottom/right) und feste
Größen der Bar/Dock-Fenster. Die brauchen `eww reload` + Geometrie-Neubau
(Orientierungswechsel bei bottom). Sag Bescheid, wenn du das willst — dann
erweitere ich die eww-Seite und dieses Doc; bis dahin nicht in der GUI anbieten.
---
## 3. Wie man anwendet
Du schreibst `panel.json`**mehr nicht**. eww zieht nach, auf zwei Wegen:
1. **Automatisch:** ein Watcher (`scripts/panelcfg.sh watch`, läuft aus
`launch.sh`) pollt die Datei alle 2 s und wendet Änderungen an.
2. **Sofort (optional, empfohlen für „Apply"):** nach dem Schreiben einmal
```
~/eww/scripts/panelcfg.sh apply
```
feuern — dann greift es ohne die 2-s-Latenz. (Best-effort, schadet nie.)
**Kein `eww reload` nötig** für die v1-Knöpfe. Intern macht `panelcfg.sh`:
`eww update cfg-icon-size=… cfg-modules=…`, schaltet Autohide imperativ, und
`clock_format`/`hide_delay` werden on-demand gelesen. (Du musst die
eww-Variablennamen **nicht** kennen — nur `panel.json` schreiben.)
---
## 4. Die Grenze — wer schreibt was
- **`panel.json` gehört dir (TANINUX).** Schreib es frei. eww liest es nur.
- **Gepinnte Dock-Apps** liegen NICHT in `panel.json`, sondern in
`~/.config/eww/dock-pins` — eine simple Zeilen-Datei, Format **`exec|class|icon`**:
```
librewolf|librewolf|librewolf
kitty|kitty|kitty
code|Code|code-oss
```
- `exec` = Startbefehl, `class` = Fensterklasse (app_id/WM_CLASS), `icon` =
Icon-Name (Papirus). eww spiegelt Änderungen automatisch (Poll alle 2 s).
- **Die Zeilen-REIHENFOLGE = die Dock-Reihenfolge.** → **Drag & Drop bitte hier
bauen:** Die „Dock"-Gruppe zeigt die gepinnten Apps als ziehbare GTK-Liste;
beim Loslassen schreibst du `dock-pins` in der neuen Reihenfolge neu. eww
sortiert das Dock in ≤2 s nach. Echtes DnD im eww-Dock selbst geht nicht
(eww/GTK3 hat keine Drag-Primitiven) — deshalb gehört das in deine GTK-Seite.
(eww bietet zusätzlich „Move up/Move down" im Dock-Rechtsklick als
Schnell-Option — die schreibt dieselbe Datei.)
- **Du darfst diese Datei direkt lesen UND schreiben** (z.B. die Pin-Liste in
der GUI verwalten). eww mutiert sie auch selbst (Dock-Rechtsklick →
Pin/Unpin). Zwei-Wege ist ok, weil das Format trivial und idempotent ist —
schreib die ganze Datei neu, eww liest sie beim nächsten Poll.
- Falls du lieber Befehle feuerst statt zu schreiben:
`~/eww/scripts/dock.sh pin <class>` / `unpin <class>`.
- **`~/eww/**` (yuck/scss/andere scripts)** ist eww-intern. Für *Settings*
brauchst du das nie anzufassen — alles läuft über `panel.json` + `dock-pins`.
### Darfst du eww trotzdem direkt anfassen?
Ja — für *Code/Feature*-Arbeit an der Bar selbst (neue Widgets, Layout) ist es
EIN Projekt, kein Tabu. **Einzige harte Regel: nie zwei Editoren gleichzeitig
auf derselben Datei** (genau das hat beim Hyprland→Sway-Umbau Chaos gemacht).
Für *Settings* aber gilt: über `panel.json` gehen, nicht eww hand-editieren —
sonst ist jede GUI-Änderung ein yuck-Edit (brittle + Race-Gefahr).
---
## Status (gebaut & getestet)
- ✅ `panel.json` (Default vorhanden) + `scripts/panelcfg.sh` (apply/watch/get).
- ✅ `dock.icon_size` live (2464, getestet 42↔56), `bar.modules` live,
`dock.autohide` imperativ, `bar.clock_format` via `scripts/clock.sh`,
`dock.hide_delay` aus der JSON gelesen.
- ✅ Watcher in `launch.sh` eingetragen.
- ⏳ `dock.position`/Fenstergrößen = Reload-Thema, auf Anfrage.
Damit kannst du `core/panel.py` (Read/Write `panel.json` + optional `dock-pins`,
Apply = Datei schreiben + `panelcfg.sh apply`) und die GTK-Seite „Panel & Dock"
(Gruppen *Top bar* / *Dock*) direkt bauen.