xkbcomp: handle empty keymaps We should handle empty xkb_keycode and xkb_symbol sections, since xkbcomp handles them, and apparently XQuartz uses it. There are also files for it in xkeyboard-config (rules=base model=empty layout=empty, which translate to keycodes/empty and symbols/empty). https://bugs.freedesktop.org/show_bug.cgi?id=67654 Reported-By: Gatis Paeglis <gatis.paeglis@digia.com> Signed-off-by: Ran Benita <ran234@gmail.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
diff --git a/src/xkbcomp/keycodes.c b/src/xkbcomp/keycodes.c
index 44e11bc..59916b7 100644
--- a/src/xkbcomp/keycodes.c
+++ b/src/xkbcomp/keycodes.c
@@ -231,7 +231,10 @@ InitKeyNamesInfo(KeyNamesInfo *info, struct xkb_context *ctx)
{
memset(info, 0, sizeof(*info));
info->ctx = ctx;
- info->min_key_code = XKB_KEYCODE_MAX;
+ info->min_key_code = XKB_KEYCODE_INVALID;
+#if XKB_KEYCODE_INVALID < XKB_KEYCODE_MAX
+#error "Hey, you can't be changing stuff like that."
+#endif
}
static xkb_keycode_t
@@ -606,15 +609,26 @@ CopyKeyNamesToKeymap(struct xkb_keymap *keymap, KeyNamesInfo *info)
keymap->keycodes_section_name = strdup_safe(info->name);
XkbEscapeMapName(keymap->keycodes_section_name);
- keymap->min_key_code = info->min_key_code;
- keymap->max_key_code = info->max_key_code;
+ if (info->min_key_code != XKB_KEYCODE_INVALID) {
+ keymap->min_key_code = info->min_key_code;
+ keymap->max_key_code = info->max_key_code;
+ }
+ else {
+ /*
+ * If the keymap has no keys, let's just use the safest pair
+ * we know.
+ */
+ keymap->min_key_code = 8;
+ keymap->max_key_code = 255;
+ }
- /* Copy key names. */
- keymap->keys = calloc(info->max_key_code + 1, sizeof(*keymap->keys));
- for (kc = info->min_key_code; kc <= info->max_key_code; kc++) {
+ keymap->keys = calloc(keymap->max_key_code + 1, sizeof(*keymap->keys));
+ for (kc = keymap->min_key_code; kc <= keymap->max_key_code; kc++)
keymap->keys[kc].keycode = kc;
+
+ /* Copy key names. */
+ for (kc = info->min_key_code; kc <= info->max_key_code; kc++)
keymap->keys[kc].name = darray_item(info->key_names, kc);
- }
/*
* Do some sanity checking on the aliases. We can't do it before
diff --git a/src/xkbcomp/symbols.c b/src/xkbcomp/symbols.c
index 5cf68d9..6033264 100644
--- a/src/xkbcomp/symbols.c
+++ b/src/xkbcomp/symbols.c
@@ -1619,9 +1619,6 @@ CompileSymbols(XkbFile *file, struct xkb_keymap *keymap,
HandleSymbolsFile(&info, file, merge);
- if (darray_empty(info.keys))
- goto err_info;
-
if (info.errorCount != 0)
goto err_info;
diff --git a/test/data/keycodes/empty b/test/data/keycodes/empty
new file mode 100644
index 0000000..eedc943
--- /dev/null
+++ b/test/data/keycodes/empty
@@ -0,0 +1,4 @@
+default xkb_keycodes "empty" {
+ minimum= 8;
+ maximum= 255;
+};
diff --git a/test/data/symbols/empty b/test/data/symbols/empty
new file mode 100644
index 0000000..cae3303
--- /dev/null
+++ b/test/data/symbols/empty
@@ -0,0 +1,4 @@
+default partial alphanumeric_keys modifier_keys
+xkb_symbols "basic" {
+ name[Group1]= "Empty";
+};
diff --git a/test/data/sync.sh b/test/data/sync.sh
index 7f2538a..12ed434 100755
--- a/test/data/sync.sh
+++ b/test/data/sync.sh
@@ -32,9 +32,12 @@ for file in \
symbols/rupeesign \
symbols/kpdl \
symbols/de \
+ symbols/ch \
+ symbols/empty \
keycodes/xfree86 \
keycodes/aliases \
keycodes/evdev \
+ keycodes/empty \
types/complete \
types/pc \
types/basic \
diff --git a/test/rulescomp.c b/test/rulescomp.c
index 97b4315..60e7a4c 100644
--- a/test/rulescomp.c
+++ b/test/rulescomp.c
@@ -231,6 +231,10 @@ main(int argc, char *argv[])
assert(!test_rmlvo_env(ctx, "broken", "what-on-earth", "invalid", "", "",
KEY_A, BOTH, XKB_KEY_a, FINISH));
+ /* Ensure a keymap with an empty xkb_keycodes compiles fine. */
+ assert(test_rmlvo_env(ctx, "base", "empty", "empty", "", "",
+ KEY_A, BOTH, XKB_KEY_NoSymbol, FINISH));
+
xkb_context_unref(ctx);
ctx = test_get_context(0);