diff --git a/docs/md/modules.md b/docs/md/modules.md index 3ea5e68..3b834bc 100644 --- a/docs/md/modules.md +++ b/docs/md/modules.md @@ -135,6 +135,8 @@ bash ~/Dotfiles/setup/install-modules.sh | `wprs` | Wayland proxy for remote sessions (wprs-git, AUR) | | `plymouth` | boot splash — bundled skull logo and spinner | | `plymouth-custom` | boot splash with a user-supplied image | +| `lightdm` | LightDM GTK greeter, cyberqueer-themed (HyprLua default) | +| `ly` | ly TUI display manager, cyberqueer-themed | ### Gaming diff --git a/etc-lightdm/lightdm-gtk-greeter.conf b/etc-lightdm/lightdm-gtk-greeter.conf new file mode 100644 index 0000000..ec93b05 --- /dev/null +++ b/etc-lightdm/lightdm-gtk-greeter.conf @@ -0,0 +1,17 @@ +# lightdm-gtk-greeter.conf — cyberqueer-themed LightDM greeter +# +# Deployed to /etc/lightdm/lightdm-gtk-greeter.conf by +# setup/modules/optional-Modules/apps/lightdm.sh. +# +# Colours are inherited from the cyberqueer GTK theme (installed to +# /usr/share/themes/cyberqueer), which is an apply-theme.sh SYS_FILES target — +# so there are no hardcoded palette hex values to keep in sync here. +[greeter] +theme-name = cyberqueer +icon-theme-name = Papirus-Dark +background = /usr/share/backgrounds/cyberqueer-skull.png +font-name = JetBrains Mono 11 +xft-antialias = true +xft-hintstyle = hintfull +indicators = ~host;~spacer;~clock;~spacer;~session;~power +clock-format = %H:%M diff --git a/setup/install-modules.sh b/setup/install-modules.sh index 090dac8..1eae7c1 100755 --- a/setup/install-modules.sh +++ b/setup/install-modules.sh @@ -113,6 +113,9 @@ count_steps() { [[ "$sel" == *"butter"* ]] && TOTAL=$(( TOTAL + 1 )) [[ "$sel" == *"plymouth"* ]] && TOTAL=$(( TOTAL + 1 )) [[ "$sel" == *"plymouth-custom"* ]] && TOTAL=$(( TOTAL + 1 )) + [[ "$sel" == *"lightdm"* ]] && TOTAL=$(( TOTAL + 1 )) + # 'ly' is padded/quote-stripped so it doesn't substring-match 'p(ly)mouth'. + [[ " ${sel//\"/} " == *" ly "* ]] && TOTAL=$(( TOTAL + 1 )) [[ "$sel" == *"tlp"* ]] && TOTAL=$(( TOTAL + 1 )) [[ "$sel" == *"steam"* ]] && TOTAL=$(( TOTAL + 1 )) [[ "$sel" == *"vesktop"* ]] && TOTAL=$(( TOTAL + 1 )) @@ -211,6 +214,8 @@ SELECTED=$(dialog --backtitle "$BACKTITLE" \ "butter" "butter btrfs snapshot backup (AUR)" off \ "plymouth" "Plymouth boot splash — skull logo + spinner" off \ "plymouth-custom" "Plymouth (custom) boot splash — supply your own image" off \ + "lightdm" "LightDM GTK greeter, cyberqueer-themed" off \ + "ly" "ly TUI display manager, cyberqueer" off \ "tlp" "TLP laptop power management" off \ \ "steam" "Steam gaming platform" off \ @@ -304,6 +309,8 @@ SUMMARY="" [[ "$SELECTED" == *"localtunnel"* ]] && SUMMARY+=" ✦ LocalTunnel\n" [[ "$SELECTED" == *"butter"* ]] && SUMMARY+=" ✦ butter (btrfs backup)\n" [[ "$SELECTED" == *"plymouth"* ]] && SUMMARY+=" ✦ Plymouth boot splash\n" +[[ "$SELECTED" == *"lightdm"* ]] && SUMMARY+=" ✦ LightDM greeter\n" +[[ " ${SELECTED//\"/} " == *" ly "* ]] && SUMMARY+=" ✦ ly greeter\n" if [[ "$SELECTED" == *"plymouth-custom"* ]]; then if [[ -n "$PLYMOUTH_LOGO_SRC" ]]; then SUMMARY+=" ✦ Plymouth (custom logo: $PLYMOUTH_LOGO_SRC)\n" @@ -384,11 +391,14 @@ DE_DIR="$MODULES/Desktop-Environments" [[ "$SELECTED" == *"ffmpeg"* ]] && run_module "FFmpeg extras" "$APPS/ffmpeg.sh" [[ "$SELECTED" == *"localtunnel"* ]] && run_module "LocalTunnel" "$APPS/localtunnel.sh" [[ "$SELECTED" == *"butter"* ]] && run_module "butter" "$APPS/butter.sh" -[[ "$SELECTED" == *"plymouth"* ]] && run_module "Plymouth" "$MODULES/optional-Modules/plymouth.sh" +[[ "$SELECTED" == *"plymouth"* ]] && run_module "Plymouth" "$APPS/plymouth.sh" if [[ "$SELECTED" == *"plymouth-custom"* ]]; then export PLYMOUTH_LOGO_SRC run_module "Plymouth (custom)" "$APPS/plymouth-custom.sh" fi +[[ "$SELECTED" == *"lightdm"* ]] && run_module "LightDM greeter" "$APPS/lightdm.sh" +# 'ly' is padded/quote-stripped so it doesn't substring-match 'p(ly)mouth'. +[[ " ${SELECTED//\"/} " == *" ly "* ]] && run_module "ly greeter" "$APPS/ly.sh" [[ "$SELECTED" == *"tlp"* ]] && run_module "TLP" "$APPS/tlp.sh" [[ "$SELECTED" == *"steam"* ]] && run_module "Steam" "$APPS/steam.sh" [[ "$SELECTED" == *"vesktop"* ]] && run_module "Vesktop" "$APPS/vesktop.sh" diff --git a/setup/modules.conf b/setup/modules.conf index 69c34b9..e07da11 100644 --- a/setup/modules.conf +++ b/setup/modules.conf @@ -51,6 +51,8 @@ zfs|system|zfs-dkms kernel module|off| wprs|system|Wayland proxy for remote sessions (wprs-git, AUR)|off| plymouth|system|boot splash — bundled skull logo and spinner|on|plymouth-custom plymouth-custom|system|boot splash with a user-supplied image|off|plymouth +lightdm|system|LightDM GTK greeter, cyberqueer-themed (HyprLua default)|off|ly +ly|system|ly TUI display manager, cyberqueer-themed|off|lightdm # ── Gaming ──────────────────────────────────────────────────────────────────── steam|gaming|Steam gaming platform|off| diff --git a/setup/modules/Desktop-Environments/hyprlua.sh b/setup/modules/Desktop-Environments/hyprlua.sh index 6ad7c48..cd1ad44 100755 --- a/setup/modules/Desktop-Environments/hyprlua.sh +++ b/setup/modules/Desktop-Environments/hyprlua.sh @@ -25,7 +25,7 @@ # 3. systemd service enablement # 4. AUR packages via yay # 5. EWW bar (form-factor selection + Rust compilation) -# 6. Themes, ly config, terminal symlink, SSH askpass, dark-mode preference +# 6. Themes, terminal symlink, SSH askpass, dark-mode preference # 7. Nordzy left-hand cursor theme # 8. Bluetooth / iwd services # 9. Config file deployment (hyprlua source tree) @@ -133,7 +133,6 @@ HYPRLUA_PACKAGES=( hyprpicker # colour picker outputting hex/rgb/hsl values pcmanfm-qt # Qt file manager (kept as fallback / alternative) udisks2 # D-Bus daemon for querying and managing storage devices - ly # minimal TUI display manager (takes over tty1 from getty) kew # terminal-based music player hyprpolkitagent # Hyprland-native Polkit authentication agent @@ -155,18 +154,13 @@ log "Enabling essential services..." # NetworkManager: manages all network connections (wired, Wi-Fi, VPN). enable_service NetworkManager.service -# Disable the default getty login prompt on tty1 so ly can own that TTY. -# '|| true' prevents abort if the unit is already disabled. -sudo systemctl disable getty@tty1.service || true - -# Disable greetd, which core.sh enables by default for every install. hyprlua -# uses ly as its greeter, so leaving greetd enabled means two display managers -# both race to claim tty1 — and the stale greetd/tuigreet greeter can win, -# showing the old text login instead of ly. Disable it so ly is the sole greeter. -disable_service greetd.service - -# ly: TUI display manager that presents the login screen on tty1. -enable_service ly@tty1.service +# Greeter: HyprLua uses LightDM with the cyberqueer GTK greeter. The lightdm +# module installs LightDM, deploys its themed config + skull background, disables +# the competing greeters (greetd from core.sh, ly, and the tty1 getty) and +# enables lightdm.service — so exactly one display manager owns the login screen. +# ly remains available as a standalone module (optional-Modules/apps/ly.sh) for +# anyone who prefers it. +bash "$(dirname "${BASH_SOURCE[0]}")/../optional-Modules/apps/lightdm.sh" # udisks2: D-Bus block-device service required by udiskie for auto-mounting. enable_service udisks2.service @@ -273,8 +267,8 @@ sudo cp -r ~/Dotfiles/gtk-themes/cyberqueer /usr/share/themes # Install the matching btop resource-monitor colour theme. sudo cp ~/Dotfiles/desktopenvs/hyprlua/btop/themes/cyberqueer.theme /usr/share/btop/themes -# Deploy the ly display-manager configuration (login screen appearance). -sudo cp -f ~/Dotfiles/etc-ly-config.ini /etc/ly/config.ini +# (The login greeter — LightDM + cyberqueer GTK greeter — is set up in step 3 +# via the lightdm module, which also deploys the greeter theme and background.) # Register kitty as the system terminal for xdg-terminal-exec so file managers # and scripts that open "a terminal here" consistently launch kitty. diff --git a/setup/modules/optional-Modules/apps/lightdm.sh b/setup/modules/optional-Modules/apps/lightdm.sh new file mode 100755 index 0000000..385d5a1 --- /dev/null +++ b/setup/modules/optional-Modules/apps/lightdm.sh @@ -0,0 +1,71 @@ +#!/bin/bash +# lightdm.sh — LightDM + GTK greeter (cyberqueer-themed) +# +# The default greeter for HyprLua. LightDM's GTK greeter reuses the cyberqueer +# GTK theme shipped in this repo (gtk-themes/cyberqueer), so it matches the rest +# of the desktop, and it is driven by a single trivial INI file +# (/etc/lightdm/lightdm-gtk-greeter.conf) — the simplest config of the +# LightDM/LXDM/GDM options. +# +# This module is self-contained (installs the theme + skull background itself) +# so it can also be selected on its own from modules.conf. It is mutually +# exclusive with the ly greeter module. Enabling LightDM here disables the other +# greeters (greetd, ly) and the tty1 getty so exactly one display manager runs. + +set -euo pipefail +source "$(dirname "${BASH_SOURCE[0]}")/../../lib/logging.sh" + +# apps/ → optional-Modules → modules → setup → repo root (four levels up). +DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)" + +log "Installing LightDM + GTK greeter..." +sudo pacman -S --noconfirm --needed lightdm lightdm-gtk-greeter + +# ── Ensure the cyberqueer GTK theme is present system-wide ──────────────────── +# The greeter runs as the 'lightdm' user and reads themes from /usr/share/themes. +# DE modules already install this, but copy it here too so LightDM can be chosen +# standalone. (Papirus-Dark icons are pulled in by the desktop modules.) +GTK_THEME_SRC="$DOTFILES_DIR/gtk-themes/cyberqueer" +if [[ -d "$GTK_THEME_SRC" ]]; then + log "Installing cyberqueer GTK theme to /usr/share/themes..." + sudo cp -r "$GTK_THEME_SRC" /usr/share/themes/ +else + warn "cyberqueer GTK theme not found at $GTK_THEME_SRC — greeter will use the default GTK theme." +fi + +# ── Render the skull background from the bundled SVG ─────────────────────────── +# lightdm-gtk-greeter needs a raster background; convert the 1920x1080 SVG. +SKULL_SRC="$DOTFILES_DIR/resources/bg-skull.svg" +SKULL_DST="/usr/share/backgrounds/cyberqueer-skull.png" +if [[ -f "$SKULL_SRC" ]]; then + if ! command -v rsvg-convert &>/dev/null; then + log "Installing librsvg (rsvg-convert) for SVG→PNG conversion..." + sudo pacman -S --noconfirm --needed librsvg + fi + log "Rendering skull background → $SKULL_DST..." + TMP_BG="$(mktemp /tmp/lightdm-skull.XXXXXX.png)" + trap 'rm -f "$TMP_BG"' EXIT + rsvg-convert -w 1920 "$SKULL_SRC" -o "$TMP_BG" + sudo install -Dm644 "$TMP_BG" "$SKULL_DST" +else + warn "Skull SVG not found at $SKULL_SRC — greeter will fall back to a solid background." +fi + +# ── Deploy the greeter configuration ────────────────────────────────────────── +GREETER_CONF_SRC="$DOTFILES_DIR/etc-lightdm/lightdm-gtk-greeter.conf" +if [[ -f "$GREETER_CONF_SRC" ]]; then + log "Deploying lightdm-gtk-greeter.conf..." + sudo install -Dm644 "$GREETER_CONF_SRC" /etc/lightdm/lightdm-gtk-greeter.conf +else + warn "Greeter config not found at $GREETER_CONF_SRC — LightDM will use greeter defaults." +fi + +# ── Make LightDM the sole display manager ───────────────────────────────────── +# LightDM manages its own VT; free tty1 and disable the competing greeters so +# nothing else races it. +sudo systemctl disable getty@tty1.service || true +disable_service greetd.service +disable_service ly@tty1.service +enable_service lightdm.service + +log "LightDM installed and enabled. The cyberqueer GTK greeter starts on next boot." diff --git a/setup/modules/optional-Modules/apps/ly.sh b/setup/modules/optional-Modules/apps/ly.sh new file mode 100755 index 0000000..31c7af2 --- /dev/null +++ b/setup/modules/optional-Modules/apps/ly.sh @@ -0,0 +1,43 @@ +#!/bin/bash +# ly.sh — ly TUI display manager (cyberqueer-themed) +# +# ly is a minimal, animated TUI login manager that takes over tty1 from getty. +# Its cyberqueer theming (colormix / doom animation colours) lives in the repo's +# etc-ly-config.ini, which is also an apply-theme.sh SYS_FILES target so the +# palette stays in sync. +# +# This module was extracted from the Desktop-Environment scripts so ly can be +# installed independently of any particular DE. It is mutually exclusive with +# the lightdm greeter module (see modules.conf). Enabling ly here disables the +# other greeters (greetd, lightdm) and the tty1 getty so exactly one display +# manager owns tty1. + +set -euo pipefail +source "$(dirname "${BASH_SOURCE[0]}")/../../lib/logging.sh" + +# apps/ → optional-Modules → modules → setup → repo root (four levels up). +DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)" + +log "Installing ly display manager..." +sudo pacman -S --noconfirm --needed ly + +# ── Deploy the cyberqueer ly configuration ──────────────────────────────────── +LY_CONF_SRC="$DOTFILES_DIR/etc-ly-config.ini" +if [[ -f "$LY_CONF_SRC" ]]; then + log "Deploying ly config to /etc/ly/config.ini..." + sudo mkdir -p /etc/ly + sudo cp -f "$LY_CONF_SRC" /etc/ly/config.ini +else + warn "ly config not found at $LY_CONF_SRC — leaving ly defaults in place." +fi + +# ── Make ly the sole greeter on tty1 ────────────────────────────────────────── +# Free tty1 from the getty login prompt so ly can own it. +sudo systemctl disable getty@tty1.service || true +# Turn off the other display managers so two greeters don't race for tty1. +disable_service greetd.service +disable_service lightdm.service +# ly presents the login screen on tty1. +enable_service ly@tty1.service + +log "ly display manager installed and enabled. It takes over tty1 on next boot." diff --git a/setup/modules/optional-Modules/apps/plymouth-custom.sh b/setup/modules/optional-Modules/apps/plymouth-custom.sh index e84957d..faa3a48 100644 --- a/setup/modules/optional-Modules/apps/plymouth-custom.sh +++ b/setup/modules/optional-Modules/apps/plymouth-custom.sh @@ -19,4 +19,4 @@ fi log "Custom Plymouth logo: $PLYMOUTH_LOGO_SRC" export PLYMOUTH_LOGO_SRC -exec bash "$(dirname "${BASH_SOURCE[0]}")/../plymouth.sh" +exec bash "$(dirname "${BASH_SOURCE[0]}")/plymouth.sh" diff --git a/setup/modules/optional-Modules/apps/plymouth.sh b/setup/modules/optional-Modules/apps/plymouth.sh index d92af94..5f43ba1 100644 --- a/setup/modules/optional-Modules/apps/plymouth.sh +++ b/setup/modules/optional-Modules/apps/plymouth.sh @@ -1,8 +1,9 @@ #!/bin/bash # plymouth.sh — Plymouth boot splash installer # -# Installs the M-Archy Plymouth theme: skull logo centred on a dark background -# with a magenta spinning-dot animation below it. +# Installs the M-Archy Plymouth theme: the transparent skull/CRT artwork scaled +# to fill the screen over a dark background, with a magenta spinning-dot +# animation near the bottom. # # SVG NOTE: Plymouth's image loader (ply-image) is PNG-only — it links against # libpng and has no SVG or gdk-pixbuf dependency. The ply-image.h header is @@ -19,7 +20,7 @@ # Steps: # 1. Install plymouth (extra repo) # 2. Install librsvg (rsvg-convert) if logo is SVG; imagemagick for dot -# 3. Produce logo.png (300 px wide) from the resolved source +# 3. Produce logo.png (native 1920 px wide) from the resolved source # 4. Generate a 10×10 magenta dot.png for the spinner # 5. Write the m-archy theme (.plymouth descriptor + .script animation) # 6. Register with plymouth-set-default-theme @@ -32,7 +33,8 @@ source "$(dirname "${BASH_SOURCE[0]}")/../../lib/logging.sh" THEME_DIR="/usr/share/plymouth/themes/m-archy" SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -DOTFILES_DIR="$(cd "$SCRIPT_DIR/../../.." && pwd)" +# apps/ → optional-Modules → modules → setup → repo root (four levels up). +DOTFILES_DIR="$(cd "$SCRIPT_DIR/../../../.." && pwd)" # Resolve logo source — env var takes priority, then bundled SVG LOGO_SRC="${PLYMOUTH_LOGO_SRC:-}" @@ -67,7 +69,7 @@ trap 'rm -f "$TMP_LOGO" "$TMP_DOT"' EXIT if [[ -z "$LOGO_SRC" ]]; then warn "No logo source found — using transparent placeholder." - convert -size 300x300 xc:transparent "$TMP_LOGO" + convert -size 1920x1080 xc:transparent "$TMP_LOGO" elif [[ "${LOGO_SRC,,}" == *.png ]]; then log "Using PNG directly: $LOGO_SRC" cp "$LOGO_SRC" "$TMP_LOGO" @@ -77,8 +79,10 @@ else log "Installing librsvg (rsvg-convert) for SVG→PNG conversion..." sudo pacman -S --noconfirm --needed librsvg fi - log "Converting $LOGO_SRC → PNG (300 px wide)..." - rsvg-convert -w 300 "$LOGO_SRC" -o "$TMP_LOGO" + # Render at native width so the full-screen splash keeps detail when the + # Plymouth script scales it to the display resolution. + log "Converting $LOGO_SRC → PNG (1920 px wide)..." + rsvg-convert -w 1920 "$LOGO_SRC" -o "$TMP_LOGO" fi # ── Generate spinner dot ────────────────────────────────────────────────────── @@ -106,7 +110,7 @@ ScriptFile=/usr/share/plymouth/themes/m-archy/m-archy.script EOF sudo tee "$THEME_DIR/m-archy.script" > /dev/null <<'EOF' -# M-Archy Plymouth splash — skull logo + magenta spinner +# M-Archy Plymouth splash — full-screen skull background + magenta spinner Window.SetBackgroundTopColor (0.10, 0.10, 0.10); Window.SetBackgroundBottomColor (0.07, 0.07, 0.07); @@ -114,19 +118,24 @@ Window.SetBackgroundBottomColor (0.07, 0.07, 0.07); screen_width = Window.GetWidth (); screen_height = Window.GetHeight (); -# Centred skull logo +# Full-screen skull background. bg-skull.svg is a 1920x1080 composition with a +# transparent field, so we scale it to fill the display and pin it at the +# origin; the transparent areas reveal the dark background gradient above. logo.image = Image ("logo.png"); -logo.sprite = Sprite (logo.image); -logo.sprite.SetX (Math.Int (screen_width / 2 - logo.image.GetWidth () / 2)); -logo.sprite.SetY (Math.Int (screen_height / 2 - logo.image.GetHeight () / 2)); +scaled = logo.image.Scale (screen_width, screen_height); +logo.sprite = Sprite (scaled); +logo.sprite.SetX (0); +logo.sprite.SetY (0); logo.sprite.SetZ (10); -# 12-dot spinner below the logo +# 12-dot spinner near the bottom of the screen. The centre is a fixed fraction +# of the screen height (not derived from the logo size) so it stays put +# regardless of the source image's dimensions. num_dots = 12; dot_r = 5; orbit = 35; cx = screen_width / 2; -cy = screen_height / 2 + logo.image.GetHeight () / 2 + 55; +cy = Math.Int (screen_height * 0.93); dot.image = Image ("dot.png"); for (i = 0; i < num_dots; i++) { diff --git a/setup/tools/generate-answerfile.sh b/setup/tools/generate-answerfile.sh index 6acdc70..264637d 100755 --- a/setup/tools/generate-answerfile.sh +++ b/setup/tools/generate-answerfile.sh @@ -239,7 +239,7 @@ if [[ "$AF_RUN_TUI" == "true" ]]; then # BEGIN GENERATED MODULES: module-checklist AF_APPS=$(dialog --backtitle "$BACKTITLE" \ --title " Applications " \ - --checklist "Optional applications — installed after base components:" 40 76 80 \ + --checklist "Optional applications — installed after base components:" 40 76 82 \ "ollama" "ollama local LLM runner and API server" off \ "llama-cpp" "llama-cpp standalone LLM inference CLI and server" off \ "open-webui" "open-webui browser UI for Ollama and LLM backends" off \ @@ -274,6 +274,8 @@ if [[ "$AF_RUN_TUI" == "true" ]]; then "wprs" "wprs Wayland proxy for remote sessions (wprs-git, AUR)" off \ "plymouth" "plymouth boot splash — bundled skull logo and spinner" on \ "plymouth-custom" "plymouth-custom boot splash with a user-supplied image" off \ + "lightdm" "lightdm LightDM GTK greeter, cyberqueer-themed (HyprLua default)" off \ + "ly" "ly ly TUI display manager, cyberqueer-themed" off \ "steam" "steam Steam gaming platform" off \ "vesktop" "vesktop Discord client with Vencord theme" off \ "spotify" "spotify Spotify launcher with Spicetify theming" off \ diff --git a/setup/tools/migrate-to-lightdm.sh b/setup/tools/migrate-to-lightdm.sh new file mode 100755 index 0000000..a0febd7 --- /dev/null +++ b/setup/tools/migrate-to-lightdm.sh @@ -0,0 +1,193 @@ +#!/bin/bash +# ============================================================================= +# migrate-to-lightdm.sh — switch an existing install to Plymouth + LightDM +# ============================================================================= +# Migrates a machine that currently boots ly / greetd / GDM / SDDM / LXDM (or any +# other display manager) to this repo's boot experience: +# +# Plymouth skull splash → LightDM + lightdm-gtk-greeter (cyberqueer theme) +# +# What it does: +# 1. Detects the currently-configured display manager(s). +# 2. Disables every known greeter EXCEPT lightdm — for the NEXT boot only. It +# does NOT stop your running session, so you stay logged in until you +# reboot yourself. +# 3. Runs the lightdm module (installs LightDM + lightdm-gtk-greeter, deploys +# the cyberqueer greeter config + skull background, enables lightdm.service). +# 4. Runs the plymouth module (skull splash, initramfs + GRUB cmdline) unless +# --no-plymouth is given. +# +# It reuses the real module scripts under optional-Modules/apps/ so there is no +# duplicated install logic — this tool only handles detection, teardown of the +# OLD display manager, and orchestration. +# +# Safe to re-run (idempotent). Reboot to complete the switch. +# +# Usage: +# migrate-to-lightdm.sh [--yes] [--no-plymouth] [--dry-run] [--help] +# -y, --yes Skip the confirmation prompt (required for non-TTY runs) +# --no-plymouth Migrate the display manager only; leave Plymouth alone +# -n, --dry-run Print what would happen; change nothing +# -h, --help Show this help and exit +# ============================================================================= + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +SETUP_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" +APPS="$SETUP_DIR/modules/optional-Modules/apps" + +# Shared helpers: log / skip / warn / err, and best-effort disable_service. +source "$SETUP_DIR/modules/lib/logging.sh" + +# ── Argument parsing ────────────────────────────────────────────────────────── +ASSUME_YES=0 +DO_PLYMOUTH=1 +DRY_RUN=0 + +usage() { + cat <<'EOF' +migrate-to-lightdm.sh — switch this machine to Plymouth + LightDM (cyberqueer) + +Disables the current display manager (ly / greetd / GDM / SDDM / LXDM / …) for +the next boot, installs and themes LightDM, and sets up the Plymouth splash. Your +running session is left untouched; reboot to complete the switch. + +Usage: + migrate-to-lightdm.sh [--yes] [--no-plymouth] [--dry-run] [--help] + -y, --yes Skip the confirmation prompt (required for non-TTY runs) + --no-plymouth Migrate the display manager only; leave Plymouth alone + -n, --dry-run Print what would happen; change nothing + -h, --help Show this help and exit +EOF +} + +while [[ $# -gt 0 ]]; do + case "$1" in + -y|--yes) ASSUME_YES=1 ;; + --no-plymouth) DO_PLYMOUTH=0 ;; + -n|--dry-run) DRY_RUN=1 ;; + -h|--help) usage; exit 0 ;; + *) err "Unknown argument: $1"; echo "Try --help." >&2; exit 2 ;; + esac + shift +done + +# In dry-run, describe an action instead of doing it. In real mode, run it. +run() { + if (( DRY_RUN )); then + printf '[dry-run] would run: %s\n' "$*" + else + "$@" + fi +} + +# ── Known display managers ──────────────────────────────────────────────────── +# Every greeter/DM unit this tool knows how to turn off. lightdm is the TARGET, +# so it never appears here. ly is a template unit (ly@tty1) but some setups use +# the plain ly.service alias, so both are listed. +OTHER_DMS=( + "ly@tty1.service" "ly.service" + "greetd.service" + "gdm.service" "gdm3.service" + "sddm.service" + "lxdm.service" + "xdm.service" + "slim.service" + "lemurs.service" + "emptty.service" +) + +# ── 1. Detect what is configured now ────────────────────────────────────────── +log "Detecting the current display manager configuration..." + +# The canonical "which DM boots" pointer is the display-manager.service symlink. +# Use plain readlink to get the intended target name even if the link is broken; +# a self-referential/absent target means no real DM is configured there. +primary_dm="" +if dm_link="$(readlink /etc/systemd/system/display-manager.service 2>/dev/null)"; then + dm_link="$(basename "$dm_link")" + [[ "$dm_link" != "display-manager.service" ]] && primary_dm="$dm_link" +fi + +# Also probe every known unit directly — ly-based installs often have no +# display-manager.service symlink, they just enable ly@tty1 on tty1. +enabled_dms=() +for unit in "${OTHER_DMS[@]}"; do + state="$(systemctl is-enabled "$unit" 2>/dev/null || true)" + [[ "$state" == "enabled" || "$state" == "alias" || "$state" == "enabled-runtime" ]] \ + && enabled_dms+=("$unit") +done + +# `is-enabled` on an absent unit both prints "not-found" and exits non-zero; +# capture with `|| true` (never `|| echo`, which would concatenate two lines) +# and normalise the "not installed" cases to one label. +lightdm_state="$(systemctl is-enabled lightdm.service 2>/dev/null || true)" +[[ -z "$lightdm_state" || "$lightdm_state" == "not-found" ]] && lightdm_state="not-installed" + +echo +echo " Current display-manager.service : ${primary_dm:-}" +if (( ${#enabled_dms[@]} )); then + echo " Enabled greeter units : ${enabled_dms[*]}" +else + echo " Enabled greeter units : " +fi +echo " lightdm.service : $lightdm_state" +echo " Plymouth migration : $( ((DO_PLYMOUTH)) && echo 'yes' || echo 'skipped (--no-plymouth)')" +echo + +if (( ${#enabled_dms[@]} == 0 )) && [[ "$lightdm_state" == "enabled" ]]; then + log "LightDM already appears to be the active greeter — re-running to refresh config/theme." +fi + +# ── 2. Confirm ──────────────────────────────────────────────────────────────── +# This changes what greets you at the NEXT boot. Require an explicit yes unless +# --yes was given; on a non-interactive stdin, --yes is mandatory. +if (( ! ASSUME_YES )); then + if [[ ! -t 0 ]]; then + err "Non-interactive shell and --yes not given — refusing to change the display manager." + exit 1 + fi + read -r -p "Switch this machine to Plymouth + LightDM as described above? [y/N] " reply + case "$reply" in + y|Y|yes|YES) ;; + *) warn "Aborted — nothing changed."; exit 0 ;; + esac +fi + +# ── 3. Disable the OLD display managers (next boot only) ────────────────────── +# We intentionally do NOT `systemctl stop` the running greeter: that would kill +# your current graphical session. Disabling only removes it from the next boot; +# lightdm.service (enabled below) takes over then. +if (( ${#enabled_dms[@]} )); then + log "Disabling old display manager(s) for the next boot: ${enabled_dms[*]}" + for unit in "${enabled_dms[@]}"; do + run disable_service "$unit" + done +else + skip "No competing display managers enabled — nothing to disable." +fi + +# ── 4. Install + theme + enable LightDM (delegated to the module) ───────────── +# lightdm.sh installs LightDM + the GTK greeter, deploys the cyberqueer greeter +# config + skull background, disables greetd/ly@tty1/getty@tty1, and enables +# lightdm.service. Running it here keeps a single source of truth. +log "Setting up LightDM via the lightdm module..." +run bash "$APPS/lightdm.sh" + +# ── 5. Plymouth splash (delegated to the module) ────────────────────────────── +if (( DO_PLYMOUTH )); then + log "Setting up the Plymouth splash via the plymouth module..." + run bash "$APPS/plymouth.sh" +else + skip "Skipping Plymouth setup (--no-plymouth)." +fi + +# ── Done ────────────────────────────────────────────────────────────────────── +echo +if (( DRY_RUN )); then + log "Dry run complete — no changes were made." +else + log "Migration complete. Your current session is untouched." + log "Reboot to boot into the Plymouth splash and the LightDM cyberqueer greeter." +fi diff --git a/setup/tui-install.sh b/setup/tui-install.sh index 5c141eb..7ba9b7b 100755 --- a/setup/tui-install.sh +++ b/setup/tui-install.sh @@ -367,6 +367,8 @@ count_steps() { [[ " $a " == *" wprs "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" plymouth "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" plymouth-custom "* ]] && TOTAL=$(( TOTAL + 1 )) + [[ " $a " == *" lightdm "* ]] && TOTAL=$(( TOTAL + 1 )) + [[ " $a " == *" ly "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" steam "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" vesktop "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" spotify "* ]] && TOTAL=$(( TOTAL + 1 )) @@ -589,6 +591,8 @@ else "wprs" "wprs Wayland proxy for remote sessions (wprs-git, AUR)" off \ "plymouth" "plymouth boot splash — bundled skull logo and spinner" on \ "plymouth-custom" "plymouth-custom boot splash with a user-supplied image" off \ + "lightdm" "lightdm LightDM GTK greeter, cyberqueer-themed (HyprLua default)" off \ + "ly" "ly ly TUI display manager, cyberqueer-themed" off \ "steam" "steam Steam gaming platform" off \ "vesktop" "vesktop Discord client with Vencord theme" off \ "spotify" "spotify Spotify launcher with Spicetify theming" off \ @@ -700,6 +704,8 @@ if ! $ANSWERFILE_MODE; then [[ " $SELECTED_APPS " == *" wprs "* ]] && SUMMARY+=" ✦ wprs\n" [[ " $SELECTED_APPS " == *" plymouth "* ]] && SUMMARY+=" ✦ plymouth\n" [[ " $SELECTED_APPS " == *" plymouth-custom "* ]] && SUMMARY+=" ✦ plymouth-custom\n" + [[ " $SELECTED_APPS " == *" lightdm "* ]] && SUMMARY+=" ✦ lightdm\n" + [[ " $SELECTED_APPS " == *" ly "* ]] && SUMMARY+=" ✦ ly\n" [[ " $SELECTED_APPS " == *" steam "* ]] && SUMMARY+=" ✦ steam\n" [[ " $SELECTED_APPS " == *" vesktop "* ]] && SUMMARY+=" ✦ vesktop\n" [[ " $SELECTED_APPS " == *" spotify "* ]] && SUMMARY+=" ✦ spotify\n" @@ -804,6 +810,20 @@ if [[ " $SELECTED_APPS " == *" plymouth-custom "* && " $SELECTED_APPS " == *" pl SELECTED_APPS="${SELECTED_APPS# }" SELECTED_APPS="${SELECTED_APPS% }" fi +if [[ " $SELECTED_APPS " == *" lightdm "* && " $SELECTED_APPS " == *" ly "* ]]; then + warn "'lightdm' and 'ly' are mutually exclusive — deselecting 'ly'" + SELECTED_APPS=" $SELECTED_APPS " + SELECTED_APPS="${SELECTED_APPS/ ly / }" + SELECTED_APPS="${SELECTED_APPS# }" + SELECTED_APPS="${SELECTED_APPS% }" +fi +if [[ " $SELECTED_APPS " == *" ly "* && " $SELECTED_APPS " == *" lightdm "* ]]; then + warn "'ly' and 'lightdm' are mutually exclusive — deselecting 'lightdm'" + SELECTED_APPS=" $SELECTED_APPS " + SELECTED_APPS="${SELECTED_APPS/ lightdm / }" + SELECTED_APPS="${SELECTED_APPS# }" + SELECTED_APPS="${SELECTED_APPS% }" +fi # END GENERATED MODULES: module-conflicts # BEGIN GENERATED MODULES: module-dispatch [[ " $SELECTED_APPS " == *" ollama "* ]] && run_module "ollama" "$APPS/ollama.sh" @@ -840,6 +860,8 @@ fi [[ " $SELECTED_APPS " == *" wprs "* ]] && run_module "wprs" "$APPS/wprs.sh" [[ " $SELECTED_APPS " == *" plymouth "* ]] && run_module "plymouth" "$APPS/plymouth.sh" [[ " $SELECTED_APPS " == *" plymouth-custom "* ]] && run_module "plymouth-custom" "$APPS/plymouth-custom.sh" +[[ " $SELECTED_APPS " == *" lightdm "* ]] && run_module "lightdm" "$APPS/lightdm.sh" +[[ " $SELECTED_APPS " == *" ly "* ]] && run_module "ly" "$APPS/ly.sh" [[ " $SELECTED_APPS " == *" steam "* ]] && run_module "steam" "$APPS/steam.sh" [[ " $SELECTED_APPS " == *" vesktop "* ]] && run_module "vesktop" "$APPS/vesktop.sh" [[ " $SELECTED_APPS " == *" spotify "* ]] && run_module "spotify" "$APPS/spotify.sh"