web-dev-qa-db-ja.com

キーを押すためにどのキーボードが使用されたかを見分ける方法は?

複数のキーボードがインストールされているペアリングステーションで頻繁に作業しています。 setxkbmap-device <ID>と組み合わせて使用​​して、特定のキーボードのレイアウトを設定できます( IDからxinput を使用して)。両方のキーボードを何度も試すことは避けた方がいいので、setxkbmapのこの情報を取得する簡単なツールを書きたいと思います。私は次のような典型的なユースケースを期待します:

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

Linuxでこの情報を提供するインターフェースはどれですか?理想的にはXがなくても機能するはずですが、それは要件ではありません(Xなしでこれをサポートするツールは多くないようです)。


これまでの調査結果:

  • Linuxmustは、複数のキーボードの異なるレイアウトを同時にサポートするために、どのキーボードで入力するかを知っている必要があります。
  • xinput →list.c→list_xi2XIQueryDeviceは、setxkbmapが使用できるデバイスIDを提供します。
  • showkeyおよびxevはキーボードIDを出力しません。
  • xinput list-props $IDは、キーボードイベントの送信先を示します 。ただし、 別の回答からのコード を使用すると、このデバイスはキーボードを識別するために何も出力しないようです。
  • ほとんどの解決策の1つは、各キーボードIDに対してxinput --test <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)]
    
16
l0b0

さらに掘り下げて明らかに 別の解決策 プレーン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
1
l0b0

デバイスを無効にする

これは、どのキーボードがどれであるかを識別するための1つのアイデアです。コマンド 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)]

上記の出力は、Thinkpadラップトップに搭載されているさまざまなデバイスを示しています。キーボードは1つしか接続していませんが、これは次のとおりです。

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

次に、このデバイスを介して利用可能なプロパティを見てみましょう。

$ 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.

上記から、それが有効になっていることがわかりますので、無効にしましょう:

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

有効にするには:

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

アイデア?

このコマンドを使用してキーボードの1つを無効にして、現在使用しているキーボードを判別できます。

参考文献

4
slm

Xツールを引用しているので、この質問は少し矛盾しているように思えますが、「Xなしで理想的に機能するはずの」ソリューションを求めます。

あなたについて4番目 発見:xinputはあなたに通信を提供します

_$ xinput list-props 11
Device 'AT Translated Set 2 keyboard':
    Device Enabled (145):   1
    Coordinate Transformation Matrix (147): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000
    Device Product ID (266):    1, 1
    Device Node (267):  "/dev/input/event0"
_

少なくとも次のバージョンでは

_$ xinput --version
xinput version 1.6.1
XI version on server: 2.3
_

最初のステップ:Cでキーボードイベントデバイスを検出する

_#include <stdio.h>
//#include <unistd.h>
#include <fcntl.h>
#include <linux/input.h>

// typical use : Sudo ./a.out /dev/input/event*
int main (int argc, char *argv[])
{
  struct input_event ev[64];
  int fd[argc],rd,idev,value, size = sizeof (struct input_event);
  char name[256] = "Unknown";

  if(argc==1) return -1;

  int ndev=1;
  while(ndev<argc && (fd[ndev] = open (argv[ndev], O_RDONLY|O_NONBLOCK)) != -1){
    ndev++;
  }
  fprintf (stderr,"Found %i devices.\n", ndev);
  if(ndev==1) return -1;

  while (1){
    for(idev=1; idev<argc; idev++){
      if( (rd=read (fd[idev], ev, size * 64)) >= size){
      value = ev[0].value;
      if (value != ' ' && ev[1].value == 1 && ev[1].type == 1){
        ioctl (fd[idev], EVIOCGNAME (sizeof (name)), name);
        printf ("%s\n", name);
        return idev;
      }
      }
    }
//    sleep(1);
  }
  return -1;
}
_

このページ に感謝します。私は、ここで借りたコードからほとんどの安全性チェックを取り除いています。明確にするために、実際のコードではおそらくそれらが必要です。

キーの押下はエコーされることに注意してください。したがって、anyキーではなく、修飾キー(Shift、Control ...)を押すようにユーザーに親切に依頼したい場合があります。

2番目のステップ:xinputを使用してデバイス名からX IDを取得する

上記のCソースをコンパイルし、次のように使用します。

xinput list --id-only "keyboard:$(Sudo ./a.out /dev/input/event*)"

4
L. Levrel