[PATCH 0/4] Add localed, fixing keyboard layout in GDM

  • Done
  • quality assurance status badge
Details
One participant
  • Ludovic Courtès
Owner
unassigned
Submitted by
Ludovic Courtès
Severity
normal
L
L
Ludovic Courtès wrote on 3 Apr 2019 11:41
(address . guix-patches@gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
20190403094154.22664-1-ludo@gnu.org
Hello Guix!

This patch adds localed, a D-Bus service for keyboard layout
and “locales” (not quite actually):


The only motivation was to fix keyboard layout in GDM: until
now, GDM would always install a US English layout, regardless
of how we configured Xorg. It did that because it tried to
ask localed about the current keyboard layout, but since that
daemon was unavailable, it would assume that the current layout
is US English and tell XKB to install it.

You would think that it would simply ask X to know what the
current layout is—after all, X knows that first-hand. But no!
Instead, there’s this localed daemon that normally goes ahead
and greps /etc/X11/xorg.d/00-keyboard.conf in search of
“XkbLayout” and similar options.

This patch modifies localed so that it gets this information
directly from environment variables set by our ‘localed’ service;
their values is inherited from the ‘xorg-configuration’ field of
<gdm-configuration>.

This is all pretty ugly. Regarding localed itself, I think we
should maintain our own fork since we really just need a couple
of files from systemd. That would require disentangling the code
from systemd’s own support functions (like its D-Bus API wrapper).
That should be easy for someone who’s ever played with D-Bus in
C, but that’s not me. :-)

Another option, of course, is to write a D-Bus implementation in
Guile and do the whole thing in Guile. Shave a yak!

Anyway, in the meantime, this thing does the job.

Thoughts?

Ludo’.

Ludovic Courtès (4):
services: dbus: Add 'wrapped-dbus-service'.
gnu: Add localed, extracted from systemd.
services: dbus: 'wrapped-dbus-service' accepts a list of variables.
services: Add 'localed' service type and have GDM extend it.

gnu/local.mk | 1 +
gnu/packages/freedesktop.scm | 148 +++++++-
.../patches/localed-xorg-keyboard.patch | 322 ++++++++++++++++++
gnu/services/dbus.scm | 48 +++
gnu/services/desktop.scm | 52 +--
gnu/services/xorg.scm | 89 ++++-
6 files changed, 612 insertions(+), 48 deletions(-)
create mode 100644 gnu/packages/patches/localed-xorg-keyboard.patch

