96

I cannot make xmodmap run on login in Ubuntu 13.04. I have searched around, including in askubuntu and all answers I found do not work.

I have a file named .Xmodmap in my home folder which contains the desired mappings. If I run it manually it works fine, so there is no error there. In order to make it run on startup, I have tried:

  1. Using various .xinitrc containing one of the following commands:

    • xmodmap .Xmodmap
    • xmodmap ~/.Xmodmap
    • /usr/bin/xmodmap /home/NAME/.Xmodmap
    • if [ -s ~/.Xmodmap ]; then
      xmodmap ~/.Xmodmap
      fi
  2. Using .Xresources instead of .xinitrc with the same variations.

  3. Setting it as a startup application.

None of the above works in Ubuntu 13.04 (64-bit). I also saw a few ideas about globally changing the keyboard mappings, but most of them were not applicable in Ubuntu 13.04 (i.e. the corresponding files did not exist where specified) and I prefer not to touch the global settings anyway.

11 Answers 11

105

Ubuntu no longer uses xmodmap, but instead uses xkb (as far as I understand, this facilitates per-window keyboard layouts, among other things).

The system-wide map files are in

/usr/share/X11/xkb/symbols/

The maps appears to be loaded hierarchically, with the pc map as the root, and whatever language (e.g. en) as a child of the root.

In my particular case, I physically swapped Page Up with Home and Page Down with End on my keyboard, so I very crudely made changes to the system-wide pc map, as follows:

 key <HOME> {    [  Prior        ]   };
 key <PGUP> {    [  Home         ]   };
 key  <END> {    [  Next         ]   };
 key <PGDN> {    [  End          ]   };

NOTE: To force Xorg to use your new keyboard map, you may have to remove the existing pre-compiled maps (*.xkm) in

/var/lib/xkb/

and then restart Xorg.

There are various resources on xkb, but this one is related to Ubuntu.

13
  • 13
    As of Ubuntu 14.04, this is sadly the easiest way to swap keys. You CAN make xmodmap run on login by adding it to the Startup Applications, but if you suspend, hibernate etc you must manually start it up or create startup daemon scripts. Jan 8, 2014 at 20:16
  • 1
    I can remap keys depending on modifiers: unmodified shift altgr* shift+altgr. But what about left alt and super key?
    – Farzher
    Apr 11, 2014 at 19:42
  • 9
    I don't think your first sentence is true. Do you have any source for it? I find it hard to believe that "the Ubuntu way" of remapping your keys would be editing the keyboard maps from xkb. Besides being cryptic, this has the problem that your custom maps are deleted when xkb is updated. Jun 15, 2014 at 21:36
  • 3
    There's got to be a better way. I know the exact keycode I want to map, but keycode 217 isn't even listed in xkb. I don't even see a way to add new keycodes.
    – Jonathan
    Dec 27, 2014 at 22:18
  • 2
    For me, and evdev-based solution works persistently under 19.10, see askubuntu.com/a/1161870/835198
    – mfg
    Jul 15, 2020 at 15:45
21

For me, the xkb configuration is too complicated if you want to remap 1 or 2 keys in a way not available in the System Settings. Plus, the solution should remain on the user side, without editing '/usr/share/X11/xkb/symbols/' etc. Force the 'xmodmap ~/.Xmodmap' load using the Startup Applications only works until you suspend, change users or change the keyboard layout. So, as holocronweaver suggests, with code snippets I found, I made a python script to be loaded on session startup, that reloads the '~/.Xmodmap' when needed.

Check the bug report #1243642 (comment #6), and download it here.

8
  • 2
    Still working as of 15.10 :-) Thanks! Feb 11, 2016 at 15:42
  • 1
    The link to this legendary script seems to be broken. Could somebody put it up on github?
    – Epigene
    Jan 28, 2017 at 9:07
  • 1
    Great - and only viable- answer! Working in 16.04. To get it to work in Python3 changed: "import gobject" to "from gi.repository import GObject as gobject". Feb 21, 2018 at 2:51
  • 2
    @Epigene - the link is there now Feb 21, 2018 at 3:07
  • 1
    Praise be! A genius work around.
    – dmanexe
    May 7, 2018 at 17:33
7

