I often plugin a USB keyboard to my laptop (in addition to external monitor and mouse, which all virtually convert my laptop to a desktop computer) and I prefer using a different keyboard layout then.
I have to manually change the current keyboard layout each time I plugin this USB keyboard.
And I'd like to use an automated way for this, if possible.
Radu's answer to the question here gives some clues, but it seems I'll need a startup script for this task as the device ID for my USB keyboard changes every time the computer starts.
This startup script will probably first include the command xinput -list | grep "USB Keyboard"
, and another command to grab the first USB Keyboard ID number displayed and then use it in the final command to set my chosen layout for that USB keyboard as below:
setxkbmap -device <NUMBER> -layout <LAYOUT>
After a little research, I've found a solution, although I'm still open to other (probably better) answers.
Here's a startup script (which can be added to Startup Applications) which will set the maually entered usbkbd_layout variable to the usbkbd device ids found in the xinput -list:
This script is quite useful (and more stable) for scenarios where user starts using the laptop on a desktop setup (with external keyboard, mouse and monitor, etc.), and it can also be run manually whenever the external USB keyboard is plugged in...
==========================================================================
THE BETTER (almost perfect) SOLUTION - found thanks to MinimusHeximus and the respective contributors to the thread he mentioned in his comment below:
I can now just plugin my USB keyboard and automatically have its different (TR-F) keyboard layout applied while still keeping the default keyboard layout (TR-Q) on my laptop!
Here are the files and their contents that make this possible:
/etc/udev/rules.d/00-usb-keyboard.rules
/home/sadi/.bin/usb-keyboard-in_udev
/home/sadi/.bin/usb-keyboard-in
/home/sadi/.bin/usb-keyboard-out_udev
/home/sadi/.bin/usb-keyboard-out
Notes:
chmod - 755 /home/sadi/.bin/usb-keyboard-*
IN ORDER TO ADAPT THIS SETUP TO DIFFERENT REQUIREMENTS:
lsusb
(For example, mylsusb
output have this for my USB Keyboard:Bus 001 Device 006: ID 09da:0260 A4 Tech Co., Ltd
)xinput -list | grep "USB Keyboard"
gives me two lines;↳ USB Keyboard id=14 [slave keyboard (3)]
and↳ USB Keyboard id=16 [slave keyboard (3)]
; which are then filtered byawk
using "=" as field delimiter and capturing the second part; then cutting only the first two digits, and then using only the value in the first line)One can specify X11 driver options inside the udev rule, no custom scripts are needed. As an example, here are the contents of my /etc/udev/rules.d/99-usb-kbd.rules
This rule ensures that a particular USB keyboard uses US layout in Xorg (my laptop's internal keyboard is German, and this is also my primary layout). Important points:
idVendor
andidProduct
of your device usinglsusb
orevtest
/usr/share/X11/xkb/symbols
. Pay attention to specify both a valid layout and a valid variant./lib/udev/rules.d/64-xorg-xkb.rules
I've just improved this solution for a bépo Typematrix keyboard (french version of optimized excellent dvorak) and in a wide system context (it supposes that you have a root access to the machine). It needs only 3 files to work. You can consult a logfile in case of failure to figure out what is failing.
/etc/udev/96-usb-keyboard.rules
/etc/udev/bepo-typematrix-kbd.sh (absolutely necessary to use an intermediate backgrounding script)
/etc/udev/bepo-typematrix-kbd
After fiddling around a lot, this is what I have running for now. Maybe I’ll write a complete article of sorts and publish the code within a repository, if that would be of interest.
Set up a new rule set for udev like that:
The rule is supposed to call a shell script whenever some action is triggered by a device with the given combination of vendor and product ID.
After adding the new rule set, restart the udev service:
Note: I was not able to achieve reliable results by providing more specific matching rules in that file. Most significantly, adding a
ACTION
matching rule did not work. As far as I can tell, the script was triggered anyway. When addingACTION=="add"
, the script would still be called upon removing the device. Very strange and confusing.However the action that triggered the udev rule will be available to the called script as shown below.
Next, the script itself. Well, not quite. Note the
wrapper
suffix in the file name. This indicates that this is not the actual script but a wrapper that calls the script and executes it in the background so that udev can finish its process.~/.bin/switch-kb-layout-wrapper.sh
:The variable
ACTION
contains the udev action that was triggered by the device. It yields values likeadd
(device was plugged in) andremove
(device was removed). We’ll use these later on.~/.bin/switch-kb-layout.sh
:Replace my username with yours when setting the
HOME
variable ($(whoami)
won’t work here, since this will not be called by your user but byroot
).For testing purpose, I added some lines that log certain events to a file in my home directory to see whether everything works. You can savely remove these.
Finally, these scripts need to have execution permissions. Also it might be important to note that these scripts will be called by the
root
user, so be careful what you do in there.I had some permission problem with the script executed by udev. I resolved with sudo as follow:
Set the keyboard map for each device
You can also define it in a Xorg config file.
It is layed out in this stackexchange answer: https://superuser.com/a/946575/437492