Xorg – How to Tell Which Keyboard Was Used to Press a Key

keyboardx11xorg

I frequently work on pairing stations where there are multiple keyboards installed. I can use setxkbmap with -device <ID> to set the layout for a specific keyboard (using an ID from xinput), but often it's not obvious which keyboard I'm at. It would be better to avoid the back-and-forth of trying both keyboards, so I'd like to write a quick tool to get this information for setxkbmap. I'd expect a typical use case like the following:

$ setxkbmap -device "$(get-keyboard-id)" -layout gb
Press Enter to detect keyboard ID

Which interface provides this information on Linux? Ideally it should work without X, but that's not a requirement (there doesn't seem to be many tools which support this without X).


Findings so far:

  • Linux must know which keyboard I'm typing on to support different layouts for multiple keyboards simultaneously.
  • xinput → list.c → list_xi2XIQueryDevice provides device IDs usable by setxkbmap.
  • showkey and xev don't print keyboard IDs.
  • xinput list-props $ID shows where keyboard events are sent. However, using code from another answer it seems this device doesn't print anything to identify the keyboard.
  • One almost possible solution is to run xinput --test <ID> & for each keyboard ID and see which one returns something first. The problem with that is figuring out which "keyboards" are actually keyboards:

    $ xinput | grep keyboard
    ⎣ Virtual core keyboard                         id=3    [master keyboard (2)]
        ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
        ↳ Power Button                              id=6    [slave  keyboard (3)]
        ↳ Video Bus                                 id=7    [slave  keyboard (3)]
        ↳ Power Button                              id=8    [slave  keyboard (3)]
        ↳ Sleep Button                              id=9    [slave  keyboard (3)]
        ↳ WebCam SC-13HDL10931N                     id=10   [slave  keyboard (3)]
        ↳ AT Translated Set 2 keyboard              id=11   [slave  keyboard (3)]
    

Best Answer

Disable device

Here's one idea towards identifying which keyboard is which. You can use the command xinput to enable and disable devices.

Example

$ xinput list
⎡ Virtual core pointer                      id=2    [master pointer  (3)]
⎜   ↳ Virtual core XTEST pointer                id=4    [slave  pointer  (2)]
⎜   ↳ SynPS/2 Synaptics TouchPad                id=12   [slave  pointer  (2)]
⎜   ↳ TPPS/2 IBM TrackPoint                     id=13   [slave  pointer  (2)]
⎜   ↳ Logitech USB Receiver                     id=9    [slave  pointer  (2)]
⎜   ↳ Logitech USB Receiver                     id=10   [slave  pointer  (2)]
⎣ Virtual core keyboard                     id=3    [master keyboard (2)]
    ↳ Virtual core XTEST keyboard               id=5    [slave  keyboard (3)]
    ↳ Power Button                              id=6    [slave  keyboard (3)]
    ↳ Video Bus                                 id=7    [slave  keyboard (3)]
    ↳ Sleep Button                              id=8    [slave  keyboard (3)]
    ↳ AT Translated Set 2 keyboard              id=11   [slave  keyboard (3)]
    ↳ ThinkPad Extra Buttons                    id=14   [slave  keyboard (3)]

The above output shows the various devices that I have on my Thinkpad laptop. I only have 1 keyboard attached, this one:

    ↳ AT Translated Set 2 keyboard              id=11   [slave  keyboard (3)]

Now take a look at the properties available through this device:

$ xinput list-props "AT Translated Set 2 keyboard"
Device 'AT Translated Set 2 keyboard':
    Device Enabled (124):   1
    Coordinate Transformation Matrix (126): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.

From the above you can see that it's enabled, so let's disable it:

$ xinput set-prop "AT Translated Set 2 keyboard" "Device Enabled" 0

To enable it:

$ xinput set-prop "AT Translated Set 2 keyboard" "Device Enabled" 1

The idea?

You could enable disable one of the keyboards using this command to determine which one you're on.

References