├── fuzz ├── .gitignore ├── compose │ ├── dict │ ├── testcases │ │ └── Compose │ └── target.c ├── fuzz.sh └── keymap │ ├── target.c │ ├── testcases │ └── input.xkb │ └── dict ├── doc ├── .gitignore ├── doxygen-extra.css ├── Doxyfile.in ├── compat.md └── rules-format.md ├── test ├── data │ ├── .gitattributes │ ├── rules │ │ ├── inc-src-looped │ │ ├── inc-src-nested │ │ ├── inc-src-simple │ │ ├── inc-src-loop-twice │ │ ├── inc-src-before-after │ │ ├── inc-src-options │ │ ├── inc-dst-simple │ │ ├── inc-dst-loop-twice │ │ ├── groups │ │ ├── simple │ │ ├── multiple-options │ │ ├── index │ │ └── xkb.dtd │ ├── keycodes │ │ ├── empty │ │ ├── aliases-xkbcommon │ │ └── aliases │ ├── symbols │ │ ├── empty │ │ ├── rupeesign │ │ ├── terminate │ │ ├── garbage │ │ ├── eurosign │ │ ├── awesome │ │ ├── capslock │ │ ├── shift │ │ ├── compose │ │ ├── pc │ │ ├── srvr_ctrl │ │ ├── kpdl │ │ └── altwin │ ├── keymaps │ │ ├── bad.xkb │ │ ├── syntax-error2.xkb │ │ ├── basic.xkb │ │ └── divide-by-zero.xkb │ ├── types │ │ ├── complete │ │ ├── mousekeys │ │ ├── iso9995 │ │ ├── basic │ │ ├── numpad │ │ └── pc │ ├── compat │ │ ├── complete │ │ ├── pc │ │ ├── caps │ │ ├── lednum │ │ ├── ledcaps │ │ ├── ledscroll │ │ ├── basic │ │ ├── accessx │ │ ├── level5 │ │ ├── iso9995 │ │ ├── xfree86 │ │ └── misc │ └── sync.sh ├── .gitignore ├── symbols-leak-test.py ├── utils.c ├── test-keysym.py ├── filecomp.c ├── test.h ├── x11.c ├── buffercomp.c ├── stringcomp.c └── log.c ├── src ├── xkbcomp │ ├── .gitignore │ ├── rules.h │ ├── vmod.h │ ├── parser-priv.h │ ├── include.h │ ├── action.h │ ├── keywords.gperf │ ├── expr.h │ ├── ast-build.h │ ├── vmod.c │ └── xkbcomp-priv.h ├── utf8.h ├── compose │ ├── parser.h │ └── paths.h ├── atom.h ├── x11 │ ├── state.c │ └── x11-priv.h ├── text.h ├── util-list.h ├── keysym.h └── util-list.c ├── bench ├── .gitignore ├── bench.h ├── rulescomp.c ├── rules.c ├── compose.c ├── key-proc.c ├── bench.c └── x11.c ├── scripts ├── update-keywords ├── update-keysyms ├── doxygen-wrapper ├── makeheader └── makekeys ├── xkbcommon-x11.map ├── .editorconfig ├── tools ├── xkbcli-how-to-type.1 ├── xkbcli-interactive-x11.1 ├── xkbcli-interactive-wayland.1 ├── xkbcli-list.1 ├── xkbcli-compile-keymap.1 ├── xkbcli.1 ├── xkbcli-interactive-evdev.1 ├── tools-common.h └── xkbcli.c ├── meson_options.txt ├── xkbcommon └── xkbcommon-names.h ├── xkbregistry.map ├── README.md ├── PACKAGING ├── xkbcommon.map └── .github └── workflows └── main.yml /fuzz/.gitignore: -------------------------------------------------------------------------------- 1 | findings/ 2 | -------------------------------------------------------------------------------- /doc/.gitignore: -------------------------------------------------------------------------------- 1 | Doxyfile 2 | html/ 3 | -------------------------------------------------------------------------------- /test/data/.gitattributes: -------------------------------------------------------------------------------- 1 | * eol=lf 2 | -------------------------------------------------------------------------------- /src/xkbcomp/.gitignore: -------------------------------------------------------------------------------- 1 | parser.c 2 | parser.h 3 | -------------------------------------------------------------------------------- /test/data/rules/inc-src-looped: -------------------------------------------------------------------------------- 1 | ! include %S/inc-src-looped 2 | -------------------------------------------------------------------------------- /test/data/rules/inc-src-nested: -------------------------------------------------------------------------------- 1 | ! include %S/inc-src-simple 2 | -------------------------------------------------------------------------------- /bench/.gitignore: -------------------------------------------------------------------------------- 1 | key-proc 2 | rules 3 | rulescomp 4 | compose 5 | -------------------------------------------------------------------------------- /fuzz/compose/dict: -------------------------------------------------------------------------------- 1 | "Ctrl" 2 | "Lock" 3 | "Caps" 4 | "Shift" 5 | "Alt" 6 | "Meta" 7 | "None" 8 | "acute" 9 | -------------------------------------------------------------------------------- /test/data/keycodes/empty: -------------------------------------------------------------------------------- 1 | default xkb_keycodes "empty" { 2 | minimum= 8; 3 | maximum= 255; 4 | }; 5 | -------------------------------------------------------------------------------- /test/data/rules/inc-src-simple: -------------------------------------------------------------------------------- 1 | ! layout = symbols 2 | my_layout = my_symbols 3 | 4 | ! include %S/inc-dst-simple 5 | -------------------------------------------------------------------------------- /test/data/rules/inc-src-loop-twice: -------------------------------------------------------------------------------- 1 | ! model = keycodes 2 | my_model = my_keycodes 3 | 4 | ! include %S/inc-dst-loop-twice 5 | -------------------------------------------------------------------------------- /test/data/symbols/empty: -------------------------------------------------------------------------------- 1 | default partial alphanumeric_keys modifier_keys 2 | xkb_symbols "basic" { 3 | name[Group1]= "Empty"; 4 | }; 5 | -------------------------------------------------------------------------------- /fuzz/compose/testcases/Compose: -------------------------------------------------------------------------------- 1 | : "~" asciitilde # X 2 | Meta !Alt ~Shift : "\"\'\x43\123abc" acute # Y 3 | -------------------------------------------------------------------------------- /test/data/symbols/rupeesign: -------------------------------------------------------------------------------- 1 | // keyboards having the RupeeSign on the 4 key 2 | partial 3 | xkb_symbols "4" { 4 | key { [ NoSymbol, NoSymbol, U20B9 ] }; 5 | }; 6 | -------------------------------------------------------------------------------- /test/data/keymaps/bad.xkb: -------------------------------------------------------------------------------- 1 | xkb_keymap { 2 | xkb_types { include "complete" }; 3 | xkb_compat { include "complete" }; 4 | xkb_symbols { include "pc+us" }; 5 | }; 6 | -------------------------------------------------------------------------------- /test/data/rules/inc-src-before-after: -------------------------------------------------------------------------------- 1 | ! model = keycodes 2 | before_model = my_keycodes 3 | 4 | ! include %S/inc-dst-simple 5 | 6 | ! layout = symbols 7 | after_layout = my_symbols 8 | -------------------------------------------------------------------------------- /doc/doxygen-extra.css: -------------------------------------------------------------------------------- 1 | div#top, div.header, div.contents { 2 | margin-left: auto; 3 | margin-right: auto; 4 | width: 960px; 5 | } 6 | 7 | .footer { 8 | display: none; 9 | } 10 | -------------------------------------------------------------------------------- /scripts/update-keywords: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this if you add/remove a new keyword to the xkbcomp scanner, 3 | # or just want to regenerate the gperf file. 4 | gperf < src/xkbcomp/keywords.gperf > src/xkbcomp/keywords.c 5 | -------------------------------------------------------------------------------- /xkbcommon-x11.map: -------------------------------------------------------------------------------- 1 | V_0.5.0 { 2 | global: 3 | xkb_x11_setup_xkb_extension; 4 | xkb_x11_get_core_keyboard_device_id; 5 | xkb_x11_keymap_new_from_device; 6 | xkb_x11_state_new_from_device; 7 | local: 8 | *; 9 | }; 10 | -------------------------------------------------------------------------------- /test/data/keymaps/syntax-error2.xkb: -------------------------------------------------------------------------------- 1 | xkb_keymap { 2 | xkb_compatibility "complete" { 3 | interpret ISO_Level2_Latch+Exactly(Shift) { 4 | action == LatchMods(modifiers=Shift,clearLocks,latchToLock); 5 | }; 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /test/data/keymaps/basic.xkb: -------------------------------------------------------------------------------- 1 | xkb_keymap { 2 | xkb_keycodes { include "evdev+aliases(qwerty)" }; 3 | xkb_types { include "complete" }; 4 | xkb_compat { include "complete" }; 5 | xkb_symbols { include "pc+us" }; 6 | }; 7 | -------------------------------------------------------------------------------- /test/data/types/complete: -------------------------------------------------------------------------------- 1 | default xkb_types "complete" { 2 | include "basic" 3 | include "mousekeys" 4 | include "pc" 5 | include "iso9995" 6 | include "level5" 7 | include "extra" 8 | include "numpad" 9 | }; 10 | -------------------------------------------------------------------------------- /test/data/symbols/terminate: -------------------------------------------------------------------------------- 1 | default partial modifier_keys 2 | xkb_symbols "ctrl_alt_bksp" { 3 | key { 4 | type="CTRL+ALT", 5 | symbols[Group1] = [ NoSymbol, NoSymbol, NoSymbol, NoSymbol, Terminate_Server ] 6 | }; 7 | }; 8 | -------------------------------------------------------------------------------- /test/data/types/mousekeys: -------------------------------------------------------------------------------- 1 | default partial xkb_types "default" { 2 | virtual_modifiers Alt; 3 | 4 | type "SHIFT+ALT" { 5 | modifiers = Shift+Alt; 6 | map[Shift+Alt] = Level2; 7 | level_name[Level1] = "Base"; 8 | level_name[Level2] = "Shift+Alt"; 9 | }; 10 | }; 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | end_of_line = lf 6 | trim_trailing_whitespace = true 7 | insert_final_newline = true 8 | indent_style = space 9 | indent_size = 4 10 | max_line_length = 80 11 | 12 | [*.yml] 13 | indent_style = space 14 | indent_size = 2 15 | -------------------------------------------------------------------------------- /test/data/compat/complete: -------------------------------------------------------------------------------- 1 | default xkb_compatibility "complete" { 2 | include "basic" 3 | augment "iso9995" 4 | augment "mousekeys" 5 | augment "accessx(full)" 6 | augment "misc" 7 | augment "xfree86" 8 | augment "level5" 9 | augment "caps(caps_lock)" 10 | }; 11 | -------------------------------------------------------------------------------- /scripts/update-keysyms: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run this to regenerate xkbcommon-keysyms.h from the X11 headers 3 | # defining the keysyms and update the name <-> keysym mapping. 4 | export LC_CTYPE=C 5 | scripts/makeheader > xkbcommon/xkbcommon-keysyms.h 6 | scripts/makekeys xkbcommon/xkbcommon-keysyms.h > src/ks_tables.h 7 | -------------------------------------------------------------------------------- /scripts/doxygen-wrapper: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # Run doxygen such that the working directory is the source root. 3 | # This is needed for various reasons (e.g. relative references in md files). 4 | # Do not use directly. 5 | DOXYGEN="$1" 6 | DOXYFILE="$2" 7 | ABS_TOP_SRCDIR="$3" 8 | cd "$ABS_TOP_SRCDIR" && exec "$DOXYGEN" "$DOXYFILE" 9 | -------------------------------------------------------------------------------- /test/data/rules/inc-src-options: -------------------------------------------------------------------------------- 1 | ! option = compat 2 | option111 = +substring 3 | option1 = +some:compat 4 | option11 = +group(bla) 5 | 6 | ! include %S/inc-dst-simple 7 | 8 | ! option = symbols 9 | option3 = +compose(foo)+keypad(bar) 10 | colon:opt = +altwin(menu) 11 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | *.trs 3 | filecomp 4 | rulescomp 5 | keymap 6 | keysym 7 | state 8 | context 9 | rules-file 10 | stringcomp 11 | buffercomp 12 | keyseq 13 | log 14 | interactive-evdev 15 | rmlvo-to-kccgst 16 | rmlvo-to-keymap 17 | print-compiled-keymap 18 | atom 19 | x11 20 | interactive-x11 21 | interactive-wayland 22 | utf8 23 | x11comp 24 | compose 25 | -------------------------------------------------------------------------------- /test/data/compat/pc: -------------------------------------------------------------------------------- 1 | default partial xkb_compatibility "pc" { 2 | 3 | // Sets the "Alt" virtual modifier. 4 | 5 | virtual_modifiers Alt; 6 | 7 | setMods.clearLocks= True; 8 | interpret Alt_L+Any { 9 | virtualModifier= Alt; 10 | action = SetMods(modifiers=modMapMods); 11 | }; 12 | 13 | interpret Alt_R+Any { 14 | virtualModifier= Alt; 15 | action = SetMods(modifiers=modMapMods); 16 | }; 17 | }; 18 | -------------------------------------------------------------------------------- /test/data/keymaps/divide-by-zero.xkb: -------------------------------------------------------------------------------- 1 | xkb_keymap { 2 | xkb_keycodes { 3 | = 1; 4 | }; 5 | 6 | xkb_types { 7 | virtual_modifiers NumLock; 8 | }; 9 | 10 | xkb_compatibility { 11 | virtual_modifiers NumLock; 12 | interpret KP_1+AnyOfOrNone(all) { 13 | repeat= True; 14 | action= MovePtr(x=(1/0),y=+1); 15 | }; 16 | }; 17 | 18 | xkb_symbols { 19 | key { [ NoSymbol, Hyper_L ] }; 20 | }; 21 | }; 22 | -------------------------------------------------------------------------------- /fuzz/fuzz.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -e 3 | 4 | case "$1" in 5 | keymap|compose) 6 | ;; 7 | *) 8 | echo "usage: $0 keymap|compose" 1>&2 9 | exit 1 10 | ;; 11 | esac 12 | 13 | export CC=afl-clang-fast 14 | export AFL_HARDEN=1 15 | test -d fuzz/build || meson setup -Db_lto=true fuzz/build 16 | ninja -C fuzz/build 17 | afl-fuzz -i fuzz/$1/testcases -x fuzz/$1/dict -o fuzz/$1/findings -t 200 -m 10 -- ./fuzz/build/fuzz-$1 @@ 18 | -------------------------------------------------------------------------------- /test/data/rules/inc-dst-simple: -------------------------------------------------------------------------------- 1 | ! model = keycodes 2 | my_model = my_keycodes 3 | * = default_keycodes 4 | 5 | ! layout variant = symbols 6 | my_layout my_variant = my_symbols+extra_variant 7 | 8 | ! layout = symbols 9 | * = default_symbols 10 | 11 | ! model = types 12 | * = default_types 13 | 14 | ! model = compat 15 | * = default_compat 16 | 17 | ! option = compat 18 | my_option = |some:compat 19 | -------------------------------------------------------------------------------- /test/data/types/iso9995: -------------------------------------------------------------------------------- 1 | default partial xkb_types "default" { 2 | 3 | // A key type which can be used to implement 4 | // an ISO9995-style level-three shift. 5 | 6 | virtual_modifiers LevelThree; 7 | 8 | type "THREE_LEVEL" { 9 | modifiers = Shift+LevelThree; 10 | map[None] = Level1; 11 | map[Shift] = Level2; 12 | map[LevelThree] = Level3; 13 | map[Shift+LevelThree] = Level3; 14 | level_name[Level1] = "Base"; 15 | level_name[Level2] = "Shift"; 16 | level_name[Level3] = "Level3"; 17 | }; 18 | }; 19 | -------------------------------------------------------------------------------- /test/data/symbols/garbage: -------------------------------------------------------------------------------- 1 | default alphanumeric_keys 2 | xkb_symbols "garbage" { 3 | include "us" 4 | 5 | name[Group1]= "My garbage Layout"; 6 | 7 | // The garbage keysym will *not* override the corresponding symbol from the 8 | // 'us' layout 9 | key { [ keysym_is_garbage, exclam ] }; 10 | 11 | // AE13 is unused by 'us', use it to avoid fallback to the 'us' definition. 12 | // Define with 2 levels but first level is a garbage symbol. 13 | key { [ keysym_is_garbage, asciitilde ] }; 14 | }; 15 | -------------------------------------------------------------------------------- /test/data/compat/caps: -------------------------------------------------------------------------------- 1 | partial xkb_compatibility "caps_lock" { 2 | // Keysym Caps_Lock locks the Lock modifier. 3 | // With this definition, the keysym Caps_Lock can be used without binding 4 | // the whole key to a real modifier. This is essential when you don't 5 | // want to use Caps_Lock on the first level. 6 | // This should not have any compatibility issues when used together with 7 | // other layouts which don't utilize this capability. 8 | interpret Caps_Lock { 9 | action = LockMods(modifiers = Lock); 10 | }; 11 | }; 12 | -------------------------------------------------------------------------------- /test/data/rules/inc-dst-loop-twice: -------------------------------------------------------------------------------- 1 | ! model = keycodes 2 | * = default_keycodes 3 | 4 | ! layout variant = symbols 5 | my_layout my_variant = my_symbols+extra_variant 6 | 7 | ! layout = symbols 8 | my_layout = my_symbols 9 | * = default_symbols 10 | 11 | ! model = types 12 | * = default_types 13 | 14 | ! model = compat 15 | * = default_compat 16 | 17 | ! option = compat 18 | my_option = |some:compat 19 | 20 | ! include %S/inc-src-loop-twice 21 | -------------------------------------------------------------------------------- /test/data/compat/lednum: -------------------------------------------------------------------------------- 1 | // Use the Num Lock LED to show either 2 | // Num Lock, Group, or Shift Lock state. 3 | 4 | default partial xkb_compatibility "num_lock" { 5 | indicator "Num Lock" { 6 | !allowExplicit; 7 | whichModState= Locked; 8 | modifiers= NumLock; 9 | }; 10 | }; 11 | 12 | partial xkb_compatibility "group_lock" { 13 | indicator "Num Lock" { 14 | modifiers= None; 15 | groups=All-group1; 16 | }; 17 | }; 18 | 19 | partial xkb_compatibility "shift_lock" { 20 | indicator "Num Lock" { 21 | whichModState= Locked; 22 | modifiers= Shift; 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /test/data/compat/ledcaps: -------------------------------------------------------------------------------- 1 | // Use the Caps Lock LED to show either 2 | // Caps Lock, Group, or Shift Lock state. 3 | 4 | default partial xkb_compatibility "caps_lock" { 5 | indicator "Caps Lock" { 6 | !allowExplicit; 7 | whichModState= Locked; 8 | modifiers= Lock; 9 | }; 10 | }; 11 | 12 | partial xkb_compatibility "group_lock" { 13 | indicator "Caps Lock" { 14 | modifiers= None; 15 | groups=All-group1; 16 | }; 17 | }; 18 | 19 | partial xkb_compatibility "shift_lock" { 20 | indicator "Caps Lock" { 21 | whichModState= Locked; 22 | modifiers= Shift; 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /test/data/rules/groups: -------------------------------------------------------------------------------- 1 | ! $model_group = pc101 pc102 \ 2 | pc104\ 3 | pc105\ 4 | pc106 5 | ! $layout_group = ar br cr us 6 | ! $variant_group = 7 | 8 | ! model = keycodes 9 | $model_group = something(%m) 10 | * = default_keycodes 11 | 12 | ! layout variant = symbols 13 | $layout_group * = my_symbols+%(v) 14 | * * = default_symbols 15 | 16 | ! model = types 17 | * = default_types 18 | 19 | ! model = compat 20 | * = default_compat 21 | -------------------------------------------------------------------------------- /test/data/compat/ledscroll: -------------------------------------------------------------------------------- 1 | // Use the Scroll Lock LED to show either 2 | // Scroll Lock, Group, or Shift Lock state. 3 | 4 | default partial xkb_compatibility "scroll_lock" { 5 | indicator "Scroll Lock" { 6 | allowExplicit; 7 | whichModState= Locked; 8 | modifiers= ScrollLock; 9 | }; 10 | }; 11 | 12 | partial xkb_compatibility "group_lock" { 13 | indicator "Scroll Lock" { 14 | modifiers= None; 15 | groups=All-group1; 16 | }; 17 | }; 18 | 19 | partial xkb_compatibility "shift_lock" { 20 | indicator "Scroll Lock" { 21 | whichModState= Locked; 22 | modifiers= Shift; 23 | }; 24 | }; 25 | -------------------------------------------------------------------------------- /test/data/rules/simple: -------------------------------------------------------------------------------- 1 | ! model = keycodes 2 | my_model = my_keycodes 3 | * = default_keycodes 4 | 5 | ! layout variant = symbols 6 | my_layout my_variant = my_symbols+extra_variant 7 | 8 | ! layout = symbols 9 | my_layout = my_symbols 10 | * = default_symbols 11 | 12 | ! model = types 13 | my_model = my_types 14 | * = default_types 15 | 16 | ! model = compat 17 | my_model = my_compat 18 | * = default_compat 19 | 20 | ! option = compat 21 | my_option = |some:compat 22 | -------------------------------------------------------------------------------- /test/data/symbols/eurosign: -------------------------------------------------------------------------------- 1 | // Most keyboards have the EuroSign engraved on the E key 2 | partial 3 | xkb_symbols "e" { 4 | key { [ NoSymbol, NoSymbol, EuroSign, NoSymbol ] }; 5 | }; 6 | 7 | // Many Apple keyboards have the EuroSign engraved on the 2 key 8 | partial 9 | xkb_symbols "2" { 10 | key { [ NoSymbol, NoSymbol, EuroSign, NoSymbol ] }; 11 | }; 12 | 13 | // Some keyboards have the EuroSign engraved on the 4 key 14 | partial 15 | xkb_symbols "4" { 16 | key { [ NoSymbol, NoSymbol, EuroSign, NoSymbol ] }; 17 | }; 18 | 19 | // Many keyboards have the EuroSign engraved on the 5 key 20 | partial 21 | xkb_symbols "5" { 22 | key { [ NoSymbol, NoSymbol, EuroSign, NoSymbol ] }; 23 | }; 24 | -------------------------------------------------------------------------------- /test/data/types/basic: -------------------------------------------------------------------------------- 1 | default xkb_types "basic" { 2 | 3 | // Fairly standard definitions for 4 | // three of the four required key types. 5 | // The fourth type "KEYPAD" is defined in the "numpad" file. 6 | 7 | virtual_modifiers NumLock; 8 | 9 | type "ONE_LEVEL" { 10 | modifiers = None; 11 | map[None] = Level1; 12 | level_name[Level1]= "Any"; 13 | }; 14 | 15 | type "TWO_LEVEL" { 16 | modifiers = Shift; 17 | map[Shift] = Level2; 18 | level_name[Level1] = "Base"; 19 | level_name[Level2] = "Shift"; 20 | }; 21 | 22 | type "ALPHABETIC" { 23 | modifiers = Shift+Lock; 24 | map[Shift] = Level2; 25 | map[Lock] = Level2; 26 | level_name[Level1] = "Base"; 27 | level_name[Level2] = "Caps"; 28 | }; 29 | 30 | }; 31 | -------------------------------------------------------------------------------- /test/data/rules/multiple-options: -------------------------------------------------------------------------------- 1 | ! model = keycodes 2 | my_model = my_keycodes 3 | * = default_keycodes 4 | 5 | ! layout variant = symbols 6 | my_layout my_variant = my_symbols+extra_variant 7 | 8 | ! layout = symbols 9 | my_layout = my_symbols 10 | * = default_symbols 11 | 12 | ! model = types 13 | my_model = my_types 14 | * = default_types 15 | 16 | ! model = compat 17 | my_model = my_compat 18 | * = default_compat 19 | 20 | ! option = compat 21 | option111 = +substring 22 | option1 = +some:compat 23 | option11 = +group(bla) 24 | 25 | ! option = symbols 26 | option3 = +compose(foo)+keypad(bar) 27 | colon:opt = +altwin(menu) 28 | -------------------------------------------------------------------------------- /tools/xkbcli-how-to-type.1: -------------------------------------------------------------------------------- 1 | .Dd July 27, 2020 2 | .Dt XKBCLI\-HOW\-TO\-TYPE 1 3 | .Os 4 | . 5 | .Sh NAME 6 | .Nm "xkbcli how\-to\-type" 7 | .Nd query how to type a given Unicode codepoint 8 | . 9 | .Sh SYNOPSIS 10 | .Nm 11 | .Op options 12 | .Ar codepoint 13 | . 14 | .Sh DESCRIPTION 15 | .Nm 16 | prints the key combinations (keycode + modifiers) in the keymap's layouts which 17 | would produce the given Unicode codepoint. 18 | . 19 | .Bl -tag -width Ds 20 | .It Fl \-rules Ar rules 21 | The XKB ruleset 22 | . 23 | .It Fl \-model Ar model 24 | The XKB model 25 | . 26 | .It Fl \-layout Ar layout 27 | The XKB layout 28 | . 29 | .It Fl \-variant Ar variant 30 | The XKB layout variant 31 | . 32 | .It Fl \-options Ar options 33 | The XKB options 34 | .El 35 | . 36 | .Sh SEE ALSO 37 | .Xr xkbcli 1 , 38 | .Lk https://xkbcommon.org "The libxkbcommon online documentation" 39 | -------------------------------------------------------------------------------- /tools/xkbcli-interactive-x11.1: -------------------------------------------------------------------------------- 1 | .Dd July 27, 2020 2 | .Dt XKBCLI\-INTERACTIVE\-X11 1 3 | .Os 4 | . 5 | .Sh NAME 6 | .Nm "xkbcli interactive\-x11" 7 | .Nd interactive debugger for XKB keymaps 8 | . 9 | .Sh SYNOPSIS 10 | .Nm 11 | .Op Ar options 12 | . 13 | .Sh DESCRIPTION 14 | .Nm 15 | is a commandline tool to interactively debug XKB keymaps by listening to X11 events. 16 | . 17 | .Pp 18 | This requires an X server to be running. 19 | . 20 | .Pp 21 | Press the 22 | .Aq Escape 23 | key to exit. 24 | . 25 | .Pp 26 | This is a debugging tool, its behavior or output is not guaranteed to be stable. 27 | . 28 | .Bl -tag -width Ds 29 | .It Fl \-help 30 | Print help and exit 31 | .El 32 | . 33 | .Sh SEE ALSO 34 | .Xr xkbcli 1 , 35 | .Xr xkbcli\-interactive\-evdev 1 , 36 | .Xr xkbcli\-interactive\-wayland 1 , 37 | .Lk https://xkbcommon.org "The libxkbcommon online documentation" 38 | -------------------------------------------------------------------------------- /test/data/rules/index: -------------------------------------------------------------------------------- 1 | ! $layouts = al az br cn us 2 | 3 | ! layout option = symbols 4 | $layouts some:opt = +extra 5 | 6 | ! layout[1] option = symbols 7 | $layouts some:opt = +extra:1 8 | 9 | ! layout[2] option = symbols 10 | $layouts some:opt = +extra:2 11 | 12 | ! layout[3] option = symbols 13 | $layouts some:opt = +extra:3 14 | 15 | ! layout[4] option = symbols 16 | $layouts some:opt = +extra:4 17 | 18 | ! model = symbols 19 | * = default_symbols 20 | 21 | ! model = keycodes 22 | * = default_keycodes 23 | 24 | ! model = types 25 | * = default_types 26 | 27 | ! model = compat 28 | * = default_compat 29 | -------------------------------------------------------------------------------- /tools/xkbcli-interactive-wayland.1: -------------------------------------------------------------------------------- 1 | .Dd July 27, 2020 2 | .Dt XKBCLI\-INTERACTIVE\-WAYLAND 1 3 | .Os 4 | . 5 | .Sh NAME 6 | .Nm "xkbcli interactive\-wayland" 7 | .Nd interactive debugger for XKB keymaps 8 | . 9 | .Sh SYNOPSIS 10 | .Nm 11 | .Op Ar options 12 | . 13 | .Sh DESCRIPTION 14 | .Nm 15 | is a commandline tool to interactively debug XKB keymaps by listening to Wayland events. 16 | . 17 | .Pp 18 | This requires a Wayland compositor to be running. 19 | . 20 | .Pp 21 | Press the 22 | .Aq Escape 23 | key to exit. 24 | . 25 | .Pp 26 | This is a debugging tool, its behavior or output is not guaranteed to be stable. 27 | . 28 | .Bl -tag -width Ds 29 | .It Fl \-help 30 | Print help and exit 31 | .El 32 | . 33 | .Sh SEE ALSO 34 | .Xr xkbcli 1 , 35 | .Xr xkbcli\-interactive\-evdev 1 , 36 | .Xr xkbcli\-interactive\-x11 1 , 37 | .Lk https://xkbcommon.org "The libxkbcommon online documentation" 38 | -------------------------------------------------------------------------------- /tools/xkbcli-list.1: -------------------------------------------------------------------------------- 1 | .Dd July 27, 2020 2 | .Dt XKBCLI\-LIST 1 3 | .Os 4 | . 5 | .Sh NAME 6 | .Nm "xkbcli list" 7 | .Nd list available XKB models, layouts, variants and options 8 | . 9 | .Sh SYNOPSIS 10 | .Nm 11 | .Op Pa /path/to/xkbbase Oo Pa /path/to/xkbbase Oc ... 12 | . 13 | .Sh DESCRIPTION 14 | .Nm 15 | is a commandline tool to list available model, layout, variant and option (MLVO) values from the XKB registry. 16 | . 17 | .Pp 18 | Positional arguments provided on the commandline are treated as XKB base directory installations. 19 | . 20 | .Bl -tag -width Ds 21 | .It Fl \-help 22 | Print help and exit 23 | . 24 | .It Fl \-verbose 25 | Increase verbosity, use multiple times for debugging output 26 | . 27 | .It Fl \-ruleset Ar name 28 | Load the ruleset with the given name 29 | . 30 | .It Fl \-skip\-default\-paths 31 | Do not load the default XKB include paths 32 | . 33 | .It Fl \-load\-exotic 34 | Load exotic (extra) layouts 35 | .El 36 | . 37 | .Sh SEE ALSO 38 | .Xr xkbcli 1 , 39 | .Lk https://xkbcommon.org "The libxkbcommon online documentation" 40 | -------------------------------------------------------------------------------- /doc/Doxyfile.in: -------------------------------------------------------------------------------- 1 | PROJECT_NAME = @PACKAGE_NAME@ 2 | 3 | PROJECT_NUMBER = @PACKAGE_VERSION@ 4 | 5 | OUTPUT_DIRECTORY = @OUTPUT_DIRECTORY@ 6 | 7 | BRIEF_MEMBER_DESC = NO 8 | 9 | JAVADOC_AUTOBRIEF = YES 10 | 11 | OPTIMIZE_OUTPUT_FOR_C = YES 12 | 13 | EXTENSION_MAPPING = no_extension=md 14 | 15 | SORT_MEMBER_DOCS = NO 16 | 17 | QUIET = YES 18 | 19 | WARN_IF_UNDOCUMENTED = NO 20 | 21 | INPUT = @INPUT@ 22 | 23 | FILE_PATTERNS = *.c \ 24 | *.h 25 | 26 | RECURSIVE = YES 27 | 28 | USE_MDFILE_AS_MAINPAGE = README.md 29 | 30 | VERBATIM_HEADERS = NO 31 | 32 | ALPHABETICAL_INDEX = NO 33 | 34 | IGNORE_PREFIX = xkb_ \ 35 | XKB_ \ 36 | rxkb_ \ 37 | RXKB_ 38 | 39 | HTML_EXTRA_STYLESHEET = doc/doxygen-extra.css 40 | 41 | HTML_TIMESTAMP = NO 42 | 43 | ENUM_VALUES_PER_LINE = 1 44 | 45 | SEARCHENGINE = NO 46 | 47 | GENERATE_LATEX = NO 48 | -------------------------------------------------------------------------------- /test/data/symbols/awesome: -------------------------------------------------------------------------------- 1 | default alphanumeric_keys modifier_keys function_keys alternate_group 2 | xkb_symbols "awesome" { 3 | include "us" 4 | 5 | name[Group1]= "My Awesome Layout"; 6 | 7 | key { [ 2, at, Page_Up, Page_Up ] }; 8 | key { [ 3, numbersign, Page_Down, Page_Down ] }; 9 | 10 | key { [ q, Q, Escape, Escape ] }; 11 | key { [ w, W, Home, Home ] }; 12 | key { 13 | type="THREE_LEVEL", 14 | symbols=[ e, E, Up] 15 | }; 16 | key { [ r, R, End, End ] }; 17 | key { [ t, T, Tab, Tab ] }; 18 | 19 | key { [ a, A, Return, Return ] }; 20 | key { [ s, S, Left] }; 21 | key { [ d, D, Down] }; 22 | key { [ f, F, Righ] }; 23 | key { [ g, G, BackSpace, BackSpace ] }; 24 | 25 | key { [ b, B, Delete, Delete ] }; 26 | }; 27 | -------------------------------------------------------------------------------- /fuzz/keymap/target.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A target program for fuzzing the XKB keymap text format. 3 | * 4 | * Currently, just parses an input file, and hopefully doesn't crash or hang. 5 | */ 6 | #include "config.h" 7 | 8 | #include 9 | 10 | #include "xkbcommon/xkbcommon.h" 11 | 12 | int 13 | main(int argc, char *argv[]) 14 | { 15 | struct xkb_context *ctx; 16 | FILE *file; 17 | struct xkb_keymap *keymap; 18 | 19 | if (argc != 2) { 20 | fprintf(stderr, "usage: %s \n", argv[0]); 21 | return 1; 22 | } 23 | 24 | ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES | XKB_CONTEXT_NO_ENVIRONMENT_NAMES); 25 | assert(ctx); 26 | 27 | #ifdef __AFL_HAVE_MANUAL_CONTROL 28 | __AFL_INIT(); 29 | 30 | while (__AFL_LOOP(1000)) 31 | #endif 32 | { 33 | file = fopen(argv[1], "rb"); 34 | assert(file); 35 | keymap = xkb_keymap_new_from_file(ctx, file, 36 | XKB_KEYMAP_FORMAT_TEXT_V1, 37 | XKB_KEYMAP_COMPILE_NO_FLAGS); 38 | xkb_keymap_unref(keymap); 39 | fclose(file); 40 | } 41 | 42 | puts(keymap ? "OK" : "FAIL"); 43 | xkb_context_unref(ctx); 44 | } 45 | -------------------------------------------------------------------------------- /test/data/compat/basic: -------------------------------------------------------------------------------- 1 | // Minimal set of symbol interpretations to provide 2 | // reasonable default behavior (Num lock, Shift lock, 3 | // Caps lock, and Mode switch) and set up the 4 | // automatic updating of common keyboard LEDs. 5 | 6 | default xkb_compatibility "basic" { 7 | 8 | virtual_modifiers NumLock,AltGr; 9 | 10 | interpret.repeat= False; 11 | setMods.clearLocks= True; 12 | latchMods.clearLocks= True; 13 | latchMods.latchToLock= True; 14 | 15 | interpret Shift_Lock+AnyOf(Shift+Lock) { 16 | action= LockMods(modifiers=Shift); 17 | }; 18 | 19 | interpret Any+Lock { 20 | action= LockMods(modifiers=Lock); 21 | }; 22 | 23 | interpret Num_Lock+Any { 24 | virtualModifier= NumLock; 25 | action= LockMods(modifiers=NumLock); 26 | }; 27 | 28 | interpret Mode_switch { 29 | useModMapMods= level1; 30 | virtualModifier= AltGr; 31 | action= SetGroup(group=+1); 32 | }; 33 | 34 | interpret Any + Any { 35 | action= SetMods(modifiers=modMapMods); 36 | }; 37 | 38 | group 2 = AltGr; 39 | group 3 = AltGr; 40 | group 4 = AltGr; 41 | 42 | include "ledcaps" 43 | include "lednum" 44 | indicator "Shift Lock" { 45 | !allowExplicit; 46 | whichModState= Locked; 47 | modifiers= Shift; 48 | }; 49 | }; 50 | -------------------------------------------------------------------------------- /fuzz/compose/target.c: -------------------------------------------------------------------------------- 1 | /* 2 | * A target program for fuzzing the Compose text format. 3 | * 4 | * Currently, just parses an input file, and hopefully doesn't crash or hang. 5 | */ 6 | #include "config.h" 7 | 8 | #include 9 | 10 | #include "xkbcommon/xkbcommon.h" 11 | #include "xkbcommon/xkbcommon-compose.h" 12 | 13 | int 14 | main(int argc, char *argv[]) 15 | { 16 | struct xkb_context *ctx; 17 | FILE *file; 18 | struct xkb_compose_table *table; 19 | 20 | if (argc != 2) { 21 | fprintf(stderr, "usage: %s \n", argv[0]); 22 | return 1; 23 | } 24 | 25 | ctx = xkb_context_new(XKB_CONTEXT_NO_DEFAULT_INCLUDES | XKB_CONTEXT_NO_ENVIRONMENT_NAMES); 26 | assert(ctx); 27 | 28 | #ifdef __AFL_HAVE_MANUAL_CONTROL 29 | __AFL_INIT(); 30 | 31 | while (__AFL_LOOP(1000)) 32 | #endif 33 | { 34 | file = fopen(argv[1], "rb"); 35 | assert(file); 36 | table = xkb_compose_table_new_from_file(ctx, file, 37 | "en_US.UTF-8", 38 | XKB_COMPOSE_FORMAT_TEXT_V1, 39 | XKB_COMPOSE_COMPILE_NO_FLAGS); 40 | xkb_compose_table_unref(table); 41 | fclose(file); 42 | } 43 | 44 | puts(table ? "OK" : "FAIL"); 45 | xkb_context_unref(ctx); 46 | } 47 | -------------------------------------------------------------------------------- /test/data/compat/accessx: -------------------------------------------------------------------------------- 1 | default partial xkb_compatibility "basic" { 2 | interpret AccessX_Enable { 3 | action= LockControls(controls=AccessXKeys); 4 | }; 5 | }; 6 | 7 | partial xkb_compatibility "full" { 8 | 9 | interpret AccessX_Enable { 10 | action= LockControls(controls=AccessXKeys); 11 | }; 12 | 13 | interpret AccessX_Feedback_Enable { 14 | action= LockControls(controls=AccessXFeedback); 15 | }; 16 | 17 | interpret RepeatKeys_Enable { 18 | action= LockControls(controls=RepeatKeys); 19 | }; 20 | 21 | interpret SlowKeys_Enable { 22 | action= LockControls(controls=SlowKeys); 23 | }; 24 | 25 | interpret BounceKeys_Enable { 26 | action= LockControls(controls=BounceKeys); 27 | }; 28 | 29 | interpret StickyKeys_Enable { 30 | action= LockControls(controls=StickyKeys); 31 | }; 32 | 33 | interpret MouseKeys_Enable { 34 | action= LockControls(controls=MouseKeys); 35 | }; 36 | 37 | interpret MouseKeys_Accel_Enable { 38 | action= LockControls(controls=MouseKeysAccel); 39 | }; 40 | 41 | interpret Overlay1_Enable { 42 | action= LockControls(controls=Overlay1); 43 | }; 44 | 45 | interpret Overlay2_Enable { 46 | action= LockControls(controls=Overlay2); 47 | }; 48 | 49 | interpret AudibleBell_Enable { 50 | action= LockControls(controls=AudibleBell); 51 | }; 52 | }; 53 | -------------------------------------------------------------------------------- /test/data/rules/xkb.dtd: -------------------------------------------------------------------------------- 1 | 2 | 3 | 9 | 10 | 11 | 12 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 32 | 33 | 34 | 35 | 36 | 37 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/xkbcomp/rules.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Dan Nicholson 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef XKBCOMP_RULES_H 25 | #define XKBCOMP_RULES_H 26 | 27 | bool 28 | xkb_components_from_rules(struct xkb_context *ctx, 29 | const struct xkb_rule_names *rmlvo, 30 | struct xkb_component_names *out); 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/utf8.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Intel Corporation 3 | * Copyright © 2014 Ran Benita 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | * 24 | * Author: Rob Bradford 25 | */ 26 | 27 | #ifndef XKBCOMMON_UTF8_H 28 | #define XKBCOMMON_UTF8_H 29 | 30 | int 31 | utf32_to_utf8(uint32_t unichar, char *buffer); 32 | 33 | bool 34 | is_valid_utf8(const char *ss, size_t len); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /tools/xkbcli-compile-keymap.1: -------------------------------------------------------------------------------- 1 | .Dd July 27, 2020 2 | .Dt XKBCLI\-COMPILE\-KEYMAP 1 3 | .Os 4 | . 5 | .Sh NAME 6 | .Nm "xkbcli compile\-keymap" 7 | .Nd compile an XKB keymap 8 | . 9 | .Sh SYNOPSIS 10 | .Nm 11 | .Op Ar options 12 | . 13 | .Sh DESCRIPTION 14 | .Nm 15 | compiles and prints a keymap based on the given options. 16 | . 17 | .Bl -tag -width Ds 18 | .It Fl \-help 19 | Print help and exit 20 | . 21 | .It Fl \-verbose 22 | Enable verbose debugging output 23 | . 24 | .It Fl \-rmlvo 25 | Print the full RMLVO with the defaults filled in for missing elements 26 | . 27 | .It Fl \-from\-xkb 28 | Load the XKB file from stdin, ignore RMLVO options. 29 | This option must not be used with 30 | .Fl \-kccgst . 31 | . 32 | .It Fl \-include Ar PATH 33 | Add the given path to the include path list. 34 | This option is order\-dependent, include paths given first are searched first. 35 | If an include path is given, the default include path list is not used. 36 | Use 37 | .Fl -\-include\-defaults 38 | to add the default include paths. 39 | . 40 | .It Fl \-include\-defaults 41 | Add the default set of include directories. 42 | This option is order-dependent, include paths given first are searched first. 43 | . 44 | .It Fl \-rules Ar rules 45 | The XKB ruleset 46 | . 47 | .It Fl \-model Ar model 48 | The XKB model 49 | . 50 | .It Fl \-layout Ar layout 51 | The XKB layout 52 | . 53 | .It Fl \-variant Ar variant 54 | The XKB layout variant 55 | . 56 | .It Fl \-options Ar options 57 | The XKB options 58 | .El 59 | . 60 | .Sh SEE ALSO 61 | .Xr xkbcli 1 , 62 | .Lk https://xkbcommon.org "The libxkbcommon online documentation" 63 | -------------------------------------------------------------------------------- /fuzz/keymap/testcases/input.xkb: -------------------------------------------------------------------------------- 1 | xkb_keymap{ 2 | xkb_keycodes"0"{ 3 | minimum=0; 4 | maximum=500; 5 | =0; 6 | indicator 1="X"; 7 | alias=; 8 | }; 9 | xkb_types"X"{ 10 | virtual_modifiers NumLock; 11 | type"X"{ 12 | modifiers=Shift; 13 | map[Shift]=Level2; 14 | level_name[Level1]="X"; 15 | preserve[Shift]=Shift; 16 | }; 17 | }; 18 | partial xkb_compat{ 19 | virtual_modifiers Alt; 20 | interpret.useModMapMods=AnyLevel; 21 | interpret.repeat=False; 22 | interpret.locking=False; 23 | interpret ISO_Level2_Latch+Exactly(Shift){ 24 | repeat=True; 25 | virtualModifier=NumLock; 26 | useModMapMods=level1; 27 | action=LatchMods(modifiers=Shift,clearLocks,latchToLock); 28 | action=MovePtr(x=+0,y=-0); 29 | action=SwitchScreen(screen=00,!same); 30 | action=Private(type=0x80,data[0]=0x00); 31 | }; 32 | indicator"X"{whichModState=locked;modifiers=Lock;}; 33 | }; 34 | xkb_symbols{ 35 | name[group1]="X"; 36 | key{type[group2]="X",symbols[Group1]=[0,exclam],symbols[Group2]=[0xff,U00],symbols[Group3]=[z]}; 37 | modifier_map Control{}; 38 | }; 39 | default xkb_geometry"X"{ 40 | description="X"; 41 | width=470; 42 | shape.cornerRadius=1; 43 | shape"NORM"{cornerRadius=0,{[0.0,0]},{[0,0],[0,0.0]}}; 44 | solid"X"{shape="X";top=00;left=00;color="X";}; 45 | indicator.onColor="X"; 46 | indicator.top=00.0; 47 | indicator.shape="X"; 48 | indicator"X"{left=0;}; 49 | text.top=00; 50 | text.color="X"; 51 | text"X"{left=0;text="X";}; 52 | section.left=00; 53 | row.left=0; 54 | key.shape="X"; 55 | key.gap=1; 56 | section"X"{top=22;row{top=1;keys{{,color="X"},{,00.0},,,};};}; 57 | alias=; 58 | }; 59 | }; 60 | -------------------------------------------------------------------------------- /src/compose/parser.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef COMPOSE_PARSER_H 25 | #define COMPOSE_PARSER_H 26 | 27 | bool 28 | parse_string(struct xkb_compose_table *table, 29 | const char *string, size_t len, 30 | const char *file_name); 31 | 32 | bool 33 | parse_file(struct xkb_compose_table *table, 34 | FILE *file, const char *file_name); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /tools/xkbcli.1: -------------------------------------------------------------------------------- 1 | .Dd July 27, 2020 2 | .Dt XKBCLI 1 3 | .Os 4 | . 5 | .Sh NAME 6 | .Nm xkbcli 7 | .Nd tool to interact with XKB keymaps 8 | . 9 | .Sh SYNOPSIS 10 | .Nm 11 | .Ar command Bo arguments Bc 12 | . 13 | .Nm 14 | .Op Fl \-help | Fl \-version 15 | . 16 | .Sh DESCRIPTION 17 | .Nm 18 | is a commandline tool to query, compile and test XKB keymaps, layouts and other elements. 19 | . 20 | .Bl -tag -width Ds 21 | .It Fl \-help 22 | Print help and exit 23 | . 24 | .It Fl \-version 25 | Print the version and exit 26 | .El 27 | . 28 | .Ss COMMANDS 29 | .Bl -tag -width Ds 30 | .It Ic compile\-keymap 31 | Compile an XKB keymap, see 32 | .Xr xkbcli\-compile\-keymap 1 33 | 34 | .It Ic how\-to\-type 35 | Show how to type a given Unicode codepoint, see 36 | .Xr xkbcli\-how\-to\-type 1 37 | . 38 | .It Ic interactive\-x11 39 | Interactive debugger for XKB keymaps for X11, see 40 | .Xr xkbcli\-interactive\-x11 1 41 | . 42 | .It Ic interactive\-wayland 43 | Interactive debugger for XKB keymaps for Wayland, see 44 | .Xr xkbcli\-interactive\-wayland 1 45 | . 46 | .It Ic interactive\-evdev 47 | Interactive debugger for XKB keymaps for evdev, see 48 | .Xr xkbcli\-interactive\-evdev 1 49 | . 50 | .It Ic list 51 | List available layouts and more, see 52 | .Xr xkbcli\-list 1 53 | .El 54 | . 55 | .Pp 56 | Note that not all tools may be available on your system. 57 | . 58 | .Sh EXIT STATUS 59 | .Bl -tag -compact -width Ds 60 | .It 0 61 | exited successfully 62 | .It 1 63 | an error occured 64 | .It 2 65 | program was called with invalid arguments 66 | .El 67 | . 68 | .Sh SEE ALSO 69 | .Lk https://xkbcommon.org "The libxkbcommon online documentation" 70 | -------------------------------------------------------------------------------- /test/data/compat/level5: -------------------------------------------------------------------------------- 1 | // Fairly complete set of symbol interpretations 2 | // to provide reasonable default behavior. 3 | 4 | default partial xkb_compatibility "default" { 5 | 6 | virtual_modifiers LevelFive; 7 | 8 | interpret.repeat= False; 9 | setMods.clearLocks= True; 10 | latchMods.clearLocks= True; 11 | latchMods.latchToLock= True; 12 | 13 | interpret ISO_Level5_Shift+Any { 14 | useModMapMods= level1; 15 | virtualModifier= LevelFive; 16 | action= SetMods(modifiers=LevelFive); 17 | }; 18 | 19 | interpret ISO_Level5_Shift { 20 | action= SetMods(modifiers=LevelFive); 21 | }; 22 | 23 | interpret ISO_Level5_Latch+Any { 24 | useModMapMods= level1; 25 | virtualModifier= LevelFive; 26 | action= LatchMods(modifiers=LevelFive); 27 | }; 28 | 29 | interpret ISO_Level5_Latch { 30 | action= LatchMods(modifiers=LevelFive); 31 | }; 32 | 33 | interpret ISO_Level5_Lock+Any { 34 | useModMapMods= level1; 35 | virtualModifier= LevelFive; 36 | action= LockMods(modifiers=LevelFive); 37 | }; 38 | 39 | interpret ISO_Level5_Lock { 40 | action= LockMods(modifiers=LevelFive); 41 | }; 42 | }; 43 | 44 | partial xkb_compatibility "level5_lock" { 45 | // This defines a Level5-Lock using the NumLock real modifier 46 | // in order to create arbitrary level-behaviour, which would 47 | // not be possible with the virtual modifier. 48 | // See also: types/level5 : EIGHT_LEVEL_LEVEL_FIVE_LOCK 49 | // See also: symbols/level5(lock) 50 | 51 | virtual_modifiers NumLock; 52 | 53 | interpret ISO_Level5_Lock { 54 | action = LockMods(modifiers = NumLock); 55 | }; 56 | }; 57 | -------------------------------------------------------------------------------- /test/data/sync.sh: -------------------------------------------------------------------------------- 1 | #/bin/sh 2 | 3 | XKBCONFIGROOT='/usr/share/X11/xkb' 4 | 5 | if [ ! -d test/data ]; then 6 | echo "Run this from the top source dir" 7 | exit 1 8 | fi 9 | 10 | for file in \ 11 | symbols/terminate \ 12 | symbols/in \ 13 | symbols/keypad \ 14 | symbols/altwin \ 15 | symbols/ctrl \ 16 | symbols/eurosign \ 17 | symbols/inet \ 18 | symbols/shift \ 19 | symbols/pc \ 20 | symbols/ca \ 21 | symbols/cz \ 22 | symbols/srvr_ctrl \ 23 | symbols/capslock \ 24 | symbols/latin \ 25 | symbols/level5 \ 26 | symbols/macintosh_vndr/apple \ 27 | symbols/macintosh_vndr/us \ 28 | symbols/us \ 29 | symbols/nbsp \ 30 | symbols/il \ 31 | symbols/group \ 32 | symbols/compose \ 33 | symbols/level3 \ 34 | symbols/ru \ 35 | symbols/rupeesign \ 36 | symbols/kpdl \ 37 | symbols/de \ 38 | symbols/ch \ 39 | symbols/empty \ 40 | keycodes/xfree86 \ 41 | keycodes/aliases \ 42 | keycodes/evdev \ 43 | keycodes/empty \ 44 | types/complete \ 45 | types/pc \ 46 | types/basic \ 47 | types/iso9995 \ 48 | types/level5 \ 49 | types/numpad \ 50 | types/extra \ 51 | types/mousekeys \ 52 | compat/complete \ 53 | compat/lednum \ 54 | compat/pc \ 55 | compat/ledscroll \ 56 | compat/basic \ 57 | compat/misc \ 58 | compat/iso9995 \ 59 | compat/accessx \ 60 | compat/xfree86 \ 61 | compat/level5 \ 62 | compat/caps \ 63 | compat/ledcaps \ 64 | compat/mousekeys \ 65 | rules/base \ 66 | rules/evdev \ 67 | ; do 68 | cp "$XKBCONFIGROOT/$file" "test/data/$file" 69 | done 70 | -------------------------------------------------------------------------------- /src/xkbcomp/vmod.h: -------------------------------------------------------------------------------- 1 | /************************************************************ 2 | * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 | * 4 | * Permission to use, copy, modify, and distribute this 5 | * software and its documentation for any purpose and without 6 | * fee is hereby granted, provided that the above copyright 7 | * notice appear in all copies and that both that copyright 8 | * notice and this permission notice appear in supporting 9 | * documentation, and that the name of Silicon Graphics not be 10 | * used in advertising or publicity pertaining to distribution 11 | * of the software without specific prior written permission. 12 | * Silicon Graphics makes no representation about the suitability 13 | * of this software for any purpose. It is provided "as is" 14 | * without any express or implied warranty. 15 | * 16 | * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 | * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 | * THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 | * 25 | ********************************************************/ 26 | 27 | #ifndef XKBCOMP_VMOD_H 28 | #define XKBCOMP_VMOD_H 29 | 30 | bool 31 | HandleVModDef(struct xkb_context *ctx, struct xkb_mod_set *mods, 32 | VModDef *stmt, enum merge_mode merge); 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /src/compose/paths.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef COMPOSE_RESOLVE_H 25 | #define COMPOSE_RESOLVE_H 26 | 27 | char * 28 | resolve_locale(const char *locale); 29 | 30 | const char * 31 | get_xlocaledir_path(void); 32 | 33 | char * 34 | get_xcomposefile_path(void); 35 | 36 | char * 37 | get_xdg_xcompose_file_path(void); 38 | 39 | char * 40 | get_home_xcompose_file_path(void); 41 | 42 | char * 43 | get_locale_compose_file_path(const char *locale); 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/atom.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Dan Nicholson 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef ATOM_H 25 | #define ATOM_H 26 | 27 | typedef uint32_t xkb_atom_t; 28 | 29 | #define XKB_ATOM_NONE 0 30 | 31 | struct atom_table; 32 | 33 | struct atom_table * 34 | atom_table_new(void); 35 | 36 | void 37 | atom_table_free(struct atom_table *table); 38 | 39 | xkb_atom_t 40 | atom_intern(struct atom_table *table, const char *string, size_t len, bool add); 41 | 42 | const char * 43 | atom_text(struct atom_table *table, xkb_atom_t atom); 44 | 45 | #endif /* ATOM_H */ 46 | -------------------------------------------------------------------------------- /meson_options.txt: -------------------------------------------------------------------------------- 1 | option( 2 | 'xkb-config-root', 3 | type: 'string', 4 | description: 'The XKB config root [default=xkeyboard-config install path]', 5 | ) 6 | option( 7 | 'xkb-config-extra-path', 8 | type: 'string', 9 | description: 'Extra lookup path for system-wide XKB data [default=$sysconfdir/xkb]', 10 | ) 11 | option( 12 | 'x-locale-root', 13 | type: 'string', 14 | description: 'The X locale root [default=$datadir/X11/locale]', 15 | ) 16 | option( 17 | 'default-rules', 18 | type: 'string', 19 | value: 'evdev', 20 | description: 'Default XKB ruleset', 21 | ) 22 | option( 23 | 'default-model', 24 | type: 'string', 25 | value: 'pc105', 26 | description: 'Default XKB model', 27 | ) 28 | option( 29 | 'default-layout', 30 | type: 'string', 31 | value: 'us', 32 | description: 'Default XKB layout', 33 | ) 34 | option( 35 | 'default-variant', 36 | type: 'string', 37 | value: '', 38 | description: 'Default XKB variant', 39 | ) 40 | option( 41 | 'default-options', 42 | type: 'string', 43 | value: '', 44 | description: 'Default XKB options', 45 | ) 46 | option( 47 | 'enable-x11', 48 | type: 'boolean', 49 | value: true, 50 | description: 'Enable building the xkbcommon-x11 library', 51 | ) 52 | option( 53 | 'enable-docs', 54 | type: 'boolean', 55 | value: true, 56 | description: 'Enable building the documentation', 57 | ) 58 | option( 59 | 'enable-wayland', 60 | type: 'boolean', 61 | value: true, 62 | description: 'Enable support for Wayland utility programs', 63 | ) 64 | option( 65 | 'enable-xkbregistry', 66 | type: 'boolean', 67 | value: true, 68 | description: 'Enable building libxkbregistry', 69 | ) 70 | -------------------------------------------------------------------------------- /test/symbols-leak-test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | """Check that all exported symbols are specified in the symbol version scripts. 3 | 4 | If this fails, please update the appropriate .map file (adding new version 5 | nodes as needed). 6 | """ 7 | import os 8 | import pathlib 9 | import re 10 | import sys 11 | 12 | 13 | top_srcdir = pathlib.Path(os.environ['top_srcdir']) 14 | 15 | 16 | def symbols_from_map(path): 17 | return re.findall(r'^\s+(xkb_.*);', path.read_text('utf-8'), re.MULTILINE) 18 | 19 | 20 | def symbols_from_src(path): 21 | return re.findall(r'XKB_EXPORT.*\n(xkb_.*)\(', path.read_text('utf-8')) 22 | 23 | 24 | def diff(map_path, src_paths): 25 | map_symbols = set(symbols_from_map(map_path)) 26 | src_symbols = set.union(set(), *(symbols_from_src(path) for path in src_paths)) 27 | return sorted(map_symbols - src_symbols), sorted(src_symbols - map_symbols) 28 | 29 | 30 | exit = 0 31 | 32 | # xkbcommon symbols 33 | left, right = diff( 34 | top_srcdir/'xkbcommon.map', 35 | [ 36 | *(top_srcdir/'src').glob('*.c'), 37 | *(top_srcdir/'src'/'xkbcomp').glob('*.c'), 38 | *(top_srcdir/'src'/'compose').glob('*.c'), 39 | ], 40 | ) 41 | if left: 42 | print('xkbcommon map has extra symbols:', ' '.join(left)) 43 | exit = 1 44 | if right: 45 | print('xkbcommon src has extra symbols:', ' '.join(right)) 46 | exit = 1 47 | 48 | # xkbcommon-x11 symbols 49 | left, right = diff( 50 | top_srcdir/'xkbcommon-x11.map', 51 | [ 52 | *(top_srcdir/'src'/'x11').glob('*.c'), 53 | ], 54 | ) 55 | if left: 56 | print('xkbcommon-x11 map has extra symbols:', ' '.join(left)) 57 | exit = 1 58 | if right: 59 | print('xkbcommon-x11 src has extra symbols:', ' '.join(right)) 60 | exit = 1 61 | 62 | sys.exit(exit) 63 | -------------------------------------------------------------------------------- /tools/xkbcli-interactive-evdev.1: -------------------------------------------------------------------------------- 1 | .Dd July 27, 2020 2 | .Dt XKBCLI\-INTERACTIVE\-EVDEV 1 3 | .Os 4 | . 5 | .Sh NAME 6 | .Nm "xkbcli interactive\-evdev" 7 | .Nd interactive debugger for XKB keymaps 8 | . 9 | .Sh SYNOPSIS 10 | .Nm 11 | .Op Ar options 12 | . 13 | .Sh DESCRIPTION 14 | .Nm 15 | is a commandline tool to interactively debug XKB keymaps by listening to 16 | .Pa /dev/input/eventX 17 | evdev devices. 18 | . 19 | .Pp 20 | .Nm 21 | requires permission to open the evdev device nodes. 22 | This usually requires being the 23 | .Dq root 24 | user or belonging to the 25 | .Dq input 26 | group. 27 | . 28 | .Pp 29 | Press the 30 | .Aq Escape 31 | key to exit. 32 | . 33 | .Pp 34 | This is a debugging tool, its behavior or output is not guaranteed to be stable. 35 | . 36 | .Bl -tag -width Ds 37 | .It Fl \-help 38 | Print help and exit 39 | . 40 | .It Fl \-rules Ar rules 41 | The XKB ruleset 42 | . 43 | .It Fl \-model Ar model 44 | The XKB model 45 | . 46 | .It Fl \-layout Ar layout 47 | The XKB layout 48 | . 49 | .It Fl \-variant Ar variant 50 | The XKB layout variant 51 | . 52 | .It Fl \-option Ar options 53 | The XKB options 54 | . 55 | .It Fl \-keymap Ar file 56 | Specify a keymap path. 57 | This option is mutually exclusive with the RMLVO options. 58 | . 59 | .It Fl \-report\-state\-changes 60 | Report changes to the keyboard state 61 | . 62 | .It Fl \-enable\-compose 63 | Enable Compose functionality 64 | . 65 | .It Fl \-consumed\-mode Brq xkb|gtk 66 | Set the consumed modifiers mode (default: xkb) 67 | . 68 | .It Fl \-without\-x11\-offset 69 | Don't add an offset of 8 when converting an evdev keycode to an XKB keycode. 70 | You probably don't want this option. 71 | .El 72 | . 73 | .Sh SEE ALSO 74 | .Xr xkbcli 1 , 75 | .Xr xkbcli\-interactive\-wayland 1 , 76 | .Xr xkbcli\-interactive\-x11 1 , 77 | .Lk https://xkbcommon.org "The libxkbcommon online documentation" 78 | -------------------------------------------------------------------------------- /src/xkbcomp/parser-priv.h: -------------------------------------------------------------------------------- 1 | /************************************************************ 2 | * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 | * 4 | * Permission to use, copy, modify, and distribute this 5 | * software and its documentation for any purpose and without 6 | * fee is hereby granted, provided that the above copyright 7 | * notice appear in all copies and that both that copyright 8 | * notice and this permission notice appear in supporting 9 | * documentation, and that the name of Silicon Graphics not be 10 | * used in advertising or publicity pertaining to distribution 11 | * of the software without specific prior written permission. 12 | * Silicon Graphics makes no representation about the suitability 13 | * of this software for any purpose. It is provided "as is" 14 | * without any express or implied warranty. 15 | * 16 | * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 | * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 | * THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 | * 25 | ********************************************************/ 26 | 27 | #ifndef XKBCOMP_PARSER_PRIV_H 28 | #define XKBCOMP_PARSER_PRIV_H 29 | 30 | struct parser_param; 31 | struct scanner; 32 | 33 | #include "parser.h" 34 | 35 | int 36 | _xkbcommon_lex(YYSTYPE *yylval, struct scanner *scanner); 37 | 38 | XkbFile * 39 | parse(struct xkb_context *ctx, struct scanner *scanner, const char *map); 40 | 41 | int 42 | keyword_to_token(const char *string, size_t len); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /fuzz/keymap/dict: -------------------------------------------------------------------------------- 1 | "Control" 2 | "Group1" 3 | "Group5" 4 | "Lock" 5 | "Mod1" 6 | "Mod9" 7 | "Shift" 8 | "U1" 9 | "0x1" 10 | "Up" 11 | "accel" 12 | "action" 13 | "actions" 14 | "affect" 15 | "alias" 16 | "all" 17 | "allowexplicit" 18 | "allownone" 19 | "alphanumeric_keys" 20 | "alternate" 21 | "alternate_group" 22 | "any" 23 | "augment" 24 | "both" 25 | "button" 26 | "clearLocks" 27 | "clearmods" 28 | "controls" 29 | "count" 30 | "ctrls" 31 | "data" 32 | "default" 33 | "dev" 34 | "device" 35 | "dfltbtn" 36 | "driveskbd" 37 | "false" 38 | "foo" 39 | "function_keys" 40 | "genKeyEvent" 41 | "group" 42 | "groupname" 43 | "groups" 44 | "groupsclamp" 45 | "groupsredirect" 46 | "groupswrap" 47 | "hidden" 48 | "include" 49 | "increment" 50 | "index" 51 | "indicator" 52 | "indicatordriveskbd" 53 | "interpret" 54 | "kc" 55 | "key" 56 | "keycode" 57 | "keypad_keys" 58 | "keys" 59 | "latchToLock" 60 | "leddriveskbd" 61 | "levelname" 62 | "lock" 63 | "locking" 64 | "logo" 65 | "map" 66 | "mod_map" 67 | "modifier_keys" 68 | "modifier_map" 69 | "modifiers" 70 | "modmap" 71 | "modmapmods" 72 | "mods" 73 | "name" 74 | "neither" 75 | "no" 76 | "none" 77 | "nosymbol" 78 | "off" 79 | "on" 80 | "outline" 81 | "overlay" 82 | "override" 83 | "partial" 84 | "preserve" 85 | "radiogroup" 86 | "repeat" 87 | "replace" 88 | "report" 89 | "row" 90 | "same" 91 | "sameServer" 92 | "screen" 93 | "section" 94 | "shape" 95 | "solid" 96 | "symbols" 97 | "text" 98 | "true" 99 | "type" 100 | "unlock" 101 | "usemodmap" 102 | "value" 103 | "virtual" 104 | "virtual_modifiers" 105 | "virtualmod" 106 | "vmods" 107 | "voidsymbol" 108 | "whichgroupstate" 109 | "whichmodstate" 110 | "x" 111 | "xkb_compat" 112 | "xkb_geometry" 113 | "xkb_keycodes" 114 | "xkb_keymap" 115 | "xkb_layout" 116 | "xkb_semantics" 117 | "xkb_symbols" 118 | "xkb_types" 119 | "y" 120 | "yes" 121 | -------------------------------------------------------------------------------- /xkbcommon/xkbcommon-names.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | * Author: Daniel Stone 24 | */ 25 | 26 | #ifndef _XKBCOMMON_NAMES_H 27 | #define _XKBCOMMON_NAMES_H 28 | 29 | /** 30 | * @file 31 | * @brief Predefined names for common modifiers and LEDs. 32 | */ 33 | 34 | #define XKB_MOD_NAME_SHIFT "Shift" 35 | #define XKB_MOD_NAME_CAPS "Lock" 36 | #define XKB_MOD_NAME_CTRL "Control" 37 | #define XKB_MOD_NAME_ALT "Mod1" 38 | #define XKB_MOD_NAME_NUM "Mod2" 39 | #define XKB_MOD_NAME_LOGO "Mod4" 40 | 41 | #define XKB_LED_NAME_CAPS "Caps Lock" 42 | #define XKB_LED_NAME_NUM "Num Lock" 43 | #define XKB_LED_NAME_SCROLL "Scroll Lock" 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /bench/bench.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Kazunobu Kuriyama 3 | * Ran Benita 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #ifndef LIBXKBCOMMON_BENCH_H 26 | #define LIBXKBCOMMON_BENCH_H 27 | 28 | struct bench_time { 29 | long seconds; 30 | long microseconds; 31 | }; 32 | 33 | struct bench { 34 | struct bench_time start; 35 | struct bench_time stop; 36 | }; 37 | 38 | void 39 | bench_start(struct bench *bench); 40 | void 41 | bench_stop(struct bench *bench); 42 | 43 | void 44 | bench_elapsed(const struct bench *bench, struct bench_time *result); 45 | /* The caller is responsibile to free() the returned string. */ 46 | char * 47 | bench_elapsed_str(const struct bench *bench); 48 | 49 | #endif /* LIBXKBCOMMON_BENCH_H */ 50 | -------------------------------------------------------------------------------- /test/data/compat/iso9995: -------------------------------------------------------------------------------- 1 | // Fairly complete set of symbol interpretations 2 | // to provide reasonable default behavior. 3 | 4 | default partial xkb_compatibility "default" { 5 | 6 | virtual_modifiers LevelThree,AltGr; 7 | 8 | interpret.repeat= False; 9 | setMods.clearLocks= True; 10 | latchMods.clearLocks= True; 11 | latchMods.latchToLock= True; 12 | 13 | interpret ISO_Level2_Latch+Shift { 14 | useModMapMods= level1; 15 | action= LatchMods(modifiers=Shift); 16 | }; 17 | 18 | interpret ISO_Level3_Shift+Any { 19 | useModMapMods= level1; 20 | virtualModifier= LevelThree; 21 | action= SetMods(modifiers=LevelThree); 22 | }; 23 | 24 | interpret ISO_Level3_Shift { 25 | action= SetMods(modifiers=LevelThree); 26 | }; 27 | 28 | interpret ISO_Level3_Latch+Any { 29 | useModMapMods= level1; 30 | virtualModifier= LevelThree; 31 | action= LatchMods(modifiers=LevelThree); 32 | }; 33 | 34 | interpret ISO_Level3_Latch { 35 | action= LatchMods(modifiers=LevelThree); 36 | }; 37 | 38 | interpret ISO_Level3_Lock+Any { 39 | useModMapMods= level1; 40 | virtualModifier= LevelThree; 41 | action= LockMods(modifiers=LevelThree); 42 | }; 43 | 44 | interpret ISO_Level3_Lock { 45 | action= LockMods(modifiers=LevelThree); 46 | }; 47 | 48 | interpret ISO_Group_Latch { 49 | useModMapMods= level1; 50 | virtualModifier= AltGr; 51 | action= LatchGroup(group=2); 52 | }; 53 | 54 | interpret ISO_Next_Group { 55 | useModMapMods= level1; 56 | virtualModifier= AltGr; 57 | action= LockGroup(group=+1); 58 | }; 59 | 60 | interpret ISO_Prev_Group { 61 | useModMapMods= level1; 62 | virtualModifier= AltGr; 63 | action= LockGroup(group=-1); 64 | }; 65 | interpret ISO_First_Group { 66 | action= LockGroup(group=1); 67 | }; 68 | 69 | interpret ISO_Last_Group { 70 | action= LockGroup(group=2); 71 | }; 72 | 73 | indicator "Group 2" { 74 | !allowExplicit; 75 | groups= All-Group1; 76 | }; 77 | }; 78 | -------------------------------------------------------------------------------- /src/xkbcomp/include.h: -------------------------------------------------------------------------------- 1 | /************************************************************ 2 | * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 | * 4 | * Permission to use, copy, modify, and distribute this 5 | * software and its documentation for any purpose and without 6 | * fee is hereby granted, provided that the above copyright 7 | * notice appear in all copies and that both that copyright 8 | * notice and this permission notice appear in supporting 9 | * documentation, and that the name of Silicon Graphics not be 10 | * used in advertising or publicity pertaining to distribution 11 | * of the software without specific prior written permission. 12 | * Silicon Graphics makes no representation about the suitability 13 | * of this software for any purpose. It is provided "as is" 14 | * without any express or implied warranty. 15 | * 16 | * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 | * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 | * THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 | * 25 | ********************************************************/ 26 | 27 | #ifndef XKBCOMP_INCLUDE_H 28 | #define XKBCOMP_INCLUDE_H 29 | 30 | bool 31 | ParseIncludeMap(char **str_inout, char **file_rtrn, char **map_rtrn, 32 | char *nextop_rtrn, char **extra_data); 33 | 34 | FILE * 35 | FindFileInXkbPath(struct xkb_context *ctx, const char *name, 36 | enum xkb_file_type type, char **pathRtrn, 37 | unsigned int *offset); 38 | 39 | XkbFile * 40 | ProcessIncludeFile(struct xkb_context *ctx, IncludeStmt *stmt, 41 | enum xkb_file_type file_type); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /scripts/makeheader: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | from __future__ import print_function 3 | import re 4 | import os 5 | 6 | # expected format: 7 | # #define XF86XK_FooBar _EVDEVK(0x123) /* some optional comment */ 8 | evdev_pattern = re.compile(r'^#define\s+XF86XK_(?P\w+)\s+_EVDEVK\((?P0x[0-9A-Fa-f]+)\)') 9 | 10 | prefix = os.environ.get('X11_HEADERS_PREFIX', '/usr') 11 | HEADERS = [ 12 | prefix + '/include/X11/keysymdef.h', 13 | prefix + '/include/X11/XF86keysym.h', 14 | prefix + '/include/X11/Sunkeysym.h', 15 | prefix + '/include/X11/DECkeysym.h', 16 | prefix + '/include/X11/HPkeysym.h', 17 | ] 18 | 19 | print('''#ifndef _XKBCOMMON_KEYSYMS_H 20 | #define _XKBCOMMON_KEYSYMS_H 21 | 22 | /* This file is autogenerated; please do not commit directly. */ 23 | 24 | #define XKB_KEY_NoSymbol 0x000000 /* Special KeySym */ 25 | ''') 26 | for path in HEADERS: 27 | with open(path) as header: 28 | for line in header: 29 | if '#ifdef' in line or '#ifndef' in line or '#endif' in line: 30 | continue 31 | 32 | # Remove #define _OSF_Keysyms and such. 33 | if '#define _' in line: 34 | continue 35 | 36 | # Handle a duplicate definition in HPkeysyms.h which kicks in if 37 | # it's not already defined. 38 | if 'XK_Ydiaeresis' in line and '0x100000ee' in line: 39 | continue 40 | 41 | # Replace the xorgproto _EVDEVK macro with the actual value 42 | # 0x10081000 is the base, the evdev hex code is added to that. 43 | # We replace to make parsing of the keys later easier. 44 | match = re.match(evdev_pattern, line) 45 | if match: 46 | value = 0x10081000 + int(match.group('value'), 16) 47 | line = re.sub(r'_EVDEVK\(0x([0-9A-Fa-f]+)\)', '{:#x}'.format(value), line) 48 | 49 | line = re.sub(r'#define\s*(\w*)XK_', r'#define XKB_KEY_\1', line) 50 | 51 | print(line, end='') 52 | print('\n\n#endif') 53 | -------------------------------------------------------------------------------- /test/utils.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2019 Red Hat, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | #include "test.h" 32 | #include "utils.h" 33 | 34 | int 35 | main(void) 36 | { 37 | char buffer[10]; 38 | 39 | assert(!snprintf_safe(buffer, 0, "foo")); 40 | assert(!snprintf_safe(buffer, 1, "foo")); 41 | assert(!snprintf_safe(buffer, 3, "foo")); 42 | 43 | assert(snprintf_safe(buffer, 10, "foo")); 44 | assert(streq(buffer, "foo")); 45 | 46 | assert(!snprintf_safe(buffer, 10, "%s", "1234567890")); 47 | assert(snprintf_safe(buffer, 10, "%s", "123456789")); 48 | 49 | assert(streq_null("foo", "foo")); 50 | assert(!streq_null("foobar", "foo")); 51 | assert(!streq_null("foobar", NULL)); 52 | assert(!streq_null(NULL, "foobar")); 53 | assert(streq_null(NULL, NULL)); 54 | 55 | return 0; 56 | } 57 | -------------------------------------------------------------------------------- /test/data/compat/xfree86: -------------------------------------------------------------------------------- 1 | // XFree86 special keysyms. 2 | 3 | default partial xkb_compatibility "basic" { 4 | 5 | interpret.repeat= True; 6 | 7 | interpret XF86_Switch_VT_1 { 8 | action = SwitchScreen(Screen=1, !SameServer); 9 | }; 10 | interpret XF86_Switch_VT_2 { 11 | action = SwitchScreen(Screen=2, !SameServer); 12 | }; 13 | interpret XF86_Switch_VT_3 { 14 | action = SwitchScreen(Screen=3, !SameServer); 15 | }; 16 | interpret XF86_Switch_VT_4 { 17 | action = SwitchScreen(Screen=4, !SameServer); 18 | }; 19 | interpret XF86_Switch_VT_5 { 20 | action = SwitchScreen(Screen=5, !SameServer); 21 | }; 22 | interpret XF86_Switch_VT_6 { 23 | action = SwitchScreen(Screen=6, !SameServer); 24 | }; 25 | interpret XF86_Switch_VT_7 { 26 | action = SwitchScreen(Screen=7, !SameServer); 27 | }; 28 | interpret XF86_Switch_VT_8 { 29 | action = SwitchScreen(Screen=8, !SameServer); 30 | }; 31 | interpret XF86_Switch_VT_9 { 32 | action = SwitchScreen(Screen=9, !SameServer); 33 | }; 34 | interpret XF86_Switch_VT_10 { 35 | action = SwitchScreen(Screen=10, !SameServer); 36 | }; 37 | interpret XF86_Switch_VT_11 { 38 | action = SwitchScreen(Screen=11, !SameServer); 39 | }; 40 | interpret XF86_Switch_VT_12 { 41 | action = SwitchScreen(Screen=12, !SameServer); 42 | }; 43 | 44 | interpret XF86LogGrabInfo { 45 | action = Private(type=0x86, data="PrGrbs"); 46 | }; 47 | interpret XF86LogWindowTree { 48 | action = Private(type=0x86, data="PrWins"); 49 | }; 50 | 51 | interpret XF86_Next_VMode { 52 | action = Private(type=0x86, data="+VMode"); 53 | }; 54 | interpret XF86_Prev_VMode { 55 | action = Private(type=0x86, data="-VMode"); 56 | }; 57 | }; 58 | 59 | partial xkb_compatibility "grab_break" { 60 | interpret XF86_Ungrab { 61 | action = Private(type=0x86, data="Ungrab"); 62 | }; 63 | interpret XF86_ClearGrab { 64 | action = Private(type=0x86, data="ClsGrb"); 65 | }; 66 | }; 67 | -------------------------------------------------------------------------------- /xkbregistry.map: -------------------------------------------------------------------------------- 1 | /* versions are kept in sync with libxkbcommon.so */ 2 | V_1.0.0 { 3 | global: 4 | rxkb_context_new; 5 | rxkb_context_parse; 6 | rxkb_context_parse_default_ruleset; 7 | rxkb_context_ref; 8 | rxkb_context_unref; 9 | rxkb_context_set_user_data; 10 | rxkb_context_get_user_data; 11 | rxkb_context_set_log_level; 12 | rxkb_context_get_log_level; 13 | rxkb_context_set_log_fn; 14 | rxkb_context_include_path_append; 15 | rxkb_context_include_path_append_default; 16 | rxkb_model_first; 17 | rxkb_model_next; 18 | rxkb_model_ref; 19 | rxkb_model_unref; 20 | rxkb_model_get_name; 21 | rxkb_model_get_description; 22 | rxkb_model_get_vendor; 23 | rxkb_model_get_popularity; 24 | rxkb_layout_first; 25 | rxkb_layout_next; 26 | rxkb_layout_ref; 27 | rxkb_layout_unref; 28 | rxkb_layout_get_name; 29 | rxkb_layout_get_brief; 30 | rxkb_layout_get_description; 31 | rxkb_layout_get_variant; 32 | rxkb_layout_get_popularity; 33 | rxkb_option_group_first; 34 | rxkb_option_group_next; 35 | rxkb_option_group_ref; 36 | rxkb_option_group_unref; 37 | rxkb_option_group_get_name; 38 | rxkb_option_group_get_description; 39 | rxkb_option_group_allows_multiple; 40 | rxkb_option_group_get_popularity; 41 | rxkb_option_first; 42 | rxkb_option_next; 43 | rxkb_option_ref; 44 | rxkb_option_unref; 45 | rxkb_option_get_name; 46 | rxkb_option_get_brief; 47 | rxkb_option_get_description; 48 | rxkb_option_get_popularity; 49 | rxkb_layout_get_iso639_first; 50 | rxkb_iso639_code_next; 51 | rxkb_iso639_code_ref; 52 | rxkb_iso639_code_unref; 53 | rxkb_iso639_code_get_code; 54 | rxkb_layout_get_iso3166_first; 55 | rxkb_iso3166_code_next; 56 | rxkb_iso3166_code_ref; 57 | rxkb_iso3166_code_unref; 58 | rxkb_iso3166_code_get_code; 59 | local: 60 | *; 61 | }; 62 | -------------------------------------------------------------------------------- /test/data/types/numpad: -------------------------------------------------------------------------------- 1 | default partial xkb_types "pc" { 2 | type "KEYPAD" { 3 | modifiers = Shift+NumLock; 4 | map[None] = Level1; 5 | map[Shift] = Level2; 6 | map[NumLock] = Level2; 7 | map[Shift+NumLock] = Level1; 8 | level_name[Level1] = "Base"; 9 | level_name[Level2] = "Number"; 10 | }; 11 | include "extra(keypad)" 12 | }; 13 | 14 | // On Mac keypads, level 1 and 2 are swapped. 15 | partial xkb_types "mac" { 16 | type "KEYPAD" { 17 | modifiers = None; 18 | map[None] = Level2; 19 | level_name[Level2] = "Number"; 20 | }; 21 | include "extra(keypad)" 22 | }; 23 | 24 | partial xkb_types "microsoft" { 25 | type "KEYPAD" { 26 | modifiers = Shift+NumLock; 27 | map[None] = Level1; 28 | preserve[Shift] = Shift; 29 | map[NumLock] = Level2; 30 | level_name[Level1] = "Base"; 31 | level_name[Level2] = "Number"; 32 | }; 33 | include "extra(keypad)" 34 | }; 35 | 36 | // Swiss-German style numeric keypad: Shift and NumLock operate as 37 | // two independent modifiers; however, since we want shift state for 38 | // the cursor keys, only three levels are used from the key mappings. 39 | // Closest type is actually FOUR_LEVEL_X, but most numpad layouts use 40 | // FOUR_LEVEL_MIXED_KEYPAD, so that's the one we are going to override. 41 | partial xkb_types "shift3" { 42 | type "FOUR_LEVEL_MIXED_KEYPAD" { 43 | modifiers = Shift+NumLock+Control+Alt; 44 | 45 | // NumLock Off => navigate using cursor keys 46 | map[None] = Level1; 47 | 48 | // NumLock Off + Shift pressed => select using cursor keys 49 | preserve[Shift] = Shift; 50 | 51 | // NumLock On => decimal digits 52 | map[NumLock] = Level2; 53 | 54 | // NumLock On + Shift pressed => auxiliary symbols, 55 | // e.g. hexadecimal digits 56 | map[Shift+NumLock] = Level3; 57 | 58 | // Ctrl + Alt, regardless of NumLock and Shift => command keys 59 | map[Control+Alt] = Level4; 60 | 61 | // reverse map from levels to modifiers 62 | level_name[Level1] = "Base"; 63 | level_name[Level2] = "NumLock"; 64 | level_name[Level3] = "Shift+NumLock"; 65 | level_name[Level4] = "Ctrl+Alt"; 66 | }; 67 | }; 68 | -------------------------------------------------------------------------------- /bench/rulescomp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Dan Nicholson 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | 28 | #include "../test/test.h" 29 | #include "bench.h" 30 | 31 | #define BENCHMARK_ITERATIONS 2500 32 | 33 | int 34 | main(int argc, char *argv[]) 35 | { 36 | struct xkb_context *ctx; 37 | struct xkb_keymap *keymap; 38 | struct bench bench; 39 | char *elapsed; 40 | int i; 41 | 42 | ctx = test_get_context(0); 43 | assert(ctx); 44 | 45 | xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); 46 | xkb_context_set_log_verbosity(ctx, 0); 47 | 48 | bench_start(&bench); 49 | for (i = 0; i < BENCHMARK_ITERATIONS; i++) { 50 | keymap = test_compile_rules(ctx, "evdev", "evdev", "us", "", ""); 51 | assert(keymap); 52 | xkb_keymap_unref(keymap); 53 | } 54 | bench_stop(&bench); 55 | 56 | elapsed = bench_elapsed_str(&bench); 57 | fprintf(stderr, "compiled %d keymaps in %ss\n", 58 | BENCHMARK_ITERATIONS, elapsed); 59 | free(elapsed); 60 | 61 | xkb_context_unref(ctx); 62 | return 0; 63 | } 64 | -------------------------------------------------------------------------------- /tools/tools-common.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | * Author: Daniel Stone 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "config.h" 29 | 30 | #include 31 | 32 | /* Don't use compat names in internal code. */ 33 | #define _XKBCOMMON_COMPAT_H 34 | #include "xkbcommon/xkbcommon.h" 35 | #include "xkbcommon/xkbcommon-compose.h" 36 | 37 | #define ARRAY_SIZE(arr) ((sizeof(arr) / sizeof(*(arr)))) 38 | 39 | void 40 | tools_print_keycode_state(struct xkb_state *state, 41 | struct xkb_compose_state *compose_state, 42 | xkb_keycode_t keycode, 43 | enum xkb_consumed_mode consumed_mode); 44 | 45 | void 46 | tools_print_state_changes(enum xkb_state_component changed); 47 | 48 | void 49 | tools_disable_stdin_echo(void); 50 | 51 | void 52 | tools_enable_stdin_echo(void); 53 | 54 | int 55 | tools_exec_command(const char *prefix, int argc, char **argv); 56 | 57 | #ifdef _MSC_VER 58 | #define setenv(varname, value, overwrite) _putenv_s((varname), (value)) 59 | #define unsetenv(varname) _putenv_s(varname, "") 60 | #endif 61 | -------------------------------------------------------------------------------- /src/xkbcomp/action.h: -------------------------------------------------------------------------------- 1 | /************************************************************ 2 | * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 | * 4 | * Permission to use, copy, modify, and distribute this 5 | * software and its documentation for any purpose and without 6 | * fee is hereby granted, provided that the above copyright 7 | * notice appear in all copies and that both that copyright 8 | * notice and this permission notice appear in supporting 9 | * documentation, and that the name of Silicon Graphics not be 10 | * used in advertising or publicity pertaining to distribution 11 | * of the software without specific prior written permission. 12 | * Silicon Graphics makes no representation about the suitability 13 | * of this software for any purpose. It is provided "as is" 14 | * without any express or implied warranty. 15 | * 16 | * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 | * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 | * THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 | * 25 | ********************************************************/ 26 | 27 | #ifndef XKBCOMP_ACTION_H 28 | #define XKBCOMP_ACTION_H 29 | 30 | /* 31 | * This struct contains the default values which every new action 32 | * (e.g. in an interpret statement) starts off with. It can be 33 | * modified within the files (see calls to SetActionField). 34 | */ 35 | typedef struct { 36 | union xkb_action actions[_ACTION_TYPE_NUM_ENTRIES]; 37 | } ActionsInfo; 38 | 39 | ActionsInfo * 40 | NewActionsInfo(void); 41 | 42 | void 43 | FreeActionsInfo(ActionsInfo *info); 44 | 45 | bool 46 | HandleActionDef(struct xkb_context *ctx, ActionsInfo *info, 47 | const struct xkb_mod_set *mods, ExprDef *def, 48 | union xkb_action *action); 49 | 50 | bool 51 | SetActionField(struct xkb_context *ctx, ActionsInfo *info, 52 | struct xkb_mod_set *mods, const char *elem, 53 | const char *field, ExprDef *array_ndx, ExprDef *value); 54 | 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /test/data/symbols/capslock: -------------------------------------------------------------------------------- 1 | default hidden partial modifier_keys 2 | xkb_symbols "capslock" { 3 | replace key { [ Caps_Lock ] }; 4 | modifier_map Lock { Caps_Lock }; 5 | }; 6 | 7 | hidden partial modifier_keys 8 | xkb_symbols "shiftlock" { 9 | replace key { [ Shift_Lock ] }; 10 | modifier_map Shift { Shift_Lock }; 11 | }; 12 | 13 | hidden partial modifier_keys 14 | xkb_symbols "grouplock" { 15 | replace key { [ ISO_Next_Group, Caps_Lock ] }; 16 | }; 17 | 18 | hidden partial modifier_keys 19 | xkb_symbols "groupshift" { 20 | key { 21 | type[Group1] = "PC_ALT_LEVEL2", 22 | [ Mode_switch, Caps_Lock ] 23 | }; 24 | }; 25 | 26 | hidden partial modifier_keys 27 | xkb_symbols "swapescape" { 28 | key { [ Escape ] }; 29 | key { [ Caps_Lock ] }; 30 | }; 31 | 32 | hidden partial modifier_keys 33 | xkb_symbols "escape" { 34 | key { [ Escape ] }; 35 | }; 36 | 37 | hidden partial modifier_keys 38 | xkb_symbols "escape_shifted_capslock" { 39 | key { 40 | type[Group1] = "TWO_LEVEL", 41 | symbols[Group1] = [ Escape, Caps_Lock ], 42 | actions[Group1] = [ NoAction(), LockMods(modifiers = Lock) ] 43 | }; 44 | }; 45 | 46 | hidden partial modifier_keys 47 | xkb_symbols "backspace" { 48 | key { [ BackSpace ] }; 49 | }; 50 | 51 | hidden partial modifier_keys 52 | xkb_symbols "super" { 53 | key { [ Super_L ] }; 54 | modifier_map Mod4 { }; 55 | }; 56 | 57 | hidden partial modifier_keys 58 | xkb_symbols "hyper" { 59 | key { [ Hyper_L ] }; 60 | modifier_map Mod4 { }; 61 | }; 62 | 63 | hidden partial modifier_keys 64 | xkb_symbols "menu" { 65 | key { [ Menu ] }; 66 | }; 67 | 68 | hidden partial modifier_keys 69 | xkb_symbols "numlock" { 70 | key { [ Num_Lock ] }; 71 | }; 72 | 73 | // This changes the key to become a Control modifier, 74 | // but it will still produce the Caps_Lock keysym. 75 | hidden partial modifier_keys 76 | xkb_symbols "ctrl_modifier" { 77 | replace key { 78 | type[Group1] = "ONE_LEVEL", 79 | symbols[Group1] = [ Caps_Lock ], 80 | actions[Group1] = [ SetMods(modifiers=Control) ] 81 | }; 82 | modifier_map Control { }; 83 | }; 84 | 85 | hidden partial modifier_keys 86 | xkb_symbols "none" { 87 | key { [ VoidSymbol ] }; 88 | }; 89 | -------------------------------------------------------------------------------- /src/xkbcomp/keywords.gperf: -------------------------------------------------------------------------------- 1 | %{ 2 | #include "config.h" 3 | 4 | #include "xkbcomp-priv.h" 5 | #include "parser-priv.h" 6 | 7 | static const struct keyword_tok * 8 | keyword_gperf_lookup (register const char *str, register size_t len); 9 | %} 10 | 11 | struct keyword_tok { int name; int tok; }; 12 | %language=ANSI-C 13 | %define hash-function-name keyword_gperf_hash 14 | %define lookup-function-name keyword_gperf_lookup 15 | %readonly-tables 16 | %enum 17 | %includes 18 | %struct-type 19 | %pic 20 | %ignore-case 21 | 22 | %% 23 | action, ACTION_TOK 24 | alias, ALIAS 25 | alphanumeric_keys, ALPHANUMERIC_KEYS 26 | alternate_group, ALTERNATE_GROUP 27 | alternate, ALTERNATE 28 | augment, AUGMENT 29 | default, DEFAULT 30 | function_keys, FUNCTION_KEYS 31 | group, GROUP 32 | hidden, HIDDEN 33 | include, INCLUDE 34 | indicator, INDICATOR 35 | interpret, INTERPRET 36 | keypad_keys, KEYPAD_KEYS 37 | key, KEY 38 | keys, KEYS 39 | logo, LOGO 40 | modifier_keys, MODIFIER_KEYS 41 | modifier_map, MODIFIER_MAP 42 | mod_map, MODIFIER_MAP 43 | modmap, MODIFIER_MAP 44 | outline, OUTLINE 45 | overlay, OVERLAY 46 | override, OVERRIDE 47 | partial, PARTIAL 48 | replace, REPLACE 49 | row, ROW 50 | section, SECTION 51 | shape, SHAPE 52 | solid, SOLID 53 | text, TEXT 54 | type, TYPE 55 | virtual_modifiers, VIRTUAL_MODS 56 | virtual, VIRTUAL 57 | xkb_compatibility_map, XKB_COMPATMAP 58 | xkb_compatibility, XKB_COMPATMAP 59 | xkb_compat_map, XKB_COMPATMAP 60 | xkb_compat, XKB_COMPATMAP 61 | xkb_geometry, XKB_GEOMETRY 62 | xkb_keycodes, XKB_KEYCODES 63 | xkb_keymap, XKB_KEYMAP 64 | xkb_layout, XKB_LAYOUT 65 | xkb_semantics, XKB_SEMANTICS 66 | xkb_symbols, XKB_SYMBOLS 67 | xkb_types, XKB_TYPES 68 | %% 69 | 70 | int 71 | keyword_to_token(const char *string, size_t len) 72 | { 73 | const struct keyword_tok *kt = keyword_gperf_lookup(string, len); 74 | if (!kt) 75 | return -1; 76 | return kt->tok; 77 | } 78 | -------------------------------------------------------------------------------- /doc/compat.md: -------------------------------------------------------------------------------- 1 | # Compatibility 2 | 3 | Relative to the XKB 1.0 specification implemented in current X servers, 4 | xkbcommon has removed support for some parts of the specification which 5 | introduced unnecessary complications. Many of these removals were in fact 6 | not implemented, or half-implemented at best, as well as being totally 7 | unused in the standard dataset. 8 | 9 | Notable removals: 10 | - geometry support 11 | + there were very few geometry definitions available, and while 12 | xkbcommon was responsible for parsing this insanely complex format, 13 | it never actually did anything with it 14 | + hopefully someone will develop a companion library which supports 15 | keyboard geometries in a more useful format 16 | - KcCGST (keycodes/compat/geometry/symbols/types) API 17 | + use RMLVO instead; KcCGST is now an implementation detail 18 | + including pre-defined keymap files 19 | - XKM support 20 | + may come in an optional X11 support/compatibility library 21 | - around half of the interpret actions 22 | + pointer device, message and redirect actions in particular 23 | - non-virtual modifiers 24 | + core and virtual modifiers have been collapsed into the same 25 | namespace, with a 'significant' flag that largely parallels the 26 | core/virtual split 27 | - radio groups 28 | + completely unused in current keymaps, never fully implemented 29 | - overlays 30 | + almost completely unused in current keymaps 31 | - key behaviors 32 | + used to implement radio groups and overlays, and to deal with things 33 | like keys that physically lock; unused in current keymaps 34 | - indicator behaviours such as LED-controls-key 35 | + the only supported LED behaviour is key-controls-LED; again this 36 | was never really used in current keymaps 37 | 38 | On the other hand, some features and extensions were added. 39 | 40 | Notable additions: 41 | - 32-bit keycodes 42 | - extended number of modifiers (planned) 43 | - extended number of groups (planned) 44 | - multiple keysyms per level 45 | + such levels are ignored by x11/xkbcomp. 46 | - key names (e.g. ``) can be longer than 4 characters. 47 | 48 | ## Compose support 49 | 50 | Relative to the standard implementation in libX11 (described in the 51 | Compose(5) man-page), some features are not supported: 52 | 53 | - the (! MODIFIER) syntax 54 | + parsed correctly but ignored. 55 | - using modifier keysyms in Compose sequences 56 | - several interactions with Braille keysyms 57 | -------------------------------------------------------------------------------- /test/data/keycodes/aliases-xkbcommon: -------------------------------------------------------------------------------- 1 | 2 | // keycode aliases for phonetic keyboard maps 3 | 4 | default 5 | xkb_keycodes "qwerty" { 6 | 7 | alias = ; 8 | alias = ; 9 | alias = ; 10 | alias = ; 11 | alias = ; 12 | alias = ; 13 | alias = ; 14 | alias = ; 15 | alias = ; 16 | alias =

