6

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.

coversnail
  • 6,366

2 Answers2

7

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:

#!/bin/sh
/path/to/set-keyboard-layout.sh uk

Disconnect script:

#!/bin/sh
/path/to/set-keyboard-layout.sh us

set-keyboard-layout.sh

#!/bin/sh
sleep 1
DISPLAY=":0.0"
HOME=/home/your-username
XAUTHORITY=$HOME/.Xauthority
export DISPLAY XAUTHORITY HOME
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).

jeremija
  • 3,308
  • 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
  • This worked almost fine. The layout automatically switches when you plug in the keyboard but it switches back to the previous layout about two seconds after. I tested it in XUbuntu. – Emilio Oct 17 '21 at 13:47
1

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:

#!/bin/sh
case $ACTION in
        add) id=1;;
        remove) id=0;;
esac
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.

xeruf
  • 412