diff --git a/Containerfile b/Containerfile index a738e0c..d710b12 100644 --- a/Containerfile +++ b/Containerfile @@ -26,7 +26,10 @@ COPY build /build ############################################################################### # BASE IMAGE ############################################################################### -FROM quay.io/fedora/fedora-kinoite:44 +# labwc/Noctalia-Zweig: minimale fedora-bootc-Basis statt Kinoite. +# Der komplette Desktop (labwc, greetd, Noctalia) wird in den Layern unten +# aufgebaut. Der Kinoite-Stand bleibt auf Branch main / Tag :stable erhalten. +FROM quay.io/fedora/fedora-bootc:44 ### /opt (Unverändert) # RUN rm /opt && mkdir /opt @@ -42,13 +45,34 @@ RUN --mount=type=bind,from=build-ctx,source=/build/10-repos.sh,target=/tmp/10-re --mount=type=tmpfs,dst=/tmp \ bash /tmp/10-repos.sh && dnf5 clean all -# LAYER 2: Unerwünschte Pakete entfernen (Bereinigungsschicht - vorgezogen) +# LAYER 2: Unerwünschte Pakete entfernen (Guard - auf bootc-Basis meist No-Op) RUN --mount=type=bind,from=build-ctx,source=/build/20-remove-packages.sh,target=/tmp/20-remove-packages.sh \ --mount=type=cache,dst=/var/cache \ --mount=type=cache,dst=/var/log \ --mount=type=tmpfs,dst=/tmp \ bash /tmp/20-remove-packages.sh +# LAYER 2b: labwc Desktop-Basis (Compositor, Portale, Audio, Docking-Tools) +RUN --mount=type=bind,from=build-ctx,source=/build/20-desktop-labwc.sh,target=/tmp/20-desktop-labwc.sh \ + --mount=type=cache,dst=/var/cache \ + --mount=type=cache,dst=/var/log \ + --mount=type=tmpfs,dst=/tmp \ + bash /tmp/20-desktop-labwc.sh + +# LAYER 2c: Login-Stack (greetd + tuigreet-Fallback + Noctalia-Greeter) +RUN --mount=type=bind,from=build-ctx,source=/build/21-greetd.sh,target=/tmp/21-greetd.sh \ + --mount=type=cache,dst=/var/cache \ + --mount=type=cache,dst=/var/log \ + --mount=type=tmpfs,dst=/tmp \ + bash /tmp/21-greetd.sh + +# LAYER 2d: Noctalia Shell v5 (nativ, aus Fedora-Repos) +RUN --mount=type=bind,from=build-ctx,source=/build/22-noctalia.sh,target=/tmp/22-noctalia.sh \ + --mount=type=cache,dst=/var/cache \ + --mount=type=cache,dst=/var/log \ + --mount=type=tmpfs,dst=/tmp \ + bash /tmp/22-noctalia.sh + # LAYER 3: Virtualisierung & Tools (Großer Download - stark gecacht) RUN --mount=type=bind,from=build-ctx,source=/build/30-virt.sh,target=/tmp/30-virt.sh \ --mount=type=cache,dst=/var/cache \ @@ -91,8 +115,39 @@ RUN chmod 0644 /etc/containers/policy.json /etc/pki/containers/cosign.pub && \ COPY configs/bootc-timer-override.conf /usr/lib/systemd/system/bootc-fetch-apply-updates.timer.d/override.conf COPY configs/bootc-override.conf /usr/lib/systemd/system/bootc-fetch-apply-updates.service.d/override.conf -# 3. Kopiere das Benachrichtigungs-Skript +# 3. Kopiere die Session-Helfer und Desktop-Defaults COPY --chmod=755 scripts/notify-bootc-user.sh /usr/bin/ +COPY --chmod=755 scripts/kanshi-autoconfig /usr/bin/kanshi-autoconfig +COPY --chmod=755 scripts/seed-labwc-skel.sh /usr/bin/seed-labwc-skel + +# labwc/kanshi-Defaults fuer neue Benutzer (Bestand bleibt via seed-labwc-skel) +COPY configs/skel/ /etc/skel/ + +# Wayland-Session fuer Display-Manager (Greeter-Auswahl) +COPY configs/wayland-sessions/labwc.desktop /usr/share/wayland-sessions/labwc.desktop + +# greetd-Konfiguration (Noctalia-Greeter + tuigreet-Fallback dokumentiert) +COPY configs/greetd/config.toml /etc/greetd/config.toml + +# Noctalia-Greeter Standardwerte (de-Tastatur etc., werden per tmpfiles +# beim Erst-Boot nach /var/lib/noctalia-greeter/greeter.toml kopiert) +COPY configs/noctalia-greeter/greeter.toml.default /usr/share/noctalia-greeter/greeter.toml.default +COPY configs/tmpfiles/noctalia-greeter-seed.conf /usr/lib/tmpfiles.d/noctalia-greeter-seed.conf + +# Fail-fast: Greeter-Integration verifizieren (lieber Build-Abbruch als +# defekter Login-Screen). Terra paketiert eigenstaendig, daher wird der +# real installierte Wrapper-Pfad gegen /etc/greetd/config.toml abgeglichen +# plus D-Bus/polkit/Session auf Vorhandensein geprueft. +RUN set -u; \ + cfg="$(sed -n 's/^command = "\(.*\)"/\1/p' /etc/greetd/config.toml | head -n 1)"; \ + wrapper="$(command -v noctalia-greeter-session || true)"; \ + echo "Greeter config-Pfad: ${cfg}"; \ + echo "Gefundener Wrapper: ${wrapper}"; \ + test -n "${cfg}" && test "${cfg}" = "${wrapper}" && test -x "${cfg}" && \ + command -v dbus-run-session >/dev/null && test -x /usr/bin/pkexec && \ + test -f /usr/share/wayland-sessions/labwc.desktop && \ + echo "Greeter-Check OK" || \ + { echo "FEHLER: Noctalia-Greeter-Integration unvollstaendig (Wrapper-Pfad, D-Bus, polkit oder labwc-Session fehlt/weicht ab)"; exit 1; } # ============================================================================= # SYSTEMD SERVICES (Modern Bootc Architecture) @@ -102,12 +157,19 @@ COPY --chmod=755 scripts/notify-bootc-user.sh /usr/bin/ COPY configs/flatpak-preinstall.service /usr/lib/systemd/system/flatpak-preinstall.service # 5. Aktiviere Services (Presets greifen nicht bei COPY-Dateien) +# HINWEIS: greetd wird bereits in 21-greetd.sh enabled; hier als +# Doku/Netz doppelt abgesichert (idempotent). RUN systemctl enable \ # libvirtd.service \ # virtlogd.service \ podman.socket \ bootc-fetch-apply-updates.timer \ - flatpak-preinstall.service + flatpak-preinstall.service \ + greetd.service + +# SELinux-Labels fuer Greeter/Skel/Sessions (Fehler tolerieren, Labels +# werden beim Deployment ggf. erneut gesetzt) +RUN restorecon -Rv /etc/greetd /etc/skel /usr/share/wayland-sessions 2>/dev/null || true ############################################################################### # FINAL CLEANUP diff --git a/Justfile b/Justfile index cf98ea4..dc81a4f 100644 --- a/Justfile +++ b/Justfile @@ -124,6 +124,9 @@ _rootful_load_image $target_image $tag=default_tag: fi # Build a bootc bootable image using Bootc Image Builder (BIB) +# HINWEIS: Bei Typ "iso" wird die Image-Referenz im Kickstart (iso/iso.toml) +# automatisch auf $target_image:$tag umgeschrieben. So installiert eine lokal +# gebaute Test-ISO auch das Test-Image und nicht :stable. _build-bib $target_image $tag $type $config: (_rootful_load_image target_image tag) #!/usr/bin/env bash set -euo pipefail @@ -134,6 +137,16 @@ _build-bib $target_image $tag $type $config: (_rootful_load_image target_image t BUILDTMP=$(mktemp -p "${PWD}" -d -t _build-bib.XXXXXXXXXX) + CONFIG_ABS="$(pwd)/${config}" + CONFIGTMP="" + if [[ "${type}" == "iso" ]]; then + CONFIGTMP=$(mktemp -p "${PWD}" -d -t _build-bib-config.XXXXXXXXXX) + sed "s|humocs-man.duckdns.org/humocs-man/fluffy-pancake:stable|{{ target_image }}:{{ tag }}|g" \ + "${CONFIG_ABS}" > "$CONFIGTMP/config.toml" + CONFIG_ABS="$CONFIGTMP/config.toml" + echo "==> ISO-Kickstart zeigt auf {{ target_image }}:{{ tag }}" + fi + sudo podman run \ --rm \ -it \ @@ -141,7 +154,7 @@ _build-bib $target_image $tag $type $config: (_rootful_load_image target_image t --pull=newer \ --net=host \ --security-opt label=type:unconfined_t \ - -v "$(pwd)/${config}":/config.toml:ro \ + -v "${CONFIG_ABS}":/config.toml:ro \ -v "$BUILDTMP":/output \ -v /var/lib/containers/storage:/var/lib/containers/storage \ "${bib_image}" \ @@ -151,6 +164,7 @@ _build-bib $target_image $tag $type $config: (_rootful_load_image target_image t mkdir -p output sudo mv -f $BUILDTMP/* output/ sudo rmdir $BUILDTMP + if [[ -n "$CONFIGTMP" ]]; then rm -rf "$CONFIGTMP"; fi sudo chown -R $USER:$USER output/ # Rebuild-Schritt: Führt vor BIB ein lokales 'podman build' aus diff --git a/build/10-repos.sh b/build/10-repos.sh index fa3e080..04f8893 100755 --- a/build/10-repos.sh +++ b/build/10-repos.sh @@ -6,4 +6,12 @@ dnf5 install -y \ https://mirrors.rpmfusion.org/free/fedora/rpmfusion-free-release-${FEDORA_VERSION}.noarch.rpm \ https://mirrors.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-${FEDORA_VERSION}.noarch.rpm -dnf5 clean all \ No newline at end of file +# Terra-Repository (Fyralabs) fuer noctalia-greeter. +# Die Shell (Paket `noctalia`, v5) liegt in den offiziellen Fedora-Repos, +# der Greeter aktuell NUR in Terra (Stand: Fedora 44). +# Siehe https://docs.noctalia.dev/greeter/installation/ +dnf5 install -y --nogpgcheck \ + --repofrompath "terra,https://repos.fyralabs.com/terra${FEDORA_VERSION}" \ + terra-release + +dnf5 clean all diff --git a/build/20-desktop-labwc.sh b/build/20-desktop-labwc.sh new file mode 100755 index 0000000..1575941 --- /dev/null +++ b/build/20-desktop-labwc.sh @@ -0,0 +1,56 @@ +#!/usr/bin/bash +set -eoux pipefail + +############################################################################### +# Transaction: labwc Desktop-Basis (Compositor + Wayland-Stack + Docking) +# Basiert auf fedora-bootc (kein KDE). Noctalia-Shell und Greeter kommen +# in eigenen Layern (21/22), damit sie unabhaengig gecacht werden. +############################################################################### +echo "Installing labwc desktop base..." + +# Kern-Pakete (hart erforderlich) +dnf5 install -y \ + --allowerasing \ + labwc \ + xorg-x11-server-Xwayland \ + kanshi \ + wlr-randr \ + swaybg \ + swayidle \ + wlopm \ + xdg-desktop-portal-wlr \ + xdg-desktop-portal-gtk \ + pipewire \ + pipewire-pulseaudio \ + wireplumber \ + NetworkManager \ + foot \ + wl-clipboard \ + xdg-user-dirs \ + upower \ + power-profiles-daemon \ + bolt \ + lxqt-policykit \ + accountsservice \ + inter-fonts \ + jetbrains-mono-fonts \ + wdisplays \ + brightnessctl \ + swaylock + +# Optionale Pakete (duerfen fehlen -> --skip-unavailable, eigener Aufruf, +# damit ein fehlendes Optionales den Kern nicht zu Fall bringt) +dnf5 install -y \ + --allowerasing \ + --skip-unavailable \ + ddcutil \ + fwupd \ + cliphist \ + wlsunset \ + || true + +# User-Services fuer Audio (Presets greifen nicht fuer nachinstallierte +# Pakete auf bootc-Basis -> explizit global enablen, Fehler tolerieren) +systemctl --global enable pipewire.socket pipewire-pulse.socket wireplumber.service || true + +dnf5 clean all diff --git a/build/20-remove-packages.sh b/build/20-remove-packages.sh index 6e9a199..9b8ddb6 100755 --- a/build/20-remove-packages.sh +++ b/build/20-remove-packages.sh @@ -1,18 +1,22 @@ #!/usr/bin/bash set -eoux pipefail - ############################################################################### -# Cleanup of Unwanted Packages +# Bereinigung unerwuenschter Pakete (Guard-Layer) ############################################################################### -echo "Removing Firefox and langpacks..." +# Auf fedora-bootc-Basis gibt es kein Plasma/Firefox/Discover mehr. +# Das Skript bleibt als Sicherheitsnetz, falls unerwuenschte Pakete +# ueber Abhaengigkeiten hereinkommen. Fehlende Pakete sind kein Fehler. +echo "Removing unwanted packages (if present)..." dnf5 remove -y \ firefox \ - firefox-langpacks* \ + firefox-langpacks\* \ plasma-discover \ plasma-discover-flatpak \ - plasma-discover-notifier + plasma-discover-notifier \ + sddm \ + || true - rm -f /etc/xdg/autostart/org.kde.discover.notifier.desktop - - dnf5 clean all +rm -f /etc/xdg/autostart/org.kde.discover.notifier.desktop || true + +dnf5 clean all diff --git a/build/21-greetd.sh b/build/21-greetd.sh new file mode 100755 index 0000000..e2a8519 --- /dev/null +++ b/build/21-greetd.sh @@ -0,0 +1,45 @@ +#!/usr/bin/bash +set -eoux pipefail + +############################################################################### +# Transaction: Login-Stack (greetd + tuigreet-Fallback + Noctalia-Greeter) +############################################################################### +# - greetd ist der Display-Manager (leicht, Wayland-nativ). +# - noctalia-greeter (aus Terra, siehe 10-repos.sh) ist die Login-UI in +# Noctalia-Optik. Braucht ZWINGEND greetd als Unterbau. +# - tuigreet bleibt als sparsamer Fallback, falls der grafische Greeter +# je streikt (in /etc/greetd/config.toml per Kommentar umschaltbar). +############################################################################### +echo "Installing login stack (greetd + Noctalia greeter)..." + +# greetd + D-Bus + polkit sind harte Voraussetzungen des Noctalia-Greeters +# (https://docs.noctalia.dev/greeter/installation/) und werden hier explizit +# installiert statt von der Basis vorausgesetzt. +dnf5 install -y \ + --allowerasing \ + greetd \ + greetd-selinux \ + dbus-daemon \ + polkit \ + tuigreet \ + noctalia-greeter + +dnf5 clean all + +# accounts-daemon: liefert User-Avatare auf dem Login-Screen. +systemctl enable accounts-daemon.service + +# System-Setup des Greeters: legt /var/lib/noctalia-greeter/ + greeter.toml +# fuer den greetd-Session-User an und gibt die fertige config.toml-Zeile aus. +# Pfad laut PACKAGING.md: share/noctalia-greeter/setup_greeter_system.sh +if [[ -x /usr/share/noctalia-greeter/setup_greeter_system.sh ]]; then + /usr/share/noctalia-greeter/setup_greeter_system.sh || true +else + echo "WARN: setup_greeter_system.sh nicht gefunden - Greeter-State wird erst beim Boot angelegt" +fi + +# Alte Display-Manager explizit aus (zwei DMs = Blackscreen). +# Auf fedora-bootc-Basis existieren sie i.d.R. nicht -> Fehler tolerieren. +systemctl disable sddm.service gdm.service lightdm.service 2>/dev/null || true +systemctl enable greetd.service +systemctl set-default graphical.target || true diff --git a/build/22-noctalia.sh b/build/22-noctalia.sh new file mode 100755 index 0000000..64afdbe --- /dev/null +++ b/build/22-noctalia.sh @@ -0,0 +1,20 @@ +#!/usr/bin/bash +set -eoux pipefail + +############################################################################### +# Transaction: Noctalia Shell v5 (nativer Wayland-Desktop-Shell) +############################################################################### +# Paket `noctalia` aus den offiziellen Fedora-Repos (ab F44). +# KEIN COPR noetig. Start via labwc-autostart (siehe configs/skel). +# Doku: https://docs.noctalia.dev/noctalia/getting-started/installation/ +############################################################################### +echo "Installing Noctalia Shell v5..." + +dnf5 install -y \ + --allowerasing \ + noctalia \ + imagemagick \ + python3 \ + git + +dnf5 clean all diff --git a/build/30-virt.sh b/build/30-virt.sh index 524578b..5027f13 100755 --- a/build/30-virt.sh +++ b/build/30-virt.sh @@ -2,26 +2,24 @@ set -eoux pipefail ############################################################################### -# Transaction 2: Virtualization, Tools & Hardware Helpers +# Transaction: Virtualization, Tools & Hardware Helpers # Zusammengefasst für effizientere Paketauflösung. +# HINWEIS (labwc-Zweig): plasma-setup und noctalia sind hier raus. +# plasma-setup war KDE-spezifisch, noctalia liegt in 22-noctalia.sh. +# webkit2gtk bleibt (Bazaar/Flatpak-Store braucht es). ############################################################################### -echo "Installing Virtualization, Plasma Setup and Hardware Helpers..." +echo "Installing Virtualization, Tools and Hardware Helpers..." dnf5 install -y \ --allowerasing \ --skip-unavailable \ distrobox \ toolbox \ - plasma-setup \ libva-utils \ micro \ fuse \ fuse-libs \ fuse3 \ webkit2gtk4.1 \ - javascriptcoregtk4.1 \ - noctalia + javascriptcoregtk4.1 dnf5 clean all - - - diff --git a/build/README.md b/build/README.md index eeb2fec..e18274e 100644 --- a/build/README.md +++ b/build/README.md @@ -8,8 +8,11 @@ Scripts are named with a number prefix and run in ascending order during the con ## Included Scripts -- **`10-repos.sh`** - RPM Fusion repositories einrichten (frei + nonfree) -- **`20-remove-packages.sh`** - Entfernt unerwuenschte Pakete (Firefox, Plasma Discover) +- **`10-repos.sh`** - RPM Fusion (frei + nonfree) + Terra-Repo (fuer noctalia-greeter) +- **`20-remove-packages.sh`** - Guard-Layer: entfernt unerwuenschte Pakete, falls vorhanden (auf fedora-bootc-Basis meist No-Op) +- **`20-desktop-labwc.sh`** - labwc-Compositor, XWayland, kanshi, Portale, Pipewire, Docking-Tools (bolt), PolicyKit, Fonts +- **`21-greetd.sh`** - greetd + tuigreet-Fallback + Noctalia-Greeter, SDDM/GDM aus, graphical.target +- **`22-noctalia.sh`** - Noctalia Shell v5 aus den Fedora-Repos - **`30-virt.sh`** - Virtualisierungstools, Distrobox, Toolbox, Micro, etc. - **`40-multimedia.sh`** - Mesa Freeworld, Codecs, FFmpeg, GStreamer, Intel-Media-Treiber - **`50-prepare-flatpak-for-bazaar.sh`** - Laedt Flathub-Repo-Definition fuer Bazaar diff --git a/configs/greetd/config.toml b/configs/greetd/config.toml new file mode 100644 index 0000000..a03588b --- /dev/null +++ b/configs/greetd/config.toml @@ -0,0 +1,17 @@ +# greetd-Konfiguration – fluffy-pancake (labwc/Noctalia-Zweig) +# Greeter ist der Noctalia-Greeter (Login-UI in Noctalia-Optik). +# Er braucht greetd als Unterbau und wird via Session-Wrapper gestartet, +# NICHT direkt als Binary (der Wrapper startet den Compositor mit). +# Doku: https://docs.noctalia.dev/greeter/installation/ + +[terminal] +vt = 1 + +[default_session] +command = "/usr/bin/noctalia-greeter-session" +user = "greeter" + +# --- Fallback, falls der grafische Greeter je streikt --- +# Dafuer diese Zeile einkommentieren und die obere auskommentieren, +# danach `systemctl restart greetd`: +# command = "tuigreet --cmd labwc --time --asterisks --remember" diff --git a/configs/noctalia-greeter/greeter.toml.default b/configs/noctalia-greeter/greeter.toml.default new file mode 100644 index 0000000..d4a8670 --- /dev/null +++ b/configs/noctalia-greeter/greeter.toml.default @@ -0,0 +1,20 @@ +# Noctalia-Greeter Standardwerte – fluffy-pancake (Noctalia-Zweig) +# Diese Datei wird als /usr/share/noctalia-greeter/greeter.toml.default +# installiert und beim ERSTEN Boot via tmpfiles.d nach +# /var/lib/noctalia-greeter/greeter.toml kopiert (nur wenn dort noch +# keine Datei liegt - Hand-Edits bleiben erhalten). +# Referenz aller Keys: https://docs.noctalia.dev/greeter/configuration/ +# Feintuning danach: Noctalia Shell -> Einstellungen -> Sicherheit -> +# Noctalia Greeter -> Sync Now (Wallpaper/Palette syncen). + +[keyboard] +layout = "de" +variant = "nodeadkeys" + +[idle] +timeout = 300 + +# [output] bewusst nicht gesetzt: Greeter spiegelt auf allen Monitoren +# mit nativer Aufloesung. Bei Bedarf pinnen, z.B.: +# [output] +# name = "DP-1" diff --git a/configs/skel/.config/kanshi/config.template b/configs/skel/.config/kanshi/config.template new file mode 100644 index 0000000..14da924 --- /dev/null +++ b/configs/skel/.config/kanshi/config.template @@ -0,0 +1,31 @@ +# kanshi-Template – fluffy-pancake (Noctalia-Zweig) +# Diese Datei liegt als Vorlage in /etc/skel und wird beim Anlegen neuer +# Benutzer nach ~/.config/kanshi/config kopiert. +# +# EMPFOHLEN: nichts von Hand raten, sondern generieren lassen: +# kanshi-autoconfig --print # zeigt erkannte Outputs + Vorschlag +# kanshi-autoconfig --apply # schreibt ~/.config/kanshi/config +# wdisplays # grafisches Feintuning (optional) +# +# Die generierte Config enthaelt drei Profile: +# docked – externe Monitore in einer Reihe, internes Panel aus +# (Deckel-zu am Dock; bei offenem Deckel ggf. anpassen) +# undocked – nur internes Panel +# fallback – letzter Ausweg: alles an (uebereinander auf 0,0) +# +# Beispiel einer generierten Config (Namen/Modi kommen live via wlr-randr): +# profile docked { +# output eDP-1 disable +# output DP-1 mode 2560x1440@59.95 position 0,0 scale 1 +# output DP-2 mode 2560x1440@59.95 position 2560,0 scale 1 +# } +# profile undocked { +# output eDP-1 mode 2256x1504@60 position 0,0 scale 1 +# } +# profile fallback { +# output * enable +# } + +profile fallback { + output * enable +} diff --git a/configs/skel/.config/labwc/autostart b/configs/skel/.config/labwc/autostart new file mode 100644 index 0000000..af9f760 --- /dev/null +++ b/configs/skel/.config/labwc/autostart @@ -0,0 +1,26 @@ +# labwc-Autostart – fluffy-pancake (Noctalia-Zweig) +# Tastatur/Locale stehen in ~/.config/labwc/environment. + +# 1. Output-Profile (gedockt/ungedockt). Schreibt die kanshi-Config nur, +# wenn sie fehlt oder von kanshi-autoconfig verwaltet wird. +# Eigene Hand-Edits bleiben unangetastet. +kanshi-autoconfig --apply-if-managed >/dev/null 2>&1 || true +kanshi >/dev/null 2>&1 & + +# 2. Hintergrund-Fallback (Noctalia setzt das Wallpaper selbst) +swaybg -c '#1a1b26' >/dev/null 2>&1 & + +# 3. PolicyKit-Agent (labwc startet kein XDG-Autostart von selbst) +lxqt-policykit-agent >/dev/null 2>&1 & + +# 4. Desktop-Shell: Bar, Dock, Launcher, Control-Center, Lock, OSDs +noctalia >/dev/null 2>&1 & + +# 5. Idle-Handling: nach 5 Min sperren (Noctalia-Lockscreen), +# nach 10 Min Displays stromsparend dunkel schalten (wlopm, damit +# Fensterlayouts erhalten bleiben – KEIN output --off). +swayidle -w \ + timeout 300 'noctalia msg session lock' \ + timeout 600 'wlopm --off *' \ + resume 'wlopm --on *' \ + before-sleep 'noctalia msg session lock' >/dev/null 2>&1 & diff --git a/configs/skel/.config/labwc/environment b/configs/skel/.config/labwc/environment new file mode 100644 index 0000000..1970063 --- /dev/null +++ b/configs/skel/.config/labwc/environment @@ -0,0 +1,9 @@ +# labwc-Umgebung – fluffy-pancake (Noctalia-Zweig) +# Wird von labwc beim Start eingelesen (~/.config/labwc/environment). +XKB_DEFAULT_LAYOUT=de +XKB_DEFAULT_VARIANT=nodeadkeys +QT_QPA_PLATFORM=wayland +GDK_BACKEND=wayland +XDG_CURRENT_DESKTOP=labwc +XDG_SESSION_TYPE=wayland +MOZ_ENABLE_WAYLAND=1 diff --git a/configs/skel/.config/labwc/menu.xml b/configs/skel/.config/labwc/menu.xml new file mode 100644 index 0000000..635a9c0 --- /dev/null +++ b/configs/skel/.config/labwc/menu.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/skel/.config/labwc/rc.xml b/configs/skel/.config/labwc/rc.xml new file mode 100644 index 0000000..58e2796 --- /dev/null +++ b/configs/skel/.config/labwc/rc.xml @@ -0,0 +1,45 @@ + + + + + 8 + + + + Clearlooks + + + + no + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/configs/tmpfiles/noctalia-greeter-seed.conf b/configs/tmpfiles/noctalia-greeter-seed.conf new file mode 100644 index 0000000..6cc0d76 --- /dev/null +++ b/configs/tmpfiles/noctalia-greeter-seed.conf @@ -0,0 +1,4 @@ +# Noctalia-Greeter Standardwerte seeden (nur Erst-Boot, Hand-Edits bleiben). +# Das Paket legt das Verzeichnis bereits per tmpfiles.d an; diese Regel +# kopiert zusaetzlich unsere de-Defaults, falls noch keine greeter.toml da ist. +C /var/lib/noctalia-greeter/greeter.toml 0640 greeter greeter - /usr/share/noctalia-greeter/greeter.toml.default diff --git a/configs/wayland-sessions/labwc.desktop b/configs/wayland-sessions/labwc.desktop new file mode 100644 index 0000000..f7a9c6d --- /dev/null +++ b/configs/wayland-sessions/labwc.desktop @@ -0,0 +1,6 @@ +[Desktop Entry] +Name=labwc +Comment=Lab Wayland Compositor (fluffy-pancake Noctalia-Desktop) +Exec=labwc +Type=Application +DesktopNames=labwc diff --git a/scripts/kanshi-autoconfig b/scripts/kanshi-autoconfig new file mode 100755 index 0000000..5b0880b --- /dev/null +++ b/scripts/kanshi-autoconfig @@ -0,0 +1,171 @@ +#!/usr/bin/env python3 +"""kanshi-autoconfig - generiert kanshi-Profile aus live erkannten Outputs. + +Liest die angeschlossenen Monitore via `wlr-randr --json` aus (EDID-Namen, +bevorzugte Modi, aktuelle Skalierung) und schreibt daraus eine +funktionsfaehige ~/.config/kanshi/config mit den Profilen +docked / undocked / fallback. + +Verhalten: + --print Vorschlag auf stdout, schreibt nichts. + --apply Schreibt (mit Backup *.bak), fragt nicht. + --apply-if-managed Schreibt nur, wenn die Config fehlt oder den Marker + '# kanshi-autoconfig: managed' enthaelt. + -> Hand-Edits bleiben unangetastet. Wird vom + labwc-Autostart bei jedem Login aufgerufen. + +Faellt die Erkennung fehl (kein Wayland, kein wlr-randr), wird eine +reine Fallback-Config geschrieben, damit nie ein schwarzer Bildschirm +ohne Layout dasteht. +""" + +import json +import shutil +import subprocess +import sys +from datetime import datetime +from pathlib import Path + +MARKER = "# kanshi-autoconfig: managed" +CONFIG_PATH = Path.home() / ".config" / "kanshi" / "config" + + +def detect_outputs(): + """Liste von Dicts: name, internal, width, height, rate, scale.""" + try: + proc = subprocess.run( + ["wlr-randr", "--json"], capture_output=True, text=True, timeout=10 + ) + except (FileNotFoundError, subprocess.TimeoutExpired): + return [] + if proc.returncode != 0: + return [] + try: + data = json.loads(proc.stdout) + except json.JSONDecodeError: + return [] + outputs = [] + for out in data: + name = out.get("name", "?") + # Nur verbundene Outputs betrachten (kanshi matcht nur angesteckte) + if out.get("connected") is False: + continue + modes = out.get("modes", []) or [] + preferred = next((m for m in modes if m.get("preferred")), None) + current = out.get("current_mode") or out.get("mode") + chosen = preferred or current or (modes[0] if modes else None) + if not chosen: + continue + width = chosen.get("width") + height = chosen.get("height") + rate = chosen.get("refresh") or chosen.get("rate") + if isinstance(rate, (int, float)) and rate > 1000: + rate = rate / 1000 # mHz -> Hz + outputs.append( + { + "name": name, + "internal": name.startswith(("eDP-", "LVDS-", "DSI-")), + "width": width, + "height": height, + "rate": rate, + "scale": out.get("scale", 1) or 1, + } + ) + return outputs + + +def mode_str(o): + s = f"{o['width']}x{o['height']}" + if o["rate"]: + s += f"@{o['rate']:.2f}" if isinstance(o["rate"], float) else f"@{o['rate']}" + return s + + +def render(outputs): + lines = [ + MARKER, + f"# generiert am {datetime.now().isoformat(timespec='seconds')}", + "# Quelle: wlr-randr (live). Feintuning: wdisplays oder Hand-Edit", + "# (Hand-Edit: Marker-Zeile loeschen, dann fasst --apply-if-managed", + "# diese Datei nicht mehr an.)", + "", + ] + externals = [o for o in outputs if not o["internal"]] + internals = [o for o in outputs if o["internal"]] + + if externals: + lines.append("profile docked {") + for i in internals: + lines.append(f" output {i['name']} disable") + x = 0 + for o in externals: + lines.append( + f" output {o['name']} mode {mode_str(o)} position {x},0 scale {o['scale']}" + ) + x += o["width"] or 0 + lines.append("}") + lines.append("") + + if internals: + lines.append("profile undocked {") + for o in internals: + lines.append( + f" output {o['name']} mode {mode_str(o)} position 0,0 scale {o['scale']}" + ) + lines.append("}") + lines.append("") + elif not externals: + # Gar nichts erkannt -> reiner Fallback, nie leer lassen + lines.append("# Keine Outputs erkannt (ausserhalb einer Wayland-Session") + lines.append("# aufgerufen?) - nur Fallback geschrieben.") + lines.append("") + + lines.append("profile fallback {") + lines.append(" output * enable") + lines.append("}") + lines.append("") + return "\n".join(lines) + + +def is_managed(path: Path): + if not path.exists(): + return True + try: + return MARKER in path.read_text() + except OSError: + return False + + +def apply(text): + CONFIG_PATH.parent.mkdir(parents=True, exist_ok=True) + if CONFIG_PATH.exists(): + backup = CONFIG_PATH.with_suffix(".bak") + shutil.copy2(CONFIG_PATH, backup) + print(f"Backup: {backup}") + CONFIG_PATH.write_text(text) + print(f"Geschrieben: {CONFIG_PATH}") + + +def main(argv): + outputs = detect_outputs() + if not outputs: + print("WARN: keine Outputs erkannt - schreibe Fallback-Config", file=sys.stderr) + text = render(outputs) + # Default ohne Schreib-Flag: nur anzeigen, nichts schreiben (sicher). + if "--print" in argv or ("--apply" not in argv and "--apply-if-managed" not in argv): + print(text) + if outputs: + print( + f"# Erkannt: {', '.join(o['name'] for o in outputs)}", + file=sys.stderr, + ) + return 0 + if "--apply-if-managed" in argv and not is_managed(CONFIG_PATH): + print(f"{CONFIG_PATH} ist hand-gepflegt - lasse sie unangetastet.") + return 0 + apply(text) + return 0 + + +if __name__ == "__main__": + sys.exit(main(sys.argv)) diff --git a/scripts/seed-labwc-skel.sh b/scripts/seed-labwc-skel.sh new file mode 100755 index 0000000..89d5f37 --- /dev/null +++ b/scripts/seed-labwc-skel.sh @@ -0,0 +1,33 @@ +#!/usr/bin/env bash +# seed-labwc-skel: kopiert fehlende labwc/kanshi-Defaults aus /etc/skel. +# Nuetzlich nach Rebase von Kinoite auf den labwc-Zweig, weil /home +# erhalten bleibt und /etc/skel nur bei NEU angelegten Benutzern greift. +# Bestehende Dateien werden NIEMALS ueberschrieben (cp -n). +set -euo pipefail + +SKEL="/etc/skel" +TARGETS=( + ".config/labwc/environment" + ".config/labwc/autostart" + ".config/labwc/rc.xml" + ".config/labwc/menu.xml" + ".config/kanshi/config.template" +) + +for rel in "${TARGETS[@]}"; do + src="${SKEL}/${rel}" + dst="${HOME}/${rel}" + if [[ ! -e "${dst}" ]]; then + mkdir -p "$(dirname "${dst}")" + cp -n "${src}" "${dst}" + echo "angelegt: ${dst}" + else + echo "bleibt: ${dst}" + fi +done + +if [[ ! -e "${HOME}/.config/kanshi/config" ]]; then + echo "" + echo "Keine kanshi-Config gefunden. Erzeugen mit:" + echo " kanshi-autoconfig --apply (schreibt ~/.config/kanshi/config)" +fi