locale: convert generated vconsole keymap to x11 layout automatically

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.
This commit is contained in:
Franck Bui 2023-04-20 09:27:52 +02:00
parent 3c7012cdda
commit c821ad7d60

View 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) {