I had this problem in Ubuntu 14.04, and found the solution here. Apparently, Ubuntu is not able to configure the keyboard right away after logging in, but it is a bit later. So if you add a command

sleep 4 && xmodmap ~/.Xmodmap &

to ~/.bash_profile then it should work (it does for me).

EDIT: This seems to work only after logging in, not after starting up. I'll have to investigate this later.

3
  • 1
    Any luck setting this to run after suspend/hibernate?
    – Jonathan
    Dec 27, 2014 at 22:34
  • No, unfortunately I still can't even get it to work after booting. So every time I boot, I open a terminal and type xmodmap ~/.Xmodmap :(
    – dremodaris
    Dec 28, 2014 at 15:19
  • be aware that on ubuntu 16.04 you should use .profile Sep 3, 2018 at 20:21
7

Convert Caps Lock into Esc for vim use

Here is my variant of a key mapping startup script. It converts Caps Lock into Esc on whatever keyboard for use with vi, vim or gvim.

Unlike the answer of q4w56, this answer does not use any infinite while; do loop. Otherwise, one core of my dual core CPU would hit 42% every 5 seconds, severely reducing my laptop battery charge.

#!/usr/bin/env bash
sleep 4
xmodmap -e "clear Lock"
xmodmap -e "keysym Caps_Lock = Escape"

Save it as a script. Make the file executable with chmod +x. Add the script name and location to Session and Startup → Application Autostart (in Xubuntu).

The keyboard behaviour for this user will remain persistent through reboot and logout, but not suspend. Persistence through suspend can be achieved, but unfortunately only at the system level, not readily at the user level.

EDIT

I moved away from above solution in favour of this solution which offers, apart from the Esc function on CapsLock, also the arrow keys and the keys PgUpHomeEndPgDn through CapsLock+HJKL, respectively CapsLock+UIOP.

Rationale for this keyboard remapping

In today's computing world there is very little use left for the Caps Lock key. In general, one should refrain from using ALL CAPS by virtue of both netiquette and the separation of presentation and content. Moreover, accidentally hitting the Caps Lock key whilst editing text with vim is not always immediately noted, but invariably results in rather annoying vim behaviour further on. Disabling the Caps Lock key all together and repurposing it as an easy to reach Esc key results in a double win for vim use.

6
  • Replacing the function of the Caps Lock key might be a real life saver for vim users on Apple MacBooks without an Esc key. Oct 27, 2016 at 7:40
  • 3
    It's better to remap the capslock to ctrl. This solves many more problems, and in Vim, then, you can use capslock + [ for Esc Sorry for meddling, but I felt obliged to suggest this.
    – d.k
    Mar 2, 2017 at 15:43
  • What exactly is suspend? Is that closing the lid on your laptop? After that your solution doesn't work? How do you use vim after you close the lid on your laptop? May 29, 2018 at 14:47
  • 1
    @MarkoAvlijaš How do you use vim after you close the lid on your laptop? By opening the lid of course! May 30, 2018 at 17:50
  • Haha I'd never guess that. I mean caps lock isn't mapped to esc any more after that? May 30, 2018 at 18:16
6

@Daniel's answer pointed me the right way, but I would like to extend on it.

Works for me on Linux Mint 17.2 and Ubuntu 16.04.

I tried all twists I could think of to keep using xmodmap, but they all fail when the system goes into sleep mode. The same even holds for start up-applicication scripts that use setxkbmap in cases where the *settings-daemon (for me it is xfce4) runs later than the script --- and order cannot really be influenced.

What I finally came up with has the following ingredients:

1) Write a minimal keyboard mapping file for /usr/share/X11/xkb/symbols. Lets call the file mylayout It can be as simple as

xkb_symbols "basic" {
  name[Group1] = "My Layout";
  include "us"
  key <AE03> { [ 3, numbersign, sterling, sterling] };
  include "level3(ralt_switch)"
}
  • basic is just a name, we'll meet it later again.
  • The name[Group1] similarly is just a name it seems, but it will play no role later.
  • include "us" includes the plain us keyboard. Actually us is another file in the same directory. This is the keyboard layout we are adapting. Choose a different one as needed. Note: no semicolon to end this line.
  • The key line is one adaptation of the keyboard, more can follow. The <AE03> can be found in the files under /usr/share/X11/xkb/keycodes. Use the xev program to figure out that the "3"-key has keycode 12 and in the keycodes file Xfree86 it is mapped to <AE03>.
  • Finally another include directive to activate another keyboard option, in this case I want to have the right Alt-key to be the level-3 shift key, i.e. the key which gives access to the sterling sign I defined above. level3 is just a file name in the same folder with ralt_switch one section of it. Have a look around and choose what you need to include.

