test/compose
build_only_tests = \
test/rmlvo-to-kccgst \
+ test/rmlvo-to-keymap \
test/print-compiled-keymap
run_only_tests = \
test/symbols-leak-test.bash
test_keyseq_LDADD = $(TESTS_LDADD)
test_rulescomp_LDADD = $(TESTS_LDADD)
test_rmlvo_to_kccgst_LDADD = $(TESTS_LDADD)
+test_rmlvo_to_keymap_LDADD = $(TESTS_LDADD)
test_print_compiled_keymap_LDADD = $(TESTS_LDADD)
test_compose_LDADD = $(TESTS_LDADD) $(RT_LIBS)
# Demo programs.
executable('rmlvo-to-kccgst', 'test/rmlvo-to-kccgst.c', dependencies: test_dep)
+executable('rmlvo-to-keymap', 'test/rmlvo-to-keymap.c', dependencies: test_dep)
executable('print-compiled-keymap', 'test/print-compiled-keymap.c', dependencies: test_dep)
if cc.has_header('linux/input.h')
executable('interactive-evdev', 'test/interactive-evdev.c', dependencies: test_dep)
executable('interactive-wayland', 'test/interactive-wayland.c', xdg_shell_sources, dependencies: [test_dep, wayland_client_dep])
endif
+# xkeyboard-config "verifier"
+xkct_config = configuration_data()
+xkct_config.set('MESON_BUILD_ROOT', meson.build_root())
+xkct_config.set('XKB_CONFIG_ROOT', XKBCONFIGROOT)
+configure_file(input: 'test/xkeyboard-config-test.py.in',
+ output: 'xkeyboard-config-test',
+ configuration: xkct_config,
+ install: false)
+
# Benchmarks.
libxkbcommon_bench_internal = static_library(
log
interactive-evdev
rmlvo-to-kccgst
+rmlvo-to-keymap
print-compiled-keymap
atom
x11
--- /dev/null
+/*
+ * Copyright © 2018 Red Hat, Inc.
+ *
+ * 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 <assert.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include "xkbcommon/xkbcommon.h"
+
+static bool print = false;
+
+static void
+usage(void)
+{
+ printf("Usage: %s [--print] [--rules <rules>] [--layout <layout>] [--variant <variant>] [--options <option>]\n",
+ program_invocation_short_name);
+ printf("This tool tests the compilation from RMLVO to a keymap.\n");
+ printf("--print print the resulting keymap\n");
+}
+
+static bool
+parse_options(int argc, char **argv, struct xkb_rule_names *names)
+{
+ enum options {
+ OPT_PRINT,
+ OPT_RULES,
+ OPT_MODEL,
+ OPT_LAYOUT,
+ OPT_VARIANT,
+ OPT_OPTION,
+ };
+ static struct option opts[] = {
+ {"help", no_argument, 0, 'h'},
+ {"print", no_argument, 0, OPT_PRINT},
+ {"rules", required_argument, 0, OPT_RULES},
+ {"model", required_argument, 0, OPT_MODEL},
+ {"layout", required_argument, 0, OPT_LAYOUT},
+ {"variant", required_argument, 0, OPT_VARIANT},
+ {"options", required_argument, 0, OPT_OPTION},
+ {0, 0, 0, 0},
+ };
+
+ while (1) {
+ int c;
+ int option_index = 0;
+ c = getopt_long(argc, argv, "h", opts, &option_index);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'h':
+ usage();
+ exit(0);
+ case OPT_PRINT:
+ print = true;
+ break;
+ case OPT_RULES:
+ names->rules = optarg;
+ break;
+ case OPT_MODEL:
+ names->model = optarg;
+ break;
+ case OPT_LAYOUT:
+ names->layout = optarg;
+ break;
+ case OPT_VARIANT:
+ names->variant = optarg;
+ break;
+ case OPT_OPTION:
+ names->options = optarg;
+ break;
+ default:
+ usage();
+ exit(1);
+ }
+
+ }
+
+ return true;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct xkb_context *ctx;
+ struct xkb_keymap *keymap;
+ struct xkb_rule_names names = {
+ .rules = NULL,
+ .model = NULL,
+ .layout = NULL,
+ .variant = NULL,
+ .options = NULL,
+ };
+ int rc;
+
+ if (argc <= 1) {
+ usage();
+ return 1;
+ }
+
+ if (!parse_options(argc, argv, &names))
+ return 1;
+
+ ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS);
+ assert(ctx);
+
+ keymap = xkb_keymap_new_from_names(ctx, &names, XKB_KEYMAP_COMPILE_NO_FLAGS);
+ rc = (keymap == NULL);
+
+ if (rc == 0 && print)
+ printf("%s\n", xkb_keymap_get_as_string(keymap,
+ XKB_KEYMAP_FORMAT_TEXT_V1));
+
+ xkb_keymap_unref(keymap);
+ xkb_context_unref(ctx);
+
+ return rc;
+}
--- /dev/null
+#!/usr/bin/env python
+import sys
+import subprocess
+import os
+import xml.etree.ElementTree as ET
+
+
+verbose = True
+
+DEFAULT_RULES_XML = '@XKB_CONFIG_ROOT@/rules/evdev.xml'
+
+# Meson needs to fill this in so we can call the tool in the buildir.
+EXTRA_PATH='@MESON_BUILD_ROOT@'
+os.environ['PATH'] = ':'.join([EXTRA_PATH, os.getenv('PATH')])
+
+
+# The function generating the progress bar (if any).
+progress_bar = lambda x, desc: x
+if os.isatty(sys.stdout.fileno()):
+ try:
+ from tqdm import tqdm
+ progress_bar = tqdm
+
+ verbose = False
+ except ImportError:
+ pass
+
+
+def xkbcommontool(r='evdev', m='pc105', l='us', v=None, o=None):
+ args = [
+ 'rmlvo-to-keymap',
+ '--rules', r,
+ '--model', m,
+ '--layout', l,
+ ]
+ if v is not None:
+ args += ['--variant', v]
+ if o is not None:
+ args += ['--options', o]
+
+ if verbose:
+ print(':: {}'.format(' '.join(args)))
+
+ try:
+ output = subprocess.check_output(args, stderr=subprocess.STDOUT)
+ if verbose:
+ print(output.decode('utf-8'))
+ except subprocess.CalledProcessError as err:
+ print('ERROR: Failed to compile: {}'.format(' '.join(args)))
+ print(err.output.decode('utf-8'))
+ sys.exit(1)
+
+
+def xkbcomp(r='evdev', m='pc105', l='us', v='', o=''):
+ args = ['setxkbmap', '-print']
+ if r is not None:
+ args.append('-rules')
+ args.append('{}'.format(r))
+ if m is not None:
+ args.append('-model')
+ args.append('{}'.format(m))
+ if l is not None:
+ args.append('-layout')
+ args.append('{}'.format(l))
+ if o is not None:
+ args.append('-option')
+ args.append('{}'.format(o))
+
+ if verbose:
+ print(':: {}'.format(' '.join(args)))
+
+ try:
+ xkbcomp_args = ['xkbcomp', '-xkb', '-', '-']
+
+ setxkbmap = subprocess.Popen(args, stdout=subprocess.PIPE)
+ xkbcomp = subprocess.Popen(xkbcomp_args, stdin=setxkbmap.stdout,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ setxkbmap.stdout.close()
+ stdout, stderr = xkbcomp.communicate()
+ if xkbcomp.returncode != 0:
+ print('ERROR: Failed to compile: {}'.format(' '.join(args)))
+ if xkbcomp.returncode != 0 or verbose:
+ print(stdout.decode('utf-8'))
+ print(stderr.decode('utf-8'))
+
+ # This catches setxkbmap errors.
+ except subprocess.CalledProcessError as err:
+ print('ERROR: Failed to compile: {}'.format(' '.join(args)))
+ print(err.output.decode('utf-8'))
+
+
+def parse(root):
+ layouts = root.findall('layoutList/layout')
+
+ options = [
+ e.text
+ for e in root.findall('optionList/group/option/configItem/name')
+ ]
+
+ # Switch this to xkbcomp if needed.
+ tool = xkbcommontool
+ # tool = xkbcomp
+
+ for l in progress_bar(layouts, 'layout '):
+ layout = l.find('configItem/name').text
+ tool(l=layout)
+
+ variants = l.findall('variantList/variant')
+ for v in progress_bar(variants, 'variant'):
+ variant = v.find('configItem/name').text
+ tool(l=layout, v=variant)
+
+ for option in progress_bar(options, 'option '):
+ tool(l=layout, v=variant, o=option)
+
+
+def main(args):
+ try:
+ path = args[1]
+ except IndexError:
+ path = DEFAULT_RULES_XML
+
+ with open(path) as f:
+ root = ET.fromstring(f.read())
+ parse(root)
+
+
+if __name__ == '__main__':
+ main(sys.argv)