xkb: Fix default key types

Before this commit, using xkbcomp to compile a keymap that omits the key
type `ALPHABETIC` leads to either a wrong serialization (`-xkb` output)
or a server error such as:

    X Error of failed request:  BadValue (integer parameter out of range for operation)
      Major opcode of failed request:  135 (XKEYBOARD)
      Minor opcode of failed request:  9 (XkbSetMap)
      Value in failed request:  0x8010202
      Serial number of failed request:  55
      Current serial number in output stream:  60

Indeed, there is an error in the default key maps: the second field of
`XkbKTMapEntryRec` if a level index, not a modifier mask. While it worked
*by chance* for `ShiftMask` (e.g. the `TWO_LEVEL` type), it does not work
for `LockMask` (e.g. the `ALPHABETIC` type).

Fixed by using the correct level indices.

It probably went unnoticed for so long because xkbcomp and libxkbcommon
< 1.12 always use all the key types, while libxkbcommon ≥ 1.12 does not
serialize unused key types. The latter case may result in a keymap that
omits `ALPHABETIC`, e.g. with keyboard layouts with 4+ levels which use
alternative key types such as `FOUR_LEVEL_ALPHABETIC`.

Signed-off-by: Pierre Le Marre <dev@wismill.eu>
Part-of: <https://gitlab.freedesktop.org/xorg/lib/libx11/-/merge_requests/292>
This commit is contained in:
Pierre Le Marre 2025-10-14 10:26:17 +02:00
parent 76a930ca99
commit ff409a48f9

View file

@ -40,12 +40,12 @@ THE USE OR PERFORMANCE OF THIS SOFTWARE.
#define mapSize(m) (sizeof(m)/sizeof(XkbKTMapEntryRec))
static XkbKTMapEntryRec map2Level[] = {
{ True, ShiftMask, {1, ShiftMask, 0} }
{ True, 1, {ShiftMask, ShiftMask, 0} }
};
static XkbKTMapEntryRec mapAlpha[] = {
{ True, ShiftMask, {1, ShiftMask, 0} },
{ True, LockMask, {0, LockMask, 0} }
{ True, 1, {ShiftMask, ShiftMask, 0} },
{ True, 1, { LockMask, LockMask, 0} }
};
static XkbModsRec preAlpha[] = {
@ -55,8 +55,8 @@ static XkbModsRec preAlpha[] = {
#define NL_VMOD_MASK 0
static XkbKTMapEntryRec mapKeypad[] = {
{ True, ShiftMask, { 1, ShiftMask, 0 } },
{ False, 0, { 1, 0, NL_VMOD_MASK } }
{ True, 1, { ShiftMask, ShiftMask, 0 } },
{ False, 1, { 0, 0, NL_VMOD_MASK } }
};
static XkbKeyTypeRec canonicalTypes[XkbNumRequiredTypes] = {
@ -118,17 +118,9 @@ XkbInitCanonicalKeyTypes(XkbDescPtr xkb, unsigned which, int keypadVMod)
type = &to[XkbKeypadIndex];
if ((keypadVMod >= 0) && (keypadVMod < XkbNumVirtualMods) &&
(rtrn == Success)) {
/* Replace the NL_VMOD_MASK placeholder */
type->mods.vmods = (1 << keypadVMod);
type->map[0].active = True;
type->map[0].mods.mask = ShiftMask;
type->map[0].mods.real_mods = ShiftMask;
type->map[0].mods.vmods = 0;
type->map[0].level = 1;
type->map[1].active = False;
type->map[1].mods.mask = 0;
type->map[1].mods.real_mods = 0;
type->map[1].mods.vmods = (1 << keypadVMod);
type->map[1].level = 1;
}
}
return Success;