Remapping keyboard

If you are not satisfied with your hardware keyboard layout, with root access (through rootsh or ssh) you can modify that as follows.


Permanent remap

You need to edit this file on your N900: /usr/share/X11/xkb/symbols/nokia_vndr/rx-51

Before editing it you should back it up first in case something goes wrong. Do not place the copy in the nokia_vndr folder or it will stop your phone from booting. Obviously all access to this file needs to be from the root account so use sudo or sudo gainroot.

After backing up you can then edit the file using a text editor such as leafpad, or vi from within the X terminal. (vi is not intuitive so if you have never used it before, read a manual and try it on another file first.)

After modifying the rx-51 file, type `setxkbmap' to apply any changes for English keyboards, `setxkbmap de' for German keyboards, etc. If you see an error you should replace the rx-51 file with your backup - if you don't the device will fail to boot and you'll have to reflash it!

Test all the keys, levels and language keyboards you have changed. If you are satisfied with your new rx-51 file, back it up as well. The next firmware upgrade might restore it to the factory default. Find some keyboard stickers if you have trouble remembering the keys you have set.

When making particularly intricate/complicated/fancy keyboard mappings, remember that order matters when pressing buttons. If you press your thumb on both Shift and FN (the blue up-right arrow key), even if you pressed them both at the same time, electronics is fast enough that the N900 registers Fn+Shift as different than Shift+Fn. For most remappings this doesn't matter because Shift is always Shift and Fn is always Fn, but you can map a special symbol onto one of them as a second level (so that an Fn'ed Shift is different than a normal shift, or a Shift'ed Fn is different than a normal Fn). This is also the same reason why you COULD make Ctrl+Fn+[Key] do something (like send dbus signals as is possible with the modified hildon desktop package by Matan that's now in the CSSU), and still get to the special symbol virtual keyboard using Fn+Ctrl. However this doesn't seem to affect the examples in this first section.

Remapping keyboard arrows

The N900 sold in English-speaking countries has 4 arrow keys, and there are no extra symbols attached to these. If you have a different device with 2 arrow keys you should be able to change the hardware keyboard layout in the equivalent of Settings-->Text Input.

The arrow key mappings are located at the end of the file. If your device is set to a 4-arrow key layout, this can be modified by editing the section under xkb_symbols "arrows_4btns" {. Note that this will change any other language layout that includes 4btns - which is every layout that has the normal four arrows instead of just two in the defult file (every layout includes either arrows_4btns or arrows_2btns, either directly or by including another layout that includes them) - indicated by include "nokia_vndr/rx51{arrows_4btns}" in the relevant language section.

(You can change the settings just for the English layout by copying the keys you want from the arrows section to beneath the line name[Group1] = "U.S. English";, near the top of the file. This means you could also do things like change the Polish keyboard to keys useful for programming, and change back to English for the standard keys, or vice versa if you are Polish. There are also faster but more complicated ways to use several layouts as mentioned further down this page.)

If you don't use accented characters you may want to add Page Up, Page Down, Home and End as in the following example. Pressing Fn+Left would send you to the beginning of a line.

partial hidden alphanumeric_keys
xkb_symbols "arrows_4btns" {
    key <UP>   { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Up, Page_Up ] };
    key <LEFT> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Left, Home ] };
    key <DOWN> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Down, Page_Down ] };
    key <RGHT> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Right, End ] };

The PC_FN_LEVEL2 setting allows combining the new keys with Shift for selecting text. For example, to select a large block of text more quickly, you can press Fn+Shift+Down, or press Fn twice to lock it and then press Shift+Down (which has become Shift+PageDown).

The next example shows how to add dead acuté, gravè, tilde~ and circumflêx accents used in Portuguese, Spanish, French, etc. To use these accents, press the relevant arrow key while holding down Fn, followed by the letter you want (i.e. a,c,e,i,n,o,u,y).

xkb_symbols "arrows_4btns" {
    key <UP>   { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Up, dead_circumflex ] };
    key <LEFT> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Left, dead_acute ] };
    key <DOWN> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Down, dead_tilde ] };
    key <RGHT> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Right, dead_grave ] };

