From b879b1ae8905240a4195bebd6c4b067549db9e6e Mon Sep 17 00:00:00 2001 From: The_miro Date: Sat, 4 Jul 2026 13:37:30 +0200 Subject: [PATCH] feat(greeter): cyberqueer ReGreet theme + wire greetd into installers Add a self-contained CyberQueer login skin for the greetd/ReGreet greeter and make it a first-class, selectable module. Theme: - New etc-greetd/regreet.css: login-specific stylesheet (glowing pink clock + card, violet-bordered combos, hot-pink Login, quiet red-outline power buttons). Loaded by ReGreet at APPLICATION priority over an Adwaita-dark base; regreet.toml theme_name switched cyberqueer->Adwaita to avoid the desktop theme's `* { all: unset }`. Redefines Adwaita's accent/destructive named colours so the semantic buttons recolour. Verified via headless demo render. - Register regreet.css in apply-theme.sh SYS_FILES so palette edits propagate. Installers: - modules.conf: add greetd-regreet (three-way mutually exclusive with lightdm+ly). - Regenerate tui-install.sh, generate-answerfile.sh, docs/md/modules.md via generate-modules.sh. - install-modules.sh (hand-maintained): add greetd-regreet to counter/menu/ summary/dispatch. Migration: - New migrate-to-greetd.sh: migrate to Plymouth + greetd/ReGreet (greetd is the target, so it's not in the disable list). migrate-to-lightdm.sh relabelled the Xorg alternative. Co-Authored-By: Claude Opus 4.8 Claude-Session: https://claude.ai/code/session_01P1ApxGuM3N3nSiAJonSjMQ --- apply-theme.sh | 1 + docs/md/modules.md | 3 +- etc-greetd/regreet.css | 257 ++++++++++++++++++ etc-greetd/regreet.toml | 18 +- setup/install-modules.sh | 6 +- setup/modules.conf | 5 +- .../optional-Modules/apps/greetd-regreet.sh | 13 +- setup/tools/generate-answerfile.sh | 5 +- setup/tools/migrate-to-greetd.sh | 220 +++++++++++++++ setup/tools/migrate-to-lightdm.sh | 4 + setup/tui-install.sh | 34 ++- 11 files changed, 549 insertions(+), 17 deletions(-) create mode 100644 etc-greetd/regreet.css create mode 100755 setup/tools/migrate-to-greetd.sh diff --git a/apply-theme.sh b/apply-theme.sh index 4a60be7..3013776 100755 --- a/apply-theme.sh +++ b/apply-theme.sh @@ -61,6 +61,7 @@ USER_FILES=( # System-owned paths — sed is run via sudo SYS_FILES=( "etc-ly-config.ini|/etc/ly/config.ini" + "etc-greetd/regreet.css|/etc/greetd/regreet.css" "gtk-themes/cyberqueer/gtk-3.0/gtk.css|/usr/share/themes/cyberqueer/gtk-3.0/gtk.css" "gtk-themes/cyberqueer/gtk-4.0/gtk.css|/usr/share/themes/cyberqueer/gtk-4.0/gtk.css" ) diff --git a/docs/md/modules.md b/docs/md/modules.md index 7edd214..852e4f5 100644 --- a/docs/md/modules.md +++ b/docs/md/modules.md @@ -135,7 +135,8 @@ bash ~/Dotfiles/setup/install-modules.sh | `wprs` | Wayland proxy for remote sessions (wprs-git, AUR) | | `plymouth` | boot splash — bundled skull logo + boot-log tail | | `plymouth-custom` | boot splash with a user-supplied image | -| `lightdm` | LightDM GTK greeter, cyberqueer-themed (HyprLua default) | +| `greetd-regreet` | greetd + ReGreet greeter, Wayland-native, cyberqueer-themed | +| `lightdm` | LightDM GTK greeter, cyberqueer-themed (Xorg) | | `ly` | ly TUI display manager, cyberqueer-themed | diff --git a/etc-greetd/regreet.css b/etc-greetd/regreet.css new file mode 100644 index 0000000..743935e --- /dev/null +++ b/etc-greetd/regreet.css @@ -0,0 +1,257 @@ +/* regreet.css — CyberQueer login theme for ReGreet (greetd, Wayland-native) + * + * Deployed to /etc/greetd/regreet.css by + * setup/modules/optional-Modules/apps/greetd-regreet.sh and loaded by ReGreet + * via `regreet -s` at STYLE_PROVIDER_PRIORITY_APPLICATION (600) — i.e. ON TOP of + * the base GTK theme (priority 200). So this file owns the login-screen look + * outright; the base theme (regreet.toml `theme_name`) only supplies sane widget + * defaults. We deliberately do NOT reuse the desktop `cyberqueer` GTK theme here: + * its `* { all: unset }` reset is meant for waybar/eww/Thunar and would strip a + * login card's layout. This is the greeter's own, self-contained cyberqueer skin. + * + * Colours mirror colors.conf (the CyberQueer palette). apply-theme.sh rewrites + * the hex values below in lock-step with the rest of the system — keep them as + * bare 6-digit hex so its case-insensitive sed substitution keeps matching. + * + * ReGreet widget map (relm4 `#[name]` sets Rust fields, NOT CSS ids — so only + * css classes + node types are selectable): + * frame.background → login card AND clock card + * frame.background > grid → the login card's contents + * frame.background > label→ the clock label (clock card's only child) + * entry / entry.password → username / session / secret fields + * combobox → user + session pickers + * button.suggested-action → Login + * button.destructive-action → Reboot / Power Off + * button.toggle → manual user/session entry toggles + * infobar → PAM notification bar + */ + +@define-color cq_bg #1A1A1A; /* near-black base surface */ +@define-color cq_text #D6ABAB; /* warm quasi-white foreground */ +@define-color cq_pink #E40046; /* hot-pink primary accent */ +@define-color cq_violet #5018DD; /* electric-violet secondary */ +@define-color cq_red #F50505; /* hi-vis danger red */ + +/* Re-tint the base (Adwaita) theme's semantic named colours to CyberQueer. + * Adwaita paints .suggested-action / .destructive-action / selections from + * these named colours, so overriding them here is what actually recolours the + * Login and Reboot/Power-Off buttons (a plain `.suggested-action` rule loses to + * Adwaita's own). Kept in bare hex so apply-theme.sh rewrites them too. */ +@define-color accent_color #E40046; +@define-color accent_bg_color #E40046; +@define-color accent_fg_color #1A1A1A; +@define-color theme_selected_bg_color #E40046; +@define-color theme_selected_fg_color #1A1A1A; +@define-color destructive_color #F50505; +@define-color destructive_bg_color #F50505; +@define-color destructive_fg_color #1A1A1A; + +/* ── Backdrop ───────────────────────────────────────────────────────────── + * Solid near-black behind the wallpaper Picture, so the greeter never flashes + * white and stays legible if no wallpaper has been synced yet. */ +window, +overlay { + background-color: @cq_bg; + color: @cq_text; +} + +/* ── Cards: the login frame and the clock frame both carry `.background` ──── */ +frame.background { + background-color: alpha(@cq_bg, 0.86); + color: @cq_text; + border: 2px solid @cq_pink; + border-radius: 20px; + padding: 10px 16px; + box-shadow: 0 0 26px 2px alpha(@cq_pink, 0.40), + inset 0 0 60px alpha(@cq_violet, 0.14); +} + +/* The clock card sits flush on the top edge (ReGreet flattens its top corners + * via inline_css at priority 800, which wins over this — so we only need to + * style the glow + fill, not fight the border geometry). */ +frame.background > label { + font-family: "JetBrains Mono", monospace; + font-size: 30pt; + font-weight: 700; + letter-spacing: 4px; + padding: 4px 26px; + color: @cq_text; + text-shadow: 0 0 12px alpha(@cq_pink, 0.75), + 0 0 22px alpha(@cq_violet, 0.55); +} + +/* ── Text & labels inside the login card ─────────────────────────────────── */ +frame.background > grid > label { + color: @cq_text; + margin: 0 6px; +} + +/* ── Entries: username / session / password ──────────────────────────────── */ +entry, +entry.password { + background-color: alpha(#000000, 0.45); + color: @cq_text; + caret-color: @cq_pink; + border: 2px solid alpha(@cq_violet, 0.85); + border-radius: 12px; + padding: 8px 12px; + min-height: 34px; + transition: border-color 160ms ease, box-shadow 160ms ease; +} + +entry image, +entry.password image { /* the peek-password / clear icons */ + color: @cq_violet; +} + +entry:focus-within, +entry.password:focus-within { + border-color: @cq_pink; + box-shadow: 0 0 14px 1px alpha(@cq_pink, 0.55); +} + +entry selection { + background-color: @cq_pink; + color: @cq_bg; +} + +/* ── Combo boxes: user + session pickers render as `combobox > button` ───── */ +combobox > button.combo { + background-color: alpha(#000000, 0.45); + color: @cq_text; + border: 2px solid alpha(@cq_violet, 0.85); + border-radius: 12px; + padding: 6px 12px; + min-height: 34px; +} + +combobox > button.combo:hover { + border-color: @cq_pink; +} + +combobox arrow { + color: @cq_pink; + min-height: 16px; + min-width: 16px; +} + +/* The drop-down popover list */ +combobox popover contents { + background-color: @cq_bg; + border: 1px solid @cq_violet; + border-radius: 12px; +} + +combobox popover contents :selected { + background-color: @cq_pink; + color: @cq_bg; +} + +/* ── Buttons ─────────────────────────────────────────────────────────────── */ +button { + color: @cq_text; + background-color: alpha(@cq_violet, 0.16); + border: 2px solid alpha(@cq_violet, 0.85); + border-radius: 12px; + padding: 8px 18px; + min-height: 34px; + transition: all 160ms ease; +} + +button:hover { + background-color: alpha(@cq_violet, 0.32); + border-color: @cq_pink; + color: #FFFFFF; +} + +button:active { + background-color: @cq_violet; + color: @cq_bg; +} + +/* Manual-entry toggles (pencil icons) — quieter, icon-only */ +button.toggle { + background-color: transparent; + border-color: alpha(@cq_violet, 0.55); + padding: 6px; +} + +button.toggle:checked { + background-color: alpha(@cq_pink, 0.20); + border-color: @cq_pink; + color: @cq_pink; +} + +/* Primary action: Login. The `window` prefix (specificity 0,1,2) and + * `background-image: none` are needed to beat Adwaita's own accent styling. */ +window button.suggested-action { + background-image: none; + background-color: @cq_pink; + color: @cq_bg; + border: 2px solid @cq_pink; + font-weight: 700; + box-shadow: 0 0 16px alpha(@cq_pink, 0.45); +} + +window button.suggested-action:hover { + background-color: #FF1A5E; + border-color: #FF1A5E; + color: @cq_bg; + box-shadow: 0 0 22px alpha(@cq_pink, 0.75); +} + +window button.suggested-action:active { + background-color: @cq_violet; + border-color: @cq_violet; +} + +/* Destructive actions: Reboot / Power Off — quiet red outline, red glow on + * hover (overrides Adwaita's solid-red fill; same specificity trick). */ +window button.destructive-action { + background-image: none; + background-color: transparent; + color: @cq_text; + border: 2px solid alpha(@cq_red, 0.65); +} + +window button.destructive-action:hover { + background-color: alpha(@cq_red, 0.18); + border-color: @cq_red; + color: @cq_red; + box-shadow: 0 0 16px alpha(@cq_red, 0.45); +} + +/* ── PAM notification bar ────────────────────────────────────────────────── */ +/* Style only the inner message box so a collapsed/unrevealed infobar draws + * nothing (no stray border line above the power buttons). */ +infobar { + background: transparent; + border: none; + box-shadow: none; +} + +infobar > revealer > box { + background-color: alpha(@cq_bg, 0.90); + color: @cq_text; + border: 2px solid @cq_violet; + border-radius: 12px; + box-shadow: 0 0 18px alpha(@cq_violet, 0.40); +} + +infobar.error > revealer > box { + border-color: @cq_red; + box-shadow: 0 0 18px alpha(@cq_red, 0.45); +} + +infobar label { + color: @cq_text; + padding: 6px 12px; +} + +/* ── Tooltips (hover hints on the toggle buttons) ────────────────────────── */ +tooltip { + background-color: @cq_violet; + color: @cq_bg; + border-radius: 10px; + padding: 4px 8px; +} diff --git a/etc-greetd/regreet.toml b/etc-greetd/regreet.toml index e028e33..6ff444f 100644 --- a/etc-greetd/regreet.toml +++ b/etc-greetd/regreet.toml @@ -3,11 +3,15 @@ # Deployed to /etc/greetd/regreet.toml by # setup/modules/optional-Modules/apps/greetd-regreet.sh. # -# ReGreet is GTK4, so it reuses the cyberqueer GTK theme's gtk-4.0 assets -# (/usr/share/themes/cyberqueer) — matching the desktop without hardcoded colours -# here. Being a wlroots/Wayland greeter it drives every monitor natively (no -# blank outputs) and hands input straight to the Wayland session with no -# Xorg→Wayland VT handover. +# The cyberqueer look is applied by /etc/greetd/regreet.css (loaded via +# `regreet -s` at APPLICATION priority, above the base theme). That stylesheet +# is the greeter's own self-contained CyberQueer skin — we do NOT reuse the +# desktop `cyberqueer` GTK theme, whose `* { all: unset }` reset is tuned for +# waybar/eww/Thunar and would strip a login card's layout. `theme_name` below is +# therefore just a clean, predictable widget base (Adwaita-dark) for the CSS to +# paint on. Being a wlroots/Wayland greeter, ReGreet drives every monitor +# natively (no blank outputs) and hands input straight to the Wayland session +# with no Xorg→Wayland VT handover. # Remember the last user + session and skip the pickers. skip_selection = false @@ -27,7 +31,9 @@ cursor_blink = true # the 4K panel. Tune here (or via GDK_SCALE in regreet-session.sh) to taste. font_name = "JetBrains Mono 16" icon_theme_name = "Adwaita" -theme_name = "cyberqueer" +# Clean base for regreet.css to paint on (see header). The CyberQueer colours +# live in /etc/greetd/regreet.css, not in this theme. +theme_name = "Adwaita" [commands] reboot = ["systemctl", "reboot"] diff --git a/setup/install-modules.sh b/setup/install-modules.sh index ddc6340..f5731bf 100755 --- a/setup/install-modules.sh +++ b/setup/install-modules.sh @@ -113,6 +113,7 @@ count_steps() { [[ "$sel" == *"butter"* ]] && TOTAL=$(( TOTAL + 1 )) [[ "$sel" == *"plymouth"* ]] && TOTAL=$(( TOTAL + 1 )) [[ "$sel" == *"plymouth-custom"* ]] && TOTAL=$(( TOTAL + 1 )) + [[ "$sel" == *"greetd-regreet"* ]] && 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 )) @@ -214,7 +215,8 @@ SELECTED=$(dialog --backtitle "$BACKTITLE" \ "butter" "butter btrfs snapshot backup (AUR)" off \ "plymouth" "Plymouth boot splash — skull logo + boot-log tail" off \ "plymouth-custom" "Plymouth (custom) boot splash — supply your own image" off \ - "lightdm" "LightDM GTK greeter, cyberqueer-themed" off \ + "greetd-regreet" "greetd + ReGreet Wayland greeter, cyberqueer-themed" off \ + "lightdm" "LightDM GTK greeter, cyberqueer (Xorg)" off \ "ly" "ly TUI display manager, cyberqueer" off \ "tlp" "TLP laptop power management" off \ \ @@ -309,6 +311,7 @@ SUMMARY="" [[ "$SELECTED" == *"localtunnel"* ]] && SUMMARY+=" ✦ LocalTunnel\n" [[ "$SELECTED" == *"butter"* ]] && SUMMARY+=" ✦ butter (btrfs backup)\n" [[ "$SELECTED" == *"plymouth"* ]] && SUMMARY+=" ✦ Plymouth boot splash\n" +[[ "$SELECTED" == *"greetd-regreet"* ]] && SUMMARY+=" ✦ greetd + ReGreet greeter\n" [[ "$SELECTED" == *"lightdm"* ]] && SUMMARY+=" ✦ LightDM greeter\n" [[ " ${SELECTED//\"/} " == *" ly "* ]] && SUMMARY+=" ✦ ly greeter\n" if [[ "$SELECTED" == *"plymouth-custom"* ]]; then @@ -396,6 +399,7 @@ if [[ "$SELECTED" == *"plymouth-custom"* ]]; then export PLYMOUTH_LOGO_SRC run_module "Plymouth (custom)" "$APPS/plymouth-custom.sh" fi +[[ "$SELECTED" == *"greetd-regreet"* ]] && run_module "greetd + ReGreet" "$APPS/greetd-regreet.sh" [[ "$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" diff --git a/setup/modules.conf b/setup/modules.conf index 17233b8..adbf1a2 100644 --- a/setup/modules.conf +++ b/setup/modules.conf @@ -51,8 +51,9 @@ 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 + boot-log tail|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 +greetd-regreet|system|greetd + ReGreet greeter, Wayland-native, cyberqueer-themed|off|lightdm,ly +lightdm|system|LightDM GTK greeter, cyberqueer-themed (Xorg)|off|greetd-regreet,ly +ly|system|ly TUI display manager, cyberqueer-themed|off|greetd-regreet,lightdm # ── Gaming ──────────────────────────────────────────────────────────────────── steam|gaming|Steam gaming platform|off| diff --git a/setup/modules/optional-Modules/apps/greetd-regreet.sh b/setup/modules/optional-Modules/apps/greetd-regreet.sh index df60e24..95f704d 100644 --- a/setup/modules/optional-Modules/apps/greetd-regreet.sh +++ b/setup/modules/optional-Modules/apps/greetd-regreet.sh @@ -8,9 +8,10 @@ # wlroots (inside a cage kiosk), so it drives every output natively and hands # input straight to the Wayland session — none of those failure modes. # -# It reuses the cyberqueer GTK theme (gtk-4.0 assets) and the greeter-background -# sync (the wallpaper picker's choice, mirrored to a greeter-readable path by the -# lightdm-greeter-wallpaper.path unit — shared, greeter-agnostic despite the name). +# The CyberQueer login look is a self-contained stylesheet (etc-greetd/regreet.css, +# loaded by ReGreet over an Adwaita-dark base). The greeter background tracks the +# wallpaper picker's choice, mirrored to a greeter-readable path by the +# lightdm-greeter-wallpaper.path unit (shared, greeter-agnostic despite the name). # # Mutually exclusive with the lightdm and ly greeter modules: enabling greetd # here disables the others and the tty1 getty so exactly one greeter runs. @@ -26,7 +27,10 @@ ETC_LIGHTDM="$DOTFILES_DIR/etc-lightdm" # shared wallpaper-sync helper + units log "Installing greetd + ReGreet + cage..." sudo pacman -S --noconfirm --needed greetd greetd-regreet cage -# ── cyberqueer GTK theme (ReGreet is GTK4 → needs the gtk-4.0 assets) ────────── +# ── cyberqueer GTK theme (optional) ─────────────────────────────────────────── +# The greeter's look is driven by regreet.css over an Adwaita base, so this is no +# longer required — but we still ship it so flipping regreet.toml's theme_name +# back to "cyberqueer" works, and so the theme exists on a greeter-only install. GTK_THEME_SRC="$DOTFILES_DIR/gtk-themes/cyberqueer" if [[ -d "$GTK_THEME_SRC" ]]; then log "Installing cyberqueer GTK theme to /usr/share/themes..." @@ -50,6 +54,7 @@ fi log "Deploying greetd config, ReGreet config, and session launcher..." sudo install -Dm644 "$ETC_GREETD/config.toml" /etc/greetd/config.toml sudo install -Dm644 "$ETC_GREETD/regreet.toml" /etc/greetd/regreet.toml +sudo install -Dm644 "$ETC_GREETD/regreet.css" /etc/greetd/regreet.css sudo install -Dm755 "$ETC_GREETD/regreet-session.sh" /etc/greetd/regreet-session.sh # ── PAM: password (system-login) + required FIDO/U2F touch ──────────────────── diff --git a/setup/tools/generate-answerfile.sh b/setup/tools/generate-answerfile.sh index e806cff..f4611e0 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 82 \ + --checklist "Optional applications — installed after base components:" 40 76 83 \ "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,7 +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 + boot-log tail" on \ "plymouth-custom" "plymouth-custom boot splash with a user-supplied image" off \ - "lightdm" "lightdm LightDM GTK greeter, cyberqueer-themed (HyprLua default)" off \ + "greetd-regreet" "greetd-regreet greetd + ReGreet greeter, Wayland-native, cyberqueer-themed" off \ + "lightdm" "lightdm LightDM GTK greeter, cyberqueer-themed (Xorg)" off \ "ly" "ly ly TUI display manager, cyberqueer-themed" off \ "steam" "steam Steam gaming platform" off \ "vesktop" "vesktop Discord client with Vencord theme" off \ diff --git a/setup/tools/migrate-to-greetd.sh b/setup/tools/migrate-to-greetd.sh new file mode 100755 index 0000000..6fc66b9 --- /dev/null +++ b/setup/tools/migrate-to-greetd.sh @@ -0,0 +1,220 @@ +#!/bin/bash +# ============================================================================= +# migrate-to-greetd.sh — switch an existing install to Plymouth + greetd/ReGreet +# ============================================================================= +# Migrates a machine that currently boots lightdm / ly / GDM / SDDM / LXDM (or a +# bare greetd+tuigreet) to this repo's current default boot experience: +# +# Plymouth skull splash → greetd + ReGreet + cage (Wayland-native, +# cyberqueer-themed graphical greeter) +# +# This is the Wayland counterpart to migrate-to-lightdm.sh. ReGreet runs on +# wlroots (inside a cage kiosk), so it drives every output natively (no blank +# monitor) and hands input straight to the Wayland session with no Xorg→Wayland +# VT handover race — the reason The-Core moved off the LightDM (Xorg) greeter. +# +# What it does: +# 1. Detects the currently-configured display manager(s). +# 2. Disables every known greeter EXCEPT greetd — for the NEXT boot only. It +# does NOT stop your running session, so you stay logged in until you +# reboot yourself. +# 3. Runs the greetd-regreet module (installs greetd + greetd-regreet + cage, +# deploys the greetd/ReGreet config, the cyberqueer regreet.css skin, the +# skull fallback background + wallpaper-sync units, sets up PAM/FIDO, +# disables lightdm/ly@tty1/getty@tty1, and enables greetd.service). +# 4. Runs the plymouth module (skull splash, initramfs + GRUB cmdline) unless +# --no-plymouth is given. +# +# greetd.service is the TARGET, so it is never disabled here: a machine already +# on a bare greetd+tuigreet is simply reconfigured to run ReGreet instead. +# +# 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-greetd.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-greetd.sh — switch this machine to Plymouth + greetd/ReGreet (cyberqueer) + +Disables the current display manager (lightdm / ly / GDM / SDDM / LXDM / …) for +the next boot, installs and themes the greetd + ReGreet (Wayland) greeter, and +sets up the Plymouth splash. Your running session is left untouched; reboot to +complete the switch. + +Usage: + migrate-to-greetd.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. greetd is the TARGET, +# so it never appears here (a bare greetd+tuigreet install is reconfigured, not +# disabled). ly is a template unit (ly@tty1) but some setups use the plain +# ly.service alias, so both are listed. +OTHER_DMS=( + "lightdm.service" + "ly@tty1.service" "ly.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. +greetd_state="$(systemctl is-enabled greetd.service 2>/dev/null || true)" +[[ -z "$greetd_state" || "$greetd_state" == "not-found" ]] && greetd_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 " greetd.service : $greetd_state" +echo " Plymouth migration : $( ((DO_PLYMOUTH)) && echo 'yes' || echo 'skipped (--no-plymouth)')" +echo + +if (( ${#enabled_dms[@]} == 0 )) && [[ "$greetd_state" == "enabled" ]]; then + log "greetd already appears to be the active greeter — re-running to install/refresh ReGreet + 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 + greetd/ReGreet 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; +# greetd.service (enabled below by the module) 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 greetd/ReGreet (delegated to the module) ────── +# greetd-regreet.sh installs greetd + greetd-regreet + cage, deploys the greetd +# config + ReGreet config + cyberqueer regreet.css skin + skull background, +# wires up PAM/FIDO and the wallpaper-sync units, disables lightdm/ly@tty1/ +# getty@tty1, and enables greetd.service. Running it here keeps a single source +# of truth. +log "Setting up greetd + ReGreet via the greetd-regreet module..." +run bash "$APPS/greetd-regreet.sh" + +# ── 5. Plymouth splash (delegated to the module) ────────────────────────────── +if (( DO_PLYMOUTH )); then + # Upgrade cleanup: the current theme is a centred skull + boot-log tail. The + # previous version scaled the skull full-screen and drew a spinning-dot + # throbber from dot.png. That file is now dead weight — strip it (and any + # other stale theme assets) BEFORE re-running the module, so it is neither + # rendered nor baked into the initramfs that plymouth.sh rebuilds. + THEME_DIR="/usr/share/plymouth/themes/m-archy" + for stale in "$THEME_DIR/dot.png"; do + if [[ -e "$stale" ]]; then + log "Removing obsolete Plymouth asset: $stale" + run sudo rm -f "$stale" + fi + done + + 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 greetd/ReGreet cyberqueer greeter." +fi diff --git a/setup/tools/migrate-to-lightdm.sh b/setup/tools/migrate-to-lightdm.sh index ccdd046..ac69572 100755 --- a/setup/tools/migrate-to-lightdm.sh +++ b/setup/tools/migrate-to-lightdm.sh @@ -7,6 +7,10 @@ # # Plymouth skull splash → LightDM + lightdm-gtk-greeter (cyberqueer theme) # +# NOTE: LightDM (Xorg) is now the *alternative* greeter. The current default is +# the Wayland-native greetd + ReGreet greeter — see migrate-to-greetd.sh. Use +# this script only to switch (back) to the LightDM/Xorg path. +# # What it does: # 1. Detects the currently-configured display manager(s). # 2. Disables every known greeter EXCEPT lightdm — for the NEXT boot only. It diff --git a/setup/tui-install.sh b/setup/tui-install.sh index 9220a73..d8116bf 100755 --- a/setup/tui-install.sh +++ b/setup/tui-install.sh @@ -367,6 +367,7 @@ count_steps() { [[ " $a " == *" wprs "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" plymouth "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" plymouth-custom "* ]] && TOTAL=$(( TOTAL + 1 )) + [[ " $a " == *" greetd-regreet "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" lightdm "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" ly "* ]] && TOTAL=$(( TOTAL + 1 )) [[ " $a " == *" steam "* ]] && TOTAL=$(( TOTAL + 1 )) @@ -591,7 +592,8 @@ else "wprs" "wprs Wayland proxy for remote sessions (wprs-git, AUR)" off \ "plymouth" "plymouth boot splash — bundled skull logo + boot-log tail" on \ "plymouth-custom" "plymouth-custom boot splash with a user-supplied image" off \ - "lightdm" "lightdm LightDM GTK greeter, cyberqueer-themed (HyprLua default)" off \ + "greetd-regreet" "greetd-regreet greetd + ReGreet greeter, Wayland-native, cyberqueer-themed" off \ + "lightdm" "lightdm LightDM GTK greeter, cyberqueer-themed (Xorg)" off \ "ly" "ly ly TUI display manager, cyberqueer-themed" off \ "steam" "steam Steam gaming platform" off \ "vesktop" "vesktop Discord client with Vencord theme" off \ @@ -704,6 +706,7 @@ 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 " == *" greetd-regreet "* ]] && SUMMARY+=" ✦ greetd-regreet\n" [[ " $SELECTED_APPS " == *" lightdm "* ]] && SUMMARY+=" ✦ lightdm\n" [[ " $SELECTED_APPS " == *" ly "* ]] && SUMMARY+=" ✦ ly\n" [[ " $SELECTED_APPS " == *" steam "* ]] && SUMMARY+=" ✦ steam\n" @@ -810,6 +813,27 @@ if [[ " $SELECTED_APPS " == *" plymouth-custom "* && " $SELECTED_APPS " == *" pl SELECTED_APPS="${SELECTED_APPS# }" SELECTED_APPS="${SELECTED_APPS% }" fi +if [[ " $SELECTED_APPS " == *" greetd-regreet "* && " $SELECTED_APPS " == *" lightdm "* ]]; then + warn "'greetd-regreet' 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 +if [[ " $SELECTED_APPS " == *" greetd-regreet "* && " $SELECTED_APPS " == *" ly "* ]]; then + warn "'greetd-regreet' 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 " == *" lightdm "* && " $SELECTED_APPS " == *" greetd-regreet "* ]]; then + warn "'lightdm' and 'greetd-regreet' are mutually exclusive — deselecting 'greetd-regreet'" + SELECTED_APPS=" $SELECTED_APPS " + SELECTED_APPS="${SELECTED_APPS/ greetd-regreet / }" + 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 " @@ -817,6 +841,13 @@ if [[ " $SELECTED_APPS " == *" lightdm "* && " $SELECTED_APPS " == *" ly "* ]]; SELECTED_APPS="${SELECTED_APPS# }" SELECTED_APPS="${SELECTED_APPS% }" fi +if [[ " $SELECTED_APPS " == *" ly "* && " $SELECTED_APPS " == *" greetd-regreet "* ]]; then + warn "'ly' and 'greetd-regreet' are mutually exclusive — deselecting 'greetd-regreet'" + SELECTED_APPS=" $SELECTED_APPS " + SELECTED_APPS="${SELECTED_APPS/ greetd-regreet / }" + 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 " @@ -860,6 +891,7 @@ 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 " == *" greetd-regreet "* ]] && run_module "greetd-regreet" "$APPS/greetd-regreet.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"