TL;DR ~/.Xmodmap is obsolete and doesn’t work within GNOME/Unity. You have to apply it via hotplug command of gnome-settings-daemon. Work it around with .desktop file placed in autostart directory.


I use the xmodmap command to modify layout of my keyboard (Caps Lock as Esc is great for vimists). At first, I thought I’d just create a ~/.Xmodmap file and it’d work for me. I didn’t do the research across desktop environments and graphical servers, however, it seems to work on KDE in openSUSE. On the other hand, Unity (Ubuntu) and GNOME (openSUSE) doesn’t apply settings from this file and I had to execute xmodmap ~/.Xmodmap manually after each reboot. What is worse it did even happen after suspend and wake up, which is annoying.

The cause for this is the gnome-settings-daemon and its keyboard plugin that handles keyboard layouts. The gnome-settings-daemon overrides any xmodmap settings you may create, e.g. after suspend-wake up cycle. Secondly, it deliberately ignores ~/.Xmodmap file (reasoning).

I think the proper solution for this would be to create a custom layout and use that with your favorite key mappings. However, I didn’t pursue this and it may worth a future try.

The gnome-settings-daemon and it’s plugin allows you to specify a hotplug action which is executed when the device is discovered. In order to use this just do following.

# cat /etc/hotplug-command.sh
#!/bin/bash

sleep 5
xmodmap $HOME/.Xmodmap
gsettings set org.gnome.settings-daemon.peripherals.input-devices \
        hotplug-command /etc/hotplug-command.sh

Little note about the hotplug script. It is triggered for each in put device (which should be at least a mouse and a keyboard), see what arguments it gets. Fortunately, my variant is idempotent and so I don’t handle any args. Further, the script is invoked for mouse only (to be more precise it’s implemented for adding/removing keyboards only, not present) and there is a race with keyboard layout configuration by g-s-d itself. That’s why the sleep 5 is used.

Update since gnome-settings-daemon 3.19.5

Newer versions of gnome-settings-daemon don’t support hotplug commands anymore (since c50ceb880, released in 3.19.5).

Simple workaround with systemd user service doesn’t work as it can’t properly connect to X server. (xmodmap: unable to open display ':0').

Ugly yet easy solution is creation of ~/.config/autostart/xmodmap.desktop file wrapping the xmodmap script

[Desktop Entry]
Encoding=UTF-8
Name=xmodmap modify keyboard layout
Exec=/etc/hotplug-command.sh 
Type=Application
Categories=System;
StartupNotify=true

Such an “application” will be started on GNOME session startup. Alas it fails to modify keyboard layout when you switch between users or resume from suspend (AFAIK gnome-settings-daemon will overwrite your modifications with keyboard layout).