ComputersHow to modify a keyboard layout in Linux

Or: how to define a programmer-friendl(er) Spanish keyboard.
…and you can add Greek, too!

A bit of history

There was a time when the computers all had the same keyboard — basically, the US one. You really do not need any more; the set of characters that could be represented where, after all, just the ASCII set — so you could not really write a “ñ” or a “è”, so no problem arose. Programming languages where designed around that limitation, and everyone was happy.

Unless you need to write something in a language that’s not English, I mean. Not using diacritics is a no-no in most romance languages; “año” is not the same word without the tilde over the “n”, and in Italian “perché” without an accent switch the meaning from a question to a school of fishes.

So the character set was extended, unfortunately in a very bad way.  The idea of having tens of individual codings for different national glyphs created a nightmare that is still with us… And in parallel, the same bad idea was adopted for keyboards. Instead of extending the de-facto  standard keyboard (at least for Western European languages that was not a big deal), tens of national keyboards where invented. In Italy, for example, keys for the accented vowel were added, àèéìòóù… and useless things like { and } were omitted for lack of space. Nice.

Try to write a C program in that keyboard; you need finger contortions every time you need a brace, when the real solution (adding a couple of dead keys, the same for every keyboard, and forget the mess) was so handy… So I still think that the better solution and the better keyboard is the US one, with the AltGr-international mapping.

One example: the Spanish keyboard.

But what if you have a different keyboard? I live in Spain (normally), and if you buy a laptop, chances are that you can’t choose a keyboard. Now, with the Spanish keyboard is possible to live with (contrary to the Italian one which is without any hope). All symbols are at hand, minus, basically, one… the non-dead grave: `. This key is present only as a “dead-key”, in other words, a key that you need to press before another one to modify it. For example, pressing the key “dead_grave” and e gives you an “è”. For typing a bare “`”, you need to press space after the key.

Unfortunately, this key is basic in vim (and other vi-kind editors), and in a lot of programming languages. Especially in vim, you often use it “blindly”, in movement commands, and it is highly p***ing to have to stroke two keys for it.

The layout is like this one:

Spanish default keyboard layout

where the orange keys are “dead” keys. Notice that in the right, correct and just position where the “grave” symbol should be we have a key for “º” and “ª”… which I use maybe once in a bluemoon. Even writing in Spanish. So I decided that this thing must change. And while at it, I will remap a couple more chars that I think are highly mis-thinked in that keyboard.

How? After a lot of hassle, I discovered how to tame the incredibly flexible and (over?)complex keyboard system on my Linux. Let’s start.

Changing your keyboard layout.

Once upon a time, you just used  xmodmap and the .Xmodmap file. Too easy; now with the need of multiple input methods and layout that trick does not work so well. The layout is changed, yes, but it will be reset to the standard one in a lot of strange occasions… mysteries of the XKB protocol; the official documentation is a bit, ehem, sparse… A better written document is Doug Palmer’s guide, although I feel really represented from the first quote on that page.

I want just small changes, so my idea was to add a variant to the keyboard, to have a layout like this one:

New layout for my Spanish keyboard

Changes are in green. I want to change the upper left key to have “`” and “~” as first functions, and move the “º” and “ª” symbols under the AltGr-modifier. This make me lose the backslash  “\”; I  will remap it instead of “ç” which I never use (it’s not used in Spanish, nor in Italian. It’s here for the Catalan variant of the keyboard). Should I need it, I can use the compose key and type it as  Compose, c, and ,  (comma);  you can type anything with the Compose key trick.

So, let’s start. The main keyboard definition file for the Spanish keyboard is in /usr/share/X11/xkb/symbols/es. Make a copy of that file, then open it and study it a bit.  You can see that it defines the spanish keyboard based on the standard latin (type4) one at the start:

default partial alphanumeric_keys
xkb_symbols "basic" {

include "latin(type4)"


key <AE01> { [ 1, exclam, bar, exclamdown ] };

and then goes on and defines a bunch of keys, as for example the one show there: the key “1” will emit the number “1” when pressed alone, the key “exclam” (!)  when pressed with shift, the “bar”  (|) when pressed with Alt-Gr, and the reverse exclamation sign “exclamdown” (¡) with shift+AltGr.

The key names (the one like <AE01>) can be found here or generated by the command

xkbprint -label name -o $DISPLAY; ps2pdf

which will give you a nice PDF file (the .ps will create problem to the viewer…). For the name of the symbols, you can use the table for the compose char.

Then the file will start to define variants, like for example one that changes the position of the dead keys:

partial alphanumeric_keys
xkb_symbols "Sundeadkeys" {

    include "es(basic)"

    key  <AC11> { [dead_acute, dead_diaeresis, braceleft, braceleft ]   };
    key  <AD11> { [dead_grave, dead_circumflex, bracketleft, dead_abovering ] };

My plan is to add my personal variant to the keyboard. I would love to be able do do that without touching the system files, but I did not find how… so let’s modify these files.

Go to the end of the file /usr/share/X11/xkb/symbols/es, make a backup of it, and add this stanza:

partial alphanumeric_keys
xkb_symbols "standard_tlde" {

    include "es(basic)"

    key <TLDE>	{ [ grave,     asciitilde,  masculine,    ordfeminine ]	};
    key <BKSL>	{ [ backslash, bar,         braceright,   dead_breve ]	};

This will add a variant to the keyboard, called “standard_tlde” (TLDE is the name of the physical key that is the main change…). You can choose your name here.

Now you need to tell to the system that this keyboard variant is to be visible on the outside. You have to edit four more files for this, all situated in /usr/share/X11/xkb/rules; the files are evdev.lst, evdev.xml, base.lst, base.xml.

In the two files ending with .lst you should add this line:

standard_tlde   es: Spanish (your comment here) 

somewhere near the definition of Spanish variants. For example, I added it after the entry for “deadtilde”, modifying the file from:

  deadtilde       es: Spanish (include dead tilde)
  sundeadkeys     es: Spanish (Sun dead keys)

to this one:

  deadtilde       es: Spanish (include dead tilde)
  standard_tlde   es: Spanish (grave and asciitilde on TLDE, backslash on ccedilla)
  sundeadkeys     es: Spanish (Sun dead keys)

(make exactly the same modification in the two files. It works, don’t ask. I do not know why).

A similar modification must be made to the two .xml files, again the same for the two. Find the stanza that says:

            <description>Spanish (include dead tilde)</description>

and immediately after add:

            <description>Spanish (grave and asciitilde on TLDE, backslash on ccedilla)</description>

Congratulations: You’re done. Now you can (maybe after a logout and a new login) choose the new layout in whatever interface present your distribution/desktop environment. This is an example on a Xubuntu control panel:

Choosing variant layout on Xubuntu

If the new layout seems to not work…

Maybe you need to clean the xkb cache:

cd /var/lib/xkb/
rm *.xkm

(as root, or add the appropriate sudo), and then restarting the X server.

Links and references.

Beside the one scattered around the post, you can have a look at these one too, which helped me in this quest.

4 comments to How to modify a keyboard layout in Linux

Leave a Reply

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>