--
2.21.0
L
L
Ludovic Courtès wrote on 3 Apr 2019 11:44
[PATCH 1/4] services: dbus: Add 'wrapped-dbus-service'.
(address . 35118@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
20190403094419.22802-1-ludo@gnu.org
* gnu/services/desktop.scm (wrapped-dbus-service): Move to...
* gnu/services/dbus.scm (wrapped-dbus-service): ... here. New
procedure.
---
gnu/services/dbus.scm | 42 ++++++++++++++++++++++++++++++++++++++++
gnu/services/desktop.scm | 40 --------------------------------------
2 files changed, 42 insertions(+), 40 deletions(-)

Toggle diff (120 lines)
diff --git a/gnu/services/dbus.scm b/gnu/services/dbus.scm
index 606ee0c2f5..3d2dbb903c 100644
--- a/gnu/services/dbus.scm
+++ b/gnu/services/dbus.scm
@@ -26,6 +26,7 @@
#:use-module (gnu packages polkit)
#:use-module (gnu packages admin)
#:use-module (guix gexp)
+ #:use-module ((guix packages) #:select (package-name))
#:use-module (guix records)
#:use-module (srfi srfi-1)
#:use-module (ice-9 match)
@@ -33,6 +34,7 @@
dbus-configuration?
dbus-root-service-type
dbus-service
+ wrapped-dbus-service
polkit-service-type
polkit-service))
@@ -229,6 +231,46 @@ and policy files. For example, to allow avahi-daemon to use the system bus,
(dbus-configuration (dbus dbus)
(services services))))
+(define (wrapped-dbus-service service program variable value)
+ "Return a wrapper for @var{service}, a package containing a D-Bus service,
+where @var{program} is wrapped such that environment variable @var{variable}
+is set to @var{value} when the bus daemon launches it."
+ (define wrapper
+ (program-file (string-append (package-name service) "-program-wrapper")
+ #~(begin
+ (setenv #$variable #$value)
+ (apply execl (string-append #$service "/" #$program)
+ (string-append #$service "/" #$program)
+ (cdr (command-line))))))
+
+ (define build
+ (with-imported-modules '((guix build utils))
+ #~(begin
+ (use-modules (guix build utils))
+
+ (define service-directory
+ "/share/dbus-1/system-services")
+
+ (mkdir-p (dirname (string-append #$output
+ service-directory)))
+ (copy-recursively (string-append #$service
+ service-directory)
+ (string-append #$output
+ service-directory))
+ (symlink (string-append #$service "/etc") ;for etc/dbus-1
+ (string-append #$output "/etc"))
+
+ (for-each (lambda (file)
+ (substitute* file
+ (("Exec[[:blank:]]*=[[:blank:]]*([[:graph:]]+)(.*)$"
+ _ original-program arguments)
+ (string-append "Exec=" #$wrapper arguments
+ "\n"))))
+ (find-files #$output "\\.service$")))))
+
+ (computed-file (string-append (package-name service) "-wrapper")
+ build))
+
;;;
;;; Polkit privilege management service.
diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm
index dcab950822..230aeb324c 100644
--- a/gnu/services/desktop.scm
+++ b/gnu/services/desktop.scm
@@ -150,46 +150,6 @@
((package . _) package))))
-(define (wrapped-dbus-service service program variable value)
- "Return a wrapper for @var{service}, a package containing a D-Bus service,
-where @var{program} is wrapped such that environment variable @var{variable}
-is set to @var{value} when the bus daemon launches it."
- (define wrapper
- (program-file (string-append (package-name service) "-program-wrapper")
- #~(begin
- (setenv #$variable #$value)
- (apply execl (string-append #$service "/" #$program)
- (string-append #$service "/" #$program)
- (cdr (command-line))))))
-
- (define build
- (with-imported-modules '((guix build utils))
- #~(begin
- (use-modules (guix build utils))
-
- (define service-directory
- "/share/dbus-1/system-services")
-
- (mkdir-p (dirname (string-append #$output
- service-directory)))
- (copy-recursively (string-append #$service
- service-directory)
- (string-append #$output
- service-directory))
- (symlink (string-append #$service "/etc") ;for etc/dbus-1
- (string-append #$output "/etc"))
-
- (for-each (lambda (file)
- (substitute* file
- (("Exec[[:blank:]]*=[[:blank:]]*([[:graph:]]+)(.*)$"
- _ original-program arguments)
- (string-append "Exec=" #$wrapper arguments
- "\n"))))
- (find-files #$output "\\.service$")))))
-
- (computed-file (string-append (package-name service) "-wrapper")
- build))
-
;;;
;;; Upower D-Bus service.
--
2.21.0
L
L
Ludovic Courtès wrote on 3 Apr 2019 11:44
[PATCH 2/4] gnu: Add localed, extracted from systemd.
(address . 35118@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
20190403094419.22802-2-ludo@gnu.org
* gnu/packages/freedesktop.scm (localed): New variable.
* gnu/packages/patches/localed-xorg-keyboard.patch: New file.
* gnu/local.mk (dist_patch_DATA): Add it.
---
gnu/local.mk | 1 +
gnu/packages/freedesktop.scm | 148 +++++++-
.../patches/localed-xorg-keyboard.patch | 322 ++++++++++++++++++
3 files changed, 470 insertions(+), 1 deletion(-)
create mode 100644 gnu/packages/patches/localed-xorg-keyboard.patch

Toggle diff (488 lines)
diff --git a/gnu/local.mk b/gnu/local.mk
index 45598d4e14..5c86ee0809 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -929,6 +929,7 @@ dist_patch_DATA = \
%D%/packages/patches/kdbusaddons-kinit-file-name.patch \
%D%/packages/patches/khmer-use-libraries.patch \
%D%/packages/patches/libziparchive-add-includes.patch \
+ %D%/packages/patches/localed-xorg-keyboard.patch \
%D%/packages/patches/kiki-level-selection-crash.patch \
%D%/packages/patches/kiki-makefile.patch \
%D%/packages/patches/kiki-missing-includes.patch \
diff --git a/gnu/packages/freedesktop.scm b/gnu/packages/freedesktop.scm
index 56aeca0478..ec8688d2d4 100644
--- a/gnu/packages/freedesktop.scm
+++ b/gnu/packages/freedesktop.scm
@@ -2,7 +2,7 @@
;;; Copyright © 2015 Andreas Enge <andreas@enge.fr>
;;; Copyright © 2015 Sou Bunnbu <iyzsong@gmail.com>
;;; Copyright © 2015, 2017 Andy Wingo <wingo@pobox.com>
-;;; Copyright © 2015, 2016, 2017 Ludovic Courtès <ludo@gnu.org>
+;;; Copyright © 2015, 2016, 2017, 2019 Ludovic Courtès <ludo@gnu.org>
;;; Copyright © 2015, 2017, 2018, 2019 Ricardo Wurmus <rekado@elephly.net>
;;; Copyright © 2015 David Hashe <david.hashe@dhashe.com>
;;; Copyright © 2016, 2017 Efraim Flashner <efraim@flashner.co.il>
@@ -307,6 +307,152 @@ the org.freedesktop.login1 interface over the system bus, allowing other parts
of a the system to know what users are logged in, and where.")
(license license:lgpl2.1+)))
+(define-public localed
+ ;; XXX: This package is extracted from systemd but we retain so little of it
+ ;; that it would make more sense to maintain of fork of the bits we need.
+ (package
+ (name "localed")
+ (version "241")
+ (source (origin
+ (method git-fetch)
+ (uri (git-reference
+ (url "https://github.com/systemd/systemd")
+ (commit (string-append "v" version))))
+ (sha256
+ (base32
+ "0sy91flzbhpq58k7v0294pa2gxpr0bk27rcnxlbhk2fi6nc51d28"))
+ (file-name (git-file-name name version))
+ (modules '((guix build utils)))
+ (snippet
+ '(begin
+ ;; Connect to the right location for our D-Bus daemon.
+ (substitute* '("src/basic/def.h"
+ "src/libsystemd/sd-bus/sd-bus.c"
+ "src/stdio-bridge/stdio-bridge.c")
+ (("/run/dbus/system_bus_socket")
+ "/var/run/dbus/system_bus_socket"))
+
+ ;; Don't insist on having systemd as PID 1 (otherwise
+ ;; 'localectl' would exit without doing anything.)
+ (substitute* "src/shared/bus-util.c"
+ (("sd_booted\\(\\)")
+ "(1)"))
+ #t))
+ (patches (search-patches "localed-xorg-keyboard.patch"))))
+ (build-system meson-build-system)
+ (arguments
+ ;; Try to build as little as possible (list of components taken from the
+ ;; top-level 'meson.build' file.)
+ (let ((components '("utmp"
+ "hibernate"
+ "environment-d"
+ "binfmt"
+ "coredump"
+ "resolve"
+ "logind"
+ "hostnamed"
+ "localed"
+ "machined"
+ "portabled"
+ "networkd"
+ "timedated"
+ "timesyncd"
+ "firstboot"
+ "randomseed"
+ "backlight"
+ "vconsole"
+ "quotacheck"
+ "sysusers"
+ "tmpfiles"
+ "hwdb"
+ "rfkill"
+ "ldconfig"
+ "efi"
+ "tpm"
+ "ima"
+ "smack"
+ "gshadow"
+ "idn"
+ "nss-myhostname"
+ "nss-systemd")))
+ `(#:configure-flags ',(map (lambda (component)
+ (string-append "-D" component "=false"))
+ (delete "localed" components))
+
+ ;; It doesn't make sense to test all of systemd.
+ #:tests? #f
+
+ #:phases (modify-phases %standard-phases
+ (add-after 'unpack 'set-xkeyboard-config-file-name
+ (lambda* (#:key inputs #:allow-other-keys)
+ ;; Set the file name to xkeyboard-config and kbd.
+ ;; This is used by 'localectl list-x11-keymap-layouts'
+ ;; and similar functions.
+ (let ((xkb (assoc-ref inputs "xkeyboard-config"))
+ (kbd (assoc-ref inputs "kbd")))
+ (substitute* "src/locale/localectl.c"
+ (("/usr/share/X11/xkb/rules")
+ (string-append xkb "/share/X11/xkb/rules")))
+ (substitute* "src/basic/def.h"
+ (("/usr/share/keymaps")
+ (string-append kbd "/share/keymaps")))
+ #t)))
+ (replace 'install
+ (lambda* (#:key outputs #:allow-other-keys)
+ ;; Install 'localed', the D-Bus and polkit files, and
+ ;; 'localectl'.
+ (let* ((out (assoc-ref outputs "out"))
+ (libexec (string-append out "/libexec/localed"))
+ (bin (string-append out "/bin"))
+ (lib (string-append out "/lib"))
+ (dbus (string-append out
+ "/share/dbus-1/system-services"))
+ (conf (string-append out
+ "/etc/dbus-1/system.d/"))
+ (polkit (string-append out
+ "/share/polkit-1/actions"))
+ (data (string-append out "/share/systemd")))
+ (define (source-file regexp)
+ (car (find-files ".." regexp)))
+
+ (mkdir-p libexec)
+ (copy-file "systemd-localed"
+ (string-append libexec "/localed"))
+ (install-file "localectl" bin)
+
+ (let ((service-file (source-file
+ "\\.locale1\\.service$")))
+ (substitute* service-file
+ (("^Exec=.*$")
+ (string-append "Exec=" libexec "/localed\n")))
+ (install-file service-file dbus))
+ (install-file (source-file "\\.locale1\\.policy$")
+ polkit)
+ (install-file (source-file "\\.locale1\\.conf$")
+ conf)
+ (for-each (lambda (file)
+ (install-file file lib))
+ (find-files "src/shared"
+ "libsystemd-shared.*\\.so"))
+
+ (for-each (lambda (map)
+ (install-file map data))
+ (find-files ".." "^(kbd-model-map|language-fallback-map)$"))
+ #t)))))))
+ (native-inputs (package-native-inputs elogind))
+ (inputs `(("libmount" ,util-linux)
+ ("xkeyboard-config" ,xkeyboard-config)
+ ("kbd" ,kbd)
+ ,@(package-inputs elogind)))
+ (home-page "https://www.freedesktop.org/wiki/Software/systemd/localed/")
+ (synopsis "Control the system locale and keyboard layout")
+ (description
+ "Localed is a tiny daemon that can be used to control the system locale
+and keyboard mapping from user programs. It is used among other things by the
+GNOME Shell. The @command{localectl} command-line tool allows you to interact
+with localed. This package is extracted from the broader systemd package.")
+ (license license:lgpl2.1+)))
+
(define-public packagekit
(package
(name "packagekit")
diff --git a/gnu/packages/patches/localed-xorg-keyboard.patch b/gnu/packages/patches/localed-xorg-keyboard.patch
new file mode 100644
index 0000000000..9a9071ba0a
--- /dev/null
+++ b/gnu/packages/patches/localed-xorg-keyboard.patch
@@ -0,0 +1,322 @@
+Normally localed would do an approximate parsing of the Xorg config file
+to determine the XKB keyboard layout. This doesn't make sense on Guix
+where there's no such file in /etc, and where the keyboard layout is
+known statically at configuration time.
+
+This patch removes the XOrg configuration parsing and expects to read the
+configuration from environment variables instead. It also removes the
+stateful bits that would write configuration to /etc/vconsole.conf
+and /etc/X11, which are unused in Guix anyway.
+
+Patch by Ludovic Courtès <ludo@gnu.org>.
+
+diff --git a/src/locale/keymap-util.c b/src/locale/keymap-util.c
+index 6b6b32a591..46aab472b0 100644
+--- a/src/locale/keymap-util.c
++++ b/src/locale/keymap-util.c
+@@ -174,32 +174,16 @@ int vconsole_read_data(Context *c, sd_bus_message *m) {
+ c->vc_cache = sd_bus_message_ref(m);
+ }
+
+- if (stat("/etc/vconsole.conf", &st) < 0) {
+- if (errno != ENOENT)
+- return -errno;
+-
+- c->vc_mtime = USEC_INFINITY;
+- context_free_vconsole(c);
+- return 0;
+- }
+-
+- /* If mtime is not changed, then we do not need to re-read */
+- t = timespec_load(&st.st_mtim);
+- if (c->vc_mtime != USEC_INFINITY && t == c->vc_mtime)
+- return 0;
+-
+- c->vc_mtime = t;
++ c->vc_mtime = USEC_INFINITY;
+ context_free_vconsole(c);
+-
+- r = parse_env_file(NULL, "/etc/vconsole.conf",
+- "KEYMAP", &c->vc_keymap,
+- "KEYMAP_TOGGLE", &c->vc_keymap_toggle);
+- if (r < 0)
+- return r;
+-
+ return 0;
+ }
+
++static char *getenv_strdup(const char *variable) {
++ const char *value = getenv(variable);
++ return value == NULL ? NULL : strdup(value);
++}
++
+ int x11_read_data(Context *c, sd_bus_message *m) {
+ _cleanup_fclose_ FILE *f = NULL;
+ bool in_section = false;
+@@ -216,258 +200,27 @@ int x11_read_data(Context *c, sd_bus_message *m) {
+ c->x11_cache = sd_bus_message_ref(m);
+ }
+
+- if (stat("/etc/X11/xorg.conf.d/00-keyboard.conf", &st) < 0) {
+- if (errno != ENOENT)
+- return -errno;
+-
+- c->x11_mtime = USEC_INFINITY;
+- context_free_x11(c);
+- return 0;
+- }
+-
+- /* If mtime is not changed, then we do not need to re-read */
+- t = timespec_load(&st.st_mtim);
+- if (c->x11_mtime != USEC_INFINITY && t == c->x11_mtime)
+- return 0;
+-
+- c->x11_mtime = t;
++ c->x11_mtime = 0;
+ context_free_x11(c);
+
+- f = fopen("/etc/X11/xorg.conf.d/00-keyboard.conf", "re");
+- if (!f)
+- return -errno;
+-
+- for (;;) {
+- _cleanup_free_ char *line = NULL;
+- char *l;
+-
+- r = read_line(f, LONG_LINE_MAX, &line);
+- if (r < 0)
+- return r;
+- if (r == 0)
+- break;
+-
+- l = strstrip(line);
+- if (IN_SET(l[0], 0, '#'))
+- continue;
+-
+- if (in_section && first_word(l, "Option")) {
+- _cleanup_strv_free_ char **a = NULL;
+-
+- r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES);
+- if (r < 0)
+- return r;
+-
+- if (strv_length(a) == 3) {
+- char **p = NULL;
+-
+- if (streq(a[1], "XkbLayout"))
+- p = &c->x11_layout;
+- else if (streq(a[1], "XkbModel"))
+- p = &c->x11_model;
+- else if (streq(a[1], "XkbVariant"))
+- p = &c->x11_variant;
+- else if (streq(a[1], "XkbOptions"))
+- p = &c->x11_options;
+-
+- if (p) {
+- free_and_replace(*p, a[2]);
+- }
+- }
+-
+- } else if (!in_section && first_word(l, "Section")) {
+- _cleanup_strv_free_ char **a = NULL;
+-
+- r = strv_split_extract(&a, l, WHITESPACE, EXTRACT_QUOTES);
+- if (r < 0)
+- return -ENOMEM;
+-
+- if (strv_length(a) == 2 && streq(a[1], "InputClass"))
+- in_section = true;
+-
+- } else if (in_section && first_word(l, "EndSection"))
+- in_section = false;
+- }
++ c->x11_layout = getenv_strdup("GUIX_XKB_LAYOUT");
++ c->x11_model = getenv_strdup("GUIX_XKB_MODEL");
++ c->x11_variant = getenv_strdup("GUIX_XKB_VARIANT");
++ c->x11_options = getenv_strdup("GUIX_XKB_OPTIONS");
+
+ return 0;
+ }
+
+ int locale_write_data(Context *c, char ***settings) {
+- _cleanup_strv_free_ char **l = NULL;
+- struct stat st;
+- int r, p;
+-
+- /* Set values will be returned as strv in *settings on success. */
+-
+- for (p = 0; p < _VARIABLE_LC_MAX; p++) {
+- _cleanup_free_ char *t = NULL;
+- char **u;
+- const char *name;
+-
+- name = locale_variable_to_string(p);
+- assert(name);
+-
+- if (isempty(c->locale[p]))
+- continue;
+-
+- if (asprintf(&t, "%s=%s", name, c->locale[p]) < 0)
+- return -ENOMEM;
+-
+- u = strv_env_set(l, t);
+- if (!u)
+- return -ENOMEM;
+-
+- strv_free_and_replace(l, u);
+- }
+-
+- if (strv_isempty(l)) {
+- if (unlink("/etc/locale.conf") < 0)
+- return errno == ENOENT ? 0 : -errno;
+-
+- c->locale_mtime = USEC_INFINITY;
+- return 0;
+- }
+-
+- r = write_env_file_label("/etc/locale.conf", l);
+- if (r < 0)
+- return r;
+-
+- *settings = TAKE_PTR(l);
+-
+- if (stat("/etc/locale.conf", &st) >= 0)
+- c->locale_mtime = timespec_load(&st.st_mtim);
+-
+- return 0;
++ return -ENOSYS;
+ }
+
+ int vconsole_write_data(Context *c) {
+- _cleanup_strv_free_ char **l = NULL;
+- struct stat st;
+- int r;
+-
+- r = load_env_file(NULL, "/etc/vconsole.conf", &l);
+- if (r < 0 && r != -ENOENT)
+- return r;
+-
+- if (isempty(c->vc_keymap))
+- l = strv_env_unset(l, "KEYMAP");
+- else {
+- _cleanup_free_ char *s = NULL;
+- char **u;
+-
+- s = strappend("KEYMAP=", c->vc_keymap);
+- if (!s)
+- return -ENOMEM;
+-
+- u = strv_env_set(l, s);
+- if (!u)
+- return -ENOMEM;
+-
+- strv_free_and_replace(l, u);
+- }
+-
+- if (isempty(c->vc_keymap_toggle))
+- l = strv_env_unset(l, "KEYMAP_TOGGLE");
+- else {
+- _cleanup_free_ char *s = NULL;
+- char **u;
+-
+- s = strappend("KEYMAP_TOGGLE=", c->vc_keymap_toggle);
+- if (!s)
+- return -ENOMEM;
+-
+- u = strv_env_set(l, s);
+- if (!u)
+- return -ENOMEM;
+-
+- strv_free_and_replace(l, u);
+- }
+-
+- if (strv_isempty(l)) {
+- if (unlink("/etc/vconsole.conf") < 0)
+- return errno == ENOENT ? 0 : -errno;
+-
+- c->vc_mtime = USEC_INFINITY;
+- return 0;
+- }
+-
+- r = write_env_file_label("/etc/vconsole.conf", l);
+- if (r < 0)
+- return r;
+-
+- if (stat("/etc/vconsole.conf", &st) >= 0)
+- c->vc_mtime = timespec_load(&st.st_mtim);
+-
+- return 0;
++ return -ENOSYS;
+ }
+
+ int x11_write_data(Context *c) {
+- _cleanup_fclose_ FILE *f = NULL;
+- _cleanup_free_ char *temp_path = NULL;
+- struct stat st;
+- int r;
+-
+- if (isempty(c->x11_layout) &&
+- isempty(c->x11_model) &&
+- isempty(c->x11_variant) &&
+- isempty(c->x11_options)) {
+-
+- if (unlink("/etc/X11/xorg.conf.d/00-keyboard.conf") < 0)
+- return errno == ENOENT ? 0 : -errno;
+-
+- c->vc_mtime = USEC_INFINITY;
+- return 0;
+- }
+-
+- mkdir_p_label("/etc/X11/xorg.conf.d", 0755);
+-
+- r = fopen_temporary("/etc/X11/xorg.conf.d/00-keyboard.conf", &f, &temp_path);
+- if (r < 0)
+- return r;
+-
+- (void) __fsetlocking(f, FSETLOCKING_BYCALLER);
+- (void) fchmod(fileno(f), 0644);
+-
+- fputs("# Written by systemd-localed(8), read by systemd-localed and Xorg. It's\n"
+- "# probably wise not to edit this file manually. Use localectl(1) to\n"
+- "# instruct systemd-localed to update it.\n"
+- "Section \"InputClass\"\n"
+- " Identifier \"system-keyboard\"\n"
+- " MatchIsKeyboard \"on\"\n", f);
+-
+- if (!isempty(c->x11_layout))
+- fprintf(f, " Option \"XkbLayout\" \"%s\"\n", c->x11_layout);
+-
+- if (!isempty(c->x11_model))
+- fprintf(f, " Option \"XkbModel\" \"%s\"\n", c->x11_model);
+-
+- if (!isempty(c->x11_variant))
+- fprintf(f, " Option \"XkbVariant\" \"%s\"\n", c->x11_variant);
+-
+- if (!isempty(c->x11_options))
+- fprintf(f, " Option \"XkbOptions\" \"%s\"\n", c->x11_options);
+-
+- fputs("EndSection\n", f);
+-
+- r = fflush_sync_and_check(f);
+- if (r < 0)
+- goto fail;
+-
+- if (rename(temp_path, "/etc/X11/xorg.conf.d/00-keyboard.
This message was truncated. Download the full message here.
L
L
Ludovic Courtès wrote on 3 Apr 2019 11:44
[PATCH 3/4] services: dbus: 'wrapped-dbus-service' accepts a list of variables.
(address . 35118@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
20190403094419.22802-3-ludo@gnu.org
* gnu/services/dbus.scm (wrapped-dbus-service): Replace 'variable' and
'value' by 'variables', and adjust code accordingly.
* gnu/services/desktop.scm (upower-dbus-service):
(geoclue-dbus-service, elogind-dbus-service): Adjust accordingly.
---
gnu/services/dbus.scm | 14 ++++++++++----
gnu/services/desktop.scm | 12 ++++++------
2 files changed, 16 insertions(+), 10 deletions(-)

Toggle diff (68 lines)
diff --git a/gnu/services/dbus.scm b/gnu/services/dbus.scm
index 3d2dbb903c..35d7ff3c9c 100644
--- a/gnu/services/dbus.scm
+++ b/gnu/services/dbus.scm
@@ -231,14 +231,20 @@ and policy files. For example, to allow avahi-daemon to use the system bus,
(dbus-configuration (dbus dbus)
(services services))))
-(define (wrapped-dbus-service service program variable value)
+(define (wrapped-dbus-service service program variables)
"Return a wrapper for @var{service}, a package containing a D-Bus service,
-where @var{program} is wrapped such that environment variable @var{variable}
-is set to @var{value} when the bus daemon launches it."
+where @var{program} is wrapped such that @var{variables}, a list of name/value
+tuples, are all set as environment variables when the bus daemon launches it."
(define wrapper
(program-file (string-append (package-name service) "-program-wrapper")
#~(begin
- (setenv #$variable #$value)
+ (use-modules (ice-9 match))
+
+ (for-each (match-lambda
+ ((variable value)
+ (setenv variable value)))
+ '#$variables)
+
(apply execl (string-append #$service "/" #$program)
(string-append #$service "/" #$program)
(cdr (command-line))))))
diff --git a/gnu/services/desktop.scm b/gnu/services/desktop.scm
index 230aeb324c..578095b146 100644
--- a/gnu/services/desktop.scm
+++ b/gnu/services/desktop.scm
@@ -217,8 +217,8 @@
(define (upower-dbus-service config)
(list (wrapped-dbus-service (upower-configuration-upower config)
"libexec/upowerd"
- "UPOWER_CONF_FILE_NAME"
- (upower-configuration-file config))))
+ `(("UPOWER_CONF_FILE_NAME"
+ ,(upower-configuration-file config))))))
(define (upower-shepherd-service config)
"Return a shepherd service for UPower with CONFIG."
@@ -349,8 +349,8 @@ users are allowed."
(define (geoclue-dbus-service config)
(list (wrapped-dbus-service (geoclue-configuration-geoclue config)
"libexec/geoclue"
- "GEOCLUE_CONFIG_FILE"
- (geoclue-configuration-file config))))
+ `(("GEOCLUE_CONFIG_FILE"
+ ,(geoclue-configuration-file config))))))
(define %geoclue-accounts
(list (user-group (name "geoclue") (system? #t))
@@ -702,8 +702,8 @@ include the @command{udisksctl} command, part of UDisks, and GNOME Disks."
(define (elogind-dbus-service config)
(list (wrapped-dbus-service (elogind-package config)
"libexec/elogind/elogind"
- "ELOGIND_CONF_FILE"
- (elogind-configuration-file config))))
+ `(("ELOGIND_CONF_FILE"
+ ,(elogind-configuration-file config))))))
(define (pam-extension-procedure config)
"Return an extension for PAM-ROOT-SERVICE-TYPE that ensures that all the PAM
--
2.21.0
L
L
Ludovic Courtès wrote on 3 Apr 2019 11:44
[PATCH 4/4] services: Add 'localed' service type and have GDM extend it.
(address . 35118@debbugs.gnu.org)(name . Ludovic Courtès)(address . ludo@gnu.org)
20190403094419.22802-4-ludo@gnu.org
This fixes a bug whereby GDM would always switch to US English keyboard
layout regardless to the configured Xorg keyboard layout.

* gnu/services/xorg.scm (<localed-configuration>): New record type.
(localed-dbus-service): New procedure.
(localed-service-type): New variable.
(gdm-service-type): Extend LOCALED-SERVICE-TYPE.
---
gnu/services/xorg.scm | 89 ++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 88 insertions(+), 1 deletion(-)

Toggle diff (130 lines)
diff --git a/gnu/services/xorg.scm b/gnu/services/xorg.scm
index 29c7f30013..7745f9a3cc 100644
--- a/gnu/services/xorg.scm
+++ b/gnu/services/xorg.scm
@@ -27,6 +27,7 @@
#:use-module (gnu services shepherd)
#:use-module (gnu system pam)
#:use-module (gnu system keyboard)
+ #:use-module (gnu services base)
#:use-module (gnu services dbus)
#:use-module ((gnu packages base) #:select (canonical-package))
#:use-module (gnu packages guile)
@@ -35,6 +36,7 @@
#:use-module (gnu packages gl)
#:use-module (gnu packages glib)
#:use-module (gnu packages display-managers)
+ #:use-module (gnu packages freedesktop)
#:use-module (gnu packages gnustep)
#:use-module (gnu packages gnome)
#:use-module (gnu packages admin)
@@ -91,6 +93,10 @@
screen-locker-service-type
screen-locker-service
+ localed-configuration
+ localed-configuration?
+ localed-service-type
+
gdm-configuration
gdm-service-type
gdm-service))
@@ -653,6 +659,82 @@ makes the good ol' XlockMore usable."
(file-append package "/bin/" program)
allow-empty-passwords?)))
+
+;;;
+;;; Locale service.
+;;;
+
+(define-record-type* <localed-configuration>
+ localed-configuration make-localed-configuration
+ localed-configuration?
+ (localed localed-configuration-localed
+ (default localed))
+ (keyboard-layout localed-configuration-keyboard-layout
+ (default #f)))
+
+(define (localed-dbus-service config)
+ "Return the 'localed' D-Bus service for @var{config}, a
+@code{<localed-configuration>} record."
+ (define keyboard-layout
+ (localed-configuration-keyboard-layout config))
+
+ ;; The primary purpose of 'localed' is to tell GDM what the "current" Xorg
+ ;; keyboard layout is. If 'localed' is missing, or if it's unable to
+ ;; determine the current XKB layout, then GDM forcefully installs its
+ ;; default XKB config (US English). Here we communicate the configured
+ ;; layout through environment variables.
+
+ (if keyboard-layout
+ (let* ((layout (keyboard-layout-name keyboard-layout))
+ (variant (keyboard-layout-variant keyboard-layout))
+ (model (keyboard-layout-model keyboard-layout))
+ (options (keyboard-layout-options keyboard-layout)))
+ (list (wrapped-dbus-service
+ (localed-configuration-localed config)
+ "libexec/localed/localed"
+ `(("GUIX_XKB_LAYOUT" ,layout)
+ ,@(if variant
+ `(("GUIX_XKB_VARIANT" ,variant))
+ '())
+ ,@(if model
+ `(("GUIX_XKB_MODEL" ,model))
+ '())
+ ,@(if (null? options)
+ '()
+ `(("GUIX_XKB_OPTIONS"
+ ,(string-join options ","))))))))
+ (localed-configuration-localed config)))
+
+(define localed-service-type
+ (let ((package (compose list localed-configuration-localed)))
+ (service-type (name 'localed)
+ (extensions
+ (list (service-extension dbus-root-service-type
+ localed-dbus-service)
+ (service-extension udev-service-type package)
+ (service-extension polkit-service-type package)
+
+ ;; Add 'localectl' to the profile.
+ (service-extension profile-service-type package)))
+
+ ;; This service can be extended, typically by the X login
+ ;; manager, to communicate the chosen Xorg keyboard layout.
+ (compose first)
+ (extend (lambda (config keyboard-layout)
+ (localed-configuration
+ (inherit config)
+ (keyboard-layout keyboard-layout))))
+ (description
+ "Run the locale daemon, @command{localed}, which can be used
+to control the system locale and keyboard mapping from user programs such as
+the GNOME desktop environment.")
+ (default-value (localed-configuration)))))
+
+
+;;;
+;;; GNOME Desktop Manager.
+;;;
+
(define %gdm-accounts
(list (user-group (name "gdm") (system? #t))
(user-account
@@ -787,7 +869,12 @@ makes the good ol' XlockMore usable."
gdm-configuration-gnome-shell-assets)
(service-extension dbus-root-service-type
(compose list
- gdm-configuration-gdm))))
+ gdm-configuration-gdm))
+ (service-extension localed-service-type
+ (compose
+ xorg-configuration-keyboard-layout
+ gdm-configuration-xorg))))
+
(default-value (gdm-configuration))
(description
"Run the GNOME Desktop Manager (GDM), a program that allows
--
2.21.0
L
L
Ludovic Courtès wrote on 5 Apr 2019 15:47
Re: [bug#35118] [PATCH 0/4] Add localed, fixing keyboard layout in GDM
(address . 35118-done@debbugs.gnu.org)
87wok8tvgn.fsf@gnu.org
Hello,

Pushed!

Ludovic Courtès <ludo@gnu.org> skribis:

Toggle quote (7 lines)
> This is all pretty ugly. Regarding localed itself, I think we
> should maintain our own fork since we really just need a couple
> of files from systemd. That would require disentangling the code
> from systemd’s own support functions (like its D-Bus API wrapper).
> That should be easy for someone who’s ever played with D-Bus in
> C, but that’s not me. :-)

As discussed on IRC with Julien and others, I tried to actually fork
systemd and strip everything but src/locale. Unfortunately that turned
out to be pretty tricky because of all the systemd-internal utilities
being used (allocation, string manipulation, etc.)

If someone is willing to give it a try, I can share what I have so far!

Ludo’.
Closed
?