Subject: Re: Keyboard layout configuration

From: nee <[email-masked]>
Date: Sun, 13 Jan 2019 23:49:56 +0100

Am 13.01.19 um 22:36 schrieb Ludovic Courtès:
>> 1) grub
>> 2) linux's initrd
>> 3) console
>> 4) X/wayland's layout
>> 5) How to do the above

Hello, I was working on this recently and made a patch for X11 that
fixes the layout in the slim login and when you login into gnome3 or
whatever desktop environment.

I also made a patch for grub that fixes the layout when you edit the
boot command for a menu entry, but not for the luks prompt. I think that
might require installing a custom grub image (grub-mkimage) with
grub-bios-setup instead of using grub-install (I saw some posts on the
archlinux forum I don't have a link to right now). But this patch should
lay the groundwork for it, as it can generate grub keyboard config files.

The patches are pretty dirty, but I might not have that much time in the
next few weeks to work on this, and since is hot on the mailing list
right now, I'm sending them here now.

Happy hacking!
>From 5612630ea4324339322ba726846d1962aaa86dc8 Mon Sep 17 00:00:00 2001
From: nee <[email-masked]>
Date: Sat, 5 Jan 2019 22:07:30 +0100
Subject: [PATCH] bootloader: grub custom keyboard-layout, but luks password
 prompts are still unaffected

---
 gnu/bootloader/grub.scm      | 128 +++++++++++++++++++++++------------
 gnu/packages/bootloaders.scm |  11 +++
 gnu/packages/xorg.scm        | 121 +++++++++++++++++++++++++++++++++
 3 files changed, 215 insertions(+), 45 deletions(-)

diff --git a/gnu/bootloader/grub.scm b/gnu/bootloader/grub.scm
index 161e8b3d0..ca9f2f565 100644
--- a/gnu/bootloader/grub.scm
+++ b/gnu/bootloader/grub.scm
@@ -29,6 +29,7 @@
   #:use-module (gnu system file-systems)
   #:autoload   (gnu packages bootloaders) (grub)
   #:autoload   (gnu packages gtk) (guile-cairo guile-rsvg)
+  #:autoload   (gnu packages xorg) (xkeyboard-config)
   #:use-module (ice-9 match)
   #:use-module (ice-9 regex)
   #:use-module (srfi srfi-1)
@@ -46,6 +47,8 @@
             %background-image
             %default-theme
 
+            grub-keyboard-layout-file
+
             grub-bootloader
             grub-efi-bootloader
             grub-mkrescue-bootloader
@@ -219,11 +222,35 @@ fi~%"
 ;;; Configuration file.
 ;;;
 
+(define* (grub-keyboard-layout-file
+          #:key
+          (layout #f) ; something like "fr" "de" "ru"
+          (grub grub)
+          (xkeyboard-config xkeyboard-config))
+  "Returns a Gexp that generates a xkb keyboard LAYOUT file that GRUB can load.
+The LAYOUT must be present in XKEYBOARD-CONFIGs share/X11xkb/symbols/ directory.
+When LAYOUT is #f no file will be generated and 'no-keymap-used is
+returned in a gexp."
+  (define builder
+    #~(zero?
+       (system* (string-append #$grub "/bin/grub-kbdcomp")
+                (string-append #$xkeyboard-config
+                               "/share/X11/xkb/symbols/" #$layout)
+                (string-append "-I" #$xkeyboard-config
+                               "/share/X11/xkb")
+                "-rules" "base"
+                "-o" #$output)))
+
+  (if layout
+      (computed-file "keyboard-layout.xkb" builder)
+      (gexp 'no-keymap-used)))
+
+
 (define (grub-setup-io config)
   "Return GRUB commands to configure the input / output interfaces.  The result
 is a string that can be inserted in grub.cfg."
   (let* ((symbols->string (lambda (list)
-                           (string-join (map symbol->string list) " ")))
+                            (string-join (map symbol->string list) " ")))
          (outputs (bootloader-configuration-terminal-outputs config))
          (inputs (bootloader-configuration-terminal-inputs config))
          (unit (bootloader-configuration-serial-unit config))
@@ -233,41 +260,41 @@ is a string that can be inserted in grub.cfg."
          ;; as documented in GRUB manual section "Simple Configuration
          ;; Handling".
          (valid-outputs '(console serial serial_0 serial_1 serial_2 serial_3
-                          gfxterm vga_text mda_text morse spkmodem))
+                                  gfxterm vga_text mda_text morse spkmodem))
          (valid-inputs '(console serial serial_0 serial_1 serial_2 serial_3
-                         at_keyboard usb_keyboard))
+                                 at_keyboard usb_keyboard))
 
          (io (string-append
-               "terminal_output "
-               (symbols->string
-                 (map
-                   (lambda (output)
-                     (if (memq output valid-outputs) output #f)) outputs)) "\n"
-               (if (null? inputs)
-                 ""
-                 (string-append
-                   "terminal_input "
-                   (symbols->string
-                     (map
-                       (lambda (input)
-                         (if (memq input valid-inputs) input #f)) inputs)) "\n"))
-               ;; UNIT and SPEED are arguments to the same GRUB command
-               ;; ("serial"), so we process them together.
-               (if (or unit speed)
-                 (string-append
-                   "serial"
-                   (if unit
-                     ;; COM ports 1 through 4
-                     (if (and (exact-integer? unit) (<= unit 3) (>= unit 0))
-                       (string-append " --unit=" (number->string unit))
-                       #f)
-                     "")
-                   (if speed
-                     (if (exact-integer? speed)
-                       (string-append " --speed=" (number->string speed))
-                       #f)
-                     ""))
-                 ""))))
+              "terminal_output "
+              (symbols->string
+               (map
+                (lambda (output)
+                  (if (memq output valid-outputs) output #f)) outputs)) "\n"
+                  (if (null? inputs)
+                      ""
+                      (string-append
+                       "terminal_input "
+                       (symbols->string
+                        (map
+                         (lambda (input)
+                           (if (memq input valid-inputs) input #f)) inputs)) "\n"))
+                  ;; UNIT and SPEED are arguments to the same GRUB command
+                  ;; ("serial"), so we process them together.
+                  (if (or unit speed)
+                      (string-append
+                       "serial"
+                       (if unit
+                           ;; COM ports 1 through 4
+                           (if (and (exact-integer? unit) (<= unit 3) (>= unit 0))
+                               (string-append " --unit=" (number->string unit))
+                               #f)
+                           "")
+                       (if speed
+                           (if (exact-integer? speed)
+                               (string-append " --speed=" (number->string speed))
+                               #f)
+                           ""))
+                      ""))))
     (format #f "~a" io)))
 
 (define (grub-root-search device file)
@@ -293,6 +320,8 @@ code."
 
 (define* (grub-configuration-file config entries
                                   #:key
+                                  (keyboard-layout-file
+                                   (grub-keyboard-layout-file))
                                   (system (%current-system))
                                   (old-entries '()))
   "Return the GRUB configuration file corresponding to CONFIG, a
@@ -329,6 +358,14 @@ entries corresponding to old generations of the system."
                (menu-entry-device-mount-point (first all-entries))
                #:system system
                #:port #~port))
+  (define keyboard-layout-config
+    #~(let ((keymap #$keyboard-layout-file))
+        (if (eq? 'no-keymap-used keymap)
+            (format port "")
+            (format port "terminal_input at_keyboard
+insmod keylayouts
+keymap ~a
+" keymap))))
 
   (define builder
     #~(call-with-output-file #$output
@@ -338,6 +375,7 @@ entries corresponding to old generations of the system."
 # will be lost upon reconfiguration.
 ")
           #$sugar
+          #$keyboard-layout-config
           (format port "
 set default=~a
 set timeout=~a~%"
@@ -426,17 +464,17 @@ submenu \"GNU system, old configurations...\" {~%")
 
 (define-syntax grub-configuration
   (syntax-rules (grub)
-                ((_ (grub package) fields ...)
-                 (if (eq? package grub)
-                     (bootloader-configuration
-                      (bootloader grub-bootloader)
-                      fields ...)
-                   (bootloader-configuration
-                    (bootloader grub-efi-bootloader)
-                    fields ...)))
-                ((_ fields ...)
-                 (bootloader-configuration
-                  (bootloader grub-bootloader)
-                  fields ...))))
+    ((_ (grub package) fields ...)
+     (if (eq? package grub)
+         (bootloader-configuration
+          (bootloader grub-bootloader)
+          fields ...)
+         (bootloader-configuration
+          (bootloader grub-efi-bootloader)
+          fields ...)))
+    ((_ fields ...)
+     (bootloader-configuration
+      (bootloader grub-bootloader)
+      fields ...))))
 
 ;;; grub.scm ends here
diff --git a/gnu/packages/bootloaders.scm b/gnu/packages/bootloaders.scm
index 2a595fafa..3cc331dcb 100644
--- a/gnu/packages/bootloaders.scm
+++ b/gnu/packages/bootloaders.scm
@@ -55,6 +55,7 @@
   #:use-module (gnu packages swig)
   #:use-module (gnu packages valgrind)
   #:use-module (gnu packages virtualization)
+  #:use-module (gnu packages xorg)
   #:use-module (gnu packages web)
   #:use-module (guix build-system gnu)
   #:use-module (guix download)
@@ -110,6 +111,12 @@
                      ;; Make the font visible.
                      (copy-file (assoc-ref inputs "unifont") "unifont.bdf.gz")
                      (system* "gunzip" "unifont.bdf.gz")
+
+                     ;; patch the path to ckbcomp
+                     (substitute* "util/grub-kbdcomp.in"
+                       (("^ckbcomp ")
+                        (string-append (assoc-ref inputs "console-setup")
+                                       "/bin/ckbcomp ")))
                      #t))
                   (add-before 'check 'disable-flaky-test
                     (lambda _
@@ -134,6 +141,10 @@
        ;; to determine whether the root file system is RAID.
        ("mdadm" ,mdadm)
 
+       ;; console-setup's ckbcomp is invoked by grub-kbdcomp
+       ;; it is required for generating alternative keyboard layouts
+       ("console-setup" ,console-setup)
+
        ("freetype" ,freetype)
        ;; ("libusb" ,libusb)
        ;; ("fuse" ,fuse)
diff --git a/gnu/packages/xorg.scm b/gnu/packages/xorg.scm
index 9aa65291b..0a95a21cf 100644
--- a/gnu/packages/xorg.scm
+++ b/gnu/packages/xorg.scm
@@ -46,6 +46,7 @@
   #:use-module (gnu packages)
   #:use-module (gnu packages anthy)
   #:use-module (gnu packages autotools)
+  #:use-module (gnu packages base)
   #:use-module (gnu packages bison)
   #:use-module (gnu packages check)
   #:use-module (gnu packages compression)
@@ -6258,3 +6259,123 @@ selecting windows by pointing select actual focused X11 window, selecting by
 window name or id, forcing toggle, increase or decrease opacity.")
     (home-page "http://forchheimer.se/transset-df/")
     (license license:x11)))
+
+(define-public bdfresize
+  (package
+    (name "bdfresize")
+    (version "1.5-11")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "https://salsa.debian.org/debian/bdfresize/-/archive/debian/"
+                           version "/bdfresize-debian-"version ".tar.bz2"))
+       (sha256
+        (base32
+         "1fcn0hhzk8g3h0x50n982jwgsivhkqfd50bqs3iv2db3j4bnxp51"))))
+    (build-system gnu-build-system)
+    (arguments
+     '(;; #:make-flags
+       ;; (let ((bash (assoc-ref %build-inputs "bash"))
+       ;;       (out (assoc-ref %outputs "out")))
+       ;;   (list (string-append "SHELL=" bash "/bin/bash")
+       ;;         ;; (string-append "prefix=" out)
+       ;;         ))
+       #:phases
+       (modify-phases %standard-phases
+         (replace 'configure
+           (lambda* (#:key build configure-flags outputs inputs
+                     #:allow-other-keys #:rest args)
+             (let ((out (assoc-ref outputs "out")))
+               ;; The default configure tries to pass
+               ;; SHELL=/gnu/store/…-bash-minimal-4.4.23/bin/bash
+               ;; This breaks the configure script with:
+               ;; "error: can only configure for one host and one target at a time"
+               (setenv "CONFIG_SHELL"
+                       (string-append (assoc-ref %build-inputs "bash")
+                                      "/bin/bash"))
+               (zero? (system* "./configure"
+
+                               "--build" build
+                               "--prefix" out)))))
+         (add-after 'configure 'fix-for-new-gcc
+           ;; TODO might upstream, once upstream is back
+           (lambda _
+             (substitute* "charresize.c"
+               (("char\t\\*malloc\\(\\);")
+                ""))
+             #t)))))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)))
+    (inputs `(("perl" ,perl)))
+    (synopsis "")
+    (description "")
+    ;; latest upstream vanished, using debian fork for now
+    ;; used to be: http://openlab.jp/efont/
+    (home-page "https://tracker.debian.org/pkg/bdfresize")
+    (license license:x11)) )
+
+(define-public console-setup
+  (package
+    (name "console-setup")
+    (version "1.188")
+    (source
+     (origin
+       (method url-fetch)
+       (uri (string-append "https://salsa.debian.org/installer-team/console-setup/-/archive/"
+                           version "/console-setup-" version ".tar.bz2"))
+       (sha256
+        (base32
+         "1v6zfnsp1fakv1q8b68wdjjxscpw2sbmw2fpqw5af4b3isha5sgr"))))
+    (build-system gnu-build-system)
+    (arguments
+     '(#:make-flags
+       (let ((bash (assoc-ref %build-inputs "bash"))
+             (out (assoc-ref %outputs "out")))
+         (list (string-append "SHELL=" bash "/bin/bash")
+               ;; (string-append "prefix=" out)
+               ))
+       #:phases
+       (modify-phases %standard-phases
+         (delete 'configure)
+         (add-before 'build 'make-doubled-bdfs
+           (lambda* (#:key inputs #:allow-other-keys)
+             (with-directory-excursion "Fonts"
+               (zero? (system* (string-append (assoc-ref inputs "make")
+                                              "/bin/make")
+                               "doubled_bdfs"
+                               (string-append "SHELL="
+                                              (assoc-ref inputs "bash")
+                                              "/bin/bash"))))))
+         (delete 'check)
+         (replace 'install
+           (lambda* (#:key inputs outputs #:allow-other-keys)
+             (let ((out (assoc-ref %outputs "out")))
+               (zero? (system* (string-append (assoc-ref inputs "make")
+                                              "/bin/make")
+                               "install-linux"
+                               (string-append "prefix=" out)
+                               (string-append "SHELL="
+                                              (assoc-ref inputs "bash")
+                                              "/bin/bash")))))))))
+    (native-inputs
+     `(("pkg-config" ,pkg-config)
+       ;; ("bash" ,bash)
+       ("bdftopcf" ,bdftopcf)
+       ("bdfresize" ,bdfresize)
+       ("sharutils" ,sharutils)
+       ("make" ,gnu-make)
+       ))
+    (inputs `(("perl" ,perl)))
+    (synopsis "")
+    (description "console-setup provides the console with the same
+keyboard configuration scheme that X Window System has.
+In result, there is no need to duplicate or change the console keyboard
+files just to make simple customizations such as the use of dead keys,
+the key functioning as AltGr or Compose key, the key(s) to switch between
+Latin and non-Latin layouts, etc.  Besides the keyboard,
+the package configures also the font on the console.
+It includes a rich collection of fonts and supports several languages that
+ would be otherwise unsupported on the console (such as Armenian, Georgian,
+ Lao and Thai).")
+    (home-page "https://salsa.debian.org/installer-team/console-setup/")
+    (license license:x11)))
-- 
2.20.1

>From 54b0b2a8b29a797932bf9a65c7f2e3981a630425 Mon Sep 17 00:00:00 2001
From: nee <[email-masked]>
Date: Sat, 5 Jan 2019 23:43:42 +0100
Subject: [PATCH] services: Init the keyboard-layout in
 xorg-configuration-directory.

* doc/guix.texi (X Window):
    Document keyboard-layout and keyboard-variant for xorg-start-command.
    Remove the example about setting the keyboard-layout through extra-config.

* gnu/services/xorg.scm (xorg-configuration-file):
    Add keyboard-layout and keyboard-variant arguments.

* gnu/system/examples/desktop.tmpl:
    Add keyboard-layout and keyboard-variant for xorg.
* gnu/system/examples/lightweight-desktop.tmpl:
    Add keyboard-layout and keyboard-variant for xorg.
---
 doc/guix.texi                                | 69 +++++---------------
 gnu/services/xorg.scm                        | 25 +++++--
 gnu/system/examples/desktop.tmpl             | 13 +++-
 gnu/system/examples/lightweight-desktop.tmpl | 13 +++-
 4 files changed, 60 insertions(+), 60 deletions(-)

diff --git a/doc/guix.texi b/doc/guix.texi
index f86a2885a..2a915c07d 100644
--- a/doc/guix.texi
+++ b/doc/guix.texi
@@ -48,7 +48,7 @@ Copyright @copyright{} 2017, 2018 Tobias Geerinckx-Rice@*
 Copyright @copyright{} 2017 George Clemmer@*
 Copyright @copyright{} 2017 Andy Wingo@*
 Copyright @copyright{} 2017, 2018 Arun Isaac@*
-Copyright @copyright{} 2017 nee@*
+Copyright @copyright{} 2017, 2019 nee@*
 Copyright @copyright{} 2018 Rutger Helling@*
 Copyright @copyright{} 2018 Oleg Pykhalov@*
 Copyright @copyright{} 2018 Mike Gerwitz@*
@@ -1004,7 +1004,7 @@ similar file.  It can be converted to the OpenSSH format using
 @command{lsh-export-key} (@pxref{Converting keys,,, lsh, LSH Manual}):
 
 @example
-$ lsh-export-key --openssh < /etc/lsh/host-key.pub 
+$ lsh-export-key --openssh < /etc/lsh/host-key.pub
 ssh-rsa AAAAB3NzaC1yc2EAAAAEOp8FoQAAAQEAs1eB46LV@dots{}
 @end example
 
@@ -2807,13 +2807,13 @@ produced by @command{guix pull}, along with details about their provenance:
 
 @example
 $ guix pull -l
-Generation 1	Jun 10 2018 00:18:18
+Generation 1    Jun 10 2018 00:18:18
   guix 65956ad
     repository URL: https://git.savannah.gnu.org/git/guix.git
     branch: origin/master
     commit: 65956ad3526ba09e1f7a40722c96c6ef7c0936fe
 
-Generation 2	Jun 11 2018 11:02:49
+Generation 2    Jun 11 2018 11:02:49
   guix e0cc7f6
     repository URL: https://git.savannah.gnu.org/git/guix.git
     branch: origin/master
@@ -2823,7 +2823,7 @@ Generation 2	Jun 11 2018 11:02:49
     guile2.0-guix@@0.14.0-12.77a1aac, guix@@0.14.0-12.77a1aac,
     heimdal@@7.5.0, milkytracker@@1.02.00, nix@@2.0.4
 
-Generation 3	Jun 13 2018 23:31:07	(current)
+Generation 3    Jun 13 2018 23:31:07    (current)
   guix 844cc1c
     repository URL: https://git.savannah.gnu.org/git/guix.git
     branch: origin/master
@@ -3018,7 +3018,7 @@ modules:
 @example
 $ guix pull --list-generations
 @dots{}
-Generation 19	Aug 27 2018 16:20:48
+Generation 19   Aug 27 2018 16:20:48
   guix d894ab8
     repository URL: https://git.savannah.gnu.org/git/guix.git
     branch: master
@@ -3255,7 +3255,7 @@ and commit IDs (@pxref{Channels}):
 
 @example
 $ guix describe
-Generation 10	Sep 03 2018 17:32:44	(current)
+Generation 10   Sep 03 2018 17:32:44    (current)
   guix e0fa68c
     repository URL: https://git.savannah.gnu.org/git/guix.git
     branch: master
@@ -4342,9 +4342,9 @@ build file @file{build.xml} with tasks to build the specified jar
 archive.  In this case the parameter @code{#:source-dir} can be used to
 specify the source sub-directory, defaulting to ``src''.
 
-The @code{#:main-class} parameter can be used with the minimal ant 
-buildfile to specify the main class of the resulting jar.  This makes the 
-jar file executable.  The @code{#:test-include} parameter can be used to 
+The @code{#:main-class} parameter can be used with the minimal ant
+buildfile to specify the main class of the resulting jar.  This makes the
+jar file executable.  The @code{#:test-include} parameter can be used to
 specify the list of junit tests to run. It defaults to
 @code{(list "**/*Test.java")}.  The @code{#:test-exclude} can be used to
 disable some tests. It defaults to @code{(list "**/Abstract*.java")},
@@ -12949,12 +12949,15 @@ type @code{<sddm-configuration>}.
 @deffn {Scheme Procedure} xorg-start-command [#:guile] @
   [#:modules %default-xorg-modules] @
   [#:fonts %default-xorg-fonts] @
+  [#:keyboard-layout "us"] @
+  [#:keyboard-variant #f] @
   [#:configuration-file (xorg-configuration-file @dots{})] @
   [#:xorg-server @var{xorg-server}]
 Return a @code{startx} script in which @var{modules}, a list of X module
-packages, and @var{fonts}, a list of X font directories, are available.  See
-@code{xorg-wrapper} for more details on the arguments.  The result should be
-used in place of @code{startx}.
+packages, and @var{fonts}, a list of X font directories, are available.
+It will use the @var{keyboard-layout} with the @var{keyboard-variant}
+if it exists in @var{xkeyboard-config}.  See @code{xorg-wrapper} for more
+details on the arguments.  The result should be used in place of @code{startx}.
 
 Usually the X server is started by a login manager.
 @end deffn
@@ -12982,44 +12985,6 @@ resolutions---e.g., @code{((1024 768) (640 480))}.
 Last, @var{extra-config} 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.
-
-@cindex keymap
-@cindex keyboard layout
-This procedure is especially useful to configure a different keyboard layout
-than the default US keymap.  For instance, to use the ``bépo'' keymap by
-default on the display manager:
-
-@example
-(define bepo-evdev
-  "Section \"InputClass\"
-        Identifier \"evdev keyboard catchall\"
-        Driver \"evdev\"
-        MatchIsKeyboard \"on\"
-        Option \"xkb_layout\" \"fr\"
-        Option \"xkb_variant\" \"bepo\"
-EndSection")
-
-(operating-system
-  ...
-  (services
-    (modify-services %desktop-services
-      (slim-service-type config =>
-        (slim-configuration
-          (inherit config)
-          (startx (xorg-start-command
-                   #:configuration-file
-                   (xorg-configuration-file
-                     #:extra-config
-                     (list bepo-evdev)))))))))
-@end example
-
-The @code{MatchIsKeyboard} line specifies that we only apply the configuration
-to keyboards.  Without this line, other devices such as touchpad may not work
-correctly because they will be attached to the wrong driver.  In this example,
-the user typically used @code{setxkbmap fr bepo} to set their favorite keymap
-once logged in.  The first argument corresponds to the layout, while the second
-argument corresponds to the variant.  The @code{xkb_variant} line can be omitted
-to select the default variant.
 @end deffn
 
 @deffn {Scheme Procedure} screen-locker-service @var{package} [@var{program}]
@@ -22727,7 +22692,7 @@ extends: shepherd-root
 description: Install the given fonts on the specified ttys (fonts are
 + per virtual console on GNU/Linux).  The value of this service is a list
 + of tty/font pairs like:
-+ 
++
 +      '(("tty1" . "LatGrkCyr-8x16"))
 relevance: 20
 
diff --git a/gnu/services/xorg.scm b/gnu/services/xorg.scm
index ea8433af3..f41c5dfe8 100644
--- a/gnu/services/xorg.scm
+++ b/gnu/services/xorg.scm
@@ -2,6 +2,7 @@
 ;;; Copyright © 2017 Andy Wingo <[email-masked]>
 ;;; Copyright © 2013, 2014, 2015, 2016, 2017 Ludovic Courtès <[email-masked]>
 ;;; Copyright © 2015 Sou Bunnbu <[email-masked]>
+;;; Copyright © 2019 nee <[email-masked]>
 ;;;
 ;;; This file is part of GNU Guix.
 ;;;
@@ -121,6 +122,8 @@
                                   (modules %default-xorg-modules)
                                   (fonts %default-xorg-fonts)
                                   (drivers '()) (resolutions '())
+                                  (keyboard-layout #f)
+                                  (keyboard-variant #f)
                                   (extra-config '()))
   "Return a configuration file for the Xorg server containing search paths for
 all the common drivers.
@@ -222,6 +225,21 @@ EndSection\n" port)
                      port)
             (newline port)
 
+            (when #$keyboard-layout
+              (display "Section \"InputClass\"
+        Identifier \"evdev keyboard catchall\"
+        MatchIsKeyboard \"on\"\n" port)
+              (format port
+                      "        Option \"XkbLayout\" ~s\n" #$keyboard-layout)
+              (when #$keyboard-variant
+                (format
+                 port
+                 "        Option \"XkbVariant\" ~s\n" #$keyboard-variant))
+              (display
+               "        MatchDevicePath \"/dev/input/event*\"
+        Driver \"evdev\"
+EndSection\n" port))
+
             (for-each (lambda (config)
                         (display config port))
                       '#$extra-config)))))
@@ -229,7 +247,7 @@ EndSection\n" port)
   (computed-file "xserver.conf" build))

-(define (xorg-configuration-directory modules)
+(define* (xorg-configuration-directory modules)
   "Return a directory that contains the @code{.conf} files for X.org that
 includes the @code{share/X11/xorg.conf.d} directories of each package listed
 in @var{modules}."
@@ -255,6 +273,7 @@ in @var{modules}."
                                  files)
                        #t))))
 
+
 (define* (xorg-wrapper #:key
                        (guile (canonical-package guile-2.0))
                        (modules %default-xorg-modules)
@@ -290,9 +309,7 @@ in place of @code{/usr/bin/X}."
                                                        #:fonts fonts))
                              (xorg-server xorg-server))
   "Return a @code{startx} script in which @var{modules}, a list of X module
-packages, and @var{fonts}, a list of X font directories, are available.  See
-@code{xorg-wrapper} for more details on the arguments.  The result should be
-used in place of @code{startx}."
+packages, and @var{fonts}, a list of X font directories, are available."
   (define X
     (xorg-wrapper #:guile guile
                   #:configuration-file configuration-file
diff --git a/gnu/system/examples/desktop.tmpl b/gnu/system/examples/desktop.tmpl
index 1b8d46afa..cb561c4e5 100644
--- a/gnu/system/examples/desktop.tmpl
+++ b/gnu/system/examples/desktop.tmpl
@@ -3,7 +3,7 @@
 ;; root partition is encrypted with LUKS.
 
 (use-modules (gnu) (gnu system nss))
-(use-service-modules desktop)
+(use-service-modules desktop xorg)
 (use-package-modules certs gnome)
 
 (operating-system
@@ -52,7 +52,16 @@
   ;; NetworkManager, and more.
   (services (cons* (gnome-desktop-service)
                    (xfce-desktop-service)
-                   %desktop-services))
+                   (modify-services %desktop-services
+				(slim-service-type config =>
+					(slim-configuration
+					(inherit config)
+					(startx
+					 (xorg-start-command
+ 					  #:configuration-file
+					  (xorg-configuration-file
+					   #:keyboard-layout "us"
+					   #:keyboard-variant #f))))))))
 
   ;; Allow resolution of '.local' host names with mDNS.
   (name-service-switch %mdns-host-lookup-nss))
diff --git a/gnu/system/examples/lightweight-desktop.tmpl b/gnu/system/examples/lightweight-desktop.tmpl
index 360ee62ff..c5ca4a3db 100644
--- a/gnu/system/examples/lightweight-desktop.tmpl
+++ b/gnu/system/examples/lightweight-desktop.tmpl
@@ -3,7 +3,7 @@
 ;; environments.
 
 (use-modules (gnu) (gnu system nss))
-(use-service-modules desktop)
+(use-service-modules desktop xorg)
 (use-package-modules bootloaders certs ratpoison suckless wm)
 
 (operating-system
@@ -46,7 +46,16 @@
 
   ;; Use the "desktop" services, which include the X11
   ;; log-in service, networking with NetworkManager, and more.
-  (services %desktop-services)
+  (services (modify-services %desktop-services
+		(slim-service-type config =>
+			(slim-configuration
+				(inherit config)
+				(startx
+				 (xorg-start-command
+				  #:configuration-file
+				  (xorg-configuration-file
+				   #:keyboard-layout "us"
+				   #:keyboard-variant #f)))))))
 
   ;; Allow resolution of '.local' host names with mDNS.
   (name-service-switch %mdns-host-lookup-nss))
-- 
2.20.1