複数のキーボードがインストールされているペアリングステーションで頻繁に作業しています。 setxkbmap
を-device <ID>
と組み合わせて使用して、特定のキーボードのレイアウトを設定できます( IDからxinput
を使用して)。両方のキーボードを何度も試すことは避けた方がいいので、setxkbmap
のこの情報を取得する簡単なツールを書きたいと思います。私は次のような典型的なユースケースを期待します:
$ setxkbmap -device "$(get-keyboard-id)" -layout gb
Press Enter to detect keyboard ID
Linuxでこの情報を提供するインターフェースはどれですか?理想的にはXがなくても機能するはずですが、それは要件ではありません(Xなしでこれをサポートするツールは多くないようです)。
これまでの調査結果:
xinput
→list.c→list_xi2
→XIQueryDevice
は、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)]
さらに掘り下げて明らかに 別の解決策 プレーン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つのアイデアです。コマンド 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つを無効にして、現在使用しているキーボードを判別できます。
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
_
_#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 ...)を押すようにユーザーに親切に依頼したい場合があります。
上記のCソースをコンパイルし、次のように使用します。
xinput list --id-only "keyboard:$(Sudo ./a.out /dev/input/event*)"