From 958c35c2a9e6b7b86d34b787127619741eb6b45e Mon Sep 17 00:00:00 2001 From: Pierre Le Marre Date: Mon, 13 Jan 2025 15:20:47 +0100 Subject: [PATCH 1/2] symbols: Add tests for key merge modes (keysyms/actions) This commit adds tests for merging various key configurations: - With/without keysyms/actions - Single/multiple keysyms/actions per level We test all the merge modes for including a map (global) as well as directly on the keys (local): - default (global: include, local: implicit) - augment - override - replace The tests data are generated with: - A Python script `scripts/update-merge-modes-tests.py` for keycodes and symbols data. Use `--debug` for extra comments to help debugging. The script can optionally generate C headers for alternative key sequence tests, that were used before implementing golden tests. The latter tests are not used anymore (duplicate with golden tests) but their generator is kept for now, as they can still be useful for debugging or writing similar tests. - The `merge-modes` test generates its own keymap files for golden tests, using: `build/test-merge-modes update`. It can also replace them with the obtained output rather than the expected one using `build/test-merge-modes update-obtained`, which is very useful for debugging. --- meson.build | 11 + scripts/update-merge-modes-tests.py | 1759 ++++++++++++++++++++ test/buffercomp.c | 3 +- test/common.c | 66 + test/data/keycodes/merge_modes | 160 ++ test/data/keycodes/merge_modes.jinja | 12 + test/data/keymaps/merge-modes/augment.xkb | 782 +++++++++ test/data/keymaps/merge-modes/default.xkb | 786 +++++++++ test/data/keymaps/merge-modes/override.xkb | 786 +++++++++ test/data/keymaps/merge-modes/replace.xkb | 759 +++++++++ test/data/symbols/merge_modes | 1460 ++++++++++++++++ test/data/symbols/merge_modes.jinja | 56 + test/merge_modes.c | 76 + test/merge_modes.h | 159 ++ test/test.h | 27 +- 15 files changed, 6895 insertions(+), 7 deletions(-) create mode 100755 scripts/update-merge-modes-tests.py create mode 100644 test/data/keycodes/merge_modes create mode 100644 test/data/keycodes/merge_modes.jinja create mode 100644 test/data/keymaps/merge-modes/augment.xkb create mode 100644 test/data/keymaps/merge-modes/default.xkb create mode 100644 test/data/keymaps/merge-modes/override.xkb create mode 100644 test/data/keymaps/merge-modes/replace.xkb create mode 100644 test/data/symbols/merge_modes create mode 100644 test/data/symbols/merge_modes.jinja create mode 100644 test/merge_modes.c create mode 100644 test/merge_modes.h diff --git a/meson.build b/meson.build index 51a6d342c..47d0da8f9 100644 --- a/meson.build +++ b/meson.build @@ -786,6 +786,17 @@ test( executable('test-buffercomp', 'test/buffercomp.c', dependencies: test_dep), env: test_env, ) +test( + 'merge-modes', + executable( + 'test-merge-modes', + 'test/merge_modes.c', + 'test/merge_modes.h', + 'src/messages-codes.h', + dependencies: test_dep + ), + env: test_env, +) test( 'log', executable('test-log', 'test/log.c', dependencies: test_dep), diff --git a/scripts/update-merge-modes-tests.py b/scripts/update-merge-modes-tests.py new file mode 100755 index 000000000..17a7a2b2d --- /dev/null +++ b/scripts/update-merge-modes-tests.py @@ -0,0 +1,1759 @@ +#!/usr/bin/env python3 + +""" +This script generate tests for symbols. +""" + +from __future__ import annotations + +import argparse +import dataclasses +import itertools +from abc import ABCMeta, abstractmethod +from dataclasses import dataclass +from enum import Flag, IntFlag, auto, unique +from pathlib import Path +from typing import Any, ClassVar, Iterable, Iterator, NewType, Self + +import jinja2 + +SCRIPT = Path(__file__) +LINUX_EVENT_CODES = ( + None, + "ESC", + "1", + "2", + "3", + "4", + "5", + "6", + "7", + "8", + "9", + "0", + "MINUS", + "EQUAL", + "BACKSPACE", + "TAB", + "Q", + "W", + "E", + "R", + "T", + "Y", + "U", + "I", + "O", + "P", + "LEFTBRACE", + "RIGHTBRACE", + "ENTER", + "LEFTCTRL", + "A", + "S", + "D", + "F", + "G", + "H", + "J", + "K", + "L", + "SEMICOLON", + "APOSTROPHE", + "GRAVE", + "LEFTSHIFT", + "BACKSLASH", + "Z", + "X", + "C", + "V", + "B", + "N", + "M", + "COMMA", + "DOT", + "SLASH", + "RIGHTSHIFT", + "KPASTERISK", + "LEFTALT", + "SPACE", + "CAPSLOCK", + "F1", + "F2", + "F3", + "F4", + "F5", + "F6", + "F7", + "F8", + "F9", + "F10", + "NUMLOCK", + "SCROLLLOCK", + "KP7", + "KP8", + "KP9", + "KPMINUS", + "KP4", + "KP5", + "KP6", + "KPPLUS", + "KP1", + "KP2", + "KP3", + "KP0", + "KPDOT", + None, + "ZENKAKUHANKAKU", + "102ND", + "F11", + "F12", + "RO", + "KATAKANA", + "HIRAGANA", + "HENKAN", + "KATAKANAHIRAGANA", + "MUHENKAN", + "KPJPCOMMA", + "KPENTER", + "RIGHTCTRL", + "KPSLASH", + "SYSRQ", + "RIGHTALT", + "LINEFEED", + "HOME", + "UP", + "PAGEUP", + "LEFT", + "RIGHT", + "END", + "DOWN", + "PAGEDOWN", + "INSERT", + "DELETE", + "MACRO", + "MUTE", + "VOLUMEDOWN", + "VOLUMEUP", + "POWER", + "KPEQUAL", + "KPPLUSMINUS", + "PAUSE", + "SCALE", + "KPCOMMA", + "HANGEUL", + "HANJA", + "YEN", + "LEFTMETA", + "RIGHTMETA", + "COMPOSE", + "STOP", + "AGAIN", + "PROPS", + "UNDO", + "FRONT", + "COPY", + "OPEN", + "PASTE", + "FIND", + "CUT", + "HELP", + "MENU", + "CALC", + "SETUP", + "SLEEP", + "WAKEUP", + "FILE", + "SENDFILE", + "DELETEFILE", + "XFER", + "PROG1", + "PROG2", + "WWW", + "MSDOS", + "COFFEE", + "DIRECTION", + "CYCLEWINDOWS", + "MAIL", + "BOOKMARKS", + "COMPUTER", + "BACK", + "FORWARD", + "CLOSECD", + "EJECTCD", + "EJECTCLOSECD", + "NEXTSONG", + "PLAYPAUSE", + "PREVIOUSSONG", + "STOPCD", + "RECORD", + "REWIND", + "PHONE", + "ISO", + "CONFIG", + "HOMEPAGE", + "REFRESH", + "EXIT", + "MOVE", + "EDIT", + "SCROLLUP", + "SCROLLDOWN", + "KPLEFTPAREN", + "KPRIGHTPAREN", + "NEW", + "REDO", + "F13", + "F14", + "F15", + "F16", + "F17", + "F18", + "F19", + "F20", + "F21", + "F22", + "F23", + "F24", + None, + None, + None, + None, + None, + "PLAYCD", + "PAUSECD", + "PROG3", + "PROG4", + "DASHBOARD", + "SUSPEND", + "CLOSE", + "PLAY", + "FASTFORWARD", +) + + +Comment = NewType("Comment", str) + + +def is_not_comment(x: Any) -> bool: + return not isinstance(x, str) + + +@dataclass(frozen=True) +class KeyCode: + _evdev: str + _xkb: str + + @property + def c(self) -> str: + return f"KEY_{self._evdev}" + + @property + def xkb(self) -> str: + return f"<{self._xkb}>" + + +class Keysym(str): + @property + def c(self) -> str: + return f"XKB_KEY_{self}" + + @classmethod + def parse(cls, raw: str | None) -> Self: + if not raw: + return cls("NoSymbol") + else: + return cls(raw) + + +NoSymbol = Keysym("NoSymbol") + + +class Modifier(IntFlag): + NoModifier = 0 + Shift = 1 << 0 + Lock = 1 << 1 + Control = 1 << 2 + Mod1 = 1 << 3 + Mod2 = 1 << 4 + Mod3 = 1 << 5 + Mod4 = 1 << 6 + Mod5 = 1 << 7 + LevelThree = Mod5 + + def __iter__(self) -> Iterator[Self]: + for m in self.__class__: + if m & self: + yield m + + def __str__(self) -> str: + return "+".join(m.name for m in self) + + +class Action(metaclass=ABCMeta): + @abstractmethod + def __bool__(self) -> bool: ... + + @classmethod + def parse(cls, raw: Any) -> Self: + if raw is None: + return GroupAction.parse(None) + elif isinstance(raw, Modifier): + return ModAction.parse(raw) + elif isinstance(raw, int): + return GroupAction.parse(raw) + else: + raise ValueError(raw) + + @abstractmethod + def action_to_keysym(self, index: int, level: int) -> Keysym: ... + + +@dataclass +class GroupAction(Action): + """ + SetGroup or NoAction + """ + + group: int + keysyms: ClassVar[dict[tuple[int, int, int], Keysym]] = { + (2, 0, 0): Keysym("a"), + (2, 0, 1): Keysym("A"), + (2, 1, 0): Keysym("b"), + (2, 1, 1): Keysym("B"), + (3, 0, 0): Keysym("Greek_alpha"), + (3, 0, 1): Keysym("Greek_ALPHA"), + (3, 1, 0): Keysym("Greek_beta"), + (3, 1, 1): Keysym("Greek_BETA"), + } + + def __str__(self) -> str: + if self.group > 0: + return f"SetGroup(group={self.group})" + else: + return "NoAction()" + + def __bool__(self) -> bool: + return bool(self.group) + + @classmethod + def parse(cls, raw: int | None) -> Self: + if not raw: + return cls(0) + else: + return cls(raw) + + def action_to_keysym(self, index: int, level: int) -> Keysym: + if not self.group: + return NoSymbol + else: + if ( + keysym := self.keysyms.get((self.group % 4, index % 2, level % 2)) + ) is None: + raise ValueError((self, index, level)) + return keysym + + +@dataclass +class ModAction(Action): + """ + SetMod or NoAction + """ + + mods: Modifier + keysyms: ClassVar[dict[tuple[Modifier, int, int], Keysym]] = { + (Modifier.Control, 0, 0): Keysym("x"), + (Modifier.Control, 0, 1): Keysym("X"), + (Modifier.Control, 1, 0): Keysym("y"), + (Modifier.Control, 1, 1): Keysym("Y"), + (Modifier.Mod5, 0, 0): Keysym("Greek_xi"), + (Modifier.Mod5, 0, 1): Keysym("Greek_XI"), + (Modifier.Mod5, 1, 0): Keysym("Greek_upsilon"), + (Modifier.Mod5, 1, 1): Keysym("Greek_UPSILON"), + } + + def __str__(self) -> str: + if self.mods is Modifier.NoModifier: + return "NoAction()" + else: + return f"SetMods(mods={self.mods})" + + def __bool__(self) -> bool: + return self.mods is Modifier.NoModifier + + @classmethod + def parse(cls, raw: Modifier | None) -> Self: + if not raw: + return cls(Modifier.NoModifier) + else: + return cls(raw) + + def action_to_keysym(self, index: int, level: int) -> Keysym: + if self.mods is Modifier.NoModifier: + return NoSymbol + else: + if (keysym := self.keysyms.get((self.mods, index % 2, level % 2))) is None: + raise ValueError((self, index, level)) + return keysym + + +@dataclass +class Level: + keysyms: tuple[Keysym, ...] + actions: tuple[Action, ...] + + @staticmethod + def _c(default: str, xs: Iterable[Any]) -> str: + match len(xs): + case 0: + return default + case 1: + return xs[0].c + case _: + return ", ".join(map(lambda x: x.c, xs)) + + @staticmethod + def _xkb(default: str, xs: Iterable[Any]) -> str: + match len(xs): + case 0: + return default + case 1: + return str(xs[0]) + case _: + return "{" + ", ".join(map(str, xs)) + "}" + + @classmethod + def has_empty_symbols(cls, keysyms: tuple[Keysym, ...]) -> bool: + return all(ks == NoSymbol for ks in keysyms) + + @property + def empty_symbols(self) -> bool: + return self.has_empty_symbols(self.keysyms) + + @property + def keysyms_c(self) -> str: + if not self.keysyms and self.actions: + return self._c( + NoSymbol.c, tuple(itertools.repeat(NoSymbol, len(self.actions))) + ) + return self._c(NoSymbol.c, self.keysyms) + + @property + def keysyms_xkb(self) -> str: + return self._xkb(NoSymbol, self.keysyms) + + @classmethod + def has_empty_actions(cls, actions: tuple[Action, ...]) -> bool: + return not any(actions) + + @property + def empty_actions(self) -> bool: + return self.has_empty_actions(self.actions) + + @property + def actions_xkb(self) -> str: + return self._xkb("NoAction()", self.actions) + + @classmethod + def Keysyms(cls, *keysyms: str | None) -> Self: + return cls.Mix(keysyms, ()) + + @classmethod + def Actions(cls, *actions: int | Modifier | None) -> Self: + return cls.Mix((), actions) + + @classmethod + def Mix( + cls, keysyms: tuple[str | None, ...], actions: tuple[int | Modifier | None,] + ) -> Self: + return cls(tuple(map(Keysym.parse, keysyms)), tuple(map(Action.parse, actions))) + + def add_keysyms(self, keep_actions: bool, level: int) -> Self: + return self.__class__( + keysyms=tuple( + a.action_to_keysym(index=k, level=level) + for k, a in enumerate(self.actions) + ), + actions=self.actions if keep_actions else (), + ) + + @property + def target_group(self) -> int: + for a in self.actions: + if isinstance(a, GroupAction) and a.group > 1: + return a.group + else: + return 0 + + @property + def target_level(self) -> int: + for a in self.actions: + if isinstance(a, ModAction) and a.mods: + match a.mods: + case Modifier.LevelThree: + return 2 + case _: + return 0 + else: + return 0 + + +@dataclass +class KeyEntry: + levels: tuple[Level, ...] + + def __init__(self, *levels: Level): + self.levels = levels + + @property + def xkb(self) -> Iterator[str]: + if not self.levels: + yield "" + return + keysyms = tuple(l.keysyms for l in self.levels) + has_keysyms = any(not Level.has_empty_symbols(s) for s in keysyms) + no_keysyms = all(not s for s in keysyms) + actions = tuple(l.actions for l in self.levels) + has_actions = any(not Level.has_empty_actions(a) for a in actions) + if has_keysyms or (not no_keysyms and not has_actions): + yield "[" + yield ", ".join(l.keysyms_xkb for l in self.levels) + yield "]" + if has_actions or no_keysyms: + if has_keysyms: + yield ", " + yield "[" + yield ", ".join(l.actions_xkb for l in self.levels) + yield "]" + + def add_keysyms(self, keep_actions: bool) -> Self: + return self.__class__( + *( + l.add_keysyms(keep_actions=keep_actions, level=k) + for k, l in enumerate(self.levels) + ) + ) + + +class TestType(IntFlag): + KeysymsOnly = auto() + ActionsOnly = auto() + KeysymsAndActions = auto() + All = ActionsOnly | KeysymsOnly | KeysymsAndActions + + +@dataclass +class TestId: + type: TestType + base: int = 0 + _last_base: ClassVar[int] = 0 + _max_type: ClassVar[int] = TestType.KeysymsAndActions >> 1 + _forbidden_keys: tuple[str, ...] = ("LEFTSHIFT", "RIGHTALT") + + def __post_init__(self): + if self.base == -1: + self.base = self.__class__._last_base + elif self.base < 0: + raise ValueError(self.base) + elif self.base == 0: + self.__class__._last_base += 1 + self.base = self.__class__._last_base + while not self.check_linux_keys(self._base_id): + self.__class__._last_base += 1 + self.base = self.__class__._last_base + else: + self.__class__._last_base = max(self.__class__._last_base, self.base) + assert self.linux_key, self + # print(self.base, self.id, self.xkb_key) + + def __hash__(self) -> int: + return self.id + + @property + def _base_id(self) -> int: + return (self.base - 1) * (self._max_type + 1) + 1 + + @property + def id(self) -> int: + # return (self.base << 2) | (self.type >> 1) + return self._base_id + (self.type >> 1) + + def with_type(self, type: TestType) -> Self: + return dataclasses.replace(self, type=type) + + @property + def xkb_key(self) -> str: + return f"T{self.id:0>3}" + + @classmethod + def check_linux_key(cls, idx: int) -> bool: + if idx >= len(LINUX_EVENT_CODES): + raise ValueError("Not enough Linux keys available!") + key: str | None = LINUX_EVENT_CODES[idx] + return bool(key) and key not in cls._forbidden_keys + + @classmethod + def check_linux_keys(cls, base_id) -> bool: + return all( + cls.check_linux_key(base_id + k) for k in range(0, cls._max_type + 1) + ) + + @property + def linux_key(self) -> str: + if self.id >= len(LINUX_EVENT_CODES): + raise ValueError("Not enough Linux keys available!") + return LINUX_EVENT_CODES[self.id] + + @property + def key(self) -> KeyCode: + return KeyCode(self.linux_key, self.xkb_key) + + +@unique +class Implementation(Flag): + x11 = auto() + xkbcommon = auto() + all = x11 | xkbcommon + + +@dataclass +class TestEntry: + id: TestId + key: KeyCode = dataclasses.field(init=False) + base: KeyEntry + update: KeyEntry + augment: KeyEntry + override: KeyEntry + replace: KeyEntry + types: TestType + implementations: Implementation + + group_keysyms: ClassVar[tuple[tuple[str, str], ...]] = ( + ("Ukrainian_i", "Ukrainian_I", "Ukrainian_yi", "Ukrainian_YI"), + ("ch", "Ch", "c_h", "C_h"), + ) + + def __init__( + self, + id: TestId | None, + base: KeyEntry, + update: KeyEntry, + augment: KeyEntry, + override: KeyEntry, + types: TestType = TestType.All, + replace: KeyEntry | None = None, + implementations: Implementation = Implementation.all, + ): + self.id = TestId(0, 0) if id is None else id + self.key = id.key + self.base = base + self.update = update + self.augment = augment + self.override = override + self.types = types + self.replace = self.update if replace is None else replace + self.implementations = implementations + + @property + def default(self) -> KeyEntry: + return self.override + + def add_keysyms(self, keep_actions: bool) -> Self: + types = TestType.KeysymsAndActions if keep_actions else TestType.KeysymsOnly + return dataclasses.replace( + self, + id=self.id.with_type(types), + base=self.base.add_keysyms(keep_actions=keep_actions), + update=self.update.add_keysyms(keep_actions=keep_actions), + augment=self.augment.add_keysyms(keep_actions=keep_actions), + override=self.override.add_keysyms(keep_actions=keep_actions), + replace=self.replace.add_keysyms(keep_actions=keep_actions), + types=types, + ) + + @classmethod + def alt_keysym(cls, group: int, level: int) -> Keysym: + return Keysym(cls.group_keysyms[group % 2][level % 4]) + + @classmethod + def alt_keysyms(cls, group: int) -> Iterator[Keysym]: + for keysym in cls.group_keysyms[group % 2]: + yield Keysym(keysym) + + +@dataclass +class TestGroup: + name: str + tests: tuple[TestEntry | Comment, ...] + + def _with_implementation( + self, implementation: Implementation + ) -> Iterable[TestEntry | Comment]: + pending_comment: Comment | None = None + for t in self.tests: + if not isinstance(t, TestEntry): + pending_comment = t + elif t.implementations & implementation: + if pending_comment is not None: + yield pending_comment + pending_comment = None + yield t + + def with_implementation(self, implementation: Implementation) -> Self: + return dataclasses.replace( + self, tests=tuple(self._with_implementation(implementation)) + ) + + @staticmethod + def _add_keysyms(entry: TestEntry | Comment) -> Iterable[TestEntry | Comment]: + if isinstance(entry, TestEntry) and entry.id.type is TestType.ActionsOnly: + if entry.types & TestType.KeysymsOnly: + yield entry.add_keysyms(keep_actions=False) + yield entry + if entry.types & TestType.KeysymsAndActions: + yield entry.add_keysyms(keep_actions=True) + else: + yield entry + + def add_keysyms(self, name: str = "") -> Self: + return dataclasses.replace( + self, + name=name or self.name, + tests=tuple(t for ts in self.tests for t in self._add_keysyms(ts)), + ) + + def __add__(self, other: Any) -> Self: + if isinstance(other, tuple): + return dataclasses.replace(self, tests=self.tests + other) + elif isinstance(other, self.__class__): + return dataclasses.replace(self, tests=self.tests + other.tests) + else: + return NotImplemented + + +C_HEADER_TEMPLATE = r"""// WARNING: This file was auto-generated by: {{ script }} +#include "evdev-scancodes.h" +#include + +#include "src/utils.h" +#include "test.h" + +{%- macro key_seq(entry, type, level) -%} + {% if entry[type].levels|length == 0 %} + {{- entry.id.id }}, BOTH, XKB_KEY_NoSymbol{# -#} + {% else %} + {% if entry[type].levels[level].target_group < 2 %} + {{- entry.id.id }}, BOTH, {{ entry[type].levels[level].keysyms_c -}} + {% else %} + {{- entry.id.id }}, DOWN, {{ entry[type].levels[level].keysyms_c }}, NEXT, + {{ entry.id.id }}, UP, {{ + alt_keysym(entry[type].levels[level].target_group, + entry[type].levels[level].target_level + level).c + -}} + {% endif %} + {% endif %} +{% endmacro %} + +{% macro make_test(mode, ref, tests_group, compile_buffer) -%} + {% set keymap_str = "keymap_" + tests_group.name.replace("-", "_") + mode -%} + const char {{ keymap_str }}[] = + "xkb_keymap {\n" + " xkb_keycodes { include \"merge_modes\" };\n" + " xkb_types { include \"basic+numpad+extra\" };\n" + " xkb_compat { include \"basic+iso9995\" };\n" + " xkb_symbols {\n" + " key { [Shift_L] };\n" + " key { [ISO_Level3_Shift] };\n" + " modifier_map Shift { };\n" + " modifier_map Mod5 { };\n" + // NOTE: Separate statements so that *all* the merge modes *really* work. + // Using + and | separators downgrades `replace key` to `override/ + // augment key`. + " include \"{{symbols_file}}({{ tests_group.name }}base)\"\n" + " {{ mode }} \"{{symbols_file}}({{ tests_group.name }}new)\"\n" + " include \"{{symbols_file}}(group2):2+{{symbols_file}}(group3):3\"\n" + " };\n" + "};"; + fprintf(stderr, "*** test_merge_modes: {{ tests_group.name }}, {{ mode }} ***\n"); + keymap = compile_buffer(ctx, {{ keymap_str }}, + ARRAY_SIZE({{ keymap_str }}), + private); + assert(keymap); + assert_printf(test_key_seq(keymap, + {%- for entry in tests_group.tests +%} + {% if is_not_comment(entry) %} + {{ key_seq(entry, ref, 0) }}, {%- if entry[ref].levels|length > 1 %} NEXT, + KEY_LEFTSHIFT, DOWN, XKB_KEY_Shift_L, NEXT, + {{ key_seq(entry, ref, 1) }}, NEXT, + KEY_LEFTSHIFT, UP, XKB_KEY_Shift_L, + {%- endif %}{%- if entry[ref].levels|length > 2 %} NEXT, + KEY_RIGHTALT, DOWN, XKB_KEY_ISO_Level3_Shift, NEXT, + {{ key_seq(entry, ref, 2) }}, NEXT, + KEY_RIGHTALT, UP, XKB_KEY_ISO_Level3_Shift, + {%- endif %}{% if not loop.last %} NEXT,{% endif %} + {% else %} + // {{ entry -}} + {% endif %} + {% endfor %} FINISH + ), "test_merge_modes: {{ tests_group.name }}, {{ mode }}\n"); + xkb_keymap_unref(keymap); +{%- endmacro %} + +static void +{{ test_func }}(struct xkb_context *ctx, +{{ " "*(test_func|length + 1) }}test_compile_buffer_t compile_buffer, void *private) +{ + struct xkb_keymap *keymap; + {% for tests_group in tests_groups %} + {% if tests_group.tests %} + {% if tests_group.name %} + + /**************************************************************** + * Test group: {{ tests_group.name }} + ****************************************************************/ + {% endif %} + + /* Mode: Default */ + {{ make_test("include", "default", tests_group, "compile_buffer") }} + + /* Mode: Augment */ + {{ make_test("augment", "augment", tests_group, "compile_buffer") }} + + /* Mode: Override */ + {{ make_test("override", "override", tests_group, "compile_buffer") }} + + /* Mode: Replace */ + {{ make_test("replace", "replace", tests_group, "compile_buffer") }} + {% endif %} + {% endfor %} +} +""" + + +@dataclass +class TestFile: + suffix: str + tests: tuple[TestGroup, ...] + symbols_file: ClassVar[str] = "merge_modes" + test_file: ClassVar[str] = "merge_modes_symbols.h" + + @classmethod + def write_keycodes( + cls, root: Path, jinja_env: jinja2.Environment, tests: tuple[TestFile, ...] + ) -> None: + """ + XKB custom keycodes + """ + path = root / f"test/data/keycodes/{cls.symbols_file}" + template_path = path.with_suffix(f"{path.suffix}.jinja") + template = jinja_env.get_template(str(template_path.relative_to(root))) + ids: set[TestId] = set( + t.id + for f in tests + for ts in f.tests + for t in ts.tests + if isinstance(t, TestEntry) + ) + + with path.open("wt", encoding="utf-8") as fd: + fd.writelines( + template.generate( + ids=sorted(ids, key=lambda id: id.xkb_key), + script=SCRIPT.relative_to(root), + ) + ) + + @classmethod + def write_symbols( + cls, + root: Path, + jinja_env: jinja2.Environment, + tests: tuple[TestFile, ...], + use_extra_groups: bool, + debug: bool, + ) -> None: + """ + XKB Symbols data for all merge modes + """ + path = root / f"test/data/symbols/{cls.symbols_file}" + template_path = path.with_suffix(f"{path.suffix}.jinja") + template = jinja_env.get_template(str(template_path.relative_to(root))) + for t in tests: + _path = path.with_stem(path.stem + t.suffix) + _tests = t.tests + keycodes = sorted( + frozenset( + t.key for g in _tests for t in filter(is_not_comment, g.tests) + ), + key=lambda x: x._xkb, + ) + with _path.open("wt", encoding="utf-8") as fd: + fd.writelines( + template.generate( + keycodes=keycodes, + tests_groups=_tests, + script=SCRIPT.relative_to(root), + extra_groups=2 if use_extra_groups else 0, + filename=_path.name, + debug=debug, + ) + ) + + @classmethod + def write_c_tests( + cls, + root: Path, + jinja_env: jinja2.Environment, + tests: tuple[TestFile, ...], + ) -> None: + """ + C headers for alternative tests + """ + path = root / f"test/{cls.test_file}" + template_path = path.with_suffix(f"{path.suffix}.jinja") + # Write jinja template + with template_path.open("wt", encoding="utf-8") as fd: + fd.write(C_HEADER_TEMPLATE) + # Write C headers + template = jinja_env.get_template(str(template_path.relative_to(root))) + for t in tests: + _path = path.with_stem(path.stem + t.suffix) + _tests = t.tests + symbols_file = cls.symbols_file + t.suffix + test_func = f"test_symbols_merge_modes{t.suffix}" + with _path.open("wt", encoding="utf-8") as fd: + fd.writelines( + template.generate( + symbols_file=symbols_file, + test_func=test_func, + tests_groups=_tests, + script=SCRIPT.relative_to(root), + ) + ) + + +TESTS_BOTH = TestGroup( + "", + ( + Comment("Trivial cases"), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(), + update=KeyEntry(), + augment=KeyEntry(), + override=KeyEntry(), + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(), + update=KeyEntry(Level.Actions(3)), + augment=KeyEntry(Level.Actions(3)), + override=KeyEntry(Level.Actions(3)), + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2)), + update=KeyEntry(), + augment=KeyEntry(Level.Actions(2)), + override=KeyEntry(Level.Actions(2)), + ), + Comment("Same key"), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2)), + update=KeyEntry(Level.Actions(2)), + augment=KeyEntry(Level.Actions(2)), + override=KeyEntry(Level.Actions(2)), + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), + update=KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), + override=KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), + implementations=Implementation.xkbcommon, + ), + Comment("Mismatch levels count"), + ( + TEST_BOTH_Q := TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(2)), + update=KeyEntry( + Level.Actions(3), Level.Actions(None), Level.Actions(None) + ), + augment=KeyEntry( + Level.Actions(3), Level.Actions(2), Level.Actions(None) + ), + override=KeyEntry( + Level.Actions(3), Level.Actions(2), Level.Actions(None) + ), + # X11 and xkbcommon handle keysyms-only case differently + types=TestType.ActionsOnly | TestType.KeysymsAndActions, + ) + ), + # Trailing NoSymbols are discarded in xkbcomp + dataclasses.replace( + TEST_BOTH_Q, + augment=KeyEntry(Level.Actions(3), Level.Actions(2)), + override=KeyEntry(Level.Actions(3), Level.Actions(2)), + replace=KeyEntry(Level.Actions(3)), + implementations=Implementation.x11, + ).add_keysyms(keep_actions=False), + dataclasses.replace( + TEST_BOTH_Q, implementations=Implementation.xkbcommon + ).add_keysyms(keep_actions=False), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(2)), + update=KeyEntry(Level.Actions(3), Level.Actions(None), Level.Actions(None)), + augment=KeyEntry(Level.Actions(3), Level.Actions(2), Level.Actions(None)), + override=KeyEntry(Level.Actions(3), Level.Actions(2), Level.Actions(None)), + # X11 and xkbcommon handle keysyms-only case differently + types=TestType.ActionsOnly | TestType.KeysymsAndActions, + ), + ( + TEST_BOTH_W := TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(2), Level.Actions(None)), + update=KeyEntry(Level.Actions(3), Level.Actions(None)), + augment=KeyEntry( + Level.Actions(3), Level.Actions(2), Level.Actions(None) + ), + override=KeyEntry( + Level.Actions(3), Level.Actions(2), Level.Actions(None) + ), + # X11 and xkbcommon handle keysyms-only case differently + types=TestType.ActionsOnly | TestType.KeysymsAndActions, + ) + ), + dataclasses.replace( + TEST_BOTH_W, + augment=KeyEntry(Level.Actions(3), Level.Actions(2)), + override=KeyEntry(Level.Actions(3), Level.Actions(2)), + replace=KeyEntry(Level.Actions(3)), + implementations=Implementation.x11, + ).add_keysyms(keep_actions=False), + dataclasses.replace( + TEST_BOTH_W, implementations=Implementation.xkbcommon + ).add_keysyms(keep_actions=False), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(3), Level.Actions(3), Level.Actions(3)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2), Level.Actions(3)), + override=KeyEntry(Level.Actions(3), Level.Actions(3), Level.Actions(3)), + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(3), Level.Actions(3)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(3), Level.Actions(3), Level.Actions(2)), + ), + Comment("Single keysyms -> single keysyms"), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry(Level.Actions(None), Level.Actions(None)), + augment=KeyEntry(Level.Actions(None), Level.Actions(None)), + override=KeyEntry(Level.Actions(None), Level.Actions(None)), + ), + ( + TEST_BOTH_Y := TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry(Level.Actions(3), Level.Actions(None)), + augment=KeyEntry(Level.Actions(3), Level.Actions(None)), + override=KeyEntry(Level.Actions(3), Level.Actions(None)), + # X11 and xkbcommon handle keysyms-only case differently + types=TestType.ActionsOnly | TestType.KeysymsAndActions, + ) + ), + dataclasses.replace( + TEST_BOTH_Y, + augment=KeyEntry(Level.Actions(3)), + override=KeyEntry(Level.Actions(3)), + replace=KeyEntry(Level.Actions(3)), + implementations=Implementation.x11, + ).add_keysyms(keep_actions=False), + dataclasses.replace( + TEST_BOTH_Y, implementations=Implementation.xkbcommon + ).add_keysyms(keep_actions=False), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry(Level.Actions(None), Level.Actions(3)), + augment=KeyEntry(Level.Actions(None), Level.Actions(3)), + override=KeyEntry(Level.Actions(None), Level.Actions(3)), + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry(Level.Actions(3), Level.Actions(3)), + augment=KeyEntry(Level.Actions(3), Level.Actions(3)), + override=KeyEntry(Level.Actions(3), Level.Actions(3)), + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(None), Level.Actions(None)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(2), Level.Actions(2)), + ), + ( + TEST_BOTH_P := TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(3), Level.Actions(None)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(3), Level.Actions(2)), + # X11 and xkbcommon handle keysyms-only case differently + types=TestType.ActionsOnly | TestType.KeysymsAndActions, + ) + ), + dataclasses.replace( + TEST_BOTH_P, + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(3), Level.Actions(2)), + replace=KeyEntry(Level.Actions(3)), + implementations=Implementation.x11, + ).add_keysyms(keep_actions=False), + dataclasses.replace( + TEST_BOTH_P, implementations=Implementation.xkbcommon + ).add_keysyms(keep_actions=False), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(None), Level.Actions(3)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(2), Level.Actions(3)), + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(3), Level.Actions(3)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(3), Level.Actions(3)), + ), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Keysyms("a"), Level.Actions(2)), + update=KeyEntry(Level.Actions(3), Level.Keysyms("X")), + augment=KeyEntry(Level.Mix(("a"), (3,)), Level.Mix(("X",), (2,))), + override=KeyEntry(Level.Mix(("a"), (3,)), Level.Mix(("X",), (2,))), + ), + Comment("Single keysyms -> multiple keysyms"), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry(Level.Actions(3, None), Level.Actions(None)), + augment=KeyEntry(Level.Actions(3, None), Level.Actions(None)), + override=KeyEntry(Level.Actions(3, None), Level.Actions(None)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry(Level.Actions(3, None), Level.Actions(None, None)), + augment=KeyEntry(Level.Actions(3, None), Level.Actions(None)), + override=KeyEntry(Level.Actions(3, None), Level.Actions(None)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry(Level.Actions(None), Level.Actions(3, None)), + augment=KeyEntry(Level.Actions(None), Level.Actions(3, None)), + override=KeyEntry(Level.Actions(None), Level.Actions(3, None)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry(Level.Actions(None, None), Level.Actions(3, None)), + augment=KeyEntry(Level.Actions(None), Level.Actions(3, None)), + override=KeyEntry(Level.Actions(None), Level.Actions(3, None)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), + augment=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), + override=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None), Level.Actions(None)), + update=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3, Modifier.LevelThree), + ), + augment=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3, Modifier.LevelThree), + ), + override=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3, Modifier.LevelThree), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(3, None), Level.Actions(None)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(3, None), Level.Actions(2)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(3, None), Level.Actions(None, None)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(3, None), Level.Actions(2)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(None), Level.Actions(3, None)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(2), Level.Actions(3, None)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(None, None), Level.Actions(3, None)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(2), Level.Actions(3, None)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry(Level.Actions(3, None), Level.Actions(3, None)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2), Level.Actions(2)), + update=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3, Modifier.LevelThree), + ), + augment=KeyEntry(Level.Actions(2), Level.Actions(2)), + override=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3, Modifier.LevelThree), + ), + implementations=Implementation.xkbcommon, + ), + Comment("Multiple keysyms -> multiple keysyms"), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None, None), Level.Actions(None, None)), + update=KeyEntry( + Level.Actions(None, None), Level.Actions(3, Modifier.LevelThree) + ), + augment=KeyEntry( + Level.Actions(None, None), Level.Actions(3, Modifier.LevelThree) + ), + override=KeyEntry( + Level.Actions(None, None), Level.Actions(3, Modifier.LevelThree) + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None, None), Level.Actions(None, None)), + update=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), + augment=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), + override=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None, None), Level.Actions(2, Modifier.Control)), + update=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3, Modifier.LevelThree), + ), + augment=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(2, Modifier.Control), + ), + override=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3, Modifier.LevelThree), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), + update=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), + augment=KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), + override=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), + update=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(Modifier.LevelThree, 3), + ), + augment=KeyEntry( + Level.Actions(2, Modifier.LevelThree), + Level.Actions(Modifier.LevelThree, 2), + ), + override=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(Modifier.LevelThree, 3), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry( + Level.Actions(2, Modifier.Control), Level.Actions(2, Modifier.Control) + ), + update=KeyEntry( + Level.Actions(None, None), Level.Actions(3, Modifier.LevelThree) + ), + augment=KeyEntry( + Level.Actions(2, Modifier.Control), Level.Actions(2, Modifier.Control) + ), + override=KeyEntry( + Level.Actions(2, Modifier.Control), + Level.Actions(3, Modifier.LevelThree), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry( + Level.Actions(2, Modifier.Control), Level.Actions(Modifier.Control, 2) + ), + update=KeyEntry(Level.Actions(3, None), Level.Actions(None, 3)), + augment=KeyEntry( + Level.Actions(2, Modifier.Control), Level.Actions(Modifier.Control, 2) + ), + override=KeyEntry( + Level.Actions(3, Modifier.Control), Level.Actions(Modifier.Control, 3) + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None, None), Level.Actions(None, None, None)), + update=KeyEntry(Level.Actions(None, None, None), Level.Actions(None, None)), + augment=KeyEntry( + Level.Actions(None, None), Level.Actions(None, None, None) + ), + override=KeyEntry( + Level.Actions(None, None), Level.Actions(None, None, None) + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None, None), Level.Actions(None, None, None)), + update=KeyEntry( + Level.Actions(3, None, Modifier.LevelThree), + Level.Actions(Modifier.LevelThree, 3), + ), + augment=KeyEntry( + Level.Actions(3, None, Modifier.LevelThree), + Level.Actions(Modifier.LevelThree, 3), + ), + override=KeyEntry( + Level.Actions(3, None, Modifier.LevelThree), + Level.Actions(Modifier.LevelThree, 3), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry( + Level.Actions(2, Modifier.Control), + Level.Actions(Modifier.Control, None, 2), + ), + update=KeyEntry(Level.Actions(None, None, None), Level.Actions(None, None)), + augment=KeyEntry( + Level.Actions(2, Modifier.Control), + Level.Actions(Modifier.Control, None, 2), + ), + override=KeyEntry( + Level.Actions(2, Modifier.Control), + Level.Actions(Modifier.Control, None, 2), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry( + Level.Actions(2, Modifier.Control), + Level.Actions(Modifier.Control, None, 2), + ), + update=KeyEntry( + Level.Actions(3, None, Modifier.LevelThree), + Level.Actions(Modifier.LevelThree, 3), + ), + augment=KeyEntry( + Level.Actions(2, Modifier.Control), + Level.Actions(Modifier.Control, None, 2), + ), + override=KeyEntry( + Level.Actions(3, None, Modifier.LevelThree), + Level.Actions(Modifier.LevelThree, 3), + ), + implementations=Implementation.xkbcommon, + ), + Comment("Multiple keysyms -> single keysyms"), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None, None), Level.Actions(2, Modifier.Control)), + update=KeyEntry(Level.Actions(None), Level.Actions(None)), + augment=KeyEntry( + Level.Actions(None, None), Level.Actions(2, Modifier.Control) + ), + override=KeyEntry( + Level.Actions(None, None), Level.Actions(2, Modifier.Control) + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(None, None), Level.Actions(2, Modifier.Control)), + update=KeyEntry(Level.Actions(3), Level.Actions(3)), + augment=KeyEntry(Level.Actions(3), Level.Actions(2, Modifier.Control)), + override=KeyEntry(Level.Actions(3), Level.Actions(3)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), + update=KeyEntry(Level.Actions(None), Level.Actions(None)), + augment=KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), + override=KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.ActionsOnly), + KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), + update=KeyEntry(Level.Actions(3), Level.Actions(3)), + augment=KeyEntry(Level.Actions(2, None), Level.Actions(None, 2)), + override=KeyEntry(Level.Actions(3), Level.Actions(3)), + implementations=Implementation.xkbcommon, + ), + Comment("Mix"), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Actions(2)), + update=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3, Modifier.LevelThree), + ), + augment=KeyEntry(Level.Actions(2), Level.Actions(3, Modifier.LevelThree)), + override=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3, Modifier.LevelThree), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Actions(2, Modifier.Control)), + update=KeyEntry(Level.Actions(3, Modifier.LevelThree), Level.Actions(3)), + augment=KeyEntry(Level.Actions(2, Modifier.Control), Level.Actions(3)), + override=KeyEntry(Level.Actions(3, Modifier.LevelThree), Level.Actions(3)), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), + update=KeyEntry(Level.Actions(3, Modifier.LevelThree), Level.Actions(3)), + augment=KeyEntry(Level.Actions(2), Level.Actions(2, Modifier.Control)), + override=KeyEntry(Level.Actions(3, Modifier.LevelThree), Level.Actions(3)), + implementations=Implementation.xkbcommon, + ), + Comment("Mix"), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Keysyms("a"), Level.Actions(2)), + update=KeyEntry( + Level.Actions(3, Modifier.LevelThree), Level.Keysyms("X", "Y") + ), + augment=KeyEntry(Level.Keysyms("a"), Level.Actions(2)), + override=KeyEntry( + Level.Actions(3, Modifier.LevelThree), Level.Keysyms("X", "Y") + ), + implementations=Implementation.xkbcommon, + ), + Comment("Multiple keysyms/actions –> single"), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Keysyms("a", "b"), Level.Actions(2, Modifier.Control)), + update=KeyEntry(Level.Actions(3), Level.Keysyms("X")), + augment=KeyEntry( + Level.Keysyms("a", "b"), Level.Actions(2, Modifier.Control) + ), + override=KeyEntry(Level.Actions(3), Level.Keysyms("X")), + implementations=Implementation.xkbcommon, + ), + Comment("Multiple keysyms/actions –> multiple (xor)"), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Keysyms("a", "b"), Level.Actions(2, Modifier.Control)), + update=KeyEntry( + Level.Actions(3, Modifier.LevelThree), Level.Keysyms("X", "Y") + ), + augment=KeyEntry( + Level.Mix(("a", "b"), (3, Modifier.LevelThree)), + Level.Mix(("X", "Y"), (2, Modifier.Control)), + ), + override=KeyEntry( + Level.Mix(("a", "b"), (3, Modifier.LevelThree)), + Level.Mix(("X", "Y"), (2, Modifier.Control)), + ), + implementations=Implementation.xkbcommon, + ), + Comment("Multiple keysyms/actions –> multiple (mix)"), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Keysyms("a", None), Level.Actions(2, None)), + update=KeyEntry( + Level.Mix(("x", "y"), (3, Modifier.LevelThree)), + Level.Mix(("X", "Y"), (3, Modifier.LevelThree)), + ), + augment=KeyEntry( + Level.Mix(("a", "y"), (3, Modifier.LevelThree)), + Level.Mix(("X", "Y"), (2, Modifier.LevelThree)), + ), + override=KeyEntry( + Level.Mix(("x", "y"), (3, Modifier.LevelThree)), + Level.Mix(("X", "Y"), (3, Modifier.LevelThree)), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Keysyms("a", "b"), Level.Actions(2, Modifier.Control)), + update=KeyEntry( + Level.Mix(("x", None), (3, Modifier.LevelThree)), + Level.Mix(("X", "Y"), (3, None)), + ), + augment=KeyEntry( + Level.Mix(("a", "b"), (3, Modifier.LevelThree)), + Level.Mix(("X", "Y"), (2, Modifier.Control)), + ), + override=KeyEntry( + Level.Mix(("x", "b"), (3, Modifier.LevelThree)), + Level.Mix(("X", "Y"), (3, Modifier.Control)), + ), + implementations=Implementation.xkbcommon, + ), + Comment("Multiple (mix) –> multiple keysyms/actions"), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry( + Level.Mix(("a", "b"), (2, Modifier.Control)), + Level.Mix(("A", "B"), (2, Modifier.Control)), + ), + update=KeyEntry(Level.Keysyms("x", None), Level.Actions(3, None)), + augment=KeyEntry( + Level.Mix(("a", "b"), (2, Modifier.Control)), + Level.Mix(("A", "B"), (2, Modifier.Control)), + ), + override=KeyEntry( + Level.Mix(("x", "b"), (2, Modifier.Control)), + Level.Mix(("A", "B"), (3, Modifier.Control)), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry( + Level.Mix(("a", None), (2, Modifier.Control)), + Level.Mix(("A", "B"), (2, None)), + ), + update=KeyEntry( + Level.Keysyms("x", "y"), Level.Actions(3, Modifier.LevelThree) + ), + augment=KeyEntry( + Level.Mix(("a", "y"), (2, Modifier.Control)), + Level.Mix(("A", "B"), (2, Modifier.LevelThree)), + ), + override=KeyEntry( + Level.Mix(("x", "y"), (2, Modifier.Control)), + Level.Mix(("A", "B"), (3, Modifier.LevelThree)), + ), + implementations=Implementation.xkbcommon, + ), + Comment("Multiple (mix) –> multiple (mix)"), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry( + Level.Mix(("a", "b"), (2, Modifier.Control)), + Level.Mix((None, "B"), (2, None)), + ), + update=KeyEntry( + Level.Mix((None, "y"), (3, None)), + Level.Mix(("X", "Y"), (3, Modifier.LevelThree)), + ), + augment=KeyEntry( + Level.Mix(("a", "b"), (2, Modifier.Control)), + Level.Mix(("X", "B"), (2, Modifier.LevelThree)), + ), + override=KeyEntry( + Level.Mix(("a", "y"), (3, Modifier.Control)), + Level.Mix(("X", "Y"), (3, Modifier.LevelThree)), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry( + Level.Mix(("a", None), (2, None)), + Level.Mix((None, "B"), (None, Modifier.Control)), + ), + update=KeyEntry( + Level.Mix((None, "y"), (None, Modifier.LevelThree)), + Level.Mix(("X", None), (3, None)), + ), + augment=KeyEntry( + Level.Mix(("a", "y"), (2, Modifier.LevelThree)), + Level.Mix(("X", "B"), (3, Modifier.Control)), + ), + override=KeyEntry( + Level.Mix(("a", "y"), (2, Modifier.LevelThree)), + Level.Mix(("X", "B"), (3, Modifier.Control)), + ), + implementations=Implementation.xkbcommon, + ), + Comment("Mismatch count with mix"), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry( + Level.Keysyms("a"), + Level.Keysyms("A", "B"), + ), + update=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3), + ), + augment=KeyEntry( + Level.Keysyms("a"), + Level.Keysyms("A", "B"), + ), + override=KeyEntry( + Level.Actions(3, Modifier.LevelThree), + Level.Actions(3), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry( + Level.Actions(3), + Level.Actions(3, Modifier.LevelThree), + ), + update=KeyEntry( + Level.Keysyms("A", "B"), + Level.Keysyms("a"), + ), + augment=KeyEntry( + Level.Actions(3), + Level.Actions(3, Modifier.LevelThree), + ), + override=KeyEntry( + Level.Keysyms("A", "B"), + Level.Keysyms("a"), + ), + implementations=Implementation.xkbcommon, + ), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry( + Level.Mix(("a",), (2,)), + Level.Mix(("A", "B"), (2, Modifier.Control)), + ), + update=KeyEntry( + Level.Mix(("x", "y"), (3, Modifier.LevelThree)), + Level.Mix(("X",), (3,)), + ), + augment=KeyEntry( + Level.Mix(("a",), (2,)), + Level.Mix(("A", "B"), (2, Modifier.Control)), + ), + override=KeyEntry( + Level.Mix(("x", "y"), (3, Modifier.LevelThree)), + Level.Mix(("X",), (3,)), + ), + implementations=Implementation.xkbcommon, + ), + Comment("Issue #564"), + TestEntry( + TestId(TestType.KeysymsAndActions), + KeyEntry(Level.Keysyms("A")), + update=KeyEntry(Level.Mix(("A", "A"), (3, Modifier.LevelThree))), + augment=KeyEntry(Level.Keysyms("A")), + override=KeyEntry(Level.Mix(("A", "A"), (3, Modifier.LevelThree))), + implementations=Implementation.xkbcommon, + ), + ), +).add_keysyms() + +TESTS_XKBCOMMON = TestFile( + "", (TESTS_BOTH.with_implementation(Implementation.xkbcommon),) +) +TESTS = (TESTS_XKBCOMMON,) + + +if __name__ == "__main__": + # Root of the project + ROOT = Path(__file__).parent.parent + + # Parse commands + parser = argparse.ArgumentParser(description="Generate symbols tests") + parser.add_argument( + "--root", + type=Path, + default=ROOT, + help="Path to the root of the project (default: %(default)s)", + ) + parser.add_argument( + "--alternative-tests", + action="store_true", + help="Write the C headers for alternative tests", + ) + parser.add_argument("--debug", action="store_true", help="Activate debug mode") + + args = parser.parse_args() + template_loader = jinja2.FileSystemLoader(args.root, encoding="utf-8") + jinja_env = jinja2.Environment( + loader=template_loader, + keep_trailing_newline=True, + trim_blocks=True, + lstrip_blocks=True, + ) + jinja_env.globals["alt_keysym"] = TestEntry.alt_keysym + jinja_env.globals["alt_keysyms"] = TestEntry.alt_keysyms + jinja_env.globals["is_not_comment"] = is_not_comment + jinja_env.tests["is_not_comment"] = is_not_comment + TestFile.write_keycodes(root=args.root, jinja_env=jinja_env, tests=TESTS) + TestFile.write_symbols( + root=args.root, + jinja_env=jinja_env, + tests=TESTS, + use_extra_groups=args.alternative_tests, + debug=args.debug, + ) + if args.alternative_tests: + TestFile.write_c_tests(root=args.root, jinja_env=jinja_env, tests=TESTS) diff --git a/test/buffercomp.c b/test/buffercomp.c index a31686b96..e7d093675 100644 --- a/test/buffercomp.c +++ b/test/buffercomp.c @@ -318,6 +318,5 @@ main(int argc, char *argv[]) xkb_context_unref(ctx); - - return 0; + return EXIT_SUCCESS; } diff --git a/test/common.c b/test/common.c index 88ab4bf69..a6004a7cf 100644 --- a/test/common.c +++ b/test/common.c @@ -455,3 +455,69 @@ test_compile_rules(struct xkb_context *context, const char *rules, return keymap; } + +bool +test_compile_output(struct xkb_context *ctx, + test_compile_buffer_t compile_buffer, + void *compile_buffer_private, const char *test_title, + const char *keymap_str, size_t keymap_len, + const char *rel_path, bool update_output_files) +{ + int success = true; + fprintf(stderr, "*** %s ***\n", test_title); + + struct xkb_keymap *keymap = + compile_buffer(ctx, keymap_str, keymap_len, compile_buffer_private); + assert(keymap); + + char *got = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); + assert(got); + + xkb_keymap_unref(keymap); + + char *path = test_get_path(rel_path); + assert(path); + + if (update_output_files) { + fprintf(stderr, "Writing golden test output to: %s\n", path); + FILE *file = fopen(path, "wb"); + assert(file); + fwrite(got, 1, strlen(got), file); + fclose(file); + } else { + fprintf(stderr, "Reading golden test output: %s\n", path); + char *expected = test_read_file(rel_path); + assert(expected); + const char *label[2] = {"Golden test", "Roundtrip"}; + for (unsigned int k = 0; k < ARRAY_SIZE(label) && success; k++) { + if (streq(expected, got)) { + fprintf(stderr, "%s succeeded.\n", label[k]); + if (k > 0) + continue; + /* Test round trip */ + free(got); + keymap = compile_buffer(ctx, expected, strlen(expected), + compile_buffer_private); + assert(keymap); + got = xkb_keymap_get_as_string(keymap, + XKB_KEYMAP_USE_ORIGINAL_FORMAT); + assert(got); + xkb_keymap_unref(keymap); + } else { + fprintf(stderr, + "%s failed: dumped map differs from expected.\n", + label[k]); + fprintf(stderr, "Path to expected file: %s\n", path); + fprintf(stderr, "Length: expected %zu, got: %zu\n", + strlen(expected), strlen(got)); + fprintf(stderr, "Dumped map:\n"); + fprintf(stderr, "%s\n", got); + success = false; + } + } + free(expected); + } + free(got); + free(path); + return success; +} diff --git a/test/data/keycodes/merge_modes b/test/data/keycodes/merge_modes new file mode 100644 index 000000000..5b0ca705a --- /dev/null +++ b/test/data/keycodes/merge_modes @@ -0,0 +1,160 @@ +// WARNING: This file was auto-generated by: scripts/update-merge-modes-tests.py +default xkb_keycodes "evdev" { + minimum = 8; + maximum = 255; + + = 9; + = 10; + = 11; + = 12; + = 13; + = 14; + = 15; + = 16; + = 17; + = 18; + = 19; + = 20; + = 21; + = 22; + = 23; + = 24; + = 25; + = 26; + = 28; + = 29; + = 30; + = 31; + = 32; + = 33; + = 34; + = 35; + = 36; + = 37; + = 38; + = 39; + = 40; + = 41; + = 42; + = 43; + = 44; + = 45; + = 46; + = 47; + = 51; + = 52; + = 53; + = 54; + = 55; + = 56; + = 57; + = 58; + = 59; + = 60; + = 61; + = 62; + = 63; + = 64; + = 65; + = 68; + = 69; + = 70; + = 71; + = 72; + = 73; + = 74; + = 75; + = 76; + = 77; + = 78; + = 79; + = 80; + = 81; + = 82; + = 83; + = 84; + = 85; + = 86; + = 87; + = 88; + = 89; + = 93; + = 94; + = 95; + = 96; + = 97; + = 98; + = 99; + = 100; + = 101; + = 102; + = 103; + = 104; + = 105; + = 106; + = 107; + = 111; + = 112; + = 113; + = 114; + = 115; + = 116; + = 117; + = 118; + = 119; + = 120; + = 121; + = 122; + = 123; + = 124; + = 125; + = 126; + = 127; + = 128; + = 129; + = 130; + = 131; + = 132; + = 133; + = 134; + = 135; + = 136; + = 137; + = 138; + = 139; + = 140; + = 141; + = 142; + = 143; + = 144; + = 145; + = 146; + = 147; + = 148; + = 149; + = 150; + = 151; + = 152; + = 153; + = 154; + = 155; + = 158; + = 161; + = 164; + = 167; + = 170; + = 173; + = 176; + = 179; + = 182; + = 185; + = 188; + = 191; + = 194; + = 197; + = 200; + = 212; + + = 50; + = 108; +}; diff --git a/test/data/keycodes/merge_modes.jinja b/test/data/keycodes/merge_modes.jinja new file mode 100644 index 000000000..4b90372e8 --- /dev/null +++ b/test/data/keycodes/merge_modes.jinja @@ -0,0 +1,12 @@ +// WARNING: This file was auto-generated by: {{ script }} +default xkb_keycodes "evdev" { + minimum = 8; + maximum = 255; + +{% for id in ids %} + <{{ id.xkb_key }}> = {{ id.id + 8 }}; +{% endfor %} + + = 50; + = 108; +}; diff --git a/test/data/keymaps/merge-modes/augment.xkb b/test/data/keymaps/merge-modes/augment.xkb new file mode 100644 index 000000000..d890f8178 --- /dev/null +++ b/test/data/keymaps/merge-modes/augment.xkb @@ -0,0 +1,782 @@ +xkb_keymap { +xkb_keycodes "(unnamed)" { + minimum = 8; + maximum = 255; + = 9; + = 10; + = 11; + = 12; + = 13; + = 14; + = 15; + = 16; + = 17; + = 18; + = 19; + = 20; + = 21; + = 22; + = 23; + = 24; + = 25; + = 26; + = 28; + = 29; + = 30; + = 31; + = 32; + = 33; + = 34; + = 35; + = 36; + = 37; + = 38; + = 39; + = 40; + = 41; + = 42; + = 43; + = 44; + = 45; + = 46; + = 47; + = 50; + = 51; + = 52; + = 53; + = 54; + = 55; + = 56; + = 57; + = 58; + = 59; + = 60; + = 61; + = 62; + = 63; + = 64; + = 65; + = 68; + = 69; + = 70; + = 71; + = 72; + = 73; + = 74; + = 75; + = 76; + = 77; + = 78; + = 79; + = 80; + = 81; + = 82; + = 83; + = 84; + = 85; + = 86; + = 87; + = 88; + = 89; + = 93; + = 94; + = 95; + = 96; + = 97; + = 98; + = 99; + = 100; + = 101; + = 102; + = 103; + = 104; + = 105; + = 106; + = 107; + = 108; + = 111; + = 112; + = 113; + = 114; + = 115; + = 116; + = 117; + = 118; + = 119; + = 120; + = 121; + = 122; + = 123; + = 124; + = 125; + = 126; + = 127; + = 128; + = 129; + = 130; + = 131; + = 132; + = 133; + = 134; + = 135; + = 136; + = 137; + = 138; + = 139; + = 140; + = 141; + = 142; + = 143; + = 144; + = 145; + = 146; + = 147; + = 148; + = 149; + = 150; + = 151; + = 152; + = 153; + = 154; + = 155; + = 158; + = 161; + = 164; + = 167; + = 170; + = 173; + = 176; + = 179; + = 182; + = 185; + = 188; + = 191; + = 194; + = 197; + = 200; + = 212; +}; + +xkb_types "(unnamed)" { + virtual_modifiers NumLock,LevelThree; + + type "ONE_LEVEL" { + modifiers= none; + level_name[1]= "Any"; + }; + type "TWO_LEVEL" { + modifiers= Shift; + map[Shift]= 2; + level_name[1]= "Base"; + level_name[2]= "Shift"; + }; + type "ALPHABETIC" { + modifiers= Shift+Lock; + map[Shift]= 2; + map[Lock]= 2; + level_name[1]= "Base"; + level_name[2]= "Caps"; + }; + type "FOUR_LEVEL" { + modifiers= Shift+LevelThree; + map[Shift]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; + type "FOUR_LEVEL_ALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= 2; + map[Lock]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + map[Lock+LevelThree]= 4; + map[Shift+Lock+LevelThree]= 3; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; + type "FOUR_LEVEL_SEMIALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= 2; + map[Lock]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + map[Lock+LevelThree]= 3; + preserve[Lock+LevelThree]= Lock; + map[Shift+Lock+LevelThree]= 4; + preserve[Shift+Lock+LevelThree]= Lock; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; +}; + +xkb_compatibility "(unnamed)" { + virtual_modifiers NumLock,LevelThree; + + interpret.useModMapMods= AnyLevel; + interpret.repeat= False; +}; + +xkb_symbols "(unnamed)" { + key { [ Greek_alpha ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha ], + actions[Group1]= [ SetGroup(group=3) ] + }; + key { [ a ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { [ a ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { [ a, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, { A, Y } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ Greek_alpha, A, NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { [ Greek_alpha, A, NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { [ a, A, Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2), SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A, Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2), SetGroup(group=3), NoAction() ] + }; + key { [ a, A, a, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2), SetGroup(group=2), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A, a, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2), SetGroup(group=2), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { [ Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { [ NoSymbol, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, Greek_ALPHA ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, X ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2) ] + }; + key { [ { Greek_alpha, NoSymbol }, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { [ { Greek_alpha, NoSymbol }, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { [ NoSymbol, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { [ NoSymbol, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { A, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ { a, NoSymbol }, { NoSymbol, B } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, NoSymbol }, { NoSymbol, B } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { [ { a, Greek_upsilon }, { Greek_XI, B } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, Greek_upsilon }, { Greek_XI, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=2) } ] + }; + key { [ { a, y }, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { A, Y } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ { a, y }, { X, B } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=2) } ] + }; + key { [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { NoAction(), NoAction(), NoAction() } ] + }; + key { [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ] }; + key { [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ { a, y }, { X, NoSymbol, A } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, NoSymbol, A } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), NoAction(), SetGroup(group=2) } ] + }; + key { [ { a, y }, { X, NoSymbol, A } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, NoSymbol, A } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), NoAction(), SetGroup(group=2) } ] + }; + key { [ { NoSymbol, NoSymbol }, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { A, Y } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ Greek_alpha, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=3), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, { A, Y } ], + actions[Group1]= [ SetGroup(group=3), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ { a, NoSymbol }, { NoSymbol, B } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, NoSymbol }, { NoSymbol, B } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { [ { a, NoSymbol }, { NoSymbol, B } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, NoSymbol }, { NoSymbol, B } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, NoSymbol ], + actions[Group1]= [ NoAction(), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, b }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, b }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, b }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, b }, { A, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { A, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=2), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, b }, { X, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=2), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Control) } ] + }; + key { [ a, { A, B } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=3), { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, { A, B } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ A ] }; +}; + +}; diff --git a/test/data/keymaps/merge-modes/default.xkb b/test/data/keymaps/merge-modes/default.xkb new file mode 100644 index 000000000..4424569d8 --- /dev/null +++ b/test/data/keymaps/merge-modes/default.xkb @@ -0,0 +1,786 @@ +xkb_keymap { +xkb_keycodes "(unnamed)" { + minimum = 8; + maximum = 255; + = 9; + = 10; + = 11; + = 12; + = 13; + = 14; + = 15; + = 16; + = 17; + = 18; + = 19; + = 20; + = 21; + = 22; + = 23; + = 24; + = 25; + = 26; + = 28; + = 29; + = 30; + = 31; + = 32; + = 33; + = 34; + = 35; + = 36; + = 37; + = 38; + = 39; + = 40; + = 41; + = 42; + = 43; + = 44; + = 45; + = 46; + = 47; + = 50; + = 51; + = 52; + = 53; + = 54; + = 55; + = 56; + = 57; + = 58; + = 59; + = 60; + = 61; + = 62; + = 63; + = 64; + = 65; + = 68; + = 69; + = 70; + = 71; + = 72; + = 73; + = 74; + = 75; + = 76; + = 77; + = 78; + = 79; + = 80; + = 81; + = 82; + = 83; + = 84; + = 85; + = 86; + = 87; + = 88; + = 89; + = 93; + = 94; + = 95; + = 96; + = 97; + = 98; + = 99; + = 100; + = 101; + = 102; + = 103; + = 104; + = 105; + = 106; + = 107; + = 108; + = 111; + = 112; + = 113; + = 114; + = 115; + = 116; + = 117; + = 118; + = 119; + = 120; + = 121; + = 122; + = 123; + = 124; + = 125; + = 126; + = 127; + = 128; + = 129; + = 130; + = 131; + = 132; + = 133; + = 134; + = 135; + = 136; + = 137; + = 138; + = 139; + = 140; + = 141; + = 142; + = 143; + = 144; + = 145; + = 146; + = 147; + = 148; + = 149; + = 150; + = 151; + = 152; + = 153; + = 154; + = 155; + = 158; + = 161; + = 164; + = 167; + = 170; + = 173; + = 176; + = 179; + = 182; + = 185; + = 188; + = 191; + = 194; + = 197; + = 200; + = 212; +}; + +xkb_types "(unnamed)" { + virtual_modifiers NumLock,LevelThree; + + type "ONE_LEVEL" { + modifiers= none; + level_name[1]= "Any"; + }; + type "TWO_LEVEL" { + modifiers= Shift; + map[Shift]= 2; + level_name[1]= "Base"; + level_name[2]= "Shift"; + }; + type "ALPHABETIC" { + modifiers= Shift+Lock; + map[Shift]= 2; + map[Lock]= 2; + level_name[1]= "Base"; + level_name[2]= "Caps"; + }; + type "FOUR_LEVEL" { + modifiers= Shift+LevelThree; + map[Shift]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; + type "FOUR_LEVEL_ALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= 2; + map[Lock]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + map[Lock+LevelThree]= 4; + map[Shift+Lock+LevelThree]= 3; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; + type "FOUR_LEVEL_SEMIALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= 2; + map[Lock]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + map[Lock+LevelThree]= 3; + preserve[Lock+LevelThree]= Lock; + map[Shift+Lock+LevelThree]= 4; + preserve[Shift+Lock+LevelThree]= Lock; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; +}; + +xkb_compatibility "(unnamed)" { + virtual_modifiers NumLock,LevelThree; + + interpret.useModMapMods= AnyLevel; + interpret.repeat= False; +}; + +xkb_symbols "(unnamed)" { + key { [ Greek_alpha ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha ], + actions[Group1]= [ SetGroup(group=3) ] + }; + key { [ a ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { [ a ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { [ a, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, { A, Y } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ Greek_alpha, A, NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { [ Greek_alpha, A, NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] + }; + key { [ Greek_alpha, Greek_ALPHA, a, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=2), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA, a, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=2), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { [ Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { [ NoSymbol, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, Greek_ALPHA ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ Greek_alpha, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2) ] + }; + key { [ a, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=3) ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, X ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2) ] + }; + key { [ { Greek_alpha, NoSymbol }, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { [ { Greek_alpha, NoSymbol }, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { [ NoSymbol, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { [ NoSymbol, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, A ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, A ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, SetGroup(group=2) ] + }; + key { [ { Greek_alpha, NoSymbol }, A ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, A ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, SetGroup(group=2) ] + }; + key { [ a, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=3), NoAction() } ] + }; + key { [ a, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ { a, y }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, y }, { X, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, y }, { X, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=3) } ] + }; + key { [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { NoAction(), NoAction(), NoAction() } ] + }; + key { [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ] }; + key { [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ { a, y }, { X, NoSymbol, A } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, NoSymbol, A } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), NoAction(), SetGroup(group=2) } ] + }; + key { [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ { NoSymbol, NoSymbol }, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { A, Y } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { [ { a, NoSymbol }, { NoSymbol, B } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, NoSymbol }, { NoSymbol, B } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { NoAction(), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, X ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, b }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, y }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, b }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, b }, { A, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, y }, { A, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { [ { A, B }, a ] }; + key { + repeat= No, + symbols[Group1]= [ { x, y }, X ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { A, A } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; +}; + +}; diff --git a/test/data/keymaps/merge-modes/override.xkb b/test/data/keymaps/merge-modes/override.xkb new file mode 100644 index 000000000..4424569d8 --- /dev/null +++ b/test/data/keymaps/merge-modes/override.xkb @@ -0,0 +1,786 @@ +xkb_keymap { +xkb_keycodes "(unnamed)" { + minimum = 8; + maximum = 255; + = 9; + = 10; + = 11; + = 12; + = 13; + = 14; + = 15; + = 16; + = 17; + = 18; + = 19; + = 20; + = 21; + = 22; + = 23; + = 24; + = 25; + = 26; + = 28; + = 29; + = 30; + = 31; + = 32; + = 33; + = 34; + = 35; + = 36; + = 37; + = 38; + = 39; + = 40; + = 41; + = 42; + = 43; + = 44; + = 45; + = 46; + = 47; + = 50; + = 51; + = 52; + = 53; + = 54; + = 55; + = 56; + = 57; + = 58; + = 59; + = 60; + = 61; + = 62; + = 63; + = 64; + = 65; + = 68; + = 69; + = 70; + = 71; + = 72; + = 73; + = 74; + = 75; + = 76; + = 77; + = 78; + = 79; + = 80; + = 81; + = 82; + = 83; + = 84; + = 85; + = 86; + = 87; + = 88; + = 89; + = 93; + = 94; + = 95; + = 96; + = 97; + = 98; + = 99; + = 100; + = 101; + = 102; + = 103; + = 104; + = 105; + = 106; + = 107; + = 108; + = 111; + = 112; + = 113; + = 114; + = 115; + = 116; + = 117; + = 118; + = 119; + = 120; + = 121; + = 122; + = 123; + = 124; + = 125; + = 126; + = 127; + = 128; + = 129; + = 130; + = 131; + = 132; + = 133; + = 134; + = 135; + = 136; + = 137; + = 138; + = 139; + = 140; + = 141; + = 142; + = 143; + = 144; + = 145; + = 146; + = 147; + = 148; + = 149; + = 150; + = 151; + = 152; + = 153; + = 154; + = 155; + = 158; + = 161; + = 164; + = 167; + = 170; + = 173; + = 176; + = 179; + = 182; + = 185; + = 188; + = 191; + = 194; + = 197; + = 200; + = 212; +}; + +xkb_types "(unnamed)" { + virtual_modifiers NumLock,LevelThree; + + type "ONE_LEVEL" { + modifiers= none; + level_name[1]= "Any"; + }; + type "TWO_LEVEL" { + modifiers= Shift; + map[Shift]= 2; + level_name[1]= "Base"; + level_name[2]= "Shift"; + }; + type "ALPHABETIC" { + modifiers= Shift+Lock; + map[Shift]= 2; + map[Lock]= 2; + level_name[1]= "Base"; + level_name[2]= "Caps"; + }; + type "FOUR_LEVEL" { + modifiers= Shift+LevelThree; + map[Shift]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; + type "FOUR_LEVEL_ALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= 2; + map[Lock]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + map[Lock+LevelThree]= 4; + map[Shift+Lock+LevelThree]= 3; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; + type "FOUR_LEVEL_SEMIALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= 2; + map[Lock]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + map[Lock+LevelThree]= 3; + preserve[Lock+LevelThree]= Lock; + map[Shift+Lock+LevelThree]= 4; + preserve[Shift+Lock+LevelThree]= Lock; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; +}; + +xkb_compatibility "(unnamed)" { + virtual_modifiers NumLock,LevelThree; + + interpret.useModMapMods= AnyLevel; + interpret.repeat= False; +}; + +xkb_symbols "(unnamed)" { + key { [ Greek_alpha ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha ], + actions[Group1]= [ SetGroup(group=3) ] + }; + key { [ a ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { [ a ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { [ a, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, { A, Y } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ Greek_alpha, A, NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { [ Greek_alpha, A, NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2), NoAction(), NoAction() ] + }; + key { [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] + }; + key { [ Greek_alpha, Greek_ALPHA, a, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=2), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA, a, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=2), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { [ Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { [ NoSymbol, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, Greek_ALPHA ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { [ a, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, A ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=2) ] + }; + key { [ Greek_alpha, A ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, A ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2) ] + }; + key { [ a, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=2), SetGroup(group=3) ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ a, X ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=2) ] + }; + key { [ { Greek_alpha, NoSymbol }, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { [ { Greek_alpha, NoSymbol }, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { [ NoSymbol, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { [ NoSymbol, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, A ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, A ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, SetGroup(group=2) ] + }; + key { [ { Greek_alpha, NoSymbol }, A ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, A ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, SetGroup(group=2) ] + }; + key { [ a, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=3), NoAction() } ] + }; + key { [ a, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ { a, y }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, y }, { X, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, y }, { X, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), SetGroup(group=3) } ] + }; + key { [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { NoAction(), NoAction(), NoAction() } ] + }; + key { [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ] }; + key { [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ { a, y }, { X, NoSymbol, A } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, NoSymbol, A } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetMods(modifiers=Control), NoAction(), SetGroup(group=2) } ] + }; + key { [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ { NoSymbol, NoSymbol }, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { A, Y } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { [ { a, NoSymbol }, { NoSymbol, B } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, NoSymbol }, { NoSymbol, B } ], + actions[Group1]= [ { SetGroup(group=2), NoAction() }, { NoAction(), SetGroup(group=2) } ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { NoAction(), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, X ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, b }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, y }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, b }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, b }, { A, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, y }, { A, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Control) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { a, y }, { X, B } ], + actions[Group1]= [ { SetGroup(group=2), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { [ { A, B }, a ] }; + key { + repeat= No, + symbols[Group1]= [ { x, y }, X ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { A, A } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; +}; + +}; diff --git a/test/data/keymaps/merge-modes/replace.xkb b/test/data/keymaps/merge-modes/replace.xkb new file mode 100644 index 000000000..2115d1308 --- /dev/null +++ b/test/data/keymaps/merge-modes/replace.xkb @@ -0,0 +1,759 @@ +xkb_keymap { +xkb_keycodes "(unnamed)" { + minimum = 8; + maximum = 255; + = 9; + = 10; + = 11; + = 12; + = 13; + = 14; + = 15; + = 16; + = 17; + = 18; + = 19; + = 20; + = 21; + = 22; + = 23; + = 24; + = 25; + = 26; + = 28; + = 29; + = 30; + = 31; + = 32; + = 33; + = 34; + = 35; + = 36; + = 37; + = 38; + = 39; + = 40; + = 41; + = 42; + = 43; + = 44; + = 45; + = 46; + = 47; + = 50; + = 51; + = 52; + = 53; + = 54; + = 55; + = 56; + = 57; + = 58; + = 59; + = 60; + = 61; + = 62; + = 63; + = 64; + = 65; + = 68; + = 69; + = 70; + = 71; + = 72; + = 73; + = 74; + = 75; + = 76; + = 77; + = 78; + = 79; + = 80; + = 81; + = 82; + = 83; + = 84; + = 85; + = 86; + = 87; + = 88; + = 89; + = 93; + = 94; + = 95; + = 96; + = 97; + = 98; + = 99; + = 100; + = 101; + = 102; + = 103; + = 104; + = 105; + = 106; + = 107; + = 108; + = 111; + = 112; + = 113; + = 114; + = 115; + = 116; + = 117; + = 118; + = 119; + = 120; + = 121; + = 122; + = 123; + = 124; + = 125; + = 126; + = 127; + = 128; + = 129; + = 130; + = 131; + = 132; + = 133; + = 134; + = 135; + = 136; + = 137; + = 138; + = 139; + = 140; + = 141; + = 142; + = 143; + = 144; + = 145; + = 146; + = 147; + = 148; + = 149; + = 150; + = 151; + = 152; + = 153; + = 154; + = 155; + = 158; + = 161; + = 164; + = 167; + = 170; + = 173; + = 176; + = 179; + = 182; + = 185; + = 188; + = 191; + = 194; + = 197; + = 200; + = 212; +}; + +xkb_types "(unnamed)" { + virtual_modifiers NumLock,LevelThree; + + type "ONE_LEVEL" { + modifiers= none; + level_name[1]= "Any"; + }; + type "TWO_LEVEL" { + modifiers= Shift; + map[Shift]= 2; + level_name[1]= "Base"; + level_name[2]= "Shift"; + }; + type "ALPHABETIC" { + modifiers= Shift+Lock; + map[Shift]= 2; + map[Lock]= 2; + level_name[1]= "Base"; + level_name[2]= "Caps"; + }; + type "FOUR_LEVEL" { + modifiers= Shift+LevelThree; + map[Shift]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; + type "FOUR_LEVEL_ALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= 2; + map[Lock]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + map[Lock+LevelThree]= 4; + map[Shift+Lock+LevelThree]= 3; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; + type "FOUR_LEVEL_SEMIALPHABETIC" { + modifiers= Shift+Lock+LevelThree; + map[Shift]= 2; + map[Lock]= 2; + map[LevelThree]= 3; + map[Shift+LevelThree]= 4; + map[Lock+LevelThree]= 3; + preserve[Lock+LevelThree]= Lock; + map[Shift+Lock+LevelThree]= 4; + preserve[Shift+Lock+LevelThree]= Lock; + level_name[1]= "Base"; + level_name[2]= "Shift"; + level_name[3]= "Alt Base"; + level_name[4]= "Shift Alt"; + }; +}; + +xkb_compatibility "(unnamed)" { + virtual_modifiers NumLock,LevelThree; + + interpret.useModMapMods= AnyLevel; + interpret.repeat= False; +}; + +xkb_symbols "(unnamed)" { + key { [ Greek_alpha ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha ], + actions[Group1]= [ SetGroup(group=3) ] + }; + key { [ a ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { + repeat= No, + symbols[Group1]= [ a ], + actions[Group1]= [ SetGroup(group=2) ] + }; + key { [ a, { A, Y } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { + repeat= No, + symbols[Group1]= [ a, { A, Y } ], + actions[Group1]= [ SetGroup(group=2), { SetGroup(group=2), SetMods(modifiers=Control) } ] + }; + key { [ Greek_alpha, NoSymbol, NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction(), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction(), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction(), NoAction(), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction(), NoAction(), NoAction() ] + }; + key { [ Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol, NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA, Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3), SetGroup(group=3), NoAction() ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { [ Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { [ NoSymbol, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, Greek_ALPHA ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { [ Greek_alpha, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { [ NoSymbol, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, Greek_ALPHA ], + actions[Group1]= [ NoAction(), SetGroup(group=3) ] + }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, X ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { [ { Greek_alpha, NoSymbol }, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), NoAction() } ] + }; + key { [ NoSymbol, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { [ { NoSymbol, NoSymbol }, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, NoAction() ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), NoAction() } ] + }; + key { [ NoSymbol, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { NoSymbol, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ NoAction(), { SetGroup(group=3), NoAction() } ] + }; + key { [ { NoSymbol, NoSymbol }, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { Greek_ALPHA, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, Greek_upsilon }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { Greek_ALPHA, Greek_UPSILON } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol }, { NoSymbol, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { NoAction(), SetGroup(group=3) } ] + }; + key { [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction(), NoAction() }, { NoAction(), NoAction() } ] + }; + key { [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ] }; + key { [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction(), NoAction() }, { NoAction(), NoAction() } ] + }; + key { [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ] }; + key { [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ] }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { Greek_alpha, NoSymbol, Greek_xi }, { Greek_XI, Greek_BETA } ], + actions[Group1]= [ { SetGroup(group=3), NoAction(), SetMods(modifiers=Mod5) }, { SetMods(modifiers=Mod5), SetGroup(group=3) } ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ NoAction(), NoAction() ] + }; + key { [ NoSymbol, NoSymbol ] }; + key { [ Greek_alpha, Greek_ALPHA ] }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, NoSymbol ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ Greek_alpha, Greek_ALPHA ], + actions[Group1]= [ SetGroup(group=3), SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { NoAction(), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ NoSymbol, X ], + actions[Group1]= [ SetGroup(group=3), NoAction() ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { NoAction(), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, y }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, NoSymbol }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, NoSymbol }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { x, y }, { NoSymbol, NoSymbol } ], + actions[Group1]= [ { NoAction(), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, y }, { X, Y } ], + actions[Group1]= [ { SetGroup(group=3), NoAction() }, { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, y }, { X, NoSymbol } ], + actions[Group1]= [ { NoAction(), SetMods(modifiers=Mod5) }, { SetGroup(group=3), NoAction() } ] + }; + key { + repeat= No, + symbols[Group1]= [ { NoSymbol, NoSymbol }, NoSymbol ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { [ { A, B }, a ] }; + key { + repeat= No, + symbols[Group1]= [ { x, y }, X ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) }, SetGroup(group=3) ] + }; + key { + repeat= No, + symbols[Group1]= [ { A, A } ], + actions[Group1]= [ { SetGroup(group=3), SetMods(modifiers=Mod5) } ] + }; +}; + +}; diff --git a/test/data/symbols/merge_modes b/test/data/symbols/merge_modes new file mode 100644 index 000000000..828f517b5 --- /dev/null +++ b/test/data/symbols/merge_modes @@ -0,0 +1,1460 @@ +// WARNING: This file was auto-generated by: scripts/update-merge-modes-tests.py +xkb_symbols "base" { + key { }; + key { }; + key { }; + key { }; + key { }; + key { }; + key { [a] }; + key { [SetGroup(group=2)] }; + key { [a], [SetGroup(group=2)] }; + key { [a] }; + key { [SetGroup(group=2)] }; + key { [a], [SetGroup(group=2)] }; + key { [a, {A, Y}] }; + key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [NoAction(), SetGroup(group=2)] }; + key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; + key { [NoSymbol, A] }; + key { [NoAction(), SetGroup(group=2)] }; + key { [NoSymbol, A], [NoAction(), SetGroup(group=2)] }; + key { [NoAction(), SetGroup(group=2), NoAction()] }; + key { [NoSymbol, A, NoSymbol], [NoAction(), SetGroup(group=2), NoAction()] }; + key { [NoSymbol, A, NoSymbol] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A, a] }; + key { [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A, a], [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [NoSymbol, NoSymbol] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{NoSymbol, NoSymbol}, {A, Y}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}] }; + key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}] }; + key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, y}, {A, Y}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, y}, {A, Y}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, y}, {X, B}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; + key { [{a, y}, {X, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; + key { [{a, y}, {X, NoSymbol, A}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + key { [{a, y}, {X, NoSymbol, A}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + key { [{NoSymbol, NoSymbol}, {A, Y}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{NoSymbol, NoSymbol}, {A, Y}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}] }; + key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}] }; + key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [SetGroup(group=2)] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}] }; + key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; + key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=2), NoAction()}] }; + key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, b}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, NoSymbol}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; + key { [{a, b}, {NoSymbol, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), NoAction()}] }; + key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetMods(mods=Control)}] }; + key { [a, {A, B}] }; + key { [SetGroup(group=3), {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [a, {A, B}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [A] }; +}; + +xkb_symbols "new" { + + ////// Trivial cases ////// + key { }; + key { }; + key { }; + key { [Greek_alpha] }; + key { [SetGroup(group=3)] }; + key { [Greek_alpha], [SetGroup(group=3)] }; + key { }; + key { }; + key { }; + + ////// Same key ////// + key { [a] }; + key { [SetGroup(group=2)] }; + key { [a], [SetGroup(group=2)] }; + key { [a, {A, Y}] }; + key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Mismatch levels count ////// + key { [SetGroup(group=3), NoAction(), NoAction()] }; + key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + key { [Greek_alpha, NoSymbol, NoSymbol] }; + key { [SetGroup(group=3), NoAction(), NoAction()] }; + key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + key { [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol] }; + key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; + key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Single keysyms -> single keysyms ////// + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol] }; + key { [NoSymbol, Greek_ALPHA] }; + key { [NoAction(), SetGroup(group=3)] }; + key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol] }; + key { [NoSymbol, Greek_ALPHA] }; + key { [NoAction(), SetGroup(group=3)] }; + key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Single keysyms -> multiple keysyms ////// + key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple keysyms -> multiple keysyms ////// + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + + ////// Multiple keysyms -> single keysyms ////// + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Mix ////// + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Mix ////// + key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> single ////// + key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (xor) ////// + key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (mix) ////// + key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{x, NoSymbol}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Multiple (mix) –> multiple keysyms/actions ////// + key { [{x, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [{x, y}, NoSymbol], [NoAction(), {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple (mix) –> multiple (mix) ////// + key { [{NoSymbol, y}, {X, Y}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{NoSymbol, y}, {X, NoSymbol}], [{NoAction(), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Mismatch count with mix ////// + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + key { [{A, B}, a] }; + key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Issue #564 ////// + key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; +}; + +xkb_symbols "new-default" { + include "merge_modes(base)" + + ////// Trivial cases ////// + key { }; + key { }; + key { }; + key { [Greek_alpha] }; + key { [SetGroup(group=3)] }; + key { [Greek_alpha], [SetGroup(group=3)] }; + key { }; + key { }; + key { }; + + ////// Same key ////// + key { [a] }; + key { [SetGroup(group=2)] }; + key { [a], [SetGroup(group=2)] }; + key { [a, {A, Y}] }; + key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Mismatch levels count ////// + key { [SetGroup(group=3), NoAction(), NoAction()] }; + key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + key { [Greek_alpha, NoSymbol, NoSymbol] }; + key { [SetGroup(group=3), NoAction(), NoAction()] }; + key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + key { [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol] }; + key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; + key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Single keysyms -> single keysyms ////// + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol] }; + key { [NoSymbol, Greek_ALPHA] }; + key { [NoAction(), SetGroup(group=3)] }; + key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol] }; + key { [NoSymbol, Greek_ALPHA] }; + key { [NoAction(), SetGroup(group=3)] }; + key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Single keysyms -> multiple keysyms ////// + key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple keysyms -> multiple keysyms ////// + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + + ////// Multiple keysyms -> single keysyms ////// + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Mix ////// + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Mix ////// + key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> single ////// + key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (xor) ////// + key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (mix) ////// + key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{x, NoSymbol}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Multiple (mix) –> multiple keysyms/actions ////// + key { [{x, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [{x, y}, NoSymbol], [NoAction(), {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple (mix) –> multiple (mix) ////// + key { [{NoSymbol, y}, {X, Y}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{NoSymbol, y}, {X, NoSymbol}], [{NoAction(), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Mismatch count with mix ////// + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + key { [{A, B}, a] }; + key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Issue #564 ////// + key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; +}; + +xkb_symbols "new-augment" { + include "merge_modes(base)" + + ////// Trivial cases ////// + augment key { }; + augment key { }; + augment key { }; + augment key { [Greek_alpha] }; + augment key { [SetGroup(group=3)] }; + augment key { [Greek_alpha], [SetGroup(group=3)] }; + augment key { }; + augment key { }; + augment key { }; + + ////// Same key ////// + augment key { [a] }; + augment key { [SetGroup(group=2)] }; + augment key { [a], [SetGroup(group=2)] }; + augment key { [a, {A, Y}] }; + augment key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + augment key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Mismatch levels count ////// + augment key { [SetGroup(group=3), NoAction(), NoAction()] }; + augment key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + augment key { [Greek_alpha, NoSymbol, NoSymbol] }; + augment key { [SetGroup(group=3), NoAction(), NoAction()] }; + augment key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + augment key { [SetGroup(group=3), NoAction()] }; + augment key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + augment key { [Greek_alpha, NoSymbol] }; + augment key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; + augment key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + augment key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + augment key { [Greek_alpha, Greek_ALPHA] }; + augment key { [SetGroup(group=3), SetGroup(group=3)] }; + augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Single keysyms -> single keysyms ////// + augment key { [NoSymbol, NoSymbol] }; + augment key { [NoAction(), NoAction()] }; + augment key { [NoSymbol, NoSymbol] }; + augment key { [SetGroup(group=3), NoAction()] }; + augment key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + augment key { [Greek_alpha, NoSymbol] }; + augment key { [NoSymbol, Greek_ALPHA] }; + augment key { [NoAction(), SetGroup(group=3)] }; + augment key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + augment key { [Greek_alpha, Greek_ALPHA] }; + augment key { [SetGroup(group=3), SetGroup(group=3)] }; + augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + augment key { [NoSymbol, NoSymbol] }; + augment key { [NoAction(), NoAction()] }; + augment key { [NoSymbol, NoSymbol] }; + augment key { [SetGroup(group=3), NoAction()] }; + augment key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + augment key { [Greek_alpha, NoSymbol] }; + augment key { [NoSymbol, Greek_ALPHA] }; + augment key { [NoAction(), SetGroup(group=3)] }; + augment key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + augment key { [Greek_alpha, Greek_ALPHA] }; + augment key { [SetGroup(group=3), SetGroup(group=3)] }; + augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + augment key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Single keysyms -> multiple keysyms ////// + augment key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + augment key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + augment key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + augment key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + augment key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + augment key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + augment key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + augment key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + augment key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + augment key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + augment key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + augment key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + augment key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + augment key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + augment key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + augment key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + augment key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + augment key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + augment key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple keysyms -> multiple keysyms ////// + augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + augment key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + augment key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; + augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + augment key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + augment key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + augment key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + augment key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + augment key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + augment key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + augment key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + augment key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + augment key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + augment key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + augment key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + augment key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + augment key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + augment key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + augment key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + augment key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + + ////// Multiple keysyms -> single keysyms ////// + augment key { [NoSymbol, NoSymbol] }; + augment key { [NoAction(), NoAction()] }; + augment key { [NoSymbol, NoSymbol] }; + augment key { [Greek_alpha, Greek_ALPHA] }; + augment key { [SetGroup(group=3), SetGroup(group=3)] }; + augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + augment key { [NoSymbol, NoSymbol] }; + augment key { [NoAction(), NoAction()] }; + augment key { [NoSymbol, NoSymbol] }; + augment key { [Greek_alpha, Greek_ALPHA] }; + augment key { [SetGroup(group=3), SetGroup(group=3)] }; + augment key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Mix ////// + augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Mix ////// + augment key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> single ////// + augment key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (xor) ////// + augment key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (mix) ////// + augment key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{x, NoSymbol}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Multiple (mix) –> multiple keysyms/actions ////// + augment key { [{x, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=3), NoAction()}] }; + augment key { [{x, y}, NoSymbol], [NoAction(), {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple (mix) –> multiple (mix) ////// + augment key { [{NoSymbol, y}, {X, Y}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + augment key { [{NoSymbol, y}, {X, NoSymbol}], [{NoAction(), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Mismatch count with mix ////// + augment key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + augment key { [{A, B}, a] }; + augment key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Issue #564 ////// + augment key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; +}; + +xkb_symbols "new-override" { + include "merge_modes(base)" + + ////// Trivial cases ////// + override key { }; + override key { }; + override key { }; + override key { [Greek_alpha] }; + override key { [SetGroup(group=3)] }; + override key { [Greek_alpha], [SetGroup(group=3)] }; + override key { }; + override key { }; + override key { }; + + ////// Same key ////// + override key { [a] }; + override key { [SetGroup(group=2)] }; + override key { [a], [SetGroup(group=2)] }; + override key { [a, {A, Y}] }; + override key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + override key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Mismatch levels count ////// + override key { [SetGroup(group=3), NoAction(), NoAction()] }; + override key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + override key { [Greek_alpha, NoSymbol, NoSymbol] }; + override key { [SetGroup(group=3), NoAction(), NoAction()] }; + override key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + override key { [SetGroup(group=3), NoAction()] }; + override key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + override key { [Greek_alpha, NoSymbol] }; + override key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; + override key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + override key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + override key { [Greek_alpha, Greek_ALPHA] }; + override key { [SetGroup(group=3), SetGroup(group=3)] }; + override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Single keysyms -> single keysyms ////// + override key { [NoSymbol, NoSymbol] }; + override key { [NoAction(), NoAction()] }; + override key { [NoSymbol, NoSymbol] }; + override key { [SetGroup(group=3), NoAction()] }; + override key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + override key { [Greek_alpha, NoSymbol] }; + override key { [NoSymbol, Greek_ALPHA] }; + override key { [NoAction(), SetGroup(group=3)] }; + override key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + override key { [Greek_alpha, Greek_ALPHA] }; + override key { [SetGroup(group=3), SetGroup(group=3)] }; + override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + override key { [NoSymbol, NoSymbol] }; + override key { [NoAction(), NoAction()] }; + override key { [NoSymbol, NoSymbol] }; + override key { [SetGroup(group=3), NoAction()] }; + override key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + override key { [Greek_alpha, NoSymbol] }; + override key { [NoSymbol, Greek_ALPHA] }; + override key { [NoAction(), SetGroup(group=3)] }; + override key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + override key { [Greek_alpha, Greek_ALPHA] }; + override key { [SetGroup(group=3), SetGroup(group=3)] }; + override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + override key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Single keysyms -> multiple keysyms ////// + override key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + override key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + override key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + override key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + override key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + override key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + override key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + override key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + override key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + override key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + override key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + override key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + override key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + override key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + override key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + override key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + override key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + override key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + override key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + override key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + override key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple keysyms -> multiple keysyms ////// + override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + override key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + override key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + override key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + override key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; + override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + override key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + override key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + override key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + override key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + override key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + override key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + override key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + override key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + override key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + override key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + override key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + override key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + override key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + override key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + override key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + override key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + + ////// Multiple keysyms -> single keysyms ////// + override key { [NoSymbol, NoSymbol] }; + override key { [NoAction(), NoAction()] }; + override key { [NoSymbol, NoSymbol] }; + override key { [Greek_alpha, Greek_ALPHA] }; + override key { [SetGroup(group=3), SetGroup(group=3)] }; + override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + override key { [NoSymbol, NoSymbol] }; + override key { [NoAction(), NoAction()] }; + override key { [NoSymbol, NoSymbol] }; + override key { [Greek_alpha, Greek_ALPHA] }; + override key { [SetGroup(group=3), SetGroup(group=3)] }; + override key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Mix ////// + override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Mix ////// + override key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> single ////// + override key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (xor) ////// + override key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (mix) ////// + override key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{x, NoSymbol}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Multiple (mix) –> multiple keysyms/actions ////// + override key { [{x, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=3), NoAction()}] }; + override key { [{x, y}, NoSymbol], [NoAction(), {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple (mix) –> multiple (mix) ////// + override key { [{NoSymbol, y}, {X, Y}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + override key { [{NoSymbol, y}, {X, NoSymbol}], [{NoAction(), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Mismatch count with mix ////// + override key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + override key { [{A, B}, a] }; + override key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Issue #564 ////// + override key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; +}; + +xkb_symbols "new-replace" { + include "merge_modes(base)" + + ////// Trivial cases ////// + replace key { }; + replace key { }; + replace key { }; + replace key { [Greek_alpha] }; + replace key { [SetGroup(group=3)] }; + replace key { [Greek_alpha], [SetGroup(group=3)] }; + replace key { }; + replace key { }; + replace key { }; + + ////// Same key ////// + replace key { [a] }; + replace key { [SetGroup(group=2)] }; + replace key { [a], [SetGroup(group=2)] }; + replace key { [a, {A, Y}] }; + replace key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + replace key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Mismatch levels count ////// + replace key { [SetGroup(group=3), NoAction(), NoAction()] }; + replace key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + replace key { [Greek_alpha, NoSymbol, NoSymbol] }; + replace key { [SetGroup(group=3), NoAction(), NoAction()] }; + replace key { [Greek_alpha, NoSymbol, NoSymbol], [SetGroup(group=3), NoAction(), NoAction()] }; + replace key { [SetGroup(group=3), NoAction()] }; + replace key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + replace key { [Greek_alpha, NoSymbol] }; + replace key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; + replace key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + replace key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + replace key { [Greek_alpha, Greek_ALPHA] }; + replace key { [SetGroup(group=3), SetGroup(group=3)] }; + replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Single keysyms -> single keysyms ////// + replace key { [NoSymbol, NoSymbol] }; + replace key { [NoAction(), NoAction()] }; + replace key { [NoSymbol, NoSymbol] }; + replace key { [SetGroup(group=3), NoAction()] }; + replace key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + replace key { [Greek_alpha, NoSymbol] }; + replace key { [NoSymbol, Greek_ALPHA] }; + replace key { [NoAction(), SetGroup(group=3)] }; + replace key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + replace key { [Greek_alpha, Greek_ALPHA] }; + replace key { [SetGroup(group=3), SetGroup(group=3)] }; + replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + replace key { [NoSymbol, NoSymbol] }; + replace key { [NoAction(), NoAction()] }; + replace key { [NoSymbol, NoSymbol] }; + replace key { [SetGroup(group=3), NoAction()] }; + replace key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + replace key { [Greek_alpha, NoSymbol] }; + replace key { [NoSymbol, Greek_ALPHA] }; + replace key { [NoAction(), SetGroup(group=3)] }; + replace key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + replace key { [Greek_alpha, Greek_ALPHA] }; + replace key { [SetGroup(group=3), SetGroup(group=3)] }; + replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + replace key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Single keysyms -> multiple keysyms ////// + replace key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + replace key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + replace key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + replace key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + replace key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + replace key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + replace key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + replace key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + replace key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + replace key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + replace key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + replace key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}] }; + replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, NoSymbol}], [{SetGroup(group=3), NoAction()}, {NoAction(), NoAction()}] }; + replace key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + replace key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + replace key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + replace key { [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{NoAction(), NoAction()}, {SetGroup(group=3), NoAction()}] }; + replace key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + replace key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + replace key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple keysyms -> multiple keysyms ////// + replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + replace key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + replace key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; + replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + replace key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + replace key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + replace key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + replace key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + replace key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + replace key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + replace key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + replace key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + replace key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + replace key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + replace key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + replace key { [{NoAction(), NoAction(), NoAction()}, {NoAction(), NoAction()}] }; + replace key { [{NoSymbol, NoSymbol, NoSymbol}, {NoSymbol, NoSymbol}] }; + replace key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + replace key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + replace key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + + ////// Multiple keysyms -> single keysyms ////// + replace key { [NoSymbol, NoSymbol] }; + replace key { [NoAction(), NoAction()] }; + replace key { [NoSymbol, NoSymbol] }; + replace key { [Greek_alpha, Greek_ALPHA] }; + replace key { [SetGroup(group=3), SetGroup(group=3)] }; + replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + replace key { [NoSymbol, NoSymbol] }; + replace key { [NoAction(), NoAction()] }; + replace key { [NoSymbol, NoSymbol] }; + replace key { [Greek_alpha, Greek_ALPHA] }; + replace key { [SetGroup(group=3), SetGroup(group=3)] }; + replace key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Mix ////// + replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Mix ////// + replace key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> single ////// + replace key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (xor) ////// + replace key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (mix) ////// + replace key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{x, NoSymbol}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Multiple (mix) –> multiple keysyms/actions ////// + replace key { [{x, NoSymbol}, NoSymbol], [NoAction(), {SetGroup(group=3), NoAction()}] }; + replace key { [{x, y}, NoSymbol], [NoAction(), {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple (mix) –> multiple (mix) ////// + replace key { [{NoSymbol, y}, {X, Y}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + replace key { [{NoSymbol, y}, {X, NoSymbol}], [{NoAction(), SetMods(mods=Mod5)}, {SetGroup(group=3), NoAction()}] }; + + ////// Mismatch count with mix ////// + replace key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + replace key { [{A, B}, a] }; + replace key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Issue #564 ////// + replace key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; +}; + +xkb_symbols "augment" { + + ////// Trivial cases ////// + key { }; + key { }; + key { }; + key { [Greek_alpha] }; + key { [SetGroup(group=3)] }; + key { [Greek_alpha], [SetGroup(group=3)] }; + key { [a] }; + key { [SetGroup(group=2)] }; + key { [a], [SetGroup(group=2)] }; + + ////// Same key ////// + key { [a] }; + key { [SetGroup(group=2)] }; + key { [a], [SetGroup(group=2)] }; + key { [a, {A, Y}] }; + key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Mismatch levels count ////// + key { [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol], [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol] }; + key { [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol], [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol], [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol] }; + key { [a, A, Greek_alpha] }; + key { [SetGroup(group=2), SetGroup(group=2), SetGroup(group=3)] }; + key { [a, A, Greek_alpha], [SetGroup(group=2), SetGroup(group=2), SetGroup(group=3)] }; + key { [a, A, a] }; + key { [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A, a], [SetGroup(group=2), SetGroup(group=2), SetGroup(group=2)] }; + + ////// Single keysyms -> single keysyms ////// + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol] }; + key { [NoSymbol, Greek_ALPHA] }; + key { [NoAction(), SetGroup(group=3)] }; + key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, X], [SetGroup(group=3), SetGroup(group=2)] }; + + ////// Single keysyms -> multiple keysyms ////// + key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + + ////// Multiple keysyms -> multiple keysyms ////// + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {A, Y}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{Greek_alpha, Greek_upsilon}, {A, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}] }; + key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, Greek_upsilon}, {Greek_XI, B}] }; + key { [{SetGroup(group=2), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=2)}] }; + key { [{a, Greek_upsilon}, {Greek_XI, B}], [{SetGroup(group=2), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=2)}] }; + key { [{a, y}, {A, Y}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, y}, {A, Y}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, y}, {X, B}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; + key { [{a, y}, {X, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=2)}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{a, y}, {X, NoSymbol, A}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + key { [{a, y}, {X, NoSymbol, A}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + + ////// Multiple keysyms -> single keysyms ////// + key { [{NoSymbol, NoSymbol}, {A, Y}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [Greek_alpha, {A, Y}] }; + key { [SetGroup(group=3), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [Greek_alpha, {A, Y}], [SetGroup(group=3), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}] }; + key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}] }; + key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + + ////// Mix ////// + key { [SetGroup(group=2), {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, SetGroup(group=3)] }; + key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Mix ////// + key { [a, NoSymbol], [NoAction(), SetGroup(group=2)] }; + + ////// Multiple keysyms/actions –> single ////// + key { [{a, b}, NoSymbol], [NoAction(), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Multiple keysyms/actions –> multiple (xor) ////// + key { [{a, b}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Multiple keysyms/actions –> multiple (mix) ////// + key { [{a, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=2), SetMods(mods=Mod5)}] }; + key { [{a, b}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Multiple (mix) –> multiple keysyms/actions ////// + key { [{a, b}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{a, y}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Mod5)}] }; + + ////// Multiple (mix) –> multiple (mix) ////// + key { [{a, b}, {X, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=2), SetMods(mods=Mod5)}] }; + key { [{a, y}, {X, B}], [{SetGroup(group=2), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Control)}] }; + + ////// Mismatch count with mix ////// + key { [a, {A, B}] }; + key { [SetGroup(group=3), {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [a, {A, B}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Issue #564 ////// + key { [A] }; +}; + +xkb_symbols "override" { + + ////// Trivial cases ////// + key { }; + key { }; + key { }; + key { [Greek_alpha] }; + key { [SetGroup(group=3)] }; + key { [Greek_alpha], [SetGroup(group=3)] }; + key { [a] }; + key { [SetGroup(group=2)] }; + key { [a], [SetGroup(group=2)] }; + + ////// Same key ////// + key { [a] }; + key { [SetGroup(group=2)] }; + key { [a], [SetGroup(group=2)] }; + key { [a, {A, Y}] }; + key { [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [a, {A, Y}], [SetGroup(group=2), {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Mismatch levels count ////// + key { [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol], [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol] }; + key { [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol], [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol], [SetGroup(group=3), SetGroup(group=2), NoAction()] }; + key { [Greek_alpha, A, NoSymbol] }; + key { [Greek_alpha, Greek_ALPHA, Greek_alpha] }; + key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA, Greek_alpha], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA, a] }; + key { [SetGroup(group=3), SetGroup(group=3), SetGroup(group=2)] }; + key { [Greek_alpha, Greek_ALPHA, a], [SetGroup(group=3), SetGroup(group=3), SetGroup(group=2)] }; + + ////// Single keysyms -> single keysyms ////// + key { [NoSymbol, NoSymbol] }; + key { [NoAction(), NoAction()] }; + key { [NoSymbol, NoSymbol] }; + key { [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol], [SetGroup(group=3), NoAction()] }; + key { [Greek_alpha, NoSymbol] }; + key { [NoSymbol, Greek_ALPHA] }; + key { [NoAction(), SetGroup(group=3)] }; + key { [NoSymbol, Greek_ALPHA], [NoAction(), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [a, A] }; + key { [SetGroup(group=2), SetGroup(group=2)] }; + key { [a, A], [SetGroup(group=2), SetGroup(group=2)] }; + key { [SetGroup(group=3), SetGroup(group=2)] }; + key { [Greek_alpha, A], [SetGroup(group=3), SetGroup(group=2)] }; + key { [Greek_alpha, A] }; + key { [a, Greek_ALPHA] }; + key { [SetGroup(group=2), SetGroup(group=3)] }; + key { [a, Greek_ALPHA], [SetGroup(group=2), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [a, X], [SetGroup(group=3), SetGroup(group=2)] }; + + ////// Single keysyms -> multiple keysyms ////// + key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol] }; + key { [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [{Greek_alpha, NoSymbol}, NoSymbol], [{SetGroup(group=3), NoAction()}, NoAction()] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}] }; + key { [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [NoSymbol, {Greek_ALPHA, NoSymbol}], [NoAction(), {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, A] }; + key { [{SetGroup(group=3), NoAction()}, SetGroup(group=2)] }; + key { [{Greek_alpha, NoSymbol}, A], [{SetGroup(group=3), NoAction()}, SetGroup(group=2)] }; + key { [{Greek_alpha, NoSymbol}, A] }; + key { [{SetGroup(group=3), NoAction()}, SetGroup(group=2)] }; + key { [{Greek_alpha, NoSymbol}, A], [{SetGroup(group=3), NoAction()}, SetGroup(group=2)] }; + key { [a, {Greek_ALPHA, NoSymbol}] }; + key { [SetGroup(group=2), {SetGroup(group=3), NoAction()}] }; + key { [a, {Greek_ALPHA, NoSymbol}], [SetGroup(group=2), {SetGroup(group=3), NoAction()}] }; + key { [a, {Greek_ALPHA, NoSymbol}] }; + key { [SetGroup(group=2), {SetGroup(group=3), NoAction()}] }; + key { [a, {Greek_ALPHA, NoSymbol}], [SetGroup(group=2), {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}] }; + key { [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, NoSymbol}, {Greek_ALPHA, NoSymbol}], [{SetGroup(group=3), NoAction()}, {SetGroup(group=3), NoAction()}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple keysyms -> multiple keysyms ////// + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{NoSymbol, NoSymbol}, {Greek_ALPHA, Greek_UPSILON}], [{NoAction(), NoAction()}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol}, {NoSymbol, Greek_BETA}], [{SetGroup(group=3), NoAction()}, {NoAction(), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, Greek_upsilon}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{a, y}, {Greek_ALPHA, Greek_UPSILON}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{a, y}, {Greek_ALPHA, Greek_UPSILON}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{Greek_alpha, y}, {X, Greek_BETA}] }; + key { [{SetGroup(group=3), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=3)}] }; + key { [{Greek_alpha, y}, {X, Greek_BETA}], [{SetGroup(group=3), SetMods(mods=Control)}, {SetMods(mods=Control), SetGroup(group=3)}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; + key { [{NoAction(), NoAction()}, {NoAction(), NoAction(), NoAction()}] }; + key { [{NoSymbol, NoSymbol}, {NoSymbol, NoSymbol, NoSymbol}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{a, y}, {X, NoSymbol, A}] }; + key { [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + key { [{a, y}, {X, NoSymbol, A}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetMods(mods=Control), NoAction(), SetGroup(group=2)}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}] }; + key { [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + key { [{Greek_alpha, NoSymbol, Greek_xi}, {Greek_XI, Greek_BETA}], [{SetGroup(group=3), NoAction(), SetMods(mods=Mod5)}, {SetMods(mods=Mod5), SetGroup(group=3)}] }; + + ////// Multiple keysyms -> single keysyms ////// + key { [{NoSymbol, NoSymbol}, {A, Y}] }; + key { [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [{NoSymbol, NoSymbol}, {A, Y}], [{NoAction(), NoAction()}, {SetGroup(group=2), SetMods(mods=Control)}] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + key { [{a, NoSymbol}, {NoSymbol, B}] }; + key { [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [{a, NoSymbol}, {NoSymbol, B}], [{SetGroup(group=2), NoAction()}, {NoAction(), SetGroup(group=2)}] }; + key { [Greek_alpha, Greek_ALPHA] }; + key { [SetGroup(group=3), SetGroup(group=3)] }; + key { [Greek_alpha, Greek_ALPHA], [SetGroup(group=3), SetGroup(group=3)] }; + + ////// Mix ////// + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Mix ////// + key { [NoSymbol, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, NoAction()] }; + + ////// Multiple keysyms/actions –> single ////// + key { [NoSymbol, X], [SetGroup(group=3), NoAction()] }; + + ////// Multiple keysyms/actions –> multiple (xor) ////// + key { [{a, b}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=2), SetMods(mods=Control)}] }; + + ////// Multiple keysyms/actions –> multiple (mix) ////// + key { [{x, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{x, b}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Control)}] }; + + ////// Multiple (mix) –> multiple keysyms/actions ////// + key { [{x, b}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=3), SetMods(mods=Control)}] }; + key { [{x, y}, {A, B}], [{SetGroup(group=2), SetMods(mods=Control)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + + ////// Multiple (mix) –> multiple (mix) ////// + key { [{a, y}, {X, Y}], [{SetGroup(group=3), SetMods(mods=Control)}, {SetGroup(group=3), SetMods(mods=Mod5)}] }; + key { [{a, y}, {X, B}], [{SetGroup(group=2), SetMods(mods=Mod5)}, {SetGroup(group=3), SetMods(mods=Control)}] }; + + ////// Mismatch count with mix ////// + key { [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + key { [{A, B}, a] }; + key { [{x, y}, X], [{SetGroup(group=3), SetMods(mods=Mod5)}, SetGroup(group=3)] }; + + ////// Issue #564 ////// + key { [{A, A}], [{SetGroup(group=3), SetMods(mods=Mod5)}] }; +}; diff --git a/test/data/symbols/merge_modes.jinja b/test/data/symbols/merge_modes.jinja new file mode 100644 index 000000000..cd3666666 --- /dev/null +++ b/test/data/symbols/merge_modes.jinja @@ -0,0 +1,56 @@ +// WARNING: This file was auto-generated by: {{ script }} +{%- macro make_symbols(tests_group, map_suffix, mode, local) -%} +xkb_symbols "{{ tests_group.name }}{{ map_suffix }}{{ "-" + mode if local else "" }}" { + {% if local %} + include "{{ filename }}({{ tests_group.name }}base)" + {% endif %} + {% for entry in tests_group.tests %} + {% if is_not_comment(entry) %} + {% if debug and not local and mode == "update" %} + + // base: {{ "".join(entry.base.xkb) or "(empty)" }} + // key to merge / replace result + {% endif %} + {{ mode + " " if local and mode != "default" else "" -}} + key {{ entry.key.xkb }} { {{ "".join(entry["update" if local else mode].xkb) }} }; + {% if debug and not local and mode == "update" %} + // override: {{ "".join(entry.override.xkb) or "(empty)" }} + // augment: {{ "".join(entry.augment.xkb) or "(empty)" }} + {% endif %} + {% else %} + + ////// {{ entry }} ////// + {% endif %} + {% endfor %} +}; +{%- endmacro %} +{% for tests_group in tests_groups %} + +xkb_symbols "{{ tests_group.name }}base" { + {% for entry in tests_group.tests|select("is_not_comment") %} + key {{ entry.key.xkb }} { {{ "".join(entry.base.xkb) }} }; + {% endfor %} +}; + +{{ make_symbols(tests_group, "new", "update", false) }} + +{{ make_symbols(tests_group, "new", "default", true) }} + +{{ make_symbols(tests_group, "new", "augment", true) }} + +{{ make_symbols(tests_group, "new", "override", true) }} + +{{ make_symbols(tests_group, "new", "replace", true) }} + +{{ make_symbols(tests_group, "augment", "augment", false) }} + +{{ make_symbols(tests_group, "override", "override", false) }} +{% endfor %} +{% for g in range(extra_groups) %} + +xkb_symbols "group{{ g + 2 }}" { + {% for key in keycodes %} + key {{ key.xkb }} { [{{ alt_keysyms(g) | join(", ") }}] }; + {% endfor %} +}; +{% endfor %} diff --git a/test/merge_modes.c b/test/merge_modes.c new file mode 100644 index 000000000..ca6eb8507 --- /dev/null +++ b/test/merge_modes.c @@ -0,0 +1,76 @@ +/* + * Copyright © 2024 Pierre Le Marre + * + * 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 +#include +#include + +#include "test.h" +#include "merge_modes.h" + +/* Our keymap compiler is the xkbcommon buffer compiler */ +static struct xkb_keymap * +compile_buffer(struct xkb_context *context, const char *buf, size_t len, + void *private) +{ + return test_compile_buffer(context, buf, len); +} + +static void +test_symbols(struct xkb_context *ctx, enum update_files update_output_files) +{ + make_symbols_tests("merge_modes", "", "", + compile_buffer, NULL, update_output_files); +} + +int +main(int argc, char *argv[]) +{ + test_init(); + + /* Check if we run the tests or just update their outputs */ + enum update_files update_output_files = NO_UPDATE; + if (argc > 1) { + if (streq(argv[1], "update")) { + /* Update files with *expected* results */ + update_output_files = UPDATE_USING_TEST_INPUT; + } else if (streq(argv[1], "update-obtained")) { + /* Update files with *obtained* results */ + update_output_files = UPDATE_USING_TEST_OUTPUT; + } else { + fprintf(stderr, "ERROR: unsupported argument: \"%s\n\".", argv[1]); + exit(EXIT_FAILURE); + } + } + + struct xkb_context *ctx = test_get_context(CONTEXT_NO_FLAG); + assert(ctx); + + test_symbols(ctx, update_output_files); + + xkb_context_unref(ctx); + + return EXIT_SUCCESS; +} diff --git a/test/merge_modes.h b/test/merge_modes.h new file mode 100644 index 000000000..3aebc1e1b --- /dev/null +++ b/test/merge_modes.h @@ -0,0 +1,159 @@ +/* + * Copyright © 2024 Pierre Le Marre + * + * 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. + */ + +/* Use macro sorcery */ +#include "src/messages-codes.h" + +enum update_files { + NO_UPDATE = 0, + UPDATE_USING_TEST_INPUT, + UPDATE_USING_TEST_OUTPUT +}; + +#define GOLDEN_TESTS_OUTPUTS "keymaps/merge-modes/" + +#define keymap_common \ + "xkb_keymap {\n" \ + " xkb_keycodes { include \"merge_modes\" };\n" \ + " xkb_types {\n" \ + " include \"basic\"\n" \ + /* Add only used levels; `types/extra` has some types uneeded here */ \ + " virtual_modifiers LevelThree;\n" \ + " type \"FOUR_LEVEL\" {\n" \ + " modifiers = Shift+LevelThree;\n" \ + " map[None] = Level1;\n" \ + " map[Shift] = Level2;\n" \ + " map[LevelThree] = Level3;\n" \ + " map[Shift+LevelThree] = Level4;\n" \ + " level_name[Level1] = \"Base\";\n" \ + " level_name[Level2] = \"Shift\";\n" \ + " level_name[Level3] = \"Alt Base\";\n" \ + " level_name[Level4] = \"Shift Alt\";\n" \ + " };\n" \ + " type \"FOUR_LEVEL_ALPHABETIC\" {\n" \ + " modifiers = Shift+Lock+LevelThree;\n" \ + " map[None] = Level1;\n" \ + " map[Shift] = Level2;\n" \ + " map[Lock] = Level2;\n" \ + " map[LevelThree] = Level3;\n" \ + " map[Shift+LevelThree] = Level4;\n" \ + " map[Lock+LevelThree] = Level4;\n" \ + " map[Lock+Shift+LevelThree] = Level3;\n" \ + " level_name[Level1] = \"Base\";\n" \ + " level_name[Level2] = \"Shift\";\n" \ + " level_name[Level3] = \"Alt Base\";\n" \ + " level_name[Level4] = \"Shift Alt\";\n" \ + " };\n" \ + " type \"FOUR_LEVEL_SEMIALPHABETIC\" {\n" \ + " modifiers = Shift+Lock+LevelThree;\n" \ + " map[None] = Level1;\n" \ + " map[Shift] = Level2;\n" \ + " map[Lock] = Level2;\n" \ + " map[LevelThree] = Level3;\n" \ + " map[Shift+LevelThree] = Level4;\n" \ + " map[Lock+LevelThree] = Level3;\n" \ + " map[Lock+Shift+LevelThree] = Level4;\n" \ + " preserve[Lock+LevelThree] = Lock;\n" \ + " preserve[Lock+Shift+LevelThree] = Lock;\n" \ + " level_name[Level1] = \"Base\";\n" \ + " level_name[Level2] = \"Shift\";\n" \ + " level_name[Level3] = \"Alt Base\";\n" \ + " level_name[Level4] = \"Shift Alt\";\n" \ + " };\n" \ + " };\n" \ + " xkb_compat { };\n" + +/* Macro sorcery: see "src/messages-codes.h" */ +#define MATCHdefault unused,default +#define CHECK_MERGE_MODE(value) SECOND(JOIN(MATCH, value), other, unused) + +#define FORMAT_MERGE_MODE_global_default(mode) "include" +#define FORMAT_MERGE_MODE_global_other(mode) #mode +#define FORMAT_MERGE_MODE_global(mode) \ + JOIN(FORMAT_MERGE_MODE_global_, CHECK_MERGE_MODE(mode))(mode) + +/* Helper to create a keymap string to initialize output files */ +#define make_ref_keymap(file, map, suffix) \ + keymap_common \ + " xkb_symbols {\n" \ + " include \"" file "(" map suffix ")\"\n" \ + " };\n" \ + "};" + +/* Helper to create a keymap string to test (global) */ +#define make_test_keymap_global(file, map, merge_mode) \ + keymap_common \ + " xkb_symbols {\n" \ + /* \ + * NOTE: Separate statements so that *all* the merge modes *really* work. \ + * Using + and | separators downgrades `replace key` to `override/ \ + * augment key`. \ + */ \ + " include \"" file "(" map "base)\"\n" \ + " " FORMAT_MERGE_MODE_global(merge_mode) " \"" file "(" map "new)\"\n" \ + " };\n" \ + "};" + +/* Helper to create a keymap string to test (local) */ +#define make_test_keymap_local(file, map, merge_mode) \ + keymap_common \ + " xkb_symbols {\n" \ + /* \ + * NOTE: Separate statements so that *all* the merge modes *really* work. \ + * Using + and | separators downgrades `replace key` to `override/ \ + * augment key`. \ + */ \ + " include \"" file "(" map "new-" #merge_mode ")\"\n" \ + " };\n" \ + "};" + +/* Helper to create a test for a single keymap string */ +#define make_symbols_test(localness, merge_mode, file, map, map_suffix, \ + file_suffix, compile, priv, update) do { \ + const char keymap_ref_str[] = make_ref_keymap(file, map, map_suffix); \ + const char keymap_test_str[] = make_test_keymap_##localness(file, map, merge_mode);\ + assert(test_compile_output( \ + ctx, compile, priv, \ + "test_merge_mode: " map ", " #localness " " #merge_mode, \ + (update == UPDATE_USING_TEST_INPUT) ? keymap_ref_str : keymap_test_str, \ + (update == UPDATE_USING_TEST_INPUT) ? ARRAY_SIZE(keymap_ref_str) \ + : ARRAY_SIZE(keymap_test_str), \ + /* Local and global merge modes use the same result file */ \ + GOLDEN_TESTS_OUTPUTS #merge_mode map file_suffix ".xkb", \ + !!update)); \ +} while (0) + +/* Helper to create a test for each merge mode */ +#define make_symbols_tests(file, map, suffix, compile, priv, update) \ + /* Mode: Default */ \ + make_symbols_test(local, default, file, map, "override", suffix, compile, priv, update); \ + make_symbols_test(global, default, file, map, "override", suffix, compile, priv, update); \ + /* Mode: Augment */ \ + make_symbols_test(local, augment, file, map, "augment", suffix, compile, priv, update); \ + make_symbols_test(global, augment, file, map, "augment", suffix, compile, priv, update); \ + /* Mode: Override */ \ + make_symbols_test(local, override, file, map, "override", suffix, compile, priv, update); \ + make_symbols_test(global, override, file, map, "override", suffix, compile, priv, update);\ + /* Mode: Replace */ \ + make_symbols_test(local, replace, file, map, "new", suffix, compile, priv, update); \ + make_symbols_test(global, replace, file, map, "new", suffix, compile, priv, update) diff --git a/test/test.h b/test/test.h index a72514366..4f7093b3c 100644 --- a/test/test.h +++ b/test/test.h @@ -23,6 +23,9 @@ * Author: Daniel Stone */ +#ifndef TEST_H +#define TEST_H + #include /* Don't use compat names in internal code. */ @@ -36,11 +39,12 @@ #define SKIP_TEST 77 #define TEST_SETUP_FAILURE 99 -#define assert_printf(cond, ...) \ - if (!(cond)) { \ - fprintf(stderr, "Assertion failure: " __VA_ARGS__); \ - assert(cond); \ - } +#define assert_printf(cond, ...) do { \ + const bool __cond = (cond); \ + if (!__cond) { \ + fprintf(stderr, "Assertion failure: " __VA_ARGS__); \ + assert(__cond); \ + }} while (0) #define assert_streq_not_null(test_name, expected, got) \ assert_printf(streq_not_null(expected, got), \ @@ -100,6 +104,17 @@ test_compile_string(struct xkb_context *context, const char *string); struct xkb_keymap * test_compile_buffer(struct xkb_context *context, const char *buf, size_t len); +typedef struct xkb_keymap * (*test_compile_buffer_t)(struct xkb_context *context, + const char *buf, size_t len, + void *private); + +bool +test_compile_output(struct xkb_context *ctx, + test_compile_buffer_t compile_buffer, + void *compile_buffer_private, const char *test_title, + const char *keymap_str, size_t keymap_len, + const char *rel_path, bool update_output_files); + struct xkb_keymap * test_compile_rules(struct xkb_context *context, const char *rules, const char *model, const char *layout, const char *variant, @@ -110,3 +125,5 @@ test_compile_rules(struct xkb_context *context, const char *rules, #define setenv(varname, value, overwrite) _putenv_s((varname), (value)) #define unsetenv(varname) _putenv_s(varname, "") #endif + +#endif From 5f82d3534ec50c70f3584d6f50999fb4ac8a8e34 Mon Sep 17 00:00:00 2001 From: Pierre Le Marre Date: Thu, 19 Dec 2024 18:21:01 +0100 Subject: [PATCH 2/2] symbols: Fix key symbols/actions merge - Fixed field for defined keysyms/actions - Fixed regression introduced by fdf2c525977e7e8af4135d593110f5bc1454abd8 --- src/keymap-priv.c | 24 ++++++ src/keymap.h | 6 ++ src/xkbcomp/symbols.c | 165 +++++++++++++++++++++++++++++++----------- 3 files changed, 152 insertions(+), 43 deletions(-) diff --git a/src/keymap-priv.c b/src/keymap-priv.c index 41f4c7540..c615134c0 100644 --- a/src/keymap-priv.c +++ b/src/keymap-priv.c @@ -152,6 +152,30 @@ XkbLevelsSameSyms(const struct xkb_level *a, const struct xkb_level *b) return memcmp(a->s.syms, b->s.syms, sizeof(*a->s.syms) * a->num_syms) == 0; } +bool +XkbLevelHasNoKeysym(const struct xkb_level *level) +{ + if (level->num_syms == 0) + return true; + if (level->num_syms == 1) + return level->s.sym == XKB_KEY_NoSymbol; + for (unsigned int k = 0; k < level->num_syms; k++) { + if (level->s.syms[k] != XKB_KEY_NoSymbol) + return false; + } + return true; +} + +bool +XkbLevelsSameActions(const struct xkb_level *a, const struct xkb_level *b) +{ + if (a->num_syms != b->num_syms) + return false; + if (a->num_syms <= 1) + return memcmp(&a->a.action, &b->a.action, sizeof(a->a.action)) == 0; + return memcmp(a->a.actions, b->a.actions, sizeof(*a->a.actions) * a->num_syms) == 0; +} + bool XkbLevelHasNoAction(const struct xkb_level *level) { diff --git a/src/keymap.h b/src/keymap.h index 218a389ed..1ddf54485 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -498,6 +498,12 @@ XkbModNameToIndex(const struct xkb_mod_set *mods, xkb_atom_t name, bool XkbLevelsSameSyms(const struct xkb_level *a, const struct xkb_level *b); +bool +XkbLevelHasNoKeysym(const struct xkb_level *level); + +bool +XkbLevelsSameActions(const struct xkb_level *a, const struct xkb_level *b); + bool XkbLevelHasNoAction(const struct xkb_level *level); diff --git a/src/xkbcomp/symbols.c b/src/xkbcomp/symbols.c index b95172867..fa1795b76 100644 --- a/src/xkbcomp/symbols.c +++ b/src/xkbcomp/symbols.c @@ -298,21 +298,62 @@ MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber, /* Merge the actions and syms. */ levels_in_both = MIN(darray_size(into->levels), darray_size(from->levels)); + unsigned int fromKeysymsCount = 0; + unsigned int fromActionsCount = 0; for (i = 0; i < levels_in_both; i++) { struct xkb_level *intoLevel = &darray_item(into->levels, i); struct xkb_level *fromLevel = &darray_item(from->levels, i); - if (fromLevel->num_syms == 0) { - /* it's empty for consistency with other comparisons */ + const bool fromHasNoKeysym = XkbLevelHasNoKeysym(fromLevel); + const bool fromHasNoAction = XkbLevelHasNoAction(fromLevel); + if (fromHasNoKeysym && fromHasNoAction) { + /* Empty `from`: do nothing */ + continue; } - else if (intoLevel->num_syms == 0) { + + const bool intoHasNoKeysym = XkbLevelHasNoKeysym(intoLevel); + const bool intoHasNoAction = XkbLevelHasNoAction(intoLevel); + if (intoHasNoKeysym && intoHasNoAction) { + /* Empty `into`: use `from` keysyms and actions */ StealLevelInfo(intoLevel, fromLevel); + fromKeysymsCount++; + fromActionsCount++; + continue; + } + + if (intoLevel->num_syms != fromLevel->num_syms) { + /* Handle different keysyms/actions count */ + assert(intoLevel->num_syms > 0); + assert(fromLevel->num_syms > 0); + if (report) { + log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_SYMBOL, + "Multiple definitions for level %d/group %u on key %s " + "with incompatible keysyms/actions count; " + "Using %s (count: %u), ignoring %s (count: %u)\n", + i + 1, group + 1, KeyNameText(info->ctx, key_name), + (clobber ? "from" : "to"), + (clobber ? fromLevel->num_syms : intoLevel->num_syms), + (clobber ? "to" : "from"), + (clobber ? intoLevel->num_syms : fromLevel->num_syms)); + } + if (clobber) { + /* There is no obvious way to deal with this case other than + * just cloning `from` */ + StealLevelInfo(intoLevel, fromLevel); + fromKeysymsCount++; + fromActionsCount++; + } + continue; } else { - bool actions_replaced = false; + /* Possible level conflict */ + assert(intoLevel->num_syms > 0); + assert(fromLevel->num_syms == intoLevel->num_syms); + /* Handle keysyms */ if (!XkbLevelsSameSyms(fromLevel, intoLevel)) { - if (report) { + /* Incompatible keysyms */ + if (report && !(intoHasNoKeysym || fromHasNoKeysym)) { log_warn(info->ctx, XKB_WARNING_CONFLICTING_KEY_SYMBOL, "Multiple symbols for level %d/group %u on key %s; " "Using %s, ignoring %s\n", @@ -320,47 +361,43 @@ MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber, (clobber ? "from" : "to"), (clobber ? "to" : "from")); } - - if (clobber) { - /* Use `from` keysyms and actions */ - if (report && !XkbLevelHasNoAction(intoLevel)) { - if (fromLevel->num_syms > 1) { - log_warn( - info->ctx, XKB_WARNING_CONFLICTING_KEY_ACTION, - "Multiple actions for level %d/group %u " - "on key %s; Using from, ignoring to\n", - i + 1, group + 1, - KeyNameText(info->ctx, key_name)); - } else { - log_warn( - info->ctx, XKB_WARNING_CONFLICTING_KEY_ACTION, - "Multiple actions for level %d/group %u " - "on key %s; Using %s, ignoring %s\n", - i + 1, group + 1, - KeyNameText(info->ctx, key_name), - ActionTypeText(fromLevel->a.action.type), - ActionTypeText(intoLevel->a.action.type)); + if (fromHasNoKeysym) { + /* No keysym to copy */ + } else if (clobber) { + /* Override: copy any defined keysym from `from` */ + if (unlikely(intoLevel->num_syms > 1)) { + for (unsigned int k = 0; k < fromLevel->num_syms; k++) { + if (fromLevel->s.syms[k] != XKB_KEY_NoSymbol) + intoLevel->s.syms[k] = fromLevel->s.syms[k]; + } + } else if (fromLevel->s.sym != XKB_KEY_NoSymbol) { + intoLevel->s.sym = fromLevel->s.sym; + } + fromKeysymsCount++; + } else { + /* Augment: copy only the keysyms from `from` that are + * undefined in `into` */ + if (unlikely(intoLevel->num_syms > 1)) { + bool copiedSome = false; + for (unsigned int k = 0; k < intoLevel->num_syms; k++) { + if (intoLevel->s.syms[k] == XKB_KEY_NoSymbol) { + intoLevel->s.syms[k] = fromLevel->s.syms[k]; + copiedSome = true; + } } + fromKeysymsCount += copiedSome; + } else if (intoLevel->s.sym == XKB_KEY_NoSymbol) { + intoLevel->s.sym = fromLevel->s.sym; + fromKeysymsCount++; } - StealLevelInfo(intoLevel, fromLevel); - actions_replaced = true; } } /* Handle actions */ - if (actions_replaced) { - /* Already handled, included incompatible keysyms/actions count */ - } else if (XkbLevelHasNoAction(fromLevel)) { - /* It's empty for consistency with other comparisons */ - } else if (XkbLevelHasNoAction(intoLevel)) { - /* Take actions from `from` */ - assert(intoLevel->num_syms == fromLevel->num_syms); - StealLevelInfo(intoLevel, fromLevel); - } else { + if (!XkbLevelsSameActions(intoLevel, fromLevel)) { /* Incompatible actions */ - assert(intoLevel->num_syms == fromLevel->num_syms); - if (report) { - if (intoLevel->num_syms > 1) { + if (report && !(intoHasNoAction || fromHasNoAction)) { + if (unlikely(intoLevel->num_syms > 1)) { log_warn( info->ctx, XKB_WARNING_CONFLICTING_KEY_ACTION, "Multiple actions for level %d/group %u on key %s; " @@ -386,18 +423,60 @@ MergeGroups(SymbolsInfo *info, GroupInfo *into, GroupInfo *from, bool clobber, ActionTypeText(ignore->type)); } } - if (clobber) - StealLevelInfo(intoLevel, fromLevel); + if (fromHasNoAction) + continue; + if (clobber) { + /* Override: copy any defined action from `from` */ + if (unlikely(fromLevel->num_syms > 1)) { + for (unsigned int k = 0; k < fromLevel->num_syms; k++) { + if (fromLevel->a.actions[k].type != ACTION_TYPE_NONE) + intoLevel->a.actions[k] = fromLevel->a.actions[k]; + } + } else if (fromLevel->a.action.type != ACTION_TYPE_NONE) { + intoLevel->a.action = fromLevel->a.action; + } + fromActionsCount++; + } else { + /* Augment: copy only the actions from `from` that are + * undefined in `into` */ + if (unlikely(intoLevel->num_syms > 1)) { + bool copiedSome = false; + for (unsigned int k = 0; k < intoLevel->num_syms; k++) { + if (intoLevel->a.actions[k].type == ACTION_TYPE_NONE) { + intoLevel->a.actions[k] = fromLevel->a.actions[k]; + copiedSome = true; + } + } + fromActionsCount += copiedSome; + } else if (intoLevel->a.action.type == ACTION_TYPE_NONE) { + intoLevel->a.action = fromLevel->a.action; + fromActionsCount++; + } + } } } } /* If @from has extra levels, get them as well. */ darray_foreach_from(level, from->levels, levels_in_both) { darray_append(into->levels, *level); + /* We may have stolen keysyms or actions arrays: + * do not free them when clearing `from` */ level->num_syms = 0; + fromKeysymsCount++; + fromActionsCount++; + } + if (fromKeysymsCount) { + /* Reset defined keysyms field if we used no keysym from `into` */ + if (fromKeysymsCount == darray_size(into->levels)) + into->defined &= ~GROUP_FIELD_SYMS; + into->defined |= (from->defined & GROUP_FIELD_SYMS); + } + if (fromActionsCount) { + /* Reset defined actions field if we used no action from `into` */ + if (fromActionsCount == darray_size(into->levels)) + into->defined &= ~GROUP_FIELD_ACTS; + into->defined |= (from->defined & GROUP_FIELD_ACTS); } - into->defined |= (from->defined & GROUP_FIELD_ACTS); - into->defined |= (from->defined & GROUP_FIELD_SYMS); return true; }