3

On an Asus X551M running Xubuntu 14.04, I would like to set the following keyboard configuration:

The pair of modifier keys immediately adjacent to the spacebar are mapped to control. The next closest pair are mapped to Alt.

That is, the bottom row of my keyboard looks like this:

[ctrl] [fn] [win] [alt] [    space    ] [alt] [menu] [ctrl]

whereas I want it to behave logically like this:

[ctrl] [fn] [alt] [ctrl] [    space    ] [ctrl] [alt] [ctrl]

(I never use the outermost pair of Ctrl keys, so their mapping is arbitrary.)

In the past I've done this by manually editing my xmodmap file, which never Just Works on the first try. Further, xmodmap locks up when loading config files, which is apparently a known issue. Everything I've read on the subject suggests that xmodmap is deprecated and I should use setxbdmap instead.

So I first tried:

setxbdmap -option altwin:ctrl_alt_win

which works almost perfectly. Now my keyboard is logically:

[ctrl] [fn] [alt] [ctrl] [    space    ] [ctrl] [menu] [ctrl]

i.e. I just need to map the Menu key to Alt. Is there a way to do this using setxbdmap?

I next looked through /usr/share/X11/xbd/rules/evdev.lst until I found the line:

altwin:menu     Add the standard behavior to Menu key

and tried that, but it seems to have made no difference. There is an option:

ctrl:menu_rctrl   Menu as Right Ctrl

which is almost what I want except, naturally, that it maps Menu to Ctrl instead of Alt. So, is there any way to do this with setxbdmap?

jasonwryan
  • 73,126

1 Answers1

2

You can create a file ~/.xkb/symbols/local containing:

xkb_symbols "local" {
    key <LWIN> {
        type= "ONE_LEVEL",
        symbols[Group1]= [ ISO_Level3_Shift ]
    };
    key <MENU> {
        type= "ONE_LEVEL",
        symbols[Group1]= [ ISO_Level3_Shift ]
    };
    key <LALT> {         [       Control_L ] };
    key <RALT> {         [       Control_R ] };
};

or

xkb_symbols "local" {
    key <LWIN> {
        type= "ONE_LEVEL",
        symbols[Group1]= [            Alt_L ]
    };
    key <MENU> {
        type= "ONE_LEVEL",
        symbols[Group1]= [            Alt_R ]
    };
    key <LALT> {         [       Control_L ] };
    key <RALT> {         [       Control_R ] };
};

(or something between), depending on which kind of Alt you want. And do each time you start X (e.g. in your ~/.xsession file if you have one):

mkdir -p .xkb/keymap
setxkbmap -print | sed -e '/xkb_symbols/s/"[[:space:]]/+local&/' > $HOME/.xkb/keymap/custom
xkbcomp -w0 -I$HOME/.xkb -R$HOME/.xkb keymap/custom $DISPLAY

The second line creates a file ~/.xkb/keymap with xkb_symbols { include "...+local" };, i.e. which includes ~/.xkb/symbols/local when xkbcomp (third line) is used with the -I$HOME/.xkb option. You can check this file before running xkbcomp.

I've not tried this exactly, but this is based on what I'm doing: https://www.vinc17.net/unix/xkb.html (without the types directory).

vinc17
  • 12,174
  • Thanks for the help. I made the changes to my .xsession and tried both options for .xkb/symbols/local, but neither worked. This might be naive, but how does setxbdmap know to look at .xkb/symbols/local? – Patrick O'Neill Aug 25 '14 at 04:28
  • @PatrickO'Neill I've edited my answer to add explanations after the 3 commands. Note that here the setxbdmap line just generates a config file, but the config change itself is done by xkbcomp. The reason of these two steps is that here one modifies current settings instead of directly defining a keyboard map from scratch. One could also use a pipe between both, as described in the setxkbmap(1) man page. You can check with strace whether the .xkb/symbols/local file is read. – vinc17 Aug 25 '14 at 07:40