feat(hyprland): add hyprland configuration with keyboard layout injection and vm compatibility

Add Hyprland desktop environment support with:

- New hyprland.conf template with keyboard layout placeholders (__KB_LAYOUT__ and __KB_VARIANT__) that get injected during installation
- Hyprland wrapper script (/usr/local/bin/fws-hyprland) that detects virtual machines and forces software rendering to prevent compositor crashes on virtual GPUs (VMware vmwgfx, VirtualBox)
- Automatic configuration deployment to /etc/skel and existing user home directories
- Refactored keyboard layout detection logic (moved to section 3bis) to support both X11/SDDM and Hyprland configurations
- Added locale generation during installation to ensure proper language support

Keyboard layout is now derived from either kickstart configuration or system locale using langtable, providing consistent keyboard behavior across all desktop environments.
This commit is contained in:
2026-06-24 23:06:20 +02:00
parent ff98a1e186
commit 99006b9ede
2 changed files with 142 additions and 26 deletions
@@ -0,0 +1,61 @@
# FWS — configuration Hyprland par défaut.
# Le clavier (__KB_LAYOUT__ / __KB_VARIANT__) est injecté à l'installation,
# depuis le choix fait dans Anaconda. Édite ce fichier librement.
monitor = , preferred, auto, 1
input {
kb_layout = __KB_LAYOUT__
kb_variant = __KB_VARIANT__
follow_mouse = 1
numlock_by_default = true
}
general {
gaps_in = 4
gaps_out = 8
border_size = 2
layout = dwindle
}
decoration {
rounding = 6
}
# Barre d'état au démarrage.
exec-once = waybar
$mod = SUPER
# Applications
bind = $mod, Return, exec, kitty
bind = $mod, E, exec, firefox
bind = $mod, R, exec, wofi --show drun
bind = $mod, Q, killactive,
bind = $mod SHIFT, Q, exit,
bind = $mod, V, togglefloating,
bind = $mod, F, fullscreen,
# Focus
bind = $mod, left, movefocus, l
bind = $mod, right, movefocus, r
bind = $mod, up, movefocus, u
bind = $mod, down, movefocus, d
# Espaces de travail 1-6
bind = $mod, 1, workspace, 1
bind = $mod, 2, workspace, 2
bind = $mod, 3, workspace, 3
bind = $mod, 4, workspace, 4
bind = $mod, 5, workspace, 5
bind = $mod, 6, workspace, 6
bind = $mod SHIFT, 1, movetoworkspace, 1
bind = $mod SHIFT, 2, movetoworkspace, 2
bind = $mod SHIFT, 3, movetoworkspace, 3
bind = $mod SHIFT, 4, movetoworkspace, 4
bind = $mod SHIFT, 5, movetoworkspace, 5
bind = $mod SHIFT, 6, movetoworkspace, 6
# Souris : déplacer / redimensionner les fenêtres
bindm = $mod, mouse:272, movewindow
bindm = $mod, mouse:273, resizewindow
@@ -205,6 +205,44 @@ else
echo "[FWS] AVERTISSEMENT : grub-install a échoué — bootloader à refaire à la main" echo "[FWS] AVERTISSEMENT : grub-install a échoué — bootloader à refaire à la main"
fi fi
# --- 3bis) Clavier (X11) + LOCALE --------------------------------------------
# CLAVIER : Anaconda passe par localed et n'écrit pas fiablement la disposition X
# sur la CIBLE → SDDM / sessions X en QWERTY US. On CALCULE la disposition CHOISIE
# (kickstart généré, sinon dérivée de la locale via langtable) en XL/XV, réutilisés
# plus bas (00-keyboard.conf pour SDDM/X ET la config Hyprland qui a son propre
# kb_layout). LOCALE : le locale choisi (ex. fr_CH.UTF-8) doit être GÉNÉRÉ —
# Anaconda vient de Fedora (locales pré-générées) et ne lance pas locale-gen →
# sans ça LANG casse et tout retombe en C.
XL=""; XV=""
XKB="$(sed -n "s/.*--xlayouts=//p" /root/anaconda-ks.cfg 2>/dev/null | head -1)"
XKB="${XKB#[\'\"]}"; XKB="${XKB%%[\'\"]*}"; XKB="${XKB%%,*}" # 1re dispo, ex. « ch (fr) »
if [ -z "$XKB" ]; then
_loc="$(. /etc/locale.conf 2>/dev/null; printf '%s' "${LANG%%.*}")" # fr_CH
_lng="${_loc%%_*}"; _terr="${_loc#*_}"; [ "$_terr" = "$_loc" ] && _terr=""
[ -n "$_terr" ] && XKB="$(python3 -c "import langtable; k=langtable.list_keyboards(languageId='$_lng', territoryId='$_terr'); print(k[0] if k else '')" 2>/dev/null)"
fi
if [ -n "$XKB" ]; then
XL="${XKB%%(*}"; XL="${XL%% *}" # ch
case "$XKB" in *'('*')') XV="${XKB#*(}"; XV="${XV%)}" ;; *) XV="" ;; esac # fr
install -d /etc/X11/xorg.conf.d
cat > /etc/X11/xorg.conf.d/00-keyboard.conf <<KBEOF
Section "InputClass"
Identifier "system-keyboard"
MatchIsKeyboard "on"
Option "XkbLayout" "$XL"
Option "XkbVariant" "$XV"
EndSection
KBEOF
fi
FWSLANG="$(. /etc/locale.conf 2>/dev/null; printf '%s' "${LANG:-}")"
if [ -n "$FWSLANG" ]; then
_cs="${FWSLANG##*.}"; [ "$_cs" = "$FWSLANG" ] && _cs="UTF-8"
grep -qE "^[[:space:]]*${FWSLANG}[[:space:]]+${_cs}\b" /etc/locale.gen 2>/dev/null \
|| printf '%s %s\n' "$FWSLANG" "$_cs" >> /etc/locale.gen
locale-gen || echo "[FWS] locale-gen a échoué pour $FWSLANG"
fi
# --- 4) Bureau choisi : pacman -S du DE (non bloquant si pas de réseau) ------- # --- 4) Bureau choisi : pacman -S du DE (non bloquant si pas de réseau) -------
DESK="cli" DESK="cli"
[ -f /tmp/fws-desktop ] && DESK="$(tr -d '[:space:]' < /tmp/fws-desktop)" [ -f /tmp/fws-desktop ] && DESK="$(tr -d '[:space:]' < /tmp/fws-desktop)"
@@ -229,37 +267,54 @@ if [ -n "$PKGS" ]; then
install -d /etc/sddm.conf.d install -d /etc/sddm.conf.d
printf '[General]\nNumlock=on\n' > /etc/sddm.conf.d/10-fws.conf printf '[General]\nNumlock=on\n' > /etc/sddm.conf.d/10-fws.conf
fi fi
# Hyprland en VM : sur GPU virtuel (VMware/VirtualBox) le compositeur
# crashe au lancement → SDDM « remet au login ». On le lance via un
# wrapper qui force le rendu LOGICIEL UNIQUEMENT en VM (systemd-detect-virt)
# ; sur un vrai GPU le rendu matériel est conservé.
if [ "$DESK" = "hyprland" ]; then
cat > /usr/local/bin/fws-hyprland <<'HYEOF'
#!/bin/sh
if systemd-detect-virt --quiet 2>/dev/null; then
# GPU virtuel (VMware vmwgfx…) : on FORCE le chemin d'affichage 100% logiciel.
# La PIÈCE MAÎTRESSE est MESA_LOADER_DRIVER_OVERRIDE=kms_swrast : elle force
# Mesa à allouer le GBM/EGL via kms_swrast (rendu logiciel dans les « dumb
# buffers » KMS) AU LIEU du pilote vmwgfx (qui ne fournit pas le GBM dont
# aquamarine a besoin → « CBackend::create() failed »). + llvmpipe pour le GL.
export MESA_LOADER_DRIVER_OVERRIDE=kms_swrast
export GALLIUM_DRIVER=llvmpipe LIBGL_ALWAYS_SOFTWARE=1
export WLR_RENDERER_ALLOW_SOFTWARE=1 WLR_NO_HARDWARE_CURSORS=1
export AQ_NO_ATOMIC=1
fi
exec Hyprland "$@"
HYEOF
chmod 755 /usr/local/bin/fws-hyprland
if [ -f /usr/share/wayland-sessions/hyprland.desktop ]; then
sed -i 's|^Exec=.*|Exec=/usr/local/bin/fws-hyprland|' \
/usr/share/wayland-sessions/hyprland.desktop
fi
fi
else else
echo "[FWS] Bureau '$DESK' non installé (réseau ?) — à refaire après le 1er boot." echo "[FWS] Bureau '$DESK' non installé (réseau ?) — à refaire après le 1er boot."
fi fi
fi fi
# --- Clavier X11 (SDDM + sessions graphiques) -------------------------------- # --- Config Hyprland (si choisi) : clavier + apps + waybar -------------------
# SDDM et les sessions X/Wayland (kwin lit aussi ce fichier) prennent leur # Hyprland (Wayland) NE lit PAS /etc/X11/xorg.conf.d/00-keyboard.conf : sa
# disposition de /etc/X11/xorg.conf.d/00-keyboard.conf. Anaconda passe par localed # disposition est dans SA config (input { kb_layout }). Sans config il démarre nu
# qui ne l'écrit pas fiablement sur la CIBLE → écran SDDM en QWERTY US → le mot de # (QWERTY US, aucune touche utile). On déploie une config FWS (template +
# passe (tapé sur le clavier choisi, ex. suisse QWERTZ) ne correspond pas. On # clavier XL/XV injecté) dans /etc/skel ET le home de chaque utilisateur déjà
# l'écrit donc nous-mêmes, depuis la disposition X CHOISIE (kickstart généré), # créé par Anaconda (le %post tourne APRÈS la création de l'utilisateur).
# sinon dérivée de la locale via langtable. Cohérent avec le clavier du GUI. if [ "$DESK" = "hyprland" ] && [ -f /usr/local/share/fws/hyprland.conf.tmpl ]; then
XKB="$(sed -n "s/.*--xlayouts=//p" /root/anaconda-ks.cfg 2>/dev/null | head -1)" sed -e "s/__KB_LAYOUT__/${XL:-us}/" -e "s/__KB_VARIANT__/${XV}/" \
XKB="${XKB#[\'\"]}"; XKB="${XKB%%[\'\"]*}"; XKB="${XKB%%,*}" # 1re dispo, ex. « ch (fr) » /usr/local/share/fws/hyprland.conf.tmpl > /tmp/fws-hyprland.conf
if [ -z "$XKB" ]; then install -Dm644 /tmp/fws-hyprland.conf /etc/skel/.config/hypr/hyprland.conf
_loc="$(. /etc/locale.conf 2>/dev/null; printf '%s' "${LANG%%.*}")" # fr_CH while IFS=: read -r _u _x _uid _g _gec _home _sh; do
_lng="${_loc%%_*}"; _terr="${_loc#*_}"; [ "$_terr" = "$_loc" ] && _terr="" [ "$_uid" -ge 1000 ] && [ "$_uid" -le 60000 ] && [ -d "$_home" ] || continue
[ -n "$_terr" ] && XKB="$(python3 -c "import langtable; k=langtable.list_keyboards(languageId='$_lng', territoryId='$_terr'); print(k[0] if k else '')" 2>/dev/null)" install -Dm644 /tmp/fws-hyprland.conf "$_home/.config/hypr/hyprland.conf"
fi chown "$_u": "$_home/.config" 2>/dev/null || true
if [ -n "$XKB" ]; then chown -R "$_u": "$_home/.config/hypr" 2>/dev/null || true
XL="${XKB%%(*}"; XL="${XL%% *}" # ch done < /etc/passwd
case "$XKB" in *'('*')') XV="${XKB#*(}"; XV="${XV%)}" ;; *) XV="" ;; esac # fr rm -f /tmp/fws-hyprland.conf
install -d /etc/X11/xorg.conf.d
cat > /etc/X11/xorg.conf.d/00-keyboard.conf <<KBEOF
Section "InputClass"
Identifier "system-keyboard"
MatchIsKeyboard "on"
Option "XkbLayout" "$XL"
Option "XkbVariant" "$XV"
EndSection
KBEOF
fi fi
# --- 4bis) Sudo : l'utilisateur créé doit pouvoir administrer ----------------- # --- 4bis) Sudo : l'utilisateur créé doit pouvoir administrer -----------------