From d6ea38db1410763e472deae6596bef2156afee18 Mon Sep 17 00:00:00 2001 From: Danny Date: Fri, 20 Mar 2026 09:45:20 +0100 Subject: [PATCH] Moved to new phase --- configs/dwl/config.h | 184 ++++++++++++++++++++++++++++++++ configs/rc.conf | 3 +- configs/rc.d/seatd | 34 ++++++ configs/zprofile | 36 +++++-- docs/CHANGELOG.md | 92 ++++++++++++++++ src/install/modules/packages.sh | 79 +++++++++++++- src/install/modules/user.sh | 19 +++- src/iso/build-iso-arch.sh | 6 ++ tests/run-tests.sh | 87 ++++++++++++++- 9 files changed, 521 insertions(+), 19 deletions(-) create mode 100644 configs/dwl/config.h create mode 100755 configs/rc.d/seatd diff --git a/configs/dwl/config.h b/configs/dwl/config.h new file mode 100644 index 0000000..4e1b717 --- /dev/null +++ b/configs/dwl/config.h @@ -0,0 +1,184 @@ +/* ============================================================================ + * DarkForge Linux — dwl Configuration + * ============================================================================ + * Custom config for dwl (dynamic Wayland compositor). + * Keybindings use Super (Windows/Logo) key as the modifier. + * + * Key bindings: + * Super+Return = Launch terminal (foot) + * Super+P = Launch application menu (fuzzel) + * Super+B = Launch Firefox + * Super+G = Launch Steam + * Super+Shift+C = Close focused window + * Super+Shift+Q = Quit dwl + * Super+J/K = Focus next/prev window + * Super+H/L = Shrink/grow master area + * Super+T = Tiled layout + * Super+F = Floating layout + * Super+M = Monocle layout + * Super+E = Toggle fullscreen + * Super+1-9 = Switch to tag 1-9 + * Super+Shift+1-9 = Move window to tag 1-9 + * Audio keys = Volume up/down/mute (via pactl) + * ============================================================================ */ + +/* Taken from https://github.com/djpohly/dwl/issues/466 */ +#define COLOR(hex) { ((hex >> 24) & 0xFF) / 255.0f, \ + ((hex >> 16) & 0xFF) / 255.0f, \ + ((hex >> 8) & 0xFF) / 255.0f, \ + (hex & 0xFF) / 255.0f } + +/* appearance */ +static const int sloppyfocus = 1; /* focus follows mouse */ +static const int bypass_surface_visibility = 0; +static const unsigned int borderpx = 2; /* border pixel — slightly thicker for visibility */ +static const float rootcolor[] = COLOR(0x1a1a2eff); /* dark background */ +static const float bordercolor[] = COLOR(0x444444ff); /* unfocused border */ +static const float focuscolor[] = COLOR(0x7aa2f7ff); /* focused border — blue accent */ +static const float urgentcolor[] = COLOR(0xf7768eff); /* urgent — red */ +static const float fullscreen_bg[] = {0.0f, 0.0f, 0.0f, 1.0f}; + +/* tagging - TAGCOUNT must be no greater than 31 */ +#define TAGCOUNT (9) + +/* logging */ +static int log_level = WLR_ERROR; + +/* rules — assign apps to specific tags if desired */ +static const Rule rules[] = { + /* app_id title tags mask isfloating monitor */ + { "firefox", NULL, 1 << 1, 0, -1 }, /* Firefox on tag 2 */ + { "Steam", NULL, 1 << 3, 0, -1 }, /* Steam on tag 4 */ + { "steam", NULL, 1 << 3, 0, -1 }, /* steam lowercase variant */ + { NULL, NULL, 0, 0, -1 }, /* default rule */ +}; + +/* layout(s) */ +static const Layout layouts[] = { + /* symbol arrange function */ + { "[]=", tile }, + { "><>", NULL }, /* floating */ + { "[M]", monocle }, +}; + +/* monitors */ +static const MonitorRule monrules[] = { + /* name mfact nmaster scale layout rotate/reflect x y */ + { NULL, 0.55f, 1, 1, &layouts[0], WL_OUTPUT_TRANSFORM_NORMAL, -1, -1 }, +}; + +/* keyboard */ +static const struct xkb_rule_names xkb_rules = { + /* XKB rules are set per-user via environment or runtime config */ + .options = NULL, +}; + +static const int repeat_rate = 40; /* faster repeat for gaming/dev */ +static const int repeat_delay = 300; /* shorter delay before repeat starts */ + +/* Trackpad — not used on desktop but kept for completeness */ +static const int tap_to_click = 1; +static const int tap_and_drag = 1; +static const int drag_lock = 1; +static const int natural_scrolling = 0; +static const int disable_while_typing = 1; +static const int left_handed = 0; +static const int middle_button_emulation = 0; +static const enum libinput_config_scroll_method scroll_method = LIBINPUT_CONFIG_SCROLL_2FG; +static const enum libinput_config_click_method click_method = LIBINPUT_CONFIG_CLICK_METHOD_BUTTON_AREAS; +static const uint32_t send_events_mode = LIBINPUT_CONFIG_SEND_EVENTS_ENABLED; +static const enum libinput_config_accel_profile accel_profile = LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT; +/* Flat acceleration profile — no mouse acceleration, critical for FPS games */ +static const double accel_speed = 0.0; +static const enum libinput_config_tap_button_map button_map = LIBINPUT_CONFIG_TAP_MAP_LRM; + +/* Use Super (Windows/Logo) key as the modifier — more natural than Alt */ +#define MODKEY WLR_MODIFIER_LOGO + +#define TAGKEYS(KEY,SKEY,TAG) \ + { MODKEY, KEY, view, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_CTRL, KEY, toggleview, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_SHIFT, SKEY, tag, {.ui = 1 << TAG} }, \ + { MODKEY|WLR_MODIFIER_CTRL|WLR_MODIFIER_SHIFT,SKEY,toggletag, {.ui = 1 << TAG} } + +/* helper for spawning shell commands */ +#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } + +/* commands */ +static const char *termcmd[] = { "foot", NULL }; +static const char *menucmd[] = { "fuzzel", NULL }; +static const char *browsercmd[] = { "firefox", NULL }; +static const char *steamcmd[] = { "steam", NULL }; + +static const Key keys[] = { + /* modifier key function argument */ + + /* --- Application launchers --- */ + { MODKEY, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_p, spawn, {.v = menucmd} }, + { MODKEY, XKB_KEY_b, spawn, {.v = browsercmd} }, + { MODKEY, XKB_KEY_g, spawn, {.v = steamcmd} }, + + /* --- Audio controls (via PipeWire/pactl) --- */ + { 0, XKB_KEY_XF86AudioRaiseVolume, spawn, SHCMD("pactl set-sink-volume @DEFAULT_SINK@ +5%") }, + { 0, XKB_KEY_XF86AudioLowerVolume, spawn, SHCMD("pactl set-sink-volume @DEFAULT_SINK@ -5%") }, + { 0, XKB_KEY_XF86AudioMute, spawn, SHCMD("pactl set-sink-mute @DEFAULT_SINK@ toggle") }, + + /* --- Screenshot (grim + slurp) --- */ + { 0, XKB_KEY_Print, spawn, SHCMD("grim ~/Screenshots/$(date +%Y%m%d_%H%M%S).png") }, + { MODKEY, XKB_KEY_Print, spawn, SHCMD("grim -g \"$(slurp)\" ~/Screenshots/$(date +%Y%m%d_%H%M%S).png") }, + + /* --- Window management --- */ + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, + { MODKEY, XKB_KEY_l, setmfact, {.f = +0.05f} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, zoom, {0} }, + { MODKEY, XKB_KEY_Tab, view, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_C, killclient, {0} }, + + /* --- Layouts --- */ + { MODKEY, XKB_KEY_t, setlayout, {.v = &layouts[0]} }, + { MODKEY, XKB_KEY_f, setlayout, {.v = &layouts[1]} }, + { MODKEY, XKB_KEY_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XKB_KEY_space, setlayout, {0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_space, togglefloating, {0} }, + { MODKEY, XKB_KEY_e, togglefullscreen, {0} }, + + /* --- Tags (workspaces) --- */ + { MODKEY, XKB_KEY_0, view, {.ui = ~0} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_parenright, tag, {.ui = ~0} }, + + /* --- Monitor management --- */ + { MODKEY, XKB_KEY_comma, focusmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY, XKB_KEY_period, focusmon, {.i = WLR_DIRECTION_RIGHT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_less, tagmon, {.i = WLR_DIRECTION_LEFT} }, + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_greater, tagmon, {.i = WLR_DIRECTION_RIGHT} }, + + /* --- Tag switching --- */ + TAGKEYS( XKB_KEY_1, XKB_KEY_exclam, 0), + TAGKEYS( XKB_KEY_2, XKB_KEY_at, 1), + TAGKEYS( XKB_KEY_3, XKB_KEY_numbersign, 2), + TAGKEYS( XKB_KEY_4, XKB_KEY_dollar, 3), + TAGKEYS( XKB_KEY_5, XKB_KEY_percent, 4), + TAGKEYS( XKB_KEY_6, XKB_KEY_asciicircum, 5), + TAGKEYS( XKB_KEY_7, XKB_KEY_ampersand, 6), + TAGKEYS( XKB_KEY_8, XKB_KEY_asterisk, 7), + TAGKEYS( XKB_KEY_9, XKB_KEY_parenleft, 8), + + /* --- Session --- */ + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Q, quit, {0} }, + + /* VT switching (Ctrl+Alt+F1-F12) */ +#define CHVT(n) { WLR_MODIFIER_CTRL|WLR_MODIFIER_ALT,XKB_KEY_XF86Switch_VT_##n, chvt, {.ui = (n)} } + CHVT(1), CHVT(2), CHVT(3), CHVT(4), CHVT(5), CHVT(6), + CHVT(7), CHVT(8), CHVT(9), CHVT(10), CHVT(11), CHVT(12), +}; + +static const Button buttons[] = { + { MODKEY, BTN_LEFT, moveresize, {.ui = CurMove} }, + { MODKEY, BTN_MIDDLE, togglefloating, {0} }, + { MODKEY, BTN_RIGHT, moveresize, {.ui = CurResize} }, +}; diff --git a/configs/rc.conf b/configs/rc.conf index cbc8737..a39a537 100644 --- a/configs/rc.conf +++ b/configs/rc.conf @@ -26,10 +26,11 @@ FONT="ter-v18n" # Scripts are started in listed order at boot, stopped in reverse at shutdown. DAEMONS=( eudev # Device manager — must be first for hardware detection + seatd # Seat manager — gives user access to GPU, input, sound devices syslog # System logging dbus # D-Bus message bus — needed by polkit, PipeWire dhcpcd # DHCP client for ethernet - pipewire # Audio server (replaces PulseAudio) + pipewire # Audio server — prepares XDG_RUNTIME_DIR (user session starts audio) ) # --- Kernel modules to load at boot ---------------------------------------- diff --git a/configs/rc.d/seatd b/configs/rc.d/seatd new file mode 100755 index 0000000..98753b9 --- /dev/null +++ b/configs/rc.d/seatd @@ -0,0 +1,34 @@ +#!/bin/bash +# ============================================================================ +# DarkForge Linux — seatd daemon +# ============================================================================ +# Seat manager — provides access to GPU, input devices, and sound hardware +# for unprivileged user sessions. Required by wlroots/dwl for Wayland. +# The autologin user must be in the 'video' group. +# ============================================================================ + +DAEMON="/usr/bin/seatd" + +case "$1" in + start) + if [ -x "$DAEMON" ]; then + ${DAEMON} -g video & + echo " seatd started (group: video)" + else + echo " seatd not found at ${DAEMON}" + fi + ;; + stop) + killall seatd 2>/dev/null + echo " seatd stopped" + ;; + restart) + $0 stop + sleep 1 + $0 start + ;; + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 + ;; +esac diff --git a/configs/zprofile b/configs/zprofile index 1db3d47..711d186 100644 --- a/configs/zprofile +++ b/configs/zprofile @@ -1,27 +1,28 @@ # ============================================================================ # DarkForge Linux — User Shell Profile (~/.zprofile) # ============================================================================ -# Sourced on login to zsh. Auto-starts PipeWire and dwl on tty1. -# This file is installed to /home/danny/.zprofile during system installation. +# Sourced on login to zsh. Auto-starts the full desktop session on tty1: +# D-Bus user session → PipeWire audio → polkit agent → dwl compositor # ============================================================================ -# --- Environment variables for Wayland + NVIDIA ---------------------------- +# --- XDG directories -------------------------------------------------------- export XDG_SESSION_TYPE=wayland export XDG_RUNTIME_DIR="/run/user/$(id -u)" export XDG_CONFIG_HOME="${HOME}/.config" export XDG_CACHE_HOME="${HOME}/.cache" export XDG_DATA_HOME="${HOME}/.local/share" export XDG_STATE_HOME="${HOME}/.local/state" +export XDG_CURRENT_DESKTOP=dwl -# NVIDIA Wayland-specific environment +# --- NVIDIA Wayland environment --------------------------------------------- export GBM_BACKEND=nvidia-drm export __GLX_VENDOR_LIBRARY_NAME=nvidia export WLR_NO_HARDWARE_CURSORS=1 -# WLR_NO_HARDWARE_CURSORS may be needed for wlroots + nvidia -# Remove if hardware cursors work correctly +export LIBVA_DRIVER_NAME=nvidia +# Hardware video decoding (Firefox, mpv) export MOZ_ENABLE_WAYLAND=1 -# Firefox: use Wayland backend +# Firefox: use native Wayland backend export QT_QPA_PLATFORM=wayland # Qt applications: use Wayland backend @@ -29,6 +30,10 @@ export QT_QPA_PLATFORM=wayland export SDL_VIDEODRIVER=wayland # SDL2 games: prefer Wayland (falls back to X11 via XWayland) +# --- Seatd environment (seat manager for wlroots) -------------------------- +export LIBSEAT_BACKEND=seatd +# Tell wlroots/dwl to use seatd for device access + # --- Ensure XDG runtime directory exists ------------------------------------ if [ ! -d "${XDG_RUNTIME_DIR}" ]; then mkdir -p "${XDG_RUNTIME_DIR}" @@ -37,12 +42,25 @@ fi # --- Auto-start Wayland compositor on tty1 ---------------------------------- if [ -z "${WAYLAND_DISPLAY}" ] && [ "$(tty)" = "/dev/tty1" ]; then + + # Start user D-Bus session (required by PipeWire, polkit, desktop apps) + if [ -z "${DBUS_SESSION_BUS_ADDRESS}" ]; then + eval "$(dbus-launch --sh-syntax)" + export DBUS_SESSION_BUS_ADDRESS + fi + # Start PipeWire audio stack (runs as user, not system service) pipewire & + sleep 0.2 pipewire-pulse & + # PulseAudio compatibility server — needed by Firefox, Steam, most apps wireplumber & + # Session manager — handles audio routing and device management + + # Start polkit authentication agent (for GUI password prompts) + lxqt-policykit-agent &>/dev/null & # Start the dwl Wayland compositor - # dwl will set WAYLAND_DISPLAY and become the session leader - exec dwl -s "foot" 2>/dev/null + # -s "startup_cmd" runs a command after dwl starts (opens a terminal) + exec dwl 2>/dev/null fi diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index ef3aa84..a858879 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -2,6 +2,98 @@ --- +## V33 2026-03-20 16:45:00 + +**Add missing package definitions and update tests for complete boot chain** + +### Changes: +- Created 14 new package definitions to fill gaps blocking Firefox audio and Steam: + - `core/alsa-lib` — ALSA sound library (PipeWire hardware audio access) + - `extra/xorgproto` — Combined X11 protocol headers + - `extra/xtrans` — X11 transport abstraction + - `extra/libx11` — Core X11 client library (XWayland apps) + - `extra/libxext` — X11 miscellaneous extensions (SHAPE, SHM, DPMS) + - `extra/libxfixes` — X11 Fixes extension (cursor, regions) + - `extra/libxrender` — X11 Render extension (anti-aliased fonts) + - `extra/libxcursor` — X11 cursor management (themed cursors) + - `extra/libxrandr` — X11 RandR extension (multi-monitor) + - `extra/libxi` — X11 Input extension (input devices) + - `extra/libxtst` — X11 Testing extension (needed by Steam) + - `extra/libxcomposite` — X11 Composite extension + - `extra/libxdamage` — X11 Damage extension + - `extra/liberation-fonts` — Font family compatible with Arial/Times/Courier +- Updated `extra/pipewire/pipewire.toml`: + - Added alsa-lib dependency + - Enabled `-Dpipewire-pulse=enabled` for PulseAudio compat (Firefox/Steam audio) + - Enabled `-Dpipewire-alsa=enabled` for ALSA backend +- Updated `desktop/firefox/firefox.toml`: added pipewire, alsa-lib, X11 libs, fonts deps +- Updated `gaming/steam/steam.toml`: added full X11 stack, PipeWire, fonts deps +- Updated `desktop/dwl/dwl.toml`: + - Added libxcursor dependency + - Added configure step to copy DarkForge config.h from /etc/dwl/ +- Updated `tests/run-tests.sh` with 15 new boot chain tests: + - seatd in DAEMONS and rc.d daemon check + - dbus-launch, polkit agent, LIBSEAT_BACKEND, pipewire-pulse, wireplumber in zprofile + - dwl config.h exists with terminal/browser/steam/audio keybindings + - Installer deploys rc.d scripts and dwl config to target + - ISO squashfs contains seatd daemon and dwl config.h + +### Plan deviation/changes: +- None + +### What is missing/needs polish: +- 32-bit multilib support for Steam/Wine (major work item — needs lib32 toolchain) +- Package sha256 checksums still placeholder (will be filled by dpack sign) +- liberation-fonts install step is minimal (no fontconfig xml config) + +--- + +## V32 2026-03-20 15:30:00 + +**Comprehensive boot chain audit fixes — seatd, D-Bus, polkit, dwl config, installer** + +### Changes: +- Created `configs/dwl/config.h` — complete dwl configuration: + - Super key as modifier (WLR_MODIFIER_LOGO) + - App launchers: Super+Return=foot, Super+P=fuzzel, Super+B=firefox, Super+G=steam + - Audio controls via pactl (XF86AudioRaiseVolume/Lower/Mute) + - Screenshots via grim+slurp (PrintScreen / Super+PrintScreen) + - Window rules: Firefox→tag2, Steam→tag4 + - Flat mouse acceleration (LIBINPUT_CONFIG_ACCEL_PROFILE_FLAT) for FPS gaming + - Faster key repeat (rate=40, delay=300) + - Dark color scheme (rootcolor=0x1a1a2e, focuscolor=0x7aa2f7) +- Created `configs/rc.d/seatd` — seat manager daemon script: + - Starts seatd with `-g video` (user must be in video group) + - Required by wlroots/dwl for unprivileged GPU/input/sound access +- Updated `configs/rc.conf`: + - Added seatd to DAEMONS array (after eudev, before syslog) +- Rewrote `configs/zprofile`: + - Added D-Bus user session via dbus-launch (required by PipeWire and polkit) + - Added LIBSEAT_BACKEND=seatd environment variable + - Added LIBVA_DRIVER_NAME=nvidia for hardware video decoding + - Added XDG_CURRENT_DESKTOP=dwl + - Added pipewire-pulse and wireplumber startup with ordering delays + - Added lxqt-policykit-agent for GUI password prompts + - Removed `-s "foot"` from dwl (config.h handles terminal keybinding) +- Updated `src/install/modules/packages.sh`: + - Added config deployment: rc.d scripts, inittab, rc.conf, dwl config, zprofile + - Config source detection: checks /install/configs, then relative paths + - Added seatd to DAEMONS in configure_rc_conf() +- Updated `src/install/modules/user.sh`: + - Improved zprofile source detection (fallback to /etc/skel) + - Creates ~/Screenshots directory for grim keybinding +- Updated `src/iso/build-iso-arch.sh`: + - Copies dwl config directory to rootfs /etc/dwl/ and installer configs + - Copies fstab.template to installer configs + +### Plan deviation/changes: +- None + +### What is missing/needs polish: +- Missing package definitions for audio/X11/fonts (addressed in V33) + +--- + ## V31 2026-03-20 08:26:57 **Fix QEMU boot test — all 127 tests passing** diff --git a/src/install/modules/packages.sh b/src/install/modules/packages.sh index 751e6d8..5d6fc2d 100755 --- a/src/install/modules/packages.sh +++ b/src/install/modules/packages.sh @@ -62,10 +62,83 @@ install_base_system() { fi # Create essential directories - mkdir -p "${MOUNT_POINT}"/{boot,home,mnt,opt,srv,tmp} - mkdir -p "${MOUNT_POINT}"/var/{cache,lib,log,lock,run,spool,tmp} + mkdir -p "${MOUNT_POINT}/boot" + mkdir -p "${MOUNT_POINT}/home" + mkdir -p "${MOUNT_POINT}/mnt" + mkdir -p "${MOUNT_POINT}/opt" + mkdir -p "${MOUNT_POINT}/srv" + mkdir -p "${MOUNT_POINT}/tmp" + mkdir -p "${MOUNT_POINT}/var/cache" + mkdir -p "${MOUNT_POINT}/var/lib/dpack/db" + mkdir -p "${MOUNT_POINT}/var/lib/dpack/repos" + mkdir -p "${MOUNT_POINT}/var/log" + mkdir -p "${MOUNT_POINT}/var/lock" + mkdir -p "${MOUNT_POINT}/var/run" + mkdir -p "${MOUNT_POINT}/var/spool" + mkdir -p "${MOUNT_POINT}/var/tmp" + mkdir -p "${MOUNT_POINT}/etc/rc.d" + mkdir -p "${MOUNT_POINT}/etc/sysconfig" chmod 1777 "${MOUNT_POINT}/tmp" + # --- Deploy DarkForge configuration files --------------------------------- + # These must be copied BEFORE user setup (which modifies inittab) + info "Installing DarkForge configuration..." + + # Determine where configs live — either on the live ISO or relative to installer + CONFIG_SRC="" + if [ -d "/install/configs" ]; then + CONFIG_SRC="/install/configs" + elif [ -d "${SCRIPT_DIR}/../configs" ]; then + CONFIG_SRC="$(cd "${SCRIPT_DIR}/../configs" && pwd)" + elif [ -d "${SCRIPT_DIR}/../../configs" ]; then + CONFIG_SRC="$(cd "${SCRIPT_DIR}/../../configs" && pwd)" + fi + + if [ -n "$CONFIG_SRC" ]; then + # rc.d daemon scripts — critical for boot + if [ -d "${CONFIG_SRC}/rc.d" ]; then + cp -a "${CONFIG_SRC}/rc.d/"* "${MOUNT_POINT}/etc/rc.d/" 2>/dev/null || true + chmod 755 "${MOUNT_POINT}/etc/rc.d/"* 2>/dev/null || true + ok " rc.d scripts installed" + fi + + # inittab — needed for auto-login (user.sh modifies it via sed) + if [ -f "${CONFIG_SRC}/inittab" ]; then + cp "${CONFIG_SRC}/inittab" "${MOUNT_POINT}/etc/inittab" + ok " inittab installed" + fi + + # rc.conf (template — will be overwritten with final values at end of install) + if [ -f "${CONFIG_SRC}/rc.conf" ]; then + cp "${CONFIG_SRC}/rc.conf" "${MOUNT_POINT}/etc/rc.conf" + ok " rc.conf template installed" + fi + + # fstab template + if [ -f "${CONFIG_SRC}/fstab.template" ]; then + cp "${CONFIG_SRC}/fstab.template" "${MOUNT_POINT}/etc/fstab" + fi + + # dwl config.h — dwl reads this at compile time, but we also install it + # to /etc/dwl/ so dpack can find it when building dwl on the target + if [ -d "${CONFIG_SRC}/dwl" ]; then + mkdir -p "${MOUNT_POINT}/etc/dwl" + cp -a "${CONFIG_SRC}/dwl/"* "${MOUNT_POINT}/etc/dwl/" 2>/dev/null || true + ok " dwl config installed" + fi + + # zprofile — user shell profile that auto-starts the Wayland session + if [ -f "${CONFIG_SRC}/zprofile" ]; then + # Will be copied to the user's home directory by user.sh + mkdir -p "${MOUNT_POINT}/etc/skel" + cp "${CONFIG_SRC}/zprofile" "${MOUNT_POINT}/etc/skel/.zprofile" + ok " zprofile template installed to /etc/skel" + fi + else + warn "Config source not found — rc.d scripts, inittab may be missing" + warn "System may not boot correctly without these files" + fi + ok "Base system installed" } @@ -171,7 +244,7 @@ KEYMAP="${INSTALL_KEYMAP:-us}" LOCALE="${INSTALL_LOCALE:-en_US.UTF-8}" FONT="ter-v18n" -DAEMONS=(eudev syslog dbus dhcpcd pipewire) +DAEMONS=(eudev seatd syslog dbus dhcpcd pipewire) MODULES=(nvidia nvidia-modeset nvidia-drm nvidia-uvm) diff --git a/src/install/modules/user.sh b/src/install/modules/user.sh index a082419..83cdd84 100755 --- a/src/install/modules/user.sh +++ b/src/install/modules/user.sh @@ -37,11 +37,24 @@ setup_users() { info "Set password for '${INSTALL_USERNAME}':" chroot "${MOUNT_POINT}" /bin/bash -c "passwd '${INSTALL_USERNAME}'" - # Install user shell profile + # Install user shell profile (auto-starts Wayland session on tty1) + local zprofile_src="" if [ -f "/install/configs/zprofile" ]; then - cp "/install/configs/zprofile" "${MOUNT_POINT}/home/${INSTALL_USERNAME}/.zprofile" - chroot "${MOUNT_POINT}" chown "${INSTALL_USERNAME}:${INSTALL_USERNAME}" "/home/${INSTALL_USERNAME}/.zprofile" + zprofile_src="/install/configs/zprofile" + elif [ -f "${MOUNT_POINT}/etc/skel/.zprofile" ]; then + zprofile_src="${MOUNT_POINT}/etc/skel/.zprofile" fi + if [ -n "${zprofile_src}" ]; then + cp "${zprofile_src}" "${MOUNT_POINT}/home/${INSTALL_USERNAME}/.zprofile" + chroot "${MOUNT_POINT}" chown "${INSTALL_USERNAME}:${INSTALL_USERNAME}" "/home/${INSTALL_USERNAME}/.zprofile" + ok " Installed .zprofile for ${INSTALL_USERNAME}" + else + warn " zprofile not found — user will need to start dwl manually" + fi + + # Create Screenshots directory for grim keybinding + mkdir -p "${MOUNT_POINT}/home/${INSTALL_USERNAME}/Screenshots" + chroot "${MOUNT_POINT}" chown "${INSTALL_USERNAME}:${INSTALL_USERNAME}" "/home/${INSTALL_USERNAME}/Screenshots" # Update inittab with the correct username for auto-login sed -i "s/--autologin danny/--autologin ${INSTALL_USERNAME}/" \ diff --git a/src/iso/build-iso-arch.sh b/src/iso/build-iso-arch.sh index 8038282..2362407 100755 --- a/src/iso/build-iso-arch.sh +++ b/src/iso/build-iso-arch.sh @@ -154,6 +154,10 @@ cp "${PROJECT_ROOT}/configs/inittab" "${ROOTFS}/etc/" cp "${PROJECT_ROOT}/configs/fstab.template" "${ROOTFS}/etc/fstab" cp -a "${PROJECT_ROOT}/configs/rc.d/"* "${ROOTFS}/etc/rc.d/" 2>/dev/null || true cp "${PROJECT_ROOT}/configs/zprofile" "${ROOTFS}/etc/skel/.zprofile" 2>/dev/null || true +if [ -d "${PROJECT_ROOT}/configs/dwl" ]; then + mkdir -p "${ROOTFS}/etc/dwl" + cp -a "${PROJECT_ROOT}/configs/dwl/"* "${ROOTFS}/etc/dwl/" 2>/dev/null || true +fi # Override inittab for live mode (auto-login root) cat > "${ROOTFS}/etc/inittab" << 'EOF' @@ -172,6 +176,8 @@ cp "${PROJECT_ROOT}/configs/zprofile" "${ROOTFS}/install/configs/zprofile" 2>/de cp "${PROJECT_ROOT}/configs/inittab" "${ROOTFS}/install/configs/inittab" 2>/dev/null || true cp "${PROJECT_ROOT}/configs/rc.conf" "${ROOTFS}/install/configs/rc.conf" 2>/dev/null || true cp -a "${PROJECT_ROOT}/configs/rc.d" "${ROOTFS}/install/configs/rc.d" 2>/dev/null || true +cp -a "${PROJECT_ROOT}/configs/dwl" "${ROOTFS}/install/configs/dwl" 2>/dev/null || true +cp "${PROJECT_ROOT}/configs/fstab.template" "${ROOTFS}/install/configs/fstab.template" 2>/dev/null || true # Live shell profile with installer prompt cat > "${ROOTFS}/root/.bash_profile" << 'PROFILE' diff --git a/tests/run-tests.sh b/tests/run-tests.sh index 2d6bf78..ec92c89 100755 --- a/tests/run-tests.sh +++ b/tests/run-tests.sh @@ -484,7 +484,7 @@ for f in rc.conf inittab fstab.template zprofile; do fi done -for daemon in eudev syslog dbus dhcpcd pipewire; do +for daemon in eudev seatd syslog dbus dhcpcd pipewire; do script="${PROJECT_ROOT}/configs/rc.d/${daemon}" if [ -x "$script" ]; then if bash -n "$script" 2>/dev/null; then @@ -544,7 +544,7 @@ done # anywhere in the file within the DAEMONS block (or just present as a daemon entry) RC_CONF="${PROJECT_ROOT}/configs/rc.conf" if [ -f "$RC_CONF" ]; then - for svc in eudev dbus dhcpcd pipewire; do + for svc in eudev seatd dbus dhcpcd pipewire; do if grep -q "^[[:space:]]*${svc}" "$RC_CONF"; then record_test "chain.daemon_listed.${svc}" "pass" else @@ -591,10 +591,89 @@ if [ -f "$ZPROFILE" ]; then else record_test "chain.zprofile_xdg_runtime" "fail" "zprofile missing XDG_RUNTIME_DIR setup" fi + + # D-Bus user session — required by PipeWire and polkit + if grep -q 'dbus-launch' "$ZPROFILE"; then + record_test "chain.zprofile_dbus_session" "pass" + else + record_test "chain.zprofile_dbus_session" "fail" "zprofile missing dbus-launch — PipeWire and polkit won't work" + fi + + # polkit authentication agent — needed for GUI password prompts (e.g., Steam) + if grep -q 'policykit-agent\|polkit.*agent' "$ZPROFILE"; then + record_test "chain.zprofile_polkit_agent" "pass" + else + record_test "chain.zprofile_polkit_agent" "fail" "zprofile missing polkit agent — no GUI password prompts" + fi + + # LIBSEAT_BACKEND — seatd environment for wlroots/dwl + if grep -q 'LIBSEAT_BACKEND' "$ZPROFILE"; then + record_test "chain.zprofile_seatd_env" "pass" + else + record_test "chain.zprofile_seatd_env" "fail" "zprofile missing LIBSEAT_BACKEND — dwl may not get GPU access" + fi + + # pipewire-pulse — PulseAudio compat server needed by Firefox/Steam + if grep -q 'pipewire-pulse' "$ZPROFILE"; then + record_test "chain.zprofile_pipewire_pulse" "pass" + else + record_test "chain.zprofile_pipewire_pulse" "fail" "zprofile missing pipewire-pulse — Firefox/Steam audio won't work" + fi + + # wireplumber — session manager for PipeWire + if grep -q 'wireplumber' "$ZPROFILE"; then + record_test "chain.zprofile_wireplumber" "pass" + else + record_test "chain.zprofile_wireplumber" "fail" "zprofile missing wireplumber — audio routing won't work" + fi else record_test "chain.zprofile_dwl" "fail" "zprofile file missing entirely" fi +# 7.11 — dwl config.h exists with keybindings +DWL_CONFIG="${PROJECT_ROOT}/configs/dwl/config.h" +if [ -f "$DWL_CONFIG" ]; then + record_test "chain.dwl_config_exists" "pass" + # Check for critical keybindings + if grep -q 'XKB_KEY_Return' "$DWL_CONFIG" && grep -q 'termcmd' "$DWL_CONFIG"; then + record_test "chain.dwl_config_terminal" "pass" + else + record_test "chain.dwl_config_terminal" "fail" "dwl config.h missing terminal keybinding" + fi + if grep -q 'browsercmd\|firefox' "$DWL_CONFIG"; then + record_test "chain.dwl_config_browser" "pass" + else + record_test "chain.dwl_config_browser" "fail" "dwl config.h missing browser keybinding" + fi + if grep -q 'steamcmd\|steam' "$DWL_CONFIG"; then + record_test "chain.dwl_config_steam" "pass" + else + record_test "chain.dwl_config_steam" "fail" "dwl config.h missing Steam keybinding" + fi + if grep -q 'XF86Audio' "$DWL_CONFIG"; then + record_test "chain.dwl_config_audio_keys" "pass" + else + record_test "chain.dwl_config_audio_keys" "fail" "dwl config.h missing audio key controls" + fi +else + record_test "chain.dwl_config_exists" "fail" "configs/dwl/config.h missing — dwl will use defaults (no custom keybindings)" +fi + +# 7.12 — Installer deploys rc.d scripts and dwl config to target +INSTALLER_PKG="${PROJECT_ROOT}/src/install/modules/packages.sh" +if [ -f "$INSTALLER_PKG" ]; then + if grep -q 'rc\.d' "$INSTALLER_PKG" && grep -q 'cp.*rc\.d' "$INSTALLER_PKG"; then + record_test "chain.installer_deploys_rcd" "pass" + else + record_test "chain.installer_deploys_rcd" "fail" "Installer doesn't copy rc.d scripts to target" + fi + if grep -q 'dwl' "$INSTALLER_PKG"; then + record_test "chain.installer_deploys_dwl_config" "pass" + else + record_test "chain.installer_deploys_dwl_config" "fail" "Installer doesn't copy dwl config to target" + fi +fi + # 7.7 — rc.d/pipewire does NOT hardcode a username (should auto-detect) PW_SCRIPT="${PROJECT_ROOT}/configs/rc.d/pipewire" if [ -f "$PW_SCRIPT" ]; then @@ -786,7 +865,9 @@ if [ "$QUICK_MODE" = false ] && [ "$ISO_PREREQS_OK" = true ]; then "install/modules/user.sh:user module in live rootfs" \ "install/modules/locale.sh:locale module in live rootfs" \ "install/modules/packages.sh:packages module in live rootfs" \ - "install/configs/zprofile:zprofile for target user in live rootfs"; do + "install/configs/zprofile:zprofile for target user in live rootfs" \ + "etc/rc.d/seatd:seatd daemon in live rootfs" \ + "install/configs/dwl/config.h:dwl config.h for target in live rootfs"; do fpath="${check_file%%:*}" fdesc="${check_file##*:}" if sudo test -f "$SQFS_MNT/$fpath"; then