From 5b3539c882187c0a2daa64a2c22d2e0a14b060fb Mon Sep 17 00:00:00 2001 From: Hilton Chain Date: Thu, 9 Apr 2026 13:25:44 +0800 Subject: [PATCH] home: services: Add home-graphical-session-service-type. * modules/rosenthal/home/services/desktop.scm (): New data type. (home-graphical-session-find-socket) (home-graphical-session-shepherd-service): New procedures. (home-graphical-session-service-type): New variable. * modules/rosenthal/services/desktop.scm (%home-blueman-applet-shepherd) (%home-fcitx5-shepherd, %home-mako-shepherd) (%home-network-manager-applet-shepherd, %home-noctalia-shell-shepherd) (%home-bb-auth-shepherd, %home-polkit-gnome-shepherd, %home-swaybg-shepherd) (%home-waybar-shepherd): Depend on its shepherd service. (home-mako-service-type, home-noctalia-shell-service-type) (home-swaybg-service-type, home-waybar-service-type): Extend it. (%rosenthal-desktop-home-services): No longer manually start Shepherd. * modules/rosenthal/examples/dot-config/niri/config.kdl: Add screencasting workaround and import environment variables into Shepherd. --- .../examples/dot-config/niri/config.kdl | 11 +- modules/rosenthal/home/services/desktop.scm | 177 ++++++++++++++++++ modules/rosenthal/services/desktop.scm | 46 ++--- 3 files changed, 208 insertions(+), 26 deletions(-) create mode 100644 modules/rosenthal/home/services/desktop.scm diff --git a/modules/rosenthal/examples/dot-config/niri/config.kdl b/modules/rosenthal/examples/dot-config/niri/config.kdl index 60325d4..6539947 100644 --- a/modules/rosenthal/examples/dot-config/niri/config.kdl +++ b/modules/rosenthal/examples/dot-config/niri/config.kdl @@ -3,6 +3,14 @@ // Check the wiki for a full description of the configuration: // https://yalter.github.io/niri/Configuration:-Introduction +environment { + // Workaround for screencasting. + XDG_CURRENT_DESKTOP "niri:GNOME" +} + +// See also `import_environment' in niri source (src/main.rs). +spawn-sh-at-startup "herd set-environment graphical-session XDG_CURRENT_DESKTOP=niri XDG_SESSION_TYPE=$XDG_SESSION_TYPE NIRI_SOCKET=$NIRI_SOCKET" + // Input device configuration. // Find the full list of options on the wiki: // https://yalter.github.io/niri/Configuration:-Input @@ -268,9 +276,6 @@ layout { // Add lines like this to spawn processes at startup. // See the binds section below for more spawn examples. -// Start user Shepherd for Guix Home. -spawn-at-startup "shepherd" - // To run a shell command (with variables, pipes, etc.), use spawn-sh-at-startup: // spawn-sh-at-startup "qs -c ~/source/qs/MyAwesomeShell" diff --git a/modules/rosenthal/home/services/desktop.scm b/modules/rosenthal/home/services/desktop.scm new file mode 100644 index 0000000..dcd3c7d --- /dev/null +++ b/modules/rosenthal/home/services/desktop.scm @@ -0,0 +1,177 @@ +;;; SPDX-License-Identifier: GPL-3.0-or-later +;;; Copyright © 2023 Ludovic Courtès +;;; Copyright © 2026 Hilton Chain + +(define-module (rosenthal home services desktop) + ;; Guile builtins + #:use-module (ice-9 match) + #:use-module (srfi srfi-1) + ;; Utilities + #:use-module (guix gexp) + #:use-module (guix records) + ;; Guix System - services + #:use-module (gnu services) + #:use-module (gnu services configuration) + ;; Guix Home - services + #:use-module (gnu home services shepherd) + #:export (home-graphical-session-service-type + home-graphical-session-configuration)) + +(define-configuration/no-serialization home-graphical-session-configuration + (timeout + (integer 10) + "Time in seconds to wait before a graphical session is found.") + (wayland? + (boolean #f) + "Wait and require Wayland environment to be available, providing a +@code{wayland-display} Shepherd service.") + (x11? + (boolean #f) + "Wait and require X11 environment to be available, providing a +@code{x11-display} Shepherd service.")) + +(define (home-graphical-session-find-socket) + #~(lambda* (timeout directory pattern #:key wayland?) + ;; Wait for an accessible socket matching PATTERN to show up in + ;; DIRECTORY, up to TIMEOUT seconds. + (let loop ((attempts timeout)) + (define socket + (find (match-lambda + ((or "." "..") #f) + (name + (let ((name (in-vicinity directory name))) + (and (string-match pattern name) + (access? name O_RDWR))))) + (or (reverse (scandir directory)) + '()))) + + (if socket + (let ((display + (if wayland? + socket + (string-append ":" (string-drop socket 1))))) + (format #t "Display server found at ~s.~%" display) + display) + (if (zero? attempts) + (error + (format #f "Can't find ~a environment; giving up." + (if wayland? "Wayland" "X11"))) + (begin + (sleep 1) + (loop (- attempts 1)))))))) + +(define home-graphical-session-shepherd-service + (match-record-lambda + (timeout wayland? x11?) + (append + (if (or wayland? x11?) + (list (shepherd-service + (documentation + "Service target to indicate a graphical session is ready.") + (provision '(graphical-session)) + (requirement + (append + (if wayland? + '(wayland-display) + '()) + (if x11? + '(x11-display) + '()))) + (respawn? #f) + (start #~(const #t)) + (stop #~(const #f)) + (actions + (list (shepherd-action + (name 'set-environment) + (documentation + "Set environment variables in Shepherd.") + (procedure + #~(lambda (_ . args) + (for-each putenv args)))))))) + '()) + (if wayland? + (list (shepherd-service + (documentation "Find Wayland socket.") + (provision '(wayland-display)) + (modules + '((ice-9 ftw) + (ice-9 match) + (ice-9 regex) + (srfi srfi-1) + (shepherd support))) + (respawn? #f) + (start + #~(lambda* (#:optional (wayland-display (getenv "WAYLAND_DISPLAY"))) + (let ((wayland-display + (or wayland-display + (#$(home-graphical-session-find-socket) + #$timeout + %user-runtime-dir + "wayland-[0-9]+$" + #:wayland? #t)))) + (when wayland-display + (setenv "WAYLAND_DISPLAY" wayland-display)) + wayland-display))) + (stop + #~(lambda (_) + (unsetenv "WAYLAND_DISPLAY") + #f)))) + '()) + (if x11? + (list (shepherd-service + (documentation "Find X11 display server.") + (provision '(x11-display)) + (requirement + ;; XWayland starts later than the compositor. + (if wayland? + '(wayland-display) + '())) + (modules + '((ice-9 ftw) + (ice-9 match) + (ice-9 regex) + (srfi srfi-1))) + (respawn? #f) + (start + #~(lambda* (#:optional (x11-display (getenv "DISPLAY"))) + (let ((x11-display + (and #$x11? + (or x11-display + (#$(home-graphical-session-find-socket) + #$timeout + "/tmp/.X11-unix" + "X[0-9]+$"))))) + (when x11-display + (setenv "DISPLAY" x11-display)) + x11-display))) + (stop + #~(lambda (_) + (unsetenv "DISPLAY") + #f)))) + '())))) + +(define home-graphical-session-service-type + (service-type + (name 'home-graphical-session) + (extensions + (list (service-extension home-shepherd-service-type + home-graphical-session-shepherd-service))) + (compose identity) + (extend + (lambda (config extensions) + (match-record config + (wayland? x11?) + (home-graphical-session-configuration + (inherit config) + (wayland? + (if (or wayland? + (member 'wayland extensions)) + #t + #f)) + (x11? + (if (or x11? + (member 'x11 extensions)) + #t + #f)))))) + (default-value (home-graphical-session-configuration)) + (description ""))) diff --git a/modules/rosenthal/services/desktop.scm b/modules/rosenthal/services/desktop.scm index c315128..45eaac6 100644 --- a/modules/rosenthal/services/desktop.scm +++ b/modules/rosenthal/services/desktop.scm @@ -34,6 +34,7 @@ #:use-module (gnu home services desktop) #:use-module (gnu home services shepherd) #:use-module (gnu home services sound) + #:use-module (rosenthal home services desktop) #:use-module (rosenthal home services gtk) ;; Guix packages #:use-module (gnu packages fcitx5) @@ -109,6 +110,7 @@ (list (shepherd-service (documentation "Start blueman applet.") (provision '(blueman-applet)) + (requirement '(graphical-session)) (start #~(lambda args ((make-forkexec-constructor @@ -227,7 +229,7 @@ (list (shepherd-service (documentation "Start fcitx5.") (provision '(fcitx5)) - (requirement '(dbus)) + (requirement '(dbus graphical-session)) (start #~(lambda args ((make-forkexec-constructor @@ -283,6 +285,7 @@ (list (shepherd-service (documentation "Start mako.") (provision '(mako)) + (requirement '(graphical-session)) (start #~(lambda args ((make-forkexec-constructor @@ -299,7 +302,9 @@ (list (service-extension home-xdg-configuration-files-service-type %home-mako-xdg-config) (service-extension home-shepherd-service-type - %home-mako-shepherd))) + %home-mako-shepherd) + (service-extension home-graphical-session-service-type + (const 'wayland)))) (default-value (home-mako-configuration)) (description "Run mako, a notification daemon."))) @@ -319,6 +324,7 @@ (list (shepherd-service (documentation "Start network manager applet.") (provision '(network-manager-applet)) + (requirement '(graphical-session)) (start #~(lambda args ((make-forkexec-constructor @@ -394,6 +400,7 @@ compositor."))) (list (shepherd-service (documentation "Start noctalia-shell.") (provision '(noctalia-shell)) + (requirement '(graphical-session)) (modules '((shepherd support))) (start #~(lambda args @@ -414,7 +421,9 @@ compositor."))) (service-extension home-activation-service-type %home-noctalia-shell-activation) (service-extension home-shepherd-service-type - %home-noctalia-shell-shepherd))) + %home-noctalia-shell-shepherd) + (service-extension home-graphical-session-service-type + (const 'wayland)))) (default-value (home-noctalia-shell-configuration)) (description ""))) @@ -426,6 +435,7 @@ compositor."))) (define (%home-bb-auth-shepherd _) (list (shepherd-service (provision '(bb-auth)) + (requirement '(graphical-session)) (start #~(lambda args ((make-forkexec-constructor @@ -452,6 +462,7 @@ compositor."))) (define (%home-polkit-gnome-shepherd _) (list (shepherd-service (provision '(polkit-gnome)) + (requirement '(graphical-session)) (start #~(lambda args ((make-forkexec-constructor @@ -516,6 +527,7 @@ compositor."))) (list (shepherd-service (documentation "Start swaybg.") (provision '(swaybg)) + (requirement '(graphical-session)) (start #~(lambda args ((make-forkexec-constructor @@ -531,7 +543,9 @@ compositor."))) (name 'home-swaybg) (extensions (list (service-extension home-shepherd-service-type - %home-swaybg-shepherd))) + %home-swaybg-shepherd) + (service-extension home-graphical-session-service-type + (const 'wayland)))) (default-value (home-swaybg-configuration)) (description "Run swaybg, a screen wallpaper utility for Wayland compositors."))) @@ -651,6 +665,7 @@ compositor."))) (list (shepherd-service (documentation "Start waybar.") (provision '(waybar)) + (requirement '(graphical-session)) (start #~(lambda args ((make-forkexec-constructor @@ -667,7 +682,9 @@ compositor."))) (list (service-extension home-xdg-configuration-files-service-type %home-waybar-xdg-config) (service-extension home-shepherd-service-type - %home-waybar-shepherd))) + %home-waybar-shepherd) + (service-extension home-graphical-session-service-type + (const 'wayland)))) (default-value (home-waybar-configuration)) (description "Run waybar, a status bar for Wayland compositors."))) @@ -795,23 +812,6 @@ compositor."))) (define-deprecated %rosenthal-desktop-services %rosenthal-desktop-services/tuigreet) (define %rosenthal-desktop-home-services - (cons* (service home-shepherd-service-type - (home-shepherd-configuration - ;; Start by WM to inherit environment variables for graphical session. - (auto-start? #f) - (daemonize? #f))) - - ;; NOTE: The environment variable set by ‘home-dbus-service-type’ will - ;; prevent GNOME from starting when using above Shepherd configuration. - ;; Replace ‘home-dbus-service-type’, expecting the session bus will be - ;; started elsewhere. See also: - ;; https://codeberg.org/guix/guix/issues/5899#issuecomment-10208485 - (simple-service 'dbus home-shepherd-service-type - (list (shepherd-service - (provision '(dbus)) - (start #~(const #t)) - (stop #~(const #f))))) - + (cons* (service home-dbus-service-type) (service home-pipewire-service-type) - %base-home-services))