2) I did not put the mylayout into the system folder. Rather I made only a soft link from the system folder to a folder of my liking to immediately see that this is not stock software.

3) Further I did not fix up evdev.xml, again to prevent update hassles. But this would be necessary to find mylayout in the keyboard configuration editor (for xfce4 it is xfce4-keyboard-settings). Instead I used xfce4-settings-editor and changed keyboard-layout->XkbLayout to mylayout (the file name) and XkbVariant to basic (see above). Afterwards, mylayout/basic is displayed in the keyboard settings editor too. An entry in evdev.xml seems to be only necessary to be able to select the layout.

This way, the keyboard settings now survive sleep mode and reboot.

More background can be found here: http://www.charvolant.org/~doug/xkb/html/node5.html .

Another approach to fixing the sleep mode problem (not tried myself), can be found here: https://www.vinc17.net/unix/xkb.en.html .

UPDATE: worked with Mint 18.3 the same moment I changed the settings in xfce4-settings-editor as described above.

UPDATE: With 18.04, gdm3 as the display manager and XFCE4 as the window manager, it looks as if ~/.Xmodmap is read again and the settings seem to survive a suspend. (I rarely use suspend and I am never sure which mode the laptop is in then really.)

1
  • .Xmodmap doesn't seem to survive suspend for me on 19.10 ...
    – rogerdpack
    Feb 2, 2021 at 19:24
3

I had the problem too on Ubuntu 16.04 with fcitx, and had the solution on the fcitx wiki, but it need fcitx has 4.2.7 or later

  • touch ~/.Xmodmap
  • write the config
  • reboot and the fcitx will try to load it automatically

There also have some explanation for the reason.

5
  • 1
    Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference.
    – Videonauth
    Jun 8, 2016 at 7:36
  • @Videonauth I have modified my answer
    – Bluethon
    Jun 8, 2016 at 7:44
  • Thank you very much :) I leave my comment here still so the people in review cue can see you changed something.
    – Videonauth
    Jun 8, 2016 at 7:46
  • @Videonauth this is my first answer and I'm poor of English, so I made some fault. and thx for your advice. : P
    – Bluethon
    Jun 8, 2016 at 7:49
  • You're welcome. Providing answers is a good way to contribute to the community.
    – Videonauth
    Jun 8, 2016 at 7:54
3

REVISION

An update in early 2018 broke persistence -- auto-reload of the keymap after suspend or hibernate. Since methods using /etc/pm/sleep.d scripts stopped working (deprecated?), that left only the newer way, using /lib/systemd/system-sleep and slightly different scripting (which started working on keymaps!).

So this post is updated to the newer method for persistence, and to include normal initial keymap loading, which also started working. The routine for converting an .Xmodmap file to .xkbmap remains unchanged.

Note this is a per-user solution. For a per-device answer, see how to apply a keymap to a single device. This method could be adapted for use here.

First modify the .Xmodmap file as desired. These are easier to edit directly than .xkbmap files. When it is loaded:

xmodmap .Xmodmap

then convert to an .xkb file:

xkbcomp $DISPLAY $HOME/.xkbmap

To auto-load on startup, open Startup Applications, click Add, and on the Command line enter:

xkbcomp /home/user/.xkbmap ":0"

("user" is replaced with actual user name.) For Name, perhaps enter Load Keyboard Map. Add comment if desired and hit Save.

The keymap will now load every time the system boots, but will not survive a suspend or hibernate. For this, create a new file in /lib/systemd/system-sleep, perhaps named 60_xkbmap, which contains:

