Ask Ubuntu is a question and answer site for Ubuntu users and developers. It's 100% free.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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>

share|improve this question
up vote 9 down vote accepted

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 LAYOUT manually entered in the first line to the USB Keyboard DEVICE found first in the xinput list:

DEVICE="$(xinput -list | grep "USB Keyboard" | awk -F'=' '{print $2}' | cut -c 1-2 | head -1)"
setxkbmap -device "$DEVICE" -layout "$LAYOUT"
exit 0


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:


ATTRS{idVendor}=="09da", ATTRS{idProduct}=="0260", OWNER="sadi"
ACTION=="add", RUN+="/home/sadi/.bin/usb-keyboard-in_udev"
ACTION=="remove", RUN+="/home/sadi/.bin/usb-keyboard-out_udev"


/home/sadi/.bin/usb-keyboard-in &


sleep 1
usbkbd_id=`xinput -list | grep "USB Keyboard" | awk -F'=' '{print $2}' | cut -c 1-2 | head -1`
if [ "${usbkbd_id}" ]; then
    gsettings set org.gnome.settings-daemon.plugins.keyboard active false
    sleep 2
    setxkbmap -device "${usbkbd_id}" -layout "${usbkbd_layout}"


/home/sadi/.bin/usb-keyboard-out &


sleep 1
gsettings set org.gnome.settings-daemon.plugins.keyboard active true


  1. Of course all of the four files in your ."bin" folder should have necessary permissions (readable and executable) which maybe implemented for example with a Terminal command like chmod - 755 /home/sadi/.bin/usb-keyboard-*
  2. Sometimes after the USB keyboard is plugged in it still uses the same (default) keyboard layout, and switches to the specified layout upon the second try (perhaps requiring a little more sleep time somewhere?)
  3. The USB keyboard specific layout is not effective in the login screen (when you Log Out).
  4. If you use a separate partition for /home, then it might be a better idea to put the four scripts somewhere in the root partition, e.g. /usr/local/bin and modify the contents of all respective files accordingly as sometimes udev may look for those files before your /home partition is mounted and cause problems.


  1. USB keyboard vendor and product ids should be changed as per the output of the command lsusb (For example, my lsusb output have this for my USB Keyboard: Bus 001 Device 006: ID 09da:0260 A4 Tech Co., Ltd)
  2. OWNER and all user directory names should be changed from "sadi" to another name
  3. The usbkbd_id may require a little adjustment to grab the correct device id (For example, output of the commands 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 by awk 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)
  4. The value for usbkbd_layout may be any other valid choice
share|improve this answer
It would be great if another similar script could automatically run whenever a USB keyboard is plugged in, as asked (not answered yet) here:… – Sadi Aug 27 '13 at 7:30
It can be helpful if you can post another answer out of this messy thread:… – user126106 Aug 30 '13 at 4:00
@MinimusHeximus Thanks a million!!! After going through the thread you've pointed out and making some trial-and-error, I've finally sorted it out and will add this new (almost) perfect hotplugging solution above! – Sadi Sep 20 '13 at 12:58
well I could not examine that thread myself :) – user126106 Sep 21 '13 at 11:39
My Keyboard for some reason has two IDs, so instead of using an IF I had to use a FOR. It works for me now, thank you! – zVictor Jul 9 '14 at 8:26

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.


ATTRS{idVendor}=="1e54", ATTRS{idProduct}=="2030", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/etc/udev/ in"
ATTRS{idVendor}=="1e54", ATTRS{idProduct}=="2030", SUBSYSTEMS=="usb", ACTION=="remove", RUN+="/etc/udev/ out"

/etc/udev/ (absolutely necessary to use an intermediate backgrounding script)


dir=$(dirname $0)
command=$(basename $0)
arg=$1 # must be "in" or "out"

[ -x "$command" ] && $command $arg >$LOG 2>&1 &


# jp dot ayanides at

MODEL="tm2030USB-102" # keyboard model

USER=$(/usr/bin/who | /usr/bin/awk -v DIS=':0' '{if ($2==DIS) print $1}')
eval HOME=~$USER

case $1 in
                BEPO=$($XINPUT list --short | grep " USB Keyboard" | grep keyboard | sed -e 's/^.*id=\([0-9]\+\).*/\1/g')
                if [ -n "$BEPO" ]; then
                        [ -x $GSETTING ] && $GSETTING set org.gnome.settings-daemon.plugins.keyboard active false
                        # apparently nothing to do with TDE (trinity KDE)
                        for ID in $BEPO; do # case of multiple bepo keyboard is taken into account
                                [ -x $SETXKBMAP ] && $SETXKBMAP -device $ID -model $MODEL -layout fr -variant bepo
                echo "bépo keyboard id(s) is (are) $BEPO"
                [ -x $XSET ] && $XSET -display $DISPLAY r rate 250 40
                # apparently nothing to do with TDE (trinity KDE)
                [ -x $GSETTING ] && $GSETTING set org.gnome.settings-daemon.plugins.keyboard active true
                printf "wrong parameter: $1\n"
                exit 1
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

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