키를 누르는 데 사용 된 키보드를 확인하는 방법?

여러 키보드가 설치된 페어링 스테이션에서 자주 작업합니다. setxkbmap와 함께 사용 -device <ID>하여 특정 키보드의 레이아웃을 설정할 수 있지만 (의 IDxinput 사용 ) 종종 어떤 키보드를 사용하고 있는지 명확하지 않습니다. 두 키보드를 모두 시도하는 것을 피하는 것이 좋습니다. 따라서이 정보를 얻을 수있는 빠른 도구를 작성하고 싶습니다 setxkbmap. 다음과 같은 일반적인 유스 케이스를 기대합니다.

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

Linux에서이 정보를 제공하는 인터페이스는 무엇입니까? 이상적으로는 X없이 작동해야하지만 요구 사항은 아닙니다 (X없이 이것을 지원하는 많은 도구는 보이지 않습니다).


지금까지의 결과 :

  • Linux 여러 키보드에 대해 서로 다른 레이아웃을 동시에 지원하기 위해 입력하는 키보드 알고 있어야합니다 .
  • xinput→ list.c → list_xi2→에서 XIQueryDevice사용할 수있는 장치 ID를 제공합니다 setxkbmap.
  • showkeyxev키보드 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)]
    


답변

장치 비활성화

다음은 어떤 키보드가 어떤 키보드인지 식별하는 아이디어입니다. 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 랩탑에있는 다양한 장치를 보여줍니다. 하나의 키보드 만 연결되어 있습니다.

    ↳ 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

아이디어?

이 명령을 사용하여 키보드 중 하나를 비활성화하여 사용중인 키보드를 확인할 수 있습니다.

참고 문헌


답변

X 툴을 인용하고 있지만 “이상적으로 X없이 작동해야한다”는 솔루션을 요구하기 때문에이 질문은 약간 모순된다.

번째 발견에 관하여 :
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;
}

이 페이지 덕분에 많은 감사 . 필자는 여기서 빌린 코드에서 대부분의 안전 점검을 명확하게하기 위해 실제 코드에서 아마도 원하는 것을 제거했습니다.

키 누름은 에코되므로 실제로 사용자에게 수정 자 키 (Shift, Control …)를 누르지 말라고 친절하게 요청할 수 있습니다. 키를 누릅니다.

두 번째 단계 : xinput을 사용하여 장치 이름에서 X ID를 가져옵니다.

위의 C 소스를 컴파일하고 다음과 같이 사용하십시오.

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


답변

더 많은 파기 작업은 일반 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


답변