I have configured my keyboard layout by adding a call to setxkbmap to my .xinitrc. This works for my laptop's internal keyboard and for any external keyboard that is plugged in when the X server starts. If I plug in an external keyboard later, it uses the default US keymap.

How can I make sure that any keyboard that I plug in has my preferred layout?


As Gilles commented on Dominik R's answer yesterday, the udev approach only works for the root user and doesn't work well as a general, unprivileged solution. I'd suggest considering inputplug(1) by Andrew Shadura available in Debian as the package inputplug as well as at the project site.

inputplug(1) is a rather straightforward as a XINPUT event loop listener which will invoke a script with decoded event parameters as arguments. Since you're using .xinitrc, I imagine you're using a modest window manager / environment and a background listener of this sort should be pretty straightforward for you.

Another possibility is using udev in a less traditional way by writing a script parsing the output from "udevadm monitor" and invoking setxkbmap upon recognizing a matching device being connnected.

Good Luck!

  • 1
    I am using a modest input manager but I am a beginner at that so some example calls to inputplug would be much appreciated.
    – Thriveth
    Sep 26 '19 at 7:42
  • 1
    Added a complete example as an answer below. Jul 9 at 20:53

inputplug, suggested by etherfish five years ago, is an excellent answer, but the answer was missing a complete example. So here is what I use in my .xinitrc to run setxkbmap exactly once in the beginning, and another time every time a new keyboard is plugged in:

{ echo "XIDeviceEnabled XISlaveKeyboard"; inputplug -d -c /bin/echo; } |
while read event
        case $event in
                setxkbmap -option grp:switch,grp:shift_toggle,grp_led:scroll us,il ,lyx
                setxkbmap -option caps:none
done &

The inputplug -d -c /bin/echo echos a message like

XIDeviceEnabled 11 XISlaveKeyboard Logitech K270

every time a keyboard is plugged in, and the while loop finds such messages and causes the relevant setxkbmap commands to run (in my example, I set a Hebrew keyboard mapping, and remove the Caps Lock feature which I hate). The extra echo "XIDeviceEnabled XISlaveKeyboard" in the beginning causes the loop to also find a "new keyboard" exactly once in the beginning. inputplug also has a "-0" option to print existing keyboards on startup, but this will usually print multiple keyboards and cause the setxkbmap to be needlessly run multiple times on startup.

  • 1
    Thank you for adding extra detail and an example!
    – etherfish
    Jul 9 at 22:53
  • 1
    Author here. You can also directly call your script with -c, this is actually how it’s intended to be used — just put the case/esac into a separate script and run inputplug as a dæmon.
    – andrewsh
    Jul 21 at 14:05
  • Yes, indeed it's also possible to pass a separate handler script to inputplug. However, since anyway I need to write code to run inputplug - in my .xinitrc - I wanted all the related code to be in one place, and not have to create a separate handler script somewhere else. Jul 22 at 21:39

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.