Subject: [bug#76057] [PATCH] gnu: home: services: Add 'wayland-display' service.

From: Sisiutl <[email-masked]>
Date: Tue, 4 Feb 2025 22:06:32 +0100

* gnu/home/services/desktop.scm (wayland-shepherd-service): New procedure.
(home-wayland-service-type): New variable.

Change-Id: Ide1ca748551a280efe8286b4ac1e46787b108443
---
 gnu/home/services/desktop.scm | 68 +++++++++++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 2 deletions(-)

diff --git a/gnu/home/services/desktop.scm b/gnu/home/services/desktop.scm
index fc96ce9295..34321409f7 100644
--- a/gnu/home/services/desktop.scm
+++ b/gnu/home/services/desktop.scm
@@ -48,7 +48,7 @@ (define-module (gnu home services desktop)
 
             home-startx-command-service-type))
 
-
+
 ;;;
 ;;; Waiting for X11.
 ;;;
@@ -121,7 +121,71 @@ (define home-x11-service-type
 during that time, the @code{x11-display} service is marked as failing to
 start.")))
 
-
+
+;;;
+;;; Waiting for Wayland.
+;;;
+
+(define (wayland-shepherd-service config)
+  (list (shepherd-service
+         (provision '(wayland-display))
+         (modules '((ice-9 ftw)
+                    (ice-9 regex)
+                    (ice-9 match)
+                    (srfi srfi-1)
+                    (shepherd support)))
+         (respawn? #t)
+         (respawn-limit (home-wayland-configuration-tries config))
+         (respawn-delay 1)
+         (start
+          #~(lambda* (#:optional (env-wayland-display (getenv "WAYLAND_DISPLAY")))
+
+              (define wayland-socket-regex "wayland-[0-9]+$")
+
+              (define (socket? directory regex)
+                (find (match-lambda
+                        ((or "." "..") #f)
+                        (name
+                         (let ((name (in-vicinity directory
+                                                  name)))
+                           (and (string-match regex name)
+                                (access? name O_RDWR)))))
+                      ;; Wayland names its sockets `wayland-n`. With
+                      ;; `reverse`, we pick up on the last Wayland instance
+                      ;; created (essentially what we always want to do).
+                      (or (reverse (scandir directory)) '())))
+
+              (define wayland-display
+                (or env-wayland-display
+                    (socket? %user-runtime-dir "wayland-[0-9]+$")))
+
+              (when wayland-display
+                (format #t "Wayland display found at ~s.~%" wayland-display)
+                ;; Note: 'make-forkexec-constructor' calls take their
+                ;; default #:environment-variables value before this service
+                ;; is started and are thus unaffected by the 'setenv' call
+                ;; below.  Users of this service have to explicitly query
+                ;; its value.
+                (setenv "WAYLAND_DISPLAY" wayland-display))
+              wayland-display))
+         (stop #~(lambda (_)
+                   (unsetenv "WAYLAND_DISPLAY")
+                   #f)))))
+
+(define-public home-wayland-service-type
+  (service-type
+   (name 'home-wayland-display)
+   (extensions (list (service-extension home-shepherd-service-type
+                                        wayland-shepherd-service)))
+   (default-value 10)
+   (description
+    "Create a @code{wayland-display} Shepherd service that waits for a Wayland
+compositor to be up and running, up to a configurable delay, and sets the
+@code{WAYLAND_DISPLAY} environment variable of @command{shepherd} itself
+accordingly.  If no accessible Wayland server shows up during that time, the
+@code{wayland-display} service is marked as failing to start.")))
+
+
 ;;;
 ;;; Redshift.
 ;;;
-- 
2.48.1