#!/bin/sh
case $1/$2 in
  pre/*)
    # Place pre-suspend commands here
    exit 0
    ;;
  post/*)
    # Place post-suspend commands here
    export DISPLAY=":0"
    export XAUTHORITY="/home/user/.Xauthority"
    su user -c "xkbcomp /home/user/.xkb/xkb-map $DISPLAY 2>/dev/null"
    ;;
esac

(Ref.) As above, replace "user" with actual user name.

The keymap should now auto-load and remain persistent. Note:

  • Applies to current LTS release, 16.04, and likely later ones as well.
  • Taken from post 14 of the above-linked bug thread.
  • Earlier comments applied to original post.
2
  • I am trying this method now and now when I start a terminal i get a bunch of messages like so: Warning: No symbols defined for <AB11> (keycode 97) Warning: No symbols defined for <JPCM> (keycode 103) Warning: No symbols defined for <I120> (keycode 120) ...... many more not sure what the consequences of that will be yet. Anyone know?
    – lost baby
    Jan 21, 2017 at 0:24
  • This method despite the above mentioned warnings works but only temporarily - after a little while the mapping somehow gets forgotten and the super key reverts to its default function. So I'll try it the other way around - I'll remap the basic edit shortcuts on my mac to use the Control key instead of the Command key and see if that works. I just want my cut-copy-paste-undo-redo commands to be the same on Mac and Ubuntu. I get very frustrated when the search menu pops up on Ubuntu every time I try to copy or paste something.
    – lost baby
    Jan 28, 2017 at 8:38
2

Steps mentioned in the accepted answer(also described here) is a persistent solution, but didn't work for me in case of altering alphabetical keys.

If you got frustrated by trying other options or want to save your time, try the steps mentioned in the article - https://medium.com/@saplos123456/persistent-keyboard-mapping-on-ubuntu-using-xmodmap-cd01ad828fcd

  1. Make a new copy of xmodmap.
xmodmap -pke > .Xmodmap
  1. Edit the new file using the following command and change keycode(s) as per your requirements.
gedit .Xmodmap
  1. Activate those changes. New changes should reflect after this.
xmodmap .Xmodmap
  1. Skippable step - Generate xkb file with new mapping
xkbcomp $DISPLAY $HOME/.xkbmap
  1. All above changes are temporary and would be replaced on reboot. Create a start-up program to trigger the following command
xkbcomp /home/user/.xkbmap ":0"   // if you followed the 4th step
OR
xmodmap .Xmodmap    // if you skipped the 4th step
1

This made me stumble, too, when I upgraded from Ubuntu 12.04 to 13.04.

Luckily this setting is now (or perhaps has always been) easily accessible in the Keyboard preferences and can be changed with a few clicks of the mouse.

  1. Go to System Settings > Keyboard Layout > Options...
  2. In the Keyboard Layout Options, click the arrow to reveal the ▸ Ctrl key position options.
  3. Put the checkmark in at Swap Ctrl and Caps Lock.

There you go: Left Control and Caps Lock have switched positions.

Don't forget to delete ~/.Xmodmap once you've made the change.

3
  • This was maybe downvoted because it doesn't address xmodmap, but this was actually how I discovered that using Gnome Tweak may have been the reason some of my mappings were acting weird.
    – dragon788
    Oct 30, 2017 at 22:14
  • I don't see this in 16.04, is this still possible?
    – chrismarx
    Jan 3, 2018 at 19:12
  • 1
    @chrismarx No, they removed it. Nowadays (16.04) I set XKBOPTIONS="ctrl:swapcaps" in /etc/default/keyboard.
    – glts
    Jan 3, 2018 at 20:31
1

Most of the other solutions load xmodmap on session startup (or earlier), but then your settings get wiped when you plug a new keyboard (or switch your KVM switch). Here is a solution that reinstalls the xmodmap after you plug a USB device. I have been using it ever since Linux introduced all the Alt/Meta confusion (in about 2006).

! ~/.Xmodmap file
!
! Part 1 (since about 2006)

! Avoid BadValue (TODO: debug why we get BadValue otherwise)
clear mod1
clear mod4

! Actually, my keyboard doesn't have 0xcc/0xcd keys, thank you...
keycode 0xcc = NoSymbol
keycode 0xcd = NoSymbol

! mod3 is Alt. I'm sure this is documented somewhere.
! It works that way in every program!
add mod3 = Alt_L
add mod3 = Alt_R

! In addition to Alt keys, my keyboard has ... drumroll ... *Windows* keys!
! These are *Meta* keys. Say, in Windows web browsers.
!   Don't take my word for it, hit F12 and type:
!   onkeydown = function(e){console.log(e);}
! And, um, Alt is already taken, so obviously Meta = Windows key.
! Also Windows keys = Meta in some FreeBSD distros out of the box.
! Is Windows keys = Meta not clear to someone, or is someone just being annoying
! with all this "Alt = Meta" garbage?
keycode 0x85 = Meta_L
keycode 0x86 = Meta_R

! No, mod1 is not Alt!
! In every program, mod1 is actually meta!
add mod1 = Meta_L
add mod1 = Meta_R
remove mod1 = Alt_L
remove mod1 = Alt_R



! Part 2 (since about 2015)
! What is going on?? USB thinks it can just wipe my xmodmap???
!
! 1. Locate xkb rulefile using
!
!   udevadm control --log-priority=info
!
!
! It will be something like
!
!    /lib/udev/rules.d/64-xorg-xkb.rules
!
!
! 2. Edit /lib/udev/rules.d/64-xorg-xkb.rules. Add:
!
!   RUN += "/big/usb_fix.sh"
!
! and do:
!
!   udevadm control --reload-rules
!
! note: using /big is intentional... on new Ubuntus, the system dies
! with "a start job is running..." in disk mounting. So we prevent this
! script from running ig /big is not mounted yet.
!
!
! 3. Create the /big/usb_fix.sh script:
!
! #!/bin/sh
! echo "xmodmap ~/.Xmodmap" >> /usr/local/usb_fix.log
!
! and make it executable.
! 
! 
! 4.
! mkfifo /usr/local/usb_fix.log 
! 
! 
! 5.
! Create a script (e.g. named ~/bin/usb_fix_client)
! 
! #!/bin/sh
! yes 'cat /usr/local/usb_fix.log | sh' | sh
! 
! and put this in your .xinitrc.


! Part 3 (since about 2018)
!
! Every now and then, apt-get can overwrite the xorg-xkb-rules?
! solution for now is turn off automatic updates.

If you've set it up properly, xmodmap should say:

shift       Shift_L (0x32),  Shift_R (0x3e)
lock        Caps_Lock (0x42)
control     Control_L (0x25),  Control_R (0x69)
mod1        Meta_L (0x85),  Meta_R (0x86)
mod2        Num_Lock (0x4d)
mod3        Alt_L (0x40),  Alt_R (0x6c)
mod4      
mod5        ISO_Level3_Shift (0x5c),  Mode_switch (0xcb)

And voila, your meta and alt keys are working!

If it's too hard to locate and turn off whatever software keeps overwriting your USB rules (for me, some software comes along and clobbers it about twice per year), then just add an RC script to copy your USB rules back. Also, you can copy your improved rules to a file with a larger number in front of it, to make it override whatever other fads come along wiping your xmodmap in the future.

3
  • 1
    Is something missing in this answer? You just define the Xmodmap config but no explanation how it is loaded. You mention USB rules so I guess your solution is some udev magic but you don't describe how to configure it.
    – kayahr
    Jun 26, 2022 at 12:18
  • 1
    Ah sorry, just found "Part 2" in the first code block. That's irritating. Maybe you should split the parts into separate code blocks. Otherwise it looks like this code block just shows the content of your Xmodmap file.
    – kayahr
    Jun 26, 2022 at 12:22
  • 1
    Hm... Downvote from me because of 'solution for now is turn off automatic updates.'. You know that you can define custom udev rule files instead of modifying files which are under control of the xserver-xorg-core debian package?
    – kayahr
    Jun 26, 2022 at 12:28
-1

I find adding this script to startup satisfying:

while true;do 
    xmodmap -e "keycode 87=Prior"
    xmodmap -e "keycode 88=Next"
    sleep 5
done

I tried using xmodmap ./Xmodmap, but every time it is executed, a noticeable lag will occur.

1
  • 8
    The use of any infinite while; do loop should be avoided. It caused one core of my dual core CPU to hit 42% every 5 seconds, severely reducing my laptop battery charge! Apr 17, 2016 at 0:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .