[PATCH] gnu: home: services: Add 'wayland-display' service.

  • Open
  • quality assurance status badge
Details
3 participants
  • Hilton Chain
  • Ludovic Courtès
  • Sisiutl
Owner
unassigned
Submitted by
Sisiutl
Severity
normal
Merged with

Debbugs page

Sisiutl wrote 2 weeks ago
(address . guix-patches@gnu.org)(name . Sisiutl)(address . sisiutl@egregore.fun)
20250227224636.30227-1-sisiutl@egregore.fun
* gnu/home/services/desktop.scm (wayland-shepherd-service): New procedure.
(home-wayland-service-type): New variable.
* doc/guix.texi (Desktop Home Services): Document it.

Change-Id: If1ed849d29198d2949c6852b0f2645e325211240
---
doc/guix.texi | 36 +++++++++++++++++++
gnu/home/services/desktop.scm | 66 +++++++++++++++++++++++++++++++++++
2 files changed, 102 insertions(+)

Toggle diff (133 lines)
diff --git a/doc/guix.texi b/doc/guix.texi
index bb5f29277f..36b86cffe1 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -47839,6 +47839,42 @@ In the example above, @code{x11-display} is instructed to set
@env{DISPLAY} to @code{:3}.
@end defvar
+@defvar home-wayland-service-type
+This is the service type representing a Wayland compositor. It
+functions as an equivalent of @code{x11-service-type} for Wayland.
+
+Like X11, Wayland compositors are started by services like
+@code{gdm-service-type}, described in the system configuration. At the
+level of Guix Home, as an unprivileged user, we cannot start our Wayland
+compositor; all we can do is check whether it is running. This is what
+this service does.
+
+As a user, you probably don't need to worry or explicitly instantiate
+@code{home-wayland-service-type}. Services that require an Wayland
+graphical display instantiate this service and depend on its
+corresponding @code{wayland-display} Shepherd service (@pxref{Shepherd
+Home Service}).
+
+If you're writing a Shepherd service that requires the presence of a
+Wayland compositor, you need to depend on this service to ensure Wayland
+is accessible from your service.
+
+When the Wayland compositor is running, the @code{wayland-display}
+Shepherd service starts and sets the @env{WAYLAND_DISPLAY} environment
+variable of the @command{shepherd} process, using its original value if
+it was already set; otherwise, it fails to start.
+
+The service can also be forced to use a given value for
+@env{WAYLAND_DISPLAY}, like so:
+
+@example
+herd start wayland-display wayland-2
+@end example
+
+In the example above, @code{wayland-display} is instructed to set
+@env{WAYLAND_DISPLAY} to @code{wayland-2}.
+@end defvar
+
@defvar home-redshift-service-type
This is the service type for @uref{https://github.com/jonls/redshift,
Redshift}, a program that adjusts the display color temperature
diff --git a/gnu/home/services/desktop.scm b/gnu/home/services/desktop.scm
index fc96ce9295..88bc871adb 100644
--- a/gnu/home/services/desktop.scm
+++ b/gnu/home/services/desktop.scm
@@ -33,6 +33,8 @@ (define-module (gnu home services desktop)
#:use-module (ice-9 match)
#:export (home-x11-service-type
+ home-wayland-service-type
+
home-redshift-configuration
home-redshift-configuration?
home-redshift-service-type
@@ -121,6 +123,70 @@ (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 config)
+ (respawn-delay 1)
+ (start
+ #~(lambda* (#:optional (env-wayland-display (getenv "WAYLAND_DISPLAY")))
+
+ (define wayland-socket-regex "wayland-[0-9]+$")
+
+ (define (find-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
+ (find-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 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
Ludovic Courtès wrote 2 weeks ago
(name . Sisiutl)(address . sisiutl@egregore.fun)(address . 76619@debbugs.gnu.org)
87ikotohi8.fsf@gnu.org
Hello,

Sisiutl <sisiutl@egregore.fun> skribis:

Toggle quote (6 lines)
> * gnu/home/services/desktop.scm (wayland-shepherd-service): New procedure.
> (home-wayland-service-type): New variable.
> * doc/guix.texi (Desktop Home Services): Document it.
>
> Change-Id: If1ed849d29198d2949c6852b0f2645e325211240

Nice! So this is a followup to https://issues.guix.gnu.org/76060.


[...]

Toggle quote (12 lines)
> +(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 config)
> + (respawn-delay 1)

The default value for ‘config’ is 10, but that’s not a valid value for
‘respawn-limit’ (it should be a pair).

But anyway, we should remove these two fields: they have no effect,
except for services associated with a process. We can also change
‘default-value’ to #f or so to not give the impression that it has a
special meaning.

Apart from that LGTM; let me know if you can make this change (and if it
sounds right to you) or I can do it on your behalf.

Thanks,
Ludo’.
Hilton Chain wrote 2 weeks ago
Control message
(address . control@debbugs.gnu.org)
878qpo2gl8.wl-hako@ultrarare.space
severity 76057 normal
merge 76057 76619 76659 76667
quit
Hilton Chain wrote 2 weeks ago
Re: [bug#76619] [PATCH] gnu: home: services: Add 'wayland-display' service.
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Sisiutl)(address . sisiutl@egregore.fun)(address . 76619@debbugs.gnu.org)
877c582f2g.wl-hako@ultrarare.space
Hi Sisiutl and Ludo,
I merged all wayland-display issues, please send follow-ups to
ISSUE_NUMBER@debbugs.gnu.org instead of guix-patches@gnu.org next time :)
On Sat, 01 Mar 2025 06:02:07 +0800,
Ludovic Courtès wrote:
Toggle quote (38 lines)
>
> Hello,
>
> Sisiutl <sisiutl@egregore.fun> skribis:
>
> > * gnu/home/services/desktop.scm (wayland-shepherd-service): New procedure.
> > (home-wayland-service-type): New variable.
> > * doc/guix.texi (Desktop Home Services): Document it.
> >
> > Change-Id: If1ed849d29198d2949c6852b0f2645e325211240
>
> Nice! So this is a followup to <https://issues.guix.gnu.org/76060>.
>
>
> [...]
>
> > +(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 config)
> > + (respawn-delay 1)
>
> The default value for ‘config’ is 10, but that’s not a valid value for
> ‘respawn-limit’ (it should be a pair).
>
> But anyway, we should remove these two fields: they have no effect,
> except for services associated with a process. We can also change
> ‘default-value’ to #f or so to not give the impression that it has a
> special meaning.
>
> Apart from that LGTM; let me know if you can make this change (and if it
> sounds right to you) or I can do it on your behalf.
Since some services may depend on either DISPLAY or WAYLAND_DISPLAY, and these
two services (x11-display, wayland-display) are similar, I think we can merge
them into one and deprecate home-x11-service-type by this new service.
e.g.
Toggle snippet (8 lines)
service: home-display-service-type
configuration: x11? (boolean: #f) wayland? (boolean: #f) time-to-wait (integer: 10)
default-value #f
provision: 'x11-display when x11? is #t
'wayland-display when walyand? is #t
'display when either x11? or wayland? is #t
return value: "DISPLAY: unset; WAYLAND_DISPLAY: wayland-1"
Then one service can choose to depend on 'display or specifically 'x11-display /
'wayland-display.
Ludovic Courtès wrote 1 weeks ago
(name . Hilton Chain)(address . hako@ultrarare.space)(name . Sisiutl)(address . sisiutl@egregore.fun)(address . 76619@debbugs.gnu.org)
874j077bjx.fsf@gnu.org
Hi Hilton,

Hilton Chain <hako@ultrarare.space> skribis:

Toggle quote (17 lines)
> Since some services may depend on either DISPLAY or WAYLAND_DISPLAY, and these
> two services (x11-display, wayland-display) are similar, I think we can merge
> them into one and deprecate home-x11-service-type by this new service.
>
> e.g.
>
> service: home-display-service-type
> configuration: x11? (boolean: #f) wayland? (boolean: #f) time-to-wait (integer: 10)
> default-value #f
> provision: 'x11-display when x11? is #t
> 'wayland-display when walyand? is #t
> 'display when either x11? or wayland? is #t
> return value: "DISPLAY: unset; WAYLAND_DISPLAY: wayland-1"
>
> Then one service can choose to depend on 'display or specifically 'x11-display /
> 'wayland-display.

That sounds like a good idea to me. It goes beyond the scope of the
initial patch in this thread though.

Sisiutl, Hilton: who wants to work on it?

Thanks,
Ludo’.
Hilton Chain wrote 6 days ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Sisiutl)(address . sisiutl@egregore.fun)(address . 76619@debbugs.gnu.org)
87r0384zav.wl-hako@ultrarare.space
On Wed, 05 Mar 2025 23:16:18 +0800,
Ludovic Courtès wrote:
Toggle quote (27 lines)
>
> Hi Hilton,
>
> Hilton Chain <hako@ultrarare.space> skribis:
>
> > Since some services may depend on either DISPLAY or WAYLAND_DISPLAY, and these
> > two services (x11-display, wayland-display) are similar, I think we can merge
> > them into one and deprecate home-x11-service-type by this new service.
> >
> > e.g.
> >
> > service: home-display-service-type
> > configuration: x11? (boolean: #f) wayland? (boolean: #f) time-to-wait (integer: 10)
> > default-value #f
> > provision: 'x11-display when x11? is #t
> > 'wayland-display when walyand? is #t
> > 'display when either x11? or wayland? is #t
> > return value: "DISPLAY: unset; WAYLAND_DISPLAY: wayland-1"
> >
> > Then one service can choose to depend on 'display or specifically 'x11-display /
> > 'wayland-display.
>
> That sounds like a good idea to me. It goes beyond the scope of the
> initial patch in this thread though.
>
> Sisiutl, Hilton: who wants to work on it?

Sure, I can do this. I'll begin in a few days.
Hilton Chain wrote 4 days ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Sisiutl)(address . sisiutl@egregore.fun)(address . 76619@debbugs.gnu.org)
874j01rv27.wl-hako@ultrarare.space
On Fri, 07 Mar 2025 23:48:24 +0800,
Hilton Chain wrote:
Toggle quote (31 lines)
>
> On Wed, 05 Mar 2025 23:16:18 +0800,
> Ludovic Courtès wrote:
> >
> > Hi Hilton,
> >
> > Hilton Chain <hako@ultrarare.space> skribis:
> >
> > > Since some services may depend on either DISPLAY or WAYLAND_DISPLAY, and these
> > > two services (x11-display, wayland-display) are similar, I think we can merge
> > > them into one and deprecate home-x11-service-type by this new service.
> > >
> > > e.g.
> > >
> > > service: home-display-service-type
> > > configuration: x11? (boolean: #f) wayland? (boolean: #f) time-to-wait (integer: 10)
> > > default-value #f
> > > provision: 'x11-display when x11? is #t
> > > 'wayland-display when walyand? is #t
> > > 'display when either x11? or wayland? is #t
> > > return value: "DISPLAY: unset; WAYLAND_DISPLAY: wayland-1"
> > >
> > > Then one service can choose to depend on 'display or specifically 'x11-display /
> > > 'wayland-display.
> >
> > That sounds like a good idea to me. It goes beyond the scope of the
> > initial patch in this thread though.
> >
> > Sisiutl, Hilton: who wants to work on it?
>
> Sure, I can do this. I'll begin in a few days.
On a second thought ‘display’ may not be a good name, I'm going to use
‘graphical-session’, sounds familiar? ;)
I have realized that for a Wayland session, setting only ‘WAYLAND_DISPLAY’ in
Shepherd is not sufficient to make all applications work.
Currently to have a fully-functional setup, you'll need to disable auto starting
of ‘home-shepherd-service-type’ and start Shepherd via Wayland compositor to
have all needed environment variables passed to Shepherd. This patch doesn't
make a difference in this regard.
To address this, I have made the service to accpet passing environment variables
directly:
Toggle snippet (7 lines)
herd start graphical-session \
DISPLAY=$DISPLAY \
WAYLAND_DISPLAY=$WAYLAND_DISPLAY \
XDG_SESSION_TYPE=$XDG_SESSION_TYPE \
XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP \
NIRI_SOCKET=$NIRI_SOCKET
These environment variables will be collected in ‘GUIX_GRAPHICAL_SESSION’:
Toggle snippet (2 lines)
GUIX_GRAPHICAL_SESSION => "DISPLAY WALYAND_DISPLAY XDG_SESSION_TYPE ..."
And used by users of ‘graphical-session’:
Toggle snippet (16 lines)
#:environment-variables
(let ((update-environment-variable
(lambda (name base)
(match (getenv name)
(#f base)
(value (cons (string-append name "=" value)
(remove (cut string-prefix?
(string-append name "=")
<>)
base)))))))
(fold update-environment-variable
(default-environment-variables)
(or (and=> (getenv "GUIX_GRAPHICAL_SESSION")
string-tokenize)
'("DISPLAY" "WAYLAND_DISPLAY"))))
However I found that Shepherd starts ‘graphical-session’ even if its
auto-starting is disabled, when there're services depending on it.
Is this intended? I expect to have these services waiting ‘graphical-session’
to start instead of starting it right away.
Ludovic Courtès wrote 3 days ago
(name . Hilton Chain)(address . hako@ultrarare.space)(name . Sisiutl)(address . sisiutl@egregore.fun)(address . 76619@debbugs.gnu.org)
8734fkoabv.fsf@gnu.org
Hi!

Hilton Chain <hako@ultrarare.space> skribis:

Toggle quote (3 lines)
> On a second thought ‘display’ may not be a good name, I'm going to use
> ‘graphical-session’, sounds familiar? ;)

Good idea. :-)

Toggle quote (3 lines)
> I have realized that for a Wayland session, setting only ‘WAYLAND_DISPLAY’ in
> Shepherd is not sufficient to make all applications work.

The goal of ‘x11-display’ now is only to (1) ensure X11 is running, and
(2) determine the correct value of ‘DISPLAY’ so other services can use
it.

I would say that other environment variables like the Freedesktop ones
(XDG_*) are beyond the scope of such a service. WDYT?

Toggle quote (10 lines)
> herd start graphical-session \
> DISPLAY=$DISPLAY \
> WAYLAND_DISPLAY=$WAYLAND_DISPLAY \
> XDG_SESSION_TYPE=$XDG_SESSION_TYPE \
> XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP \
> NIRI_SOCKET=$NIRI_SOCKET
>
>
> These environment variables will be collected in ‘GUIX_GRAPHICAL_SESSION’:

That seems a bit too complex to me.

Toggle quote (3 lines)
> However I found that Shepherd starts ‘graphical-session’ even if its
> auto-starting is disabled, when there're services depending on it.

That’s not really intended, but it’s a Guix issue, not a Shepherd issue
(the Shepherd has no notion of “auto starting”; it just starts whatever
you ask it to start in your config file).

Perhaps the ‘auto-start?’ property should automatically propagate along
edges?

Thanks,
Ludo’.
Hilton Chain wrote 2 days ago
(name . Ludovic Courtès)(address . ludo@gnu.org)(name . Sisiutl)(address . sisiutl@egregore.fun)(address . 76619@debbugs.gnu.org)
87senjiqbk.wl-hako@ultrarare.space
On Tue, 11 Mar 2025 05:16:36 +0800,
Ludovic Courtès wrote:
Toggle quote (31 lines)
>
> Hi!
>
> Hilton Chain <hako@ultrarare.space> skribis:
>
> > On a second thought ‘display’ may not be a good name, I'm going to use
> > ‘graphical-session’, sounds familiar? ;)
>
> Good idea. :-)
>
> > I have realized that for a Wayland session, setting only ‘WAYLAND_DISPLAY’ in
> > Shepherd is not sufficient to make all applications work.
>
> The goal of ‘x11-display’ now is only to (1) ensure X11 is running, and
> (2) determine the correct value of ‘DISPLAY’ so other services can use
> it.
>
> I would say that other environment variables like the Freedesktop ones
> (XDG_*) are beyond the scope of such a service. WDYT?
>
> > herd start graphical-session \
> > DISPLAY=$DISPLAY \
> > WAYLAND_DISPLAY=$WAYLAND_DISPLAY \
> > XDG_SESSION_TYPE=$XDG_SESSION_TYPE \
> > XDG_CURRENT_DESKTOP=$XDG_CURRENT_DESKTOP \
> > NIRI_SOCKET=$NIRI_SOCKET
> >
> >
> > These environment variables will be collected in ‘GUIX_GRAPHICAL_SESSION’:
>
> That seems a bit too complex to me.
I finally realized...! ‘x11-display’ has a fundamental issue: It actually
relies on pre-existing graphical session!
1. Shepherd loads service definitons
- 'service' dependending on ‘x11-display’ calls ‘(getenv "DISPLAY")’ in its
definiton -> it depends on existing DISPLAY.
- Shepherd actually fails at this stage if there's no pre-existing DISPLAY.
2. Shepherd starts ‘x11-display’
- ‘x11-display’ finds socket and sets DISPLAY.
3. Shepherd starts 'service'
- 'service' is already loaded in (1.), DISPLAY set in (2.) won't affect it.
Bad news, but simplifies the whole thing a lot :)
We can just remove socket finding part from ‘x11-display’ and use ‘getenv’
instead. Then For a ‘graphical-session’ provision, Shepherd should be started
by... a graphical session. Previously for ‘x11-display’ I think Shepherd was
supposed to be started by a display manager, but I'm not sure if WAYLAND_DISPLAY
changes when using a display manager.
home-shepherd-service-type doesn't set default environment variables so
Shepherd's starting environment is inherited. Then no need to worry about
importing environment variables if we want to keep this behavior.
So a graphical session setup is what I have mentioned before: Disable
auto-starting of Shepherd, and start it in your desktop environment.
I'm using this snippet btw:
Toggle snippet (2 lines)
pgrep --uid $USER shepherd > /dev/null || shepherd
Toggle quote (9 lines)
> > However I found that Shepherd starts ‘graphical-session’ even if its
> > auto-starting is disabled, when there're services depending on it.
>
> That’s not really intended, but it’s a Guix issue, not a Shepherd issue
> (the Shepherd has no notion of “auto starting”; it just starts whatever
> you ask it to start in your config file).
>
> Perhaps the ‘auto-start?’ property should automatically propagate along
> edges?
Either services marked not to auto-start starting or those marked as auto-start
not starting? :P I'm not sure which side to choose.
For the specific case this is unnecessary now, as there's no need to wait to
import environment variables.
?
Your comment

Commenting via the web interface is currently disabled.

To comment on this conversation send an email to 76619@debbugs.gnu.org

To respond to this issue using the mumi CLI, first switch to it
mumi current 76619
Then, you may apply the latest patchset in this issue (with sign off)
mumi am -- -s
Or, compose a reply to this issue
mumi compose
Or, send patches to this issue
mumi send-email *.patch
You may also tag this issue. See list of standard tags. For example, to set the confirmed and easy tags
mumi command -t +confirmed -t +easy
Or, remove the moreinfo tag and set the help tag
mumi command -t -moreinfo -t +help