#!/bin/bash
# sddm-keyboard-regen — runs at every boot, BEFORE sddm.service, to rebuild
# the SDDM keyboard configuration from current sources of truth:
#
#   1. /home/*/.config/kxkbrc         (per-user Plasma keyboard config — FIRST,
#                                      so user's preferred layout becomes the
#                                      greeter default)
#   2. /root/.config/kxkbrc           (root's Plasma keyboard config, if any)
#   3. /etc/default/keyboard          (Debian system default — appended LAST as
#                                      a guaranteed fallback)
#
# Outputs (regenerated every boot):
#   /etc/systemd/system/sddm.service.d/xkb-default.conf
#       Wayland greeter: XKB_DEFAULT_LAYOUT/VARIANT/MODEL env vars + QML XHR enable
#   /etc/sddm.conf.d/keyboard.conf
#       X11 greeter: [X11] DisplayCommand pointing at our Xsetup wrapper
#   /usr/local/bin/sddm-xsetup
#       The wrapper itself: chains the default Xsetup, then runs setxkbmap with
#       the union layout list. SDDM does NOT honour `[X11] XkbLayout=` in
#       sddm.conf — verified by inspecting the X invocation in journalctl
#       (no -xkblayout arg). The X server keyboard MUST be set after the
#       server starts, before the greeter queries it via XKB; DisplayCommand
#       is the only stock SDDM hook in that exact window.
#
# Deployed by the Murexia-Dark SDDM installer; called as the ExecStart of
# sddm-keyboard-regen.service, which is ordered Before=sddm.service.

set -eu

declare -A SEEN
LAYOUTS=()
VARIANTS=()
MODEL=""

add() {
    local l="$1" v="$2"
    [ -z "$l" ] && return
    [ -n "${SEEN[$l]:-}" ] && return
    SEEN[$l]=1
    LAYOUTS+=("$l")
    VARIANTS+=("$v")
}

# 1. Per-user kxkbrc FIRST (so user's preferred layout is the greeter default)
for K in /home/*/.config/kxkbrc /root/.config/kxkbrc; do
    [ -r "$K" ] || continue
    L=$(awk -F= '/^LayoutList[[:space:]]*=/{gsub(/[[:space:]]/,""); print $2}' "$K" | cut -d, -f1)
    V=$(awk -F= '/^VariantList[[:space:]]*=/{gsub(/[[:space:]]/,""); print $2}' "$K" | cut -d, -f1)
    M=$(awk -F= '/^Model[[:space:]]*=/{gsub(/[[:space:]]/,""); print $2}' "$K")
    add "$L" "$V"
    [ -z "$MODEL" ] && [ -n "$M" ] && MODEL="$M"
done

# 2. /etc/default/keyboard LAST (fallback so the greeter is never empty)
if [ -f /etc/default/keyboard ]; then
    L=$(awk -F= '/^XKBLAYOUT/{gsub(/"/, ""); print $2}'  /etc/default/keyboard)
    V=$(awk -F= '/^XKBVARIANT/{gsub(/"/, ""); print $2}' /etc/default/keyboard)
    M=$(awk -F= '/^XKBMODEL/{gsub(/"/, "");   print $2}' /etc/default/keyboard)
    add "$L" "$V"
    [ -z "$MODEL" ] && [ -n "$M" ] && MODEL="$M"
fi

JL=$(IFS=,; echo "${LAYOUTS[*]}")
JV=$(IFS=,; echo "${VARIANTS[*]}")
[ -z "$MODEL" ] && MODEL="pc105"

# Wayland greeter env (libxkbcommon honours these). Kept even though the
# observed X11 deployment ignores them — useful when SDDM is reconfigured to
# DisplayServer=wayland, and harmless otherwise.
mkdir -p /etc/systemd/system/sddm.service.d
cat > /etc/systemd/system/sddm.service.d/xkb-default.conf <<EOF
[Service]
Environment=XKB_DEFAULT_LAYOUT=${JL}
Environment=XKB_DEFAULT_VARIANT=${JV}
Environment=XKB_DEFAULT_MODEL=${MODEL}
Environment=QML_XHR_ALLOW_FILE_READ=1
EOF

# X11 greeter: point SDDM at our Xsetup wrapper. SDDM ignores [X11] XkbLayout
# in sddm.conf — DisplayCommand is the only effective hook.
mkdir -p /etc/sddm.conf.d
cat > /etc/sddm.conf.d/keyboard.conf <<EOF
[X11]
DisplayCommand=/usr/local/bin/sddm-xsetup
EOF

# Generate the wrapper itself. Runs as root, with DISPLAY set by SDDM, after
# the X server is up and before the greeter is launched. Chains the default
# Xsetup if present (so any system customisation still runs), then loads the
# full layout list into the X server via setxkbmap. The greeter populates
# keyboard.layouts from XKB state at greeter startup, so this is the moment
# that actually matters.
cat > /usr/local/bin/sddm-xsetup <<EOF
#!/bin/sh
# Auto-generated by sddm-keyboard-regen — do not edit by hand.
# SDDM [X11] DisplayCommand: runs after X server start, before greeter start.
[ -x /usr/share/sddm/scripts/Xsetup ] && /usr/share/sddm/scripts/Xsetup "\$@"
setxkbmap -layout "${JL}" -variant "${JV}" -model "${MODEL}" 2>/dev/null || true
exit 0
EOF
chmod 0755 /usr/local/bin/sddm-xsetup

# Make systemd pick up the freshly written drop-in before sddm.service starts.
# Safe inside an oneshot ordered Before=sddm.service — daemon-reload is
# processed synchronously before continuing the activation transaction.
systemctl daemon-reload

logger -t sddm-keyboard-regen "regenerated: layout=${JL} variant=${JV} model=${MODEL}"
