Merge pull request #27355 from fbuihuu/kbd-improve-vc2x11-conversion
locale: improve vc -> x11 keyboard conversion
This commit is contained in:
@@ -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,47 @@ 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 && xc.variant) {
|
||||
/* If we still haven't find a match, try with no variant, it's still better than nothing. */
|
||||
xc.variant = NULL;
|
||||
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) {
|
||||
@@ -817,12 +856,12 @@ int find_legacy_keymap(const X11Context *xc, char **ret) {
|
||||
* matches just the first layout.
|
||||
*/
|
||||
|
||||
l = strndup(xc->layout, strcspn(xc->layout, ","));
|
||||
l = strdupcspn(xc->layout, ",");
|
||||
if (!l)
|
||||
return -ENOMEM;
|
||||
|
||||
if (!isempty(xc->variant)) {
|
||||
v = strndup(xc->variant, strcspn(xc->variant, ","));
|
||||
v = strdupcspn(xc->variant, ",");
|
||||
if (!v)
|
||||
return -ENOMEM;
|
||||
}
|
||||
@@ -856,8 +895,17 @@ int x11_convert_to_vconsole(const X11Context *xc, VCContext *ret) {
|
||||
}
|
||||
|
||||
r = find_converted_keymap(xc, &keymap);
|
||||
if (r == 0)
|
||||
if (r == 0) {
|
||||
r = find_legacy_keymap(xc, &keymap);
|
||||
if (r == 0 && xc->variant)
|
||||
/* If we still haven't find a match, try with no variant, it's still better than
|
||||
* nothing. */
|
||||
r = find_converted_keymap(
|
||||
&(X11Context) {
|
||||
.layout = xc->layout,
|
||||
},
|
||||
&keymap);
|
||||
}
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
|
||||
@@ -44,6 +44,7 @@ TEST(find_converted_keymap) {
|
||||
|
||||
assert_se(r == 1);
|
||||
assert_se(streq(ans, "pl"));
|
||||
ans = mfree(ans);
|
||||
|
||||
assert_se(find_converted_keymap(
|
||||
&(X11Context) {
|
||||
@@ -73,6 +74,7 @@ TEST(find_legacy_keymap) {
|
||||
TEST(vconsole_convert_to_x11) {
|
||||
_cleanup_(x11_context_clear) X11Context xc = {};
|
||||
_cleanup_(vc_context_clear) VCContext vc = {};
|
||||
int r;
|
||||
|
||||
log_info("/* test empty keymap */");
|
||||
assert_se(vconsole_convert_to_x11(&vc, &xc) >= 0);
|
||||
@@ -111,6 +113,34 @@ TEST(vconsole_convert_to_x11) {
|
||||
assert_se(vconsole_convert_to_x11(&vc, &xc) >= 0);
|
||||
assert_se(streq(xc.layout, "us"));
|
||||
assert_se(xc.variant == NULL);
|
||||
x11_context_clear(&xc);
|
||||
|
||||
/* "gh" has no mapping in kbd-model-map and kbd provides a converted keymap for this layout. */
|
||||
log_info("/* test with a converted keymap (gh:) */");
|
||||
assert_se(free_and_strdup(&vc.keymap, "gh") >= 0);
|
||||
r = vconsole_convert_to_x11(&vc, &xc);
|
||||
if (r == 0) {
|
||||
log_info("Skipping rest of %s: keymaps are not installed", __func__);
|
||||
return;
|
||||
}
|
||||
assert_se(r > 0);
|
||||
assert_se(streq(xc.layout, "gh"));
|
||||
assert_se(xc.variant == NULL);
|
||||
x11_context_clear(&xc);
|
||||
|
||||
log_info("/* test with converted keymap and with a known variant (gh:ewe) */");
|
||||
assert_se(free_and_strdup(&vc.keymap, "gh-ewe") >= 0);
|
||||
assert_se(vconsole_convert_to_x11(&vc, &xc) > 0);
|
||||
assert_se(streq(xc.layout, "gh"));
|
||||
assert_se(streq(xc.variant, "ewe"));
|
||||
x11_context_clear(&xc);
|
||||
|
||||
log_info("/* test with converted keymap and with an unknown variant (gh:ewe) */");
|
||||
assert_se(free_and_strdup(&vc.keymap, "gh-foobar") > 0);
|
||||
assert_se(vconsole_convert_to_x11(&vc, &xc) > 0);
|
||||
assert_se(streq(xc.layout, "gh"));
|
||||
assert_se(xc.variant == NULL);
|
||||
x11_context_clear(&xc);
|
||||
}
|
||||
|
||||
TEST(x11_convert_to_vconsole) {
|
||||
|
||||
@@ -273,15 +273,15 @@ test_vc_keymap() {
|
||||
assert_in "XKBVARIANT=intl" "$vc"
|
||||
assert_in "XKBOPTIONS=terminate:ctrl_alt_bksp" "$vc"
|
||||
elif [[ "$i" =~ ^us-.* ]]; then
|
||||
assert_in "X11 Layout: .unset." "$output"
|
||||
assert_not_in "X11 Model:" "$output"
|
||||
assert_not_in "X11 Variant:" "$output"
|
||||
assert_not_in "X11 Options:" "$output"
|
||||
assert_in "X11 Layout: us" "$output"
|
||||
assert_in "X11 Model: microsoftpro" "$output"
|
||||
assert_in "X11 Variant:" "$output"
|
||||
assert_in "X11 Options: terminate:ctrl_alt_bksp" "$output"
|
||||
|
||||
assert_not_in "XKBLAYOUT" "$vc"
|
||||
assert_not_in "XKBMODEL" "$vc"
|
||||
assert_not_in "XKBVARIANT" "$vc"
|
||||
assert_not_in "XKBOPTIONS" "$vc"
|
||||
assert_in "XKBLAYOUT=us" "$vc"
|
||||
assert_in "XKBMODEL=microsoftpro" "$vc"
|
||||
assert_in "XKBVARIANT=" "$vc"
|
||||
assert_in "XKBOPTIONS=terminate:ctrl_alt_bksp" "$vc"
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
Reference in New Issue
Block a user