I have a US-Style laptop, which is fine, but I also have a UK-style Ergonomic USB keyboard.

As such I usually have the US key layout set, but when I settle in at my desk and use the UK USB keyboard I find myself making stupid mistakes on symbols (normally a pretty good touch typist on either ergo or standard kbd).

Can anyone think of a clean way of setting the keyboard layout based on the inferred layout/USBID of any plugged in Keyboard?

Even having a custom setting such as adding a specific USB ID to a runtime script that checks if its plugged in or not. Can this be done without the user having to logout/in? I remember doing something similar with xorg.conf, but that required logout.


You could try writing a udev rule. Plug in your keyboard and type lsusb and write down your keyboard ID, it should look something like

Bus 001 Device 001: ID 13ab:001a name-of-the-keyboard

In this case the 13ab is the vendor ID, and the 001a is the product ID. You can disconnect your keyboard now.

Go to /etc/udev/rules.d/ and create a new file, for example 80-keyboard.rules and write in (replace the idVendor and idProduct in this example with the id of your keyboard):

SUBSYSTEM=="input", ACTION=="add", SUBSYSTEMS=="usb", ATTRS{idVendor}=="13ab", ATTRS{idProduct}=="001a", RUN+="/path/to/connect/script"
SUBSYSTEM=="input", ACTION=="remove", SUBSYSTEMS=="usb", ATTRS{idVendor}=="13ab", ATTRS{idProduct}=="001a", RUN+="/path/to/disconnect/script"

You can't just use the setxkbmap from udev because it does not have the neccessary enviroment variables set. This part is borrowed from this aswer.

Connect script:

/path/to/set-keyboard-layout.sh uk

Disconnect script:

/path/to/set-keyboard-layout.sh us


sleep 1
setxkbmap -layout $1

Don't forget to do chmod +x on all three scripts and change the /home/your-username to your home folder path.

Now run sudo service udev restart and plug in your keyboard and see if the layout changes on connect/disconnect.

I've tested this with my usb hdd and it works (except I had block instead of input for subsystem).

  • The disconnect/connect scripts work, however the udev rules do not work at all for me on Ubuntu 17.04. – kleinfreund Jul 18 '17 at 11:20

To supplement the excellent answer of jeremija, if you have multiple layouts set up (e.g. using the KDE configuration) and want to retain the ability to switch manually, use xkblayout-state in conjunction with this script:

case $ACTION in
        add) id=1;;
        remove) id=0;;
XAUTHORITY="/home/<username>/.Xauthority" DISPLAY=:0 xkblayout-state set $id

Then you also only need one udev rule, which captures all actions:

SUBSYSTEM=="input", SUBSYSTEMS=="usb", ATTRS{idVendor}=="<idVendor>", ATTRS{idProduct}=="<idProduct>", RUN+="</path/to/script>"

Note that xkblayout-state needs to be in the root-PATH, e.g. /usr/local/bin, since udev rules are run as root. Alternatively you can also specify the full path to its location.

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.