From a4569795e8e411195fe9d7ed6b242d19c8f36289 Mon Sep 17 00:00:00 2001 From: Karim Date: Thu, 18 Jun 2026 22:13:59 +0200 Subject: [PATCH] Wire niri desktop: tanin-eww, tanin-desktop (niri), tanin-setup theme follower - tanin-eww: package eww shell config + niri config -> /usr/share/tanin/skel/.config (dev paths rewritten to ~/.config/eww; niri spawn-at-startup uses sh -c) - tanin-desktop: switch metapackage from Hyprland to the niri stack (niri, greetd+tanin-greet, cage, eww stack, xdg-desktop-portal-gnome, fonts) - tanin-setup: apply Fuji theme + enable tanin-libadwaita.service on first run - tanin-libadwaita: ship systemd user service (color-scheme watcher) - distro manifest synced; drop stale regreet references Co-Authored-By: Claude Opus 4.8 --- distro/MANIFEST.md | 11 +- distro/camel.toml | 21 +- packaging/tanin-eww/PKGBUILD | 53 +++++ packaging/tanin-eww/niri-config.kdl | 195 ++++++++++++++++++ packaging/tanin-libadwaita/PKGBUILD | 2 + .../tanin-libadwaita/tanin-libadwaita.service | 13 ++ packaging/tanin-setup/tanin-setup | 21 +- 7 files changed, 294 insertions(+), 22 deletions(-) create mode 100644 packaging/tanin-eww/PKGBUILD create mode 100644 packaging/tanin-eww/niri-config.kdl create mode 100644 packaging/tanin-libadwaita/tanin-libadwaita.service diff --git a/distro/MANIFEST.md b/distro/MANIFEST.md index 4bc8cc2..f881fd5 100644 --- a/distro/MANIFEST.md +++ b/distro/MANIFEST.md @@ -54,14 +54,14 @@ AUR → OPT-IN only (paru = optdepend) | `taninux` | tsettings + thub + TUI, helper, polkit, .desktop | ready | | `tanin-greet` | custom GTK4 greeter for greetd → `/etc/greetd/` | ready (preview) | | `tanin-libadwaita` | Fuji libadwaita recolour, light + dark (pills) | ready (preview) | -| `tanin-eww` | eww config + scripts → `/usr/share/tanin/skel` | **todo** | +| `tanin-eww` | eww bar/dock/panels + niri config → `/usr/share/tanin/skel/.config` | ready | | `tanin-setup` | seed `~/.config` + enable session target | ready | -| `tanin-desktop` | metapackage pulling the whole environment (niri) | ready (needs tanin-eww) | +| `tanin-desktop` | metapackage pulling the whole environment (niri) | ready | **Rebuilt AUR deps** — the desktop's hard requirements that aren't in the official repos. We rebuild them into `[tanin]` so `tanin-desktop` can hard-depend on them **without the AUR** (binary repos must never need it): `eww`, `tiramisu`, -`waypaper`, `regreet`, `cliphist`. ⚠️ Verify each before publishing — any that +`waypaper`, `cliphist`. ⚠️ Verify each before publishing — any that turn out to live in `extra` should be dropped from this list. The full Arch package set (compositor, portals, audio, connectivity, fonts, …) @@ -79,13 +79,13 @@ waypaper/cliphist) are exactly why `[tanin]` must carry rebuilt AUR packages. ## Delivery 1. **Foundation** — `taninux` builds (`makepkg -si`). ✅ -2. **Meta + config** — finish `tanin-eww`; update `tanin-desktop` to niri; keep +2. **Meta + config** — ✅ `tanin-eww`, `tanin-desktop` (niri), `tanin-greet`, `tanin-libadwaita`, `tanin-setup`. Dotfiles ship to `/usr/share/tanin/skel`, never to `/home` at package time; `tanin-setup` seeds them on first run. 3. **`[tanin]` repo** — `repo-add -s` to build+sign the DB. Host as a Gitea/Forgejo Arch registry **or** a static dir behind `taninux.kgva.ch`. 4. **ISO** — archiso profile with `[tanin]` pre-configured; Calamares `packages` - module installs `tanin-desktop`; greetd+regreet enabled; session target wired. + module installs `tanin-desktop`; greetd + tanin-greet enabled; session target wired. ### Session / dark-mode fix libadwaita apps read light/dark via `org.freedesktop.portal.Settings`, which @@ -100,7 +100,6 @@ systemctl --user start tanin-session.target - **Name:** keep TANINUX, or split `app = tanin` / `OS = `? - **Repo hosting:** Gitea Arch registry vs static dir behind `taninux.kgva.ch`. - **Signing:** move `[tanin]` to `SigLevel = Required` + distribute the key. -- **regreet theme:** author its GTK CSS to the Fuji accent. - **AUR check:** confirm which rebuilt-AUR entries are already in `extra`. - **Blur/shadow:** niri `layer-rule` blur+shadow for eww layers (template is commented in the niri config). diff --git a/distro/camel.toml b/distro/camel.toml index 3ad55c5..f086086 100644 --- a/distro/camel.toml +++ b/distro/camel.toml @@ -85,10 +85,11 @@ status = "ready" [[packages.own]] name = "tanin-eww" -desc = "eww bar/dock/panels/spotlight config + scripts -> /usr/share/tanin/skel" -upstream = "~/projects/eww" -pkgbuild = "packaging/tanin-eww/PKGBUILD" # TODO: create -status = "todo" +desc = "eww bar/dock/panels/spotlight + niri config -> /usr/share/tanin/skel/.config" +upstream = "~/projects/eww (local build; EWW_SRC override). Publish: own eww git repo." +pkgbuild = "packaging/tanin-eww/PKGBUILD" # exists +status = "ready (built from local eww; niri config vendored + path-fixed)" +note = "ships ~/.config/{eww,niri}; rewrites $HOME/projects/eww -> $HOME/.config/eww; niri spawn-at-startup uses sh -c so $HOME expands" [[packages.own]] name = "tanin-greet" @@ -101,21 +102,22 @@ note = "replaces ReGreet — its fixed layout couldn't do topbar/corner-sess name = "tanin-libadwaita" desc = "Fuji recolour for GTK4/libadwaita + GTK3 — light + dark, pill controls" pkgbuild = "packaging/tanin-libadwaita/PKGBUILD" # exists -status = "ready (live-verified GTK4; GTK3 partial)" +status = "ready (live-verified GTK4; GTK3 partial) + ships tanin-libadwaita.service (user, watch)" note = "STATIC defaults + CLI (tanin-libadwaita {dark|light|auto|watch}) for greeter/first-boot. LIVE theming is driven by the taninux app: gui/style.py write_global_theme() regenerates ~/.config/gtk-{4.0,3.0}/gtk(.css)|libadwaita.css from the Appearance settings (dynamic accent + light/dark, surfaces #0f0f0f/#f0f0f0, pills). GTK4/libadwaita = full exact Fuji; GTK3/adw-gtk3 = light/dark + pills only (GTK3 @define-color is parse-time, so adw-gtk3's accent/surfaces can't be overridden — exact-Fuji GTK3 would need a standalone GTK3 theme)." [[packages.own]] name = "tanin-setup" -desc = "first-run: seed ~/.config from /usr/share/tanin/skel + enable session target" +desc = "first-run: seed ~/.config (eww+niri) + session target + apply theme + enable follower" pkgbuild = "packaging/tanin-setup/PKGBUILD" # exists -status = "ready" +status = "ready (wires theme follower)" +note = "seed_configs + install tanin-session.target + tanin-libadwaita auto + systemctl --user enable --now tanin-libadwaita.service. niri config (tanin-eww) autostarts dbus-update-activation-environment + tanin-session.target." [[packages.own]] name = "tanin-desktop" desc = "metapackage — depends-pulls the whole environment (own + Arch)" pkgbuild = "packaging/tanin-desktop/PKGBUILD" # exists type = "meta" -status = "ready (niri stack; depends tanin-eww which is still todo)" +status = "ready (niri stack; all own deps now exist)" # ============================================================================= # REBUILT AUR DEPS — hard requirements of the desktop that are NOT in the @@ -149,7 +151,7 @@ verify = "extra? else AUR" # ============================================================================= [packages.arch] compositor = ["niri"] -greeter = ["greetd", "cage"] # cage hosts the GTK greeter; regreet is in rebuilt_aur until confirmed in extra +greeter = ["greetd", "cage"] # cage hosts our own tanin-greet (GTK4); no regreet portals = ["xdg-desktop-portal", "xdg-desktop-portal-gtk", "xdg-desktop-portal-gnome"] toolkit = ["gtk4", "libadwaita", "gtk3", "python", "python-gobject"] terminal = ["foot"] @@ -198,6 +200,5 @@ project = "taninux.kgva.ch" # homepage + [tanin] pacman Ser name = "Final project/OS name: keep TANINUX, or split app=tanin / OS=?" repo_hosting = "Gitea/Forgejo Arch registry vs static dir behind taninux.kgva.ch" signing = "Move [tanin] SigLevel to Required + distribute the packager key" -regreet_theme = "Author the regreet GTK config/CSS to the Fuji palette (accent #a39ec4)" aur_repo_check = "Confirm which rebuilt_aur entries are actually in extra (drop those)" blur_shadow = "niri layer-rule blur/shadow for eww layers (template commented in niri config)" diff --git a/packaging/tanin-eww/PKGBUILD b/packaging/tanin-eww/PKGBUILD new file mode 100644 index 0000000..70a89cf --- /dev/null +++ b/packaging/tanin-eww/PKGBUILD @@ -0,0 +1,53 @@ +# Maintainer: Karim +# +# tanin-eww — the TANINUX desktop shell config: eww bar/dock/panels/spotlight + +# the niri compositor config. Ships into /usr/share/tanin/skel/.config; tanin-setup +# seeds it into ~/.config on first run (packages must not write to /home). +# +# Local build pulls the live config from $HOME/projects/eww (override with +# EWW_SRC=...). For publish, point `source` at the eww config git repo instead. +pkgname=tanin-eww +pkgver=0.1.0 +pkgrel=1 +pkgdesc="TANINUX desktop shell — eww bar/dock/panels/spotlight + niri config (skel)" +arch=('any') +url="https://taninux.kgva.ch" +license=('GPL-3.0-or-later') +depends=( + 'niri' 'eww' # compositor + the widget toolkit + 'jq' 'wl-clipboard' # used throughout the scripts + 'tiramisu' 'waypaper' 'cliphist' # notifications · wallpaper · clipboard history + 'brightnessctl' 'playerctl' 'libqalculate' # backlight · media · calc (qalc) + 'grim' 'slurp' # screenshots + 'networkmanager' 'bluez-utils' 'wireplumber' # net/bt/audio module backends + 'ttf-iosevka-nerd' 'inter-font' 'papirus-icon-theme' # glyphs · UI font · dock icons +) +optdepends=( + 'wlsunset: night light (niri autostart)' + 'nm-applet: tray network applet (niri autostart)' + 'waybar: fallback bar if eww is missing' +) +# source=("git+https://git.openbureau.ch/karim/tanin-eww.git#tag=v$pkgver") # publish +# sha256sums=('SKIP') + +package() { + local eww="${EWW_SRC:-$HOME/projects/eww}" + local skel="$pkgdir/usr/share/tanin/skel/.config" + install -d "$skel/eww/scripts" "$skel/eww/data" "$skel/niri" + + # --- eww config (skip HANDOVER.md / README.md) --- + install -Dm644 "$eww/eww.yuck" "$skel/eww/eww.yuck" + install -Dm644 "$eww/eww.scss" "$skel/eww/eww.scss" + install -Dm644 "$eww/dock-pins" "$skel/eww/dock-pins" + install -Dm755 "$eww/launch.sh" "$skel/eww/launch.sh" + cp -r "$eww/scripts/." "$skel/eww/scripts/" + chmod 755 "$skel/eww/scripts/"*.sh + [ -d "$eww/data" ] && cp -r "$eww/data/." "$skel/eww/data/" || true + + # --- de-hardcode dev paths -> the seeded location (~/.config/eww) --- + sed -i 's|$HOME/projects/eww|$HOME/.config/eww|g' \ + "$skel/eww/scripts/accent.sh" "$skel/eww/scripts/doupdate.sh" + + # --- niri compositor config (vendored, eww paths already fixed) --- + install -Dm644 "$startdir/niri-config.kdl" "$skel/niri/config.kdl" +} diff --git a/packaging/tanin-eww/niri-config.kdl b/packaging/tanin-eww/niri-config.kdl new file mode 100644 index 0000000..7d90251 --- /dev/null +++ b/packaging/tanin-eww/niri-config.kdl @@ -0,0 +1,195 @@ +// niri config — ported from the Hyprland/eww setup. +// Docs: https://niri-wm.github.io/niri/ · validate with `niri validate`. + +input { + keyboard { + xkb { + layout "ch" + } + numlock + } + touchpad { + tap + } + mouse {} +} + +// Outputs — scale 1.25 like the Hyprland setup. Mode omitted on purpose so niri +// picks the highest refresh rate automatically (144 Hz on DP-3). Positions are +// left to niri's auto-placement. +output "DP-3" { + scale 1.25 +} +output "HDMI-A-1" { + scale 1.25 +} + +layout { + gaps 10 + center-focused-column "never" + + preset-column-widths { + proportion 0.33333 + proportion 0.5 + proportion 0.66667 + } + default-column-width { proportion 0.5; } + + // Fuji violet accent on the focus ring. + focus-ring { + width 3 + active-color "#a39ec4" + inactive-color "#505050" + } + border { + off + } + + // Subtle window shadow for depth. + shadow { + on + softness 20 + spread 3 + offset x=0 y=4 + color "#00000070" + } +} + +// ---- autostart ------------------------------------------------------------ +// Bring up the systemd user session so portals (dark mode via +// org.freedesktop.portal.Settings) and TANINUX user services start. +spawn-at-startup "dbus-update-activation-environment" "--systemd" "--all" +spawn-at-startup "systemctl" "--user" "start" "tanin-session.target" +spawn-at-startup "/bin/sh" "-c" "$HOME/.config/eww/launch.sh" +spawn-at-startup "waypaper" "--restore" +spawn-at-startup "wlsunset" "-l" "47" "-L" "8.3" "-d" "600" "-t" "4000" "-T" "6500" +spawn-at-startup "nm-applet" +spawn-at-startup "/usr/lib/polkit-gnome/polkit-gnome-authentication-agent-1" +spawn-at-startup "nextcloud" "--background" + +hotkey-overlay { + skip-at-startup +} + +screenshot-path "~/Pictures/Screenshots/Screenshot from %Y-%m-%d %H-%M-%S.png" + +animations { + // On by default. Uncomment to disable everything: + // off +} + +// Ask apps to drop their client-side decorations (title/header bars); niri then +// draws only its own border/focus-ring. Apps that honour the protocol lose the +// top bar. (Some GTK apps ignore it and keep their headerbar — that's the app.) +prefer-no-csd + +// Rounded corners for all windows. +window-rule { + geometry-corner-radius 14 + clip-to-geometry true +} + +// ---- eww frosted-glass / effects (enable after first boot) ---------------- +// niri's layer-shell effects are version-sensitive; once niri runs we verify the +// real namespace with `niri msg --json layers` and enable blur/rounding/shadow. +// /-layer-rule { +// match namespace="^gtk-layer-shell$" +// geometry-corner-radius 14 +// shadow { on; softness 8; spread 0; offset x=0 y=2; color "#00000088"; } +// } + +binds { + Mod+Shift+Slash { show-hotkey-overlay; } + + // --- launchers / apps (Hyprland muscle memory) --- + Mod+Backspace hotkey-overlay-title="Terminal: kitty" { spawn "kitty"; } + Mod+T hotkey-overlay-title="Terminal: kitty" { spawn "kitty"; } + Mod+E hotkey-overlay-title="Files: nautilus" { spawn "nautilus"; } + Mod+Space hotkey-overlay-title="Apps: Spotlight" { spawn-sh "$HOME/.config/eww/scripts/spotlight.sh open"; } + Mod+C hotkey-overlay-title="Calc: rofi" { spawn-sh "rofi -show calc"; } + + // --- eww panels --- + Mod+A hotkey-overlay-title="Control Center" { spawn-sh "$HOME/.config/eww/scripts/panel.sh toggle control-center"; } + Mod+N hotkey-overlay-title="Calendar" { spawn-sh "$HOME/.config/eww/scripts/panel.sh toggle calendar"; } + Mod+Shift+R hotkey-overlay-title="Restart bar" { spawn-sh "$HOME/.config/eww/launch.sh"; } + // Panic-close: dismiss any open/stuck eww overlay (niri has no global Escape + // bind; a stuck :focusable spotlight would otherwise hold the keyboard). + Mod+Escape hotkey-overlay-title="Close overlays" { spawn-sh "$HOME/.config/eww/scripts/dismiss.sh"; } + + // --- window management --- + Mod+W { close-window; } + Mod+F { toggle-window-floating; } + Mod+Shift+F { fullscreen-window; } + Mod+M { maximize-column; } + Mod+V { switch-focus-between-floating-and-tiling; } + Mod+R { switch-preset-column-width; } + Mod+Minus { set-column-width "-10%"; } + Mod+Equal { set-column-width "+10%"; } + + // --- focus (arrows + hjkl) --- + Mod+Left { focus-column-left; } + Mod+Right { focus-column-right; } + Mod+Up { focus-window-up; } + Mod+Down { focus-window-down; } + Mod+H { focus-column-left; } + Mod+L { focus-column-right; } + Mod+K { focus-window-up; } + Mod+J { focus-window-down; } + + // --- move columns/windows --- + Mod+Ctrl+Left { move-column-left; } + Mod+Ctrl+Right { move-column-right; } + Mod+Ctrl+Up { move-window-up; } + Mod+Ctrl+Down { move-window-down; } + + // --- workspaces (focus + move, Hyprland-style Shift to move) --- + Mod+1 { focus-workspace 1; } + Mod+2 { focus-workspace 2; } + Mod+3 { focus-workspace 3; } + Mod+4 { focus-workspace 4; } + Mod+5 { focus-workspace 5; } + Mod+6 { focus-workspace 6; } + Mod+7 { focus-workspace 7; } + Mod+8 { focus-workspace 8; } + Mod+9 { focus-workspace 9; } + Mod+Shift+1 { move-column-to-workspace 1; } + Mod+Shift+2 { move-column-to-workspace 2; } + Mod+Shift+3 { move-column-to-workspace 3; } + Mod+Shift+4 { move-column-to-workspace 4; } + Mod+Shift+5 { move-column-to-workspace 5; } + Mod+Shift+6 { move-column-to-workspace 6; } + Mod+Shift+7 { move-column-to-workspace 7; } + Mod+Shift+8 { move-column-to-workspace 8; } + Mod+Shift+9 { move-column-to-workspace 9; } + + Mod+Page_Down { focus-workspace-down; } + Mod+Page_Up { focus-workspace-up; } + Mod+WheelScrollDown cooldown-ms=150 { focus-workspace-down; } + Mod+WheelScrollUp cooldown-ms=150 { focus-workspace-up; } + + // --- multi-monitor --- + Mod+Shift+Left { focus-monitor-left; } + Mod+Shift+Right { focus-monitor-right; } + + // --- screenshots (Mod+Y = region, like hyprshot) --- + Mod+Y { screenshot; } + Print { screenshot; } + Ctrl+Print { screenshot-screen; } + + // --- media / volume / brightness (work when locked) --- + XF86AudioRaiseVolume allow-when-locked=true { spawn-sh "wpctl set-volume -l 1 @DEFAULT_AUDIO_SINK@ 5%+"; } + XF86AudioLowerVolume allow-when-locked=true { spawn-sh "wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-"; } + XF86AudioMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; } + XF86AudioMicMute allow-when-locked=true { spawn-sh "wpctl set-mute @DEFAULT_AUDIO_SOURCE@ toggle"; } + XF86AudioPlay allow-when-locked=true { spawn-sh "playerctl play-pause"; } + XF86AudioNext allow-when-locked=true { spawn-sh "playerctl next"; } + XF86AudioPrev allow-when-locked=true { spawn-sh "playerctl previous"; } + XF86MonBrightnessUp allow-when-locked=true { spawn "brightnessctl" "set" "5%+"; } + XF86MonBrightnessDown allow-when-locked=true { spawn "brightnessctl" "set" "5%-"; } + + // --- session --- + Super+Alt+L { spawn "swaylock" "-f"; } + Mod+Shift+E { quit; } + Ctrl+Alt+Delete { quit; } + Mod+Shift+P { power-off-monitors; } +} diff --git a/packaging/tanin-libadwaita/PKGBUILD b/packaging/tanin-libadwaita/PKGBUILD index b26285e..df91094 100644 --- a/packaging/tanin-libadwaita/PKGBUILD +++ b/packaging/tanin-libadwaita/PKGBUILD @@ -21,4 +21,6 @@ package() { install -Dm644 "$startdir/gtk-3.0/dark.css" "$pkgdir/usr/share/tanin/libadwaita/gtk-3.0/dark.css" install -Dm644 "$startdir/gtk-3.0/light.css" "$pkgdir/usr/share/tanin/libadwaita/gtk-3.0/light.css" install -Dm755 "$startdir/tanin-libadwaita" "$pkgdir/usr/bin/tanin-libadwaita" + install -Dm644 "$startdir/tanin-libadwaita.service" \ + "$pkgdir/usr/lib/systemd/user/tanin-libadwaita.service" } diff --git a/packaging/tanin-libadwaita/tanin-libadwaita.service b/packaging/tanin-libadwaita/tanin-libadwaita.service new file mode 100644 index 0000000..1b37bc0 --- /dev/null +++ b/packaging/tanin-libadwaita/tanin-libadwaita.service @@ -0,0 +1,13 @@ +[Unit] +Description=TANINUX libadwaita theme follower (Fuji light/dark on color-scheme change) +PartOf=graphical-session.target +After=graphical-session.target + +[Service] +Type=simple +ExecStart=/usr/bin/tanin-libadwaita watch +Restart=on-failure +RestartSec=2 + +[Install] +WantedBy=graphical-session.target diff --git a/packaging/tanin-setup/tanin-setup b/packaging/tanin-setup/tanin-setup index 4c3becf..38fbc63 100644 --- a/packaging/tanin-setup/tanin-setup +++ b/packaging/tanin-setup/tanin-setup @@ -30,17 +30,26 @@ install_session_target() { systemctl --user daemon-reload 2>/dev/null || true } +# Apply the Fuji GTK theme for the current light/dark mode and enable the +# follower service (tanin-libadwaita watch), so the appearance toggle in the +# TANINUX settings retints every GTK3/GTK4 app live. Best-effort. +enable_theme_follower() { + command -v tanin-libadwaita >/dev/null 2>&1 || return 0 + tanin-libadwaita auto 2>/dev/null || true + systemctl --user enable --now tanin-libadwaita.service 2>/dev/null || true +} + seed_configs install_session_target +enable_theme_follower cat <<'EOF' TANINUX setup complete. - • configs seeded into ~/.config + • configs seeded into ~/.config (eww + niri) • session target installed (~/.config/systemd/user/tanin-session.target) + • GTK theme applied + follower enabled (tanin-libadwaita.service) -Make sure your compositor autostart contains: - exec-once = dbus-update-activation-environment --systemd --all - exec-once = systemctl --user start tanin-session.target - -(The shipped TANINUX compositor config already includes these.) +The shipped niri config already autostarts the session bits: + spawn-at-startup "dbus-update-activation-environment" "--systemd" "--all" + spawn-at-startup "systemctl" "--user" "start" "tanin-session.target" EOF