]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
locale: convert generated vconsole keymap to x11 layout automatically
authorFranck Bui <fbui@suse.com>
Thu, 20 Apr 2023 07:27:52 +0000 (09:27 +0200)
committerFranck Bui <fbui@suse.com>
Mon, 24 Apr 2023 16:44:57 +0000 (18:44 +0200)
When doing x11->console conversions, find_converted_keymap() searches
automatically for a candidate in the converted keymap directory for a given x11
layout.

However doing console->x11 conversions, this automatic search is not done hence
simple conversion in this direction can't be achieved without populating
kbd-model-map with entries for converted keymaps.

For example, let's consider "at" layout which is not part of kbd-model-map. The
"at" x11 layout has a generated keymap
"/usr/share/kbd/keymaps/xkb/at.map.gz". If we configure "at" for the x11
layout, localed is able to automatically find the "at" converted vc layout and
the conversion just works :

  $ localectl set-x11-keymap at
  $ localectl
  System Locale: LANG=en_US.UTF-8
      VC Keymap: at
     X11 Layout: at

However in the opposite direction, ie when setting the vc keymap to "at", no
conversion is done and the x11 layout is not defined:

  $ localectl set-keymap at
  $ localectl
  System Locale: LANG=en_US.UTF-8
      VC Keymap: at
     X11 Layout: (unset)

This patch fixes this limitation as the implemenation is relatively simple and
it removes the need to populate kbd-model-map with (many) entries for converted
keymaps. However the patch doesn't remove the existing entries in kbd-model-map
which became unneeded after this change to be on the safe side.

Note: by default the automatically generated x11 keyboard configs use keyboard
model "microsoftpro" which should be equivalent to "pc105" model but with the
internet/media key mapping added.

src/locale/localed-util.c

index 65b6108e4e7e99f54b6ad999d5e391c97c9ebe1c..bcd49fd618b9ca140a85926e239802effba7c161 100644 (file)
@@ -655,6 +655,7 @@ static int read_next_mapping(
 int vconsole_convert_to_x11(const VCContext *vc, X11Context *ret) {
         _cleanup_fclose_ FILE *f = NULL;
         const char *map;
+        X11Context xc;
         int r;
 
         assert(vc);
@@ -672,15 +673,12 @@ int vconsole_convert_to_x11(const VCContext *vc, X11Context *ret) {
 
         for (unsigned n = 0;;) {
                 _cleanup_strv_free_ char **a = NULL;
-                X11Context xc;
 
                 r = read_next_mapping(map, 5, UINT_MAX, f, &n, &a);
                 if (r < 0)
                         return r;
-                if (r == 0) {
-                        *ret = (X11Context) {};
-                        return 0;
-                }
+                if (r == 0)
+                        break;
 
                 if (!streq(vc->keymap, a[0]))
                         continue;
@@ -697,6 +695,42 @@ int vconsole_convert_to_x11(const VCContext *vc, X11Context *ret) {
 
                 return x11_context_copy(ret, &xc);
         }
+
+        /* No custom mapping has been found, see if the keymap is a converted one. In such case deducing the
+         * corresponding x11 layout is easy. */
+        _cleanup_free_ char *xlayout = NULL, *converted = NULL;
+        char *xvariant;
+
+        xlayout = strdup(vc->keymap);
+        if (!xlayout)
+                return -ENOMEM;
+        xvariant = strchr(xlayout, '-');
+        if (xvariant) {
+                xvariant[0] = '\0';
+                xvariant++;
+        }
+
+        /* Note: by default we use keyboard model "microsoftpro" which should be equivalent to "pc105" but
+         * with the internet/media key mapping added. */
+        xc = (X11Context) {
+                .layout  = xlayout,
+                .model   = (char*) "microsoftpro",
+                .variant = xvariant,
+                .options = (char*) "terminate:ctrl_alt_bksp",
+        };
+
+        /* This sanity check seems redundant with the verification of the X11 layout done on the next
+         * step. However xkbcommon is an optional dependency hence the verification might be a NOP.  */
+        r = find_converted_keymap(&xc, &converted);
+        if (r < 0)
+                return r;
+
+        if (r == 0 || x11_context_verify(&xc) < 0) {
+                *ret = (X11Context) {};
+                return 0;
+        }
+
+        return x11_context_copy(ret, &xc);
 }
 
 int find_converted_keymap(const X11Context *xc, char **ret) {