How to tell which keyboard was used to press a key?

l0b*_*0b0 16 xorg keyboard x11

我经常在安装了多个键盘的配对站上工作。我可以使用setxkbmapwith-device <ID>来设置特定键盘的布局(使用来自xinputID),但通常我在使用哪个键盘并不明显。最好避免反复尝试两种键盘,因此我想编写一个快速工具来获取setxkbmap. 我希望有一个典型的用例,如下所示:

$ setxkbmap -device "$(get-keyboard-id)" -layout gb
Press Enter to detect keyboard ID
Run Code Online (Sandbox Code Playgroud)

哪个界面在 Linux 上提供此信息?理想情况下,它应该在没有 X 的情况下工作,但这不是必需的(似乎没有很多工具可以在没有 X 的情况下支持这一点)。


迄今为止的发现:

  • Linux必须知道我正在输入哪个键盘才能同时支持多个键盘的不同布局。
  • xinput? 列表.c ? list_xi2? XIQueryDevice提供可由setxkbmap.
  • showkey并且xev不要打印键盘 ID。
  • xinput list-props $ID显示发送键盘事件的位置。但是,使用另一个答案中的代码似乎该设备不会打印任何内容来识别键盘。
  • 一种几乎可能的解决方案是xinput --test <ID> &针对每个键盘 ID运行并查看哪个首先返回某些内容。问题在于找出哪些“键盘”实际上是键盘:

    $ 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)]
    
    Run Code Online (Sandbox Code Playgroud)

slm*_*slm 5

禁用设备

这是识别哪个键盘是哪个的一个想法。您可以使用命令xinput来启用和禁用设备。

例子

$ 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)]
Run Code Online (Sandbox Code Playgroud)

上面的输出显示了我的 Thinkpad 笔记本电脑上的各种设备。我只连接了 1 个键盘,这个是:

    ? AT Translated Set 2 keyboard              id=11   [slave  keyboard (3)]
Run Code Online (Sandbox Code Playgroud)

现在看看通过这个设备可用的属性:

$ 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.
Run Code Online (Sandbox Code Playgroud)

从上面可以看到它已启用,所以让我们禁用它:

$ xinput set-prop "AT Translated Set 2 keyboard" "Device Enabled" 0
Run Code Online (Sandbox Code Playgroud)

要启用它:

$ xinput set-prop "AT Translated Set 2 keyboard" "Device Enabled" 1
Run Code Online (Sandbox Code Playgroud)

想法?

您可以使用此命令禁用其中一个键盘以确定您使用的是哪个键盘。

参考


l0b*_*0b0 4

更多的挖掘揭示了另一种使用普通 Bash 和普通用户帐户的解决方案。脚本

#!/usr/bin/env bash

set -o errexit -o nounset -o noclobber -o pipefail

# Remove leftover files and processes on exit
trap 'rm --recursive -- "$dir"; kill -- -$$' EXIT
dir="$(mktemp --directory)"
cd "$dir"

# Log key presses to file
xinput --list --id-only | while read id
do
    # Only check devices linked to an event source
    if xinput --list-props "$id" | grep --quiet --extended-regexp '^\s+Device Node.*/dev/input/event'
    then
        xinput test "$id" > "$id" &
    fi
done

# Check for key presses
while sleep 0.1
do
    for file in *
    do
        if [[ -s "$file" ]]
        then
            echo "$file"
            exit
        fi
    done
done
Run Code Online (Sandbox Code Playgroud)