fix(greetd): give hyprlua its own plain greeter skin, separate from hyprdrive

There was only one ReGreet skin in the whole repo (etc-greetd/), hand-styled
to match hyprdrive's glowy "Cosmonaut Shell" look (translucent glass, box-
shadow glow, scanlines). sysupdate.sh's _ensure_plymouth_regreet() offers to
deploy it on any machine that migrates to greetd, with no DE-awareness — so
it landed on a hyprlua box too.

Move the existing skin to desktopenvs/hyprdrive/greetd-regreet/ and add a
plain hyprlua variant at desktopenvs/hyprlua/greetd-regreet/ (flat @bg cards,
2px @violet border, @accent on hover/focus/active — no glow, matching
mnotifd/audio-panel/astal-menu's established look). config.toml and
regreet-session.sh have no DE-specific styling, so they stay shared at
etc-greetd/.

sysupdate.sh's _deploy_greetd() and the greetd-regreet.sh setup module now
resolve the active DE (reusing the same config-updater SOURCE_BASE detection
_de_source_dir() already uses elsewhere) and deploy the matching skin,
falling back to hyprdrive's for DEs without their own variant yet.
apply-theme.sh needed no functional change since it recolors whatever's
already deployed rather than reading the source path — just relabeled its
SYS_FILES entry for accuracy.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
main
Amir Alexander Abdelbaki 2026-07-30 20:03:43 +02:00
parent 37da84422a
commit 3b6cdb8dbd
7 changed files with 388 additions and 15 deletions

View File

@ -79,7 +79,12 @@ USER_FILES=(
# System-owned paths — sed is run via sudo # System-owned paths — sed is run via sudo
SYS_FILES=( SYS_FILES=(
"etc-ly-config.ini|/etc/ly/config.ini" "etc-ly-config.ini|/etc/ly/config.ini"
"etc-greetd/regreet.css|/etc/greetd/regreet.css" # /etc/greetd/regreet.css is deployed from whichever DE's own
# desktopenvs/<de>/greetd-regreet/regreet.css is active (see
# sysupdate.sh's _deploy_greetd()) — this just re-colours whatever hex
# values are actually sitting in the deployed file, so the source label
# here is informational only, not read by this script.
"desktopenvs/<de>/greetd-regreet/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-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" "gtk-themes/cyberqueer/gtk-4.0/gtk.css|/usr/share/themes/cyberqueer/gtk-4.0/gtk.css"
) )

View File

@ -1,8 +1,12 @@
/* regreet.css Cosmonaut Shell login theme for ReGreet (greetd, Wayland-native) /* regreet.css Cosmonaut Shell login theme for ReGreet (greetd, Wayland-native)
* *
* Deployed to /etc/greetd/regreet.css by * Deployed to /etc/greetd/regreet.css by
* setup/modules/optional-Modules/apps/greetd-regreet.sh and loaded by ReGreet * setup/modules/optional-Modules/apps/greetd-regreet.sh, which picks THIS file
* via `regreet -s` at STYLE_PROVIDER_PRIORITY_APPLICATION (600) i.e. ON TOP of * (vs. desktopenvs/hyprlua/greetd-regreet/regreet.css's plain skin) based on
* which desktop environment is active on the machine see that script and
* sysupdate.sh's _deploy_greetd() for the resolution logic.
*
* 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 * 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 * outright; the base theme (regreet.toml `theme_name`) only supplies sane widget
* defaults. We deliberately do NOT reuse the desktop `cyberqueer` GTK theme here: * defaults. We deliberately do NOT reuse the desktop `cyberqueer` GTK theme here:

View File

@ -1,7 +1,11 @@
# regreet.toml — cyberqueer-themed ReGreet greeter for greetd (Wayland-native) # regreet.toml — hyprdrive's "Cosmonaut Shell"-themed ReGreet greeter for
# greetd (Wayland-native)
# #
# Deployed to /etc/greetd/regreet.toml by # Deployed to /etc/greetd/regreet.toml by
# setup/modules/optional-Modules/apps/greetd-regreet.sh. # setup/modules/optional-Modules/apps/greetd-regreet.sh, which picks THIS file
# (vs. desktopenvs/hyprlua/greetd-regreet/regreet.toml's plain skin) based on
# which desktop environment is active on the machine — see that script and
# sysupdate.sh's _deploy_greetd() for the resolution logic.
# #
# The cyberqueer look is applied by /etc/greetd/regreet.css (loaded via # The cyberqueer look is applied by /etc/greetd/regreet.css (loaded via
# `regreet -s` at APPLICATION priority, above the base theme). That stylesheet # `regreet -s` at APPLICATION priority, above the base theme). That stylesheet

View File

@ -0,0 +1,259 @@
/* regreet.css hyprlua's plain CyberQueer login theme for ReGreet (greetd,
* Wayland-native): flat @bg-filled cards with a @violet border, no
* hologram/glow treatment. Mirrors the rest of hyprlua's "plain" theme set
* (mnotifd-theme, mnotifhist-theme, audio-panel-theme, astal-menu) solid
* fills instead of translucent glass, no box-shadow glow, no scanline/gradient
* overlays, no hardcoded "Cosmonaut" magenta/cyan just the five shared
* palette colours, @accent on hover/focus/active.
*
* Deployed to /etc/greetd/regreet.css by
* setup/modules/optional-Modules/apps/greetd-regreet.sh, which picks THIS
* file (vs. desktopenvs/hyprdrive/greetd-regreet/regreet.css's "Cosmonaut
* Shell" skin) based on which desktop environment is active on the machine
* see that script and sysupdate.sh's _deploy_greetd() for the resolution
* logic.
*
* 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 skin.
*
* The five PALETTE hexes below (bg/text/accent/violet/danger) are the ones
* apply-theme.sh rewrites in lock-step with colors.conf keep them as bare
* 6-digit hex so its case-insensitive sed 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 (apply-theme) */
@define-color cq_text #D6ABAB; /* warm quasi-white foreground (apply-theme)*/
@define-color cq_accent #E40046; /* hot-pink accent (apply-theme) */
@define-color cq_violet #5018DD; /* electric violet (apply-theme) */
@define-color cq_danger #F50505; /* hi-vis danger red (fixed) */
/* Re-tint the base (Adwaita) theme's semantic named colours. Adwaita paints
* .suggested-action / selections from these, so overriding them here is what
* actually recolours those widgets. Kept in bare hex so apply-theme.sh rewrites
* the palette ones 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. Monospace
* everywhere, matching the shell. */
window,
overlay {
background-color: @cq_bg;
color: @cq_text;
font-family: "Agave Nerd Font Mono", "JetBrains Mono", monospace;
}
/* Cards: the login frame and the clock frame both carry `.background`
* Flat fill, no glass/glow a solid card with a 2px violet border, same
* idiom as astal-menu's .quad-settings / mnotifd's .mnotifd-card. */
frame.background {
background-color: @cq_bg;
color: @cq_text;
border: 2px solid @cq_violet;
border-radius: 16px;
padding: 12px 18px;
}
/* The clock card sits flush on the top edge (ReGreet flattens its top corners
* via inline_css at priority 800, which wins over this). Plain HUD readout,
* no text-shadow glow. */
frame.background > label {
font-family: "Agave Nerd Font Mono", "JetBrains Mono", monospace;
font-size: 30pt;
font-weight: 700;
letter-spacing: 5px;
padding: 4px 28px;
color: @cq_text;
}
/* ── 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: @cq_bg;
color: @cq_text;
caret-color: @cq_accent;
border: 2px solid @cq_violet;
border-radius: 11px;
padding: 8px 12px;
min-height: 34px;
}
entry image,
entry.password image { /* the peek-password / clear icons */
color: @cq_text;
}
entry:focus-within,
entry.password:focus-within {
border-color: @cq_accent;
}
entry selection {
background-color: @cq_accent;
color: @cq_bg;
}
/* ── Combo boxes: user + session pickers render as `combobox > button` ───── */
combobox > button.combo {
background-color: @cq_bg;
color: @cq_text;
border: 2px solid @cq_violet;
border-radius: 11px;
padding: 6px 12px;
min-height: 34px;
}
combobox > button.combo:hover {
border-color: @cq_accent;
color: @cq_accent;
}
combobox arrow {
color: @cq_text;
min-height: 16px;
min-width: 16px;
}
combobox popover contents {
background-color: @cq_bg;
border: 2px solid @cq_violet;
border-radius: 11px;
}
combobox popover contents :selected {
background-color: @cq_accent;
color: @cq_bg;
}
/* ── Buttons ─────────────────────────────────────────────────────────────── */
button {
color: @cq_text;
background-color: @cq_bg;
border: 2px solid @cq_violet;
border-radius: 11px;
padding: 8px 18px;
min-height: 34px;
}
button:hover {
border-color: @cq_accent;
color: @cq_accent;
}
button:active {
background-color: @cq_violet;
color: @cq_bg;
}
/* Manual-entry toggles (pencil icons) — quieter, icon-only */
button.toggle {
background-color: transparent;
border-color: @cq_violet;
padding: 6px;
}
button.toggle:checked {
background-color: @cq_bg;
border-color: @cq_accent;
color: @cq_accent;
}
/* Primary action: Login. The `window` prefix (specificity 0,1,2) and
* `background-image: none` beat Adwaita's own accent styling. Solid accent
* fill the same "pressed pill" idiom as astal-menu's
* .quad-action:active / mnotifd-toggle:checked, no glow. */
window button.suggested-action {
background-image: none;
background-color: @cq_accent;
color: @cq_bg;
border: 2px solid @cq_accent;
font-weight: 700;
}
window button.suggested-action:hover {
background-color: @cq_violet;
border-color: @cq_violet;
color: @cq_bg;
}
window button.suggested-action:active {
background-color: @cq_bg;
color: @cq_accent;
border-color: @cq_accent;
}
/* Destructive actions: Reboot / Power Off — quiet red outline, filled on hover */
window button.destructive-action {
background-image: none;
background-color: transparent;
color: @cq_text;
border: 2px solid @cq_danger;
}
window button.destructive-action:hover {
background-color: @cq_danger;
color: @cq_bg;
}
/* ── PAM notification bar ────────────────────────────────────────────────── */
infobar {
background: transparent;
border: none;
box-shadow: none;
}
infobar > revealer > box {
background-color: @cq_bg;
color: @cq_text;
border: 2px solid @cq_violet;
border-radius: 11px;
}
infobar.error > revealer > box {
border-color: @cq_danger;
}
infobar label {
color: @cq_text;
padding: 6px 12px;
}
/* ── Tooltips (hover hints on the toggle buttons) ────────────────────────── */
tooltip {
background-color: @cq_bg;
color: @cq_text;
border: 2px solid @cq_violet;
border-radius: 9px;
padding: 4px 8px;
}

View File

@ -0,0 +1,52 @@
# regreet.toml — hyprlua's plain CyberQueer ReGreet greeter for greetd
# (Wayland-native)
#
# Deployed to /etc/greetd/regreet.toml by
# setup/modules/optional-Modules/apps/greetd-regreet.sh, which picks THIS file
# (vs. desktopenvs/hyprdrive/greetd-regreet/regreet.toml's "Cosmonaut Shell"
# skin) based on which desktop environment is active on the machine — see
# that script and sysupdate.sh's _deploy_greetd() for the resolution logic.
#
# The 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
[background]
# Tracks the user's current desktop wallpaper: the picker writes
# ~/.config/hypr/usr/wallpaper.conf and the lightdm-greeter-wallpaper.path unit
# copies the chosen image here (a path the unprivileged greeter can read).
path = "/usr/share/backgrounds/lightdm-greeter-bg.png"
fit = "Cover"
[GTK]
application_prefer_dark_theme = true
cursor_theme_name = "Adwaita"
cursor_blink = true
# Bumped well above the 11pt the old greeter used, so the greeter reads large on
# the 4K panel. Tune here (or via GDK_SCALE in regreet-session.sh) to taste.
font_name = "Agave Nerd Font Mono 15"
icon_theme_name = "Adwaita"
# 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"]
poweroff = ["systemctl", "poweroff"]
[appearance]
greeting_msg = "Sign in"
[widget.clock]
format = "%H:%M"
resolution = "1s"
label_width = 150

View File

@ -8,10 +8,13 @@
# wlroots (inside a cage kiosk), so it drives every output natively and hands # wlroots (inside a cage kiosk), so it drives every output natively and hands
# input straight to the Wayland session — none of those failure modes. # input straight to the Wayland session — none of those failure modes.
# #
# The CyberQueer login look is a self-contained stylesheet (etc-greetd/regreet.css, # The CyberQueer login look is a self-contained stylesheet (regreet.css, loaded
# loaded by ReGreet over an Adwaita-dark base). The greeter background tracks the # by ReGreet over an Adwaita-dark base) — picked per-DE from
# wallpaper picker's choice, mirrored to a greeter-readable path by the # desktopenvs/<de>/greetd-regreet/ (see resolve_de_dir below), so hyprdrive's
# lightdm-greeter-wallpaper.path unit (shared, greeter-agnostic despite the name). # glowy "Cosmonaut Shell" skin doesn't get applied on a hyprlua machine (or
# vice versa). 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 # Mutually exclusive with the lightdm and ly greeter modules: enabling greetd
# here disables the others and the tty1 getty so exactly one greeter runs. # here disables the others and the tty1 getty so exactly one greeter runs.
@ -21,9 +24,42 @@ source "$(dirname "${BASH_SOURCE[0]}")/../../lib/logging.sh"
# apps/ → optional-Modules → modules → setup → repo root (four levels up). # apps/ → optional-Modules → modules → setup → repo root (four levels up).
DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)" DOTFILES_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../../.." && pwd)"
ETC_GREETD="$DOTFILES_DIR/etc-greetd" ETC_GREETD="$DOTFILES_DIR/etc-greetd" # shared infra: config.toml, session script
ETC_LIGHTDM="$DOTFILES_DIR/etc-lightdm" # shared wallpaper-sync helper + units ETC_LIGHTDM="$DOTFILES_DIR/etc-lightdm" # shared wallpaper-sync helper + units
# The greeter's VISUAL skin (regreet.toml + regreet.css) is per-DE — hyprdrive's
# "Cosmonaut Shell" (translucent glass, glow, scanlines) and hyprlua's plain
# flat skin are different files under desktopenvs/<de>/greetd-regreet/. Resolve
# which DE this machine is actually running the same way sysupdate.sh's
# _de_source_dir() does: the installed config-updater's SOURCE_BASE is the
# authoritative marker (set by each DE's installer), with a running-session
# fallback for a machine that hasn't installed config-updater yet.
resolve_de_dir() {
local conf="${XDG_CONFIG_HOME:-$HOME/.config}/config-updater/updater.conf"
if [[ -f "$conf" ]]; then
local src
src=$(awk -F'[[:space:]]*=[[:space:]]*' '/^SOURCE_BASE/{print $2; exit}' "$conf")
src="${src/#\~/$HOME}"
[[ -d "${src:-}" ]] && { printf '%s' "$src"; return; }
fi
if [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]] && pgrep -x niri &>/dev/null; then
printf '%s' "$DOTFILES_DIR/desktopenvs/niri"
elif pgrep -x Hyprland &>/dev/null || [[ -n "${HYPRLAND_INSTANCE_SIGNATURE:-}" ]]; then
printf '%s' "$DOTFILES_DIR/desktopenvs/hyprlua"
fi
}
DE_DIR="$(resolve_de_dir)"
if [[ -n "$DE_DIR" && -d "$DE_DIR/greetd-regreet" ]]; then
GREETER_SKIN="$DE_DIR/greetd-regreet"
log "Using ${GREETER_SKIN#$DOTFILES_DIR/} for the greeter skin (detected DE: $(basename "$DE_DIR"))."
else
# No DE-specific skin (niri/sway/legacy hyprland) — fall back to
# hyprdrive's, the original/default look this module has always shipped.
GREETER_SKIN="$DOTFILES_DIR/desktopenvs/hyprdrive/greetd-regreet"
warn "No greeter skin for detected DE (${DE_DIR:-unknown}) — falling back to hyprdrive's."
fi
log "Installing greetd + ReGreet + cage..." log "Installing greetd + ReGreet + cage..."
sudo pacman -S --noconfirm --needed greetd greetd-regreet cage sudo pacman -S --noconfirm --needed greetd greetd-regreet cage
@ -53,8 +89,8 @@ fi
# ── Deploy greetd + ReGreet configuration ───────────────────────────────────── # ── Deploy greetd + ReGreet configuration ─────────────────────────────────────
log "Deploying greetd config, ReGreet config, and session launcher..." 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/config.toml" /etc/greetd/config.toml
sudo install -Dm644 "$ETC_GREETD/regreet.toml" /etc/greetd/regreet.toml sudo install -Dm644 "$GREETER_SKIN/regreet.toml" /etc/greetd/regreet.toml
sudo install -Dm644 "$ETC_GREETD/regreet.css" /etc/greetd/regreet.css sudo install -Dm644 "$GREETER_SKIN/regreet.css" /etc/greetd/regreet.css
sudo install -Dm755 "$ETC_GREETD/regreet-session.sh" /etc/greetd/regreet-session.sh sudo install -Dm755 "$ETC_GREETD/regreet-session.sh" /etc/greetd/regreet-session.sh
# ── PAM: password (system-login) + required FIDO/U2F touch ──────────────────── # ── PAM: password (system-login) + required FIDO/U2F touch ────────────────────