; 49 | 50 | alias = ; 51 | alias = ; 52 | alias = ; 53 | alias = ; 54 | alias = ; 55 | alias = ; 56 | alias = ; 57 | alias = ; 58 | alias = ; 59 | alias = ; 60 | 61 | alias = ; 62 | alias = ; 63 | alias = ; 64 | alias = ; 65 | alias = ; 66 | alias = ; 67 | }; 68 | 69 | xkb_keycodes "qwertz" { 70 | 71 | alias = ; 72 | alias = ; 73 | alias = ; 74 | alias = ; 75 | alias = ; 76 | alias = ; 77 | alias = ; 78 | alias = ; 79 | alias = ; 80 | alias =

; 81 | 82 | alias = ; 83 | alias = ; 84 | alias = ; 85 | alias = ; 86 | alias = ; 87 | alias = ; 88 | alias = ; 89 | alias = ; 90 | alias = ; 91 | 92 | alias = ; 93 | alias = ; 94 | alias = ; 95 | alias = ; 96 | alias = ; 97 | alias = ; 98 | alias = ; 99 | }; 100 | -------------------------------------------------------------------------------- /test/test-keysym.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # This script creates a custom layout, overriding the TDLE key with the first 4 | # argument given. 5 | 6 | import argparse 7 | import tempfile 8 | from pathlib import Path 9 | import subprocess 10 | import os 11 | import re 12 | import sys 13 | 14 | # Template to force our key to TLDE 15 | template = """ 16 | default 17 | xkb_symbols "basic" {{ 18 | include "us(basic)" 19 | replace key {{ [ {} ] }}; 20 | }}; 21 | """ 22 | 23 | parser = argparse.ArgumentParser( 24 | description='Tool to verify whether a keysym is resolved' 25 | ) 26 | parser.add_argument('keysym', type=str, help='XKB keysym') 27 | parser.add_argument('--tool', type=str, nargs=1, 28 | default=['xkbcli', 'compile-keymap'], 29 | help='Full path to the xkbcli-compile-keymap tool') 30 | args = parser.parse_args() 31 | 32 | with tempfile.TemporaryDirectory() as tmpdir: 33 | symfile = Path(tmpdir) / "symbols" / "keytest" 34 | symfile.parent.mkdir() 35 | with symfile.open(mode='w') as f: 36 | f.write(template.format(args.keysym)) 37 | 38 | try: 39 | cmd = [ 40 | *args.tool, 41 | '--layout', 'keytest', 42 | ] 43 | 44 | env = os.environ.copy() 45 | env['XKB_CONFIG_EXTRA_PATH'] = tmpdir 46 | 47 | result = subprocess.run(cmd, env=env, capture_output=True, 48 | universal_newlines=True) 49 | if result.returncode != 0: 50 | print('ERROR: Failed to compile:') 51 | print(result.stderr) 52 | sys.exit(1) 53 | 54 | # grep for TLDE actually being remapped 55 | for l in result.stdout.split('\n'): 56 | match = re.match(r'\s+key \\s+{\s+\[\s+(?P\w+)\s+\]\s+}', l) 57 | if match: 58 | if args.keysym == match.group('keysym'): 59 | sys.exit(0) 60 | elif match.group('keysym') == 'NoSymbol': 61 | print('ERROR: key {} not resolved:'.format(args.keysym), l) 62 | else: 63 | print('ERROR: key {} mapped to wrong key:'.format(args.keysym), l) 64 | sys.exit(1) 65 | 66 | print(result.stdout) 67 | print('ERROR: above keymap is missing key mapping for {}'.format(args.keysym)) 68 | sys.exit(1) 69 | except FileNotFoundError as err: 70 | print('ERROR: invalid or missing tool: {}'.format(err)) 71 | sys.exit(1) 72 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # libxkbcommon 2 | 3 | libxkbcommon is a keyboard keymap compiler and support library which 4 | processes a reduced subset of keymaps as defined by the XKB (X Keyboard 5 | Extension) specification. It also contains a module for handling Compose 6 | and dead keys and a separate library for listing available keyboard layouts. 7 | 8 | ## Quick Guide 9 | 10 | See [Quick Guide](doc/quick-guide.md). 11 | 12 | ## Building 13 | 14 | libxkbcommon is built with [Meson](http://mesonbuild.com/): 15 | 16 | meson setup build 17 | ninja -C build 18 | 19 | To build for use with Wayland, you can disable X11 support while still 20 | using the X11 keyboard configuration resource files thusly: 21 | 22 | meson setup build \ 23 | -Denable-x11=false \ 24 | -Dxkb-config-root=/usr/share/X11/xkb \ 25 | -Dx-locale-root=/usr/share/X11/locale 26 | ninja -C build 27 | 28 | ## API 29 | 30 | While libxkbcommon's API is somewhat derived from the classic XKB API as found 31 | in X11/extensions/XKB.h and friends, it has been substantially reworked to 32 | expose fewer internal details to clients. 33 | 34 | See the [API Documentation](https://xkbcommon.org/doc/current/modules.html). 35 | 36 | ## Dataset 37 | 38 | libxkbcommon does not distribute a keymap dataset itself, other than for 39 | testing purposes. The most common dataset is xkeyboard-config, which is used 40 | by all current distributions for their X11 XKB data. More information on 41 | xkeyboard-config is available here: 42 | https://www.freedesktop.org/wiki/Software/XKeyboardConfig 43 | 44 | The dataset for Compose is distributed in libX11, as part of the X locale 45 | data. 46 | 47 | ## Relation to X11 48 | 49 | See [Compatibility](doc/compat.md) notes. 50 | 51 | ## Development 52 | 53 | An extremely rudimentary homepage can be found at 54 | https://xkbcommon.org 55 | 56 | xkbcommon is maintained in git at 57 | https://github.com/xkbcommon/libxkbcommon 58 | 59 | Patches are always welcome, and may be sent to either 60 | or 61 | or in a [GitHub](https://github.com/xkbcommon/libxkbcommon) pull request. 62 | 63 | Bug reports (and usage questions) are also welcome, and may be filed at 64 | [GitHub](https://github.com/xkbcommon/libxkbcommon/issues). 65 | 66 | The maintainers are 67 | - Daniel Stone 68 | - Ran Benita 69 | 70 | ## Credits 71 | 72 | Many thanks are due to Dan Nicholson for his heroic work in getting xkbcommon 73 | off the ground initially. 74 | -------------------------------------------------------------------------------- /bench/rules.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | 28 | #include "../test/test.h" 29 | #include "xkbcomp/xkbcomp-priv.h" 30 | #include "xkbcomp/rules.h" 31 | #include "bench.h" 32 | 33 | #define BENCHMARK_ITERATIONS 20000 34 | 35 | int 36 | main(int argc, char *argv[]) 37 | { 38 | struct xkb_context *ctx; 39 | int i; 40 | struct xkb_rule_names rmlvo = { 41 | "evdev", "pc105", "us,il", ",", "ctrl:nocaps,grp:menu_toggle", 42 | }; 43 | struct bench bench; 44 | char *elapsed; 45 | 46 | ctx = test_get_context(0); 47 | assert(ctx); 48 | 49 | xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); 50 | xkb_context_set_log_verbosity(ctx, 0); 51 | 52 | bench_start(&bench); 53 | for (i = 0; i < BENCHMARK_ITERATIONS; i++) { 54 | struct xkb_component_names kccgst; 55 | 56 | assert(xkb_components_from_rules(ctx, &rmlvo, &kccgst)); 57 | free(kccgst.keycodes); 58 | free(kccgst.types); 59 | free(kccgst.compat); 60 | free(kccgst.symbols); 61 | } 62 | bench_stop(&bench); 63 | 64 | elapsed = bench_elapsed_str(&bench); 65 | fprintf(stderr, "processed %d rule files in %ss\n", 66 | BENCHMARK_ITERATIONS, elapsed); 67 | free(elapsed); 68 | 69 | xkb_context_unref(ctx); 70 | return 0; 71 | } 72 | -------------------------------------------------------------------------------- /scripts/makekeys: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | import re, sys, itertools 4 | 5 | import perfect_hash 6 | 7 | pattern = re.compile(r'^#define\s+XKB_KEY_(?P\w+)\s+(?P0x[0-9a-fA-F]+)\s') 8 | matches = [pattern.match(line) for line in open(sys.argv[1])] 9 | entries = [(m.group("name"), int(m.group("value"), 16)) for m in matches if m] 10 | 11 | entries_isorted = sorted(entries, key=lambda e: e[0].lower()) 12 | entries_kssorted = sorted(entries, key=lambda e: e[1]) 13 | 14 | print(''' 15 | /** 16 | * This file comes from libxkbcommon and was generated by makekeys.py 17 | * You can always fetch the latest version from: 18 | * https://raw.github.com/xkbcommon/libxkbcommon/master/src/ks_tables.h 19 | */ 20 | ''') 21 | 22 | entry_offsets = {} 23 | 24 | print(''' 25 | #ifdef __GNUC__ 26 | #pragma GCC diagnostic push 27 | #pragma GCC diagnostic ignored "-Woverlength-strings" 28 | #endif 29 | static const char *keysym_names = 30 | '''.strip()) 31 | offs = 0 32 | for (name, _) in entries_isorted: 33 | entry_offsets[name] = offs 34 | print(' "{name}\\0"'.format(name=name)) 35 | offs += len(name) + 1 36 | print(''' 37 | ; 38 | #ifdef __GNUC__ 39 | #pragma GCC diagnostic pop 40 | #endif 41 | '''.strip()) 42 | 43 | 44 | template = r''' 45 | static const uint16_t keysym_name_G[] = { 46 | $G 47 | }; 48 | 49 | static size_t 50 | keysym_name_hash_f(const char *key, const char *T) 51 | { 52 | size_t sum = 0; 53 | for (size_t i = 0; key[i] != '\0'; i++) 54 | sum += T[i % $NS] * key[i]; 55 | return sum % $NG; 56 | } 57 | 58 | static size_t 59 | keysym_name_perfect_hash(const char *key) 60 | { 61 | return ( 62 | keysym_name_G[keysym_name_hash_f(key, "$S1")] + 63 | keysym_name_G[keysym_name_hash_f(key, "$S2")] 64 | ) % $NG; 65 | } 66 | ''' 67 | print(perfect_hash.generate_code( 68 | keys=[name for name, value in entries_isorted], 69 | template=template, 70 | )) 71 | 72 | print(''' 73 | struct name_keysym { 74 | xkb_keysym_t keysym; 75 | uint32_t offset; 76 | };\n''') 77 | 78 | def print_entries(x): 79 | for (name, value) in x: 80 | print(' {{ 0x{value:08x}, {offs} }}, /* {name} */'.format(offs=entry_offsets[name], value=value, name=name)) 81 | 82 | print('static const struct name_keysym name_to_keysym[] = {') 83 | print_entries(entries_isorted) 84 | print('};\n') 85 | 86 | # *.sort() is stable so we always get the first keysym for duplicate 87 | print('static const struct name_keysym keysym_to_name[] = {') 88 | print_entries(next(g[1]) for g in itertools.groupby(entries_kssorted, key=lambda e: e[1])) 89 | print('};') 90 | -------------------------------------------------------------------------------- /test/data/symbols/shift: -------------------------------------------------------------------------------- 1 | // Cancel CapsLock when a Shift key is pressed. 2 | partial modifier_keys 3 | xkb_symbols "breaks_caps" { 4 | key { 5 | type = "ALPHABETIC", 6 | actions [Group1] = [ 7 | SetMods(modifiers=Shift), 8 | SetMods(modifiers=Shift+Lock,clearLocks) 9 | ] 10 | }; 11 | key { 12 | type = "ALPHABETIC", 13 | actions [Group1] = [ 14 | SetMods(modifiers=Shift), 15 | SetMods(modifiers=Shift+Lock,clearLocks) 16 | ] 17 | }; 18 | }; 19 | 20 | 21 | // Toggle CapsLock when pressed together with the other Shift key. 22 | partial modifier_keys 23 | xkb_symbols "lshift_both_capslock" { 24 | key { 25 | type[Group1]="TWO_LEVEL", 26 | symbols[Group1] = [ Shift_L, Caps_Lock ] 27 | }; 28 | }; 29 | // Toggle CapsLock when pressed together with the other Shift key. 30 | partial modifier_keys 31 | xkb_symbols "rshift_both_capslock" { 32 | key { 33 | type[Group1]="TWO_LEVEL", 34 | symbols[Group1] = [ Shift_R, Caps_Lock ] 35 | }; 36 | }; 37 | partial modifier_keys 38 | xkb_symbols "both_capslock" { 39 | include "shift(lshift_both_capslock)" 40 | include "shift(rshift_both_capslock)" 41 | }; 42 | 43 | 44 | // Set CapsLock when pressed with the other Shift key, release it when pressed alone. 45 | partial modifier_keys 46 | xkb_symbols "lshift_both_capslock_cancel" { 47 | key { 48 | type[Group1]="ALPHABETIC", 49 | symbols[Group1] = [ Shift_L, Caps_Lock ] 50 | }; 51 | }; 52 | // Set CapsLock when pressed with the other Shift key, release it when pressed alone. 53 | partial modifier_keys 54 | xkb_symbols "rshift_both_capslock_cancel" { 55 | key { 56 | type[Group1]="ALPHABETIC", 57 | symbols[Group1] = [ Shift_R, Caps_Lock ] 58 | }; 59 | }; 60 | partial modifier_keys 61 | xkb_symbols "both_capslock_cancel" { 62 | include "shift(lshift_both_capslock_cancel)" 63 | include "shift(rshift_both_capslock_cancel)" 64 | }; 65 | 66 | 67 | // Toggle ShiftLock when pressed together with the other Shift key. 68 | partial modifier_keys 69 | xkb_symbols "lshift_both_shiftlock" { 70 | key { 71 | type[Group1]="TWO_LEVEL", 72 | symbols[Group1] = [ Shift_L, Shift_Lock ] 73 | }; 74 | }; 75 | // Toggle ShiftLock when pressed together with the other Shift key. 76 | partial modifier_keys 77 | xkb_symbols "rshift_both_shiftlock" { 78 | key { 79 | type[Group1]="TWO_LEVEL", 80 | symbols[Group1] = [ Shift_R, Shift_Lock ] 81 | }; 82 | }; 83 | partial modifier_keys 84 | xkb_symbols "both_shiftlock" { 85 | include "shift(lshift_both_shiftlock)" 86 | include "shift(rshift_both_shiftlock)" 87 | }; 88 | -------------------------------------------------------------------------------- /test/data/symbols/compose: -------------------------------------------------------------------------------- 1 | partial modifier_keys 2 | xkb_symbols "ralt" { 3 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 4 | }; 5 | 6 | partial modifier_keys 7 | xkb_symbols "lwin" { 8 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 9 | }; 10 | 11 | partial modifier_keys 12 | xkb_symbols "lwin-altgr" { 13 | key { type[Group1]="FOUR_LEVEL", [ Super_L, Super_L, Multi_key, Multi_key ] }; 14 | }; 15 | 16 | partial modifier_keys 17 | xkb_symbols "rwin" { 18 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 19 | }; 20 | 21 | partial modifier_keys 22 | xkb_symbols "rwin-altgr" { 23 | key { type[Group1]="FOUR_LEVEL", [ Super_R, Super_R, Multi_key, Multi_key ] }; 24 | }; 25 | 26 | partial modifier_keys 27 | xkb_symbols "menu" { 28 | key

