Ubuntu – How to automatically change the system keyboard layout when plugging in an external keyboard


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.

Best Answer

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).