View File

@ -670,14 +670,27 @@ _redeploy_usr_configs() {
# Only when greetd is the active greeter on this machine. Uses the sudo credential # Only when greetd is the active greeter on this machine. Uses the sudo credential
# primed once at startup, so it doesn't re-prompt. PAM is intentionally left to the # primed once at startup, so it doesn't re-prompt. PAM is intentionally left to the
# setup module — a bad PAM file could lock out login. # setup module — a bad PAM file could lock out login.
#
# regreet.toml/regreet.css (the VISUAL skin) are per-DE — hyprdrive's glowy
# "Cosmonaut Shell" and hyprlua's plain flat skin are different files under
# desktopenvs/<de>/greetd-regreet/. Resolve via _de_source_dir() (same helper
# _ensure_astal_menu_deps() etc. use) so this machine's actual DE keeps its own
# skin instead of always being overwritten with whichever one used to be the
# only option. config.toml/regreet-session.sh have no DE-specific styling, so
# they stay shared at etc-greetd/.
_deploy_greetd() { _deploy_greetd() {
local src="$DOTFILES/etc-greetd" local src="$DOTFILES/etc-greetd"
[[ -d "$src" ]] || return 0 [[ -d "$src" ]] || return 0
systemctl is-enabled greetd.service &>/dev/null || return 0 systemctl is-enabled greetd.service &>/dev/null || return 0
log "Deploying greetd / ReGreet config to ${BO}/etc/greetd${RS}..."
local de_dir; de_dir=$(_de_source_dir)
local skin="$DOTFILES/desktopenvs/hyprdrive/greetd-regreet" # default/fallback
[[ -n "${de_dir:-}" && -d "$de_dir/greetd-regreet" ]] && skin="$de_dir/greetd-regreet"
log "Deploying greetd / ReGreet config to ${BO}/etc/greetd${RS} (skin: ${skin#"$DOTFILES"/})..."
sudo install -Dm644 "$src/config.toml" /etc/greetd/config.toml && \ sudo install -Dm644 "$src/config.toml" /etc/greetd/config.toml && \
sudo install -Dm644 "$src/regreet.toml" /etc/greetd/regreet.toml && \ sudo install -Dm644 "$skin/regreet.toml" /etc/greetd/regreet.toml && \
sudo install -Dm644 "$src/regreet.css" /etc/greetd/regreet.css && \ sudo install -Dm644 "$skin/regreet.css" /etc/greetd/regreet.css && \
sudo install -Dm755 "$src/regreet-session.sh" /etc/greetd/regreet-session.sh && \ sudo install -Dm755 "$src/regreet-session.sh" /etc/greetd/regreet-session.sh && \
ok "greetd config deployed" || warn "greetd config deploy had errors" ok "greetd config deployed" || warn "greetd config deploy had errors"
} }