diff options
author | Wismill <dev@wismill.eu> | 2023-05-01 22:30:41 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-01 23:30:41 +0300 |
commit | 5b5b67f28ccfe1fe69ec5569c90f1752de323a08 (patch) | |
tree | 09c02e8aa8d7fe495109823ee5848cdc01becb96 /test | |
parent | 0e9c2ec97e8f5280171002834243104b9f53a772 (diff) | |
download | libxkbcommon-5b5b67f28ccfe1fe69ec5569c90f1752de323a08.tar.gz libxkbcommon-5b5b67f28ccfe1fe69ec5569c90f1752de323a08.tar.bz2 libxkbcommon-5b5b67f28ccfe1fe69ec5569c90f1752de323a08.zip |
Add support for modmap None (#291)
Unlike current xkbcommon, X11’s xkbcomp allows to remove entries in
the modifiers’ map using “modifier_map None { … }”.
“None” is translated to the special value “XkbNoModifier” defined in
“X11/extensions/XKB.h”. Then it relies on the fact that in "CopyModMapDef",
the following code:
1U << entry->modifier
ends up being zero when “entry->modifier” is “XkbNoModifier” (i.e. 0xFF).
Indeed, it relies on the overflow behaviour of the left shift, which in
practice resolves to use only the 5 low bits of the shift amount, i.e.
0x1F here. Then the result of “1U << 0xFF” is cast to “char”, i.e. 0.
This is a good trick but too magical, so in libxkbcommon we will use
an explicit test against our new constant XKB_MOD_NONE.
Diffstat (limited to 'test')
-rw-r--r-- | test/data/keymaps/modmap-none.xkb | 148 | ||||
-rw-r--r-- | test/filecomp.c | 1 | ||||
-rw-r--r-- | test/modifiers.c | 160 |
3 files changed, 309 insertions, 0 deletions
diff --git a/test/data/keymaps/modmap-none.xkb b/test/data/keymaps/modmap-none.xkb new file mode 100644 index 0000000..a99b200 --- /dev/null +++ b/test/data/keymaps/modmap-none.xkb @@ -0,0 +1,148 @@ +xkb_keymap { +xkb_keycodes "test" { + minimum = 8; + maximum = 255; + <LVL3> = 92; + <LFSH> = 50; + <RTSH> = 62; + <LALT> = 64; + <RALT> = 108; + <LWIN> = 133; + <RWIN> = 134; + <LCTL> = 37; + <RCTL> = 105; + <CAPS> = 66; + + <AD01> = 24; + <AD02> = 25; + <AD03> = 26; + <AD04> = 27; + <AD05> = 28; + <AD06> = 29; + <AD07> = 30; + <AD08> = 31; + <AD09> = 32; +}; + +xkb_types "complete" { + type "ONE_LEVEL" { + modifiers= none; + level_name[Level1]= "Any"; + }; + type "TWO_LEVEL" { + modifiers= Shift; + map[Shift]= 2; + level_name[1]= "Base"; + level_name[2]= "Shift"; + }; +}; +xkb_compatibility "complete" { + interpret.useModMapMods= AnyLevel; + interpret.repeat= False; + interpret.locking= False; + + interpret Any+AnyOf(all) { + action= SetMods(modifiers=modMapMods,clearLocks); + }; +}; +xkb_symbols { + name[group1]="Test"; + + // Reset modmap with a key with empty modmap + key <LVL3> { [VoidSymbol] }; + modmap None { <LVL3> }; + + // Reset modmap with one key + key <LFSH> { [Shift_L] }; + modmap Shift { <LFSH> }; + modmap none { <LFSH> }; + + // Reset modmap with one symbol + key <RTSH> { [Shift_R] }; + modmap Shift { Shift_R }; + modmap NONE { Shift_R }; + + // Cycle + key <LWIN> { [Super_L] }; + modmap Mod4 { <LWIN> }; + modmap None { <LWIN> }; + modmap Mod4 { <LWIN> }; + + // Cycle + key <RWIN> { [Super_R] }; + modmap Mod4 { <RWIN> }; + modmap None { <RWIN> }; + modmap Mod4 { Super_R }; + + // Mix keycode and keysym + key <LCTL> { [Control_L] }; + modmap Control { Control_L }; + modmap None { <LCTL> }; + + // Mix keycode and keysym + key <RCTL> { [Control_R] }; + modmap Control { <RCTL> }; + modmap None { Control_R }; + + // Re-set with different modifier + key <LALT> { [Alt_L] }; + modmap Mod2 { <LALT> }; + modmap None { <LALT> }; + modmap Mod1 { <LALT> }; + + // Re-set with different modifier with both key and keysym + key <RALT> { [ISO_Level3_Shift] }; + modmap Mod1 { <RALT> }; // Mod1 + modmap None { <RALT> }; // None + modmap Mod2 { <RALT> }; // Mod2 + modmap Mod3 { ISO_Level3_Shift }; // Mod2 | Mod3 + modmap None { ISO_Level3_Shift }; // Mod2 + modmap Mod5 { ISO_Level3_Shift }; // Mod2 | Mod5 + + // Re-set with different modifier with both key and keysym + key <CAPS> { [Caps_Lock] }; + modmap Mod1 { Caps_Lock }; // Mod1 + modmap None { <CAPS> }; // Mod1 + modmap None { Caps_Lock }; // None + modmap Lock { <CAPS> }; // Lock + + // Merge modes + key <AD01> { [q] }; + modMap Mod1 { <AD01> }; + augment modMap None { <AD01> }; + + key <AD02> { [w] }; + modMap Mod2 { <AD02> }; + override modMap None { <AD02> }; + + key <AD03> { [e] }; + modMap Mod3 { <AD03> }; + replace modMap None { <AD03> }; + + key <AD04> { [r] }; + modMap Mod1 { <AD04> }; + augment modMap None { r }; + + key <AD05> { [t] }; + modMap Mod2 { <AD05> }; + replace modMap None { t }; + + key <AD06> { [y] }; + modMap Mod3 { <AD06> }; + override modMap None { y }; + + key <AD07> { [u] }; + modMap Mod1 { <AD07> }; + replace key <AD07> { [U] }; // Won’t affect the modMap + + key <AD08> { [i] }; + modMap Mod2 { i, I }; + replace key <AD08> { [I] }; + modMap None { i }; // Does not resolve + + key <AD09> { [1] }; + modMap Mod3 { 1, 2 }; + override key <AD09> { [NoSymbol, 2] }; + modMap None { 1 }; +}; +}; diff --git a/test/filecomp.c b/test/filecomp.c index 827a19c..5fc7477 100644 --- a/test/filecomp.c +++ b/test/filecomp.c @@ -47,6 +47,7 @@ main(void) assert(test_file(ctx, "keymaps/no-types.xkb")); assert(test_file(ctx, "keymaps/quartz.xkb")); assert(test_file(ctx, "keymaps/no-aliases.xkb")); + assert(test_file(ctx, "keymaps/modmap-none.xkb")); assert(!test_file(ctx, "keymaps/divide-by-zero.xkb")); assert(!test_file(ctx, "keymaps/bad.xkb")); diff --git a/test/modifiers.c b/test/modifiers.c new file mode 100644 index 0000000..807c015 --- /dev/null +++ b/test/modifiers.c @@ -0,0 +1,160 @@ +/* + * Copyright © 2023 Pierre Le Marre <dev@wismill.eu> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + */ + +#include "config.h" + +#include <assert.h> +#include <stdlib.h> + +#include "test.h" +#include "keymap.h" + +// Standard real modifier masks +#define ShiftMask (1 << 0) +#define LockMask (1 << 1) +#define ControlMask (1 << 2) +#define Mod1Mask (1 << 3) +#define Mod2Mask (1 << 4) +#define Mod3Mask (1 << 5) +#define Mod4Mask (1 << 6) +#define Mod5Mask (1 << 7) +#define NoModifier 0 + +static void +test_modmap_none(void) +{ + struct xkb_context *context = test_get_context(0); + struct xkb_keymap *keymap; + const struct xkb_key *key; + xkb_keycode_t keycode; + + keymap = test_compile_file(context, "keymaps/modmap-none.xkb"); + assert(keymap); + + keycode = xkb_keymap_key_by_name(keymap, "LVL3"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == NoModifier); + + keycode = xkb_keymap_key_by_name(keymap, "LFSH"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == NoModifier); + + keycode = xkb_keymap_key_by_name(keymap, "RTSH"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == NoModifier); + + keycode = xkb_keymap_key_by_name(keymap, "LWIN"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod4Mask); + + keycode = xkb_keymap_key_by_name(keymap, "RWIN"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod4Mask); + + keycode = xkb_keymap_key_by_name(keymap, "LCTL"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == ControlMask); + + keycode = xkb_keymap_key_by_name(keymap, "RCTL"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == ControlMask); + + keycode = xkb_keymap_key_by_name(keymap, "LALT"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod1Mask); + + keycode = xkb_keymap_key_by_name(keymap, "RALT"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == (Mod2Mask | Mod5Mask)); + + keycode = xkb_keymap_key_by_name(keymap, "CAPS"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == LockMask); + + keycode = xkb_keymap_key_by_name(keymap, "AD01"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod1Mask); + + keycode = xkb_keymap_key_by_name(keymap, "AD02"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == NoModifier); + + keycode = xkb_keymap_key_by_name(keymap, "AD03"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == NoModifier); + + keycode = xkb_keymap_key_by_name(keymap, "AD04"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod1Mask); + + keycode = xkb_keymap_key_by_name(keymap, "AD05"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod2Mask); + + keycode = xkb_keymap_key_by_name(keymap, "AD06"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod3Mask); + + keycode = xkb_keymap_key_by_name(keymap, "AD07"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod1Mask); + + keycode = xkb_keymap_key_by_name(keymap, "AD08"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod2Mask); + + keycode = xkb_keymap_key_by_name(keymap, "AD09"); + assert(keycode != XKB_KEYCODE_INVALID); + key = XkbKey(keymap, keycode); + assert(key->modmap == Mod3Mask); + + xkb_keymap_unref(keymap); + xkb_context_unref(context); +} + +int +main(void) +{ + test_modmap_none(); + + return 0; +} |