From 640aa15af8e7aba853511d288aa53d01972765d1 Mon Sep 17 00:00:00 2001 From: nocode Date: Sat, 4 Jul 2026 12:56:39 +0200 Subject: [PATCH] feat(releng): add fws-hello welcome window script Add a new GTK3-based welcome window script that displays on first boot after installation. The script provides quick access to system setup tasks including system update, multimedia codecs installation, Proton-GE setup, VR configuration, and keyboard shortcuts (on Hyprland/i3). Users can opt to hide the window on subsequent boots via a checkbox and flag file. --- .../releng/airootfs/usr/local/bin/fws-hello | 148 ++++++++++++++++++ 1 file changed, 148 insertions(+) create mode 100755 configs/releng/airootfs/usr/local/bin/fws-hello diff --git a/configs/releng/airootfs/usr/local/bin/fws-hello b/configs/releng/airootfs/usr/local/bin/fws-hello new file mode 100755 index 0000000..c286925 --- /dev/null +++ b/configs/releng/airootfs/usr/local/bin/fws-hello @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 +# FWS — fenêtre de bienvenue au premier démarrage (pendant post-install de la +# page récap de l'installateur). Boutons : mise à jour, codecs, VR, raccourcis, +# Proton-GE. GTK3 : présent sur TOUS les bureaux FWS (Firefox le tire) ; +# python-gobject est installé avec le bureau par le kickstart. +# +# Lancement : /etc/xdg/autostart (KDE/GNOME/XFCE) et exec des configs +# Hyprland/i3, toujours avec --autostart : on se retire sans bruit si +# l'utilisateur a coché « ne plus afficher » (~/.config/fws/hello-done). + +import os +import shutil +import subprocess +import sys + +import gi + +gi.require_version("Gtk", "3.0") +from gi.repository import Gtk # noqa: E402 + +_FLAG = os.path.expanduser("~/.config/fws/hello-done") + +_CODECS = ("gst-plugins-base gst-plugins-good gst-plugins-bad " + "gst-plugins-ugly gst-libav ffmpeg mpv") + +# (libellé, description, commande, en_terminal) +_ACTIONS = [ + ("Mettre à jour le système", + "pacman -Syu + nettoyage du cache", + "fws-update", True), + ("Installer les codecs multimédia", + "lecture vidéo/audio (GStreamer, ffmpeg, mpv)", + f"sudo pacman -S --needed {_CODECS}", True), + ("Proton-GE pour Steam", + "meilleure compatibilité des jeux Windows", + "fws-proton-ge", True), + ("Configurer la VR", + "drivers casque : HTC Vive, Index, Quest…", + "fws-vr-setup", True), +] + +_TERMINALS = ["kitty", "konsole", "gnome-terminal", "xfce4-terminal", "xterm"] + + +def _terminal(): + for term in _TERMINALS: + if shutil.which(term): + return term + return None + + +def _run(command, in_terminal): + if in_terminal: + term = _terminal() + if term is None: + return + if term == "gnome-terminal": + argv = [term, "--", "sh", "-c", command] + else: + argv = [term, "-e", "sh", "-c", command] + else: + argv = ["sh", "-c", command] + subprocess.Popen(argv) # noqa: S603 — commandes internes FWS + + +class HelloWindow(Gtk.Window): + def __init__(self): + super().__init__(title="Bienvenue sur FWS") + self.set_default_size(460, -1) + self.set_position(Gtk.WindowPosition.CENTER) + self.set_border_width(18) + + box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=12) + self.add(box) + + title = Gtk.Label() + title.set_markup("Bienvenue sur FWS !") + box.pack_start(title, False, False, 0) + + subtitle = Gtk.Label( + label="Ton système est prêt. Quelques réglages utiles pour bien démarrer :") + subtitle.set_line_wrap(True) + subtitle.set_xalign(0) + box.pack_start(subtitle, False, False, 0) + + actions = list(_ACTIONS) + # Raccourcis clavier : uniquement sur les sessions qui ont fws-keys + # (Hyprland/i3) — les autres bureaux ont leurs propres réglages. + session = os.environ.get("XDG_CURRENT_DESKTOP", "").lower() + if os.environ.get("HYPRLAND_INSTANCE_SIGNATURE") or "i3" in session: + actions.append(("Voir les raccourcis clavier", + "aussi disponible à tout moment : Super+K", + "fws-keys", False)) + + for label, desc, command, in_term in actions: + button = Gtk.Button() + inner = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=2) + lab = Gtk.Label() + lab.set_markup(f"{label}") + lab.set_xalign(0) + sub = Gtk.Label(label=desc) + sub.set_xalign(0) + sub.get_style_context().add_class("dim-label") + inner.pack_start(lab, False, False, 0) + inner.pack_start(sub, False, False, 0) + button.add(inner) + button.connect("clicked", + lambda _b, c=command, t=in_term: _run(c, t)) + box.pack_start(button, False, False, 0) + + self._again = Gtk.CheckButton(label="Afficher cette fenêtre au prochain démarrage") + self._again.set_active(False) + box.pack_start(self._again, False, False, 6) + + close = Gtk.Button(label="Fermer") + close.connect("clicked", lambda _b: self.close()) + box.pack_start(close, False, False, 0) + + self.connect("destroy", self._on_destroy) + + def _on_destroy(self, _win): + if not self._again.get_active(): + os.makedirs(os.path.dirname(_FLAG), exist_ok=True) + with open(_FLAG, "w") as fh: + fh.write("ok\n") + else: + try: + os.unlink(_FLAG) + except OSError: + pass + Gtk.main_quit() + + +def main(): + if "--autostart" in sys.argv and os.path.exists(_FLAG): + return 0 + # Pas d'affichage joignable (lancement hors session graphique) : on se + # retire sans traceback plutôt que de crasher. + if not Gtk.init_check()[0]: + return 1 + win = HelloWindow() + win.show_all() + Gtk.main() + return 0 + + +if __name__ == "__main__": + sys.exit(main())