How can I map the left and right shift key individually?

First off, excuse my ignorance of X and XKB; I've been trying to hack together a solution in the hope of being able to achieve what I want without requiring a detailed grasp of it.

I'm trying to create an XKB keyboard map on Ubuntu 12.04 that allows me to stipulate which of the two shift keys constitutes the Level2 modifier. Specifically, the 4 key should only produce a $ when the right shift is held, not the left.

My reading so far:

  • http://www.charvolant.org/~doug/xkb/html/node5.html
  • http://people.uleth.ca/~daniel.odonnell/Blog/custom-keyboard-in-linuxx11
  • http://www.x.org/releases/X11R7.5/doc/input/XKB-Enhancing.html
  • Lots of searching!

I've attempted to define a custom type, and then refer to it explicitly in a symbols map:

/usr/share/X11/xkb/types/mbfisher:

default xkb_types "mbfisher" {
  type "RIGHT_SHIFT" {
    modifiers = None+Shift_R;
    map[None] = Level1;
    map[Shift_R] = Level2;
  };
}

/usr/share/X11/xkb/symbols/mbfisher:

default
partial alphanumeric_keys
xkb_symbols "basic" {

  name[Group1]= "mbfisher";

  key <AE04> {
    type= "RIGHT_SHIFT",
    symbols[Group1]= [ 4,  dollar ]
  };

};

I'm then selecting the map with the Ubuntu Keyboard Layout GUI.

This obviously disables the alphanumeric keyboard apart from the 4 key, but the dollar sign can still be typed with either shift key.

I'm conscious of writing a massive question with lots of useless information so I'll stop here; please ask for anything I've missed out.

Any ideas?


Here's what finally worked! I used xmodmap and a ~/.Xmodmap file rather than xkb configuration.

~/.Xmodmap:

clear Shift

! Key Shift+Key mode_switch+Key mode_switch+Shift+Key AltGr+Key AltGr+Shift+Key
! Key Shift_L+Key Shift_R+Key Shift_R+Shift_L+Key AltGr+Key AltGr+Shift_L+Key

keycode 10 = 1 1 exclam 1
keycode 11 = 2 2 at 2
keycode 12 = 3 3 numbersign 3
keycode 13 = 4 4 dollar 4
keycode 14 = 5 5 percent 5

keysym Shift_R = Mode_switch
add Shift = Shift_L

The 2 commented lines (staring with !) show the column headings before and after my changes. This has allowed me to specify col 2 as Shift_L and col 3 as Shift_R, as I've mapped shift_R as Mode_switch.

The changes are made by running:

 # setxkbmap us
 # xmodmap ~/.Xmodmap

setxkbmap us sets the default US map so you're working from a clean slate, and xmodmap appends the custom changes to it.

When implemented the !, @, #, $ and % characters can only be typed with the right shift key, and ^, &, *, ( and ) can only be typed with the left shift key.

I can now continue by mapping all keys on the left hand side of the keyboard to only be modified by the right shift key (i.e. the aplhabetical characters and their uppercase modifications) and vice versa; this solution means I only need to remap the left side.

Other useful links found along the way:

  • https://wiki.archlinux.org/index.php/Xmodmap

Thank you very much to @Trudbert for getting me most of the way to the answer!


I don't know if it's the solution you want but one possibility to disable the left shift key would be using xmodmap. Create a file ~/.Xmodmap with contents

clear shift
add shift = Shift_R

and run xmodmap ~/.Xmodmap.


See comments/chat:

You may run into problems if there are some other modifications made to your xkbmap by some other program so resetting to a default xkbmap with something like setxkbmap us can be necessary.

If you want to make some keys respond to only one shift key you can get you current keyboard layout with xmodmap -pke > .Xmodmap this gives you an .Xmodmap with a List of all your keys in the form of keycode XX = functions. In this assignment each keycode can have several functions on the righthand side. Each corresponds to a different modifier + that key. You can than insert the clear + add from above and add something like add mod5 = Shift_L. The right shift key would than correspond to mod2 while the left one would be mod5. You can than go on and move the mod2 functions of the keys you want to call with the left shift key to mod5 by simply inserting NoSymbol and spaces till you reach the right column (keycode 57 = n N -> keycode 57 = n NoSymbol NoSymbol NoSymbol N).