Xmodmap

From Deskthority wiki
Jump to navigation Jump to search
Development status Active
Operating system Linux, BSD
Type Utility software
License GNU General Public License 2

xmodmap is a utility for modifying X Server keymaps and pointer (mouse) button mappings. It can also be used as a tool to display the current keymaps and mouse button mappings as functional within the X Server. An important thing to keep in mind, XModMap "modifies" the current layout. Due to it's design, it cannot completely replace XKB as the ultimate way to set keyboard layouts for X. Adding alternate layers is not possible with xmodmap unless they are previously set with XKB, these include (but not limited to) the functionality such as dead grave keys as well as the compose key.

XModMap is considerably easier to understand and use than compared to XKB as it is very overwhelming as it has a lot of feature bloat.

Like loadkeys, xmodmap works with a configuration file that specifies all of the keysyms that are to be changed. As well, only the keys that are specified to be changed, are changed. The rest are left as per the previous configuration.

Desktop Environments (DE) and/or Window Managers (WM) specific configurations for shortcuts does not apply here for binding keycodes. Some DE/WM specific environments may have their own extra set of layer that deals with shortcuts for certain functionality, such as switching between active windows, run programs, killing unresponsive programs via "point and click", etc. For such shortcut configurations it is best to check one's own DE/WM environments and to see how shortcuts are bound. KDE4 for instance has most of their shortcuts setup via global shortcuts. As such it does not conflict with xmodmap specific setups.

Introduction to XKB

XKB is a utility for modifying X server keymaps on a much larger scale compared to xmodmap. The utility allows ultimate functionality for one being able to write up as much as up to eight layers for keyboard bindings. The definition of keyboard bindings for instance is the case of:

  • Pressing alphanumeric to input the desired character on the screen.
  • Holding (or having Caps Lock) Shift key and pressing alphanumeric keys to attain either a set of characters with capitals as opposed to lowercase and/or to print a completely different character on the screen as per user's request.
  • Holding Alt Gr (or better known as Dead grave) key along with pressing alphanumeric keys to print out specific characters of user's preference. Notable examples of these may be found on ISO keyboards but are not restricted to only ISO keyboards as the keyboard mapping are done on the software level.
  • Holding both Shift and Alt Gr along with pressing alphanumeric keys to print out a potentially different set of characters based on user's preference. Again examples may be found on layouts that entails the need to use Alt Gr key to print out specific characters.

In addition to being able to map specific keys and their varied levels of printing certain characters on the screen (which is what xmodmap is practically capable of). XKB allows one to define how many layers should a keyboard layout have along with the amount of physical keys, etc. This is particularly handy for dealing with keyboards that have a fancy amount of keys and with one wanting to add many varied levels of character output however at the same time it adds more complexity to the issue.

TODO: Expand

TODO (Needed as xmodmap heavily depends on the state of XKB)

Basic xmodmap usage

xmodmap ideally works when it is executed to run a xmodmap specific configuration file. However xmodmap can also allow one to change parameters one at a time without the need to constantly reload the entire xmodmap specific configuration file.

xmodmap when executed to load a xmodmap specific configuration file it will be a little more resource demanding (more CPU specific) in the first few seconds or so when setting up the keyboard settings according to user requirements. Keep in mind that the initial period only lasts for a short period on a modern machine and during that time certain keys may not work depending on how it is setup. The benefits for this method is that when setup properly xmodmap can then be set to work in a more non-interactive mode thereby eliminating the need for the user to constantly interact with the program unless for instance when switching between differently sized keyboards for instance or keyboards that sends out different keycodes for certain keys.

For instance xmodmap is here is told to run a xmodmap specific configuration file named hhkb.xmodmap. The filename can be an arbitrary name as long as the contents specifically complies with xmodmap's "language". The way to execute it as such would be:

xmodmap hhkb.xmodmap

