about summary refs log tree commit diff
path: root/nixos/modules
diff options
context:
space:
mode:
authoraszlig <aszlig@redmoonstudios.org>2017-07-28 12:36:48 +0200
committeraszlig <aszlig@redmoonstudios.org>2017-07-28 12:39:55 +0200
commit6e5d2f896365fa6737d0c336b7edbc6b6a15fcb9 (patch)
tree62521cd04d1462265a166bc1aa9e0c631f76de2d /nixos/modules
parent805467bb5a03db607145dd7aae2ef08e1c1ee746 (diff)
downloadnixlib-6e5d2f896365fa6737d0c336b7edbc6b6a15fcb9.tar
nixlib-6e5d2f896365fa6737d0c336b7edbc6b6a15fcb9.tar.gz
nixlib-6e5d2f896365fa6737d0c336b7edbc6b6a15fcb9.tar.bz2
nixlib-6e5d2f896365fa6737d0c336b7edbc6b6a15fcb9.tar.lz
nixlib-6e5d2f896365fa6737d0c336b7edbc6b6a15fcb9.tar.xz
nixlib-6e5d2f896365fa6737d0c336b7edbc6b6a15fcb9.tar.zst
nixlib-6e5d2f896365fa6737d0c336b7edbc6b6a15fcb9.zip
nixos/xserver: Properly validate XKB options
Checking the keyboard layout has been a long set of hurdles so far, with
several attempts. Originally, the checking was introduced by @lheckemann
in #23709.

The initial implementation just was trying to check whether the symbols/
directory contained the layout name.

Unfortunately, that wasn't enough and keyboard variants weren't
recognized, so if you set layout to eg. "dvorak" it will fail with an
error (#25526).

So my improvement on that was to use sed to filter rules/base.lst and
match the layout against that. I fucked up twice with this, first
because layout can be a comma-separated list which I didn't account for
and second because I ran into a Nix issue (NixOS/nix#1426).

After fixing this, it still wasn't enough (and this is btw. what
localectl also does), because we were *only* matching rules but not
symbols, so using "eu" as a layout won't work either.

I decided now it's the time to actually use libxkbcommon to try
compiling the keyboard options and see whether it succeeds. This comes
in the form of a helper tool called xkbvalidate.

IMHO this approach is a lot less error-prone and we can be sure that we
don't forget about anything because that's what the X server itself uses
to compile the keymap.

Another advantage of this is that we now validate the full set of XKB
options rather than just the layout.

Tested this against a variety of wrong and correct keyboard
configurations and against the "keymap" NixOS VM tests.

Signed-off-by: aszlig <aszlig@redmoonstudios.org>
Cc: @lheckemann, @peti, @7c6f434c, @tohl, @vcunat, @lluchs
Fixes: #27597
Diffstat (limited to 'nixos/modules')
-rw-r--r--nixos/modules/services/x11/xserver.nix48
1 files changed, 4 insertions, 44 deletions
diff --git a/nixos/modules/services/x11/xserver.nix b/nixos/modules/services/x11/xserver.nix
index 638509e710be..3ce124d3da27 100644
--- a/nixos/modules/services/x11/xserver.nix
+++ b/nixos/modules/services/x11/xserver.nix
@@ -648,51 +648,11 @@ in
 
     services.xserver.xkbDir = mkDefault "${pkgs.xkeyboard_config}/etc/X11/xkb";
 
-    system.extraDependencies = singleton (pkgs.runCommand "xkb-layouts-exist" {
-      inherit (cfg) layout xkbDir;
+    system.extraDependencies = singleton (pkgs.runCommand "xkb-validated" {
+      inherit (cfg) xkbModel layout xkbVariant xkbOptions;
+      nativeBuildInputs = [ pkgs.xkbvalidate ];
     } ''
-      # We can use the default IFS here, because the layouts won't contain
-      # spaces or tabs and are ruled out by the sed expression below.
-      availableLayouts="$(
-        sed -n -e ':i /^! \(layout\|variant\) *$/ {
-          # Loop through all of the layouts/variants until we hit another ! at
-          # the start of the line or the line is empty ('t' branches only if
-          # the last substitution was successful, so if the line is empty the
-          # substition will fail).
-          :l; n; /^!/bi; s/^ *\([^ ]\+\).*/\1/p; tl
-        }' "$xkbDir/rules/base.lst" | sort -u
-      )"
-
-      layoutNotFound() {
-        echo >&2
-        echo "The following layouts and variants are available:" >&2
-        echo >&2
-
-        # While an output width of 80 is more desirable for small terminals, we
-        # really don't know the amount of columns of the terminal from within
-        # the builder. The content in $availableLayouts however is pretty
-        # large, so let's opt for a larger width here, because it will print a
-        # smaller amount of lines on modern KMS/framebuffer terminals and won't
-        # lose information even in smaller terminals (it only will look a bit
-        # ugly).
-        echo "$availableLayouts" | ${pkgs.utillinux}/bin/column -c 150 >&2
-
-        echo >&2
-        echo "However, the keyboard layout definition in" \
-             "\`services.xserver.layout' contains the layout \`$1', which" \
-             "isn't a valid layout or variant." >&2
-        echo >&2
-        exit 1
-      }
-
-      # Again, we don't need to take care of IFS, see the comment for
-      # $availableLayouts.
-      for l in ''${layout//,/ }; do
-        if ! echo "$availableLayouts" | grep -qxF "$l"; then
-          layoutNotFound "$l"
-        fi
-      done
-
+      validate "$xkbModel" "$layout" "$xkbVariant" "$xkbOptions"
       touch "$out"
     '');