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.

Contents

Permanent remap

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

This can be done by using vi, which is ran from command line with the command "vi [file path and name of file to be opened]". (Instructions on how to use vi - it's not intuitive - can be found online easily.) To be able to actually edit the rx-51 file, you have to be root already. You cannot become root from within vi. Any other text or source code editor works too, such as leafpad.

You should however make a copy first in case something goes wrong, but do not place the copy in the nokia_vndr folder or it will stop your phone from booting.

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!

If you are satisfied with your new rx-51 file, do also backup that. The next firmware upgrade might restore it to the factory default.

Locales and languages can also be added with relevant keyboard stickers.

When making particularly intricate/complicated/fancy keyboard mappings, remember that order matters when clicking 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.

Remapping keyboard arrows

In the English variant of the N900 keyboard arrow keys have no extra symbols attached to them.

You can remap those keys to add things such as accents, umlauts or other useful symbols (e.g. `|', `<' or `>' for the X terminal).

The arrow keys are located at the end of the file. This example shows how to add dead acute, grave, tilde and circumflex accents (useful for writing in Portuguese) Press Fn+Up/Down/Left/Right to use these accents.

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 umlauts:

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 one adds Page Up, Page Down, Home and End:

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 ] };
};

This one gives Escape and Tab when pressing Fn+Left/Right, and the characters '^', '~', '<' and '>' when pressing Shift+Up/Down/Left/Right

xkb_symbols "arrows_4btns" {
    key <UP>	{ type[Group1] = "FOUR_LEVEL",symbols[Group1] = [ Up, asciicircum, PageUp, PageUp ] };
    key <LEFT>	{ type[Group1] = "FOUR_LEVEL", symbols[Group1] = [ Left, less, Escape, Escape ] };
    key <DOWN>	{ type[Group1] = "FOUR_LEVEL", symbols[Group1] = [ Down, asciitilde, PageDown, PageDown ] };
    key <RGHT>	{ type[Group1] = "FOUR_LEVEL", symbols[Group1] = [ Right, greater, Tab, Tab ] };
};

thp's mapping: Helpful for Python, Vim and the Shell with the occasional German (umlauts and ß) thrown in. This one adds the dead diaeresis (for Umlauts) to Shift+Fn+Up, % to Fn+Up, | to Shift+Up. Left and Right are mapped so that Shift gives <>, Fn gives [] and Shift+Fn gives {} (especially useful for programmers). It also maps Escape to Shift+Down, Tab to Fn+Down and ß to Shift+Fn+Down.

Semantic explanation: Left, Right are all kinds of bracket pairs, Shift+Fn is for German characters (up as in Umlauts, down for ß), Up has visible special characters (% and |) and Down has invisible special keys (Tab and Escape).

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      ] };
};

Of couse all these are just examples. You can add any other symbol you like, or you can remap any other key, not just the arrows.

If you want to know the name of a symbol, just take a look at this list of standard PC keyboard layouts as an example:

http://cgit.freedesktop.org/xkeyboard-config/tree/symbols/

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

Note: the pipe symbol is called "bar".

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.

In this situation it may be useful to remap keys with characters carrying accents such that one of it is a dead accent, freeing other keys for special characters that you want to have on the hardware keyboard.

For example, on a German keyboard there are three keys occupied by umlauts ä, ö, and ü. The following modification changes ü into dead diaeresis, so that ä, ö, and ü are produced by pressing ü followed by a, o, and u. This way one can also put diaeresis on e, i, and y 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 ] };
};

In this example, brackets and braces have then be mapped on ö, ä, Ö, and Ä. Shift-ü has been used for "^". Moreover, Shift-Space has been mapped to tilde (a character that often occurs in URLs), and Shift-. has been mapped to "|". (The previous assignments are commented out by adding "//" in the beginning of a line.)

setxkbmap de

then tests and installs the new keyboard mapping. The new keymap will be used until the rx-51 file is modified again, which may happen after a firmware upgrade. So keep also a backup copy of your modified rx-51!

In the italian layout, the comma, period, up and left keys are mapped to è, ò, à and comma. In this example, we'll put the four arrow keys back and we'll change the keys to allow for all accent combinations regardless.

partial alphanumeric_keys
xkb_symbols "it" {
    include "nokia_vndr/rx-51(english_base)"
    //include "nokia_vndr/rx-51(arrows_2btns)"
    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).

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...

#!/bin/sh
 
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.

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.