├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── Sourcedeps ├── VERSION ├── contrib └── systemd │ └── sxhkd.service ├── doc ├── sxhkd.1 └── sxhkd.1.asciidoc ├── examples ├── background_shell │ ├── profile │ ├── shell │ ├── sxhkdrc │ └── xinitrc └── notification │ ├── autostart │ ├── pam_environment │ ├── sxhkd_notify │ └── xinitrc └── src ├── grab.c ├── grab.h ├── helpers.c ├── helpers.h ├── locales.h ├── parse.c ├── parse.h ├── sxhkd.c ├── sxhkd.h ├── types.c └── types.h /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | sxhkd 3 | tags 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Bastien Dejean 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | 1. Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 2. Redistributions in binary form must reproduce the above copyright notice, 10 | this list of conditions and the following disclaimer in the documentation 11 | and/or other materials provided with the distribution. 12 | 13 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | OUT = sxhkd 2 | VERCMD ?= git describe --tags 2> /dev/null 3 | VERSION := $(shell $(VERCMD) || cat VERSION) 4 | 5 | CPPFLAGS += -D_POSIX_C_SOURCE=200112L -DVERSION=\"$(VERSION)\" 6 | CFLAGS += -std=c99 -pedantic -Wall -Wextra 7 | LDFLAGS ?= 8 | LDLIBS = $(LDFLAGS) -lxcb -lxcb-keysyms 9 | 10 | PREFIX ?= /usr/local 11 | BINPREFIX ?= $(PREFIX)/bin 12 | MANPREFIX ?= $(PREFIX)/share/man 13 | DOCPREFIX ?= $(PREFIX)/share/doc/$(OUT) 14 | 15 | all: $(OUT) 16 | 17 | debug: CFLAGS += -O0 -g 18 | debug: CPPFLAGS += -DDEBUG 19 | debug: $(OUT) 20 | 21 | VPATH = src 22 | OBJ = 23 | 24 | include Sourcedeps 25 | 26 | $(OBJ): Makefile 27 | 28 | $(OUT): $(OBJ) 29 | 30 | install: 31 | mkdir -p "$(DESTDIR)$(BINPREFIX)" 32 | cp -pf $(OUT) "$(DESTDIR)$(BINPREFIX)" 33 | mkdir -p "$(DESTDIR)$(MANPREFIX)"/man1 34 | cp -p doc/$(OUT).1 "$(DESTDIR)$(MANPREFIX)"/man1 35 | mkdir -p "$(DESTDIR)$(DOCPREFIX)" 36 | cp -pr examples "$(DESTDIR)$(DOCPREFIX)"/examples 37 | 38 | uninstall: 39 | rm -f "$(DESTDIR)$(BINPREFIX)"/$(OUT) 40 | rm -f "$(DESTDIR)$(MANPREFIX)"/man1/$(OUT).1 41 | rm -rf "$(DESTDIR)$(DOCPREFIX)" 42 | 43 | doc: 44 | a2x -v -d manpage -f manpage -a revnumber=$(VERSION) doc/$(OUT).1.asciidoc 45 | 46 | clean: 47 | rm -f $(OBJ) $(OUT) 48 | 49 | .PHONY: all debug install uninstall doc clean 50 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Description 2 | 3 | *sxhkd* is an X daemon that reacts to input events by executing commands. 4 | 5 | Its configuration file is a series of bindings that define the associations between the input events and the commands. 6 | 7 | The format of the configuration file supports a simple notation for mapping multiple shortcuts to multiple commands in parallel. 8 | 9 | ## Example Bindings 10 | 11 | XF86Audio{Prev,Next} 12 | mpc -q {prev,next} 13 | 14 | @XF86LaunchA 15 | scrot -s -e 'image_viewer $f' 16 | 17 | super + shift + equal 18 | sxiv -rt "$HOME/image" 19 | 20 | XF86LaunchB 21 | xdotool selectwindow | xsel -bi 22 | 23 | super + {h,j,k,l} 24 | bspc node -f {west,south,north,east} 25 | 26 | super + alt + {0-9} 27 | mpc -q seek {0-9}0% 28 | 29 | super + {alt,ctrl,alt + ctrl} + XF86Eject 30 | sudo systemctl {suspend,reboot,poweroff} 31 | 32 | super + {_,shift + }{h,j,k,l} 33 | bspc node -{f,s} {west,south,north,east} 34 | 35 | {_,shift + ,super + }XF86MonBrightness{Down,Up} 36 | bright {-1,-10,min,+1,+10,max} 37 | 38 | super + o ; {e,w,m} 39 | {gvim,firefox,thunderbird} 40 | 41 | super + alt + control + {h,j,k,l} ; {0-9} 42 | bspc node @{west,south,north,east} -r 0.{0-9} 43 | 44 | super + alt + p 45 | bspc config focus_follows_pointer {true,false} 46 | 47 | # Smart resize, will grow or shrink depending on location. 48 | # Will always grow for floating nodes. 49 | super + ctrl + alt + {Left,Down,Up,Right} 50 | n=10; \ 51 | { d1=left; d2=right; dx=-$n; dy=0; \ 52 | , d1=bottom; d2=top; dx=0; dy=$n; \ 53 | , d1=top; d2=bottom; dx=0; dy=-$n; \ 54 | , d1=right; d2=left; dx=$n; dy=0; \ 55 | } \ 56 | bspc node --resize $d1 $dx $dy || bspc node --resize $d2 $dx $dy 57 | 58 | ## Editor Plugins 59 | 60 | ### Vim 61 | - [vim-sxhkdrc](https://github.com/baskerville/vim-sxhkdrc). 62 | - [sxhkd-vim](https://github.com/kovetskiy/sxhkd-vim). 63 | 64 | ### VS Code 65 | - [sxhkdrc-syntax](https://github.com/mosbasik/sxhkdrc-syntax). 66 | 67 | ### Emacs 68 | - [sxhkd-mode](https://github.com/xFA25E/sxhkd-mode) 69 | 70 | ---- 71 | 72 | For further information, check the `man` pages. 73 | -------------------------------------------------------------------------------- /Sourcedeps: -------------------------------------------------------------------------------- 1 | grab.o: grab.c grab.h helpers.h parse.h sxhkd.h types.h 2 | OBJ += grab.o 3 | helpers.o: helpers.c helpers.h sxhkd.h types.h 4 | OBJ += helpers.o 5 | parse.o: parse.c helpers.h locales.h parse.h sxhkd.h types.h 6 | OBJ += parse.o 7 | sxhkd.o: sxhkd.c grab.h helpers.h parse.h sxhkd.h types.h 8 | OBJ += sxhkd.o 9 | types.o: types.c grab.h helpers.h parse.h sxhkd.h types.h 10 | OBJ += types.o 11 | -------------------------------------------------------------------------------- /VERSION: -------------------------------------------------------------------------------- 1 | 0.6.2 -------------------------------------------------------------------------------- /contrib/systemd/sxhkd.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=Simple X Hotkey Daemon 3 | Documentation=man:sxhkd(1) 4 | BindsTo=display-manager.service 5 | After=display-manager.service 6 | 7 | [Service] 8 | ExecStart=/usr/bin/sxhkd 9 | ExecReload=/usr/bin/kill -SIGUSR1 $MAINPID 10 | 11 | [Install] 12 | WantedBy=graphical.target 13 | -------------------------------------------------------------------------------- /doc/sxhkd.1: -------------------------------------------------------------------------------- 1 | '\" t 2 | .\" Title: sxhkd 3 | .\" Author: [see the "Author" section] 4 | .\" Generator: DocBook XSL Stylesheets vsnapshot 5 | .\" Date: 11/19/2022 6 | .\" Manual: Sxhkd Manual 7 | .\" Source: Sxhkd 0.6.2-3-g56d3377 8 | .\" Language: English 9 | .\" 10 | .TH "SXHKD" "1" "11/19/2022" "Sxhkd 0\&.6\&.2\-3\-g56d3377" "Sxhkd Manual" 11 | .\" ----------------------------------------------------------------- 12 | .\" * Define some portability stuff 13 | .\" ----------------------------------------------------------------- 14 | .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 15 | .\" http://bugs.debian.org/507673 16 | .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html 17 | .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 18 | .ie \n(.g .ds Aq \(aq 19 | .el .ds Aq ' 20 | .\" ----------------------------------------------------------------- 21 | .\" * set default formatting 22 | .\" ----------------------------------------------------------------- 23 | .\" disable hyphenation 24 | .nh 25 | .\" disable justification (adjust text to left margin only) 26 | .ad l 27 | .\" ----------------------------------------------------------------- 28 | .\" * MAIN CONTENT STARTS HERE * 29 | .\" ----------------------------------------------------------------- 30 | .SH "NAME" 31 | sxhkd \- Simple X hotkey daemon 32 | .SH "SYNOPSIS" 33 | .sp 34 | \fBsxhkd\fR [\fIOPTIONS\fR] [\fIEXTRA_CONFIG\fR \&...] 35 | .SH "DESCRIPTION" 36 | .sp 37 | sxhkd is a simple X hotkey daemon with a powerful and compact configuration syntax\&. 38 | .SH "OPTIONS" 39 | .PP 40 | \fB\-h\fR 41 | .RS 4 42 | Print the synopsis to standard output and exit\&. 43 | .RE 44 | .PP 45 | \fB\-v\fR 46 | .RS 4 47 | Print the version information to standard output and exit\&. 48 | .RE 49 | .PP 50 | \fB\-m\fR \fICOUNT\fR 51 | .RS 4 52 | Handle the first 53 | \fICOUNT\fR 54 | mapping notify events\&. 55 | .RE 56 | .PP 57 | \fB\-t\fR \fITIMEOUT\fR 58 | .RS 4 59 | Timeout in seconds for the recording of chord chains\&. 60 | .RE 61 | .PP 62 | \fB\-c\fR \fICONFIG_FILE\fR 63 | .RS 4 64 | Read the main configuration from the given file\&. 65 | .RE 66 | .PP 67 | \fB\-r\fR \fIREDIR_FILE\fR 68 | .RS 4 69 | Redirect the commands output to the given file\&. 70 | .RE 71 | .PP 72 | \fB\-s\fR \fISTATUS_FIFO\fR 73 | .RS 4 74 | Output status information to the given FIFO\&. 75 | .RE 76 | .PP 77 | \fB\-a\fR \fIABORT_KEYSYM\fR 78 | .RS 4 79 | Name of the keysym used for aborting chord chains\&. 80 | .RE 81 | .SH "BEHAVIOR" 82 | .sp 83 | \fBsxhkd\fR is a daemon that listens to keyboard events and execute commands\&. 84 | .sp 85 | It reads its configuration file from \fB$XDG_CONFIG_HOME/sxhkd/sxhkdrc\fR by default, or from the given file if the \fB\-c\fR option is used\&. 86 | .sp 87 | Additional configuration files can be passed as arguments\&. 88 | .sp 89 | If \fBsxhkd\fR receives a \fISIGUSR1\fR (resp\&. \fISIGUSR2\fR) signal, it will reload its configuration file (resp\&. toggle the grabbing state of all its bindings)\&. 90 | .sp 91 | If \fBsxhkd\fR recieves a \fISIGALRM\fR signal, it will break the current chain if there is one in progress\&. 92 | .sp 93 | The commands are executed via \fBSHELL\fR \fI\-c\fR \fBCOMMAND\fR (hence you can use environment variables)\&. 94 | .sp 95 | \fBSHELL\fR will be the content of the first defined environment variable in the following list: \fBSXHKD_SHELL\fR, \fBSHELL\fR\&. 96 | .sp 97 | \fBSXHKD_PID\fR will be automatically set to the pid of \fBsxhkd\fR in processes spawned by \fBsxhkd\fR, which may be used by the child process to send easily signals such as \fISIGALRM\fR to the correct instance of \fBsxhkd\fR\&. 98 | .sp 99 | If you have a non\-QWERTY keyboard or a non\-standard layout configuration, you should provide a \fICOUNT\fR of \fI1\fR to the \fB\-m\fR option or \fI\-1\fR (interpreted as infinity) if you constantly switch from one layout to the other (\fBsxhkd\fR ignores all mapping notify events by default because the majority of those events are pointless)\&. 100 | .SH "CONFIGURATION" 101 | .sp 102 | Each line of the configuration file is interpreted as so: 103 | .sp 104 | .RS 4 105 | .ie n \{\ 106 | \h'-04'\(bu\h'+03'\c 107 | .\} 108 | .el \{\ 109 | .sp -1 110 | .IP \(bu 2.3 111 | .\} 112 | If it is empty or starts with 113 | #, it is ignored\&. 114 | .RE 115 | .sp 116 | .RS 4 117 | .ie n \{\ 118 | \h'-04'\(bu\h'+03'\c 119 | .\} 120 | .el \{\ 121 | .sp -1 122 | .IP \(bu 2.3 123 | .\} 124 | If it starts with a space, it is read as a command\&. 125 | .RE 126 | .sp 127 | .RS 4 128 | .ie n \{\ 129 | \h'-04'\(bu\h'+03'\c 130 | .\} 131 | .el \{\ 132 | .sp -1 133 | .IP \(bu 2.3 134 | .\} 135 | Otherwise, it is read as a hotkey\&. 136 | .RE 137 | .sp 138 | General syntax: 139 | .sp 140 | .if n \{\ 141 | .RS 4 142 | .\} 143 | .nf 144 | HOTKEY 145 | [;]COMMAND 146 | 147 | HOTKEY := CHORD_1 ; CHORD_2 ; \&... ; CHORD_n 148 | CHORD_i := [MODIFIERS_i +] [~][@]KEYSYM_i 149 | MODIFIERS_i := MODIFIER_i1 + MODIFIER_i2 + \&... + MODIFIER_ik 150 | .fi 151 | .if n \{\ 152 | .RE 153 | .\} 154 | .sp 155 | The valid modifier names are: \fIsuper\fR, \fIhyper\fR, \fImeta\fR, \fIalt\fR, \fIcontrol\fR, \fIctrl\fR, \fIshift\fR, \fImode_switch\fR, \fIlock\fR, \fImod1\fR, \fImod2\fR, \fImod3\fR, \fImod4\fR, \fImod5\fR and \fIany\fR\&. 156 | .sp 157 | The keysym names are given by the output of \fBxev \-event keyboard\fR\&. 158 | .sp 159 | Hotkeys and commands can be spread across multiple lines by ending each partial line with a backslash character\&. 160 | .sp 161 | When multiple chords are separated by semicolons, the hotkey is a chord chain: the command will only be executed after receiving each chord of the chain in consecutive order\&. 162 | .sp 163 | The colon character can be used instead of the semicolon to indicate that the chord chain shall not be aborted when the chain tail is reached\&. 164 | .sp 165 | If a command starts with a semicolon, it will be executed synchronously, otherwise asynchronously\&. 166 | .sp 167 | The \fIEscape\fR key can be used to abort a chord chain\&. 168 | .sp 169 | If \fB@\fR is added at the beginning of the keysym, the command will be run on key release events, otherwise on key press events\&. 170 | .sp 171 | If \fB~\fR is added at the beginning of the keysym, the captured event will be replayed for the other clients\&. 172 | .sp 173 | Pointer hotkeys can be defined by using one of the following special keysym names: \fIbutton1\fR, \fIbutton2\fR, \fIbutton3\fR, \&..., \fIbutton24\fR\&. 174 | .sp 175 | The hotkey and the command may contain sequences of the form \fI{STRING_1,\&...,STRING_N}\fR\&. Braces can be escaped with \fB\e\fR\&. 176 | .sp 177 | In addition, the sequences can contain ranges of the form \fIA\fR\-\fIZ\fR where \fIA\fR and \fIZ\fR are alphanumeric characters\&. 178 | .sp 179 | The underscore character represents an empty sequence element\&. 180 | .SH "AUTHOR" 181 | .sp 182 | Bastien Dejean 183 | .SH "MAILING LIST" 184 | .sp 185 | sxhkd at librelist\&.com 186 | -------------------------------------------------------------------------------- /doc/sxhkd.1.asciidoc: -------------------------------------------------------------------------------- 1 | :man source: Sxhkd 2 | :man version: {revnumber} 3 | :man manual: Sxhkd Manual 4 | 5 | sxhkd(1) 6 | ======== 7 | 8 | Name 9 | ---- 10 | 11 | sxhkd - Simple X hotkey daemon 12 | 13 | Synopsis 14 | -------- 15 | 16 | *sxhkd* [_OPTIONS_] [_EXTRA_CONFIG_ …] 17 | 18 | Description 19 | ----------- 20 | 21 | sxhkd is a simple X hotkey daemon with a powerful and compact configuration syntax. 22 | 23 | Options 24 | ------- 25 | 26 | 27 | *-h*:: 28 | Print the synopsis to standard output and exit. 29 | 30 | *-v*:: 31 | Print the version information to standard output and exit. 32 | 33 | *-m* _COUNT_:: 34 | Handle the first _COUNT_ mapping notify events. 35 | 36 | *-t* _TIMEOUT_:: 37 | Timeout in seconds for the recording of chord chains. 38 | 39 | *-c* _CONFIG_FILE_:: 40 | Read the main configuration from the given file. 41 | 42 | *-r* _REDIR_FILE_:: 43 | Redirect the commands output to the given file. 44 | 45 | *-s* _STATUS_FIFO_:: 46 | Output status information to the given FIFO. 47 | 48 | *-a* _ABORT_KEYSYM_:: 49 | Name of the keysym used for aborting chord chains. 50 | 51 | 52 | Behavior 53 | -------- 54 | 55 | *sxhkd* is a daemon that listens to keyboard events and execute commands. 56 | 57 | It reads its configuration file from *$XDG_CONFIG_HOME/sxhkd/sxhkdrc* by default, or from the given file if the *-c* option is used. 58 | 59 | Additional configuration files can be passed as arguments. 60 | 61 | If *sxhkd* receives a _SIGUSR1_ (resp. _SIGUSR2_) signal, it will reload its configuration file (resp. toggle the grabbing state of all its bindings). 62 | 63 | If *sxhkd* recieves a _SIGALRM_ signal, it will break the current chain if there is one in progress. 64 | 65 | The commands are executed via *SHELL* _-c_ *COMMAND* (hence you can use environment variables). 66 | 67 | *SHELL* will be the content of the first defined environment variable in the following list: *SXHKD_SHELL*, *SHELL*. 68 | 69 | *SXHKD_PID* will be automatically set to the pid of *sxhkd* in processes spawned by *sxhkd*, which may be used by the child process to send easily signals such as _SIGALRM_ to the correct instance of *sxhkd*. 70 | 71 | If you have a non-QWERTY keyboard or a non-standard layout configuration, you should provide a _COUNT_ of _1_ to the *-m* option or _-1_ (interpreted as infinity) if you constantly switch from one layout to the other (*sxhkd* ignores all mapping notify events by default because the majority of those events are pointless). 72 | 73 | 74 | Configuration 75 | ------------- 76 | 77 | Each line of the configuration file is interpreted as so: 78 | 79 | * If it is empty or starts with `#`, it is ignored. 80 | * If it starts with a space, it is read as a command. 81 | * Otherwise, it is read as a hotkey. 82 | 83 | General syntax: 84 | 85 | ---- 86 | HOTKEY 87 | [;]COMMAND 88 | 89 | HOTKEY := CHORD_1 ; CHORD_2 ; … ; CHORD_n 90 | CHORD_i := [MODIFIERS_i +] [~][@]KEYSYM_i 91 | MODIFIERS_i := MODIFIER_i1 + MODIFIER_i2 + … + MODIFIER_ik 92 | ---- 93 | 94 | The valid modifier names are: _super_, _hyper_, _meta_, _alt_, _control_, _ctrl_, _shift_, _mode_switch_, _lock_, _mod1_, _mod2_, _mod3_, _mod4_, _mod5_ and _any_. 95 | 96 | The keysym names are given by the output of *xev -event keyboard*. 97 | 98 | Hotkeys and commands can be spread across multiple lines by ending each partial line with a backslash character. 99 | 100 | When multiple chords are separated by semicolons, the hotkey is a chord chain: the command will only be executed after receiving each chord of the chain in consecutive order. 101 | 102 | The colon character can be used instead of the semicolon to indicate that the chord chain shall not be aborted when the chain tail is reached. 103 | 104 | If a command starts with a semicolon, it will be executed synchronously, otherwise asynchronously. 105 | 106 | The _Escape_ key can be used to abort a chord chain. 107 | 108 | If *@* is added at the beginning of the keysym, the command will be run on key release events, otherwise on key press events. 109 | 110 | If *~* is added at the beginning of the keysym, the captured event will be replayed for the other clients. 111 | 112 | Pointer hotkeys can be defined by using one of the following special keysym names: _button1_, _button2_, _button3_, …, _button24_. 113 | 114 | The hotkey and the command may contain sequences of the form '{STRING_1,…,STRING_N}'. Braces can be escaped with *\*. 115 | 116 | In addition, the sequences can contain ranges of the form _A_-_Z_ where _A_ and _Z_ are alphanumeric characters. 117 | 118 | The underscore character represents an empty sequence element. 119 | 120 | Author 121 | ------ 122 | 123 | Bastien Dejean 124 | 125 | Mailing List 126 | ------------ 127 | 128 | sxhkd at librelist.com 129 | 130 | //// 131 | vim: set ft=asciidoc: 132 | //// 133 | -------------------------------------------------------------------------------- /examples/background_shell/profile: -------------------------------------------------------------------------------- 1 | export SXHKD_SHELL=shell 2 | -------------------------------------------------------------------------------- /examples/background_shell/shell: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | printf "(%s)&\n" "$2" | tmux load-buffer - 4 | tmux paste-buffer -t sxhkd 5 | -------------------------------------------------------------------------------- /examples/background_shell/sxhkdrc: -------------------------------------------------------------------------------- 1 | # Reload functions 2 | super + Escape 3 | "$XDG_CONFIG_HOME"/sxhkd/functions 4 | -------------------------------------------------------------------------------- /examples/background_shell/xinitrc: -------------------------------------------------------------------------------- 1 | if ! tmux has-session -t sxhkd 2> /dev/null ; then 2 | tmux new-session -s sxhkd -d 3 | printf '%s\n' '. "$XDG_CONFIG_HOME"/sxhkd/functions' | tmux load-buffer - 4 | tmux paste-buffer -t sxhkd 5 | fi 6 | -------------------------------------------------------------------------------- /examples/notification/autostart: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | sxhkd_notify "$SXHKD_FIFO" & 4 | -------------------------------------------------------------------------------- /examples/notification/pam_environment: -------------------------------------------------------------------------------- 1 | SXHKD_FIFO=/tmp/sxhkd-fifo 2 | -------------------------------------------------------------------------------- /examples/notification/sxhkd_notify: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | [ $# -ne 1 ] && exit 1 4 | 5 | status_fifo=$1 6 | 7 | { while read -r line ; do 8 | msg=${line#?} 9 | case $line in 10 | H*) 11 | duration=2 12 | ;; 13 | C*) 14 | duration=4 15 | ;; 16 | T*) 17 | duration=1 18 | ;; 19 | esac 20 | notify-send -t $duration "$msg" 21 | done } < "$status_fifo" 22 | -------------------------------------------------------------------------------- /examples/notification/xinitrc: -------------------------------------------------------------------------------- 1 | [ -e "$SXHKD_FIFO" ] && rm "$SXHKD_FIFO" 2 | mkfifo "$SXHKD_FIFO" 3 | sxhkd -s "$SXHKD_FIFO" & 4 | -------------------------------------------------------------------------------- /src/grab.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include "parse.h" 28 | #include "grab.h" 29 | 30 | void grab(void) 31 | { 32 | PUTS("grab"); 33 | for (hotkey_t *hk = hotkeys_head; hk != NULL; hk = hk->next) 34 | grab_chord(hk->chain->head); 35 | xcb_flush(dpy); 36 | grabbed = true; 37 | } 38 | 39 | void grab_chord(chord_t *chord) 40 | { 41 | for (chord_t *c = chord; c != NULL; c = c->more) { 42 | if (c->button == XCB_NONE) { 43 | xcb_keycode_t *keycodes = keycodes_from_keysym(c->keysym); 44 | if (keycodes != NULL) 45 | for (xcb_keycode_t *kc = keycodes; *kc != XCB_NO_SYMBOL; kc++) 46 | if (c->keysym == xcb_key_symbols_get_keysym(symbols, *kc, 0)) 47 | grab_key_button(*kc, c->button, c->modfield); 48 | free(keycodes); 49 | } else { 50 | grab_key_button(XCB_NONE, c->button, c->modfield); 51 | } 52 | } 53 | } 54 | 55 | void grab_key_button(xcb_keycode_t keycode, xcb_button_t button, uint16_t modfield) 56 | { 57 | grab_key_button_checked(keycode, button, modfield); 58 | if (modfield == XCB_MOD_MASK_ANY) 59 | return; 60 | if (num_lock != 0) 61 | grab_key_button_checked(keycode, button, modfield | num_lock); 62 | if (caps_lock != 0) 63 | grab_key_button_checked(keycode, button, modfield | caps_lock); 64 | if (scroll_lock != 0) 65 | grab_key_button_checked(keycode, button, modfield | scroll_lock); 66 | if (num_lock != 0 && caps_lock != 0) 67 | grab_key_button_checked(keycode, button, modfield | num_lock | caps_lock); 68 | if (caps_lock != 0 && scroll_lock != 0) 69 | grab_key_button_checked(keycode, button, modfield | caps_lock | scroll_lock); 70 | if (num_lock != 0 && scroll_lock != 0) 71 | grab_key_button_checked(keycode, button, modfield | num_lock | scroll_lock); 72 | if (num_lock != 0 && caps_lock != 0 && scroll_lock != 0) 73 | grab_key_button_checked(keycode, button, modfield | num_lock | caps_lock | scroll_lock); 74 | } 75 | 76 | void grab_key_button_checked(xcb_keycode_t keycode, xcb_button_t button, uint16_t modfield) 77 | { 78 | xcb_generic_error_t *err; 79 | if (button == XCB_NONE) 80 | err = xcb_request_check(dpy, xcb_grab_key_checked(dpy, true, root, modfield, keycode, XCB_GRAB_MODE_ASYNC, XCB_GRAB_MODE_SYNC)); 81 | else 82 | err = xcb_request_check(dpy, xcb_grab_button_checked(dpy, true, root, XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE, XCB_GRAB_MODE_SYNC, XCB_GRAB_MODE_ASYNC, XCB_NONE, XCB_NONE, button, modfield)); 83 | unsigned int value = (button == XCB_NONE ? keycode : button); 84 | char *type = (button == XCB_NONE ? "key" : "button"); 85 | if (err != NULL) { 86 | warn("Could not grab %s %u with modfield %u: ", type, value, modfield); 87 | if (err->error_code == XCB_ACCESS) 88 | warn("the combination is already grabbed.\n"); 89 | else 90 | warn("error %u encountered.\n", err->error_code); 91 | free(err); 92 | } else { 93 | PRINTF("grab %s %u %u\n", type, value, modfield); 94 | } 95 | } 96 | 97 | void ungrab(void) 98 | { 99 | PUTS("ungrab"); 100 | xcb_ungrab_key(dpy, XCB_GRAB_ANY, root, XCB_BUTTON_MASK_ANY); 101 | xcb_ungrab_button(dpy, XCB_BUTTON_INDEX_ANY, root, XCB_MOD_MASK_ANY); 102 | xcb_flush(dpy); 103 | grabbed = false; 104 | } 105 | -------------------------------------------------------------------------------- /src/grab.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #ifndef SXHKD_GRAB_H 26 | #define SXHKD_GRAB_H 27 | 28 | #include "sxhkd.h" 29 | 30 | void grab(void); 31 | void grab_chord(chord_t *chord); 32 | void grab_key_button(xcb_keycode_t keycode, xcb_button_t button, uint16_t modfield); 33 | void grab_key_button_checked(xcb_keycode_t keycode, xcb_button_t button, uint16_t modfield); 34 | void ungrab(void); 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/helpers.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include "sxhkd.h" 34 | 35 | void warn(char *fmt, ...) 36 | { 37 | va_list ap; 38 | va_start(ap, fmt); 39 | vfprintf(stderr, fmt, ap); 40 | va_end(ap); 41 | } 42 | 43 | __attribute__((noreturn)) 44 | void err(char *fmt, ...) 45 | { 46 | va_list ap; 47 | va_start(ap, fmt); 48 | vfprintf(stderr, fmt, ap); 49 | va_end(ap); 50 | exit(EXIT_FAILURE); 51 | } 52 | 53 | void run(char *command, bool sync) 54 | { 55 | char *cmd[] = {shell, "-c", command, NULL}; 56 | spawn(cmd, sync); 57 | } 58 | 59 | void spawn(char *cmd[], bool sync) 60 | { 61 | if (fork() == 0) { 62 | if (dpy != NULL) 63 | close(xcb_get_file_descriptor(dpy)); 64 | if (sync) { 65 | execute(cmd); 66 | } else { 67 | if (fork() == 0) { 68 | execute(cmd); 69 | } 70 | exit(EXIT_SUCCESS); 71 | } 72 | } 73 | wait(NULL); 74 | } 75 | 76 | void execute(char *cmd[]) 77 | { 78 | setsid(); 79 | if (redir_fd != -1) { 80 | dup2(redir_fd, STDOUT_FILENO); 81 | dup2(redir_fd, STDERR_FILENO); 82 | } 83 | execvp(cmd[0], cmd); 84 | err("Spawning failed.\n"); 85 | } 86 | 87 | char *lgraph(char *s) 88 | { 89 | size_t len = strlen(s); 90 | unsigned int i = 0; 91 | while (i < len && !isgraph(s[i])) 92 | i++; 93 | if (i < len) 94 | return (s + i); 95 | else 96 | return NULL; 97 | } 98 | 99 | char *rgraph(char *s) 100 | { 101 | int i = strlen(s) - 1; 102 | while (i >= 0 && !isgraph(s[i])) 103 | i--; 104 | if (i >= 0) 105 | return (s + i); 106 | else 107 | return NULL; 108 | } 109 | -------------------------------------------------------------------------------- /src/helpers.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #ifndef SXHKD_HELPERS_H 26 | #define SXHKD_HELPERS_H 27 | 28 | #define LENGTH(x) (sizeof(x) / sizeof(*x)) 29 | #define MAXLEN 256 30 | 31 | #ifdef DEBUG 32 | # define PUTS(x) puts(x) 33 | # define PRINTF(x,...) printf(x, __VA_ARGS__) 34 | #else 35 | # define PUTS(x) ((void)0) 36 | # define PRINTF(x,...) ((void)0) 37 | #endif 38 | 39 | void warn(char *fmt, ...); 40 | __attribute__((noreturn)) 41 | void err(char *fmt, ...); 42 | void execute(char *cmd[]); 43 | void spawn(char *cmd[], bool sync); 44 | void run(char *command, bool sync); 45 | char *lgraph(char *s); 46 | char *rgraph(char *s); 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /src/locales.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #ifndef SXHKD_LOCALES_H 26 | #define SXHKD_LOCALES_H 27 | 28 | #define XK_MISCELLANY 29 | #define XK_XKB_KEYS 30 | #define XK_XFREE86 31 | #define XK_LATIN1 32 | #define XK_LATIN2 33 | #define XK_LATIN3 34 | #define XK_LATIN4 35 | #define XK_LATIN8 36 | #define XK_LATIN9 37 | #define XK_CAUCASUS 38 | #define XK_GREEK 39 | #define XK_KATAKANA 40 | #define XK_ARABIC 41 | #define XK_CYRILLIC 42 | #define XK_HEBREW 43 | #define XK_THAI 44 | #define XK_KOREAN 45 | #define XK_ARMENIAN 46 | #define XK_GEORGIAN 47 | #define XK_VIETNAMESE 48 | #define XK_CURRENCY 49 | #define XK_MATHEMATICAL 50 | #define XK_BRAILLE 51 | #define XK_SINHALA 52 | 53 | #endif 54 | -------------------------------------------------------------------------------- /src/parse.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include "locales.h" 33 | #include "parse.h" 34 | 35 | xcb_keysym_t Alt_L, Alt_R, Super_L, Super_R, Hyper_L, Hyper_R, 36 | Meta_L, Meta_R, Mode_switch, Num_Lock, Scroll_Lock; 37 | 38 | keysym_dict_t nks_dict[] = {/*{{{*/ 39 | {"VoidSymbol" , 0xffffff} , 40 | #ifdef XK_MISCELLANY 41 | {"BackSpace" , 0xff08} , 42 | {"Tab" , 0xff09} , 43 | {"Linefeed" , 0xff0a} , 44 | {"Clear" , 0xff0b} , 45 | {"Return" , 0xff0d} , 46 | {"Pause" , 0xff13} , 47 | {"Scroll_Lock" , 0xff14} , 48 | {"Sys_Req" , 0xff15} , 49 | {"Escape" , 0xff1b} , 50 | {"Delete" , 0xffff} , 51 | {"Multi_key" , 0xff20} , 52 | {"Codeinput" , 0xff37} , 53 | {"SingleCandidate" , 0xff3c} , 54 | {"MultipleCandidate" , 0xff3d} , 55 | {"PreviousCandidate" , 0xff3e} , 56 | {"Kanji" , 0xff21} , 57 | {"Muhenkan" , 0xff22} , 58 | {"Henkan_Mode" , 0xff23} , 59 | {"Henkan" , 0xff23} , 60 | {"Romaji" , 0xff24} , 61 | {"Hiragana" , 0xff25} , 62 | {"Katakana" , 0xff26} , 63 | {"Hiragana_Katakana" , 0xff27} , 64 | {"Zenkaku" , 0xff28} , 65 | {"Hankaku" , 0xff29} , 66 | {"Zenkaku_Hankaku" , 0xff2a} , 67 | {"Touroku" , 0xff2b} , 68 | {"Massyo" , 0xff2c} , 69 | {"Kana_Lock" , 0xff2d} , 70 | {"Kana_Shift" , 0xff2e} , 71 | {"Eisu_Shift" , 0xff2f} , 72 | {"Eisu_toggle" , 0xff30} , 73 | {"Kanji_Bangou" , 0xff37} , 74 | {"Zen_Koho" , 0xff3d} , 75 | {"Mae_Koho" , 0xff3e} , 76 | {"Home" , 0xff50} , 77 | {"Left" , 0xff51} , 78 | {"Up" , 0xff52} , 79 | {"Right" , 0xff53} , 80 | {"Down" , 0xff54} , 81 | {"Prior" , 0xff55} , 82 | {"Page_Up" , 0xff55} , 83 | {"Next" , 0xff56} , 84 | {"Page_Down" , 0xff56} , 85 | {"End" , 0xff57} , 86 | {"Begin" , 0xff58} , 87 | {"Select" , 0xff60} , 88 | {"Print" , 0xff61} , 89 | {"Execute" , 0xff62} , 90 | {"Insert" , 0xff63} , 91 | {"Undo" , 0xff65} , 92 | {"Redo" , 0xff66} , 93 | {"Menu" , 0xff67} , 94 | {"Find" , 0xff68} , 95 | {"Cancel" , 0xff69} , 96 | {"Help" , 0xff6a} , 97 | {"Break" , 0xff6b} , 98 | {"Mode_switch" , 0xff7e} , 99 | {"script_switch" , 0xff7e} , 100 | {"Num_Lock" , 0xff7f} , 101 | {"KP_Space" , 0xff80} , 102 | {"KP_Tab" , 0xff89} , 103 | {"KP_Enter" , 0xff8d} , 104 | {"KP_F1" , 0xff91} , 105 | {"KP_F2" , 0xff92} , 106 | {"KP_F3" , 0xff93} , 107 | {"KP_F4" , 0xff94} , 108 | {"KP_Home" , 0xff95} , 109 | {"KP_Left" , 0xff96} , 110 | {"KP_Up" , 0xff97} , 111 | {"KP_Right" , 0xff98} , 112 | {"KP_Down" , 0xff99} , 113 | {"KP_Prior" , 0xff9a} , 114 | {"KP_Page_Up" , 0xff9a} , 115 | {"KP_Next" , 0xff9b} , 116 | {"KP_Page_Down" , 0xff9b} , 117 | {"KP_End" , 0xff9c} , 118 | {"KP_Begin" , 0xff9d} , 119 | {"KP_Insert" , 0xff9e} , 120 | {"KP_Delete" , 0xff9f} , 121 | {"KP_Equal" , 0xffbd} , 122 | {"KP_Multiply" , 0xffaa} , 123 | {"KP_Add" , 0xffab} , 124 | {"KP_Separator" , 0xffac} , 125 | {"KP_Subtract" , 0xffad} , 126 | {"KP_Decimal" , 0xffae} , 127 | {"KP_Divide" , 0xffaf} , 128 | {"KP_0" , 0xffb0} , 129 | {"KP_1" , 0xffb1} , 130 | {"KP_2" , 0xffb2} , 131 | {"KP_3" , 0xffb3} , 132 | {"KP_4" , 0xffb4} , 133 | {"KP_5" , 0xffb5} , 134 | {"KP_6" , 0xffb6} , 135 | {"KP_7" , 0xffb7} , 136 | {"KP_8" , 0xffb8} , 137 | {"KP_9" , 0xffb9} , 138 | {"F1" , 0xffbe} , 139 | {"F2" , 0xffbf} , 140 | {"F3" , 0xffc0} , 141 | {"F4" , 0xffc1} , 142 | {"F5" , 0xffc2} , 143 | {"F6" , 0xffc3} , 144 | {"F7" , 0xffc4} , 145 | {"F8" , 0xffc5} , 146 | {"F9" , 0xffc6} , 147 | {"F10" , 0xffc7} , 148 | {"F11" , 0xffc8} , 149 | {"L1" , 0xffc8} , 150 | {"F12" , 0xffc9} , 151 | {"L2" , 0xffc9} , 152 | {"F13" , 0xffca} , 153 | {"L3" , 0xffca} , 154 | {"F14" , 0xffcb} , 155 | {"L4" , 0xffcb} , 156 | {"F15" , 0xffcc} , 157 | {"L5" , 0xffcc} , 158 | {"F16" , 0xffcd} , 159 | {"L6" , 0xffcd} , 160 | {"F17" , 0xffce} , 161 | {"L7" , 0xffce} , 162 | {"F18" , 0xffcf} , 163 | {"L8" , 0xffcf} , 164 | {"F19" , 0xffd0} , 165 | {"L9" , 0xffd0} , 166 | {"F20" , 0xffd1} , 167 | {"L10" , 0xffd1} , 168 | {"F21" , 0xffd2} , 169 | {"R1" , 0xffd2} , 170 | {"F22" , 0xffd3} , 171 | {"R2" , 0xffd3} , 172 | {"F23" , 0xffd4} , 173 | {"R3" , 0xffd4} , 174 | {"F24" , 0xffd5} , 175 | {"R4" , 0xffd5} , 176 | {"F25" , 0xffd6} , 177 | {"R5" , 0xffd6} , 178 | {"F26" , 0xffd7} , 179 | {"R6" , 0xffd7} , 180 | {"F27" , 0xffd8} , 181 | {"R7" , 0xffd8} , 182 | {"F28" , 0xffd9} , 183 | {"R8" , 0xffd9} , 184 | {"F29" , 0xffda} , 185 | {"R9" , 0xffda} , 186 | {"F30" , 0xffdb} , 187 | {"R10" , 0xffdb} , 188 | {"F31" , 0xffdc} , 189 | {"R11" , 0xffdc} , 190 | {"F32" , 0xffdd} , 191 | {"R12" , 0xffdd} , 192 | {"F33" , 0xffde} , 193 | {"R13" , 0xffde} , 194 | {"F34" , 0xffdf} , 195 | {"R14" , 0xffdf} , 196 | {"F35" , 0xffe0} , 197 | {"R15" , 0xffe0} , 198 | {"Shift_L" , 0xffe1} , 199 | {"Shift_R" , 0xffe2} , 200 | {"Control_L" , 0xffe3} , 201 | {"Control_R" , 0xffe4} , 202 | {"Caps_Lock" , 0xffe5} , 203 | {"Shift_Lock" , 0xffe6} , 204 | {"Meta_L" , 0xffe7} , 205 | {"Meta_R" , 0xffe8} , 206 | {"Alt_L" , 0xffe9} , 207 | {"Alt_R" , 0xffea} , 208 | {"Super_L" , 0xffeb} , 209 | {"Super_R" , 0xffec} , 210 | {"Hyper_L" , 0xffed} , 211 | {"Hyper_R" , 0xffee} , 212 | #endif 213 | #ifdef XK_XKB_KEYS 214 | {"ISO_Lock" , 0xfe01} , 215 | {"ISO_Level2_Latch" , 0xfe02} , 216 | {"ISO_Level3_Shift" , 0xfe03} , 217 | {"ISO_Level3_Latch" , 0xfe04} , 218 | {"ISO_Level3_Lock" , 0xfe05} , 219 | {"ISO_Level5_Shift" , 0xfe11} , 220 | {"ISO_Level5_Latch" , 0xfe12} , 221 | {"ISO_Level5_Lock" , 0xfe13} , 222 | {"ISO_Group_Shift" , 0xff7e} , 223 | {"ISO_Group_Latch" , 0xfe06} , 224 | {"ISO_Group_Lock" , 0xfe07} , 225 | {"ISO_Next_Group" , 0xfe08} , 226 | {"ISO_Next_Group_Lock" , 0xfe09} , 227 | {"ISO_Prev_Group" , 0xfe0a} , 228 | {"ISO_Prev_Group_Lock" , 0xfe0b} , 229 | {"ISO_First_Group" , 0xfe0c} , 230 | {"ISO_First_Group_Lock" , 0xfe0d} , 231 | {"ISO_Last_Group" , 0xfe0e} , 232 | {"ISO_Last_Group_Lock" , 0xfe0f} , 233 | {"ISO_Left_Tab" , 0xfe20} , 234 | {"ISO_Move_Line_Up" , 0xfe21} , 235 | {"ISO_Move_Line_Down" , 0xfe22} , 236 | {"ISO_Partial_Line_Up" , 0xfe23} , 237 | {"ISO_Partial_Line_Down" , 0xfe24} , 238 | {"ISO_Partial_Space_Left" , 0xfe25} , 239 | {"ISO_Partial_Space_Right" , 0xfe26} , 240 | {"ISO_Set_Margin_Left" , 0xfe27} , 241 | {"ISO_Set_Margin_Right" , 0xfe28} , 242 | {"ISO_Release_Margin_Left" , 0xfe29} , 243 | {"ISO_Release_Margin_Right" , 0xfe2a} , 244 | {"ISO_Release_Both_Margins" , 0xfe2b} , 245 | {"ISO_Fast_Cursor_Left" , 0xfe2c} , 246 | {"ISO_Fast_Cursor_Right" , 0xfe2d} , 247 | {"ISO_Fast_Cursor_Up" , 0xfe2e} , 248 | {"ISO_Fast_Cursor_Down" , 0xfe2f} , 249 | {"ISO_Continuous_Underline" , 0xfe30} , 250 | {"ISO_Discontinuous_Underline" , 0xfe31} , 251 | {"ISO_Emphasize" , 0xfe32} , 252 | {"ISO_Center_Object" , 0xfe33} , 253 | {"ISO_Enter" , 0xfe34} , 254 | {"dead_grave" , 0xfe50} , 255 | {"dead_acute" , 0xfe51} , 256 | {"dead_circumflex" , 0xfe52} , 257 | {"dead_tilde" , 0xfe53} , 258 | {"dead_perispomeni" , 0xfe53} , 259 | {"dead_macron" , 0xfe54} , 260 | {"dead_breve" , 0xfe55} , 261 | {"dead_abovedot" , 0xfe56} , 262 | {"dead_diaeresis" , 0xfe57} , 263 | {"dead_abovering" , 0xfe58} , 264 | {"dead_doubleacute" , 0xfe59} , 265 | {"dead_caron" , 0xfe5a} , 266 | {"dead_cedilla" , 0xfe5b} , 267 | {"dead_ogonek" , 0xfe5c} , 268 | {"dead_iota" , 0xfe5d} , 269 | {"dead_voiced_sound" , 0xfe5e} , 270 | {"dead_semivoiced_sound" , 0xfe5f} , 271 | {"dead_belowdot" , 0xfe60} , 272 | {"dead_hook" , 0xfe61} , 273 | {"dead_horn" , 0xfe62} , 274 | {"dead_stroke" , 0xfe63} , 275 | {"dead_abovecomma" , 0xfe64} , 276 | {"dead_psili" , 0xfe64} , 277 | {"dead_abovereversedcomma" , 0xfe65} , 278 | {"dead_dasia" , 0xfe65} , 279 | {"dead_doublegrave" , 0xfe66} , 280 | {"dead_belowring" , 0xfe67} , 281 | {"dead_belowmacron" , 0xfe68} , 282 | {"dead_belowcircumflex" , 0xfe69} , 283 | {"dead_belowtilde" , 0xfe6a} , 284 | {"dead_belowbreve" , 0xfe6b} , 285 | {"dead_belowdiaeresis" , 0xfe6c} , 286 | {"dead_invertedbreve" , 0xfe6d} , 287 | {"dead_belowcomma" , 0xfe6e} , 288 | {"dead_currency" , 0xfe6f} , 289 | {"dead_a" , 0xfe80} , 290 | {"dead_A" , 0xfe81} , 291 | {"dead_e" , 0xfe82} , 292 | {"dead_E" , 0xfe83} , 293 | {"dead_i" , 0xfe84} , 294 | {"dead_I" , 0xfe85} , 295 | {"dead_o" , 0xfe86} , 296 | {"dead_O" , 0xfe87} , 297 | {"dead_u" , 0xfe88} , 298 | {"dead_U" , 0xfe89} , 299 | {"dead_small_schwa" , 0xfe8a} , 300 | {"dead_capital_schwa" , 0xfe8b} , 301 | {"dead_greek" , 0xfe8c} , 302 | {"First_Virtual_Screen" , 0xfed0} , 303 | {"Prev_Virtual_Screen" , 0xfed1} , 304 | {"Next_Virtual_Screen" , 0xfed2} , 305 | {"Last_Virtual_Screen" , 0xfed4} , 306 | {"Terminate_Server" , 0xfed5} , 307 | {"AccessX_Enable" , 0xfe70} , 308 | {"AccessX_Feedback_Enable" , 0xfe71} , 309 | {"RepeatKeys_Enable" , 0xfe72} , 310 | {"SlowKeys_Enable" , 0xfe73} , 311 | {"BounceKeys_Enable" , 0xfe74} , 312 | {"StickyKeys_Enable" , 0xfe75} , 313 | {"MouseKeys_Enable" , 0xfe76} , 314 | {"MouseKeys_Accel_Enable" , 0xfe77} , 315 | {"Overlay1_Enable" , 0xfe78} , 316 | {"Overlay2_Enable" , 0xfe79} , 317 | {"AudibleBell_Enable" , 0xfe7a} , 318 | {"Pointer_Left" , 0xfee0} , 319 | {"Pointer_Right" , 0xfee1} , 320 | {"Pointer_Up" , 0xfee2} , 321 | {"Pointer_Down" , 0xfee3} , 322 | {"Pointer_UpLeft" , 0xfee4} , 323 | {"Pointer_UpRight" , 0xfee5} , 324 | {"Pointer_DownLeft" , 0xfee6} , 325 | {"Pointer_DownRight" , 0xfee7} , 326 | {"Pointer_Button_Dflt" , 0xfee8} , 327 | {"Pointer_Button1" , 0xfee9} , 328 | {"Pointer_Button2" , 0xfeea} , 329 | {"Pointer_Button3" , 0xfeeb} , 330 | {"Pointer_Button4" , 0xfeec} , 331 | {"Pointer_Button5" , 0xfeed} , 332 | {"Pointer_DblClick_Dflt" , 0xfeee} , 333 | {"Pointer_DblClick1" , 0xfeef} , 334 | {"Pointer_DblClick2" , 0xfef0} , 335 | {"Pointer_DblClick3" , 0xfef1} , 336 | {"Pointer_DblClick4" , 0xfef2} , 337 | {"Pointer_DblClick5" , 0xfef3} , 338 | {"Pointer_Drag_Dflt" , 0xfef4} , 339 | {"Pointer_Drag1" , 0xfef5} , 340 | {"Pointer_Drag2" , 0xfef6} , 341 | {"Pointer_Drag3" , 0xfef7} , 342 | {"Pointer_Drag4" , 0xfef8} , 343 | {"Pointer_Drag5" , 0xfefd} , 344 | {"Pointer_EnableKeys" , 0xfef9} , 345 | {"Pointer_Accelerate" , 0xfefa} , 346 | {"Pointer_DfltBtnNext" , 0xfefb} , 347 | {"Pointer_DfltBtnPrev" , 0xfefc} , 348 | {"ch" , 0xfea0} , 349 | {"Ch" , 0xfea1} , 350 | {"CH" , 0xfea2} , 351 | {"c_h" , 0xfea3} , 352 | {"C_h" , 0xfea4} , 353 | {"C_H" , 0xfea5} , 354 | #endif 355 | #ifdef XK_3270 356 | {"3270_Duplicate" , 0xfd01} , 357 | {"3270_FieldMark" , 0xfd02} , 358 | {"3270_Right2" , 0xfd03} , 359 | {"3270_Left2" , 0xfd04} , 360 | {"3270_BackTab" , 0xfd05} , 361 | {"3270_EraseEOF" , 0xfd06} , 362 | {"3270_EraseInput" , 0xfd07} , 363 | {"3270_Reset" , 0xfd08} , 364 | {"3270_Quit" , 0xfd09} , 365 | {"3270_PA1" , 0xfd0a} , 366 | {"3270_PA2" , 0xfd0b} , 367 | {"3270_PA3" , 0xfd0c} , 368 | {"3270_Test" , 0xfd0d} , 369 | {"3270_Attn" , 0xfd0e} , 370 | {"3270_CursorBlink" , 0xfd0f} , 371 | {"3270_AltCursor" , 0xfd10} , 372 | {"3270_KeyClick" , 0xfd11} , 373 | {"3270_Jump" , 0xfd12} , 374 | {"3270_Ident" , 0xfd13} , 375 | {"3270_Rule" , 0xfd14} , 376 | {"3270_Copy" , 0xfd15} , 377 | {"3270_Play" , 0xfd16} , 378 | {"3270_Setup" , 0xfd17} , 379 | {"3270_Record" , 0xfd18} , 380 | {"3270_ChangeScreen" , 0xfd19} , 381 | {"3270_DeleteWord" , 0xfd1a} , 382 | {"3270_ExSelect" , 0xfd1b} , 383 | {"3270_CursorSelect" , 0xfd1c} , 384 | {"3270_PrintScreen" , 0xfd1d} , 385 | {"3270_Enter" , 0xfd1e} , 386 | #endif 387 | #ifdef XK_LATIN1 388 | {"space" , 0x0020} , 389 | {"exclam" , 0x0021} , 390 | {"quotedbl" , 0x0022} , 391 | {"numbersign" , 0x0023} , 392 | {"dollar" , 0x0024} , 393 | {"percent" , 0x0025} , 394 | {"ampersand" , 0x0026} , 395 | {"apostrophe" , 0x0027} , 396 | {"quoteright" , 0x0027} , 397 | {"parenleft" , 0x0028} , 398 | {"parenright" , 0x0029} , 399 | {"asterisk" , 0x002a} , 400 | {"plus" , 0x002b} , 401 | {"comma" , 0x002c} , 402 | {"minus" , 0x002d} , 403 | {"period" , 0x002e} , 404 | {"slash" , 0x002f} , 405 | {"0" , 0x0030} , 406 | {"1" , 0x0031} , 407 | {"2" , 0x0032} , 408 | {"3" , 0x0033} , 409 | {"4" , 0x0034} , 410 | {"5" , 0x0035} , 411 | {"6" , 0x0036} , 412 | {"7" , 0x0037} , 413 | {"8" , 0x0038} , 414 | {"9" , 0x0039} , 415 | {"colon" , 0x003a} , 416 | {"semicolon" , 0x003b} , 417 | {"less" , 0x003c} , 418 | {"equal" , 0x003d} , 419 | {"greater" , 0x003e} , 420 | {"question" , 0x003f} , 421 | {"at" , 0x0040} , 422 | {"A" , 0x0041} , 423 | {"B" , 0x0042} , 424 | {"C" , 0x0043} , 425 | {"D" , 0x0044} , 426 | {"E" , 0x0045} , 427 | {"F" , 0x0046} , 428 | {"G" , 0x0047} , 429 | {"H" , 0x0048} , 430 | {"I" , 0x0049} , 431 | {"J" , 0x004a} , 432 | {"K" , 0x004b} , 433 | {"L" , 0x004c} , 434 | {"M" , 0x004d} , 435 | {"N" , 0x004e} , 436 | {"O" , 0x004f} , 437 | {"P" , 0x0050} , 438 | {"Q" , 0x0051} , 439 | {"R" , 0x0052} , 440 | {"S" , 0x0053} , 441 | {"T" , 0x0054} , 442 | {"U" , 0x0055} , 443 | {"V" , 0x0056} , 444 | {"W" , 0x0057} , 445 | {"X" , 0x0058} , 446 | {"Y" , 0x0059} , 447 | {"Z" , 0x005a} , 448 | {"bracketleft" , 0x005b} , 449 | {"backslash" , 0x005c} , 450 | {"bracketright" , 0x005d} , 451 | {"asciicircum" , 0x005e} , 452 | {"underscore" , 0x005f} , 453 | {"grave" , 0x0060} , 454 | {"quoteleft" , 0x0060} , 455 | {"a" , 0x0061} , 456 | {"b" , 0x0062} , 457 | {"c" , 0x0063} , 458 | {"d" , 0x0064} , 459 | {"e" , 0x0065} , 460 | {"f" , 0x0066} , 461 | {"g" , 0x0067} , 462 | {"h" , 0x0068} , 463 | {"i" , 0x0069} , 464 | {"j" , 0x006a} , 465 | {"k" , 0x006b} , 466 | {"l" , 0x006c} , 467 | {"m" , 0x006d} , 468 | {"n" , 0x006e} , 469 | {"o" , 0x006f} , 470 | {"p" , 0x0070} , 471 | {"q" , 0x0071} , 472 | {"r" , 0x0072} , 473 | {"s" , 0x0073} , 474 | {"t" , 0x0074} , 475 | {"u" , 0x0075} , 476 | {"v" , 0x0076} , 477 | {"w" , 0x0077} , 478 | {"x" , 0x0078} , 479 | {"y" , 0x0079} , 480 | {"z" , 0x007a} , 481 | {"braceleft" , 0x007b} , 482 | {"bar" , 0x007c} , 483 | {"braceright" , 0x007d} , 484 | {"asciitilde" , 0x007e} , 485 | {"nobreakspace" , 0x00a0} , 486 | {"exclamdown" , 0x00a1} , 487 | {"cent" , 0x00a2} , 488 | {"sterling" , 0x00a3} , 489 | {"currency" , 0x00a4} , 490 | {"yen" , 0x00a5} , 491 | {"brokenbar" , 0x00a6} , 492 | {"section" , 0x00a7} , 493 | {"diaeresis" , 0x00a8} , 494 | {"copyright" , 0x00a9} , 495 | {"ordfeminine" , 0x00aa} , 496 | {"guillemotleft" , 0x00ab} , 497 | {"notsign" , 0x00ac} , 498 | {"hyphen" , 0x00ad} , 499 | {"registered" , 0x00ae} , 500 | {"macron" , 0x00af} , 501 | {"degree" , 0x00b0} , 502 | {"plusminus" , 0x00b1} , 503 | {"twosuperior" , 0x00b2} , 504 | {"threesuperior" , 0x00b3} , 505 | {"acute" , 0x00b4} , 506 | {"mu" , 0x00b5} , 507 | {"paragraph" , 0x00b6} , 508 | {"periodcentered" , 0x00b7} , 509 | {"cedilla" , 0x00b8} , 510 | {"onesuperior" , 0x00b9} , 511 | {"masculine" , 0x00ba} , 512 | {"guillemotright" , 0x00bb} , 513 | {"onequarter" , 0x00bc} , 514 | {"onehalf" , 0x00bd} , 515 | {"threequarters" , 0x00be} , 516 | {"questiondown" , 0x00bf} , 517 | {"Agrave" , 0x00c0} , 518 | {"Aacute" , 0x00c1} , 519 | {"Acircumflex" , 0x00c2} , 520 | {"Atilde" , 0x00c3} , 521 | {"Adiaeresis" , 0x00c4} , 522 | {"Aring" , 0x00c5} , 523 | {"AE" , 0x00c6} , 524 | {"Ccedilla" , 0x00c7} , 525 | {"Egrave" , 0x00c8} , 526 | {"Eacute" , 0x00c9} , 527 | {"Ecircumflex" , 0x00ca} , 528 | {"Ediaeresis" , 0x00cb} , 529 | {"Igrave" , 0x00cc} , 530 | {"Iacute" , 0x00cd} , 531 | {"Icircumflex" , 0x00ce} , 532 | {"Idiaeresis" , 0x00cf} , 533 | {"ETH" , 0x00d0} , 534 | {"Eth" , 0x00d0} , 535 | {"Ntilde" , 0x00d1} , 536 | {"Ograve" , 0x00d2} , 537 | {"Oacute" , 0x00d3} , 538 | {"Ocircumflex" , 0x00d4} , 539 | {"Otilde" , 0x00d5} , 540 | {"Odiaeresis" , 0x00d6} , 541 | {"multiply" , 0x00d7} , 542 | {"Oslash" , 0x00d8} , 543 | {"Ooblique" , 0x00d8} , 544 | {"Ugrave" , 0x00d9} , 545 | {"Uacute" , 0x00da} , 546 | {"Ucircumflex" , 0x00db} , 547 | {"Udiaeresis" , 0x00dc} , 548 | {"Yacute" , 0x00dd} , 549 | {"THORN" , 0x00de} , 550 | {"Thorn" , 0x00de} , 551 | {"ssharp" , 0x00df} , 552 | {"agrave" , 0x00e0} , 553 | {"aacute" , 0x00e1} , 554 | {"acircumflex" , 0x00e2} , 555 | {"atilde" , 0x00e3} , 556 | {"adiaeresis" , 0x00e4} , 557 | {"aring" , 0x00e5} , 558 | {"ae" , 0x00e6} , 559 | {"ccedilla" , 0x00e7} , 560 | {"egrave" , 0x00e8} , 561 | {"eacute" , 0x00e9} , 562 | {"ecircumflex" , 0x00ea} , 563 | {"ediaeresis" , 0x00eb} , 564 | {"igrave" , 0x00ec} , 565 | {"iacute" , 0x00ed} , 566 | {"icircumflex" , 0x00ee} , 567 | {"idiaeresis" , 0x00ef} , 568 | {"eth" , 0x00f0} , 569 | {"ntilde" , 0x00f1} , 570 | {"ograve" , 0x00f2} , 571 | {"oacute" , 0x00f3} , 572 | {"ocircumflex" , 0x00f4} , 573 | {"otilde" , 0x00f5} , 574 | {"odiaeresis" , 0x00f6} , 575 | {"division" , 0x00f7} , 576 | {"oslash" , 0x00f8} , 577 | {"ooblique" , 0x00f8} , 578 | {"ugrave" , 0x00f9} , 579 | {"uacute" , 0x00fa} , 580 | {"ucircumflex" , 0x00fb} , 581 | {"udiaeresis" , 0x00fc} , 582 | {"yacute" , 0x00fd} , 583 | {"thorn" , 0x00fe} , 584 | {"ydiaeresis" , 0x00ff} , 585 | #endif 586 | #ifdef XK_LATIN2 587 | {"Aogonek" , 0x01a1} , 588 | {"breve" , 0x01a2} , 589 | {"Lstroke" , 0x01a3} , 590 | {"Lcaron" , 0x01a5} , 591 | {"Sacute" , 0x01a6} , 592 | {"Scaron" , 0x01a9} , 593 | {"Scedilla" , 0x01aa} , 594 | {"Tcaron" , 0x01ab} , 595 | {"Zacute" , 0x01ac} , 596 | {"Zcaron" , 0x01ae} , 597 | {"Zabovedot" , 0x01af} , 598 | {"aogonek" , 0x01b1} , 599 | {"ogonek" , 0x01b2} , 600 | {"lstroke" , 0x01b3} , 601 | {"lcaron" , 0x01b5} , 602 | {"sacute" , 0x01b6} , 603 | {"caron" , 0x01b7} , 604 | {"scaron" , 0x01b9} , 605 | {"scedilla" , 0x01ba} , 606 | {"tcaron" , 0x01bb} , 607 | {"zacute" , 0x01bc} , 608 | {"doubleacute" , 0x01bd} , 609 | {"zcaron" , 0x01be} , 610 | {"zabovedot" , 0x01bf} , 611 | {"Racute" , 0x01c0} , 612 | {"Abreve" , 0x01c3} , 613 | {"Lacute" , 0x01c5} , 614 | {"Cacute" , 0x01c6} , 615 | {"Ccaron" , 0x01c8} , 616 | {"Eogonek" , 0x01ca} , 617 | {"Ecaron" , 0x01cc} , 618 | {"Dcaron" , 0x01cf} , 619 | {"Dstroke" , 0x01d0} , 620 | {"Nacute" , 0x01d1} , 621 | {"Ncaron" , 0x01d2} , 622 | {"Odoubleacute" , 0x01d5} , 623 | {"Rcaron" , 0x01d8} , 624 | {"Uring" , 0x01d9} , 625 | {"Udoubleacute" , 0x01db} , 626 | {"Tcedilla" , 0x01de} , 627 | {"racute" , 0x01e0} , 628 | {"abreve" , 0x01e3} , 629 | {"lacute" , 0x01e5} , 630 | {"cacute" , 0x01e6} , 631 | {"ccaron" , 0x01e8} , 632 | {"eogonek" , 0x01ea} , 633 | {"ecaron" , 0x01ec} , 634 | {"dcaron" , 0x01ef} , 635 | {"dstroke" , 0x01f0} , 636 | {"nacute" , 0x01f1} , 637 | {"ncaron" , 0x01f2} , 638 | {"odoubleacute" , 0x01f5} , 639 | {"rcaron" , 0x01f8} , 640 | {"uring" , 0x01f9} , 641 | {"udoubleacute" , 0x01fb} , 642 | {"tcedilla" , 0x01fe} , 643 | {"abovedot" , 0x01ff} , 644 | #endif 645 | #ifdef XK_LATIN3 646 | {"Hstroke" , 0x02a1} , 647 | {"Hcircumflex" , 0x02a6} , 648 | {"Iabovedot" , 0x02a9} , 649 | {"Gbreve" , 0x02ab} , 650 | {"Jcircumflex" , 0x02ac} , 651 | {"hstroke" , 0x02b1} , 652 | {"hcircumflex" , 0x02b6} , 653 | {"idotless" , 0x02b9} , 654 | {"gbreve" , 0x02bb} , 655 | {"jcircumflex" , 0x02bc} , 656 | {"Cabovedot" , 0x02c5} , 657 | {"Ccircumflex" , 0x02c6} , 658 | {"Gabovedot" , 0x02d5} , 659 | {"Gcircumflex" , 0x02d8} , 660 | {"Ubreve" , 0x02dd} , 661 | {"Scircumflex" , 0x02de} , 662 | {"cabovedot" , 0x02e5} , 663 | {"ccircumflex" , 0x02e6} , 664 | {"gabovedot" , 0x02f5} , 665 | {"gcircumflex" , 0x02f8} , 666 | {"ubreve" , 0x02fd} , 667 | {"scircumflex" , 0x02fe} , 668 | #endif 669 | #ifdef XK_LATIN4 670 | {"kra" , 0x03a2} , 671 | {"kappa" , 0x03a2} , 672 | {"Rcedilla" , 0x03a3} , 673 | {"Itilde" , 0x03a5} , 674 | {"Lcedilla" , 0x03a6} , 675 | {"Emacron" , 0x03aa} , 676 | {"Gcedilla" , 0x03ab} , 677 | {"Tslash" , 0x03ac} , 678 | {"rcedilla" , 0x03b3} , 679 | {"itilde" , 0x03b5} , 680 | {"lcedilla" , 0x03b6} , 681 | {"emacron" , 0x03ba} , 682 | {"gcedilla" , 0x03bb} , 683 | {"tslash" , 0x03bc} , 684 | {"ENG" , 0x03bd} , 685 | {"eng" , 0x03bf} , 686 | {"Amacron" , 0x03c0} , 687 | {"Iogonek" , 0x03c7} , 688 | {"Eabovedot" , 0x03cc} , 689 | {"Imacron" , 0x03cf} , 690 | {"Ncedilla" , 0x03d1} , 691 | {"Omacron" , 0x03d2} , 692 | {"Kcedilla" , 0x03d3} , 693 | {"Uogonek" , 0x03d9} , 694 | {"Utilde" , 0x03dd} , 695 | {"Umacron" , 0x03de} , 696 | {"amacron" , 0x03e0} , 697 | {"iogonek" , 0x03e7} , 698 | {"eabovedot" , 0x03ec} , 699 | {"imacron" , 0x03ef} , 700 | {"ncedilla" , 0x03f1} , 701 | {"omacron" , 0x03f2} , 702 | {"kcedilla" , 0x03f3} , 703 | {"uogonek" , 0x03f9} , 704 | {"utilde" , 0x03fd} , 705 | {"umacron" , 0x03fe} , 706 | #endif 707 | #ifdef XK_LATIN8 708 | {"Wcircumflex" , 0x1000174} , 709 | {"wcircumflex" , 0x1000175} , 710 | {"Ycircumflex" , 0x1000176} , 711 | {"ycircumflex" , 0x1000177} , 712 | {"Babovedot" , 0x1001e02} , 713 | {"babovedot" , 0x1001e03} , 714 | {"Dabovedot" , 0x1001e0a} , 715 | {"dabovedot" , 0x1001e0b} , 716 | {"Fabovedot" , 0x1001e1e} , 717 | {"fabovedot" , 0x1001e1f} , 718 | {"Mabovedot" , 0x1001e40} , 719 | {"mabovedot" , 0x1001e41} , 720 | {"Pabovedot" , 0x1001e56} , 721 | {"pabovedot" , 0x1001e57} , 722 | {"Sabovedot" , 0x1001e60} , 723 | {"sabovedot" , 0x1001e61} , 724 | {"Tabovedot" , 0x1001e6a} , 725 | {"tabovedot" , 0x1001e6b} , 726 | {"Wgrave" , 0x1001e80} , 727 | {"wgrave" , 0x1001e81} , 728 | {"Wacute" , 0x1001e82} , 729 | {"wacute" , 0x1001e83} , 730 | {"Wdiaeresis" , 0x1001e84} , 731 | {"wdiaeresis" , 0x1001e85} , 732 | {"Ygrave" , 0x1001ef2} , 733 | {"ygrave" , 0x1001ef3} , 734 | #endif 735 | #ifdef XK_LATIN9 736 | {"OE" , 0x13bc} , 737 | {"oe" , 0x13bd} , 738 | {"Ydiaeresis" , 0x13be} , 739 | #endif 740 | #ifdef XK_KATAKANA 741 | {"overline" , 0x047e} , 742 | {"kana_fullstop" , 0x04a1} , 743 | {"kana_openingbracket" , 0x04a2} , 744 | {"kana_closingbracket" , 0x04a3} , 745 | {"kana_comma" , 0x04a4} , 746 | {"kana_conjunctive" , 0x04a5} , 747 | {"kana_middledot" , 0x04a5} , 748 | {"kana_WO" , 0x04a6} , 749 | {"kana_a" , 0x04a7} , 750 | {"kana_i" , 0x04a8} , 751 | {"kana_u" , 0x04a9} , 752 | {"kana_e" , 0x04aa} , 753 | {"kana_o" , 0x04ab} , 754 | {"kana_ya" , 0x04ac} , 755 | {"kana_yu" , 0x04ad} , 756 | {"kana_yo" , 0x04ae} , 757 | {"kana_tsu" , 0x04af} , 758 | {"kana_tu" , 0x04af} , 759 | {"prolongedsound" , 0x04b0} , 760 | {"kana_A" , 0x04b1} , 761 | {"kana_I" , 0x04b2} , 762 | {"kana_U" , 0x04b3} , 763 | {"kana_E" , 0x04b4} , 764 | {"kana_O" , 0x04b5} , 765 | {"kana_KA" , 0x04b6} , 766 | {"kana_KI" , 0x04b7} , 767 | {"kana_KU" , 0x04b8} , 768 | {"kana_KE" , 0x04b9} , 769 | {"kana_KO" , 0x04ba} , 770 | {"kana_SA" , 0x04bb} , 771 | {"kana_SHI" , 0x04bc} , 772 | {"kana_SU" , 0x04bd} , 773 | {"kana_SE" , 0x04be} , 774 | {"kana_SO" , 0x04bf} , 775 | {"kana_TA" , 0x04c0} , 776 | {"kana_CHI" , 0x04c1} , 777 | {"kana_TI" , 0x04c1} , 778 | {"kana_TSU" , 0x04c2} , 779 | {"kana_TU" , 0x04c2} , 780 | {"kana_TE" , 0x04c3} , 781 | {"kana_TO" , 0x04c4} , 782 | {"kana_NA" , 0x04c5} , 783 | {"kana_NI" , 0x04c6} , 784 | {"kana_NU" , 0x04c7} , 785 | {"kana_NE" , 0x04c8} , 786 | {"kana_NO" , 0x04c9} , 787 | {"kana_HA" , 0x04ca} , 788 | {"kana_HI" , 0x04cb} , 789 | {"kana_FU" , 0x04cc} , 790 | {"kana_HU" , 0x04cc} , 791 | {"kana_HE" , 0x04cd} , 792 | {"kana_HO" , 0x04ce} , 793 | {"kana_MA" , 0x04cf} , 794 | {"kana_MI" , 0x04d0} , 795 | {"kana_MU" , 0x04d1} , 796 | {"kana_ME" , 0x04d2} , 797 | {"kana_MO" , 0x04d3} , 798 | {"kana_YA" , 0x04d4} , 799 | {"kana_YU" , 0x04d5} , 800 | {"kana_YO" , 0x04d6} , 801 | {"kana_RA" , 0x04d7} , 802 | {"kana_RI" , 0x04d8} , 803 | {"kana_RU" , 0x04d9} , 804 | {"kana_RE" , 0x04da} , 805 | {"kana_RO" , 0x04db} , 806 | {"kana_WA" , 0x04dc} , 807 | {"kana_N" , 0x04dd} , 808 | {"voicedsound" , 0x04de} , 809 | {"semivoicedsound" , 0x04df} , 810 | {"kana_switch" , 0xff7e} , 811 | #endif 812 | #ifdef XK_ARABIC 813 | {"Farsi_0" , 0x10006f0} , 814 | {"Farsi_1" , 0x10006f1} , 815 | {"Farsi_2" , 0x10006f2} , 816 | {"Farsi_3" , 0x10006f3} , 817 | {"Farsi_4" , 0x10006f4} , 818 | {"Farsi_5" , 0x10006f5} , 819 | {"Farsi_6" , 0x10006f6} , 820 | {"Farsi_7" , 0x10006f7} , 821 | {"Farsi_8" , 0x10006f8} , 822 | {"Farsi_9" , 0x10006f9} , 823 | {"Arabic_percent" , 0x100066a} , 824 | {"Arabic_superscript_alef" , 0x1000670} , 825 | {"Arabic_tteh" , 0x1000679} , 826 | {"Arabic_peh" , 0x100067e} , 827 | {"Arabic_tcheh" , 0x1000686} , 828 | {"Arabic_ddal" , 0x1000688} , 829 | {"Arabic_rreh" , 0x1000691} , 830 | {"Arabic_comma" , 0x05ac} , 831 | {"Arabic_fullstop" , 0x10006d4} , 832 | {"Arabic_0" , 0x1000660} , 833 | {"Arabic_1" , 0x1000661} , 834 | {"Arabic_2" , 0x1000662} , 835 | {"Arabic_3" , 0x1000663} , 836 | {"Arabic_4" , 0x1000664} , 837 | {"Arabic_5" , 0x1000665} , 838 | {"Arabic_6" , 0x1000666} , 839 | {"Arabic_7" , 0x1000667} , 840 | {"Arabic_8" , 0x1000668} , 841 | {"Arabic_9" , 0x1000669} , 842 | {"Arabic_semicolon" , 0x05bb} , 843 | {"Arabic_question_mark" , 0x05bf} , 844 | {"Arabic_hamza" , 0x05c1} , 845 | {"Arabic_maddaonalef" , 0x05c2} , 846 | {"Arabic_hamzaonalef" , 0x05c3} , 847 | {"Arabic_hamzaonwaw" , 0x05c4} , 848 | {"Arabic_hamzaunderalef" , 0x05c5} , 849 | {"Arabic_hamzaonyeh" , 0x05c6} , 850 | {"Arabic_alef" , 0x05c7} , 851 | {"Arabic_beh" , 0x05c8} , 852 | {"Arabic_tehmarbuta" , 0x05c9} , 853 | {"Arabic_teh" , 0x05ca} , 854 | {"Arabic_theh" , 0x05cb} , 855 | {"Arabic_jeem" , 0x05cc} , 856 | {"Arabic_hah" , 0x05cd} , 857 | {"Arabic_khah" , 0x05ce} , 858 | {"Arabic_dal" , 0x05cf} , 859 | {"Arabic_thal" , 0x05d0} , 860 | {"Arabic_ra" , 0x05d1} , 861 | {"Arabic_zain" , 0x05d2} , 862 | {"Arabic_seen" , 0x05d3} , 863 | {"Arabic_sheen" , 0x05d4} , 864 | {"Arabic_sad" , 0x05d5} , 865 | {"Arabic_dad" , 0x05d6} , 866 | {"Arabic_tah" , 0x05d7} , 867 | {"Arabic_zah" , 0x05d8} , 868 | {"Arabic_ain" , 0x05d9} , 869 | {"Arabic_ghain" , 0x05da} , 870 | {"Arabic_tatweel" , 0x05e0} , 871 | {"Arabic_feh" , 0x05e1} , 872 | {"Arabic_qaf" , 0x05e2} , 873 | {"Arabic_kaf" , 0x05e3} , 874 | {"Arabic_lam" , 0x05e4} , 875 | {"Arabic_meem" , 0x05e5} , 876 | {"Arabic_noon" , 0x05e6} , 877 | {"Arabic_ha" , 0x05e7} , 878 | {"Arabic_heh" , 0x05e7} , 879 | {"Arabic_waw" , 0x05e8} , 880 | {"Arabic_alefmaksura" , 0x05e9} , 881 | {"Arabic_yeh" , 0x05ea} , 882 | {"Arabic_fathatan" , 0x05eb} , 883 | {"Arabic_dammatan" , 0x05ec} , 884 | {"Arabic_kasratan" , 0x05ed} , 885 | {"Arabic_fatha" , 0x05ee} , 886 | {"Arabic_damma" , 0x05ef} , 887 | {"Arabic_kasra" , 0x05f0} , 888 | {"Arabic_shadda" , 0x05f1} , 889 | {"Arabic_sukun" , 0x05f2} , 890 | {"Arabic_madda_above" , 0x1000653} , 891 | {"Arabic_hamza_above" , 0x1000654} , 892 | {"Arabic_hamza_below" , 0x1000655} , 893 | {"Arabic_jeh" , 0x1000698} , 894 | {"Arabic_veh" , 0x10006a4} , 895 | {"Arabic_keheh" , 0x10006a9} , 896 | {"Arabic_gaf" , 0x10006af} , 897 | {"Arabic_noon_ghunna" , 0x10006ba} , 898 | {"Arabic_heh_doachashmee" , 0x10006be} , 899 | {"Farsi_yeh" , 0x10006cc} , 900 | {"Arabic_farsi_yeh" , 0x10006cc} , 901 | {"Arabic_yeh_baree" , 0x10006d2} , 902 | {"Arabic_heh_goal" , 0x10006c1} , 903 | {"Arabic_switch" , 0xff7e} , 904 | #endif 905 | #ifdef XK_CYRILLIC 906 | {"Cyrillic_GHE_bar" , 0x1000492} , 907 | {"Cyrillic_ghe_bar" , 0x1000493} , 908 | {"Cyrillic_ZHE_descender" , 0x1000496} , 909 | {"Cyrillic_zhe_descender" , 0x1000497} , 910 | {"Cyrillic_KA_descender" , 0x100049a} , 911 | {"Cyrillic_ka_descender" , 0x100049b} , 912 | {"Cyrillic_KA_vertstroke" , 0x100049c} , 913 | {"Cyrillic_ka_vertstroke" , 0x100049d} , 914 | {"Cyrillic_EN_descender" , 0x10004a2} , 915 | {"Cyrillic_en_descender" , 0x10004a3} , 916 | {"Cyrillic_U_straight" , 0x10004ae} , 917 | {"Cyrillic_u_straight" , 0x10004af} , 918 | {"Cyrillic_U_straight_bar" , 0x10004b0} , 919 | {"Cyrillic_u_straight_bar" , 0x10004b1} , 920 | {"Cyrillic_HA_descender" , 0x10004b2} , 921 | {"Cyrillic_ha_descender" , 0x10004b3} , 922 | {"Cyrillic_CHE_descender" , 0x10004b6} , 923 | {"Cyrillic_che_descender" , 0x10004b7} , 924 | {"Cyrillic_CHE_vertstroke" , 0x10004b8} , 925 | {"Cyrillic_che_vertstroke" , 0x10004b9} , 926 | {"Cyrillic_SHHA" , 0x10004ba} , 927 | {"Cyrillic_shha" , 0x10004bb} , 928 | {"Cyrillic_SCHWA" , 0x10004d8} , 929 | {"Cyrillic_schwa" , 0x10004d9} , 930 | {"Cyrillic_I_macron" , 0x10004e2} , 931 | {"Cyrillic_i_macron" , 0x10004e3} , 932 | {"Cyrillic_O_bar" , 0x10004e8} , 933 | {"Cyrillic_o_bar" , 0x10004e9} , 934 | {"Cyrillic_U_macron" , 0x10004ee} , 935 | {"Cyrillic_u_macron" , 0x10004ef} , 936 | {"Serbian_dje" , 0x06a1} , 937 | {"Macedonia_gje" , 0x06a2} , 938 | {"Cyrillic_io" , 0x06a3} , 939 | {"Ukrainian_ie" , 0x06a4} , 940 | {"Ukranian_je" , 0x06a4} , 941 | {"Macedonia_dse" , 0x06a5} , 942 | {"Ukrainian_i" , 0x06a6} , 943 | {"Ukranian_i" , 0x06a6} , 944 | {"Ukrainian_yi" , 0x06a7} , 945 | {"Ukranian_yi" , 0x06a7} , 946 | {"Cyrillic_je" , 0x06a8} , 947 | {"Serbian_je" , 0x06a8} , 948 | {"Cyrillic_lje" , 0x06a9} , 949 | {"Serbian_lje" , 0x06a9} , 950 | {"Cyrillic_nje" , 0x06aa} , 951 | {"Serbian_nje" , 0x06aa} , 952 | {"Serbian_tshe" , 0x06ab} , 953 | {"Macedonia_kje" , 0x06ac} , 954 | {"Ukrainian_ghe_with_upturn" , 0x06ad} , 955 | {"Byelorussian_shortu" , 0x06ae} , 956 | {"Cyrillic_dzhe" , 0x06af} , 957 | {"Serbian_dze" , 0x06af} , 958 | {"numerosign" , 0x06b0} , 959 | {"Serbian_DJE" , 0x06b1} , 960 | {"Macedonia_GJE" , 0x06b2} , 961 | {"Cyrillic_IO" , 0x06b3} , 962 | {"Ukrainian_IE" , 0x06b4} , 963 | {"Ukranian_JE" , 0x06b4} , 964 | {"Macedonia_DSE" , 0x06b5} , 965 | {"Ukrainian_I" , 0x06b6} , 966 | {"Ukranian_I" , 0x06b6} , 967 | {"Ukrainian_YI" , 0x06b7} , 968 | {"Ukranian_YI" , 0x06b7} , 969 | {"Cyrillic_JE" , 0x06b8} , 970 | {"Serbian_JE" , 0x06b8} , 971 | {"Cyrillic_LJE" , 0x06b9} , 972 | {"Serbian_LJE" , 0x06b9} , 973 | {"Cyrillic_NJE" , 0x06ba} , 974 | {"Serbian_NJE" , 0x06ba} , 975 | {"Serbian_TSHE" , 0x06bb} , 976 | {"Macedonia_KJE" , 0x06bc} , 977 | {"Ukrainian_GHE_WITH_UPTURN" , 0x06bd} , 978 | {"Byelorussian_SHORTU" , 0x06be} , 979 | {"Cyrillic_DZHE" , 0x06bf} , 980 | {"Serbian_DZE" , 0x06bf} , 981 | {"Cyrillic_yu" , 0x06c0} , 982 | {"Cyrillic_a" , 0x06c1} , 983 | {"Cyrillic_be" , 0x06c2} , 984 | {"Cyrillic_tse" , 0x06c3} , 985 | {"Cyrillic_de" , 0x06c4} , 986 | {"Cyrillic_ie" , 0x06c5} , 987 | {"Cyrillic_ef" , 0x06c6} , 988 | {"Cyrillic_ghe" , 0x06c7} , 989 | {"Cyrillic_ha" , 0x06c8} , 990 | {"Cyrillic_i" , 0x06c9} , 991 | {"Cyrillic_shorti" , 0x06ca} , 992 | {"Cyrillic_ka" , 0x06cb} , 993 | {"Cyrillic_el" , 0x06cc} , 994 | {"Cyrillic_em" , 0x06cd} , 995 | {"Cyrillic_en" , 0x06ce} , 996 | {"Cyrillic_o" , 0x06cf} , 997 | {"Cyrillic_pe" , 0x06d0} , 998 | {"Cyrillic_ya" , 0x06d1} , 999 | {"Cyrillic_er" , 0x06d2} , 1000 | {"Cyrillic_es" , 0x06d3} , 1001 | {"Cyrillic_te" , 0x06d4} , 1002 | {"Cyrillic_u" , 0x06d5} , 1003 | {"Cyrillic_zhe" , 0x06d6} , 1004 | {"Cyrillic_ve" , 0x06d7} , 1005 | {"Cyrillic_softsign" , 0x06d8} , 1006 | {"Cyrillic_yeru" , 0x06d9} , 1007 | {"Cyrillic_ze" , 0x06da} , 1008 | {"Cyrillic_sha" , 0x06db} , 1009 | {"Cyrillic_e" , 0x06dc} , 1010 | {"Cyrillic_shcha" , 0x06dd} , 1011 | {"Cyrillic_che" , 0x06de} , 1012 | {"Cyrillic_hardsign" , 0x06df} , 1013 | {"Cyrillic_YU" , 0x06e0} , 1014 | {"Cyrillic_A" , 0x06e1} , 1015 | {"Cyrillic_BE" , 0x06e2} , 1016 | {"Cyrillic_TSE" , 0x06e3} , 1017 | {"Cyrillic_DE" , 0x06e4} , 1018 | {"Cyrillic_IE" , 0x06e5} , 1019 | {"Cyrillic_EF" , 0x06e6} , 1020 | {"Cyrillic_GHE" , 0x06e7} , 1021 | {"Cyrillic_HA" , 0x06e8} , 1022 | {"Cyrillic_I" , 0x06e9} , 1023 | {"Cyrillic_SHORTI" , 0x06ea} , 1024 | {"Cyrillic_KA" , 0x06eb} , 1025 | {"Cyrillic_EL" , 0x06ec} , 1026 | {"Cyrillic_EM" , 0x06ed} , 1027 | {"Cyrillic_EN" , 0x06ee} , 1028 | {"Cyrillic_O" , 0x06ef} , 1029 | {"Cyrillic_PE" , 0x06f0} , 1030 | {"Cyrillic_YA" , 0x06f1} , 1031 | {"Cyrillic_ER" , 0x06f2} , 1032 | {"Cyrillic_ES" , 0x06f3} , 1033 | {"Cyrillic_TE" , 0x06f4} , 1034 | {"Cyrillic_U" , 0x06f5} , 1035 | {"Cyrillic_ZHE" , 0x06f6} , 1036 | {"Cyrillic_VE" , 0x06f7} , 1037 | {"Cyrillic_SOFTSIGN" , 0x06f8} , 1038 | {"Cyrillic_YERU" , 0x06f9} , 1039 | {"Cyrillic_ZE" , 0x06fa} , 1040 | {"Cyrillic_SHA" , 0x06fb} , 1041 | {"Cyrillic_E" , 0x06fc} , 1042 | {"Cyrillic_SHCHA" , 0x06fd} , 1043 | {"Cyrillic_CHE" , 0x06fe} , 1044 | {"Cyrillic_HARDSIGN" , 0x06ff} , 1045 | #endif 1046 | #ifdef XK_GREEK 1047 | {"Greek_ALPHAaccent" , 0x07a1} , 1048 | {"Greek_EPSILONaccent" , 0x07a2} , 1049 | {"Greek_ETAaccent" , 0x07a3} , 1050 | {"Greek_IOTAaccent" , 0x07a4} , 1051 | {"Greek_IOTAdieresis" , 0x07a5} , 1052 | {"Greek_IOTAdiaeresis" , 0x07a5} , 1053 | {"Greek_OMICRONaccent" , 0x07a7} , 1054 | {"Greek_UPSILONaccent" , 0x07a8} , 1055 | {"Greek_UPSILONdieresis" , 0x07a9} , 1056 | {"Greek_OMEGAaccent" , 0x07ab} , 1057 | {"Greek_accentdieresis" , 0x07ae} , 1058 | {"Greek_horizbar" , 0x07af} , 1059 | {"Greek_alphaaccent" , 0x07b1} , 1060 | {"Greek_epsilonaccent" , 0x07b2} , 1061 | {"Greek_etaaccent" , 0x07b3} , 1062 | {"Greek_iotaaccent" , 0x07b4} , 1063 | {"Greek_iotadieresis" , 0x07b5} , 1064 | {"Greek_iotaaccentdieresis" , 0x07b6} , 1065 | {"Greek_omicronaccent" , 0x07b7} , 1066 | {"Greek_upsilonaccent" , 0x07b8} , 1067 | {"Greek_upsilondieresis" , 0x07b9} , 1068 | {"Greek_upsilonaccentdieresis" , 0x07ba} , 1069 | {"Greek_omegaaccent" , 0x07bb} , 1070 | {"Greek_ALPHA" , 0x07c1} , 1071 | {"Greek_BETA" , 0x07c2} , 1072 | {"Greek_GAMMA" , 0x07c3} , 1073 | {"Greek_DELTA" , 0x07c4} , 1074 | {"Greek_EPSILON" , 0x07c5} , 1075 | {"Greek_ZETA" , 0x07c6} , 1076 | {"Greek_ETA" , 0x07c7} , 1077 | {"Greek_THETA" , 0x07c8} , 1078 | {"Greek_IOTA" , 0x07c9} , 1079 | {"Greek_KAPPA" , 0x07ca} , 1080 | {"Greek_LAMDA" , 0x07cb} , 1081 | {"Greek_LAMBDA" , 0x07cb} , 1082 | {"Greek_MU" , 0x07cc} , 1083 | {"Greek_NU" , 0x07cd} , 1084 | {"Greek_XI" , 0x07ce} , 1085 | {"Greek_OMICRON" , 0x07cf} , 1086 | {"Greek_PI" , 0x07d0} , 1087 | {"Greek_RHO" , 0x07d1} , 1088 | {"Greek_SIGMA" , 0x07d2} , 1089 | {"Greek_TAU" , 0x07d4} , 1090 | {"Greek_UPSILON" , 0x07d5} , 1091 | {"Greek_PHI" , 0x07d6} , 1092 | {"Greek_CHI" , 0x07d7} , 1093 | {"Greek_PSI" , 0x07d8} , 1094 | {"Greek_OMEGA" , 0x07d9} , 1095 | {"Greek_alpha" , 0x07e1} , 1096 | {"Greek_beta" , 0x07e2} , 1097 | {"Greek_gamma" , 0x07e3} , 1098 | {"Greek_delta" , 0x07e4} , 1099 | {"Greek_epsilon" , 0x07e5} , 1100 | {"Greek_zeta" , 0x07e6} , 1101 | {"Greek_eta" , 0x07e7} , 1102 | {"Greek_theta" , 0x07e8} , 1103 | {"Greek_iota" , 0x07e9} , 1104 | {"Greek_kappa" , 0x07ea} , 1105 | {"Greek_lamda" , 0x07eb} , 1106 | {"Greek_lambda" , 0x07eb} , 1107 | {"Greek_mu" , 0x07ec} , 1108 | {"Greek_nu" , 0x07ed} , 1109 | {"Greek_xi" , 0x07ee} , 1110 | {"Greek_omicron" , 0x07ef} , 1111 | {"Greek_pi" , 0x07f0} , 1112 | {"Greek_rho" , 0x07f1} , 1113 | {"Greek_sigma" , 0x07f2} , 1114 | {"Greek_finalsmallsigma" , 0x07f3} , 1115 | {"Greek_tau" , 0x07f4} , 1116 | {"Greek_upsilon" , 0x07f5} , 1117 | {"Greek_phi" , 0x07f6} , 1118 | {"Greek_chi" , 0x07f7} , 1119 | {"Greek_psi" , 0x07f8} , 1120 | {"Greek_omega" , 0x07f9} , 1121 | {"Greek_switch" , 0xff7e} , 1122 | #endif 1123 | #ifdef XK_TECHNICAL 1124 | {"leftradical" , 0x08a1} , 1125 | {"topleftradical" , 0x08a2} , 1126 | {"horizconnector" , 0x08a3} , 1127 | {"topintegral" , 0x08a4} , 1128 | {"botintegral" , 0x08a5} , 1129 | {"vertconnector" , 0x08a6} , 1130 | {"topleftsqbracket" , 0x08a7} , 1131 | {"botleftsqbracket" , 0x08a8} , 1132 | {"toprightsqbracket" , 0x08a9} , 1133 | {"botrightsqbracket" , 0x08aa} , 1134 | {"topleftparens" , 0x08ab} , 1135 | {"botleftparens" , 0x08ac} , 1136 | {"toprightparens" , 0x08ad} , 1137 | {"botrightparens" , 0x08ae} , 1138 | {"leftmiddlecurlybrace" , 0x08af} , 1139 | {"rightmiddlecurlybrace" , 0x08b0} , 1140 | {"topleftsummation" , 0x08b1} , 1141 | {"botleftsummation" , 0x08b2} , 1142 | {"topvertsummationconnector" , 0x08b3} , 1143 | {"botvertsummationconnector" , 0x08b4} , 1144 | {"toprightsummation" , 0x08b5} , 1145 | {"botrightsummation" , 0x08b6} , 1146 | {"rightmiddlesummation" , 0x08b7} , 1147 | {"lessthanequal" , 0x08bc} , 1148 | {"notequal" , 0x08bd} , 1149 | {"greaterthanequal" , 0x08be} , 1150 | {"integral" , 0x08bf} , 1151 | {"therefore" , 0x08c0} , 1152 | {"variation" , 0x08c1} , 1153 | {"infinity" , 0x08c2} , 1154 | {"nabla" , 0x08c5} , 1155 | {"approximate" , 0x08c8} , 1156 | {"similarequal" , 0x08c9} , 1157 | {"ifonlyif" , 0x08cd} , 1158 | {"implies" , 0x08ce} , 1159 | {"identical" , 0x08cf} , 1160 | {"radical" , 0x08d6} , 1161 | {"includedin" , 0x08da} , 1162 | {"includes" , 0x08db} , 1163 | {"intersection" , 0x08dc} , 1164 | {"union" , 0x08dd} , 1165 | {"logicaland" , 0x08de} , 1166 | {"logicalor" , 0x08df} , 1167 | {"partialderivative" , 0x08ef} , 1168 | {"function" , 0x08f6} , 1169 | {"leftarrow" , 0x08fb} , 1170 | {"uparrow" , 0x08fc} , 1171 | {"rightarrow" , 0x08fd} , 1172 | {"downarrow" , 0x08fe} , 1173 | #endif 1174 | #ifdef XK_SPECIAL 1175 | {"blank" , 0x09df} , 1176 | {"soliddiamond" , 0x09e0} , 1177 | {"checkerboard" , 0x09e1} , 1178 | {"ht" , 0x09e2} , 1179 | {"ff" , 0x09e3} , 1180 | {"cr" , 0x09e4} , 1181 | {"lf" , 0x09e5} , 1182 | {"nl" , 0x09e8} , 1183 | {"vt" , 0x09e9} , 1184 | {"lowrightcorner" , 0x09ea} , 1185 | {"uprightcorner" , 0x09eb} , 1186 | {"upleftcorner" , 0x09ec} , 1187 | {"lowleftcorner" , 0x09ed} , 1188 | {"crossinglines" , 0x09ee} , 1189 | {"horizlinescan1" , 0x09ef} , 1190 | {"horizlinescan3" , 0x09f0} , 1191 | {"horizlinescan5" , 0x09f1} , 1192 | {"horizlinescan7" , 0x09f2} , 1193 | {"horizlinescan9" , 0x09f3} , 1194 | {"leftt" , 0x09f4} , 1195 | {"rightt" , 0x09f5} , 1196 | {"bott" , 0x09f6} , 1197 | {"topt" , 0x09f7} , 1198 | {"vertbar" , 0x09f8} , 1199 | #endif 1200 | #ifdef XK_PUBLISHING 1201 | {"emspace" , 0x0aa1} , 1202 | {"enspace" , 0x0aa2} , 1203 | {"em3space" , 0x0aa3} , 1204 | {"em4space" , 0x0aa4} , 1205 | {"digitspace" , 0x0aa5} , 1206 | {"punctspace" , 0x0aa6} , 1207 | {"thinspace" , 0x0aa7} , 1208 | {"hairspace" , 0x0aa8} , 1209 | {"emdash" , 0x0aa9} , 1210 | {"endash" , 0x0aaa} , 1211 | {"signifblank" , 0x0aac} , 1212 | {"ellipsis" , 0x0aae} , 1213 | {"doubbaselinedot" , 0x0aaf} , 1214 | {"onethird" , 0x0ab0} , 1215 | {"twothirds" , 0x0ab1} , 1216 | {"onefifth" , 0x0ab2} , 1217 | {"twofifths" , 0x0ab3} , 1218 | {"threefifths" , 0x0ab4} , 1219 | {"fourfifths" , 0x0ab5} , 1220 | {"onesixth" , 0x0ab6} , 1221 | {"fivesixths" , 0x0ab7} , 1222 | {"careof" , 0x0ab8} , 1223 | {"figdash" , 0x0abb} , 1224 | {"leftanglebracket" , 0x0abc} , 1225 | {"decimalpoint" , 0x0abd} , 1226 | {"rightanglebracket" , 0x0abe} , 1227 | {"marker" , 0x0abf} , 1228 | {"oneeighth" , 0x0ac3} , 1229 | {"threeeighths" , 0x0ac4} , 1230 | {"fiveeighths" , 0x0ac5} , 1231 | {"seveneighths" , 0x0ac6} , 1232 | {"trademark" , 0x0ac9} , 1233 | {"signaturemark" , 0x0aca} , 1234 | {"trademarkincircle" , 0x0acb} , 1235 | {"leftopentriangle" , 0x0acc} , 1236 | {"rightopentriangle" , 0x0acd} , 1237 | {"emopencircle" , 0x0ace} , 1238 | {"emopenrectangle" , 0x0acf} , 1239 | {"leftsinglequotemark" , 0x0ad0} , 1240 | {"rightsinglequotemark" , 0x0ad1} , 1241 | {"leftdoublequotemark" , 0x0ad2} , 1242 | {"rightdoublequotemark" , 0x0ad3} , 1243 | {"prescription" , 0x0ad4} , 1244 | {"permille" , 0x0ad5} , 1245 | {"minutes" , 0x0ad6} , 1246 | {"seconds" , 0x0ad7} , 1247 | {"latincross" , 0x0ad9} , 1248 | {"hexagram" , 0x0ada} , 1249 | {"filledrectbullet" , 0x0adb} , 1250 | {"filledlefttribullet" , 0x0adc} , 1251 | {"filledrighttribullet" , 0x0add} , 1252 | {"emfilledcircle" , 0x0ade} , 1253 | {"emfilledrect" , 0x0adf} , 1254 | {"enopencircbullet" , 0x0ae0} , 1255 | {"enopensquarebullet" , 0x0ae1} , 1256 | {"openrectbullet" , 0x0ae2} , 1257 | {"opentribulletup" , 0x0ae3} , 1258 | {"opentribulletdown" , 0x0ae4} , 1259 | {"openstar" , 0x0ae5} , 1260 | {"enfilledcircbullet" , 0x0ae6} , 1261 | {"enfilledsqbullet" , 0x0ae7} , 1262 | {"filledtribulletup" , 0x0ae8} , 1263 | {"filledtribulletdown" , 0x0ae9} , 1264 | {"leftpointer" , 0x0aea} , 1265 | {"rightpointer" , 0x0aeb} , 1266 | {"club" , 0x0aec} , 1267 | {"diamond" , 0x0aed} , 1268 | {"heart" , 0x0aee} , 1269 | {"maltesecross" , 0x0af0} , 1270 | {"dagger" , 0x0af1} , 1271 | {"doubledagger" , 0x0af2} , 1272 | {"checkmark" , 0x0af3} , 1273 | {"ballotcross" , 0x0af4} , 1274 | {"musicalsharp" , 0x0af5} , 1275 | {"musicalflat" , 0x0af6} , 1276 | {"malesymbol" , 0x0af7} , 1277 | {"femalesymbol" , 0x0af8} , 1278 | {"telephone" , 0x0af9} , 1279 | {"telephonerecorder" , 0x0afa} , 1280 | {"phonographcopyright" , 0x0afb} , 1281 | {"caret" , 0x0afc} , 1282 | {"singlelowquotemark" , 0x0afd} , 1283 | {"doublelowquotemark" , 0x0afe} , 1284 | {"cursor" , 0x0aff} , 1285 | #endif 1286 | #ifdef XK_APL 1287 | {"leftcaret" , 0x0ba3} , 1288 | {"rightcaret" , 0x0ba6} , 1289 | {"downcaret" , 0x0ba8} , 1290 | {"upcaret" , 0x0ba9} , 1291 | {"overbar" , 0x0bc0} , 1292 | {"downtack" , 0x0bc2} , 1293 | {"upshoe" , 0x0bc3} , 1294 | {"downstile" , 0x0bc4} , 1295 | {"underbar" , 0x0bc6} , 1296 | {"jot" , 0x0bca} , 1297 | {"quad" , 0x0bcc} , 1298 | {"uptack" , 0x0bce} , 1299 | {"circle" , 0x0bcf} , 1300 | {"upstile" , 0x0bd3} , 1301 | {"downshoe" , 0x0bd6} , 1302 | {"rightshoe" , 0x0bd8} , 1303 | {"leftshoe" , 0x0bda} , 1304 | {"lefttack" , 0x0bdc} , 1305 | {"righttack" , 0x0bfc} , 1306 | #endif 1307 | #ifdef XK_HEBREW 1308 | {"hebrew_doublelowline" , 0x0cdf} , 1309 | {"hebrew_aleph" , 0x0ce0} , 1310 | {"hebrew_bet" , 0x0ce1} , 1311 | {"hebrew_beth" , 0x0ce1} , 1312 | {"hebrew_gimel" , 0x0ce2} , 1313 | {"hebrew_gimmel" , 0x0ce2} , 1314 | {"hebrew_dalet" , 0x0ce3} , 1315 | {"hebrew_daleth" , 0x0ce3} , 1316 | {"hebrew_he" , 0x0ce4} , 1317 | {"hebrew_waw" , 0x0ce5} , 1318 | {"hebrew_zain" , 0x0ce6} , 1319 | {"hebrew_zayin" , 0x0ce6} , 1320 | {"hebrew_chet" , 0x0ce7} , 1321 | {"hebrew_het" , 0x0ce7} , 1322 | {"hebrew_tet" , 0x0ce8} , 1323 | {"hebrew_teth" , 0x0ce8} , 1324 | {"hebrew_yod" , 0x0ce9} , 1325 | {"hebrew_finalkaph" , 0x0cea} , 1326 | {"hebrew_kaph" , 0x0ceb} , 1327 | {"hebrew_lamed" , 0x0cec} , 1328 | {"hebrew_finalmem" , 0x0ced} , 1329 | {"hebrew_mem" , 0x0cee} , 1330 | {"hebrew_finalnun" , 0x0cef} , 1331 | {"hebrew_nun" , 0x0cf0} , 1332 | {"hebrew_samech" , 0x0cf1} , 1333 | {"hebrew_samekh" , 0x0cf1} , 1334 | {"hebrew_ayin" , 0x0cf2} , 1335 | {"hebrew_finalpe" , 0x0cf3} , 1336 | {"hebrew_pe" , 0x0cf4} , 1337 | {"hebrew_finalzade" , 0x0cf5} , 1338 | {"hebrew_finalzadi" , 0x0cf5} , 1339 | {"hebrew_zade" , 0x0cf6} , 1340 | {"hebrew_zadi" , 0x0cf6} , 1341 | {"hebrew_qoph" , 0x0cf7} , 1342 | {"hebrew_kuf" , 0x0cf7} , 1343 | {"hebrew_resh" , 0x0cf8} , 1344 | {"hebrew_shin" , 0x0cf9} , 1345 | {"hebrew_taw" , 0x0cfa} , 1346 | {"hebrew_taf" , 0x0cfa} , 1347 | {"Hebrew_switch" , 0xff7e} , 1348 | #endif 1349 | #ifdef XK_THAI 1350 | {"Thai_kokai" , 0x0da1} , 1351 | {"Thai_khokhai" , 0x0da2} , 1352 | {"Thai_khokhuat" , 0x0da3} , 1353 | {"Thai_khokhwai" , 0x0da4} , 1354 | {"Thai_khokhon" , 0x0da5} , 1355 | {"Thai_khorakhang" , 0x0da6} , 1356 | {"Thai_ngongu" , 0x0da7} , 1357 | {"Thai_chochan" , 0x0da8} , 1358 | {"Thai_choching" , 0x0da9} , 1359 | {"Thai_chochang" , 0x0daa} , 1360 | {"Thai_soso" , 0x0dab} , 1361 | {"Thai_chochoe" , 0x0dac} , 1362 | {"Thai_yoying" , 0x0dad} , 1363 | {"Thai_dochada" , 0x0dae} , 1364 | {"Thai_topatak" , 0x0daf} , 1365 | {"Thai_thothan" , 0x0db0} , 1366 | {"Thai_thonangmontho" , 0x0db1} , 1367 | {"Thai_thophuthao" , 0x0db2} , 1368 | {"Thai_nonen" , 0x0db3} , 1369 | {"Thai_dodek" , 0x0db4} , 1370 | {"Thai_totao" , 0x0db5} , 1371 | {"Thai_thothung" , 0x0db6} , 1372 | {"Thai_thothahan" , 0x0db7} , 1373 | {"Thai_thothong" , 0x0db8} , 1374 | {"Thai_nonu" , 0x0db9} , 1375 | {"Thai_bobaimai" , 0x0dba} , 1376 | {"Thai_popla" , 0x0dbb} , 1377 | {"Thai_phophung" , 0x0dbc} , 1378 | {"Thai_fofa" , 0x0dbd} , 1379 | {"Thai_phophan" , 0x0dbe} , 1380 | {"Thai_fofan" , 0x0dbf} , 1381 | {"Thai_phosamphao" , 0x0dc0} , 1382 | {"Thai_moma" , 0x0dc1} , 1383 | {"Thai_yoyak" , 0x0dc2} , 1384 | {"Thai_rorua" , 0x0dc3} , 1385 | {"Thai_ru" , 0x0dc4} , 1386 | {"Thai_loling" , 0x0dc5} , 1387 | {"Thai_lu" , 0x0dc6} , 1388 | {"Thai_wowaen" , 0x0dc7} , 1389 | {"Thai_sosala" , 0x0dc8} , 1390 | {"Thai_sorusi" , 0x0dc9} , 1391 | {"Thai_sosua" , 0x0dca} , 1392 | {"Thai_hohip" , 0x0dcb} , 1393 | {"Thai_lochula" , 0x0dcc} , 1394 | {"Thai_oang" , 0x0dcd} , 1395 | {"Thai_honokhuk" , 0x0dce} , 1396 | {"Thai_paiyannoi" , 0x0dcf} , 1397 | {"Thai_saraa" , 0x0dd0} , 1398 | {"Thai_maihanakat" , 0x0dd1} , 1399 | {"Thai_saraaa" , 0x0dd2} , 1400 | {"Thai_saraam" , 0x0dd3} , 1401 | {"Thai_sarai" , 0x0dd4} , 1402 | {"Thai_saraii" , 0x0dd5} , 1403 | {"Thai_saraue" , 0x0dd6} , 1404 | {"Thai_sarauee" , 0x0dd7} , 1405 | {"Thai_sarau" , 0x0dd8} , 1406 | {"Thai_sarauu" , 0x0dd9} , 1407 | {"Thai_phinthu" , 0x0dda} , 1408 | {"Thai_maihanakat_maitho" , 0x0dde} , 1409 | {"Thai_baht" , 0x0ddf} , 1410 | {"Thai_sarae" , 0x0de0} , 1411 | {"Thai_saraae" , 0x0de1} , 1412 | {"Thai_sarao" , 0x0de2} , 1413 | {"Thai_saraaimaimuan" , 0x0de3} , 1414 | {"Thai_saraaimaimalai" , 0x0de4} , 1415 | {"Thai_lakkhangyao" , 0x0de5} , 1416 | {"Thai_maiyamok" , 0x0de6} , 1417 | {"Thai_maitaikhu" , 0x0de7} , 1418 | {"Thai_maiek" , 0x0de8} , 1419 | {"Thai_maitho" , 0x0de9} , 1420 | {"Thai_maitri" , 0x0dea} , 1421 | {"Thai_maichattawa" , 0x0deb} , 1422 | {"Thai_thanthakhat" , 0x0dec} , 1423 | {"Thai_nikhahit" , 0x0ded} , 1424 | {"Thai_leksun" , 0x0df0} , 1425 | {"Thai_leknung" , 0x0df1} , 1426 | {"Thai_leksong" , 0x0df2} , 1427 | {"Thai_leksam" , 0x0df3} , 1428 | {"Thai_leksi" , 0x0df4} , 1429 | {"Thai_lekha" , 0x0df5} , 1430 | {"Thai_lekhok" , 0x0df6} , 1431 | {"Thai_lekchet" , 0x0df7} , 1432 | {"Thai_lekpaet" , 0x0df8} , 1433 | {"Thai_lekkao" , 0x0df9} , 1434 | #endif 1435 | #ifdef XK_KOREAN 1436 | {"Hangul" , 0xff31} , 1437 | {"Hangul_Start" , 0xff32} , 1438 | {"Hangul_End" , 0xff33} , 1439 | {"Hangul_Hanja" , 0xff34} , 1440 | {"Hangul_Jamo" , 0xff35} , 1441 | {"Hangul_Romaja" , 0xff36} , 1442 | {"Hangul_Codeinput" , 0xff37} , 1443 | {"Hangul_Jeonja" , 0xff38} , 1444 | {"Hangul_Banja" , 0xff39} , 1445 | {"Hangul_PreHanja" , 0xff3a} , 1446 | {"Hangul_PostHanja" , 0xff3b} , 1447 | {"Hangul_SingleCandidate" , 0xff3c} , 1448 | {"Hangul_MultipleCandidate" , 0xff3d} , 1449 | {"Hangul_PreviousCandidate" , 0xff3e} , 1450 | {"Hangul_Special" , 0xff3f} , 1451 | {"Hangul_switch" , 0xff7e} , 1452 | {"Hangul_Kiyeog" , 0x0ea1} , 1453 | {"Hangul_SsangKiyeog" , 0x0ea2} , 1454 | {"Hangul_KiyeogSios" , 0x0ea3} , 1455 | {"Hangul_Nieun" , 0x0ea4} , 1456 | {"Hangul_NieunJieuj" , 0x0ea5} , 1457 | {"Hangul_NieunHieuh" , 0x0ea6} , 1458 | {"Hangul_Dikeud" , 0x0ea7} , 1459 | {"Hangul_SsangDikeud" , 0x0ea8} , 1460 | {"Hangul_Rieul" , 0x0ea9} , 1461 | {"Hangul_RieulKiyeog" , 0x0eaa} , 1462 | {"Hangul_RieulMieum" , 0x0eab} , 1463 | {"Hangul_RieulPieub" , 0x0eac} , 1464 | {"Hangul_RieulSios" , 0x0ead} , 1465 | {"Hangul_RieulTieut" , 0x0eae} , 1466 | {"Hangul_RieulPhieuf" , 0x0eaf} , 1467 | {"Hangul_RieulHieuh" , 0x0eb0} , 1468 | {"Hangul_Mieum" , 0x0eb1} , 1469 | {"Hangul_Pieub" , 0x0eb2} , 1470 | {"Hangul_SsangPieub" , 0x0eb3} , 1471 | {"Hangul_PieubSios" , 0x0eb4} , 1472 | {"Hangul_Sios" , 0x0eb5} , 1473 | {"Hangul_SsangSios" , 0x0eb6} , 1474 | {"Hangul_Ieung" , 0x0eb7} , 1475 | {"Hangul_Jieuj" , 0x0eb8} , 1476 | {"Hangul_SsangJieuj" , 0x0eb9} , 1477 | {"Hangul_Cieuc" , 0x0eba} , 1478 | {"Hangul_Khieuq" , 0x0ebb} , 1479 | {"Hangul_Tieut" , 0x0ebc} , 1480 | {"Hangul_Phieuf" , 0x0ebd} , 1481 | {"Hangul_Hieuh" , 0x0ebe} , 1482 | {"Hangul_A" , 0x0ebf} , 1483 | {"Hangul_AE" , 0x0ec0} , 1484 | {"Hangul_YA" , 0x0ec1} , 1485 | {"Hangul_YAE" , 0x0ec2} , 1486 | {"Hangul_EO" , 0x0ec3} , 1487 | {"Hangul_E" , 0x0ec4} , 1488 | {"Hangul_YEO" , 0x0ec5} , 1489 | {"Hangul_YE" , 0x0ec6} , 1490 | {"Hangul_O" , 0x0ec7} , 1491 | {"Hangul_WA" , 0x0ec8} , 1492 | {"Hangul_WAE" , 0x0ec9} , 1493 | {"Hangul_OE" , 0x0eca} , 1494 | {"Hangul_YO" , 0x0ecb} , 1495 | {"Hangul_U" , 0x0ecc} , 1496 | {"Hangul_WEO" , 0x0ecd} , 1497 | {"Hangul_WE" , 0x0ece} , 1498 | {"Hangul_WI" , 0x0ecf} , 1499 | {"Hangul_YU" , 0x0ed0} , 1500 | {"Hangul_EU" , 0x0ed1} , 1501 | {"Hangul_YI" , 0x0ed2} , 1502 | {"Hangul_I" , 0x0ed3} , 1503 | {"Hangul_J_Kiyeog" , 0x0ed4} , 1504 | {"Hangul_J_SsangKiyeog" , 0x0ed5} , 1505 | {"Hangul_J_KiyeogSios" , 0x0ed6} , 1506 | {"Hangul_J_Nieun" , 0x0ed7} , 1507 | {"Hangul_J_NieunJieuj" , 0x0ed8} , 1508 | {"Hangul_J_NieunHieuh" , 0x0ed9} , 1509 | {"Hangul_J_Dikeud" , 0x0eda} , 1510 | {"Hangul_J_Rieul" , 0x0edb} , 1511 | {"Hangul_J_RieulKiyeog" , 0x0edc} , 1512 | {"Hangul_J_RieulMieum" , 0x0edd} , 1513 | {"Hangul_J_RieulPieub" , 0x0ede} , 1514 | {"Hangul_J_RieulSios" , 0x0edf} , 1515 | {"Hangul_J_RieulTieut" , 0x0ee0} , 1516 | {"Hangul_J_RieulPhieuf" , 0x0ee1} , 1517 | {"Hangul_J_RieulHieuh" , 0x0ee2} , 1518 | {"Hangul_J_Mieum" , 0x0ee3} , 1519 | {"Hangul_J_Pieub" , 0x0ee4} , 1520 | {"Hangul_J_PieubSios" , 0x0ee5} , 1521 | {"Hangul_J_Sios" , 0x0ee6} , 1522 | {"Hangul_J_SsangSios" , 0x0ee7} , 1523 | {"Hangul_J_Ieung" , 0x0ee8} , 1524 | {"Hangul_J_Jieuj" , 0x0ee9} , 1525 | {"Hangul_J_Cieuc" , 0x0eea} , 1526 | {"Hangul_J_Khieuq" , 0x0eeb} , 1527 | {"Hangul_J_Tieut" , 0x0eec} , 1528 | {"Hangul_J_Phieuf" , 0x0eed} , 1529 | {"Hangul_J_Hieuh" , 0x0eee} , 1530 | {"Hangul_RieulYeorinHieuh" , 0x0eef} , 1531 | {"Hangul_SunkyeongeumMieum" , 0x0ef0} , 1532 | {"Hangul_SunkyeongeumPieub" , 0x0ef1} , 1533 | {"Hangul_PanSios" , 0x0ef2} , 1534 | {"Hangul_KkogjiDalrinIeung" , 0x0ef3} , 1535 | {"Hangul_SunkyeongeumPhieuf" , 0x0ef4} , 1536 | {"Hangul_YeorinHieuh" , 0x0ef5} , 1537 | {"Hangul_AraeA" , 0x0ef6} , 1538 | {"Hangul_AraeAE" , 0x0ef7} , 1539 | {"Hangul_J_PanSios" , 0x0ef8} , 1540 | {"Hangul_J_KkogjiDalrinIeung" , 0x0ef9} , 1541 | {"Hangul_J_YeorinHieuh" , 0x0efa} , 1542 | {"Korean_Won" , 0x0eff} , 1543 | #endif 1544 | #ifdef XK_ARMENIAN 1545 | {"Armenian_ligature_ew" , 0x1000587} , 1546 | {"Armenian_full_stop" , 0x1000589} , 1547 | {"Armenian_verjaket" , 0x1000589} , 1548 | {"Armenian_separation_mark" , 0x100055d} , 1549 | {"Armenian_but" , 0x100055d} , 1550 | {"Armenian_hyphen" , 0x100058a} , 1551 | {"Armenian_yentamna" , 0x100058a} , 1552 | {"Armenian_exclam" , 0x100055c} , 1553 | {"Armenian_amanak" , 0x100055c} , 1554 | {"Armenian_accent" , 0x100055b} , 1555 | {"Armenian_shesht" , 0x100055b} , 1556 | {"Armenian_question" , 0x100055e} , 1557 | {"Armenian_paruyk" , 0x100055e} , 1558 | {"Armenian_AYB" , 0x1000531} , 1559 | {"Armenian_ayb" , 0x1000561} , 1560 | {"Armenian_BEN" , 0x1000532} , 1561 | {"Armenian_ben" , 0x1000562} , 1562 | {"Armenian_GIM" , 0x1000533} , 1563 | {"Armenian_gim" , 0x1000563} , 1564 | {"Armenian_DA" , 0x1000534} , 1565 | {"Armenian_da" , 0x1000564} , 1566 | {"Armenian_YECH" , 0x1000535} , 1567 | {"Armenian_yech" , 0x1000565} , 1568 | {"Armenian_ZA" , 0x1000536} , 1569 | {"Armenian_za" , 0x1000566} , 1570 | {"Armenian_E" , 0x1000537} , 1571 | {"Armenian_e" , 0x1000567} , 1572 | {"Armenian_AT" , 0x1000538} , 1573 | {"Armenian_at" , 0x1000568} , 1574 | {"Armenian_TO" , 0x1000539} , 1575 | {"Armenian_to" , 0x1000569} , 1576 | {"Armenian_ZHE" , 0x100053a} , 1577 | {"Armenian_zhe" , 0x100056a} , 1578 | {"Armenian_INI" , 0x100053b} , 1579 | {"Armenian_ini" , 0x100056b} , 1580 | {"Armenian_LYUN" , 0x100053c} , 1581 | {"Armenian_lyun" , 0x100056c} , 1582 | {"Armenian_KHE" , 0x100053d} , 1583 | {"Armenian_khe" , 0x100056d} , 1584 | {"Armenian_TSA" , 0x100053e} , 1585 | {"Armenian_tsa" , 0x100056e} , 1586 | {"Armenian_KEN" , 0x100053f} , 1587 | {"Armenian_ken" , 0x100056f} , 1588 | {"Armenian_HO" , 0x1000540} , 1589 | {"Armenian_ho" , 0x1000570} , 1590 | {"Armenian_DZA" , 0x1000541} , 1591 | {"Armenian_dza" , 0x1000571} , 1592 | {"Armenian_GHAT" , 0x1000542} , 1593 | {"Armenian_ghat" , 0x1000572} , 1594 | {"Armenian_TCHE" , 0x1000543} , 1595 | {"Armenian_tche" , 0x1000573} , 1596 | {"Armenian_MEN" , 0x1000544} , 1597 | {"Armenian_men" , 0x1000574} , 1598 | {"Armenian_HI" , 0x1000545} , 1599 | {"Armenian_hi" , 0x1000575} , 1600 | {"Armenian_NU" , 0x1000546} , 1601 | {"Armenian_nu" , 0x1000576} , 1602 | {"Armenian_SHA" , 0x1000547} , 1603 | {"Armenian_sha" , 0x1000577} , 1604 | {"Armenian_VO" , 0x1000548} , 1605 | {"Armenian_vo" , 0x1000578} , 1606 | {"Armenian_CHA" , 0x1000549} , 1607 | {"Armenian_cha" , 0x1000579} , 1608 | {"Armenian_PE" , 0x100054a} , 1609 | {"Armenian_pe" , 0x100057a} , 1610 | {"Armenian_JE" , 0x100054b} , 1611 | {"Armenian_je" , 0x100057b} , 1612 | {"Armenian_RA" , 0x100054c} , 1613 | {"Armenian_ra" , 0x100057c} , 1614 | {"Armenian_SE" , 0x100054d} , 1615 | {"Armenian_se" , 0x100057d} , 1616 | {"Armenian_VEV" , 0x100054e} , 1617 | {"Armenian_vev" , 0x100057e} , 1618 | {"Armenian_TYUN" , 0x100054f} , 1619 | {"Armenian_tyun" , 0x100057f} , 1620 | {"Armenian_RE" , 0x1000550} , 1621 | {"Armenian_re" , 0x1000580} , 1622 | {"Armenian_TSO" , 0x1000551} , 1623 | {"Armenian_tso" , 0x1000581} , 1624 | {"Armenian_VYUN" , 0x1000552} , 1625 | {"Armenian_vyun" , 0x1000582} , 1626 | {"Armenian_PYUR" , 0x1000553} , 1627 | {"Armenian_pyur" , 0x1000583} , 1628 | {"Armenian_KE" , 0x1000554} , 1629 | {"Armenian_ke" , 0x1000584} , 1630 | {"Armenian_O" , 0x1000555} , 1631 | {"Armenian_o" , 0x1000585} , 1632 | {"Armenian_FE" , 0x1000556} , 1633 | {"Armenian_fe" , 0x1000586} , 1634 | {"Armenian_apostrophe" , 0x100055a} , 1635 | #endif 1636 | #ifdef XK_GEORGIAN 1637 | {"Georgian_an" , 0x10010d0} , 1638 | {"Georgian_ban" , 0x10010d1} , 1639 | {"Georgian_gan" , 0x10010d2} , 1640 | {"Georgian_don" , 0x10010d3} , 1641 | {"Georgian_en" , 0x10010d4} , 1642 | {"Georgian_vin" , 0x10010d5} , 1643 | {"Georgian_zen" , 0x10010d6} , 1644 | {"Georgian_tan" , 0x10010d7} , 1645 | {"Georgian_in" , 0x10010d8} , 1646 | {"Georgian_kan" , 0x10010d9} , 1647 | {"Georgian_las" , 0x10010da} , 1648 | {"Georgian_man" , 0x10010db} , 1649 | {"Georgian_nar" , 0x10010dc} , 1650 | {"Georgian_on" , 0x10010dd} , 1651 | {"Georgian_par" , 0x10010de} , 1652 | {"Georgian_zhar" , 0x10010df} , 1653 | {"Georgian_rae" , 0x10010e0} , 1654 | {"Georgian_san" , 0x10010e1} , 1655 | {"Georgian_tar" , 0x10010e2} , 1656 | {"Georgian_un" , 0x10010e3} , 1657 | {"Georgian_phar" , 0x10010e4} , 1658 | {"Georgian_khar" , 0x10010e5} , 1659 | {"Georgian_ghan" , 0x10010e6} , 1660 | {"Georgian_qar" , 0x10010e7} , 1661 | {"Georgian_shin" , 0x10010e8} , 1662 | {"Georgian_chin" , 0x10010e9} , 1663 | {"Georgian_can" , 0x10010ea} , 1664 | {"Georgian_jil" , 0x10010eb} , 1665 | {"Georgian_cil" , 0x10010ec} , 1666 | {"Georgian_char" , 0x10010ed} , 1667 | {"Georgian_xan" , 0x10010ee} , 1668 | {"Georgian_jhan" , 0x10010ef} , 1669 | {"Georgian_hae" , 0x10010f0} , 1670 | {"Georgian_he" , 0x10010f1} , 1671 | {"Georgian_hie" , 0x10010f2} , 1672 | {"Georgian_we" , 0x10010f3} , 1673 | {"Georgian_har" , 0x10010f4} , 1674 | {"Georgian_hoe" , 0x10010f5} , 1675 | {"Georgian_fi" , 0x10010f6} , 1676 | #endif 1677 | #ifdef XK_CAUCASUS 1678 | {"Xabovedot" , 0x1001e8a} , 1679 | {"Ibreve" , 0x100012c} , 1680 | {"Zstroke" , 0x10001b5} , 1681 | {"Gcaron" , 0x10001e6} , 1682 | {"Ocaron" , 0x10001d1} , 1683 | {"Obarred" , 0x100019f} , 1684 | {"xabovedot" , 0x1001e8b} , 1685 | {"ibreve" , 0x100012d} , 1686 | {"zstroke" , 0x10001b6} , 1687 | {"gcaron" , 0x10001e7} , 1688 | {"ocaron" , 0x10001d2} , 1689 | {"obarred" , 0x1000275} , 1690 | {"SCHWA" , 0x100018f} , 1691 | {"schwa" , 0x1000259} , 1692 | {"EZH" , 0x10001b7} , 1693 | {"ezh" , 0x1000292} , 1694 | {"Lbelowdot" , 0x1001e36} , 1695 | {"lbelowdot" , 0x1001e37} , 1696 | #endif 1697 | #ifdef XK_VIETNAMESE 1698 | {"Abelowdot" , 0x1001ea0} , 1699 | {"abelowdot" , 0x1001ea1} , 1700 | {"Ahook" , 0x1001ea2} , 1701 | {"ahook" , 0x1001ea3} , 1702 | {"Acircumflexacute" , 0x1001ea4} , 1703 | {"acircumflexacute" , 0x1001ea5} , 1704 | {"Acircumflexgrave" , 0x1001ea6} , 1705 | {"acircumflexgrave" , 0x1001ea7} , 1706 | {"Acircumflexhook" , 0x1001ea8} , 1707 | {"acircumflexhook" , 0x1001ea9} , 1708 | {"Acircumflextilde" , 0x1001eaa} , 1709 | {"acircumflextilde" , 0x1001eab} , 1710 | {"Acircumflexbelowdot" , 0x1001eac} , 1711 | {"acircumflexbelowdot" , 0x1001ead} , 1712 | {"Abreveacute" , 0x1001eae} , 1713 | {"abreveacute" , 0x1001eaf} , 1714 | {"Abrevegrave" , 0x1001eb0} , 1715 | {"abrevegrave" , 0x1001eb1} , 1716 | {"Abrevehook" , 0x1001eb2} , 1717 | {"abrevehook" , 0x1001eb3} , 1718 | {"Abrevetilde" , 0x1001eb4} , 1719 | {"abrevetilde" , 0x1001eb5} , 1720 | {"Abrevebelowdot" , 0x1001eb6} , 1721 | {"abrevebelowdot" , 0x1001eb7} , 1722 | {"Ebelowdot" , 0x1001eb8} , 1723 | {"ebelowdot" , 0x1001eb9} , 1724 | {"Ehook" , 0x1001eba} , 1725 | {"ehook" , 0x1001ebb} , 1726 | {"Etilde" , 0x1001ebc} , 1727 | {"etilde" , 0x1001ebd} , 1728 | {"Ecircumflexacute" , 0x1001ebe} , 1729 | {"ecircumflexacute" , 0x1001ebf} , 1730 | {"Ecircumflexgrave" , 0x1001ec0} , 1731 | {"ecircumflexgrave" , 0x1001ec1} , 1732 | {"Ecircumflexhook" , 0x1001ec2} , 1733 | {"ecircumflexhook" , 0x1001ec3} , 1734 | {"Ecircumflextilde" , 0x1001ec4} , 1735 | {"ecircumflextilde" , 0x1001ec5} , 1736 | {"Ecircumflexbelowdot" , 0x1001ec6} , 1737 | {"ecircumflexbelowdot" , 0x1001ec7} , 1738 | {"Ihook" , 0x1001ec8} , 1739 | {"ihook" , 0x1001ec9} , 1740 | {"Ibelowdot" , 0x1001eca} , 1741 | {"ibelowdot" , 0x1001ecb} , 1742 | {"Obelowdot" , 0x1001ecc} , 1743 | {"obelowdot" , 0x1001ecd} , 1744 | {"Ohook" , 0x1001ece} , 1745 | {"ohook" , 0x1001ecf} , 1746 | {"Ocircumflexacute" , 0x1001ed0} , 1747 | {"ocircumflexacute" , 0x1001ed1} , 1748 | {"Ocircumflexgrave" , 0x1001ed2} , 1749 | {"ocircumflexgrave" , 0x1001ed3} , 1750 | {"Ocircumflexhook" , 0x1001ed4} , 1751 | {"ocircumflexhook" , 0x1001ed5} , 1752 | {"Ocircumflextilde" , 0x1001ed6} , 1753 | {"ocircumflextilde" , 0x1001ed7} , 1754 | {"Ocircumflexbelowdot" , 0x1001ed8} , 1755 | {"ocircumflexbelowdot" , 0x1001ed9} , 1756 | {"Ohornacute" , 0x1001eda} , 1757 | {"ohornacute" , 0x1001edb} , 1758 | {"Ohorngrave" , 0x1001edc} , 1759 | {"ohorngrave" , 0x1001edd} , 1760 | {"Ohornhook" , 0x1001ede} , 1761 | {"ohornhook" , 0x1001edf} , 1762 | {"Ohorntilde" , 0x1001ee0} , 1763 | {"ohorntilde" , 0x1001ee1} , 1764 | {"Ohornbelowdot" , 0x1001ee2} , 1765 | {"ohornbelowdot" , 0x1001ee3} , 1766 | {"Ubelowdot" , 0x1001ee4} , 1767 | {"ubelowdot" , 0x1001ee5} , 1768 | {"Uhook" , 0x1001ee6} , 1769 | {"uhook" , 0x1001ee7} , 1770 | {"Uhornacute" , 0x1001ee8} , 1771 | {"uhornacute" , 0x1001ee9} , 1772 | {"Uhorngrave" , 0x1001eea} , 1773 | {"uhorngrave" , 0x1001eeb} , 1774 | {"Uhornhook" , 0x1001eec} , 1775 | {"uhornhook" , 0x1001eed} , 1776 | {"Uhorntilde" , 0x1001eee} , 1777 | {"uhorntilde" , 0x1001eef} , 1778 | {"Uhornbelowdot" , 0x1001ef0} , 1779 | {"uhornbelowdot" , 0x1001ef1} , 1780 | {"Ybelowdot" , 0x1001ef4} , 1781 | {"ybelowdot" , 0x1001ef5} , 1782 | {"Yhook" , 0x1001ef6} , 1783 | {"yhook" , 0x1001ef7} , 1784 | {"Ytilde" , 0x1001ef8} , 1785 | {"ytilde" , 0x1001ef9} , 1786 | {"Ohorn" , 0x10001a0} , 1787 | {"ohorn" , 0x10001a1} , 1788 | {"Uhorn" , 0x10001af} , 1789 | {"uhorn" , 0x10001b0} , 1790 | #endif 1791 | #ifdef XK_CURRENCY 1792 | {"EcuSign" , 0x10020a0} , 1793 | {"ColonSign" , 0x10020a1} , 1794 | {"CruzeiroSign" , 0x10020a2} , 1795 | {"FFrancSign" , 0x10020a3} , 1796 | {"LiraSign" , 0x10020a4} , 1797 | {"MillSign" , 0x10020a5} , 1798 | {"NairaSign" , 0x10020a6} , 1799 | {"PesetaSign" , 0x10020a7} , 1800 | {"RupeeSign" , 0x10020a8} , 1801 | {"WonSign" , 0x10020a9} , 1802 | {"NewSheqelSign" , 0x10020aa} , 1803 | {"DongSign" , 0x10020ab} , 1804 | {"EuroSign" , 0x20ac} , 1805 | #endif 1806 | #ifdef XK_MATHEMATICAL 1807 | {"zerosuperior" , 0x1002070} , 1808 | {"foursuperior" , 0x1002074} , 1809 | {"fivesuperior" , 0x1002075} , 1810 | {"sixsuperior" , 0x1002076} , 1811 | {"sevensuperior" , 0x1002077} , 1812 | {"eightsuperior" , 0x1002078} , 1813 | {"ninesuperior" , 0x1002079} , 1814 | {"zerosubscript" , 0x1002080} , 1815 | {"onesubscript" , 0x1002081} , 1816 | {"twosubscript" , 0x1002082} , 1817 | {"threesubscript" , 0x1002083} , 1818 | {"foursubscript" , 0x1002084} , 1819 | {"fivesubscript" , 0x1002085} , 1820 | {"sixsubscript" , 0x1002086} , 1821 | {"sevensubscript" , 0x1002087} , 1822 | {"eightsubscript" , 0x1002088} , 1823 | {"ninesubscript" , 0x1002089} , 1824 | {"partdifferential" , 0x1002202} , 1825 | {"emptyset" , 0x1002205} , 1826 | {"elementof" , 0x1002208} , 1827 | {"notelementof" , 0x1002209} , 1828 | {"containsas" , 0x100220B} , 1829 | {"squareroot" , 0x100221A} , 1830 | {"cuberoot" , 0x100221B} , 1831 | {"fourthroot" , 0x100221C} , 1832 | {"dintegral" , 0x100222C} , 1833 | {"tintegral" , 0x100222D} , 1834 | {"because" , 0x1002235} , 1835 | {"approxeq" , 0x1002248} , 1836 | {"notapproxeq" , 0x1002247} , 1837 | {"notidentical" , 0x1002262} , 1838 | {"stricteq" , 0x1002263} , 1839 | #endif 1840 | #ifdef XK_BRAILLE 1841 | {"braille_dot_1" , 0xfff1} , 1842 | {"braille_dot_2" , 0xfff2} , 1843 | {"braille_dot_3" , 0xfff3} , 1844 | {"braille_dot_4" , 0xfff4} , 1845 | {"braille_dot_5" , 0xfff5} , 1846 | {"braille_dot_6" , 0xfff6} , 1847 | {"braille_dot_7" , 0xfff7} , 1848 | {"braille_dot_8" , 0xfff8} , 1849 | {"braille_dot_9" , 0xfff9} , 1850 | {"braille_dot_10" , 0xfffa} , 1851 | {"braille_blank" , 0x1002800} , 1852 | {"braille_dots_1" , 0x1002801} , 1853 | {"braille_dots_2" , 0x1002802} , 1854 | {"braille_dots_12" , 0x1002803} , 1855 | {"braille_dots_3" , 0x1002804} , 1856 | {"braille_dots_13" , 0x1002805} , 1857 | {"braille_dots_23" , 0x1002806} , 1858 | {"braille_dots_123" , 0x1002807} , 1859 | {"braille_dots_4" , 0x1002808} , 1860 | {"braille_dots_14" , 0x1002809} , 1861 | {"braille_dots_24" , 0x100280a} , 1862 | {"braille_dots_124" , 0x100280b} , 1863 | {"braille_dots_34" , 0x100280c} , 1864 | {"braille_dots_134" , 0x100280d} , 1865 | {"braille_dots_234" , 0x100280e} , 1866 | {"braille_dots_1234" , 0x100280f} , 1867 | {"braille_dots_5" , 0x1002810} , 1868 | {"braille_dots_15" , 0x1002811} , 1869 | {"braille_dots_25" , 0x1002812} , 1870 | {"braille_dots_125" , 0x1002813} , 1871 | {"braille_dots_35" , 0x1002814} , 1872 | {"braille_dots_135" , 0x1002815} , 1873 | {"braille_dots_235" , 0x1002816} , 1874 | {"braille_dots_1235" , 0x1002817} , 1875 | {"braille_dots_45" , 0x1002818} , 1876 | {"braille_dots_145" , 0x1002819} , 1877 | {"braille_dots_245" , 0x100281a} , 1878 | {"braille_dots_1245" , 0x100281b} , 1879 | {"braille_dots_345" , 0x100281c} , 1880 | {"braille_dots_1345" , 0x100281d} , 1881 | {"braille_dots_2345" , 0x100281e} , 1882 | {"braille_dots_12345" , 0x100281f} , 1883 | {"braille_dots_6" , 0x1002820} , 1884 | {"braille_dots_16" , 0x1002821} , 1885 | {"braille_dots_26" , 0x1002822} , 1886 | {"braille_dots_126" , 0x1002823} , 1887 | {"braille_dots_36" , 0x1002824} , 1888 | {"braille_dots_136" , 0x1002825} , 1889 | {"braille_dots_236" , 0x1002826} , 1890 | {"braille_dots_1236" , 0x1002827} , 1891 | {"braille_dots_46" , 0x1002828} , 1892 | {"braille_dots_146" , 0x1002829} , 1893 | {"braille_dots_246" , 0x100282a} , 1894 | {"braille_dots_1246" , 0x100282b} , 1895 | {"braille_dots_346" , 0x100282c} , 1896 | {"braille_dots_1346" , 0x100282d} , 1897 | {"braille_dots_2346" , 0x100282e} , 1898 | {"braille_dots_12346" , 0x100282f} , 1899 | {"braille_dots_56" , 0x1002830} , 1900 | {"braille_dots_156" , 0x1002831} , 1901 | {"braille_dots_256" , 0x1002832} , 1902 | {"braille_dots_1256" , 0x1002833} , 1903 | {"braille_dots_356" , 0x1002834} , 1904 | {"braille_dots_1356" , 0x1002835} , 1905 | {"braille_dots_2356" , 0x1002836} , 1906 | {"braille_dots_12356" , 0x1002837} , 1907 | {"braille_dots_456" , 0x1002838} , 1908 | {"braille_dots_1456" , 0x1002839} , 1909 | {"braille_dots_2456" , 0x100283a} , 1910 | {"braille_dots_12456" , 0x100283b} , 1911 | {"braille_dots_3456" , 0x100283c} , 1912 | {"braille_dots_13456" , 0x100283d} , 1913 | {"braille_dots_23456" , 0x100283e} , 1914 | {"braille_dots_123456" , 0x100283f} , 1915 | {"braille_dots_7" , 0x1002840} , 1916 | {"braille_dots_17" , 0x1002841} , 1917 | {"braille_dots_27" , 0x1002842} , 1918 | {"braille_dots_127" , 0x1002843} , 1919 | {"braille_dots_37" , 0x1002844} , 1920 | {"braille_dots_137" , 0x1002845} , 1921 | {"braille_dots_237" , 0x1002846} , 1922 | {"braille_dots_1237" , 0x1002847} , 1923 | {"braille_dots_47" , 0x1002848} , 1924 | {"braille_dots_147" , 0x1002849} , 1925 | {"braille_dots_247" , 0x100284a} , 1926 | {"braille_dots_1247" , 0x100284b} , 1927 | {"braille_dots_347" , 0x100284c} , 1928 | {"braille_dots_1347" , 0x100284d} , 1929 | {"braille_dots_2347" , 0x100284e} , 1930 | {"braille_dots_12347" , 0x100284f} , 1931 | {"braille_dots_57" , 0x1002850} , 1932 | {"braille_dots_157" , 0x1002851} , 1933 | {"braille_dots_257" , 0x1002852} , 1934 | {"braille_dots_1257" , 0x1002853} , 1935 | {"braille_dots_357" , 0x1002854} , 1936 | {"braille_dots_1357" , 0x1002855} , 1937 | {"braille_dots_2357" , 0x1002856} , 1938 | {"braille_dots_12357" , 0x1002857} , 1939 | {"braille_dots_457" , 0x1002858} , 1940 | {"braille_dots_1457" , 0x1002859} , 1941 | {"braille_dots_2457" , 0x100285a} , 1942 | {"braille_dots_12457" , 0x100285b} , 1943 | {"braille_dots_3457" , 0x100285c} , 1944 | {"braille_dots_13457" , 0x100285d} , 1945 | {"braille_dots_23457" , 0x100285e} , 1946 | {"braille_dots_123457" , 0x100285f} , 1947 | {"braille_dots_67" , 0x1002860} , 1948 | {"braille_dots_167" , 0x1002861} , 1949 | {"braille_dots_267" , 0x1002862} , 1950 | {"braille_dots_1267" , 0x1002863} , 1951 | {"braille_dots_367" , 0x1002864} , 1952 | {"braille_dots_1367" , 0x1002865} , 1953 | {"braille_dots_2367" , 0x1002866} , 1954 | {"braille_dots_12367" , 0x1002867} , 1955 | {"braille_dots_467" , 0x1002868} , 1956 | {"braille_dots_1467" , 0x1002869} , 1957 | {"braille_dots_2467" , 0x100286a} , 1958 | {"braille_dots_12467" , 0x100286b} , 1959 | {"braille_dots_3467" , 0x100286c} , 1960 | {"braille_dots_13467" , 0x100286d} , 1961 | {"braille_dots_23467" , 0x100286e} , 1962 | {"braille_dots_123467" , 0x100286f} , 1963 | {"braille_dots_567" , 0x1002870} , 1964 | {"braille_dots_1567" , 0x1002871} , 1965 | {"braille_dots_2567" , 0x1002872} , 1966 | {"braille_dots_12567" , 0x1002873} , 1967 | {"braille_dots_3567" , 0x1002874} , 1968 | {"braille_dots_13567" , 0x1002875} , 1969 | {"braille_dots_23567" , 0x1002876} , 1970 | {"braille_dots_123567" , 0x1002877} , 1971 | {"braille_dots_4567" , 0x1002878} , 1972 | {"braille_dots_14567" , 0x1002879} , 1973 | {"braille_dots_24567" , 0x100287a} , 1974 | {"braille_dots_124567" , 0x100287b} , 1975 | {"braille_dots_34567" , 0x100287c} , 1976 | {"braille_dots_134567" , 0x100287d} , 1977 | {"braille_dots_234567" , 0x100287e} , 1978 | {"braille_dots_1234567" , 0x100287f} , 1979 | {"braille_dots_8" , 0x1002880} , 1980 | {"braille_dots_18" , 0x1002881} , 1981 | {"braille_dots_28" , 0x1002882} , 1982 | {"braille_dots_128" , 0x1002883} , 1983 | {"braille_dots_38" , 0x1002884} , 1984 | {"braille_dots_138" , 0x1002885} , 1985 | {"braille_dots_238" , 0x1002886} , 1986 | {"braille_dots_1238" , 0x1002887} , 1987 | {"braille_dots_48" , 0x1002888} , 1988 | {"braille_dots_148" , 0x1002889} , 1989 | {"braille_dots_248" , 0x100288a} , 1990 | {"braille_dots_1248" , 0x100288b} , 1991 | {"braille_dots_348" , 0x100288c} , 1992 | {"braille_dots_1348" , 0x100288d} , 1993 | {"braille_dots_2348" , 0x100288e} , 1994 | {"braille_dots_12348" , 0x100288f} , 1995 | {"braille_dots_58" , 0x1002890} , 1996 | {"braille_dots_158" , 0x1002891} , 1997 | {"braille_dots_258" , 0x1002892} , 1998 | {"braille_dots_1258" , 0x1002893} , 1999 | {"braille_dots_358" , 0x1002894} , 2000 | {"braille_dots_1358" , 0x1002895} , 2001 | {"braille_dots_2358" , 0x1002896} , 2002 | {"braille_dots_12358" , 0x1002897} , 2003 | {"braille_dots_458" , 0x1002898} , 2004 | {"braille_dots_1458" , 0x1002899} , 2005 | {"braille_dots_2458" , 0x100289a} , 2006 | {"braille_dots_12458" , 0x100289b} , 2007 | {"braille_dots_3458" , 0x100289c} , 2008 | {"braille_dots_13458" , 0x100289d} , 2009 | {"braille_dots_23458" , 0x100289e} , 2010 | {"braille_dots_123458" , 0x100289f} , 2011 | {"braille_dots_68" , 0x10028a0} , 2012 | {"braille_dots_168" , 0x10028a1} , 2013 | {"braille_dots_268" , 0x10028a2} , 2014 | {"braille_dots_1268" , 0x10028a3} , 2015 | {"braille_dots_368" , 0x10028a4} , 2016 | {"braille_dots_1368" , 0x10028a5} , 2017 | {"braille_dots_2368" , 0x10028a6} , 2018 | {"braille_dots_12368" , 0x10028a7} , 2019 | {"braille_dots_468" , 0x10028a8} , 2020 | {"braille_dots_1468" , 0x10028a9} , 2021 | {"braille_dots_2468" , 0x10028aa} , 2022 | {"braille_dots_12468" , 0x10028ab} , 2023 | {"braille_dots_3468" , 0x10028ac} , 2024 | {"braille_dots_13468" , 0x10028ad} , 2025 | {"braille_dots_23468" , 0x10028ae} , 2026 | {"braille_dots_123468" , 0x10028af} , 2027 | {"braille_dots_568" , 0x10028b0} , 2028 | {"braille_dots_1568" , 0x10028b1} , 2029 | {"braille_dots_2568" , 0x10028b2} , 2030 | {"braille_dots_12568" , 0x10028b3} , 2031 | {"braille_dots_3568" , 0x10028b4} , 2032 | {"braille_dots_13568" , 0x10028b5} , 2033 | {"braille_dots_23568" , 0x10028b6} , 2034 | {"braille_dots_123568" , 0x10028b7} , 2035 | {"braille_dots_4568" , 0x10028b8} , 2036 | {"braille_dots_14568" , 0x10028b9} , 2037 | {"braille_dots_24568" , 0x10028ba} , 2038 | {"braille_dots_124568" , 0x10028bb} , 2039 | {"braille_dots_34568" , 0x10028bc} , 2040 | {"braille_dots_134568" , 0x10028bd} , 2041 | {"braille_dots_234568" , 0x10028be} , 2042 | {"braille_dots_1234568" , 0x10028bf} , 2043 | {"braille_dots_78" , 0x10028c0} , 2044 | {"braille_dots_178" , 0x10028c1} , 2045 | {"braille_dots_278" , 0x10028c2} , 2046 | {"braille_dots_1278" , 0x10028c3} , 2047 | {"braille_dots_378" , 0x10028c4} , 2048 | {"braille_dots_1378" , 0x10028c5} , 2049 | {"braille_dots_2378" , 0x10028c6} , 2050 | {"braille_dots_12378" , 0x10028c7} , 2051 | {"braille_dots_478" , 0x10028c8} , 2052 | {"braille_dots_1478" , 0x10028c9} , 2053 | {"braille_dots_2478" , 0x10028ca} , 2054 | {"braille_dots_12478" , 0x10028cb} , 2055 | {"braille_dots_3478" , 0x10028cc} , 2056 | {"braille_dots_13478" , 0x10028cd} , 2057 | {"braille_dots_23478" , 0x10028ce} , 2058 | {"braille_dots_123478" , 0x10028cf} , 2059 | {"braille_dots_578" , 0x10028d0} , 2060 | {"braille_dots_1578" , 0x10028d1} , 2061 | {"braille_dots_2578" , 0x10028d2} , 2062 | {"braille_dots_12578" , 0x10028d3} , 2063 | {"braille_dots_3578" , 0x10028d4} , 2064 | {"braille_dots_13578" , 0x10028d5} , 2065 | {"braille_dots_23578" , 0x10028d6} , 2066 | {"braille_dots_123578" , 0x10028d7} , 2067 | {"braille_dots_4578" , 0x10028d8} , 2068 | {"braille_dots_14578" , 0x10028d9} , 2069 | {"braille_dots_24578" , 0x10028da} , 2070 | {"braille_dots_124578" , 0x10028db} , 2071 | {"braille_dots_34578" , 0x10028dc} , 2072 | {"braille_dots_134578" , 0x10028dd} , 2073 | {"braille_dots_234578" , 0x10028de} , 2074 | {"braille_dots_1234578" , 0x10028df} , 2075 | {"braille_dots_678" , 0x10028e0} , 2076 | {"braille_dots_1678" , 0x10028e1} , 2077 | {"braille_dots_2678" , 0x10028e2} , 2078 | {"braille_dots_12678" , 0x10028e3} , 2079 | {"braille_dots_3678" , 0x10028e4} , 2080 | {"braille_dots_13678" , 0x10028e5} , 2081 | {"braille_dots_23678" , 0x10028e6} , 2082 | {"braille_dots_123678" , 0x10028e7} , 2083 | {"braille_dots_4678" , 0x10028e8} , 2084 | {"braille_dots_14678" , 0x10028e9} , 2085 | {"braille_dots_24678" , 0x10028ea} , 2086 | {"braille_dots_124678" , 0x10028eb} , 2087 | {"braille_dots_34678" , 0x10028ec} , 2088 | {"braille_dots_134678" , 0x10028ed} , 2089 | {"braille_dots_234678" , 0x10028ee} , 2090 | {"braille_dots_1234678" , 0x10028ef} , 2091 | {"braille_dots_5678" , 0x10028f0} , 2092 | {"braille_dots_15678" , 0x10028f1} , 2093 | {"braille_dots_25678" , 0x10028f2} , 2094 | {"braille_dots_125678" , 0x10028f3} , 2095 | {"braille_dots_35678" , 0x10028f4} , 2096 | {"braille_dots_135678" , 0x10028f5} , 2097 | {"braille_dots_235678" , 0x10028f6} , 2098 | {"braille_dots_1235678" , 0x10028f7} , 2099 | {"braille_dots_45678" , 0x10028f8} , 2100 | {"braille_dots_145678" , 0x10028f9} , 2101 | {"braille_dots_245678" , 0x10028fa} , 2102 | {"braille_dots_1245678" , 0x10028fb} , 2103 | {"braille_dots_345678" , 0x10028fc} , 2104 | {"braille_dots_1345678" , 0x10028fd} , 2105 | {"braille_dots_2345678" , 0x10028fe} , 2106 | {"braille_dots_12345678" , 0x10028ff} , 2107 | #endif 2108 | #ifdef XK_SINHALA 2109 | {"Sinh_ng" , 0x1000d82} , 2110 | {"Sinh_h2" , 0x1000d83} , 2111 | {"Sinh_a" , 0x1000d85} , 2112 | {"Sinh_aa" , 0x1000d86} , 2113 | {"Sinh_ae" , 0x1000d87} , 2114 | {"Sinh_aee" , 0x1000d88} , 2115 | {"Sinh_i" , 0x1000d89} , 2116 | {"Sinh_ii" , 0x1000d8a} , 2117 | {"Sinh_u" , 0x1000d8b} , 2118 | {"Sinh_uu" , 0x1000d8c} , 2119 | {"Sinh_ri" , 0x1000d8d} , 2120 | {"Sinh_rii" , 0x1000d8e} , 2121 | {"Sinh_lu" , 0x1000d8f} , 2122 | {"Sinh_luu" , 0x1000d90} , 2123 | {"Sinh_e" , 0x1000d91} , 2124 | {"Sinh_ee" , 0x1000d92} , 2125 | {"Sinh_ai" , 0x1000d93} , 2126 | {"Sinh_o" , 0x1000d94} , 2127 | {"Sinh_oo" , 0x1000d95} , 2128 | {"Sinh_au" , 0x1000d96} , 2129 | {"Sinh_ka" , 0x1000d9a} , 2130 | {"Sinh_kha" , 0x1000d9b} , 2131 | {"Sinh_ga" , 0x1000d9c} , 2132 | {"Sinh_gha" , 0x1000d9d} , 2133 | {"Sinh_ng2" , 0x1000d9e} , 2134 | {"Sinh_nga" , 0x1000d9f} , 2135 | {"Sinh_ca" , 0x1000da0} , 2136 | {"Sinh_cha" , 0x1000da1} , 2137 | {"Sinh_ja" , 0x1000da2} , 2138 | {"Sinh_jha" , 0x1000da3} , 2139 | {"Sinh_nya" , 0x1000da4} , 2140 | {"Sinh_jnya" , 0x1000da5} , 2141 | {"Sinh_nja" , 0x1000da6} , 2142 | {"Sinh_tta" , 0x1000da7} , 2143 | {"Sinh_ttha" , 0x1000da8} , 2144 | {"Sinh_dda" , 0x1000da9} , 2145 | {"Sinh_ddha" , 0x1000daa} , 2146 | {"Sinh_nna" , 0x1000dab} , 2147 | {"Sinh_ndda" , 0x1000dac} , 2148 | {"Sinh_tha" , 0x1000dad} , 2149 | {"Sinh_thha" , 0x1000dae} , 2150 | {"Sinh_dha" , 0x1000daf} , 2151 | {"Sinh_dhha" , 0x1000db0} , 2152 | {"Sinh_na" , 0x1000db1} , 2153 | {"Sinh_ndha" , 0x1000db3} , 2154 | {"Sinh_pa" , 0x1000db4} , 2155 | {"Sinh_pha" , 0x1000db5} , 2156 | {"Sinh_ba" , 0x1000db6} , 2157 | {"Sinh_bha" , 0x1000db7} , 2158 | {"Sinh_ma" , 0x1000db8} , 2159 | {"Sinh_mba" , 0x1000db9} , 2160 | {"Sinh_ya" , 0x1000dba} , 2161 | {"Sinh_ra" , 0x1000dbb} , 2162 | {"Sinh_la" , 0x1000dbd} , 2163 | {"Sinh_va" , 0x1000dc0} , 2164 | {"Sinh_sha" , 0x1000dc1} , 2165 | {"Sinh_ssha" , 0x1000dc2} , 2166 | {"Sinh_sa" , 0x1000dc3} , 2167 | {"Sinh_ha" , 0x1000dc4} , 2168 | {"Sinh_lla" , 0x1000dc5} , 2169 | {"Sinh_fa" , 0x1000dc6} , 2170 | {"Sinh_al" , 0x1000dca} , 2171 | {"Sinh_aa2" , 0x1000dcf} , 2172 | {"Sinh_ae2" , 0x1000dd0} , 2173 | {"Sinh_aee2" , 0x1000dd1} , 2174 | {"Sinh_i2" , 0x1000dd2} , 2175 | {"Sinh_ii2" , 0x1000dd3} , 2176 | {"Sinh_u2" , 0x1000dd4} , 2177 | {"Sinh_uu2" , 0x1000dd6} , 2178 | {"Sinh_ru2" , 0x1000dd8} , 2179 | {"Sinh_e2" , 0x1000dd9} , 2180 | {"Sinh_ee2" , 0x1000dda} , 2181 | {"Sinh_ai2" , 0x1000ddb} , 2182 | {"Sinh_o2" , 0x1000ddc} , 2183 | {"Sinh_oo2" , 0x1000ddd} , 2184 | {"Sinh_au2" , 0x1000dde} , 2185 | {"Sinh_lu2" , 0x1000ddf} , 2186 | {"Sinh_ruu2" , 0x1000df2} , 2187 | {"Sinh_luu2" , 0x1000df3} , 2188 | {"Sinh_kunddaliya" , 0x1000df4} , 2189 | #endif 2190 | #ifdef XK_XFREE86 2191 | {"XF86ModeLock" , 0x1008FF01} , 2192 | {"XF86MonBrightnessUp" , 0x1008FF02} , 2193 | {"XF86MonBrightnessDown" , 0x1008FF03} , 2194 | {"XF86KbdLightOnOff" , 0x1008FF04} , 2195 | {"XF86KbdBrightnessUp" , 0x1008FF05} , 2196 | {"XF86KbdBrightnessDown" , 0x1008FF06} , 2197 | {"XF86Standby" , 0x1008FF10} , 2198 | {"XF86AudioLowerVolume" , 0x1008FF11} , 2199 | {"XF86AudioMute" , 0x1008FF12} , 2200 | {"XF86AudioRaiseVolume" , 0x1008FF13} , 2201 | {"XF86AudioPlay" , 0x1008FF14} , 2202 | {"XF86AudioStop" , 0x1008FF15} , 2203 | {"XF86AudioPrev" , 0x1008FF16} , 2204 | {"XF86AudioNext" , 0x1008FF17} , 2205 | {"XF86HomePage" , 0x1008FF18} , 2206 | {"XF86Mail" , 0x1008FF19} , 2207 | {"XF86Start" , 0x1008FF1A} , 2208 | {"XF86Search" , 0x1008FF1B} , 2209 | {"XF86AudioRecord" , 0x1008FF1C} , 2210 | {"XF86Calculator" , 0x1008FF1D} , 2211 | {"XF86Memo" , 0x1008FF1E} , 2212 | {"XF86ToDoList" , 0x1008FF1F} , 2213 | {"XF86Calendar" , 0x1008FF20} , 2214 | {"XF86PowerDown" , 0x1008FF21} , 2215 | {"XF86ContrastAdjust" , 0x1008FF22} , 2216 | {"XF86RockerUp" , 0x1008FF23} , 2217 | {"XF86RockerDown" , 0x1008FF24} , 2218 | {"XF86RockerEnter" , 0x1008FF25} , 2219 | {"XF86Back" , 0x1008FF26} , 2220 | {"XF86Forward" , 0x1008FF27} , 2221 | {"XF86Stop" , 0x1008FF28} , 2222 | {"XF86Refresh" , 0x1008FF29} , 2223 | {"XF86PowerOff" , 0x1008FF2A} , 2224 | {"XF86WakeUp" , 0x1008FF2B} , 2225 | {"XF86Eject" , 0x1008FF2C} , 2226 | {"XF86ScreenSaver" , 0x1008FF2D} , 2227 | {"XF86WWW" , 0x1008FF2E} , 2228 | {"XF86Sleep" , 0x1008FF2F} , 2229 | {"XF86Favorites" , 0x1008FF30} , 2230 | {"XF86AudioPause" , 0x1008FF31} , 2231 | {"XF86AudioMedia" , 0x1008FF32} , 2232 | {"XF86MyComputer" , 0x1008FF33} , 2233 | {"XF86VendorHome" , 0x1008FF34} , 2234 | {"XF86LightBulb" , 0x1008FF35} , 2235 | {"XF86Shop" , 0x1008FF36} , 2236 | {"XF86History" , 0x1008FF37} , 2237 | {"XF86OpenURL" , 0x1008FF38} , 2238 | {"XF86AddFavorite" , 0x1008FF39} , 2239 | {"XF86HotLinks" , 0x1008FF3A} , 2240 | {"XF86BrightnessAdjust" , 0x1008FF3B} , 2241 | {"XF86Finance" , 0x1008FF3C} , 2242 | {"XF86Community" , 0x1008FF3D} , 2243 | {"XF86AudioRewind" , 0x1008FF3E} , 2244 | {"XF86BackForward" , 0x1008FF3F} , 2245 | {"XF86Launch0" , 0x1008FF40} , 2246 | {"XF86Launch1" , 0x1008FF41} , 2247 | {"XF86Launch2" , 0x1008FF42} , 2248 | {"XF86Launch3" , 0x1008FF43} , 2249 | {"XF86Launch4" , 0x1008FF44} , 2250 | {"XF86Launch5" , 0x1008FF45} , 2251 | {"XF86Launch6" , 0x1008FF46} , 2252 | {"XF86Launch7" , 0x1008FF47} , 2253 | {"XF86Launch8" , 0x1008FF48} , 2254 | {"XF86Launch9" , 0x1008FF49} , 2255 | {"XF86LaunchA" , 0x1008FF4A} , 2256 | {"XF86LaunchB" , 0x1008FF4B} , 2257 | {"XF86LaunchC" , 0x1008FF4C} , 2258 | {"XF86LaunchD" , 0x1008FF4D} , 2259 | {"XF86LaunchE" , 0x1008FF4E} , 2260 | {"XF86LaunchF" , 0x1008FF4F} , 2261 | {"XF86ApplicationLeft" , 0x1008FF50} , 2262 | {"XF86ApplicationRight" , 0x1008FF51} , 2263 | {"XF86Book" , 0x1008FF52} , 2264 | {"XF86CD" , 0x1008FF53} , 2265 | {"XF86Calculater" , 0x1008FF54} , 2266 | {"XF86Clear" , 0x1008FF55} , 2267 | {"XF86Close" , 0x1008FF56} , 2268 | {"XF86Copy" , 0x1008FF57} , 2269 | {"XF86Cut" , 0x1008FF58} , 2270 | {"XF86Display" , 0x1008FF59} , 2271 | {"XF86DOS" , 0x1008FF5A} , 2272 | {"XF86Documents" , 0x1008FF5B} , 2273 | {"XF86Excel" , 0x1008FF5C} , 2274 | {"XF86Explorer" , 0x1008FF5D} , 2275 | {"XF86Game" , 0x1008FF5E} , 2276 | {"XF86Go" , 0x1008FF5F} , 2277 | {"XF86iTouch" , 0x1008FF60} , 2278 | {"XF86LogOff" , 0x1008FF61} , 2279 | {"XF86Market" , 0x1008FF62} , 2280 | {"XF86Meeting" , 0x1008FF63} , 2281 | {"XF86MenuKB" , 0x1008FF65} , 2282 | {"XF86MenuPB" , 0x1008FF66} , 2283 | {"XF86MySites" , 0x1008FF67} , 2284 | {"XF86New" , 0x1008FF68} , 2285 | {"XF86News" , 0x1008FF69} , 2286 | {"XF86OfficeHome" , 0x1008FF6A} , 2287 | {"XF86Open" , 0x1008FF6B} , 2288 | {"XF86Option" , 0x1008FF6C} , 2289 | {"XF86Paste" , 0x1008FF6D} , 2290 | {"XF86Phone" , 0x1008FF6E} , 2291 | {"XF86Q" , 0x1008FF70} , 2292 | {"XF86Reply" , 0x1008FF72} , 2293 | {"XF86Reload" , 0x1008FF73} , 2294 | {"XF86RotateWindows" , 0x1008FF74} , 2295 | {"XF86RotationPB" , 0x1008FF75} , 2296 | {"XF86RotationKB" , 0x1008FF76} , 2297 | {"XF86Save" , 0x1008FF77} , 2298 | {"XF86ScrollUp" , 0x1008FF78} , 2299 | {"XF86ScrollDown" , 0x1008FF79} , 2300 | {"XF86ScrollClick" , 0x1008FF7A} , 2301 | {"XF86Send" , 0x1008FF7B} , 2302 | {"XF86Spell" , 0x1008FF7C} , 2303 | {"XF86SplitScreen" , 0x1008FF7D} , 2304 | {"XF86Support" , 0x1008FF7E} , 2305 | {"XF86TaskPane" , 0x1008FF7F} , 2306 | {"XF86Terminal" , 0x1008FF80} , 2307 | {"XF86Tools" , 0x1008FF81} , 2308 | {"XF86Travel" , 0x1008FF82} , 2309 | {"XF86UserPB" , 0x1008FF84} , 2310 | {"XF86User1KB" , 0x1008FF85} , 2311 | {"XF86User2KB" , 0x1008FF86} , 2312 | {"XF86Video" , 0x1008FF87} , 2313 | {"XF86WheelButton" , 0x1008FF88} , 2314 | {"XF86Word" , 0x1008FF89} , 2315 | {"XF86Xfer" , 0x1008FF8A} , 2316 | {"XF86ZoomIn" , 0x1008FF8B} , 2317 | {"XF86ZoomOut" , 0x1008FF8C} , 2318 | {"XF86Away" , 0x1008FF8D} , 2319 | {"XF86Messenger" , 0x1008FF8E} , 2320 | {"XF86WebCam" , 0x1008FF8F} , 2321 | {"XF86MailForward" , 0x1008FF90} , 2322 | {"XF86Pictures" , 0x1008FF91} , 2323 | {"XF86Music" , 0x1008FF92} , 2324 | {"XF86Battery" , 0x1008FF93} , 2325 | {"XF86Bluetooth" , 0x1008FF94} , 2326 | {"XF86WLAN" , 0x1008FF95} , 2327 | {"XF86UWB" , 0x1008FF96} , 2328 | {"XF86AudioForward" , 0x1008FF97} , 2329 | {"XF86AudioRepeat" , 0x1008FF98} , 2330 | {"XF86AudioRandomPlay" , 0x1008FF99} , 2331 | {"XF86Subtitle" , 0x1008FF9A} , 2332 | {"XF86AudioCycleTrack" , 0x1008FF9B} , 2333 | {"XF86CycleAngle" , 0x1008FF9C} , 2334 | {"XF86FrameBack" , 0x1008FF9D} , 2335 | {"XF86FrameForward" , 0x1008FF9E} , 2336 | {"XF86Time" , 0x1008FF9F} , 2337 | {"XF86Select" , 0x1008FFA0} , 2338 | {"XF86View" , 0x1008FFA1} , 2339 | {"XF86TopMenu" , 0x1008FFA2} , 2340 | {"XF86Red" , 0x1008FFA3} , 2341 | {"XF86Green" , 0x1008FFA4} , 2342 | {"XF86Yellow" , 0x1008FFA5} , 2343 | {"XF86Blue" , 0x1008FFA6} , 2344 | {"XF86Suspend" , 0x1008FFA7} , 2345 | {"XF86Hibernate" , 0x1008FFA8} , 2346 | {"XF86TouchpadToggle" , 0x1008FFA9} , 2347 | {"XF86TouchpadOn" , 0x1008FFB0} , 2348 | {"XF86TouchpadOff" , 0x1008FFB1} , 2349 | {"XF86AudioMicMute" , 0x1008FFB2} , 2350 | {"XF86Switch_VT_1" , 0x1008FE01} , 2351 | {"XF86Switch_VT_2" , 0x1008FE02} , 2352 | {"XF86Switch_VT_3" , 0x1008FE03} , 2353 | {"XF86Switch_VT_4" , 0x1008FE04} , 2354 | {"XF86Switch_VT_5" , 0x1008FE05} , 2355 | {"XF86Switch_VT_6" , 0x1008FE06} , 2356 | {"XF86Switch_VT_7" , 0x1008FE07} , 2357 | {"XF86Switch_VT_8" , 0x1008FE08} , 2358 | {"XF86Switch_VT_9" , 0x1008FE09} , 2359 | {"XF86Switch_VT_10" , 0x1008FE0A} , 2360 | {"XF86Switch_VT_11" , 0x1008FE0B} , 2361 | {"XF86Switch_VT_12" , 0x1008FE0C} , 2362 | {"XF86Ungrab" , 0x1008FE20} , 2363 | {"XF86ClearGrab" , 0x1008FE21} , 2364 | {"XF86Next_VMode" , 0x1008FE22} , 2365 | {"XF86Prev_VMode" , 0x1008FE23} , 2366 | {"XF86LogWindowTree" , 0x1008FE24} , 2367 | {"XF86LogGrabInfo" , 0x1008FE25} , 2368 | #endif 2369 | };/*}}}*/ 2370 | 2371 | void load_config(const char *config_file) 2372 | { 2373 | PRINTF("load configuration '%s'\n", config_file); 2374 | FILE *cfg = fopen(config_file, "r"); 2375 | if (cfg == NULL) 2376 | err("Can't open configuration file: '%s'.\n", config_file); 2377 | 2378 | char buf[3 * MAXLEN]; 2379 | char chain[MAXLEN] = {0}; 2380 | char command[2 * MAXLEN] = {0}; 2381 | int offset = 0; 2382 | char first; 2383 | 2384 | while (fgets(buf, sizeof(buf), cfg) != NULL) { 2385 | first = buf[0]; 2386 | if (strlen(buf) < 2 || first == START_COMMENT) { 2387 | continue; 2388 | } else { 2389 | char *start = lgraph(buf); 2390 | if (start == NULL) 2391 | continue; 2392 | char *end = rgraph(buf); 2393 | *(end + 1) = '\0'; 2394 | 2395 | if (isgraph(first)) 2396 | snprintf(chain + offset, sizeof(chain) - offset, "%s", start); 2397 | else 2398 | snprintf(command + offset, sizeof(command) - offset, "%s", start); 2399 | 2400 | if (*end == PARTIAL_LINE) { 2401 | offset += end - start; 2402 | continue; 2403 | } else { 2404 | offset = 0; 2405 | } 2406 | 2407 | if (isspace(first) && strlen(chain) > 0 && strlen(command) > 0) { 2408 | process_hotkey(chain, command); 2409 | chain[0] = '\0'; 2410 | command[0] = '\0'; 2411 | } 2412 | } 2413 | } 2414 | 2415 | fclose(cfg); 2416 | } 2417 | 2418 | void parse_event(xcb_generic_event_t *evt, uint8_t event_type, xcb_keysym_t *keysym, xcb_button_t *button, uint16_t *modfield) 2419 | { 2420 | if (event_type == XCB_KEY_PRESS) { 2421 | xcb_key_press_event_t *e = (xcb_key_press_event_t *) evt; 2422 | xcb_keycode_t keycode = e->detail; 2423 | *modfield = e->state; 2424 | *keysym = xcb_key_symbols_get_keysym(symbols, keycode, 0); 2425 | PRINTF("key press %u %u\n", keycode, *modfield); 2426 | } else if (event_type == XCB_KEY_RELEASE) { 2427 | xcb_key_release_event_t *e = (xcb_key_release_event_t *) evt; 2428 | xcb_keycode_t keycode = e->detail; 2429 | *modfield = e->state & ~modfield_from_keycode(keycode); 2430 | *keysym = xcb_key_symbols_get_keysym(symbols, keycode, 0); 2431 | PRINTF("key release %u %u\n", keycode, *modfield); 2432 | } else if (event_type == XCB_BUTTON_PRESS) { 2433 | xcb_button_press_event_t *e = (xcb_button_press_event_t *) evt; 2434 | *button = e->detail; 2435 | *modfield = e->state; 2436 | PRINTF("button press %u %u\n", *button, *modfield); 2437 | } else if (event_type == XCB_BUTTON_RELEASE) { 2438 | xcb_button_release_event_t *e = (xcb_button_release_event_t *) evt; 2439 | *button = e->detail; 2440 | *modfield = e->state; 2441 | PRINTF("button release %u %u\n", *button, *modfield); 2442 | } 2443 | } 2444 | 2445 | void process_hotkey(char *hotkey_string, char *command_string) 2446 | { 2447 | char hotkey[2 * MAXLEN] = {0}; 2448 | char command[2 * MAXLEN] = {0}; 2449 | char last_hotkey[2 * MAXLEN] = {0}; 2450 | unsigned char num_same = 0; 2451 | chunk_t *hk_chunks = extract_chunks(hotkey_string); 2452 | chunk_t *cm_chunks = extract_chunks(command_string); 2453 | 2454 | #define CHECKCHUNK(s, c) \ 2455 | if (c->next == NULL && !c->sequence) { \ 2456 | snprintf(s, sizeof(s), "%s", c->text); \ 2457 | destroy_chunks(c); \ 2458 | c = NULL; \ 2459 | } 2460 | CHECKCHUNK(hotkey, hk_chunks) 2461 | CHECKCHUNK(command, cm_chunks) 2462 | #undef CHECKCHUNK 2463 | 2464 | render_next(hk_chunks, hotkey); 2465 | render_next(cm_chunks, command); 2466 | 2467 | while ((hk_chunks == NULL || hotkey[0] != '\0') && (cm_chunks == NULL || command[0] != '\0')) { 2468 | 2469 | PRINTF("%s: %s\n", hotkey, command); 2470 | chain_t *chain = make_chain(); 2471 | if (parse_chain(hotkey, chain)) { 2472 | hotkey_t *hk = make_hotkey(chain, command); 2473 | for (hotkey_t* i = hotkeys_head; i; i = i->next) { 2474 | if (chains_interfere(i->chain, hk->chain)) { 2475 | warn("Hotkey interference found and may not be matched: '%s' (from '%s').\n", hotkey, hotkey_string); 2476 | } 2477 | } 2478 | add_hotkey(hk); 2479 | if (strcmp(hotkey, last_hotkey) == 0) 2480 | num_same++; 2481 | } else { 2482 | destroy_chain(chain); 2483 | } 2484 | 2485 | if (hk_chunks == NULL && cm_chunks == NULL) 2486 | break; 2487 | 2488 | snprintf(last_hotkey, sizeof(last_hotkey), "%s", hotkey); 2489 | 2490 | render_next(hk_chunks, hotkey); 2491 | render_next(cm_chunks, command); 2492 | } 2493 | 2494 | if (num_same > 0) { 2495 | int period = num_same + 1; 2496 | int delay = num_same; 2497 | for (hotkey_t *hk = hotkeys_tail; hk != NULL && delay >= 0; hk = hk->prev, delay--) 2498 | hk->cycle = make_cycle(delay, period); 2499 | } 2500 | 2501 | if (hk_chunks != NULL) 2502 | destroy_chunks(hk_chunks); 2503 | if (cm_chunks != NULL) 2504 | destroy_chunks(cm_chunks); 2505 | } 2506 | 2507 | char *get_token(char *dst, char *ign, char *src, char *sep) 2508 | { 2509 | size_t len = strlen(src); 2510 | unsigned int i = 0, j = 0, k = 0; 2511 | bool inhibit = false; 2512 | bool found = false; 2513 | while (i < len && !found) { 2514 | if (inhibit) { 2515 | dst[j++] = src[i]; 2516 | inhibit = false; 2517 | } else if (src[i] == MAGIC_INHIBIT) { 2518 | inhibit = true; 2519 | if (src[i+1] != MAGIC_INHIBIT && strchr(sep, src[i+1]) == NULL) 2520 | dst[j++] = src[i]; 2521 | } else if (strchr(sep, src[i]) != NULL) { 2522 | if (j > 0) 2523 | found = true; 2524 | do { 2525 | if (ign != NULL) 2526 | ign[k++] = src[i]; 2527 | i++; 2528 | } while (i < len && strchr(sep, src[i]) != NULL); 2529 | i--; 2530 | } else { 2531 | dst[j++] = src[i]; 2532 | } 2533 | i++; 2534 | } 2535 | dst[j] = '\0'; 2536 | if (ign != NULL) 2537 | ign[k] = '\0'; 2538 | return src + i; 2539 | } 2540 | 2541 | void render_next(chunk_t *chunks, char *dest) 2542 | { 2543 | if (chunks == NULL) 2544 | return; 2545 | int i = 0; 2546 | bool incr = false; 2547 | for (chunk_t *c = chunks; c != NULL; c = c->next) { 2548 | if (c->sequence) { 2549 | if (!incr) { 2550 | if (c->range_cur < c->range_max) { 2551 | c->range_cur++; 2552 | incr = true; 2553 | } else { 2554 | c->range_cur = 1, c->range_max = 0; 2555 | } 2556 | } 2557 | if (c->advance == NULL) { 2558 | incr = true; 2559 | c->advance = get_token(c->item, NULL, c->text, SEQ_SEP); 2560 | } else if (!incr && c->range_cur > c->range_max) { 2561 | if (c->advance[0] == '\0') { 2562 | c->advance = get_token(c->item, NULL, c->text, SEQ_SEP); 2563 | } else { 2564 | c->advance = get_token(c->item, NULL, c->advance, SEQ_SEP); 2565 | incr = true; 2566 | } 2567 | } 2568 | if (c->range_cur > c->range_max && strlen(c->item) == 3) 2569 | sscanf(c->item, "%c-%c", &c->range_cur, &c->range_max); 2570 | if (c->range_cur <= c->range_max) { 2571 | dest[i++] = c->range_cur; 2572 | } else { 2573 | if (c->item[0] == SEQ_NONE && c->item[1] == '\0') 2574 | continue; 2575 | strcpy(dest + i, c->item); 2576 | i += strlen(c->item); 2577 | } 2578 | } else { 2579 | strcpy(dest + i, c->text); 2580 | i += strlen(c->text); 2581 | } 2582 | } 2583 | dest[i] = '\0'; 2584 | if (!incr) 2585 | dest[0] = '\0'; 2586 | } 2587 | 2588 | chunk_t *extract_chunks(char *s) 2589 | { 2590 | size_t len = strlen(s); 2591 | unsigned int i = 0, j = 0; 2592 | bool inhibit = false; 2593 | int num_seq = 0; 2594 | chunk_t *c = make_chunk(); 2595 | chunk_t *head = c; 2596 | while (i < len) { 2597 | if (inhibit) { 2598 | c->text[j++] = s[i]; 2599 | inhibit = false; 2600 | } else if (s[i] == MAGIC_INHIBIT) { 2601 | inhibit = true; 2602 | if ((s[i+1] != MAGIC_INHIBIT || c->sequence) 2603 | && s[i+1] != SEQ_BEGIN 2604 | && s[i+1] != SEQ_END) 2605 | c->text[j++] = s[i]; 2606 | } else if (s[i] == SEQ_BEGIN) { 2607 | if (j > 0) { 2608 | c->text[j] = '\0'; 2609 | j = 0; 2610 | chunk_t *next = make_chunk(); 2611 | c->next = next; 2612 | c = next; 2613 | } 2614 | c->sequence = true; 2615 | } else if (s[i] == SEQ_END) { 2616 | if (c->sequence) 2617 | num_seq++; 2618 | if (j > 0) { 2619 | c->text[j] = '\0'; 2620 | j = 0; 2621 | chunk_t *next = make_chunk(); 2622 | c->next = next; 2623 | c = next; 2624 | } 2625 | c->sequence = false; 2626 | } else { 2627 | c->text[j++] = s[i]; 2628 | } 2629 | i++; 2630 | } 2631 | c->text[j] = '\0'; 2632 | return head; 2633 | } 2634 | 2635 | chunk_t *make_chunk(void) 2636 | { 2637 | chunk_t *c = calloc(1, sizeof(chunk_t)); 2638 | c->sequence = false; 2639 | c->advance = NULL; 2640 | c->next = NULL; 2641 | c->range_cur = 1; 2642 | c->range_max = 0; 2643 | return c; 2644 | } 2645 | 2646 | void destroy_chunks(chunk_t *chunk) 2647 | { 2648 | chunk_t *c = chunk; 2649 | while (c != NULL) { 2650 | chunk_t *next = c->next; 2651 | free(c); 2652 | c = next; 2653 | } 2654 | } 2655 | 2656 | bool parse_chain(char *string, chain_t *chain) 2657 | { 2658 | char chord[MAXLEN] = {0}; 2659 | char name[MAXLEN] = {0}; 2660 | char ignored[MAXLEN] = {0}; 2661 | xcb_keysym_t keysym = XCB_NO_SYMBOL; 2662 | xcb_button_t button = XCB_NONE; 2663 | uint16_t modfield = 0; 2664 | uint8_t event_type = XCB_KEY_PRESS; 2665 | bool replay_event = false; 2666 | bool lock_chain = false; 2667 | char *outer_advance; 2668 | char *inner_advance; 2669 | for (outer_advance = get_token(chord, ignored, string, LNK_SEP); chord[0] != '\0'; outer_advance = get_token(chord, ignored, outer_advance, LNK_SEP)) { 2670 | for (inner_advance = get_token(name, NULL, chord, SYM_SEP); name[0] != '\0'; inner_advance = get_token(name, NULL, inner_advance, SYM_SEP)) { 2671 | int offset = 0; 2672 | if (name[offset] == REPLAY_PREFIX) { 2673 | replay_event = true; 2674 | offset++; 2675 | } 2676 | if (name[offset] == RELEASE_PREFIX) { 2677 | event_type = XCB_KEY_RELEASE; 2678 | offset++; 2679 | } 2680 | char *nm = name + offset; 2681 | if (!parse_modifier(nm, &modfield) && !parse_keysym(nm, &keysym) && !parse_button(nm, &button)) { 2682 | warn("Unknown keysym name: '%s'.\n", nm); 2683 | return false; 2684 | } 2685 | } 2686 | if (strstr(ignored, GRP_SEP) != NULL) 2687 | lock_chain = true; 2688 | if (button != XCB_NONE) 2689 | event_type = key_to_button(event_type); 2690 | chord_t *c = make_chord(keysym, button, modfield, event_type, replay_event, lock_chain); 2691 | if (c == NULL) { 2692 | return false; 2693 | } 2694 | add_chord(chain, c); 2695 | if (status_fifo != NULL) { 2696 | snprintf(c->repr, sizeof(c->repr), "%s", chord); 2697 | } 2698 | keysym = XCB_NO_SYMBOL; 2699 | button = XCB_NONE; 2700 | modfield = 0; 2701 | event_type = XCB_KEY_PRESS; 2702 | replay_event = false; 2703 | lock_chain = false; 2704 | } 2705 | return true; 2706 | } 2707 | 2708 | bool parse_keysym(char *name, xcb_keysym_t *keysym) 2709 | { 2710 | for (unsigned int i = 0; i < LENGTH(nks_dict); i++) { 2711 | keysym_dict_t nks = nks_dict[i]; 2712 | if (strcmp(name, nks.name) == 0) { 2713 | *keysym = nks.keysym; 2714 | return true; 2715 | } 2716 | } 2717 | return false; 2718 | } 2719 | 2720 | bool parse_button(char *name, xcb_button_t *butidx) 2721 | { 2722 | /* X handles up to 24 buttons */ 2723 | return (sscanf(name, "button%" SCNu8, butidx) == 1); 2724 | } 2725 | 2726 | bool parse_modifier(char *name, uint16_t *modfield) 2727 | { 2728 | if (strcmp(name, "shift") == 0) { 2729 | *modfield |= XCB_MOD_MASK_SHIFT; 2730 | return true; 2731 | } else if (strcmp(name, "control") == 0 || strcmp(name, "ctrl") == 0) { 2732 | *modfield |= XCB_MOD_MASK_CONTROL; 2733 | return true; 2734 | } else if (strcmp(name, "alt") == 0) { 2735 | *modfield |= (modfield_from_keysym(Alt_L) | modfield_from_keysym(Alt_R)); 2736 | return true; 2737 | } else if (strcmp(name, "super") == 0) { 2738 | *modfield |= (modfield_from_keysym(Super_L) | modfield_from_keysym(Super_R)); 2739 | return true; 2740 | } else if (strcmp(name, "hyper") == 0) { 2741 | *modfield |= (modfield_from_keysym(Hyper_L) | modfield_from_keysym(Hyper_R)); 2742 | return true; 2743 | } else if (strcmp(name, "meta") == 0) { 2744 | *modfield |= (modfield_from_keysym(Meta_L) | modfield_from_keysym(Meta_R)); 2745 | return true; 2746 | } else if (strcmp(name, "mode_switch") == 0) { 2747 | *modfield |= modfield_from_keysym(Mode_switch); 2748 | return true; 2749 | } else if (strcmp(name, "mod1") == 0) { 2750 | *modfield |= XCB_MOD_MASK_1; 2751 | return true; 2752 | } else if (strcmp(name, "mod2") == 0) { 2753 | *modfield |= XCB_MOD_MASK_2; 2754 | return true; 2755 | } else if (strcmp(name, "mod3") == 0) { 2756 | *modfield |= XCB_MOD_MASK_3; 2757 | return true; 2758 | } else if (strcmp(name, "mod4") == 0) { 2759 | *modfield |= XCB_MOD_MASK_4; 2760 | return true; 2761 | } else if (strcmp(name, "mod5") == 0) { 2762 | *modfield |= XCB_MOD_MASK_5; 2763 | return true; 2764 | } else if (strcmp(name, "lock") == 0) { 2765 | *modfield |= XCB_MOD_MASK_LOCK; 2766 | return true; 2767 | } else if (strcmp(name, "any") == 0) { 2768 | *modfield |= XCB_MOD_MASK_ANY; 2769 | return true; 2770 | } 2771 | return false; 2772 | } 2773 | 2774 | bool parse_fold(char *string, char *folded_string) 2775 | { 2776 | if (strchr(string, SEQ_BEGIN) != NULL && strrchr(string, SEQ_END) != NULL) { 2777 | snprintf(folded_string, strlen(string), "%s", string); 2778 | return true; 2779 | } 2780 | return false; 2781 | } 2782 | 2783 | uint8_t key_to_button(uint8_t event_type) 2784 | { 2785 | if (event_type == XCB_KEY_PRESS) 2786 | return XCB_BUTTON_PRESS; 2787 | else if (event_type == XCB_KEY_RELEASE) 2788 | return XCB_BUTTON_RELEASE; 2789 | return event_type; 2790 | } 2791 | 2792 | void get_standard_keysyms(void) 2793 | { 2794 | #define GETKS(X) \ 2795 | if (!parse_keysym(#X, &X)) \ 2796 | warn("Couldn't retrieve keysym for '%s'.\n", #X); \ 2797 | else \ 2798 | PRINTF("keysym for '%s' is 0x%X.\n", #X, X); 2799 | GETKS(Alt_L) 2800 | GETKS(Alt_R) 2801 | GETKS(Super_L) 2802 | GETKS(Super_R) 2803 | GETKS(Hyper_L) 2804 | GETKS(Hyper_R) 2805 | GETKS(Mode_switch) 2806 | GETKS(Num_Lock) 2807 | GETKS(Scroll_Lock) 2808 | #undef GETKS 2809 | } 2810 | 2811 | void get_lock_fields(void) 2812 | { 2813 | num_lock = modfield_from_keysym(Num_Lock); 2814 | caps_lock = XCB_MOD_MASK_LOCK; 2815 | scroll_lock = modfield_from_keysym(Scroll_Lock); 2816 | PRINTF("lock fields %u %u %u\n", num_lock, caps_lock, scroll_lock); 2817 | } 2818 | 2819 | int16_t modfield_from_keysym(xcb_keysym_t keysym) 2820 | { 2821 | uint16_t modfield = 0; 2822 | xcb_keycode_t *keycodes = NULL; 2823 | if ((keycodes = keycodes_from_keysym(keysym)) != NULL) { 2824 | for (xcb_keycode_t *k = keycodes; *k != XCB_NO_SYMBOL; k++) 2825 | modfield |= modfield_from_keycode(*k); 2826 | } 2827 | free(keycodes); 2828 | return modfield; 2829 | } 2830 | 2831 | int16_t modfield_from_keycode(xcb_keycode_t keycode) 2832 | { 2833 | uint16_t modfield = 0; 2834 | xcb_keycode_t *mod_keycodes = NULL; 2835 | xcb_get_modifier_mapping_reply_t *reply = NULL; 2836 | if ((reply = xcb_get_modifier_mapping_reply(dpy, xcb_get_modifier_mapping(dpy), NULL)) != NULL && reply->keycodes_per_modifier > 0) { 2837 | if ((mod_keycodes = xcb_get_modifier_mapping_keycodes(reply)) != NULL) { 2838 | unsigned int num_mod = xcb_get_modifier_mapping_keycodes_length(reply) / reply->keycodes_per_modifier; 2839 | for (unsigned int i = 0; i < num_mod; i++) { 2840 | for (unsigned int j = 0; j < reply->keycodes_per_modifier; j++) { 2841 | xcb_keycode_t mkc = mod_keycodes[i * reply->keycodes_per_modifier + j]; 2842 | if (mkc == XCB_NO_SYMBOL) 2843 | continue; 2844 | if (keycode == mkc) 2845 | modfield |= (1 << i); 2846 | } 2847 | } 2848 | 2849 | } 2850 | } 2851 | free(reply); 2852 | return modfield; 2853 | } 2854 | 2855 | xcb_keycode_t *keycodes_from_keysym(xcb_keysym_t keysym) 2856 | { 2857 | xcb_setup_t const *setup; 2858 | unsigned int num = 0; 2859 | xcb_keycode_t *result = NULL, *result_np = NULL; 2860 | 2861 | if ((setup = xcb_get_setup(dpy)) != NULL) { 2862 | xcb_keycode_t min_kc = setup->min_keycode; 2863 | xcb_keycode_t max_kc = setup->max_keycode; 2864 | 2865 | /* We must choose a type for kc other than xcb_keycode_t whose size 2866 | * is 1, otherwise, since max_kc will most likely be 255, if kc == 255, 2867 | * kc++ would be 0 and the outer loop would start over ad infinitum */ 2868 | for(unsigned int kc = min_kc; kc <= max_kc; kc++) 2869 | for(unsigned int col = 0; col < KEYSYMS_PER_KEYCODE; col++) { 2870 | xcb_keysym_t ks = xcb_key_symbols_get_keysym(symbols, kc, col); 2871 | if (ks == keysym) { 2872 | num++; 2873 | result_np = realloc(result, sizeof(xcb_keycode_t) * (num + 1)); 2874 | if (result_np == NULL) { 2875 | free(result); 2876 | return NULL; 2877 | } 2878 | result = result_np; 2879 | result[num - 1] = kc; 2880 | result[num] = XCB_NO_SYMBOL; 2881 | break; 2882 | } 2883 | } 2884 | } 2885 | return result; 2886 | } 2887 | -------------------------------------------------------------------------------- /src/parse.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #ifndef SXHKD_PARSE_H 26 | #define SXHKD_PARSE_H 27 | 28 | #include "sxhkd.h" 29 | 30 | #define RELEASE_PREFIX '@' 31 | #define REPLAY_PREFIX '~' 32 | #define START_COMMENT '#' 33 | #define MAGIC_INHIBIT '\\' 34 | #define PARTIAL_LINE '\\' 35 | #define GRP_SEP ":" 36 | #define LNK_SEP ";" GRP_SEP 37 | #define SYM_SEP "+ " 38 | #define SEQ_BEGIN '{' 39 | #define SEQ_END '}' 40 | #define SEQ_SEP "," 41 | #define SEQ_NONE '_' 42 | 43 | typedef struct chunk_t chunk_t; 44 | struct chunk_t { 45 | char text[2 * MAXLEN]; 46 | char item[2 * MAXLEN]; 47 | char *advance; 48 | bool sequence; 49 | char range_cur; 50 | char range_max; 51 | chunk_t *next; 52 | }; 53 | 54 | void load_config(const char *config_file); 55 | void parse_event(xcb_generic_event_t *evt, uint8_t event_type, xcb_keysym_t *keysym, xcb_button_t *button, uint16_t *modfield); 56 | void process_hotkey(char *hotkey_string, char *command_string); 57 | char *get_token(char *dst, char *ign, char *src, char *sep); 58 | void render_next(chunk_t *chunks, char *dest); 59 | chunk_t *extract_chunks(char *s); 60 | chunk_t *make_chunk(void); 61 | void destroy_chunks(chunk_t *chunk); 62 | bool parse_chain(char *string, chain_t *chain); 63 | bool parse_keysym(char *name, xcb_keysym_t *keysym); 64 | bool parse_button(char *name, xcb_button_t *butidx); 65 | bool parse_modifier(char *name, uint16_t *modfield); 66 | bool parse_fold(char *string, char *folded_string); 67 | uint8_t key_to_button(uint8_t event_type); 68 | void get_standard_keysyms(void); 69 | void get_lock_fields(void); 70 | int16_t modfield_from_keysym(xcb_keysym_t keysym); 71 | int16_t modfield_from_keycode(xcb_keycode_t keycode); 72 | xcb_keycode_t *keycodes_from_keysym(xcb_keysym_t keysym); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /src/sxhkd.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | #include 36 | #include "parse.h" 37 | #include "grab.h" 38 | 39 | xcb_connection_t *dpy; 40 | xcb_window_t root; 41 | xcb_key_symbols_t *symbols; 42 | 43 | char *shell; 44 | char config_file[MAXLEN]; 45 | char *config_path; 46 | char **extra_confs; 47 | int num_extra_confs; 48 | int redir_fd; 49 | FILE *status_fifo; 50 | char progress[3 * MAXLEN]; 51 | int mapping_count; 52 | int timeout; 53 | 54 | char sxhkd_pid[MAXLEN]; 55 | 56 | hotkey_t *hotkeys_head, *hotkeys_tail; 57 | bool running, grabbed, toggle_grab, reload, bell, chained, locked; 58 | xcb_keysym_t abort_keysym; 59 | chord_t *abort_chord; 60 | 61 | uint16_t num_lock; 62 | uint16_t caps_lock; 63 | uint16_t scroll_lock; 64 | 65 | int main(int argc, char *argv[]) 66 | { 67 | int opt; 68 | char *fifo_path = NULL; 69 | status_fifo = NULL; 70 | config_path = NULL; 71 | mapping_count = 0; 72 | timeout = TIMEOUT; 73 | grabbed = false; 74 | redir_fd = -1; 75 | abort_keysym = ESCAPE_KEYSYM; 76 | 77 | while ((opt = getopt(argc, argv, "hvm:t:c:r:s:a:")) != -1) { 78 | switch (opt) { 79 | case 'v': 80 | printf("%s\n", VERSION); 81 | exit(EXIT_SUCCESS); 82 | break; 83 | case 'h': 84 | printf("sxhkd [-h|-v|-m COUNT|-t TIMEOUT|-c CONFIG_FILE|-r REDIR_FILE|-s STATUS_FIFO|-a ABORT_KEYSYM] [EXTRA_CONFIG ...]\n"); 85 | exit(EXIT_SUCCESS); 86 | break; 87 | case 'm': 88 | if (sscanf(optarg, "%i", &mapping_count) != 1) 89 | warn("Can't parse mapping count.\n"); 90 | break; 91 | case 't': 92 | timeout = atoi(optarg); 93 | break; 94 | case 'c': 95 | config_path = optarg; 96 | break; 97 | case 'r': 98 | redir_fd = open(optarg, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); 99 | if (redir_fd == -1) 100 | warn("Failed to open the command redirection file.\n"); 101 | break; 102 | case 's': 103 | fifo_path = optarg; 104 | break; 105 | case 'a': 106 | if (!parse_keysym(optarg, &abort_keysym)) { 107 | warn("Invalid keysym name: %s.\n", optarg); 108 | } 109 | break; 110 | } 111 | } 112 | 113 | num_extra_confs = argc - optind; 114 | extra_confs = argv + optind; 115 | 116 | if (config_path == NULL) { 117 | char *config_home = getenv(CONFIG_HOME_ENV); 118 | if (config_home != NULL) 119 | snprintf(config_file, sizeof(config_file), "%s/%s", config_home, CONFIG_PATH); 120 | else 121 | snprintf(config_file, sizeof(config_file), "%s/%s/%s", getenv("HOME"), ".config", CONFIG_PATH); 122 | } else { 123 | snprintf(config_file, sizeof(config_file), "%s", config_path); 124 | } 125 | 126 | if (fifo_path != NULL) { 127 | int fifo_fd = open(fifo_path, O_RDWR | O_NONBLOCK); 128 | if (fifo_fd != -1) { 129 | status_fifo = fdopen(fifo_fd, "w"); 130 | } else { 131 | warn("Couldn't open status fifo.\n"); 132 | } 133 | } 134 | 135 | signal(SIGINT, hold); 136 | signal(SIGHUP, hold); 137 | signal(SIGTERM, hold); 138 | signal(SIGUSR1, hold); 139 | signal(SIGUSR2, hold); 140 | signal(SIGALRM, hold); 141 | 142 | setup(); 143 | get_standard_keysyms(); 144 | get_lock_fields(); 145 | abort_chord = make_chord(abort_keysym, XCB_NONE, 0, XCB_KEY_PRESS, false, false); 146 | load_config(config_file); 147 | for (int i = 0; i < num_extra_confs; i++) 148 | load_config(extra_confs[i]); 149 | grab(); 150 | 151 | xcb_generic_event_t *evt; 152 | int fd = xcb_get_file_descriptor(dpy); 153 | 154 | fd_set descriptors; 155 | 156 | reload = toggle_grab = bell = chained = locked = false; 157 | running = true; 158 | 159 | xcb_flush(dpy); 160 | 161 | while (running) { 162 | FD_ZERO(&descriptors); 163 | FD_SET(fd, &descriptors); 164 | 165 | if (select(fd + 1, &descriptors, NULL, NULL, NULL) > 0) { 166 | while ((evt = xcb_poll_for_event(dpy)) != NULL) { 167 | uint8_t event_type = XCB_EVENT_RESPONSE_TYPE(evt); 168 | switch (event_type) { 169 | case XCB_KEY_PRESS: 170 | case XCB_KEY_RELEASE: 171 | case XCB_BUTTON_PRESS: 172 | case XCB_BUTTON_RELEASE: 173 | key_button_event(evt, event_type); 174 | break; 175 | case XCB_MAPPING_NOTIFY: 176 | mapping_notify(evt); 177 | break; 178 | default: 179 | PRINTF("received event %u\n", event_type); 180 | break; 181 | } 182 | free(evt); 183 | } 184 | } 185 | 186 | if (reload) { 187 | signal(SIGUSR1, hold); 188 | reload_cmd(); 189 | reload = false; 190 | } 191 | 192 | if (toggle_grab) { 193 | signal(SIGUSR2, hold); 194 | toggle_grab_cmd(); 195 | toggle_grab = false; 196 | } 197 | 198 | if (bell) { 199 | signal(SIGALRM, hold); 200 | put_status(TIMEOUT_PREFIX, "Timeout reached"); 201 | abort_chain(); 202 | bell = false; 203 | } 204 | 205 | if (xcb_connection_has_error(dpy)) { 206 | warn("The server closed the connection.\n"); 207 | running = false; 208 | } 209 | } 210 | 211 | if (redir_fd != -1) { 212 | close(redir_fd); 213 | } 214 | 215 | if (status_fifo != NULL) { 216 | fclose(status_fifo); 217 | } 218 | 219 | ungrab(); 220 | cleanup(); 221 | destroy_chord(abort_chord); 222 | xcb_key_symbols_free(symbols); 223 | xcb_disconnect(dpy); 224 | return EXIT_SUCCESS; 225 | } 226 | 227 | void key_button_event(xcb_generic_event_t *evt, uint8_t event_type) 228 | { 229 | xcb_keysym_t keysym = XCB_NO_SYMBOL; 230 | xcb_button_t button = XCB_NONE; 231 | bool replay_event = false; 232 | uint16_t modfield = 0; 233 | uint16_t lockfield = num_lock | caps_lock | scroll_lock; 234 | parse_event(evt, event_type, &keysym, &button, &modfield); 235 | modfield &= ~lockfield & MOD_STATE_FIELD; 236 | if (keysym != XCB_NO_SYMBOL || button != XCB_NONE) { 237 | hotkey_t *hk = find_hotkey(keysym, button, modfield, event_type, &replay_event); 238 | if (hk != NULL) { 239 | run(hk->command, hk->sync); 240 | put_status(COMMAND_PREFIX, hk->command); 241 | } 242 | } 243 | switch (event_type) { 244 | case XCB_BUTTON_PRESS: 245 | case XCB_BUTTON_RELEASE: 246 | if (replay_event) 247 | xcb_allow_events(dpy, XCB_ALLOW_REPLAY_POINTER, XCB_CURRENT_TIME); 248 | else 249 | xcb_allow_events(dpy, XCB_ALLOW_SYNC_POINTER, XCB_CURRENT_TIME); 250 | break; 251 | case XCB_KEY_PRESS: 252 | case XCB_KEY_RELEASE: 253 | if (replay_event) 254 | xcb_allow_events(dpy, XCB_ALLOW_REPLAY_KEYBOARD, XCB_CURRENT_TIME); 255 | else 256 | xcb_allow_events(dpy, XCB_ALLOW_SYNC_KEYBOARD, XCB_CURRENT_TIME); 257 | break; 258 | } 259 | xcb_flush(dpy); 260 | } 261 | 262 | void mapping_notify(xcb_generic_event_t *evt) 263 | { 264 | if (!mapping_count) 265 | return; 266 | xcb_mapping_notify_event_t *e = (xcb_mapping_notify_event_t *) evt; 267 | PRINTF("mapping notify %u %u\n", e->request, e->count); 268 | if (e->request == XCB_MAPPING_POINTER) 269 | return; 270 | if (xcb_refresh_keyboard_mapping(symbols, e) == 1) { 271 | destroy_chord(abort_chord); 272 | get_lock_fields(); 273 | reload_cmd(); 274 | abort_chord = make_chord(abort_keysym, XCB_NONE, 0, XCB_KEY_PRESS, false, false); 275 | if (mapping_count > 0) 276 | mapping_count--; 277 | } 278 | } 279 | 280 | void setup(void) 281 | { 282 | int screen_idx; 283 | dpy = xcb_connect(NULL, &screen_idx); 284 | if (xcb_connection_has_error(dpy)) 285 | err("Can't open display.\n"); 286 | xcb_screen_t *screen = NULL; 287 | xcb_screen_iterator_t screen_iter = xcb_setup_roots_iterator(xcb_get_setup(dpy)); 288 | for (; screen_iter.rem; xcb_screen_next(&screen_iter), screen_idx--) { 289 | if (screen_idx == 0) { 290 | screen = screen_iter.data; 291 | break; 292 | } 293 | } 294 | if (screen == NULL) 295 | err("Can't acquire screen.\n"); 296 | root = screen->root; 297 | if ((shell = getenv(SXHKD_SHELL_ENV)) == NULL && (shell = getenv(SHELL_ENV)) == NULL) 298 | err("The '%s' environment variable is not defined.\n", SHELL_ENV); 299 | symbols = xcb_key_symbols_alloc(dpy); 300 | hotkeys_head = hotkeys_tail = NULL; 301 | progress[0] = '\0'; 302 | 303 | snprintf(sxhkd_pid, MAXLEN, "%i", getpid()); 304 | setenv("SXHKD_PID", sxhkd_pid, 1); 305 | } 306 | 307 | void cleanup(void) 308 | { 309 | PUTS("cleanup"); 310 | hotkey_t *hk = hotkeys_head; 311 | while (hk != NULL) { 312 | hotkey_t *next = hk->next; 313 | destroy_chain(hk->chain); 314 | free(hk->cycle); 315 | free(hk); 316 | hk = next; 317 | } 318 | hotkeys_head = hotkeys_tail = NULL; 319 | } 320 | 321 | void reload_cmd(void) 322 | { 323 | PUTS("reload"); 324 | cleanup(); 325 | load_config(config_file); 326 | for (int i = 0; i < num_extra_confs; i++) 327 | load_config(extra_confs[i]); 328 | ungrab(); 329 | grab(); 330 | } 331 | 332 | void toggle_grab_cmd(void) 333 | { 334 | PUTS("toggle grab"); 335 | if (grabbed) { 336 | ungrab(); 337 | } else { 338 | grab(); 339 | } 340 | } 341 | 342 | void hold(int sig) 343 | { 344 | if (sig == SIGHUP || sig == SIGINT || sig == SIGTERM) 345 | running = false; 346 | else if (sig == SIGUSR1) 347 | reload = true; 348 | else if (sig == SIGUSR2) 349 | toggle_grab = true; 350 | else if (sig == SIGALRM) 351 | bell = true; 352 | } 353 | 354 | void put_status(char c, const char *s) 355 | { 356 | if (status_fifo == NULL) { 357 | return; 358 | } 359 | fprintf(status_fifo, "%c%s\n", c, s); 360 | fflush(status_fifo); 361 | } 362 | -------------------------------------------------------------------------------- /src/sxhkd.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #ifndef SXHKD_SXHKD_H 26 | #define SXHKD_SXHKD_H 27 | 28 | #include 29 | #include 30 | #include 31 | #include "types.h" 32 | #include "helpers.h" 33 | 34 | #define CONFIG_HOME_ENV "XDG_CONFIG_HOME" 35 | #define SXHKD_SHELL_ENV "SXHKD_SHELL" 36 | #define SHELL_ENV "SHELL" 37 | #define CONFIG_PATH "sxhkd/sxhkdrc" 38 | #define HOTKEY_PREFIX 'H' 39 | #define COMMAND_PREFIX 'C' 40 | #define BEGIN_CHAIN_PREFIX 'B' 41 | #define END_CHAIN_PREFIX 'E' 42 | #define TIMEOUT_PREFIX 'T' 43 | #define TIMEOUT 3 44 | 45 | extern xcb_connection_t *dpy; 46 | extern xcb_window_t root; 47 | extern xcb_key_symbols_t *symbols; 48 | 49 | extern char *shell; 50 | extern char config_file[MAXLEN]; 51 | extern char *config_path; 52 | extern char **extra_confs; 53 | extern int num_extra_confs; 54 | extern int redir_fd; 55 | extern FILE *status_fifo; 56 | extern char progress[3 * MAXLEN]; 57 | extern int mapping_count; 58 | extern int timeout; 59 | 60 | extern hotkey_t *hotkeys_head, *hotkeys_tail; 61 | extern bool running, grabbed, toggle_grab, reload, bell, chained, locked; 62 | extern xcb_keysym_t abort_keysym; 63 | extern chord_t *abort_chord; 64 | 65 | extern uint16_t num_lock; 66 | extern uint16_t caps_lock; 67 | extern uint16_t scroll_lock; 68 | 69 | void key_button_event(xcb_generic_event_t *evt, uint8_t event_type); 70 | void mapping_notify(xcb_generic_event_t *evt); 71 | void setup(void); 72 | void cleanup(void); 73 | void reload_cmd(void); 74 | void toggle_grab_cmd(void); 75 | void hold(int sig); 76 | void put_status(char c, const char *s); 77 | 78 | #endif 79 | -------------------------------------------------------------------------------- /src/types.c: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "parse.h" 31 | #include "grab.h" 32 | 33 | hotkey_t *find_hotkey(xcb_keysym_t keysym, xcb_button_t button, uint16_t modfield, uint8_t event_type, bool *replay_event) 34 | { 35 | int num_active = 0; 36 | int num_locked = 0; 37 | hotkey_t *result = NULL; 38 | 39 | for (hotkey_t *hk = hotkeys_head; hk != NULL; hk = hk->next) { 40 | chain_t *c = hk->chain; 41 | if ((chained && c->state == c->head) || (locked && c->state != c->tail)) 42 | continue; 43 | if (match_chord(c->state, event_type, keysym, button, modfield)) { 44 | if (status_fifo != NULL && num_active == 0) { 45 | if (!chained) { 46 | snprintf(progress, sizeof(progress), "%s", c->state->repr); 47 | } else { 48 | strncat(progress, ";", sizeof(progress) - strlen(progress) - 1); 49 | strncat(progress, c->state->repr, sizeof(progress) - strlen(progress) - 1); 50 | } 51 | put_status(HOTKEY_PREFIX, progress); 52 | } 53 | if (replay_event != NULL && c->state->replay_event) 54 | *replay_event = true; 55 | if (c->state->lock_chain) { 56 | num_locked += 1; 57 | if (timeout > 0) 58 | alarm(0); 59 | } 60 | if (c->state == c->tail) { 61 | if (hk->cycle != NULL) { 62 | unsigned char delay = hk->cycle->delay; 63 | hk->cycle->delay = (delay == 0 ? hk->cycle->period - 1 : delay - 1); 64 | if (delay == 0) 65 | result = hk; 66 | continue; 67 | } 68 | if (chained && !locked) 69 | abort_chain(); 70 | return hk; 71 | } else { 72 | c->state = c->state->next; 73 | num_active++; 74 | grab_chord(c->state); 75 | } 76 | } else if (chained) { 77 | if (!locked && c->state->event_type == event_type) 78 | c->state = c->head; 79 | else 80 | num_active++; 81 | } 82 | } 83 | 84 | if (result != NULL) 85 | return result; 86 | 87 | if (num_locked > 0) { 88 | locked = true; 89 | } 90 | 91 | if (!chained) { 92 | if (num_active > 0) { 93 | chained = true; 94 | put_status(BEGIN_CHAIN_PREFIX, "Begin chain"); 95 | grab_chord(abort_chord); 96 | } 97 | } else if (num_active == 0 || match_chord(abort_chord, event_type, keysym, button, modfield)) { 98 | abort_chain(); 99 | return find_hotkey(keysym, button, modfield, event_type, replay_event); 100 | } 101 | if (chained && !locked && timeout > 0) 102 | alarm(timeout); 103 | PRINTF("num active %i\n", num_active); 104 | 105 | return NULL; 106 | } 107 | 108 | bool match_chord(chord_t *chord, uint8_t event_type, xcb_keysym_t keysym, xcb_button_t button, uint16_t modfield) 109 | { 110 | for (chord_t *c = chord; c != NULL; c = c->more) 111 | if (c->event_type == event_type && c->keysym == keysym && c->button == button && (c->modfield == XCB_MOD_MASK_ANY || c->modfield == modfield)) 112 | return true; 113 | return false; 114 | } 115 | 116 | bool chains_interfere(chain_t* a, chain_t* b) { 117 | chord_t* i = a->head; 118 | chord_t* j = b->head; 119 | for (; i && j; i = i->next, j = j->next) { 120 | bool match = false; 121 | for (chord_t* k = i; k; k = k->more) { 122 | if (match_chord(j, k->event_type, k->keysym, k->button, k->modfield)) { 123 | match = true; 124 | break; 125 | } 126 | } 127 | if (!match) { 128 | break; 129 | } 130 | } 131 | bool result = !i || !j; 132 | return result; 133 | } 134 | 135 | chord_t *make_chord(xcb_keysym_t keysym, xcb_button_t button, uint16_t modfield, uint8_t event_type, bool replay_event, bool lock_chain) 136 | { 137 | chord_t *chord; 138 | if (button == XCB_NONE) { 139 | chord_t *prev = NULL; 140 | chord_t *orig = NULL; 141 | xcb_keycode_t *keycodes = keycodes_from_keysym(keysym); 142 | if (keycodes != NULL) { 143 | for (xcb_keycode_t *kc = keycodes; *kc != XCB_NO_SYMBOL; kc++) { 144 | xcb_keysym_t natural_keysym = xcb_key_symbols_get_keysym(symbols, *kc, 0); 145 | for (unsigned char col = 0; col < KEYSYMS_PER_KEYCODE; col++) { 146 | xcb_keysym_t ks = xcb_key_symbols_get_keysym(symbols, *kc, col); 147 | if (ks == keysym) { 148 | uint16_t implicit_modfield = (col & 1 ? XCB_MOD_MASK_SHIFT : 0) | (col & 2 ? modfield_from_keysym(Mode_switch) : 0); 149 | uint16_t explicit_modfield = modfield | implicit_modfield; 150 | chord = malloc(sizeof(chord_t)); 151 | bool unique = true; 152 | for (chord_t *c = orig; unique && c != NULL; c = c->more) 153 | if (c->modfield == explicit_modfield && c->keysym == natural_keysym) 154 | unique = false; 155 | if (!unique) { 156 | free(chord); 157 | break; 158 | } 159 | chord->keysym = natural_keysym; 160 | chord->button = button; 161 | chord->modfield = explicit_modfield; 162 | chord->next = chord->more = NULL; 163 | chord->event_type = event_type; 164 | chord->replay_event = replay_event; 165 | chord->lock_chain = lock_chain; 166 | if (prev != NULL) 167 | prev->more = chord; 168 | else 169 | orig = chord; 170 | prev = chord; 171 | PRINTF("key chord %u %u\n", natural_keysym, explicit_modfield); 172 | break; 173 | } 174 | } 175 | } 176 | } else { 177 | warn("No keycodes found for keysym %u.\n", keysym); 178 | } 179 | free(keycodes); 180 | chord = orig; 181 | } else { 182 | chord = malloc(sizeof(chord_t)); 183 | chord->keysym = keysym; 184 | chord->button = button; 185 | chord->modfield = modfield; 186 | chord->event_type = event_type; 187 | chord->replay_event = replay_event; 188 | chord->lock_chain = lock_chain; 189 | chord->next = chord->more = NULL; 190 | PRINTF("button chord %u %u\n", button, modfield); 191 | } 192 | return chord; 193 | } 194 | 195 | void add_chord(chain_t *chain, chord_t *chord) 196 | { 197 | if (chain->head == NULL) { 198 | chain->head = chain->tail = chain->state = chord; 199 | } else { 200 | chain->tail->next = chord; 201 | chain->tail = chord; 202 | } 203 | } 204 | 205 | chain_t *make_chain(void) 206 | { 207 | chain_t *chain = malloc(sizeof(chain_t)); 208 | chain->head = chain->tail = chain->state = NULL; 209 | return chain; 210 | } 211 | 212 | cycle_t *make_cycle(int delay, int period) 213 | { 214 | cycle_t *cycle = malloc(sizeof(cycle_t)); 215 | cycle->delay = delay; 216 | cycle->period = period; 217 | return cycle; 218 | } 219 | 220 | hotkey_t *make_hotkey(chain_t *chain, char *command) 221 | { 222 | hotkey_t *hk = malloc(sizeof(hotkey_t)); 223 | hk->chain = chain; 224 | hk->sync = false; 225 | if (command[0] == SYNCHRONOUS_CHAR) { 226 | command = lgraph(command+1); 227 | hk->sync = true; 228 | } 229 | snprintf(hk->command, sizeof(hk->command), "%s", command); 230 | hk->cycle = NULL; 231 | hk->next = hk->prev = NULL; 232 | return hk; 233 | } 234 | 235 | void add_hotkey(hotkey_t *hk) 236 | { 237 | if (hotkeys_head == NULL) { 238 | hotkeys_head = hotkeys_tail = hk; 239 | } else { 240 | hotkeys_tail->next = hk; 241 | hk->prev = hotkeys_tail; 242 | hotkeys_tail = hk; 243 | } 244 | } 245 | 246 | void abort_chain(void) 247 | { 248 | PUTS("abort chain"); 249 | put_status(END_CHAIN_PREFIX, "End chain"); 250 | for (hotkey_t *hk = hotkeys_head; hk != NULL; hk = hk->next) 251 | hk->chain->state = hk->chain->head; 252 | chained = false; 253 | locked = false; 254 | if (timeout > 0) 255 | alarm(0); 256 | ungrab(); 257 | grab(); 258 | } 259 | 260 | void destroy_chain(chain_t *chain) 261 | { 262 | chord_t *c = chain->head; 263 | while (c != NULL) { 264 | chord_t *n = c->next; 265 | destroy_chord(c); 266 | c = n; 267 | } 268 | free(chain); 269 | } 270 | 271 | void destroy_chord(chord_t *chord) 272 | { 273 | chord_t *c = chord->more; 274 | while (c != NULL) { 275 | chord_t *n = c->more; 276 | free(c); 277 | c = n; 278 | } 279 | free(chord); 280 | } 281 | -------------------------------------------------------------------------------- /src/types.h: -------------------------------------------------------------------------------- 1 | /* Copyright (c) 2013, Bastien Dejean 2 | * All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions are met: 6 | * 7 | * 1. Redistributions of source code must retain the above copyright notice, this 8 | * list of conditions and the following disclaimer. 9 | * 2. Redistributions in binary form must reproduce the above copyright notice, 10 | * this list of conditions and the following disclaimer in the documentation 11 | * and/or other materials provided with the distribution. 12 | * 13 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 14 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR 17 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 20 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 | */ 24 | 25 | #ifndef SXHKD_TYPES_H 26 | #define SXHKD_TYPES_H 27 | 28 | #include 29 | #include 30 | #include "helpers.h" 31 | 32 | #define KEYSYMS_PER_KEYCODE 4 33 | #define MOD_STATE_FIELD 255 34 | #define ESCAPE_KEYSYM 0xff1b 35 | #define SYNCHRONOUS_CHAR ';' 36 | 37 | extern xcb_keysym_t Mode_switch; 38 | 39 | typedef struct chord_t chord_t; 40 | struct chord_t { 41 | char repr[MAXLEN]; 42 | xcb_keysym_t keysym; 43 | xcb_button_t button; 44 | uint16_t modfield; 45 | uint8_t event_type; 46 | bool replay_event; 47 | bool lock_chain; 48 | chord_t *next; 49 | chord_t *more; 50 | }; 51 | 52 | typedef struct { 53 | chord_t *head; 54 | chord_t *tail; 55 | chord_t *state; 56 | } chain_t; 57 | 58 | typedef struct { 59 | int period; 60 | int delay; 61 | } cycle_t; 62 | 63 | typedef struct hotkey_t hotkey_t; 64 | struct hotkey_t { 65 | chain_t *chain; 66 | char command[2 * MAXLEN]; 67 | bool sync; 68 | cycle_t *cycle; 69 | hotkey_t *next; 70 | hotkey_t *prev; 71 | }; 72 | 73 | typedef struct { 74 | char *name; 75 | xcb_keysym_t keysym; 76 | } keysym_dict_t; 77 | 78 | hotkey_t *find_hotkey(xcb_keysym_t keysym, xcb_button_t button, uint16_t modfield, uint8_t event_type, bool *replay_event); 79 | bool match_chord(chord_t *chord, uint8_t event_type, xcb_keysym_t keysym, xcb_button_t button, uint16_t modfield); 80 | bool chains_interfere(chain_t* a, chain_t* b); 81 | chord_t *make_chord(xcb_keysym_t keysym, xcb_button_t button, uint16_t modfield, uint8_t event_type, bool replay_event, bool lock_chain); 82 | void add_chord(chain_t *chain, chord_t *chord); 83 | chain_t *make_chain(void); 84 | cycle_t *make_cycle(int delay, int period); 85 | hotkey_t *make_hotkey(chain_t *chain, char *command); 86 | void add_hotkey(hotkey_t *hk); 87 | void abort_chain(void); 88 | void destroy_chain(chain_t *chain); 89 | void destroy_chord(chord_t *chord); 90 | 91 | #endif 92 | --------------------------------------------------------------------------------