xmodmap when executed to run a specific string allows the user to load specific setups without the need for xmodmap to re-load the entire xmodmap setup that it was using. In other words, adding extra keycodes to make the system interpret certain commands that the keycode is equivalent to does not demand more of CPU usage compared to the former case above (when to load a xmodmap specific configuration file). In this particular case it also allows xmodmap to evaluate (to an extent) user's settings and throw any exception when there is an issue with the said command. If and when an exception happens on the interactive level, xmodmap does not apply the specific setup that the user requested. This is handy for those who are unfamiliar with the syntax for instance. Bear in mind that xmodmap does not ask the user whether or not to overwrite a certain configuration (e.g. keycode 111 = Enter on the current configuration and the new command replaces the Enter for Space) as xmodmap interprets that is exactly what the user wants without asking. Therefore it is always best to check the current configuration before modifying with the new one as once executing the new one will overwrite the old one without warning.

Example of where xmodmap is told to "test" and execute a single parameter for instance to swap Enter with Space for keycode 111 would be:

xmodmap -e "keycode 111  = space"

xmodmap can also print the current configuration setup as well as to show xmodmap's grammar (specific language/parameters) as well as plenty others. These information may be found via xmodmap -help, man/info pages.

xmodmap specific configuration file

xmodmap configuration file does not need to be concise however when dealing with multiple keyboards that have different layouts for certain keys, it is best to write a concise configuration file that way there would be no erroneous setup. Remember, the concept of "garbage in, garbage out" can also apply here.

When writing a configuration file there is no real need to be a specific layout (apart from using the correct syntaxes) to be set. However keeping a nice format of a xmodmap configuration file would not only be beneficial to a single person should they for instance share their xmodmap configuration file around.

xmodmap configuration file can be simply put into two groups for simplicity sake. The first group would be the keycodes and their specific output followed by shifts, locks, controls and mods (modifiers).

Modifiers are particularly handy for using keyboard modifiers to achieve a specific output. An example of this would be to use a Alt key to mimick AltGR behaviour so when for instance one holds down the AltGR key and presses the letter u on the keyboard (with the exact same keycode) it would appear on the screen as ü instead. However, modifiers will only work in combination of one modifier key at a time. If one wants to bind Ctrl+Alt+A to output as å, it will not work.

Up to five modifiers can be defined (shift keys for instance are an exception and as such cannot be used in the same manner as modifiers would work). By default the first "set" of commands from the keycode would be using the very first modifier. This does not mean that in order for one to type out the letter a they would need to hold Alt for instance in order for the machine to be able to produce the letter a on the screen. Rather as such the first set of modifiers would not only define the default behaviour of the keycode when received by the machine but when that first set of modifier is defined as such it would also output as it is. This is why in most default cases for the first set of modifiers are usually set as Alt keys.

For example, one wants to type the letter o on the keyboard, it would output as o. When setting the first modifier (mod1) to left Alt the output would still be outputted as o regardless if left Alt was held down or not. Again this is beneficial in cases where one wants to type out ö for instance they would be normally using the right Alt (mimicking AltGR behaviour) to output as intended and to not confuse programs that the first set of modifier is defined as ö which would most likely break the default behaviour of most programs.

Locks, controls are more or less the shifts in terms of default behaviour. That is when holding down either of the Shift keys, it would capitalise the letter being outputted. However one can redefine such cases if need be. Locks are lock keys such as Caps Lock, Num Lock and Scroll lock. Controls are both left and right Control keys respectively. Ideally when rebinding certain default behaviour of such groups of keys (whether it would be Controls, Shifts or Locks) it is best to not have the same key being defined in both their respective area as well as within the Modifiers area.

Here is an example of a xmodmap config file truncated for brevity:

keycode   8 =
keycode   9 = Escape NoSymbol Escape
keycode  10 = 1 exclam 1 exclam
keycode  11 = 2 quotedbl 2 quotedbl
keycode  12 = 3 numbersign 3 numbersign
keycode  13 = 4 dollar 4 dollar
keycode  14 = 5 percent 5 percent
keycode  15 = 6 ampersand 6 ampersand
keycode  16 = 7 apostrophe 7 apostrophe
keycode  17 = 8 parenleft 8 parenleft
keycode  18 = 9 parenright 9 parenright
keycode  19 = 0 kana_WO 0 kana_WO
keycode  20 = minus equal minus equal
keycode  21 = asciicircum asciitilde asciicircum asciitilde
keycode  22 = BackSpace NoSymbol BackSpace
keycode  23 = Tab ISO_Left_Tab Tab ISO_Left_Tab
keycode  24 = q Q q Q
keycode  25 = w W w W
keycode  26 = e E e E
keycode  27 = r R r R
...
keycode  255 = 
add shift   = Shift_L Shift_R
add lock    = Caps_Lock
add control = Control_L Control_R
add mod1    = Alt_L Alt_R
add mod2    = Num_Lock
add mod5    = Scroll_Lock 

In this case the example of the structured output is basically:

              Base Shift Alt_Gr Shift+Alt_Gr Compose(?) Shift+Compose(?)
keycode ?? =    ?     ?      ?        ?          ?              ?
  • Base is the character for X to emit when the key is pressed alone. In the example of above where keycode 27 is bound to the letter "r" pressing the key that emits the keycode "r" will emit just "r" on the screen.
  • Shift is the character for X to emit when the key is pressed along with holding Shift key. In the example of above where keycode 27 is bound to the letter "r" with the subsequent level of "R" to be printed will print out "R" on the screen instead of "r".
  • Alt_Gr is the character for X to emit when the key is pressed along with holding Alt_Gr key. In the example above it is not different to just pressing the base key but however when a keyboard is defined to have dead grave key functionality, it would print out whatever it is defined in either one's xmodmap configuration file or otherwise whatever is defined as per default on one of the XKB's keyboard maps. Should one compile a custom XKB map to use Alt_Gr keys for instance, the mapping for that will be used so long as it has been loaded. Normally Alt_Gr functionality is disabled by default.
  • Shift+Alt_Gr is the character for X to emit when the key is pressed along with holding both Shift and Alt_Gr key. Again this would not be enabled by default unless XKB has been notified to use a keyboard layout that bears Alt_Gr functionality along with specific indications to bind a key in order to enable Alt_Gr.
  • Compose is the character for X to emit when the key is pressed along with pressing the key reserved for Compose. At this point in time of writing, it is uncertain whether or not this last "group" of keys (Compose and Shift+Compose) is actually know as such however according to HaaTa whom referenced the various Xorg documentation; it is known as Group 5. For keepsakes a Compose key is noted instead. Again, Compose key cannot be activated nor used without XKB being notified to use a keyboard layout that has Compose key.
  • Shift+Compose is basically what is written as per above for Compose key.

In theory, it is possible to have up to eight layers in this specific setup. For instance one could have:

keycode  27 = r R paragraph registered Right Redo

Which basically implies:

  • Pressing the key that emits 27 emits "r".
  • Holding Shift key whilst pressing the key that emits 27 emits "R".
  • Holding Alt_Gr key whilst pressing the key that emits 27 emits the character "¶".
  • Holding Shift and Alt_Gr key whilst pressing the key that emits 27 emits the character "®".
  • Holding Compose key whilst pressing the key that emits 27 tells X to either go forward in character or do something in related to the arrow right key that a program has assigned the right arrow key to perform.
  • Holding Shift and Compose key whilst pressing the key that emits 27 tells X to Redo something that was undone usually.

TODO (expand)

Writing a xmodmap configuration file

There are a few notable ways (TODO: add sources) to enumerate the keycodes for use with xmodmap. Considering xmodmap is part of X11, it is ideal to use X11 related programs to harvest the keycodes for binding. In this case the simplest answer would be xev tool. The xev tool allows one to not only harvest keycodes and how the machine would translate the keycode as (or even show the current binding for that key) but it also allows one to track mouse pointers for instance and how they are referenced within the X11 environment. Inevitably there is a catch when using xev tool notably with the fact that the Event Tester window has to be active within the X11 environment.

Not all keyboards will emit the same keycode for a specific key whilst at the same time not all keyboards have unique functions such as gaming keyboards having "macro" keys or multimedia keyboard having all the audio related keys. Therefore again it is best to keep in mind when switching between keyboards or when writing up a comprehensive xmodmap it is vital for one to try and test as much keys as possible on the said keyboard.

Here is a sample output of xev running with its Event Tester window active and with the letter a pressed from the keyboard:

KeyPress event, serial 40, synthetic NO, window 0x3800001,
   root 0x1e1, subw 0x0, time 852024727, (122,40), root:(122,833),
   state 0x10, keycode 38 (keysym 0x61, a), same_screen YES,
   XLookupString gives 1 bytes: (61) "a"
   XmbLookupString gives 1 bytes: (61) "a"
   XFilterEvent returns: False

From this output, the only information needed when writing up a custom xmodmap file is the keycode mentioned. In this particular case, the keycode for the key a shows that it is keycode 38. Again bear in mind that not all keyboards may share the same keycode for all the keys.

As well as the keycode being mentioned here, xev also shows various other information. Extra information such as keysym, XLookupString and XmbLookupString shows that when the keycode 38 is being trapped by the machine - the machine interprets the keycode as the letter a.

Another way to enumerate keycodes apart from using xev is to use the xinput tool. Specifically under xinput there is a command that also shows keycodes being trapped by machine. However xinput also repeats the output of the said key on the same console as it is telling the keycode being pressed and released. Though one good benefit is that the xinput tool does not have Event Tester window unlike xev and hence does not require that window to be active in order to capture keycodes. The exact command for xinput to show the keycodes here is:

xinput test <device name>

One will need to replace the field <device name> with either the corresponding actual device number without the paranthesis or the name of the device in quotes and without paranthesis. In order to do that one will need to enumerate the list of devices along with the device number. Which can simply be done via:

xinput

Here is a sample output of xinput showing the list of input devices (anything that has a button which not only includes keyboards, mice, joysticks, etc but also power button for instance on the actual machine):

⎡ Virtual core pointer                          id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ Logitech USB-PS/2 Optical Mouse           id=8    [slave  pointer  (2)]
⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Power Button                              id=7    [slave  keyboard (3)]
    ↳ PFU Limited  HHKB Professional JP         id=10   [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=9    [slave  keyboard (3)]

As previously mentioned this is only a sample output, not everyone's setup will be exact same.

For the <device name> that one needs to use win conjunction with xinput test command and the example to base one (in this case the PFU Limited HHKB Professional JP is used) one could either start harvesting keycodes via either:

xinput test 10

or:

xinput test "PFU Limited  HHKB Professional JP"

Sample output of xinput with the letter a pressed and then released would show as this:

key release 36 
key press   38 
akey release 38 

Notice in this case how the very first line shows a completely different key code compared to the latter two lines. This is to show that the Enter key was released after the command was executed therefore the Enter key would have been caught by the machine and its keycode being shown. Along with the Enter keycode in this example is being shown, so too can one see on the last line of the output that there is an erroneous character proceeeding the word key. Again this is most likely due to an echo event from the keyboard or the program. The erroneous character does not necessarily have to be the letter a it can be whatever other characters one presses on the keyboard to harvest the keycode from. For instance the output can show bkey release 39. Regardless of the output the only relevant matter is the number that it is being outputted which is required for xmodmap.

To write xmodmap entry for the keycode 38 in this case one would need to write it as:

keycode  38 = a A

For simplicity sake only two groups (a and A) are shown. Notice how there is an extra space in between the last character e and the number 3. This is needed when writing xmodmap configuration file but only for keycode. The same case does not apply when writing modifiers.

Ideally it is best to dump a copy of the current xmodmap layout and then make minor changes as required. To do this one needs to dump the keymap table as well as their modifier separately into the same ASCII text file:

xmodmap -pke >> my.xmodmap

This command dumps the output of xmodmap's current keymap table as a form of expressions suitable for xmodmap to read and apply.

xmodmap -pm >> my.xmodmap

This command dumps the output xmodmap's current modifier map. The output is not exactly suitable for use with xmodmap as it lacks the add command (needed for appending keys to the modifier) as well as the redundant blank fields for modifiers that does not have any keys mapped to it.

Nonetheless the output is sufficient for either backing up one's current xmodmap setup and/or to base one's own custom xmodmap configuration file off.

For the list of allowed syntaxes in a xmodmap configuration file one should refer to:

xmodmap -grammar

TODO (include links to further reading)