{ type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 29 | }; 30 | 31 | partial modifier_keys 32 | xkb_symbols "menu-altgr" { 33 | key { type[Group1]="FOUR_LEVEL", [ Menu, Menu, Multi_key, Multi_key ] }; 34 | }; 35 | 36 | partial modifier_keys 37 | xkb_symbols "rctrl" { 38 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 39 | }; 40 | 41 | partial modifier_keys 42 | xkb_symbols "rctrl-altgr" { 43 | key { type[Group1]="FOUR_LEVEL", [ Control_R, Control_R, Multi_key, Multi_key ] }; 44 | }; 45 | 46 | partial modifier_keys 47 | xkb_symbols "lctrl" { 48 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 49 | }; 50 | 51 | partial modifier_keys 52 | xkb_symbols "lctrl-altgr" { 53 | key { type[Group1]="FOUR_LEVEL", [ Control_L, Control_L, Multi_key, Multi_key ] }; 54 | }; 55 | 56 | partial modifier_keys 57 | xkb_symbols "caps" { 58 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 59 | }; 60 | 61 | partial modifier_keys 62 | xkb_symbols "caps-altgr" { 63 | key { type[Group1]="FOUR_LEVEL", [ Caps_Lock, Caps_Lock, Multi_key, Multi_key ] }; 64 | }; 65 | 66 | partial modifier_keys 67 | xkb_symbols "102" { 68 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 69 | }; 70 | 71 | partial modifier_keys 72 | xkb_symbols "102-altgr" { 73 | key { type[Group1]="FOUR_LEVEL", [ less, greater, Multi_key, Multi_key ] }; 74 | }; 75 | 76 | partial modifier_keys 77 | xkb_symbols "paus" { 78 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 79 | }; 80 | 81 | partial modifier_keys 82 | xkb_symbols "prsc" { 83 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 84 | }; 85 | 86 | partial modifier_keys 87 | xkb_symbols "sclk" { 88 | key { type[Group1]="TWO_LEVEL", [ Multi_key, Multi_key ] }; 89 | }; 90 | -------------------------------------------------------------------------------- /test/data/keycodes/aliases: -------------------------------------------------------------------------------- 1 | 2 | // keycode aliases for phonetic keyboard maps 3 | 4 | default 5 | xkb_keycodes "qwerty" { 6 | 7 | alias = ; 8 | alias = ; 9 | alias = ; 10 | alias = ; 11 | alias = ; 12 | alias = ; 13 | alias = ; 14 | alias = ; 15 | alias = ; 16 | alias = ; 17 | 18 | alias = ; 19 | alias = ; 20 | alias = ; 21 | alias = ; 22 | alias = ; 23 | alias = ; 24 | alias = ; 25 | alias = ; 26 | alias = ; 27 | 28 | alias = ; 29 | alias = ; 30 | alias = ; 31 | alias = ; 32 | alias = ; 33 | alias = ; 34 | alias = ; 35 | }; 36 | 37 | xkb_keycodes "azerty" { 38 | 39 | alias = ; 40 | alias = ; 41 | alias = ; 42 | alias = ; 43 | alias = ; 44 | alias = ; 45 | alias = ; 46 | alias = ; 47 | alias = ; 48 | alias = ; 49 | 50 | alias = ; 51 | alias = ; 52 | alias = ; 53 | alias = ; 54 | alias = ; 55 | alias = ; 56 | alias = ; 57 | alias = ; 58 | alias = ; 59 | alias = ; 60 | 61 | alias = ; 62 | alias = ; 63 | alias = ; 64 | alias = ; 65 | alias = ; 66 | alias = ; 67 | }; 68 | 69 | xkb_keycodes "qwertz" { 70 | 71 | alias = ; 72 | alias = ; 73 | alias = ; 74 | alias = ; 75 | alias = ; 76 | alias = ; 77 | alias = ; 78 | alias = ; 79 | alias = ; 80 | alias = ; 81 | 82 | alias = ; 83 | alias = ; 84 | alias = ; 85 | alias = ; 86 | alias = ; 87 | alias = ; 88 | alias = ; 89 | alias = ; 90 | alias = ; 91 | 92 | alias = ; 93 | alias = ; 94 | alias = ; 95 | alias = ; 96 | alias = ; 97 | alias = ; 98 | alias = ; 99 | }; 100 | -------------------------------------------------------------------------------- /src/x11/state.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include "x11-priv.h" 27 | 28 | static bool 29 | update_initial_state(struct xkb_state *state, xcb_connection_t *conn, 30 | uint16_t device_id) 31 | { 32 | xcb_xkb_get_state_cookie_t cookie = 33 | xcb_xkb_get_state(conn, device_id); 34 | xcb_xkb_get_state_reply_t *reply = 35 | xcb_xkb_get_state_reply(conn, cookie, NULL); 36 | 37 | if (!reply) 38 | return false; 39 | 40 | xkb_state_update_mask(state, 41 | reply->baseMods, 42 | reply->latchedMods, 43 | reply->lockedMods, 44 | reply->baseGroup, 45 | reply->latchedGroup, 46 | reply->lockedGroup); 47 | 48 | free(reply); 49 | return true; 50 | } 51 | 52 | XKB_EXPORT struct xkb_state * 53 | xkb_x11_state_new_from_device(struct xkb_keymap *keymap, 54 | xcb_connection_t *conn, int32_t device_id) 55 | { 56 | struct xkb_state *state; 57 | 58 | if (device_id < 0 || device_id > 255) { 59 | log_err_func(keymap->ctx, "illegal device ID: %d", device_id); 60 | return NULL; 61 | } 62 | 63 | state = xkb_state_new(keymap); 64 | if (!state) 65 | return NULL; 66 | 67 | if (!update_initial_state(state, conn, device_id)) { 68 | xkb_state_unref(state); 69 | return NULL; 70 | } 71 | 72 | return state; 73 | } 74 | -------------------------------------------------------------------------------- /test/data/symbols/pc: -------------------------------------------------------------------------------- 1 | default partial alphanumeric_keys modifier_keys 2 | xkb_symbols "pc105" { 3 | 4 | key { [ Escape ] }; 5 | 6 | // The extra key on many European keyboards: 7 | key { [ less, greater, bar, brokenbar ] }; 8 | 9 | // The following keys are common to all layouts. 10 | key { [ backslash, bar ] }; 11 | key { [ space ] }; 12 | 13 | include "srvr_ctrl(fkey2vt)" 14 | include "pc(editing)" 15 | include "keypad(x11)" 16 | 17 | key { [ BackSpace, BackSpace ] }; 18 | 19 | key { [ Tab, ISO_Left_Tab ] }; 20 | key { [ Return ] }; 21 | 22 | key { [ Caps_Lock ] }; 23 | key { [ Num_Lock ] }; 24 | 25 | key { [ Shift_L ] }; 26 | key { [ Control_L ] }; 27 | key { [ Super_L ] }; 28 | 29 | key { [ Shift_R ] }; 30 | key { [ Control_R ] }; 31 | key { [ Super_R ] }; 32 | key { [ Menu ] }; 33 | 34 | // Beginning of modifier mappings. 35 | modifier_map Shift { Shift_L, Shift_R }; 36 | modifier_map Lock { Caps_Lock }; 37 | modifier_map Control{ Control_L, Control_R }; 38 | modifier_map Mod2 { Num_Lock }; 39 | modifier_map Mod4 { Super_L, Super_R }; 40 | 41 | // Fake keys for virtual<->real modifiers mapping: 42 | key { [ ISO_Level3_Shift ] }; 43 | key { [ Mode_switch ] }; 44 | modifier_map Mod5 { , }; 45 | 46 | key { [ NoSymbol, Alt_L ] }; 47 | include "altwin(meta_alt)" 48 | 49 | key { [ NoSymbol, Meta_L ] }; 50 | modifier_map Mod1 { }; 51 | 52 | key { [ NoSymbol, Super_L ] }; 53 | modifier_map Mod4 { }; 54 | 55 | key { [ NoSymbol, Hyper_L ] }; 56 | modifier_map Mod4 { }; 57 | // End of modifier mappings. 58 | 59 | key { [ XF86Display ] }; 60 | key { [ XF86KbdLightOnOff ] }; 61 | key { [ XF86KbdBrightnessDown ] }; 62 | key { [ XF86KbdBrightnessUp ] }; 63 | }; 64 | 65 | hidden partial alphanumeric_keys 66 | xkb_symbols "editing" { 67 | key { 68 | type= "PC_ALT_LEVEL2", 69 | symbols[Group1]= [ Print, Sys_Req ] 70 | }; 71 | key { [ Scroll_Lock ] }; 72 | key { 73 | type= "PC_CONTROL_LEVEL2", 74 | symbols[Group1]= [ Pause, Break ] 75 | }; 76 | key { [ Insert ] }; 77 | key { [ Home ] }; 78 | key { [ Prior ] }; 79 | key { [ Delete ] }; 80 | key { [ End ] }; 81 | key { [ Next ] }; 82 | 83 | key { [ Up ] }; 84 | key { [ Left ] }; 85 | key { [ Down ] }; 86 | key { [ Right ] }; 87 | }; 88 | -------------------------------------------------------------------------------- /bench/compose.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2014 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | 28 | #include "xkbcommon/xkbcommon-compose.h" 29 | 30 | #include "../test/test.h" 31 | #include "bench.h" 32 | 33 | #define BENCHMARK_ITERATIONS 1000 34 | 35 | int 36 | main(void) 37 | { 38 | struct xkb_context *ctx; 39 | char *path; 40 | FILE *file; 41 | struct xkb_compose_table *table; 42 | struct bench bench; 43 | char *elapsed; 44 | 45 | ctx = test_get_context(CONTEXT_NO_FLAG); 46 | assert(ctx); 47 | 48 | path = test_get_path("compose/en_US.UTF-8/Compose"); 49 | file = fopen(path, "rb"); 50 | if (file == NULL) { 51 | perror(path); 52 | free(path); 53 | xkb_context_unref(ctx); 54 | return -1; 55 | } 56 | 57 | xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); 58 | xkb_context_set_log_verbosity(ctx, 0); 59 | 60 | bench_start(&bench); 61 | for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { 62 | rewind(file); 63 | table = xkb_compose_table_new_from_file(ctx, file, "", 64 | XKB_COMPOSE_FORMAT_TEXT_V1, 65 | XKB_COMPOSE_COMPILE_NO_FLAGS); 66 | assert(table); 67 | xkb_compose_table_unref(table); 68 | } 69 | bench_stop(&bench); 70 | 71 | fclose(file); 72 | free(path); 73 | 74 | elapsed = bench_elapsed_str(&bench); 75 | fprintf(stderr, "compiled %d compose tables in %ss\n", 76 | BENCHMARK_ITERATIONS, elapsed); 77 | free(elapsed); 78 | 79 | xkb_context_unref(ctx); 80 | return 0; 81 | } 82 | -------------------------------------------------------------------------------- /test/filecomp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Dan Nicholson 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include "test.h" 27 | 28 | static int 29 | test_file(struct xkb_context *ctx, const char *path_rel) 30 | { 31 | struct xkb_keymap *keymap = test_compile_file(ctx, path_rel); 32 | 33 | if (!keymap) 34 | return 0; 35 | 36 | xkb_keymap_unref(keymap); 37 | return 1; 38 | } 39 | 40 | int 41 | main(void) 42 | { 43 | struct xkb_context *ctx = test_get_context(0); 44 | 45 | assert(test_file(ctx, "keymaps/basic.xkb")); 46 | assert(test_file(ctx, "keymaps/comprehensive-plus-geom.xkb")); 47 | assert(test_file(ctx, "keymaps/no-types.xkb")); 48 | assert(test_file(ctx, "keymaps/quartz.xkb")); 49 | assert(test_file(ctx, "keymaps/no-aliases.xkb")); 50 | 51 | assert(!test_file(ctx, "keymaps/divide-by-zero.xkb")); 52 | assert(!test_file(ctx, "keymaps/bad.xkb")); 53 | assert(!test_file(ctx, "keymaps/syntax-error.xkb")); 54 | assert(!test_file(ctx, "keymaps/syntax-error2.xkb")); 55 | assert(!test_file(ctx, "does not exist")); 56 | 57 | /* Test response to invalid flags and formats. */ 58 | fclose(stdin); 59 | assert(!xkb_keymap_new_from_file(ctx, NULL, XKB_KEYMAP_FORMAT_TEXT_V1, 0)); 60 | assert(!xkb_keymap_new_from_file(ctx, stdin, 0, 0)); 61 | assert(!xkb_keymap_new_from_file(ctx, stdin, XKB_KEYMAP_USE_ORIGINAL_FORMAT, 0)); 62 | assert(!xkb_keymap_new_from_file(ctx, stdin, 1234, 0)); 63 | assert(!xkb_keymap_new_from_file(ctx, stdin, XKB_KEYMAP_FORMAT_TEXT_V1, -1)); 64 | assert(!xkb_keymap_new_from_file(ctx, stdin, XKB_KEYMAP_FORMAT_TEXT_V1, 1234)); 65 | 66 | xkb_context_unref(ctx); 67 | 68 | return 0; 69 | } 70 | -------------------------------------------------------------------------------- /src/text.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Dan Nicholson 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef TEXT_H 25 | #define TEXT_H 26 | 27 | typedef struct { 28 | const char *name; 29 | unsigned int value; 30 | } LookupEntry; 31 | 32 | bool 33 | LookupString(const LookupEntry tab[], const char *string, 34 | unsigned int *value_rtrn); 35 | 36 | const char * 37 | LookupValue(const LookupEntry tab[], unsigned int value); 38 | 39 | extern const LookupEntry ctrlMaskNames[]; 40 | extern const LookupEntry modComponentMaskNames[]; 41 | extern const LookupEntry groupComponentMaskNames[]; 42 | extern const LookupEntry groupMaskNames[]; 43 | extern const LookupEntry groupNames[]; 44 | extern const LookupEntry levelNames[]; 45 | extern const LookupEntry buttonNames[]; 46 | extern const LookupEntry useModMapValueNames[]; 47 | extern const LookupEntry actionTypeNames[]; 48 | extern const LookupEntry symInterpretMatchMaskNames[]; 49 | 50 | const char * 51 | ModMaskText(struct xkb_context *ctx, const struct xkb_mod_set *mods, 52 | xkb_mod_mask_t mask); 53 | 54 | const char * 55 | ModIndexText(struct xkb_context *ctx, const struct xkb_mod_set *mods, 56 | xkb_mod_index_t ndx); 57 | 58 | const char * 59 | ActionTypeText(enum xkb_action_type type); 60 | 61 | const char * 62 | KeysymText(struct xkb_context *ctx, xkb_keysym_t sym); 63 | 64 | const char * 65 | KeyNameText(struct xkb_context *ctx, xkb_atom_t name); 66 | 67 | const char * 68 | SIMatchText(enum xkb_match_operation type); 69 | 70 | const char * 71 | LedStateMaskText(struct xkb_context *ctx, enum xkb_state_component mask); 72 | 73 | const char * 74 | ControlMaskText(struct xkb_context *ctx, enum xkb_action_controls mask); 75 | 76 | #endif /* TEXT_H */ 77 | -------------------------------------------------------------------------------- /test/data/symbols/srvr_ctrl: -------------------------------------------------------------------------------- 1 | // Actions which control the server's behavior. 2 | 3 | partial keypad_keys function_keys 4 | xkb_symbols "xfree86" { 5 | include "keypad(operators)" 6 | include "srvr_ctrl(fkey2vt)" 7 | }; 8 | 9 | partial function_keys 10 | xkb_symbols "fkey2vt" { 11 | 12 | key { 13 | type="CTRL+ALT", 14 | symbols[Group1]= [ F1, F1, F1, F1, XF86_Switch_VT_1 ] 15 | }; 16 | 17 | key { 18 | type="CTRL+ALT", 19 | symbols[Group1]= [ F2, F2, F2, F2, XF86_Switch_VT_2 ] 20 | }; 21 | 22 | key { 23 | type="CTRL+ALT", 24 | symbols[Group1]= [ F3, F3, F3, F3, XF86_Switch_VT_3 ] 25 | }; 26 | 27 | key { 28 | type="CTRL+ALT", 29 | symbols[Group1]= [ F4, F4, F4, F4, XF86_Switch_VT_4 ] 30 | }; 31 | 32 | key { 33 | type="CTRL+ALT", 34 | symbols[Group1]= [ F5, F5, F5, F5, XF86_Switch_VT_5 ] 35 | }; 36 | 37 | key { 38 | type="CTRL+ALT", 39 | symbols[Group1]= [ F6, F6, F6, F6, XF86_Switch_VT_6 ] 40 | }; 41 | 42 | key { 43 | type="CTRL+ALT", 44 | symbols[Group1]= [ F7, F7, F7, F7, XF86_Switch_VT_7 ] 45 | }; 46 | 47 | key { 48 | type="CTRL+ALT", 49 | symbols[Group1]= [ F8, F8, F8, F8, XF86_Switch_VT_8 ] 50 | }; 51 | 52 | key { 53 | type="CTRL+ALT", 54 | symbols[Group1]= [ F9, F9, F9, F9, XF86_Switch_VT_9 ] 55 | }; 56 | 57 | key { 58 | type="CTRL+ALT", 59 | symbols[Group1]= [ F10, F10, F10, F10, XF86_Switch_VT_10 ] 60 | }; 61 | 62 | key { 63 | type="CTRL+ALT", 64 | symbols[Group1]= [ F11, F11, F11, F11, XF86_Switch_VT_11 ] 65 | }; 66 | 67 | key { 68 | type="CTRL+ALT", 69 | symbols[Group1]= [ F12, F12, F12, F12, XF86_Switch_VT_12 ] 70 | }; 71 | }; 72 | 73 | partial function_keys keypad_keys 74 | xkb_symbols "no_srvr_keys" { 75 | 76 | key.type="TWO_LEVEL"; 77 | 78 | key { [ F1, F1 ] }; 79 | key { [ F2, F2 ] }; 80 | key { [ F3, F3 ] }; 81 | key { [ F4, F4 ] }; 82 | key { [ F5, F5 ] }; 83 | key { [ F6, F6 ] }; 84 | key { [ F7, F7 ] }; 85 | key { [ F8, F8 ] }; 86 | key { [ F9, F9 ] }; 87 | key { [ F10, F10 ] }; 88 | key { [ F11, F11 ] }; 89 | key { [ F12, F12 ] }; 90 | 91 | key { [ KP_Divide, KP_Divide ] }; 92 | key { [ KP_Multiply, KP_Multiply ] }; 93 | key { [ KP_Subtract, KP_Subtract ] }; 94 | key { [ KP_Add, KP_Add ] }; 95 | }; 96 | 97 | partial function_keys 98 | xkb_symbols "grab_debug" { 99 | 100 | key { 101 | type="CTRL+ALT", 102 | symbols[Group1]= [ F11, F11, F11, F11, XF86LogGrabInfo ] 103 | }; 104 | 105 | key { 106 | type="CTRL+ALT", 107 | symbols[Group1]= [ F12, F12, F12, F12, XF86LogWindowTree ] 108 | }; 109 | 110 | }; 111 | -------------------------------------------------------------------------------- /src/util-list.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2008-2011 Kristian Høgsberg 3 | * Copyright © 2011 Intel Corporation 4 | * Copyright © 2013-2015 Red Hat, Inc. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice (including the next 14 | * paragraph) shall be included in all copies or substantial portions of the 15 | * Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #pragma once 27 | 28 | #include "config.h" 29 | 30 | #include 31 | #include 32 | 33 | /* 34 | * This list data structure is a verbatim copy from wayland-util.h from the 35 | * Wayland project; except that wl_ prefix has been removed. 36 | */ 37 | 38 | struct list { 39 | struct list *prev; 40 | struct list *next; 41 | }; 42 | 43 | void list_init(struct list *list); 44 | void list_insert(struct list *list, struct list *elm); 45 | void list_append(struct list *list, struct list *elm); 46 | void list_remove(struct list *elm); 47 | bool list_empty(const struct list *list); 48 | bool list_is_last(const struct list *list, const struct list *elm); 49 | 50 | #define container_of(ptr, type, member) \ 51 | (__typeof__(type) *)((char *)(ptr) - \ 52 | offsetof(__typeof__(type), member)) 53 | 54 | #define list_first_entry(head, pos, member) \ 55 | container_of((head)->next, __typeof__(*pos), member) 56 | 57 | #define list_last_entry(head, pos, member) \ 58 | container_of((head)->prev, __typeof__(*pos), member) 59 | 60 | #define list_for_each(pos, head, member) \ 61 | for (pos = 0, pos = list_first_entry(head, pos, member); \ 62 | &pos->member != (head); \ 63 | pos = list_first_entry(&pos->member, pos, member)) 64 | 65 | #define list_for_each_safe(pos, tmp, head, member) \ 66 | for (pos = 0, tmp = 0, \ 67 | pos = list_first_entry(head, pos, member), \ 68 | tmp = list_first_entry(&pos->member, tmp, member); \ 69 | &pos->member != (head); \ 70 | pos = tmp, \ 71 | tmp = list_first_entry(&pos->member, tmp, member)) 72 | -------------------------------------------------------------------------------- /src/keysym.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 1985, 1987, 1990, 1998 The Open Group 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice shall be included in 12 | * all copies or substantial portions of the Software. 13 | * 14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 | * AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 18 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 | * 21 | * Except as contained in this notice, the names of the authors or their 22 | * institutions shall not be used in advertising or otherwise to promote the 23 | * sale, use or other dealings in this Software without prior written 24 | * authorization from the authors. 25 | */ 26 | 27 | /* 28 | * Copyright © 2009 Dan Nicholson 29 | * 30 | * Permission is hereby granted, free of charge, to any person obtaining a 31 | * copy of this software and associated documentation files (the "Software"), 32 | * to deal in the Software without restriction, including without limitation 33 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 34 | * and/or sell copies of the Software, and to permit persons to whom the 35 | * Software is furnished to do so, subject to the following conditions: 36 | * 37 | * The above copyright notice and this permission notice (including the next 38 | * paragraph) shall be included in all copies or substantial portions of the 39 | * Software. 40 | * 41 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 42 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 43 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 44 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 45 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 46 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 47 | * DEALINGS IN THE SOFTWARE. 48 | */ 49 | 50 | #ifndef KEYSYM_H 51 | #define KEYSYM_H 52 | 53 | bool 54 | xkb_keysym_is_lower(xkb_keysym_t keysym); 55 | 56 | bool 57 | xkb_keysym_is_upper(xkb_keysym_t keysym); 58 | 59 | bool 60 | xkb_keysym_is_keypad(xkb_keysym_t keysym); 61 | 62 | bool 63 | xkb_keysym_is_modifier(xkb_keysym_t keysym); 64 | 65 | #endif 66 | -------------------------------------------------------------------------------- /PACKAGING: -------------------------------------------------------------------------------- 1 | libxkbcommon consists of three shared libraries, libxkbcommon (the main 2 | library), libxkbcommon-x11 (an addon library for XCB clients) and libxkbregistry 3 | (a library to list available RMLVO options). 4 | 5 | The files for libxkbcommon-x11 are: 6 | libxkbcommon-x11.a libxkbcommon-x11.so* xkbcommon/xkbcommon-x11.h 7 | xkbcommon-x11.map xkbcommon-x11.pc 8 | 9 | libxkbcommon-x11 can be disabled with -Denable-x11=false (see 10 | `meson configure build` for other options/variables). 11 | 12 | The files for libxkbregistry are: 13 | libxkbregistry.a libxkbregistry.so* xkbcommon/xkbregistry.h 14 | xkbregistry.map xkbregistry.pc 15 | 16 | libxkbregistry can be disabled with -Denable-xkbregistry=false (see 17 | `meson configure build` for other options/variables). 18 | 19 | Dependencies for libxkbcommon: 20 | - C compiler, meson, pkg-config, libc. 21 | 22 | - (build) bison (preferred), win_bison or byacc>=20141006. 23 | byacc must be configured with --enable-btyacc. 24 | 25 | - (build optional, runtime required) xkeyboard-config. 26 | During build, for automatically detecting the value of 27 | -Dxkb-config-root instead of guessing (/usr/share/X11/xkb). 28 | During runtime, not strictly needed, but most users of the library 29 | would need it. 30 | 31 | - (runtime) libX11. 32 | Contains the dataset for Compose support (/usr/share/X11/locale). 33 | Please don't depend on it explicitly. 34 | 35 | - (build optional) doxygen. 36 | For generating the HTML documentation. 37 | To disable, use -Denable-docs=false. 38 | 39 | - (build optional) gperf. 40 | Output included in git and tarball. To regenerate, use 41 | `./scripts/update-keywords`. 42 | 43 | Dependencies for xkbcli: 44 | - libxkbcommon. 45 | 46 | Dependencies for libxkbcommon-x11: 47 | - libxkbcommon. 48 | 49 | - libxcb>=1.10 with libxcb-xkb. 50 | 51 | Dependencies for libxkbcommon-x11 tests: 52 | - xkbcomp, Xvfb. 53 | If they are not available, the relevant tests are skipped. 54 | 55 | Dependencies for libxkbregistry: 56 | - libxkbregistry is a sublibrary of libxkbcommon and cannot be built without 57 | building libxbkcommon. The files produced are otherwise independent. 58 | 59 | - libxml2 60 | 61 | - (build optional, runtime requirement) xkeyboard-config 62 | During build, for automatically detecting the value of 63 | -Dxkb-config-root instead of guessing (/usr/share/X11/xkb). 64 | 65 | Dependencies for Wayland tests: 66 | - wayland-client>=1.2.0, wayland-scanner, wayland-protocols>=1.0. 67 | To disable, use -Denable-wayland=false. 68 | 69 | Unless libxcb is always available as part of the system, it is preferred 70 | that libxkbcommon and libxkbcommon-x11 be split into separate packages, 71 | such that the main library does not depend on libxcb. This avoids a 72 | transitive dependency of Wayland clients on X libraries. 73 | 74 | It is perferred that libxkbregistry be split into a separate packages as most 75 | clients that require libxkbcommon do not require libxkbregistry and clients 76 | requiring libxkbregistry may not need libxkbcommon. 77 | -------------------------------------------------------------------------------- /test/test.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Intel Corporation 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | * 23 | * Author: Daniel Stone 24 | */ 25 | 26 | #include 27 | 28 | /* Don't use compat names in internal code. */ 29 | #define _XKBCOMMON_COMPAT_H 30 | #include "xkbcommon/xkbcommon.h" 31 | #include "xkbcommon/xkbcommon-compose.h" 32 | #include "utils.h" 33 | 34 | /* Automake test exit code to signify SKIP (à la PASS, FAIL, etc). */ 35 | #define SKIP_TEST 77 36 | 37 | /* The offset between KEY_* numbering, and keycodes in the XKB evdev 38 | * dataset. */ 39 | #define EVDEV_OFFSET 8 40 | 41 | enum key_seq_state { 42 | DOWN, 43 | REPEAT, 44 | UP, 45 | BOTH, 46 | NEXT, 47 | FINISH, 48 | }; 49 | 50 | int 51 | test_key_seq(struct xkb_keymap *keymap, ...); 52 | 53 | int 54 | test_key_seq_va(struct xkb_keymap *keymap, va_list args); 55 | 56 | char * 57 | test_get_path(const char *path_rel); 58 | 59 | char * 60 | test_read_file(const char *path_rel); 61 | 62 | enum test_context_flags { 63 | CONTEXT_NO_FLAG = 0, 64 | CONTEXT_ALLOW_ENVIRONMENT_NAMES = (1 << 0), 65 | }; 66 | 67 | struct xkb_context * 68 | test_get_context(enum test_context_flags flags); 69 | 70 | struct xkb_keymap * 71 | test_compile_file(struct xkb_context *context, const char *path_rel); 72 | 73 | struct xkb_keymap * 74 | test_compile_string(struct xkb_context *context, const char *string); 75 | 76 | struct xkb_keymap * 77 | test_compile_buffer(struct xkb_context *context, const char *buf, size_t len); 78 | 79 | struct xkb_keymap * 80 | test_compile_rules(struct xkb_context *context, const char *rules, 81 | const char *model, const char *layout, const char *variant, 82 | const char *options); 83 | 84 | 85 | #ifdef _MSC_VER 86 | #define setenv(varname, value, overwrite) _putenv_s((varname), (value)) 87 | #define unsetenv(varname) _putenv_s(varname, "") 88 | #endif 89 | -------------------------------------------------------------------------------- /src/x11/x11-priv.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #ifndef _XKBCOMMON_X11_PRIV_H 25 | #define _XKBCOMMON_X11_PRIV_H 26 | 27 | #include 28 | 29 | #include "keymap.h" 30 | #include "xkbcommon/xkbcommon-x11.h" 31 | 32 | struct x11_atom_interner { 33 | struct xkb_context *ctx; 34 | xcb_connection_t *conn; 35 | bool had_error; 36 | /* Atoms for which we send a GetAtomName request */ 37 | struct { 38 | xcb_atom_t from; 39 | xkb_atom_t *out; 40 | xcb_get_atom_name_cookie_t cookie; 41 | } pending[128]; 42 | size_t num_pending; 43 | /* Atoms which were already pending but queried again */ 44 | struct { 45 | xcb_atom_t from; 46 | xkb_atom_t *out; 47 | } copies[128]; 48 | size_t num_copies; 49 | /* These are not interned, but saved directly (after XkbEscapeMapName) */ 50 | struct { 51 | xcb_get_atom_name_cookie_t cookie; 52 | char **out; 53 | } escaped[4]; 54 | size_t num_escaped; 55 | }; 56 | 57 | void 58 | x11_atom_interner_init(struct x11_atom_interner *interner, 59 | struct xkb_context *ctx, xcb_connection_t *conn); 60 | 61 | void 62 | x11_atom_interner_round_trip(struct x11_atom_interner *interner); 63 | 64 | /* 65 | * Make a xkb_atom_t's from X atoms. The actual write is delayed until the next 66 | * call to x11_atom_interner_round_trip() or when too many atoms are pending. 67 | */ 68 | void 69 | x11_atom_interner_adopt_atom(struct x11_atom_interner *interner, 70 | const xcb_atom_t atom, xkb_atom_t *out); 71 | 72 | /* 73 | * Get a strdup'd and XkbEscapeMapName'd name of an X atom. The actual write is 74 | * delayed until the next call to x11_atom_interner_round_trip(). 75 | */ 76 | void 77 | x11_atom_interner_get_escaped_atom_name(struct x11_atom_interner *interner, 78 | xcb_atom_t atom, char **out); 79 | 80 | #endif 81 | -------------------------------------------------------------------------------- /bench/key-proc.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | #include 28 | 29 | #include "../test/test.h" 30 | #include "bench.h" 31 | 32 | #define BENCHMARK_ITERATIONS 20000000 33 | 34 | static void 35 | bench_key_proc(struct xkb_state *state) 36 | { 37 | int8_t keys[256] = { 0 }; 38 | xkb_keycode_t keycode; 39 | xkb_keysym_t keysym; 40 | int i; 41 | 42 | for (i = 0; i < BENCHMARK_ITERATIONS; i++) { 43 | keycode = (rand() % (255 - 9)) + 9; 44 | if (keys[keycode]) { 45 | xkb_state_update_key(state, keycode, XKB_KEY_UP); 46 | keys[keycode] = 0; 47 | keysym = xkb_state_key_get_one_sym(state, keycode); 48 | (void) keysym; 49 | } else { 50 | xkb_state_update_key(state, keycode, XKB_KEY_DOWN); 51 | keys[keycode] = 1; 52 | } 53 | } 54 | } 55 | 56 | int 57 | main(void) 58 | { 59 | struct xkb_context *ctx; 60 | struct xkb_keymap *keymap; 61 | struct xkb_state *state; 62 | struct bench bench; 63 | char *elapsed; 64 | 65 | ctx = test_get_context(0); 66 | assert(ctx); 67 | 68 | keymap = test_compile_rules(ctx, "evdev", "pc104", "us,ru,il,de", 69 | ",,,neo", "grp:menu_toggle"); 70 | assert(keymap); 71 | 72 | state = xkb_state_new(keymap); 73 | assert(state); 74 | 75 | xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); 76 | xkb_context_set_log_verbosity(ctx, 0); 77 | 78 | srand((unsigned) time(NULL)); 79 | 80 | bench_start(&bench); 81 | bench_key_proc(state); 82 | bench_stop(&bench); 83 | 84 | elapsed = bench_elapsed_str(&bench); 85 | fprintf(stderr, "ran %d iterations in %ss\n", 86 | BENCHMARK_ITERATIONS, elapsed); 87 | free(elapsed); 88 | 89 | xkb_state_unref(state); 90 | xkb_keymap_unref(keymap); 91 | xkb_context_unref(ctx); 92 | 93 | return 0; 94 | } 95 | -------------------------------------------------------------------------------- /src/util-list.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2008-2011 Kristian Høgsberg 3 | * Copyright © 2011 Intel Corporation 4 | * Copyright © 2013-2015 Red Hat, Inc. 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a 7 | * copy of this software and associated documentation files (the "Software"), 8 | * to deal in the Software without restriction, including without limitation 9 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 10 | * and/or sell copies of the Software, and to permit persons to whom the 11 | * Software is furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice (including the next 14 | * paragraph) shall be included in all copies or substantial portions of the 15 | * Software. 16 | * 17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 22 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | * DEALINGS IN THE SOFTWARE. 24 | */ 25 | 26 | #include "config.h" 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | #include "util-list.h" 33 | 34 | void 35 | list_init(struct list *list) 36 | { 37 | list->prev = list; 38 | list->next = list; 39 | } 40 | 41 | void 42 | list_insert(struct list *list, struct list *elm) 43 | { 44 | assert((list->next != NULL && list->prev != NULL) || 45 | !"list->next|prev is NULL, possibly missing list_init()"); 46 | assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) || 47 | !"elm->next|prev is not NULL, list node used twice?"); 48 | 49 | elm->prev = list; 50 | elm->next = list->next; 51 | list->next = elm; 52 | elm->next->prev = elm; 53 | } 54 | 55 | void 56 | list_append(struct list *list, struct list *elm) 57 | { 58 | assert((list->next != NULL && list->prev != NULL) || 59 | !"list->next|prev is NULL, possibly missing list_init()"); 60 | assert(((elm->next == NULL && elm->prev == NULL) || list_empty(elm)) || 61 | !"elm->next|prev is not NULL, list node used twice?"); 62 | 63 | elm->next = list; 64 | elm->prev = list->prev; 65 | list->prev = elm; 66 | elm->prev->next = elm; 67 | } 68 | 69 | void 70 | list_remove(struct list *elm) 71 | { 72 | assert((elm->next != NULL && elm->prev != NULL) || 73 | !"list->next|prev is NULL, possibly missing list_init()"); 74 | 75 | elm->prev->next = elm->next; 76 | elm->next->prev = elm->prev; 77 | elm->next = NULL; 78 | elm->prev = NULL; 79 | } 80 | 81 | bool 82 | list_empty(const struct list *list) 83 | { 84 | assert((list->next != NULL && list->prev != NULL) || 85 | !"list->next|prev is NULL, possibly missing list_init()"); 86 | 87 | return list->next == list; 88 | } 89 | 90 | bool 91 | list_is_last(const struct list *list, const struct list *elm) 92 | { 93 | return elm->next == list; 94 | } 95 | -------------------------------------------------------------------------------- /test/x11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2013 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include "test.h" 27 | #include "xkbcommon/xkbcommon-x11.h" 28 | 29 | int 30 | main(void) 31 | { 32 | struct xkb_context *ctx = test_get_context(0); 33 | xcb_connection_t *conn; 34 | int ret; 35 | int32_t device_id; 36 | struct xkb_keymap *keymap; 37 | struct xkb_state *state; 38 | char *dump; 39 | int exit_code = 0; 40 | 41 | /* 42 | * The next two steps depend on a running X server with XKB support. 43 | * If it fails, it's not necessarily an actual problem with the code. 44 | * So we don't want a FAIL here. 45 | */ 46 | conn = xcb_connect(NULL, NULL); 47 | if (!conn || xcb_connection_has_error(conn)) { 48 | exit_code = SKIP_TEST; 49 | goto err_conn; 50 | } 51 | 52 | ret = xkb_x11_setup_xkb_extension(conn, 53 | XKB_X11_MIN_MAJOR_XKB_VERSION, 54 | XKB_X11_MIN_MINOR_XKB_VERSION, 55 | XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, 56 | NULL, NULL, NULL, NULL); 57 | if (!ret) { 58 | exit_code = SKIP_TEST; 59 | goto err_conn; 60 | } 61 | 62 | device_id = xkb_x11_get_core_keyboard_device_id(conn); 63 | assert(device_id != -1); 64 | 65 | keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id, 66 | XKB_KEYMAP_COMPILE_NO_FLAGS); 67 | assert(keymap); 68 | 69 | state = xkb_x11_state_new_from_device(keymap, conn, device_id); 70 | assert(state); 71 | 72 | dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); 73 | assert(dump); 74 | fputs(dump, stdout); 75 | 76 | /* TODO: Write some X11-specific tests. */ 77 | 78 | free(dump); 79 | xkb_state_unref(state); 80 | xkb_keymap_unref(keymap); 81 | err_conn: 82 | xcb_disconnect(conn); 83 | xkb_context_unref(ctx); 84 | 85 | return exit_code; 86 | } 87 | -------------------------------------------------------------------------------- /xkbcommon.map: -------------------------------------------------------------------------------- 1 | V_0.5.0 { 2 | global: 3 | xkb_keysym_get_name; 4 | xkb_keysym_from_name; 5 | xkb_keysym_to_utf8; 6 | xkb_keysym_to_utf32; 7 | xkb_context_new; 8 | xkb_context_ref; 9 | xkb_context_unref; 10 | xkb_context_set_user_data; 11 | xkb_context_get_user_data; 12 | xkb_context_include_path_append; 13 | xkb_context_include_path_append_default; 14 | xkb_context_include_path_reset_defaults; 15 | xkb_context_include_path_clear; 16 | xkb_context_num_include_paths; 17 | xkb_context_include_path_get; 18 | xkb_context_set_log_level; 19 | xkb_context_get_log_level; 20 | xkb_context_set_log_verbosity; 21 | xkb_context_get_log_verbosity; 22 | xkb_context_set_log_fn; 23 | xkb_keymap_new_from_names; 24 | xkb_keymap_new_from_file; 25 | xkb_keymap_new_from_string; 26 | xkb_keymap_new_from_buffer; 27 | xkb_keymap_ref; 28 | xkb_keymap_unref; 29 | xkb_keymap_get_as_string; 30 | xkb_keymap_min_keycode; 31 | xkb_keymap_max_keycode; 32 | xkb_keymap_key_for_each; 33 | xkb_keymap_num_mods; 34 | xkb_keymap_mod_get_name; 35 | xkb_keymap_mod_get_index; 36 | xkb_keymap_num_layouts; 37 | xkb_keymap_layout_get_name; 38 | xkb_keymap_layout_get_index; 39 | xkb_keymap_num_leds; 40 | xkb_keymap_led_get_name; 41 | xkb_keymap_led_get_index; 42 | xkb_keymap_num_layouts_for_key; 43 | xkb_keymap_num_levels_for_key; 44 | xkb_keymap_key_get_syms_by_level; 45 | xkb_keymap_key_repeats; 46 | xkb_state_new; 47 | xkb_state_ref; 48 | xkb_state_unref; 49 | xkb_state_get_keymap; 50 | xkb_state_update_key; 51 | xkb_state_update_mask; 52 | xkb_state_key_get_syms; 53 | xkb_state_key_get_utf8; 54 | xkb_state_key_get_utf32; 55 | xkb_state_key_get_one_sym; 56 | xkb_state_key_get_layout; 57 | xkb_state_key_get_level; 58 | xkb_state_serialize_mods; 59 | xkb_state_serialize_layout; 60 | xkb_state_mod_name_is_active; 61 | xkb_state_mod_names_are_active; 62 | xkb_state_mod_index_is_active; 63 | xkb_state_mod_indices_are_active; 64 | xkb_state_mod_index_is_consumed; 65 | xkb_state_mod_mask_remove_consumed; 66 | xkb_state_key_get_consumed_mods; 67 | xkb_state_layout_name_is_active; 68 | xkb_state_layout_index_is_active; 69 | xkb_state_led_name_is_active; 70 | xkb_state_led_index_is_active; 71 | xkb_compose_table_new_from_locale; 72 | xkb_compose_table_new_from_file; 73 | xkb_compose_table_new_from_buffer; 74 | xkb_compose_table_ref; 75 | xkb_compose_table_unref; 76 | xkb_compose_state_new; 77 | xkb_compose_state_ref; 78 | xkb_compose_state_unref; 79 | xkb_compose_state_get_compose_table; 80 | xkb_compose_state_feed; 81 | xkb_compose_state_reset; 82 | xkb_compose_state_get_status; 83 | xkb_compose_state_get_utf8; 84 | xkb_compose_state_get_one_sym; 85 | local: 86 | *; 87 | }; 88 | 89 | V_0.6.0 { 90 | global: 91 | xkb_keymap_key_get_name; 92 | xkb_keymap_key_by_name; 93 | } V_0.5.0; 94 | 95 | V_0.7.0 { 96 | global: 97 | xkb_state_key_get_consumed_mods2; 98 | xkb_state_mod_index_is_consumed2; 99 | } V_0.6.0; 100 | 101 | V_0.8.0 { 102 | global: 103 | xkb_keysym_to_lower; 104 | xkb_keysym_to_upper; 105 | } V_0.7.0; 106 | 107 | V_1.0.0 { 108 | global: 109 | xkb_utf32_to_keysym; 110 | xkb_keymap_key_get_mods_for_level; 111 | } V_0.8.0; 112 | -------------------------------------------------------------------------------- /test/data/compat/misc: -------------------------------------------------------------------------------- 1 | default partial xkb_compatibility "misc" { 2 | 3 | virtual_modifiers Alt,Meta,Super,Hyper,ScrollLock; 4 | 5 | // Interpretations for some other useful keys. 6 | 7 | interpret Terminate_Server { 8 | action = Terminate(); 9 | }; 10 | 11 | setMods.clearLocks= True; 12 | 13 | // Sets the "Alt" virtual modifier. 14 | 15 | interpret Alt_L+Any { 16 | //useModMapMods= level1; 17 | virtualModifier= Alt; 18 | action = SetMods(modifiers=modMapMods); 19 | }; 20 | 21 | interpret Alt_L { 22 | action = SetMods(modifiers=Alt); 23 | }; 24 | 25 | interpret Alt_R+Any { 26 | //useModMapMods= level1; 27 | virtualModifier= Alt; 28 | action = SetMods(modifiers=modMapMods); 29 | }; 30 | 31 | interpret Alt_R { 32 | action = SetMods(modifiers=Alt); 33 | }; 34 | 35 | // Sets the "Meta" virtual modifier. 36 | 37 | interpret Meta_L+Any { 38 | //useModMapMods= level1; 39 | virtualModifier= Meta; 40 | action = SetMods(modifiers=modMapMods); 41 | }; 42 | 43 | interpret Meta_L { 44 | action = SetMods(modifiers=Meta); 45 | }; 46 | 47 | interpret Meta_R+Any { 48 | //useModMapMods= level1; 49 | virtualModifier= Meta; 50 | action = SetMods(modifiers=modMapMods); 51 | }; 52 | 53 | interpret Meta_R { 54 | action = SetMods(modifiers=Meta); 55 | }; 56 | 57 | // Sets the "Super" virtual modifier. 58 | 59 | interpret Super_L+Any { 60 | //useModMapMods= level1; 61 | virtualModifier= Super; 62 | action = SetMods(modifiers=modMapMods); 63 | }; 64 | 65 | interpret Super_L { 66 | action = SetMods(modifiers=Super); 67 | }; 68 | 69 | interpret Super_R+Any { 70 | //useModMapMods= level1; 71 | virtualModifier= Super; 72 | action = SetMods(modifiers=modMapMods); 73 | }; 74 | 75 | interpret Super_R { 76 | action = SetMods(modifiers=Super); 77 | }; 78 | 79 | // Sets the "Hyper" virtual modifier. 80 | 81 | interpret Hyper_L+Any { 82 | //useModMapMods= level1; 83 | virtualModifier= Hyper; 84 | action = SetMods(modifiers=modMapMods); 85 | }; 86 | 87 | interpret Hyper_L { 88 | action = SetMods(modifiers=Hyper); 89 | }; 90 | 91 | interpret Hyper_R+Any { 92 | //useModMapMods= level1; 93 | virtualModifier= Hyper; 94 | action = SetMods(modifiers=modMapMods); 95 | }; 96 | 97 | interpret Hyper_R { 98 | action = SetMods(modifiers=Hyper); 99 | }; 100 | 101 | // Sets the "ScrollLock" virtual modifier and 102 | // makes it actually lock when pressed. Sets 103 | // up a map for the scroll lock indicator. 104 | interpret Scroll_Lock+Any { 105 | virtualModifier= ScrollLock; 106 | action = LockMods(modifiers=modMapMods); 107 | }; 108 | 109 | include "ledscroll" 110 | 111 | include "misc(assign_shift_left_action)" 112 | }; 113 | 114 | partial xkb_compatibility "assign_shift_left_action" { 115 | // Because of the irrevertable modifier mapping in symbols/pc, 116 | // is getting bound to the Lock modifier when using 117 | // symbols/shift(both_capslock), creating unwanted behaviour. 118 | // This is a quirk, to circumvent the problem. 119 | interpret Shift_L { 120 | action = SetMods(modifiers = Shift); 121 | }; 122 | }; 123 | -------------------------------------------------------------------------------- /src/xkbcomp/expr.h: -------------------------------------------------------------------------------- 1 | /************************************************************ 2 | * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 | * 4 | * Permission to use, copy, modify, and distribute this 5 | * software and its documentation for any purpose and without 6 | * fee is hereby granted, provided that the above copyright 7 | * notice appear in all copies and that both that copyright 8 | * notice and this permission notice appear in supporting 9 | * documentation, and that the name of Silicon Graphics not be 10 | * used in advertising or publicity pertaining to distribution 11 | * of the software without specific prior written permission. 12 | * Silicon Graphics makes no representation about the suitability 13 | * of this software for any purpose. It is provided "as is" 14 | * without any express or implied warranty. 15 | * 16 | * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 | * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 | * THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 | * 25 | ********************************************************/ 26 | 27 | #ifndef XKBCOMP_EXPR_H 28 | #define XKBCOMP_EXPR_H 29 | 30 | bool 31 | ExprResolveLhs(struct xkb_context *ctx, const ExprDef *expr, 32 | const char **elem_rtrn, const char **field_rtrn, 33 | ExprDef **index_rtrn); 34 | 35 | bool 36 | ExprResolveModMask(struct xkb_context *ctx, const ExprDef *expr, 37 | enum mod_type mod_type, const struct xkb_mod_set *mods, 38 | xkb_mod_mask_t *mask_rtrn); 39 | 40 | bool 41 | ExprResolveMod(struct xkb_context *ctx, const ExprDef *def, 42 | enum mod_type mod_type, const struct xkb_mod_set *mods, 43 | xkb_mod_index_t *ndx_rtrn); 44 | 45 | bool 46 | ExprResolveBoolean(struct xkb_context *ctx, const ExprDef *expr, 47 | bool *set_rtrn); 48 | 49 | bool 50 | ExprResolveKeyCode(struct xkb_context *ctx, const ExprDef *expr, 51 | xkb_keycode_t *kc); 52 | 53 | bool 54 | ExprResolveInteger(struct xkb_context *ctx, const ExprDef *expr, 55 | int *val_rtrn); 56 | 57 | bool 58 | ExprResolveLevel(struct xkb_context *ctx, const ExprDef *expr, 59 | xkb_level_index_t *level_rtrn); 60 | 61 | bool 62 | ExprResolveGroup(struct xkb_context *ctx, const ExprDef *expr, 63 | xkb_layout_index_t *group_rtrn); 64 | 65 | bool 66 | ExprResolveButton(struct xkb_context *ctx, const ExprDef *expr, 67 | int *btn_rtrn); 68 | 69 | bool 70 | ExprResolveString(struct xkb_context *ctx, const ExprDef *expr, 71 | xkb_atom_t *val_rtrn); 72 | 73 | bool 74 | ExprResolveEnum(struct xkb_context *ctx, const ExprDef *expr, 75 | unsigned int *val_rtrn, const LookupEntry *values); 76 | 77 | bool 78 | ExprResolveMask(struct xkb_context *ctx, const ExprDef *expr, 79 | unsigned int *mask_rtrn, const LookupEntry *values); 80 | 81 | bool 82 | ExprResolveKeySym(struct xkb_context *ctx, const ExprDef *expr, 83 | xkb_keysym_t *sym_rtrn); 84 | 85 | #endif 86 | -------------------------------------------------------------------------------- /test/buffercomp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Dan Nicholson 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "test.h" 31 | 32 | #define DATA_PATH "keymaps/stringcomp.data" 33 | 34 | int 35 | main(int argc, char *argv[]) 36 | { 37 | struct xkb_context *ctx = test_get_context(0); 38 | struct xkb_keymap *keymap; 39 | char *original, *dump; 40 | 41 | assert(ctx); 42 | 43 | /* Load in a prebuilt keymap, make sure we can compile it from memory, 44 | * then compare it to make sure we get the same result when dumping it 45 | * to a string. */ 46 | original = test_read_file(DATA_PATH); 47 | assert(original); 48 | 49 | keymap = test_compile_buffer(ctx, original, strlen(original)); 50 | assert(keymap); 51 | 52 | dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); 53 | assert(dump); 54 | 55 | if (!streq(original, dump)) { 56 | fprintf(stderr, 57 | "round-trip test failed: dumped map differs from original\n"); 58 | fprintf(stderr, "path to original file: %s\n", 59 | test_get_path(DATA_PATH)); 60 | fprintf(stderr, "length: dumped %lu, original %lu\n", 61 | (unsigned long) strlen(dump), 62 | (unsigned long) strlen(original)); 63 | fprintf(stderr, "dumped map:\n"); 64 | fprintf(stderr, "%s\n", dump); 65 | fflush(stderr); 66 | assert(0); 67 | } 68 | 69 | free(original); 70 | free(dump); 71 | xkb_keymap_unref(keymap); 72 | 73 | /* Make sure we can't (falsely claim to) compile an empty string. */ 74 | keymap = test_compile_buffer(ctx, "", 0); 75 | assert(!keymap); 76 | 77 | /* Make sure we can recompile our output for a normal keymap from rules. */ 78 | keymap = test_compile_rules(ctx, NULL, NULL, 79 | "ru,ca,de,us", ",multix,neo,intl", NULL); 80 | assert(keymap); 81 | dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); 82 | assert(dump); 83 | xkb_keymap_unref(keymap); 84 | keymap = test_compile_buffer(ctx, dump, strlen(dump)); 85 | assert(keymap); 86 | xkb_keymap_unref(keymap); 87 | free(dump); 88 | 89 | xkb_context_unref(ctx); 90 | 91 | return 0; 92 | } 93 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | jobs: 10 | linux: 11 | runs-on: ubuntu-18.04 12 | strategy: 13 | matrix: 14 | compiler: [clang, gcc] 15 | steps: 16 | - uses: actions/checkout@v2 17 | - uses: actions/setup-python@v1 18 | with: 19 | python-version: '3.7' 20 | - name: Install dependencies 21 | run: | 22 | python -m pip install --upgrade pip meson 23 | sudo apt update -y 24 | sudo env DEBIAN_FRONTEND=noninteractive apt install -y \ 25 | doxygen libxcb-xkb-dev valgrind ninja-build \ 26 | libwayland-dev wayland-protocols bison graphviz 27 | - name: Setup 28 | run: | 29 | meson setup build 30 | env: 31 | CC: ${{ matrix.compiler }} 32 | - name: Build 33 | run: | 34 | meson compile -C build 35 | - name: Test 36 | run: 37 | meson test -C build --print-errorlogs --setup=valgrind --no-suite python-tests 38 | 39 | macos: 40 | runs-on: macos-10.15 41 | steps: 42 | - uses: actions/checkout@v2 43 | - uses: actions/setup-python@v1 44 | with: 45 | python-version: '3.7' 46 | - name: Install dependencies 47 | run: | 48 | python -m pip install --upgrade pip meson 49 | brew install libxml2 doxygen bison ninja 50 | brew link bison --force 51 | env: 52 | HOMEBREW_NO_AUTO_UPDATE: 1 53 | HOMEBREW_NO_INSTALL_CLEANUP: 1 54 | - name: Setup 55 | run: | 56 | PATH="/usr/local/opt/bison/bin:${PATH}" meson setup -Denable-wayland=false -Denable-x11=false build 57 | - name: Build 58 | run: | 59 | PATH="/usr/local/opt/bison/bin:${PATH}" meson compile -C build 60 | - name: Test 61 | run: 62 | meson test -C build --print-errorlogs 63 | 64 | windows: 65 | runs-on: windows-2019 66 | steps: 67 | - uses: actions/checkout@v2 68 | - uses: actions/setup-python@v1 69 | with: 70 | python-version: '3.7' 71 | - name: Install dependencies 72 | shell: powershell 73 | run: | 74 | python -m pip install --upgrade pip meson 75 | Invoke-WebRequest -Uri https://github.com/ninja-build/ninja/releases/download/v1.10.1/ninja-win.zip -OutFile ninja.zip 76 | Invoke-WebRequest -Uri https://github.com/lexxmark/winflexbison/releases/download/v2.5.23/win_flex_bison-2.5.23.zip -OutFile win_flex_bison.zip 77 | Expand-Archive -Path win_flex_bison.zip -DestinationPath bin 78 | Expand-Archive -Path ninja.zip -DestinationPath bin 79 | Write-Output ((Get-Location).ToString() + "./bin") | Out-File -Append -FilePath $env:GITHUB_PATH -Encoding utf8 80 | - name: Setup 81 | shell: cmd 82 | run: | 83 | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 84 | meson setup -Denable-wayland=false -Denable-x11=false -Denable-docs=false -Denable-xkbregistry=false build 85 | env: 86 | CC: cl 87 | - name: Build 88 | shell: cmd 89 | run: | 90 | call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 91 | meson compile -C build 92 | - name: Test 93 | run: 94 | meson test -C build --print-errorlogs 95 | -------------------------------------------------------------------------------- /bench/bench.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2015 Kazunobu Kuriyama 3 | * Ran Benita 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a 6 | * copy of this software and associated documentation files (the "Software"), 7 | * to deal in the Software without restriction, including without limitation 8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 | * and/or sell copies of the Software, and to permit persons to whom the 10 | * Software is furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice (including the next 13 | * paragraph) shall be included in all copies or substantial portions of the 14 | * Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 22 | * DEALINGS IN THE SOFTWARE. 23 | */ 24 | 25 | #include "config.h" 26 | 27 | #include 28 | #include 29 | 30 | #include "bench.h" 31 | #include "../src/utils.h" 32 | 33 | #ifndef _MSC_VER 34 | #include 35 | #else 36 | #include 37 | #include 38 | 39 | struct timeval { 40 | long tv_sec, tv_usec; 41 | }; 42 | 43 | static int 44 | gettimeofday(struct timeval *tv, void *unused) 45 | { 46 | static const uint64_t EPOCH = ((uint64_t) 116444736000000000ULL); 47 | 48 | SYSTEMTIME system_time; 49 | FILETIME file_time; 50 | uint64_t t; 51 | 52 | GetSystemTime(&system_time); 53 | SystemTimeToFileTime(&system_time, &file_time); 54 | t = (uint64_t) file_time.dwLowDateTime; 55 | t += ((uint64_t) file_time.dwHighDateTime) << 32; 56 | 57 | tv->tv_sec = (long) ((t - EPOCH) / 10000000L); 58 | tv->tv_usec = (long) (system_time.wMilliseconds * 1000); 59 | return 0; 60 | } 61 | #endif 62 | 63 | void 64 | bench_start(struct bench *bench) 65 | { 66 | struct timeval val; 67 | (void) gettimeofday(&val, NULL); 68 | bench->start = (struct bench_time) { 69 | .seconds = val.tv_sec, 70 | .microseconds = val.tv_usec, 71 | }; 72 | } 73 | 74 | void 75 | bench_stop(struct bench *bench) 76 | { 77 | struct timeval val; 78 | (void) gettimeofday(&val, NULL); 79 | bench->stop = (struct bench_time) { 80 | .seconds = val.tv_sec, 81 | .microseconds = val.tv_usec, 82 | }; 83 | } 84 | 85 | void 86 | bench_elapsed(const struct bench *bench, struct bench_time *result) 87 | { 88 | result->seconds = bench->stop.seconds - bench->start.seconds; 89 | result->microseconds = bench->stop.microseconds - bench->start.microseconds; 90 | if (result->microseconds < 0) { 91 | result->microseconds += 1000000; 92 | result->seconds--; 93 | } 94 | } 95 | 96 | char * 97 | bench_elapsed_str(const struct bench *bench) 98 | { 99 | struct bench_time elapsed; 100 | char *buf; 101 | int ret; 102 | 103 | bench_elapsed(bench, &elapsed); 104 | ret = asprintf(&buf, "%ld.%06ld", elapsed.seconds, elapsed.microseconds); 105 | assert(ret >= 0); 106 | 107 | return buf; 108 | } 109 | -------------------------------------------------------------------------------- /test/data/symbols/kpdl: -------------------------------------------------------------------------------- 1 | // The key is a mess. 2 | // It was probably originally meant to be a decimal separator. 3 | // Except since it was declared by USA people it didn't use the original 4 | // SI separator "," but a "." (since then the USA managed to f-up the SI 5 | // by making "." an accepted alternative, but standards still use "," as 6 | // default) 7 | // As a result users of SI-abiding countries expect either a "." or a "," 8 | // or a "decimal_separator" which may or may not be translated in one of the 9 | // above depending on applications. 10 | // It's not possible to define a default per-country since user expectations 11 | // depend on the conflicting choices of their most-used applications, 12 | // operating system, etc. Therefore it needs to be a configuration setting 13 | // Copyright © 2007 Nicolas Mailhot 14 | 15 | 16 | // Legacy #1 17 | // This assumes KP_Decimal will be translated in a dot 18 | partial keypad_keys 19 | xkb_symbols "dot" { 20 | 21 | key.type[Group1]="KEYPAD" ; 22 | 23 | key { [ KP_Delete, KP_Decimal ] }; // 24 | }; 25 | 26 | 27 | // Legacy #2 28 | // This assumes KP_Separator will be translated in a comma 29 | partial keypad_keys 30 | xkb_symbols "comma" { 31 | 32 | key.type[Group1]="KEYPAD" ; 33 | 34 | key { [ KP_Delete, KP_Separator ] }; // 35 | }; 36 | 37 | 38 | // Period , usual keyboard serigraphy in most countries 39 | partial keypad_keys 40 | xkb_symbols "dotoss" { 41 | 42 | key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; 43 | 44 | key { [ KP_Delete, period, comma, 0x100202F ] }; // . , ⍽ (narrow no-break space) 45 | }; 46 | 47 | 48 | // Period , usual keyboard serigraphy in most countries, latin-9 restriction 49 | partial keypad_keys 50 | xkb_symbols "dotoss_latin9" { 51 | 52 | key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; 53 | 54 | key { [ KP_Delete, period, comma, nobreakspace ] }; // . , ⍽ (no-break space) 55 | }; 56 | 57 | 58 | // Comma , what most non anglo-saxon people consider the real separator 59 | partial keypad_keys 60 | xkb_symbols "commaoss" { 61 | 62 | key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; 63 | 64 | key { [ KP_Delete, comma, period, 0x100202F ] }; // , . ⍽ (narrow no-break space) 65 | }; 66 | 67 | 68 | // Momayyez : Bahrain, Iran, Iraq, Kuwait, Oman, Qatar, Saudi Arabia, Syria, UAE 69 | partial keypad_keys 70 | xkb_symbols "momayyezoss" { 71 | 72 | key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; 73 | 74 | key { [ KP_Delete, 0x100066B, comma, 0x100202F ] }; // ? , ⍽ (narrow no-break space) 75 | }; 76 | 77 | 78 | // Abstracted , pray everything will work out (it usually does not) 79 | partial keypad_keys 80 | xkb_symbols "kposs" { 81 | 82 | key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; 83 | 84 | key { [ KP_Delete, KP_Decimal, KP_Separator, 0x100202F ] }; // ? ? ⍽ (narrow no-break space) 85 | }; 86 | 87 | // Spreadsheets may be configured to use the dot as decimal 88 | // punctuation, comma as a thousands separator and then semi-colon as 89 | // the list separator. Of these, dot and semi-colon is most important 90 | // when entering data by the keyboard; the comma can then be inferred 91 | // and added to the presentation afterwards. Using semi-colon as a 92 | // general separator may in fact be preferred to avoid ambiguities 93 | // in data files. Most times a decimal separator is hard-coded, it 94 | // seems to be period, probably since this is the syntax used in 95 | // (most) programming languages. 96 | partial keypad_keys 97 | xkb_symbols "semi" { 98 | 99 | key.type[Group1]="FOUR_LEVEL_MIXED_KEYPAD" ; 100 | 101 | key { [ NoSymbol, NoSymbol, semicolon ] }; 102 | }; 103 | -------------------------------------------------------------------------------- /bench/x11.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2020 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | #include 28 | 29 | #include 30 | 31 | #include "xkbcommon/xkbcommon.h" 32 | #include "xkbcommon/xkbcommon-x11.h" 33 | 34 | #include "bench.h" 35 | 36 | #define BENCHMARK_ITERATIONS 2500 37 | 38 | int 39 | main(void) 40 | { 41 | int ret; 42 | xcb_connection_t *conn; 43 | int32_t device_id; 44 | struct xkb_context *ctx; 45 | struct bench bench; 46 | char *elapsed; 47 | 48 | conn = xcb_connect(NULL, NULL); 49 | if (!conn || xcb_connection_has_error(conn)) { 50 | fprintf(stderr, "Couldn't connect to X server: error code %d\n", 51 | conn ? xcb_connection_has_error(conn) : -1); 52 | ret = -1; 53 | goto err_out; 54 | } 55 | 56 | ret = xkb_x11_setup_xkb_extension(conn, 57 | XKB_X11_MIN_MAJOR_XKB_VERSION, 58 | XKB_X11_MIN_MINOR_XKB_VERSION, 59 | XKB_X11_SETUP_XKB_EXTENSION_NO_FLAGS, 60 | NULL, NULL, NULL, NULL); 61 | if (!ret) { 62 | fprintf(stderr, "Couldn't setup XKB extension\n"); 63 | goto err_conn; 64 | } 65 | 66 | device_id = xkb_x11_get_core_keyboard_device_id(conn); 67 | if (device_id == -1) { 68 | ret = -1; 69 | fprintf(stderr, "Couldn't find core keyboard device\n"); 70 | goto err_conn; 71 | } 72 | 73 | ctx = xkb_context_new(XKB_CONTEXT_NO_FLAGS); 74 | if (!ctx) { 75 | ret = -1; 76 | fprintf(stderr, "Couldn't create xkb context\n"); 77 | goto err_conn; 78 | } 79 | 80 | bench_start(&bench); 81 | for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { 82 | struct xkb_keymap *keymap; 83 | struct xkb_state *state; 84 | 85 | keymap = xkb_x11_keymap_new_from_device(ctx, conn, device_id, 86 | XKB_KEYMAP_COMPILE_NO_FLAGS); 87 | assert(keymap); 88 | 89 | state = xkb_x11_state_new_from_device(keymap, conn, device_id); 90 | assert(state); 91 | 92 | xkb_state_unref(state); 93 | xkb_keymap_unref(keymap); 94 | } 95 | bench_stop(&bench); 96 | ret = 0; 97 | 98 | elapsed = bench_elapsed_str(&bench); 99 | fprintf(stderr, "retrieved %d keymaps from X in %ss\n", 100 | BENCHMARK_ITERATIONS, elapsed); 101 | free(elapsed); 102 | 103 | xkb_context_unref(ctx); 104 | err_conn: 105 | xcb_disconnect(conn); 106 | err_out: 107 | return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; 108 | } 109 | -------------------------------------------------------------------------------- /src/xkbcomp/ast-build.h: -------------------------------------------------------------------------------- 1 | /************************************************************ 2 | * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 | * 4 | * Permission to use, copy, modify, and distribute this 5 | * software and its documentation for any purpose and without 6 | * fee is hereby granted, provided that the above copyright 7 | * notice appear in all copies and that both that copyright 8 | * notice and this permission notice appear in supporting 9 | * documentation, and that the name of Silicon Graphics not be 10 | * used in advertising or publicity pertaining to distribution 11 | * of the software without specific prior written permission. 12 | * Silicon Graphics makes no representation about the suitability 13 | * of this software for any purpose. It is provided "as is" 14 | * without any express or implied warranty. 15 | * 16 | * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 | * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 | * THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 | * 25 | ********************************************************/ 26 | 27 | #ifndef XKBCOMP_AST_BUILD_H 28 | #define XKBCOMP_AST_BUILD_H 29 | 30 | ExprDef * 31 | ExprCreateString(xkb_atom_t str); 32 | 33 | ExprDef * 34 | ExprCreateInteger(int ival); 35 | 36 | ExprDef * 37 | ExprCreateFloat(void); 38 | 39 | ExprDef * 40 | ExprCreateBoolean(bool set); 41 | 42 | ExprDef * 43 | ExprCreateKeyName(xkb_atom_t key_name); 44 | 45 | ExprDef * 46 | ExprCreateIdent(xkb_atom_t ident); 47 | 48 | ExprDef * 49 | ExprCreateUnary(enum expr_op_type op, enum expr_value_type type, 50 | ExprDef *child); 51 | 52 | ExprDef * 53 | ExprCreateBinary(enum expr_op_type op, ExprDef *left, ExprDef *right); 54 | 55 | ExprDef * 56 | ExprCreateFieldRef(xkb_atom_t element, xkb_atom_t field); 57 | 58 | ExprDef * 59 | ExprCreateArrayRef(xkb_atom_t element, xkb_atom_t field, ExprDef *entry); 60 | 61 | ExprDef * 62 | ExprCreateAction(xkb_atom_t name, ExprDef *args); 63 | 64 | ExprDef * 65 | ExprCreateActionList(ExprDef *actions); 66 | 67 | ExprDef * 68 | ExprCreateMultiKeysymList(ExprDef *list); 69 | 70 | ExprDef * 71 | ExprCreateKeysymList(xkb_keysym_t sym); 72 | 73 | ExprDef * 74 | ExprAppendMultiKeysymList(ExprDef *list, ExprDef *append); 75 | 76 | ExprDef * 77 | ExprAppendKeysymList(ExprDef *list, xkb_keysym_t sym); 78 | 79 | KeycodeDef * 80 | KeycodeCreate(xkb_atom_t name, int64_t value); 81 | 82 | KeyAliasDef * 83 | KeyAliasCreate(xkb_atom_t alias, xkb_atom_t real); 84 | 85 | VModDef * 86 | VModCreate(xkb_atom_t name, ExprDef *value); 87 | 88 | VarDef * 89 | VarCreate(ExprDef *name, ExprDef *value); 90 | 91 | VarDef * 92 | BoolVarCreate(xkb_atom_t ident, bool set); 93 | 94 | InterpDef * 95 | InterpCreate(xkb_keysym_t sym, ExprDef *match); 96 | 97 | KeyTypeDef * 98 | KeyTypeCreate(xkb_atom_t name, VarDef *body); 99 | 100 | SymbolsDef * 101 | SymbolsCreate(xkb_atom_t keyName, VarDef *symbols); 102 | 103 | GroupCompatDef * 104 | GroupCompatCreate(unsigned group, ExprDef *def); 105 | 106 | ModMapDef * 107 | ModMapCreate(xkb_atom_t modifier, ExprDef *keys); 108 | 109 | LedMapDef * 110 | LedMapCreate(xkb_atom_t name, VarDef *body); 111 | 112 | LedNameDef * 113 | LedNameCreate(unsigned ndx, ExprDef *name, bool virtual); 114 | 115 | IncludeStmt * 116 | IncludeCreate(struct xkb_context *ctx, char *str, enum merge_mode merge); 117 | 118 | XkbFile * 119 | XkbFileCreate(enum xkb_file_type type, char *name, ParseCommon *defs, 120 | enum xkb_map_flags flags); 121 | 122 | void 123 | FreeStmt(ParseCommon *stmt); 124 | 125 | #endif 126 | -------------------------------------------------------------------------------- /test/data/types/pc: -------------------------------------------------------------------------------- 1 | default partial xkb_types "default" { 2 | 3 | // Some types that are necessary 4 | // for a full implementation of 5 | // a PC-compatible keyboard. 6 | 7 | virtual_modifiers Alt; 8 | virtual_modifiers LevelThree; 9 | virtual_modifiers LAlt; 10 | virtual_modifiers RAlt; 11 | virtual_modifiers RControl; 12 | virtual_modifiers LControl; 13 | 14 | type "PC_SUPER_LEVEL2" { 15 | modifiers = Mod4; 16 | map[None] = Level1; 17 | map[Mod4] = Level2; 18 | level_name[Level1] = "Base"; 19 | level_name[Level2] = "Super"; 20 | }; 21 | 22 | type "PC_CONTROL_LEVEL2" { 23 | modifiers = Control; 24 | map[None] = Level1; 25 | map[Control] = Level2; 26 | level_name[Level1] = "Base"; 27 | level_name[Level2] = "Control"; 28 | }; 29 | 30 | type "PC_LCONTROL_LEVEL2" { 31 | modifiers = LControl; 32 | map[None] = Level1; 33 | map[LControl] = Level2; 34 | level_name[Level1] = "Base"; 35 | level_name[Level2] = "LControl"; 36 | }; 37 | 38 | type "PC_RCONTROL_LEVEL2" { 39 | modifiers = RControl; 40 | map[None] = Level1; 41 | map[RControl] = Level2; 42 | level_name[Level1] = "Base"; 43 | level_name[Level2] = "RControl"; 44 | }; 45 | 46 | type "PC_ALT_LEVEL2" { 47 | modifiers = Alt; 48 | map[None] = Level1; 49 | map[Alt] = Level2; 50 | level_name[Level1] = "Base"; 51 | level_name[Level2] = "Alt"; 52 | }; 53 | 54 | type "PC_LALT_LEVEL2" { 55 | modifiers = LAlt; 56 | map[None] = Level1; 57 | map[LAlt] = Level2; 58 | level_name[Level1] = "Base"; 59 | level_name[Level2] = "LAlt"; 60 | }; 61 | 62 | type "PC_RALT_LEVEL2" { 63 | modifiers = RAlt; 64 | map[None] = Level1; 65 | map[RAlt] = Level2; 66 | level_name[Level1] = "Base"; 67 | level_name[Level2] = "RAlt"; 68 | }; 69 | 70 | type "CTRL+ALT" { 71 | modifiers = Control+Alt+Shift+LevelThree; 72 | map[None] = Level1; 73 | map[Shift] = Level2; 74 | map[LevelThree] = Level3; 75 | map[Shift+LevelThree] = Level4; 76 | map[Control+Alt] = Level5; 77 | preserve[Shift] = Shift; 78 | preserve[Shift+LevelThree] = Shift; 79 | level_name[Level1] = "Base"; 80 | level_name[Level2] = "Shift"; 81 | level_name[Level3] = "Alt Base"; 82 | level_name[Level4] = "Shift Alt"; 83 | level_name[Level5] = "Ctrl+Alt"; 84 | }; 85 | 86 | // Local eight level. 87 | // Needed when you want part of your layout eight-level but cannot use 88 | // LevelFive as modifier, as this will take over the right Ctrl by default 89 | // for the whole layout and is too invasive for the average four-level user. 90 | // Needed to fix bug #9529. 91 | // FIXME: Should really use RControl but it seems not to be enabled by 92 | // default and touching this requires a lot of testing. 93 | type "LOCAL_EIGHT_LEVEL" { 94 | modifiers = Shift+Lock+LevelThree+Control; 95 | 96 | map[None] = Level1; 97 | map[Lock+Shift] = Level1; 98 | map[Shift] = Level2; 99 | map[Lock] = Level2; 100 | 101 | map[LevelThree] = Level3; 102 | map[Lock+Shift+LevelThree] = Level3; 103 | map[Shift+LevelThree] = Level4; 104 | map[Lock+LevelThree] = Level4; 105 | 106 | map[Control] = Level5; 107 | map[Lock+Shift+Control] = Level5; 108 | map[Shift+Control] = Level6; 109 | map[Lock+Control] = Level6; 110 | 111 | map[LevelThree+Control] = Level7; 112 | map[Lock+Shift+LevelThree+Control] = Level7; 113 | map[Shift+LevelThree+Control] = Level8; 114 | map[Lock+LevelThree+Control] = Level8; 115 | 116 | level_name[Level1] = "Base"; 117 | level_name[Level2] = "Shift"; 118 | level_name[Level3] = "Level3"; 119 | level_name[Level4] = "Shift Level3"; 120 | level_name[Level5] = "Ctrl"; 121 | level_name[Level6] = "Shift Ctrl"; 122 | level_name[Level7] = "Level3 Ctrl"; 123 | level_name[Level8] = "Shift Level3 Ctrl"; 124 | }; 125 | 126 | }; 127 | -------------------------------------------------------------------------------- /tools/xkbcli.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2020 Red Hat, Inc. 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "tools-common.h" 31 | 32 | static void 33 | usage(void) 34 | { 35 | printf("Usage: xkbcli [--help|-h] [--version|-V] []\n" 36 | "\n" 37 | "Global options:\n" 38 | " -h, --help ...... show this help and exit\n" 39 | " -V, --version ... show version information and exit\n" 40 | "Commands:\n" 41 | #if HAVE_XKBCLI_LIST 42 | " list\n" 43 | " List available rules, models, layouts, variants and options\n" 44 | "\n" 45 | #endif 46 | #if HAVE_XKBCLI_INTERACTIVE_WAYLAND 47 | " interactive-wayland\n" 48 | " Interactive debugger for XKB keymaps for Wayland\n" 49 | "\n" 50 | #endif 51 | #if HAVE_XKBCLI_INTERACTIVE_X11 52 | " interactive-x11\n" 53 | " Interactive debugger for XKB keymaps for X11\n" 54 | "\n" 55 | #endif 56 | #if HAVE_XKBCLI_INTERACTIVE_EVDEV 57 | " interactive-evdev\n" 58 | " Interactive debugger for XKB keymaps for evdev\n" 59 | "\n" 60 | #endif 61 | #if HAVE_XKBCLI_COMPILE_KEYMAP 62 | " compile-keymap\n" 63 | " Compile an XKB keymap\n" 64 | "\n" 65 | #endif 66 | #if HAVE_XKBCLI_HOW_TO_TYPE 67 | " how-to-type\n" 68 | " Print key sequences to type a Unicode codepoint\n" 69 | "\n" 70 | #endif 71 | ); 72 | } 73 | 74 | int 75 | main(int argc, char **argv) 76 | { 77 | enum options { 78 | OPT_HELP = 1, 79 | OPT_VERSION, 80 | }; 81 | int option_index = 0; 82 | 83 | while (1) { 84 | int c; 85 | static struct option opts[] = { 86 | { "help", no_argument, 0, OPT_HELP }, 87 | { "version", no_argument, 0, OPT_VERSION }, 88 | { 0, 0, 0, 0} 89 | }; 90 | 91 | c = getopt_long(argc, argv, "+hV", opts, &option_index); 92 | if (c == -1) 93 | break; 94 | 95 | switch(c) { 96 | case 'h': 97 | case OPT_HELP: 98 | usage(); 99 | return EXIT_SUCCESS; 100 | case 'V': 101 | case OPT_VERSION: 102 | printf("%s\n", LIBXKBCOMMON_VERSION); 103 | return EXIT_SUCCESS; 104 | default: 105 | usage(); 106 | return EXIT_INVALID_USAGE; 107 | } 108 | } 109 | 110 | if (optind >= argc) { 111 | usage(); 112 | return EXIT_INVALID_USAGE; 113 | } 114 | 115 | argv += optind; 116 | argc -= optind; 117 | 118 | return tools_exec_command("xkbcli", argc, argv); 119 | } 120 | -------------------------------------------------------------------------------- /test/data/symbols/altwin: -------------------------------------------------------------------------------- 1 | // Meta is mapped to second level of Alt. 2 | partial modifier_keys 3 | xkb_symbols "meta_alt" { 4 | key { [ Alt_L, Meta_L ] }; 5 | key { type[Group1] = "TWO_LEVEL", 6 | symbols[Group1] = [ Alt_R, Meta_R ] }; 7 | modifier_map Mod1 { Alt_L, Alt_R, Meta_L, Meta_R }; 8 | // modifier_map Mod4 {}; 9 | }; 10 | 11 | // Alt is mapped to the Super and the usual Alt. 12 | partial modifier_keys 13 | xkb_symbols "alt_win" { 14 | key { [ Alt_L ] }; 15 | key { [ Alt_R ] }; 16 | modifier_map Mod1 { , }; 17 | }; 18 | 19 | // Ctrl is mapped to the Super and the usual Ctrl keys. 20 | partial modifier_keys 21 | xkb_symbols "ctrl_win" { 22 | key { [ Control_L ] }; 23 | key { [ Control_R ] }; 24 | modifier_map Control { , }; 25 | }; 26 | 27 | // Ctrl is mapped to the Alt, Alt to the Super, and Win to the Ctrl keys. 28 | partial modifier_keys 29 | xkb_symbols "ctrl_alt_win" { 30 | key { [ Control_L, Control_L ] }; 31 | key { type[Group1] = "TWO_LEVEL", 32 | symbols[Group1] = [ Control_R, Control_R ] }; 33 | key { [ Alt_L, Meta_L ] }; 34 | key { [ Alt_R, Meta_R ] }; 35 | key { [ Super_L ] }; 36 | key { [ Super_R ] }; 37 | modifier_map Control { , }; 38 | modifier_map Mod1 { , }; 39 | modifier_map Mod4 { , }; 40 | }; 41 | 42 | // Meta is mapped to the Super. 43 | partial modifier_keys 44 | xkb_symbols "meta_win" { 45 | key { [ Alt_L, Alt_L ] }; 46 | key { type[Group1] = "TWO_LEVEL", 47 | symbols[Group1] = [ Alt_R, Alt_R ] }; 48 | key { [ Meta_L ] }; 49 | key { [ Meta_R ] }; 50 | modifier_map Mod1 { Alt_L, Alt_R }; 51 | modifier_map Mod4 { , Meta_L, Meta_R }; 52 | }; 53 | 54 | // Meta is mapped to the left Win key. 55 | partial modifier_keys 56 | xkb_symbols "left_meta_win" { 57 | key { [ Alt_L, Alt_L ] }; 58 | key { [ Meta_L ] }; 59 | modifier_map Mod1 { Alt_L }; 60 | modifier_map Mod4 { , Meta_L }; 61 | }; 62 | 63 | // Hyper is mapped to the Super. 64 | partial modifier_keys 65 | xkb_symbols "hyper_win" { 66 | key { [ Hyper_L ] }; 67 | key { [ Hyper_R ] }; 68 | modifier_map Mod4 { Hyper_L, Hyper_R }; 69 | }; 70 | 71 | // Menu is mapped to the Menu key. 72 | partial modifier_keys 73 | xkb_symbols "menu" { 74 | key { [ Menu ] }; 75 | }; 76 | 77 | // Menu is mapped to the right Win key. 78 | partial modifier_keys 79 | xkb_symbols "menu_win" { 80 | key { [ Super_R ] }; 81 | }; 82 | 83 | // Layout for Tux key caps with additional right Alt key 84 | partial modifier_keys 85 | xkb_symbols "alt_super_win" { 86 | key { [ Alt_L, Meta_L ] }; 87 | key { [ Alt_R, Meta_R ] }; 88 | key { [ Super_L ]}; 89 | key { [ Super_R ] }; 90 | modifier_map Mod1 { Alt_L, Alt_R, Meta_L, Meta_R }; 91 | modifier_map Mod4 { Super_L, Super_R }; 92 | }; 93 | 94 | // Swap the Alt and Super. 95 | partial modifier_keys 96 | xkb_symbols "swap_alt_win" { 97 | include "altwin(swap_lalt_lwin)" 98 | include "altwin(swap_ralt_rwin)" 99 | }; 100 | 101 | // Swap the left Alt and Super. 102 | partial modifier_keys 103 | xkb_symbols "swap_lalt_lwin" { 104 | key { type[Group1] = "ONE_LEVEL", 105 | symbols[Group1] = [ Super_L ] }; 106 | key { [ Alt_L, Meta_L ] }; 107 | }; 108 | 109 | // Swap the right Alt and Super. 110 | hidden partial modifier_keys 111 | xkb_symbols "swap_ralt_rwin" { 112 | key { type[Group1] = "ONE_LEVEL", 113 | symbols[Group1] = [ Super_R ] }; 114 | key { [ Alt_R, Meta_R ] }; 115 | }; 116 | 117 | // Win is mapped to the PrtSc key (and the usual Win key). 118 | partial modifier_keys 119 | xkb_symbols "prtsc_rwin" { 120 | replace key { [ Super_R, Super_R ] }; 121 | modifier_map Mod4 { , }; 122 | }; 123 | -------------------------------------------------------------------------------- /doc/rules-format.md: -------------------------------------------------------------------------------- 1 | The rules file 2 | ============== 3 | 4 | The purpose of the rules file is to map between configuration values 5 | that are easy for a user to specify and understand, and the 6 | configuration values xkbcomp uses and understands. 7 | 8 | xkbcomp uses the xkb_component_names struct, which maps directly to 9 | include statements of the appropriate sections, called for short 10 | KcCGST (see doc/keymap-format-text-v1.txt; 'G' stands for "geometry", 11 | which is not supported). These are not really intuitive or straight- 12 | forward for the uninitiated. 13 | 14 | Instead, the user passes in a xkb_rule_names struct, which consists 15 | of the name of a rules file (in Linux this is usually "evdev"), a 16 | keyboard model (e.g. "pc105"), a set of layouts (which will end up 17 | in different groups, e.g. "us,fr"), variants (used to alter/augment 18 | the respective layout, e.g. "intl,dvorak"), and a set of options 19 | (used to tweak some general behavior of the keyboard, e.g. 20 | "ctrl:nocaps,compose:menu" to make the Caps Lock key act like Ctrl 21 | and the Menu key like Compose). We call these RMLVO. 22 | 23 | Format of the file 24 | ------------------ 25 | The file consists of rule sets, each consisting of rules (one per 26 | line), which match the MLVO values on the left hand side, and, if 27 | the values match to the values the user passed in, results in the 28 | values on the right hand side being added to the resulting KcCGST. 29 | Since some values are related and repeated often, it is possible 30 | to group them together and refer to them by a group name in the 31 | rules. 32 | 33 | Along with matching values by simple string equality, and for 34 | membership in a group defined previously, rules may also contain 35 | "wildcard" values - "*" - which always match. These usually appear 36 | near the end. 37 | 38 | Grammar 39 | ------- 40 | (It might be helpful to look at a file like rules/evdev along with 41 | this grammar. Comments, whitespace, etc. are not shown.) 42 | 43 | ``` 44 | File ::= { "!" (Include | Group | RuleSet) } 45 | 46 | Include ::= "include" 47 | 48 | Group ::= GroupName "=" { GroupElement } "\n" 49 | GroupName ::= "$" 50 | GroupElement ::= 51 | 52 | RuleSet ::= Mapping { Rule } 53 | 54 | Mapping ::= { Mlvo } "=" { Kccgst } "\n" 55 | Mlvo ::= "model" | "option" | ("layout" | "variant") [ Index ] 56 | Index ::= "[" 1..XKB_NUM_GROUPS "]" 57 | Kccgst ::= "keycodes" | "symbols" | "types" | "compat" | "geometry" 58 | 59 | Rule ::= { MlvoValue } "=" { KccgstValue } "\n" 60 | MlvoValue ::= "*" | GroupName | 61 | KccgstValue ::= 62 | ``` 63 | 64 | Notes: 65 | 66 | - Include processes the rules in the file path specified in the ident, 67 | in order. %-expansion is performed, as follows: 68 | 69 | ``` 70 | %%: 71 | A literal %. 72 | 73 | %H: 74 | The value of the HOME environment variable. 75 | 76 | %E: 77 | The extra lookup path for system-wide XKB data (usually /etc/xkb/rules). 78 | 79 | %S: 80 | The system-installed rules directory (usually /usr/share/X11/xkb/rules). 81 | ``` 82 | 83 | - The order of values in a Rule must be the same as the Mapping it 84 | follows. The mapping line determines the meaning of the values in 85 | the rules which follow in the RuleSet. 86 | 87 | - If a Rule is matched, %-expansion is performed on the KccgstValue, 88 | as follows: 89 | 90 | ``` 91 | %m, %l, %v: 92 | The model, layout or variant, if only one was given (e.g. 93 | %l for "us,il" is invalid). 94 | 95 | %l[1], %v[1]: 96 | Layout or variant for the specified group Index, if more than 97 | one was given (e.g. %l[1] for "us" is invalid). 98 | 99 | %+m, %+l, %+v, %+l[1], %+v[1] 100 | As above, but prefixed with '+'. Similarly, '|', '-', '_' may be 101 | used instead of '+'. 102 | 103 | %(m), %(l), %(l[1]), %(v), %(v[1]): 104 | As above, but prefixed by '(' and suffixed by ')'. 105 | ``` 106 | 107 | In case the expansion is invalid, as described above, it is 108 | skipped (the rest of the string is still processed); this includes 109 | the prefix and suffix (that's why you shouldn't use e.g. "(%v[1])"). 110 | -------------------------------------------------------------------------------- /src/xkbcomp/vmod.c: -------------------------------------------------------------------------------- 1 | /************************************************************ 2 | * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 | * 4 | * Permission to use, copy, modify, and distribute this 5 | * software and its documentation for any purpose and without 6 | * fee is hereby granted, provided that the above copyright 7 | * notice appear in all copies and that both that copyright 8 | * notice and this permission notice appear in supporting 9 | * documentation, and that the name of Silicon Graphics not be 10 | * used in advertising or publicity pertaining to distribution 11 | * of the software without specific prior written permission. 12 | * Silicon Graphics makes no representation about the suitability 13 | * of this software for any purpose. It is provided "as is" 14 | * without any express or implied warranty. 15 | * 16 | * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 | * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 | * THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 | * 25 | ********************************************************/ 26 | 27 | #include "config.h" 28 | 29 | #include "xkbcomp-priv.h" 30 | #include "text.h" 31 | #include "expr.h" 32 | #include "vmod.h" 33 | 34 | bool 35 | HandleVModDef(struct xkb_context *ctx, struct xkb_mod_set *mods, 36 | VModDef *stmt, enum merge_mode merge) 37 | { 38 | xkb_mod_index_t i; 39 | struct xkb_mod *mod; 40 | xkb_mod_mask_t mapping; 41 | 42 | merge = (merge == MERGE_DEFAULT ? stmt->merge : merge); 43 | 44 | if (stmt->value) { 45 | /* 46 | * This is a statement such as 'virtualModifiers NumLock = Mod1'; 47 | * it sets the vmod-to-real-mod[s] mapping directly instead of going 48 | * through modifier_map or some such. 49 | */ 50 | if (!ExprResolveModMask(ctx, stmt->value, MOD_REAL, mods, &mapping)) { 51 | log_err(ctx, 52 | "Declaration of %s ignored\n", 53 | xkb_atom_text(ctx, stmt->name)); 54 | return false; 55 | } 56 | } 57 | else { 58 | mapping = 0; 59 | } 60 | 61 | xkb_mods_enumerate(i, mod, mods) { 62 | if (mod->name == stmt->name) { 63 | if (mod->type != MOD_VIRT) { 64 | log_err(ctx, 65 | "Can't add a virtual modifier named \"%s\"; " 66 | "there is already a non-virtual modifier with this name! Ignored\n", 67 | xkb_atom_text(ctx, mod->name)); 68 | return false; 69 | } 70 | 71 | if (mod->mapping == mapping) 72 | return true; 73 | 74 | if (mod->mapping != 0) { 75 | xkb_mod_mask_t use, ignore; 76 | 77 | use = (merge == MERGE_OVERRIDE ? mapping : mod->mapping); 78 | ignore = (merge == MERGE_OVERRIDE ? mod->mapping : mapping); 79 | 80 | log_warn(ctx, 81 | "Virtual modifier %s defined multiple times; " 82 | "Using %s, ignoring %s\n", 83 | xkb_atom_text(ctx, stmt->name), 84 | ModMaskText(ctx, mods, use), 85 | ModMaskText(ctx, mods, ignore)); 86 | 87 | mapping = use; 88 | } 89 | 90 | mod->mapping = mapping; 91 | return true; 92 | } 93 | } 94 | 95 | if (mods->num_mods >= XKB_MAX_MODS) { 96 | log_err(ctx, 97 | "Too many modifiers defined (maximum %d)\n", 98 | XKB_MAX_MODS); 99 | return false; 100 | } 101 | 102 | mods->mods[mods->num_mods].name = stmt->name; 103 | mods->mods[mods->num_mods].type = MOD_VIRT; 104 | mods->mods[mods->num_mods].mapping = mapping; 105 | mods->num_mods++; 106 | return true; 107 | } 108 | -------------------------------------------------------------------------------- /test/stringcomp.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2009 Dan Nicholson 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "test.h" 31 | 32 | #define DATA_PATH "keymaps/stringcomp.data" 33 | 34 | int 35 | main(int argc, char *argv[]) 36 | { 37 | struct xkb_context *ctx = test_get_context(0); 38 | struct xkb_keymap *keymap; 39 | char *original, *dump, *dump2; 40 | 41 | assert(ctx); 42 | 43 | /* Load in a prebuilt keymap, make sure we can compile it from a string, 44 | * then compare it to make sure we get the same result when dumping it 45 | * to a string. */ 46 | original = test_read_file(DATA_PATH); 47 | assert(original); 48 | 49 | keymap = test_compile_string(ctx, original); 50 | assert(keymap); 51 | 52 | dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); 53 | assert(dump); 54 | 55 | if (!streq(original, dump)) { 56 | fprintf(stderr, 57 | "round-trip test failed: dumped map differs from original\n"); 58 | fprintf(stderr, "path to original file: %s\n", 59 | test_get_path(DATA_PATH)); 60 | fprintf(stderr, "length: dumped %lu, original %lu\n", 61 | (unsigned long) strlen(dump), 62 | (unsigned long) strlen(original)); 63 | fprintf(stderr, "dumped map:\n"); 64 | fprintf(stderr, "%s\n", dump); 65 | fflush(stderr); 66 | assert(0); 67 | } 68 | 69 | free(original); 70 | free(dump); 71 | xkb_keymap_unref(keymap); 72 | 73 | /* Make sure we can't (falsely claim to) compile an empty string. */ 74 | keymap = test_compile_string(ctx, ""); 75 | assert(!keymap); 76 | 77 | /* Make sure we can recompile our output for a normal keymap from rules. */ 78 | keymap = test_compile_rules(ctx, NULL, NULL, 79 | "ru,ca,de,us", ",multix,neo,intl", NULL); 80 | assert(keymap); 81 | dump = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); 82 | assert(dump); 83 | xkb_keymap_unref(keymap); 84 | keymap = test_compile_string(ctx, dump); 85 | assert(keymap); 86 | /* Now test that the dump of the dump is equal to the dump! */ 87 | dump2 = xkb_keymap_get_as_string(keymap, XKB_KEYMAP_USE_ORIGINAL_FORMAT); 88 | assert(dump2); 89 | assert(streq(dump, dump2)); 90 | 91 | /* Test response to invalid formats and flags. */ 92 | assert(!xkb_keymap_new_from_string(ctx, dump, 0, 0)); 93 | assert(!xkb_keymap_new_from_string(ctx, dump, -1, 0)); 94 | assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1+1, 0)); 95 | assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1, -1)); 96 | assert(!xkb_keymap_new_from_string(ctx, dump, XKB_KEYMAP_FORMAT_TEXT_V1, 1414)); 97 | assert(!xkb_keymap_get_as_string(keymap, 0)); 98 | assert(!xkb_keymap_get_as_string(keymap, 4893)); 99 | 100 | xkb_keymap_unref(keymap); 101 | free(dump); 102 | free(dump2); 103 | 104 | xkb_context_unref(ctx); 105 | 106 | return 0; 107 | } 108 | -------------------------------------------------------------------------------- /test/log.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright © 2012 Ran Benita 3 | * 4 | * Permission is hereby granted, free of charge, to any person obtaining a 5 | * copy of this software and associated documentation files (the "Software"), 6 | * to deal in the Software without restriction, including without limitation 7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 | * and/or sell copies of the Software, and to permit persons to whom the 9 | * Software is furnished to do so, subject to the following conditions: 10 | * 11 | * The above copyright notice and this permission notice (including the next 12 | * paragraph) shall be included in all copies or substantial portions of the 13 | * Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21 | * DEALINGS IN THE SOFTWARE. 22 | */ 23 | 24 | #include "config.h" 25 | 26 | #include "test.h" 27 | #include "context.h" 28 | 29 | #ifdef __GNUC__ 30 | #pragma GCC diagnostic ignored "-Wmissing-format-attribute" 31 | #endif 32 | 33 | static const char * 34 | log_level_to_string(enum xkb_log_level level) 35 | { 36 | switch (level) { 37 | case XKB_LOG_LEVEL_CRITICAL: 38 | return "critical"; 39 | case XKB_LOG_LEVEL_ERROR: 40 | return "error"; 41 | case XKB_LOG_LEVEL_WARNING: 42 | return "warning"; 43 | case XKB_LOG_LEVEL_INFO: 44 | return "info"; 45 | case XKB_LOG_LEVEL_DEBUG: 46 | return "debug"; 47 | } 48 | 49 | return "unknown"; 50 | } 51 | 52 | ATTR_PRINTF(3, 0) static void 53 | log_fn(struct xkb_context *ctx, enum xkb_log_level level, 54 | const char *fmt, va_list args) 55 | { 56 | char *s; 57 | int size; 58 | darray_char *ls = xkb_context_get_user_data(ctx); 59 | assert(ls); 60 | 61 | size = vasprintf(&s, fmt, args); 62 | assert(size != -1); 63 | 64 | darray_append_string(*ls, log_level_to_string(level)); 65 | darray_append_lit(*ls, ": "); 66 | darray_append_string(*ls, s); 67 | free(s); 68 | } 69 | 70 | int 71 | main(void) 72 | { 73 | darray_char log_string; 74 | struct xkb_context *ctx; 75 | int ret; 76 | 77 | ret = setenv("XKB_LOG_LEVEL", "warn", 1); 78 | assert(ret == 0); 79 | ret = setenv("XKB_LOG_VERBOSITY", "5", 1); 80 | assert(ret == 0); 81 | ctx = test_get_context(0); 82 | assert(ctx); 83 | 84 | darray_init(log_string); 85 | xkb_context_set_user_data(ctx, &log_string); 86 | xkb_context_set_log_fn(ctx, log_fn); 87 | 88 | log_warn(ctx, "first warning: %d\n", 87); 89 | log_info(ctx, "first info\n"); 90 | log_dbg(ctx, "first debug: %s\n", "hello"); 91 | log_err(ctx, "first error: %lu\n", 115415UL); 92 | log_vrb(ctx, 5, "first verbose 5\n"); 93 | 94 | xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_DEBUG); 95 | log_warn(ctx, "second warning: %d\n", 87); 96 | log_dbg(ctx, "second debug: %s %s\n", "hello", "world"); 97 | log_info(ctx, "second info\n"); 98 | log_err(ctx, "second error: %lu\n", 115415UL); 99 | log_vrb(ctx, 6, "second verbose 6\n"); 100 | 101 | xkb_context_set_log_verbosity(ctx, 0); 102 | xkb_context_set_log_level(ctx, XKB_LOG_LEVEL_CRITICAL); 103 | log_warn(ctx, "third warning: %d\n", 87); 104 | log_dbg(ctx, "third debug: %s %s\n", "hello", "world"); 105 | log_info(ctx, "third info\n"); 106 | log_err(ctx, "third error: %lu\n", 115415UL); 107 | log_vrb(ctx, 0, "third verbose 0\n"); 108 | 109 | printf("%s", log_string.item); 110 | 111 | assert(streq(log_string.item, 112 | "warning: first warning: 87\n" 113 | "error: first error: 115415\n" 114 | "warning: first verbose 5\n" 115 | "warning: second warning: 87\n" 116 | "debug: second debug: hello world\n" 117 | "info: second info\n" 118 | "error: second error: 115415\n")); 119 | 120 | xkb_context_unref(ctx); 121 | darray_free(log_string); 122 | return 0; 123 | } 124 | -------------------------------------------------------------------------------- /src/xkbcomp/xkbcomp-priv.h: -------------------------------------------------------------------------------- 1 | /************************************************************ 2 | * Copyright (c) 1994 by Silicon Graphics Computer Systems, Inc. 3 | * 4 | * Permission to use, copy, modify, and distribute this 5 | * software and its documentation for any purpose and without 6 | * fee is hereby granted, provided that the above copyright 7 | * notice appear in all copies and that both that copyright 8 | * notice and this permission notice appear in supporting 9 | * documentation, and that the name of Silicon Graphics not be 10 | * used in advertising or publicity pertaining to distribution 11 | * of the software without specific prior written permission. 12 | * Silicon Graphics makes no representation about the suitability 13 | * of this software for any purpose. It is provided "as is" 14 | * without any express or implied warranty. 15 | * 16 | * SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS 17 | * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 18 | * AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON 19 | * GRAPHICS BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL 20 | * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, 21 | * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 22 | * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 23 | * THE USE OR PERFORMANCE OF THIS SOFTWARE. 24 | * 25 | ********************************************************/ 26 | 27 | #ifndef XKBCOMP_PRIV_H 28 | #define XKBCOMP_PRIV_H 29 | 30 | #include "keymap.h" 31 | #include "ast.h" 32 | 33 | struct xkb_component_names { 34 | char *keycodes; 35 | char *types; 36 | char *compat; 37 | char *symbols; 38 | }; 39 | 40 | char * 41 | text_v1_keymap_get_as_string(struct xkb_keymap *keymap); 42 | 43 | XkbFile * 44 | XkbParseFile(struct xkb_context *ctx, FILE *file, 45 | const char *file_name, const char *map); 46 | 47 | XkbFile * 48 | XkbParseString(struct xkb_context *ctx, 49 | const char *string, size_t len, 50 | const char *file_name, const char *map); 51 | 52 | void 53 | FreeXkbFile(XkbFile *file); 54 | 55 | XkbFile * 56 | XkbFileFromComponents(struct xkb_context *ctx, 57 | const struct xkb_component_names *kkctgs); 58 | 59 | bool 60 | CompileKeycodes(XkbFile *file, struct xkb_keymap *keymap, 61 | enum merge_mode merge); 62 | 63 | bool 64 | CompileKeyTypes(XkbFile *file, struct xkb_keymap *keymap, 65 | enum merge_mode merge); 66 | 67 | bool 68 | CompileCompatMap(XkbFile *file, struct xkb_keymap *keymap, 69 | enum merge_mode merge); 70 | 71 | bool 72 | CompileSymbols(XkbFile *file, struct xkb_keymap *keymap, 73 | enum merge_mode merge); 74 | 75 | bool 76 | CompileKeymap(XkbFile *file, struct xkb_keymap *keymap, 77 | enum merge_mode merge); 78 | 79 | /***====================================================================***/ 80 | 81 | static inline bool 82 | ReportNotArray(struct xkb_context *ctx, const char *type, const char *field, 83 | const char *name) 84 | { 85 | log_err(ctx, 86 | "The %s %s field is not an array; " 87 | "Ignoring illegal assignment in %s\n", 88 | type, field, name); 89 | return false; 90 | } 91 | 92 | static inline bool 93 | ReportShouldBeArray(struct xkb_context *ctx, const char *type, 94 | const char *field, const char *name) 95 | { 96 | log_err(ctx, 97 | "Missing subscript for %s %s; " 98 | "Ignoring illegal assignment in %s\n", 99 | type, field, name); 100 | return false; 101 | } 102 | 103 | static inline bool 104 | ReportBadType(struct xkb_context *ctx, const char *type, const char *field, 105 | const char *name, const char *wanted) 106 | { 107 | log_err(ctx, "The %s %s field must be a %s; " 108 | "Ignoring illegal assignment in %s\n", 109 | type, field, wanted, name); 110 | return false; 111 | } 112 | 113 | static inline bool 114 | ReportBadField(struct xkb_context *ctx, const char *type, const char *field, 115 | const char *name) 116 | { 117 | log_err(ctx, 118 | "Unknown %s field %s in %s; " 119 | "Ignoring assignment to unknown field in %s\n", 120 | type, field, name, name); 121 | return false; 122 | } 123 | 124 | #endif 125 | --------------------------------------------------------------------------------

; 17 | 18 | alias = ; 19 | alias = ; 20 | alias = ; 21 | alias = ; 22 | alias = ; 23 | alias = ; 24 | alias = ; 25 | alias = ; 26 | alias = ; 27 | 28 | alias = ; 29 | alias = ; 30 | alias = ; 31 | alias = ; 32 | alias = ; 33 | alias = ; 34 | alias = ; 35 | }; 36 | 37 | xkb_keycodes "azerty" { 38 | 39 | alias = ; 40 | alias = ; 41 | alias = ; 42 | alias = ; 43 | alias = ; 44 | alias = ; 45 | alias = ; 46 | alias = ; 47 | alias = ; 48 | alias =