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.

Alaa Ali
  • 31,535
Alexander Karatarakis
  • 1,117
  • 3
  • 12
  • 13

11 Answers11

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.

Daniel
  • 1,174
  • 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. – holocronweaver Jan 08 '14 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 '14 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. – Mateus Araújo Jun 15 '14 at 21:36
  • 1
    That said, this is the only reliable method that I've found of remapping keys on Ubuntu. – Mateus Araújo Jun 15 '14 at 21:37
  • 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 '14 at 22:18
  • This serves the purpose but how to keep these changes same across reboots? – Ayush Goyal Apr 01 '15 at 07:38
  • ^Why would they differ across reboots? The file is loaded once per session. Unless something is changing it, it will be the same each time. – underscore_d Sep 05 '15 at 21:32
  • to see all currently used symbols and keycodes, see xkbcomp $DISPLAY myFile – phil294 Mar 15 '17 at 16:03
  • What is xkb? It's not installed on my Ubuntu 16. – Yan King Yin Jul 18 '17 at 09:39
  • To restart Xorg, see: https://askubuntu.com/questions/1220/how-to-restart-x-window-server-from-command-line – Vesanto Nov 13 '17 at 21:57
  • On Ubuntu 18.04 LTS, I'm unable to follow this process. Am I just missing something obvious? I don't see "en" in the symbols folder, anywhere. $ ls -R /usr/share/X11/xkb/symbols/ | grep -i en gives me this result: parens – Johan Apr 23 '19 at 19:43
  • 2
    For me, and evdev-based solution works persistently under 19.10, see https://askubuntu.com/a/1161870/835198 – mfg Jul 15 '20 at 15:45
  • Is there any backwards compatibility option? Can a working xmodmap file be translated to xkb? – personal_cloud Sep 05 '20 at 21:44
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.

Jonas Czech
  • 4,017
dedalu
  • 263
  • 2
    Still working as of 15.10 :-) Thanks! – lalomartins Feb 11 '16 at 15:42
  • 1
    The link to this legendary script seems to be broken. Could somebody put it up on github? – Epigene Jan 28 '17 at 09: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". – Craig Hicks Feb 21 '18 at 02:51
  • 2
    @Epigene - the link is there now – Craig Hicks Feb 21 '18 at 03:07
  • 1
    Praise be! A genius work around. – dmanexe May 07 '18 at 17:33
  • 1
    After a while, I'm using the Ubuntu 19.04. Looks like my script still working, but: did you find another way? Because now my script creates a perceptive lag. – dedalu Apr 25 '19 at 05:01
  • Note that xkb can wipe your xmodmap every time you plug a new keyboard (or switch your KVM switch) even if you stay logged into an X session. – personal_cloud Sep 05 '20 at 21:34
  • @personal_cloud that sounds like what might be happening to me. My bluetooth keyboard sometimes goes to sleep on idle and requires a reconnect, at which point the xmodmap mapping is dropped. – NeilG Aug 25 '21 at 05:22
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.

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.

Serge Stroobandt
  • 5,268
  • 1
  • 48
  • 59
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.)

Harald
  • 1,170
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.

wittich
  • 1,174
  • 13
  • 26
Bluethon
  • 133
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.
u2n
  • 923
  • 1
  • 9
  • 22
  • 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 (keycode 97) Warning: No symbols defined for (keycode 103) Warning: No symbols defined for (keycode 120) ...... many more not sure what the consequences of that will be yet. Anyone know? – lost baby Jan 21 '17 at 00: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 '17 at 08: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

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.

  • 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 '22 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 '22 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 '22 at 12:28
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.

glts
  • 119
  • 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 '17 at 22:14
  • I don't see this in 16.04, is this still possible? – chrismarx Jan 03 '18 at 19:12
  • 1
    @chrismarx No, they removed it. Nowadays (16.04) I set XKBOPTIONS="ctrl:swapcaps" in /etc/default/keyboard. – glts Jan 03 '18 at 20:31
-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.

Serge Stroobandt
  • 5,268
  • 1
  • 48
  • 59
golopot
  • 224
  • 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! – Serge Stroobandt Apr 17 '16 at 00:25