APLawrence.com -  Resources for Unix and Linux Systems, Bloggers and the self-employed

2005/05/03 loadkeys, dumpkeys

© May 2005 Tony Lawrence

You can change the output of the Linux console keyboard with loadkeys. It's an extremely powerful command, and the man page can be confusing, but for simple use (which is often all we need it for), it's very easy.

For example, let's reprogram the F10 key:

echo 'string F10 = "foo" ' | loadkeys

See? That wasn't difficult. Oops, now what was the original value so we can put it back? Ahh, perhaps a little preparation would have been wise before changing that. The "dumpkeys" command does that:

dumpkeys > myfullkeymap
dumpkeys --funcs-only > funcsonlymap

The "funcs-only" map is short:

string F1 = "\033[[A"
string F2 = "\033[[B"
string F3 = "\033[[C"
string F4 = "\033[[D"
string F5 = "\033[[E"
string F6 = "\033[17~"
string F7 = "\033[18~"
string F8 = "\033[19~"
string F9 = "\033[20~"
string F10 = "\033[21~"
string F11 = "\033[23~"
string F12 = "033[24~"
string F13 = "\033[25~"
string F14 = "\033[26~"
string F15 = "\033[28~"
string F16 = "\033[29~"
string F17 = "\033[31~"
string F18 = "\033[32~"
string F19 = "\033[33~"
string F20 = "\033[34~"
string Find = "\033[1~"
string Insert = "\033[2~"
string Remove = "\033[3~"
string Select = "\033[4~"
string Prior = "\033[5~"
string Next = "\033[6~"
string Macro = "\033[M"
string Pause = "\033[P"

Yours will be different if you reprogrammed F10 above. Do this to put it back:

echo 'string F10 = "\033[21~" ' | loadkeys

If you had previously saved "funcsonlymap", you could put it all back with "loadkeys funcsonlymap" at any time, or simply use "loadkeys -d"

The full key map is much longer and can be confusing. The first thing you have to understand is how keyboards really work: they actually send a keycode (also called "scancodes"). The "A" key on your keyboard actually sends 30, and F10 sends 68. You can use "showkey" to see what keycodes are really being sent (just stop typing briefly and showkey will exit). In the full keymap dump, you'll find:

keycode  68 = F10              F22              Console_22       F34             
        alt     keycode  68 = Console_10
        control alt     keycode  68 = Console_10

And later in the same file you'll find:

string F10 = "\033[21~"

The last one is easy to understand, but what does the first part mean? Well, it defines key symbols, "keysms" in the "man keymaps" explanation. It's position dependent: F10 is the unshifted key, F22 is the shifted F10, but then we start getting confusing. The man page does a lousy job explaining it:

       Which  of  the actions bound to a given key is taken when it is pressed
       depends on what modifiers are in effect at that moment.   The  keyboard
       driver  supports  8  modifiers. These modifiers are labeled (completely
       arbitrarily) Shift, AltGr, Control,  Alt,  ShiftL,  ShiftR,  CtrlL  and
       CtrlR.   Each  of  these modifiers has an associated weight of power of
       two according to the following table:

              modifier                weight

              Shift                     1
              AltGr                     2
              Control                   4
              Alt                       8
              ShiftL                   16
              ShiftR                   32
              CtrlL                    64
              CtrlR                   128

       The effective action of a key is found out by adding up the weights  of
       all the modifiers in effect. By default, no modifiers are in effect, so
       action number zero, i.e. the one in the first column in a  key  defini-
       tion  line,  is  taken  when  the key is pressed or released. When e.g.
       Shift and Alt modifiers are in effect, action  number  nine  (from  the
       10th column) is the effective one.

       Changing  the  state of what modifiers are in effect can be achieved by
       binding appropriate key actions to desired keys. For  example,  binding
       the  symbol  Shift to a key sets the Shift modifier in effect when that
       key is pressed and cancels the effect of that modifier when the key  is
       released. Binding AltGr_Lock to a key sets AltGr in effect when the key
       is pressed and cancels the effect when the key is pressed  again.   (By
       default Shift, AltGr, Control and Alt are bound to the keys that bear a
       similar label; AltGr may denote the right Alt key.)

AltGr is the right hand Alt-Key, by the way. Later on, the man page helpfully tells us:

  To find out what keysyms there are available for use  in  keymaps,  use
       the command

              dumpkeys --long-info

       Unfortunately,  there  is  currently no description of what each symbol
       does. It has to be guessed from the name or figured out from the kernel

So, going back to that key 68 definition, it's easy to see that F22 is the shifted F10, and indeed we can redefine it with:

echo 'string F22 = "Foo" ' | loadkeys

But if you try that with Console_22, you'll get an error message from loadkeys. That's because it is one of the "actions" the man page is so vague about. It's defining the action for the right hand alt key and the function key. I could change it by replacing the keymap definition:

keycode  68 = F10              F22              F100       F34               
        alt     keycode  68 = Console_10
        control alt     keycode  68 = Console_10

And then set F100 to be what I want:

echo 'string F100 = "Foo" ' | loadkeys

And then Right Alt-F10 will send "Foo". That's fine. Or, I could leave it as it is and use it for what it is really intended for, but we'll save that for later. The next position (F34) should be (as I understand the man page ) Shift , Right Alt, and F10. It isn't. If I program F34, it's Control F10 that sends what I set F34 to. That makes no sense at all.

Let's take it slowly: Okey-dokey. It's binary, calculated back from position, right? Seems to make sense. After F22, position One. which obviously matches Shift, we have Console_22 in position Two. That should mean that it matches the AltGr or Right Alt key and indeed it does: if I enable tty22 in /etc/inittab, the AltGr-F10 will switch me to tty22 on the console.

The next position is Three and it's F34. I define F34 on the fly

echo 'string F34 = "Key34" ' | loadkeys

because it's undefined in my default keymap. I would expect, since it is position Three, that the modifiers would be Shift and Altgr - 2 + 1 equals 3, right?

Nope. Actually, Control F10 sends "Key34" after this. How does THAT make any sense?

It doesn't. And it gets more strange. If I modify that keymapping like this:

keycode  68 = F10              F22              Console_22       F34 F100 F101

and define F34, F100, and F101, it then works exactly as I would expect it to! Right Alt F10 sends the F34 string, Control F10 sends the F100, and Shift Control F10 sends the F101 string..

So why does it work differently by adding two keysyms???

And then I look farther down the table and see more confusion. How the heck can ShiftL (which I assume means Left Shift) be a modifier weight if Shift already is? Do I assume that to use those positions you'd have to NOT define the ordinary shift combination? That might make sense, but the man page doesn't explain that.

It is easy to get confused (obviously), so they also provide a shortcut:

The "alt keycode 68 = Console_10" is a shorthand way of defining alt plus F10 without stringing out the first keycode line to nine columns. Without that, you'd need nine entries (you can use VoidSymbol as a place holder for key combinations you don't care about) and you'd need thirteen to define CTRL-ALT-F10. So at the command line you can also do:

echo 'control alt     keycode  68 = F100'  | loadkeys

That lets us redefine the key combinations but still doesn't tell us what the mysterious "Console_" entries mean. The "control alt keycode 68 = Console_10" obviously defines the key that will switch to the "F10" virtual console. Let's try changing it:

echo 'control alt     keycode  68 = Console_3'  | loadkeys

With that in place, CTRL-ALT-F10 will switch to tty3. What about Console_22? Yes, that's a virtual console too - as long as you enable tty22 in inittab. If you have enabled tty22, then with the default keymap shown above, the right alt key and F10 will switch you to a virtual console on tty22.

There's more to keymaps, but this at least gets you started.

Got something to add? Send me email.

(OLDER)    <- More Stuff -> (NEWER)    (NEWEST)   

Printer Friendly Version

-> 2005/05/03 loadkeys, dumpkeys

Inexpensive and informative Apple related e-books:

El Capitan: A Take Control Crash Course

Take Control of iCloud, Fifth Edition

Take Control of High Sierra

iOS 8: A Take Control Crash Course

Take Control of Numbers

More Articles by © Tony Lawrence

Printer Friendly Version

Have you tried Searching this site?

This is a Unix/Linux resource website. It contains technical articles about Unix, Linux and general computing related subjects, opinion, news, help files, how-to's, tutorials and more.

Contact us

Printer Friendly Version

FORTRAN's tragic fate has been its wide acceptance, mentally chaining thousands and thousands of programmers to our past mistakes. (Edsger W. Dijkstra)

Linux posts

Troubleshooting posts

This post tagged:




Unix/Linux Consultants

Skills Tests

Unix/Linux Book Reviews

My Unix/Linux Troubleshooting Book

This site runs on Linode