This example adds German ä, ö, ü and ß:

xkb_symbols "arrows_4btns" {
    key <UP>   { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Up, udiaeresis ] };
    key <LEFT> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Left, odiaeresis ] };
    key <DOWN> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Down, adiaeresis ] };
    key <RGHT> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Right, ssharp ] };

This example adds Norwegian å, ø and æ, in an arrangement similar to the usual PC keyboard layout, plus the pipe "|" for convenient xterm use:

partial alphanumeric_keys                                                                                                                                   
xkb_symbols "us" {                                                                                                                                          
    include "nokia_vndr/rx-51(english_base)"                                                                                                                
    include "nokia_vndr/rx-51(arrows_4btns)"                                                                                                                
    name[Group1] = "U.S. English";                                                                                                                          
    key <UP>   { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Up, aring ] };                                                                          
    key <LEFT> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Left, oslash ] };                                                                       
    key <DOWN> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Down, ae ] };                                                                           
    key <RGHT> { type[Group1] = "PC_FN_LEVEL2", symbols[Group1] = [ Right, U007C ] };                                                                                     

A four level mapping is also possible in which Fn, Shift or Fn+Shift will all input something different. thp's mapping is helpful for a German speaker who also programs using Python, Vim and the Shell:

Fn+Up inputs %, Shift+Up inputs |. Fn/Shift+Down give the invisible special keys Tab and Escape. Left and Right are mapped so that Shift gives <>, Fn gives [] and Shift+Fn gives {}. Finally, Shift+Fn enters German characters (Up prepares a dead diäëresïs for Umlauts and Down inputs ß).

