[bug#77266,v4,1/2] gnu: Merge xorg configurations when extending.
Commit Message
Configuration for xorg is embedded in the various display-manager
configuration records, and extension support is factored out into the
`handle-xorg-configuration' macro. However, the extension mechanism replaces
the existing xorg-configuration with the supplied one, making it impossible to
compose configuration from multiple sources. This patch adds a procedure to
merge two xorg-configuration records, and calls it within
handle-xorg-configuration, allowing the config to be built piecemeal.
* gnu/services/xorg.scm (merge-xorg-configurations): New variable.
(handle-xorg-configuration): Merge xorg configs.
* doc/guix.texi (X Window): Document xorg-configuration composition.
Change-Id: I20e9db911eef5d4efe98fdf382f3084e4defc1ba
---
doc/guix.texi | 48 +++++++++++++++++++++++++++++++++++++++++--
gnu/services/xorg.scm | 42 ++++++++++++++++++++++++++++++-------
2 files changed, 81 insertions(+), 9 deletions(-)
Comments
Hi Ian,
Ian Eure <ian@retrospec.tv> writes:
> Configuration for xorg is embedded in the various display-manager
> configuration records, and extension support is factored out into the
> `handle-xorg-configuration' macro. However, the extension mechanism replaces
> the existing xorg-configuration with the supplied one, making it impossible to
> compose configuration from multiple sources. This patch adds a procedure to
> merge two xorg-configuration records, and calls it within
> handle-xorg-configuration, allowing the config to be built piecemeal.
>
> * gnu/services/xorg.scm (merge-xorg-configurations): New variable.
> (handle-xorg-configuration): Merge xorg configs.
> * doc/guix.texi (X Window): Document xorg-configuration composition.
>
> Change-Id: I20e9db911eef5d4efe98fdf382f3084e4defc1ba
[...]
> +(define (merge-xorg-configurations a b)
> + (let ((configs (list b a))) ; Prefer later configurations.
> + (xorg-configuration
> + (modules
> + (delete-duplicates (append-map xorg-configuration-modules configs)))
> + (fonts
> + (delete-duplicates (append-map xorg-configuration-fonts configs)))
> + (drivers
> + (delete-duplicates (append-map xorg-configuration-drivers configs)))
> + (resolutions
> + (delete-duplicates (append-map xorg-configuration-resolutions configs)))
As I mentioned before, since ‘equal?’ cannot be meaningfully applied
here on file-like objects in general, all these ‘delete-duplicates’
calls should be removed.
> (define (xorg-configuration->file config)
> "Compute an Xorg configuration file corresponding to CONFIG, an
> <xorg-configuration> record."
> @@ -334,9 +362,12 @@ (define (expand modules)
> port)
> (newline port)))
>
> - (for-each (lambda (config)
> - (display config port))
> - '#$(xorg-configuration-extra-config config))))))
> + (for-each
> + (lambda (config)
> + (display config port)
> + (newline port))
> + (delete-duplicates
> + '#$(xorg-configuration-extra-config config)))))))
As I wrote before, in ‘xorg-configuration->file’, ‘delete-duplicates’
should be used for drivers, modules, and fonts, but not for
‘extra-config’ (which is merely a string).
Could you update it accordingly?
Thanks,
Ludo’.
Ludovic Courtès <ludo@gnu.org> writes:
> Hi Ian,
>
> Ian Eure <ian@retrospec.tv> writes:
>
>> +(define (merge-xorg-configurations a b)
>> + (let ((configs (list b a))) ; Prefer later
>> configurations.
>> + (xorg-configuration
>> + (modules
>> + (delete-duplicates (append-map
>> xorg-configuration-modules configs)))
>> + (fonts
>> + (delete-duplicates (append-map xorg-configuration-fonts
>> configs)))
>> + (drivers
>> + (delete-duplicates (append-map
>> xorg-configuration-drivers configs)))
>> + (resolutions
>> + (delete-duplicates (append-map
>> xorg-configuration-resolutions configs)))
>
> As I mentioned before, since ‘equal?’ cannot be meaningfully
> applied
> here on file-like objects in general, all these
> ‘delete-duplicates’
> calls should be removed.
Hmm, I thought your previous comment was about the `extra-config'
field specifically, and I did update that one. I agree that’s a
problem, but I’m not sure about the other ones, ex. `drivers' is
documented as containing a "list of strings." I can see an
argument for consistent behavior of deduplication here, and having
it all in one place.
>> (define (xorg-configuration->file config)
>> "Compute an Xorg configuration file corresponding to CONFIG,
>> an
>> <xorg-configuration> record."
>> @@ -334,9 +362,12 @@ (define (expand modules)
>> port)
>> (newline port)))
>>
>> - (for-each (lambda (config)
>> - (display config port))
>> - '#$(xorg-configuration-extra-config
>> config))))))
>> + (for-each
>> + (lambda (config)
>> + (display config port)
>> + (newline port))
>> + (delete-duplicates
>> + '#$(xorg-configuration-extra-config
>> config)))))))
>
> As I wrote before, in ‘xorg-configuration->file’,
> ‘delete-duplicates’
> should be used for drivers, modules, and fonts, but not for
> ‘extra-config’ (which is merely a string).
>
> Could you update it accordingly?
Can’t `extra-config' be a file-like?
-- Ian
Hello,
Ian Eure <ian@retrospec.tv> writes:
> Ludovic Courtès <ludo@gnu.org> writes:
>
>> Hi Ian,
>>
>> Ian Eure <ian@retrospec.tv> writes:
>>
>>> +(define (merge-xorg-configurations a b)
>>> + (let ((configs (list b a))) ; Prefer later
>>> configurations.
>>> + (xorg-configuration
>>> + (modules
>>> + (delete-duplicates (append-map xorg-configuration-modules
>>> configs)))
>>> + (fonts
>>> + (delete-duplicates (append-map xorg-configuration-fonts
>>> configs)))
>>> + (drivers
>>> + (delete-duplicates (append-map xorg-configuration-drivers
>>> configs)))
>>> + (resolutions
>>> + (delete-duplicates (append-map
>>> xorg-configuration-resolutions configs)))
>>
>> As I mentioned before, since ‘equal?’ cannot be meaningfully applied
>> here on file-like objects in general, all these ‘delete-duplicates’
>> calls should be removed.
>
> Hmm, I thought your previous comment was about the `extra-config'
> field specifically, and I did update that one.
My point is that ‘delete-duplicates’ cannot be applied on file-like
objects, as is the case for ‘modules’, ‘fonts’, and ‘drivers’ in the
excerpt above. That’s why I said in this case ‘delete-duplicates’
should be moved to the “build side”.
> Can’t `extra-config' be a file-like?
The doc says:
‘extra-config’ (default: ‘'()’)
This is a list of strings or objects appended to the
configuration file. It is used to pass extra text to be added
verbatim to the configuration file.
Ludo’.
@@ -138,6 +138,7 @@ Copyright @copyright{} 2024 45mg@*
Copyright @copyright{} 2025 Sören Tempel@*
Copyright @copyright{} 2025 Rostislav Svoboda@*
Copyright @copyright{} 2025 Zacchaeus@*
+Copyright @copyright{} 2025 Ian Eure@*
Permission is granted to copy, distribute and/or modify this document
under the terms of the GNU Free Documentation License, Version 1.3 or
@@ -24916,8 +24917,51 @@ Tell the log-in manager (of type @var{login-manager-service-type}) to use
@var{config}, an @code{<xorg-configuration>} record.
Since the Xorg configuration is embedded in the log-in manager's
-configuration---e.g., @code{gdm-configuration}---this procedure provides a
-shorthand to set the Xorg configuration.
+configuration---e.g., @code{gdm-configuration}---this procedure provides
+a shorthand to set the Xorg configuration.
+
+In addition to @code{set-xorg-configuration}, you may extend your log-in
+manager’s service-type to provide reusable, partial configurations,
+which are concatenated to create the final Xorg configuration:
+
+@lisp
+;; A service which configures Intel video drivers.
+(define %xorg-intel-service
+ (simple-service
+ 'xorg-intel
+ gdm-service-type
+ (xorg-configuration
+ (modules (list xf86-video-intel))
+ (drivers '("intel"))
+ (extra-config "
+ Section \"Device\"
+ Identifier \"Intel GPU\"
+ Driver \"intel\"
+ Option \"TearFree\" \"true\"
+ EndSection"))))
+
+;; A service which configures the keyboard.
+(define %xorg-keyboard-service
+ (simple-service
+ 'xorg-keyboard
+ gdm-service-type
+ (xorg-configuration
+ (keyboard-layout
+ (keyboard-layout "us" #:options '("ctrl:nocaps"))))))
+
+(operating-system
+ (services
+ (append
+ (list (service gdm-service-type)
+ %xorg-intel-service
+ %xorg-keyboard-service)
+ %base-services))
+ @dots{})
+@end lisp
+
+Service extension and @code{set-xorg-configuration} can each be used
+seperately, or in conjunction.
+
@end deffn
@deffn {Procedure} xorg-start-command [config]
@@ -209,6 +209,34 @@ (define-record-type* <xorg-configuration>
(server-arguments xorg-configuration-server-arguments ;list of strings
(default %default-xorg-server-arguments)))
+(define (merge-xorg-configurations a b)
+ (let ((configs (list b a))) ; Prefer later configurations.
+ (xorg-configuration
+ (modules
+ (delete-duplicates (append-map xorg-configuration-modules configs)))
+ (fonts
+ (delete-duplicates (append-map xorg-configuration-fonts configs)))
+ (drivers
+ (delete-duplicates (append-map xorg-configuration-drivers configs)))
+ (resolutions
+ (delete-duplicates (append-map xorg-configuration-resolutions configs)))
+ (extra-config (append-map xorg-configuration-extra-config configs))
+ ;; Prefer the more recently set layout.
+ (keyboard-layout (or (xorg-configuration-keyboard-layout b)
+ (xorg-configuration-keyboard-layout a)
+ #f))
+ (server
+ ;; Prefer the non-default server.
+ (if (eq? xorg-server (xorg-configuration-server a))
+ (xorg-configuration-server b)
+ (xorg-configuration-server a)))
+ (server-arguments
+ ;; Prefer the non-default arguments.
+ (if (eq? %default-xorg-server-arguments
+ (xorg-configuration-server-arguments a))
+ (xorg-configuration-server-arguments b)
+ (xorg-configuration-server-arguments a))))))
+
(define (xorg-configuration->file config)
"Compute an Xorg configuration file corresponding to CONFIG, an
<xorg-configuration> record."
@@ -334,9 +362,12 @@ (define (expand modules)
port)
(newline port)))
- (for-each (lambda (config)
- (display config port))
- '#$(xorg-configuration-extra-config config))))))
+ (for-each
+ (lambda (config)
+ (display config port)
+ (newline port))
+ (delete-duplicates
+ '#$(xorg-configuration-extra-config config)))))))
(computed-file "xserver.conf" build)))
@@ -628,10 +659,7 @@ (define-syntax handle-xorg-configuration
((_ configuration-record service-type-definition)
(service-type
(inherit service-type-definition)
- (compose (lambda (extensions)
- (match extensions
- (() #f)
- ((config . _) config))))
+ (compose (cut reduce merge-xorg-configurations #f <>))
(extend (lambda (config xorg-configuration)
(if xorg-configuration
(configuration-record