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