xkb_symbols "arrows_4btns" {
    key <UP>    { type[Group1] = "FOUR_LEVEL", symbols[Group1] = [      Up,     bar,    percent,        dead_diaeresis  ] };
    key <LEFT>  { type[Group1] = "FOUR_LEVEL", symbols[Group1] = [      Left,   less,   bracketleft,    braceleft       ] };
    key <DOWN>  { type[Group1] = "FOUR_LEVEL", symbols[Group1] = [      Down,   Escape, Tab,    ssharp  ] };
    key <RGHT>  { type[Group1] = "FOUR_LEVEL", symbols[Group1] = [      Right,  greater,        bracketright,   braceright      ] };

Example for keyboard with only two arrow keys

Non-English keyboards typically have only two keys for arrows, with Up and Down composed as Fn+Left and Fn+Right, respectively. If you want to change the arrow keys for all 2-arrow layouts, edit the "arrows_2btns" section just above the "arrows_4btns" one mentioned above.

It may also be useful to remap keys with accented characters, such that one of them is a dead accent, and the others are freed up for special characters that you want on the hardware keyboard.

For example, on a German N900 three keys are occupied by ä, ö and ü. The following modification changes the ü key into a dead diaeresis. Now to type ä, ö or ü, press the former ü key to load the diaeresis followed by a, o or u. This way one can also enter ë, ï and ÿ which occur in other languages.

partial alphanumeric_keys
xkb_symbols "de" {
    include "nokia_vndr/rx-51(english_base)"
    include "nokia_vndr/rx-51(arrows_2btns)"

    name[Group1] = "German";

    // 1. row
    key <AD06>  { [ z, Z, 6, 6 ] };
    // key <AB08> { [ udiaeresis, Udiaeresis, ssharp, ssharp ] };
    key <AB08>  { [ dead_diaeresis, asciicircum, ssharp, ssharp ] };

    // 2. row
    key <AC08>  { [ k,  K, semicolon, semicolon ] };
    key <AC09>  { [ l,  L, colon, colon ] };
    //key <AB09>  { [ odiaeresis, Odiaeresis, exclam, exclam ] };
    key <AB09>  { [ bracketleft, braceleft, exclam, exclam ] };
    //key <UP>  { [ adiaeresis, Adiaeresis, question, question ] };
    key <UP>    { [ bracketright, braceright, question, question ] };

    // 3. row
    key <AB01>  { [ y, Y, EuroSign, EuroSign ] };
    key <AB03>  { [ c, C, equal, equal ] };
    // key <SPCE>  { [ space, space, at, at ] };
    key <SPCE>  { [ space, asciitilde, at, at ] };
    //key <LEFT>  { [ period, comma, comma, comma ] };
    key <LEFT>  { [ period, bar, comma, comma ] };

The former ö, ä, Ö and Ä keys have been remapped to (brackets) and {braces} and the circumflex/exponent ^ to the former Ü key. Moreover, Shift-Space has been mapped to tilde~, the shortcut to your home directory (/home/user on the N900), and thus a character that can often occur in personal URLs. Shift+. has been mapped to the pipe/bar "|". (The original keymaps are shown commented out by prepending "//".)

Now type

setxkbmap de

to test and install the new keyboard mapping. The new keymap will be used until the rx-51 file is modified again.

The Italian layout maps the comma, period/fullstop, up and left keys to è, ò, à and comma. In this example, we'll put the four arrow keys back and add some dead accents to allow for all accent and letter combinations.

partial alphanumeric_keys
xkb_symbols "it" {
    include "nokia_vndr/rx-51(english_base)"
    // include "nokia_vndr/rx-51(arrows_2btns)"  USE 4 ARROW KEYS
    include "nokia_vndr/rx-51(arrows_4btns)"

    name[Group1] = "Italian";

    // 1. row
    //key <AB08>  { [ egrave, Egrave, eacute, Eacute ] };
    key <AB08>  { [ egrave, dead_grave, agrave, dead_acute ] };

    // 2. row
    key <AC06>  { [ h, H, semicolon, semicolon ] };
    key <AC07>  { [ j, J, colon, colon ] };
    key <AC08>  { [ k, K, exclam, exclam ] };
    key <AC09>  { [ l, L, question, question ] };
    //key <AB09>  { [ ograve, Ograve, igrave, Igrave ] };
    key <AB09>  { [ period, comma, ograve, Igrave ] };
    //key <UP>  { [ agrave, Agrave, ugrave, Ugrave ] };

    // 3. row
    key <AB01>  { [ z, Z, EuroSign, EuroSign ] };
    key <AB02>  { [ x, X, parenleft, parenleft ] };
    key <AB03>  { [ c, C, parenright, parenright ] };
    //key <LEFT>  { [ period, comma, comma, comma ] };

With this setup, you have dead grave and acute accents on Shift+è and Fn-Shift+è, and you have à on Fn+è. Period and comma have been moved to the ò key, as ò and Shift+ò, while ò and ì are on that key, as Fn+ò and Fn-Shift+ò. There's no key for the ù character, but you can write it using the dead accents (Shift-è and then u).

Of couse all these are just examples. You can add any symbol you like (such as F1-F12) and remap any keys, not just the arrows.

If you can't find the name of a symbol that you want, take a look at this list of standard PC keyboard layouts as an example:

An alternative approach for getting custom special characters is to edit the Special characters view.

Note: the pipe symbol | is called "bar".

Multiple Layouts

The keyboard can also support multiple layouts, which you can cycle through. A full understanding of the details can be better acquired through reading up on xkb documentation, however, there are some easy to follow ways of creating multiple layouts without forcing yourself to use the N900's stock eight-level layout.

There are a couple of advantages to this: You can fully use all the levels of the keyboard map - as mentioned in the known bugs section below, it seems that editing levels 7 and 8 on the eight level keymaps is useless because levels 3 and 4 override them anyway. You can also have more than just two layouts, allowing you to rotate between many different languages or symbol combinations, rather than just the two sets of characters you can fill in the eight-(effectively six)-level keymappings.

The simple way to test this model is typing setxkbmap -layout [code for layout one],[code for layout two],[etc...] The only issue is that on a stock N900, the keymap file is located deeper in the symbols directory than normal - as a result, if you do not have extkbd or bt-hid-scripts installed, the code for the standard English layout is just "us", "ru" for Russian, etc, and they are entered normally, so if you wanted to make your layout Russian, then English, you would map it like so: setxkbmap -layout ru,us However, if you have extkbd, bt-hid-scripts, or another package that installs extra external keyboard xkb mappings, for some reason, the N900 assumes that the first layout comes from the ...nokia_vndr/rx-51 file, but does not make this assumption for the following layouts. Thus, the above code would use the N900's correct Russian key mapping, but would use a standard external keyboard map for the "us" layout - which does not come with any of the third or forth level mappings for each key.

Thus, if you also use external keyboards with the available bt-hid-scripts or extkbd packages, when specifying multiple layouts (assuming you want them all to come from the rx-51 file), you need to specify the layout's path, relative to the /usr/share/X11/xkb/symbols/ folder. For the example above, with Russian followed by English, you would do: setxkbmap -layout ru,'nokia_vndr/rx-51(us)' Explanation: the first layout assumes it's coming from the rx-51 file for some reason, but the following layouts default to the main xkb key map directory (/usr/share/X11/xkb/symbols/). So you first specify the folder, nokia_vndr, that the rx-51 file resides in (standard / use to designate the path is used); then you specify the rx-51 file; then, because there is more than one mapping inside the rx-51 file, you specify the code of the map, in this case "us" for English, with parentheses. The reason for the use of the quote/apostrophe (') is that when entered in the command-line, the shell attempts to interpret the parentheses as part of the shell's own syntax, and putting it in either a ' or a " tells the shell to simply use the string as given. (Untested speculation - you may be able to use the backslash \ in front of each parentheses for the same effect.)

The main disadvantage to this is that without some fancy keymap modding, you cannot use the original Ctrl+Space combination to switch the layout, as Hildon locks that for its own eight-level layout switching. The other is that it takes a little bit more work to get these multiple layouts to stick correctly.

Switching Layouts

Layouts can be swapped in a couple of ways - one, with an appropriate setxkbmap -option flag. Two, with a special remapped or added key that cycles through the layouts used.

Option one depends on using the setxkbmap command; For example, setxkbmap -option grp:ctrl_shift_toggle will make holding down shift and control at the same time toggle between layouts. There are many options of the sort, some of which use buttons that are not mapped to the N900's keyboard by default. There are many files in the /usr/share/X11/xkb/ directory that in some way indicate what "grp:" options are available; one example is /usr/share/X11/xkb/rules/xorg.lst - starting with line 620.

Option four is the simplest because, if used on every layout that you use, it makes fiddling with the setxkbmap command unnecessary (except when testing, though it's not strictly needed then either), when combined with the below section on making multiple layouts set at boot. It does, however, mean dedicating at least one key on your keymap to the task, but there are many unused key combinations that can be used for it. Like shift+backspace or fn+enter. Or any of the Shift+Fn+[key] combinations.

Here is an example of the N900 Shift key remapped so that it works like a normal shift key when pressed by itself, but works like a layout cycling key when FN is pressed and held down before Shift is pressed.

xkb_symbols "arrows_4btns" {
    key <LFSH>    {
        type[Group1] = "PC_FN_LEVEL2",
        symbols[Group1] = [     Shift,     ISO_Next_Group  ]
    modifier_map Shift {Shift_L };

The only difference is that the "type" is changed from a one-level to the PC_FN_LEVEL2 type that Nokia included for use with their only-two-arrow-keys keymaps, and a second level is added with the key name "ISO_Next_Group". This will cycle sequentially through your layouts in the order they are set - so if you set us,ru,de, it will cycle from English, to Russian, to German, to English again. Remember that order matters when pressing keys. If the shift key is pressed down first it will register as a shift - then the Fn key will register as a shift+Fn (which, by default, is just Fn). If the Fn key is pressed first, then the Shift key will register as Fn+Shift, which is normally just Shift, but in the above mapping becomes ISO_Next_Group. This means that FN+Shift cycles different keymap layouts, but Shift+Fn+[some key] still gives you the fourth level character mapped to that key on the layout you're currently on.

There is also an "ISO_Prev_Group" for cycling in the opposite direction, an "ISO_First_Group" and "ISO_Last_Group" - which is self explanatory. There is also a "Mode_switch" key...(as of this moment I have only used ISO_Next_Group, and the others I have not tested on the N900 yet. I also am not sure what Mode_switch does at all, but I suspect it's similar in purpose. If anyone can find the time to test to verify how they work, particularly Mode_switch, it would be greatly appreciated).

Setting Multiple Layouts At Boot

If you are satisfied with your multiple layout setup, you will soon likely find yourself annoyed by the fact that you have to run setxkbmap -layout {whatever} every time you reboot. There are two ways around this, only one of which I have managed to make work - one, run a script, somewhere from event.d, that executes after Maemo sets its xkb mapping, which will then set your own. After some brief fiddling I couldn't find a point in the boot process where I could execute the script late enough so that it would come after the default setting. It's in principle doable, hence mentioned here, but I haven't figured it out yet. Nevertheless, it should be possible to use "setxkbmap -option" however, as those do not override or depend on the layouts, unless the N900 sets some xkb map options in the background as well.

The other option involved editing the gconf key /apps/osso/inputmethod/int_kb_layout. Changes to this will take effect immediately (I have not tested what happens if you try to set a layout/mapping that is broken and doesn't work when used through setxkbmap though this method), and will persist after a reboot. The Text Input settings menu applet reads and sets this key with its hardware keyboard layout setting. However, it is obviously incapable of understanding multiple layouts being specified at once, as setting mine to "us,nokia_vndr/rx-51(ru)" resulted in the Text input menu telling me my hardware keyboard was set to "čeština" (which a google search suggest is the Czech language). In spite of it erroneously reporting the keyboard layout, it correctly set the keyboard layouts to the us and ru layouts I have edited in the rx-51 file.

I have not tested what happens if you try to change/save the settings from within that settings applet after making this change.

Temporary remap

Keys can be also remapped temporarily by loading keymap to a file, edit that file and then reload changed file to N900 X server; like this (on an X terminal):

xkbcomp :0
vi server-0.xkb
xkbcomp server-0.xkb :0

This has the advantage that if keymap get screwed out, running just setxkbmap will fix it back to original. If this cannot be done, rebooting will fix things for sure.

For arrow key remapping the following script can be handy:

Just noticed that this makes N900 drain battery !!! (N900 was shutdown in the morning). After executing this maemo-xinput-sounds takes >90% of cpu time. Killing the process will be a temporary fix; I'll look for better solution...

set -eux
# busybox mktemp is sooo strict: 6 X:s at the end is the only option...
tf=`mktemp xkb-XXXXXX`
trap "rm $tf.0 $tf" 0
xkbcomp :0 $tf.0
perl -pe '
 sub out ($$$) {
        print qq(    key <$_[0]> { type[Group1] = "PC_FN_LEVEL2",);
        print qq( symbols[Group1] = [ $_[1], $_[2] ] };);
        return if s/.*};//; while (<>) { last if s/.*};//; };
 s/controls=\)/controls=SlowKeys\)/; # hmm...
 out "UP", "Up", "Odiaeresis" if (/key\s+<UP>/);
 out "DOWN", "Down", "adiaeresis" if (/key\s+<DOWN>/);
 out "LEFT", "Left", "odiaeresis" if (/key\s+<LEFT>/);
 out "RGHT", "Right", "Adiaeresis" if (/key\s+<RGHT>/);
' $tf.0 > $tf
xkbcomp $tf :0

This one maps Up, Down, Left and Right to Ö, ä, ö, Ä, respectively (for finnish/scandinavian users), and is easy to tune for other purposes. Copy this as xk to home directory on N900 and execute it as sh xk whenever (seldom) you reboot N900.

Use with vnc

You can use vnc with a custom script to show the N900's screen on your Linux PC so that you have a bigger screen and a real keyboard. In its default state the N900 will only recognise characters, even then they are typed via vnc, that are on its hardware keyboard. If you want to be able to type a % (for example) in vnc you need to add it to the N900's keyboard map. You can add them to end the of the common_keys section just after the definition of FK11:

   key <FK12>	{ [	eacute, Eacute] };
   key <FK13>	{ [	egrave, Egrave	] };
   key <FK14>	{ [	agrave, Agrave	] };
   key <FK15>	{ [	ugrave, Ugrave	] };
   key <FK16>	{ [	ecircumflex, ecircumflex	] };
   key <FK17>	{ [	oe, OE	] };
   key <FK18>	{ [	ccedilla, ccedilla	] };
   key <FK19>	{ [	ediaeresis, Ediaeresis	] };
   key <FK20>	{ [	icircumflex, icircumflex	] };
   key <FK21>	{ [	ucircumflex, Ucircumflex	] };
   key <FK22>	{ [	idiaeresis, Idiaeresis	] };
   key <FK23>	{ [	ocircumflex, Ocircumflex	] };
   key <FK24>	{ [	acircumflex, acircumflex	] };
   key <I120>	{ [	less, less	] };
   key <I126>	{ [	greater, greater	] };
   key <I129>	{ [	asciicircum, asciicircum	] };
   key <I147>	{ [	bracketright, bracketright	] };
   key <I148>	{ [	braceleft, braceleft	] };
   key <I149>	{ [	braceright, braceright	] };
   key <I150>	{ [	bracketleft, bracketleft	] };
   key <I151>	{ [	bracketright, bracketright	] };
   key <I152>	{ [	asciitilde, asciitilde	] };
   key <I153>	{ [	grave, grave	] };
   key <I154>	{ [	percent, percent	] };
   key <I155>	{ [	bar, bar	] };
   key <I156>	{ [	Ecircumflex, Ecircumflex	] };
   key <I157>	{ [	Icircumflex, Icircumflex	] };
   key <I158>	{ [	Ccedilla, Ccedilla	] };
   key <I159>	{ [	Acircumflex, Acircumflex	] };
   key <KP0>	{ [	KP_0 ] };
   key <KP1>	{ [	KP_1 ] };
   key <KP2>	{ [	KP_2 ] };
   key <KP3>	{ [	KP_3 ] };
   key <KP4>	{ [	KP_4 ] };
   key <KP5>	{ [	KP_5 ] };
   key <KP6>	{ [	KP_6 ] };
   key <KP7>	{ [	KP_7 ] };
   key <KP8>	{ [	KP_8 ] };
   key <KP9>	{ [	KP_9 ] };
   key <KPDL>	{ [	KP_Decimal ] };
   key <KPEQ>	{ [	KP_Equal ] };
   key <KPDV>	{ [	KP_Divide ] };
   key <KPMU>	{ [	KP_Multiply ] };
   key <KPSU>	{ [	KP_Subtract, KP_Subtract ] };
   key <KPAD>	{ [	KP_Add, KP_Add ] };

Adding the numeric keyboard allows these keys to used, which is especially useful when typing digits into the dialler or other fields where only digits are allowed.

Known Remap Bugs

There are some programs that do not pick up remapped keys correctly. X-Terminal, for instance, picks up a tab that's been mapped to a shift+(key) combination as a shift+tab instead of just tab. MicroB did something similar as of this writing.

As of this writing, FreOffice did not register a tab mapped to either fn+spacebar or shift+spacebar. Other keys for Tab worked fine.

Also, making the arrow keys have four buttons mapped to them instead of just two tends to cause problems with shift+arrow-key to highlight text.

J-k and Z-X are two pairs of keys for which pressing shift+fn+(key) causes the typing of both that key's fourth-level mapped character, and the pair key's fourth level character. So, with default mappings, shift+fn+j types ")&", as does "shift-fn-k". So mapping those characters to separate keys at the fourth level is typically counter productive, though it could be useful for writing programs, scripts, or just mathematical expressions if you map [ to one and ] to the next one, or {}, (), or <>.

Alternatively, you can delete one of the fourth-row key-maps from the keys in each pair, leaving it with only three characters (make sure to delete the last comma), and then both of those buttons will simply display the one key that's left.


On the eight-level layouts (such as Russian and a couple others, which switch using Ctrl+Space), it seems that only levels 5 and 6 switch with levels 1 and 2. If there are exceptions to this, I have not noticed them. Because of this, remapping levels 7 and 8 on those layouts is effectively useless.