Linux 키보드 로깅 - 키맵 변환 [닫기]

Linux 키보드 로깅 - 키맵 변환 [닫기]

저는 Linux에서 입력 이벤트를 모니터링하는 클래스를 작성 중입니다. 이는 GUI 프로그램에서 사용자의 키 입력을 기반으로 USB LED 장치에 대한 시각적 피드백을 제공하는 데몬에서 사용됩니다.

나는 /dev/input/event*에서 읽은 입력 이벤트를 사용합니다. 제가 사용하고 <linux/input.h>있는데 키코드를 받았습니다.

벨기에 키보드를 사용하고 있습니다. 키보드의 "A" 키를 눌렀다 떼면 현재 로그에 다음이 표시됩니다.

29/09/2019 - 14:14:48.751 [Info] Event: time 1569759288.751445, type 4 (Misc), code 4 (ScanCode), value 0x10
29/09/2019 - 14:14:48.751 [Info] Event: time 1569759288.751445, type 1 (Key), code 16 (Q), value 1
29/09/2019 - 14:14:48.751 [Info] Event: time 1569759288.751445, -------------- Report Sync ------------
29/09/2019 - 14:14:48.792 [Info] Event: time 1569759288.792115, type 4 (Misc), code 4 (ScanCode), value 0x10
29/09/2019 - 14:14:48.792 [Info] Event: time 1569759288.792115, type 1 (Key), code 16 (Q), value 0
29/09/2019 - 14:14:48.792 [Info] Event: time 1569759288.792115, -------------- Report Sync ------------

수정자 키가 없으면 실제로 화면에 인쇄되는 것은 작은 "a"입니다.

참고 "코드 16(Q)" - 숫자 16은 10 기반 키 코드입니다.

이제 "Q"를 키보드 레이아웃에 매핑해야 합니다. 이 경우에는 "a"가 기록되어야 합니다. 이를 위해 dumpkeys 프로그램을 사용하여 커널의 현재 변환 테이블을 얻습니다.

이 특정 예의 경우 출력되는 단축 데이터(4개 열만 표시)는 다음과 같습니다.

keycode  16 = +a               +A               at               VoidSymbol

또는 더 적합한 형식:

keycode  16 = +0x0b61          +0x0b41          0x0040           0x0200 

+는 기본적으로 이동 가능함을 의미합니다. 현 단계에서는 이것이 고려해야 할 사항인지 확실하지 않아 제거했습니다.

내가 이해한 바로는 dumpkeys 프로그램이 올바른 숫자에 0xb00을 추가하므로 +를 제거하고 0x0b61에서 0x0b00을 빼서 0x0061을 얻습니다.

0x0061은 "a"에 대한 유니코드 번호 U+0061이며 해당 QString을 벡터의 위치 0에 저장합니다. 덤프 키에 관한 한 첫 번째 열입니다.

이제 질문은 다음과 같습니다.

일부 키는 괜찮습니다. 키보드의 "1" "&" "|" 문자가 있는 물리적 키로 데이터를 해석하면 이 모든 것이 수정자 키를 통해 확인됩니다.

하지만 이 예(물리적 키에는 대문자 "A"만 있음)에서는 작동하지 않습니다.

keymaps(5) - Linux 매뉴얼 페이지에 설명된 수정자 규칙에 따라 다음이 발생해야 합니다.

수정자 키 없이 키코드 16을 누르면 U+0061 또는 "a" -> ok - 작업 번호 0(첫 번째 열에서)이 표시됩니다.

Shift 보조키로 키코드 16을 누르고 U+0041 또는 "A" -> OK를 얻습니다. Shift 보조키의 가중치는 1이므로 첫 번째 동작(두 번째 열에서)

AltGr 수정자 키로 키코드 16을 누르고 U+0040 또는 "@"을 얻습니다. -> OK, AltGr 가중치 2 - 따라서 두 번째 동작(세 번째 열에서)

이제 키코드 16과 Shift 및 AltGr을 동시에 누르면 가중치가 최대 3이 되므로 세 번째 동작(열 4에서 시작)은 VoidSymbol이므로 아무 일도 일어나지 않습니다. 내가 얻은 것은 Omega의 대문자 "Ω"였습니다. 왜?

VoidSymbol의 경우 U+0200은 실제로 ş(이중 무덤이 있는 라틴어 대문자 a)입니다. VoidSymbol로 사용하는 경우 유니코드 값을 어떻게 인쇄합니까?

다른 문제도 있습니다.

또 다른 예는 "§", "6", "^"이 있는 물리적 키입니다. 키맵 덤프 키는 "§" 문자(U+00A7)의 흔적을 제공하지 않습니다. 하지만 여전히 입력할 수 있습니다...

기본적으로 이동 가능하다는 것은 무엇입니까?

편집: 추가 질문

#define modifierShift 1;    //why the difference between ShiftL and ShiftR -> there is no 'shift' key
#define modifierControl 4;  //why the difference between ControlL and ControlR -> there is no 'control' key
#define modifierShiftL 16;  //code 42
#define modifierShiftR 32;  //code 54
#define modifierCtrlL 64;   //code 29
#define modifierCtrlR 128;  //code 97

누군가 내가 이것을 명확히하도록 도와 줄 수 있습니까?

답변1

Linux는 두 세트의 키맵을 사용합니다. 하나는 커널 입력 계층 수준에서 작동하며 키코드를 스캔코드에 할당합니다. 이 매핑을 변경하는 데 사용할 수 있습니다 loadkeys. 이것이 에서 볼 수 있는 것입니다 evtest.

다른 하나는 X 서버 수준에서 작동합니다. X evdev에는 ​​커널 입력 계층에서 입력 이벤트를 수집한 다음 이러한 이벤트를 소위 키 기호에 매핑하는 범용 드라이버가 있습니다 . 이것이 에서 볼 수 있는 것입니다 xev. xmodmapxkbd 확장을 사용하여 보다 일반적인 방법으로 수정할 수 있습니다 .

따라서 사용자가 커널에서 사용하지 않고 사용자에게 loadkeys등을 사용하여 원하는 키맵을 로드하도록 지시하는 경우

두 방법 모두 "신뢰 가능"하지만 의미가 매우 다릅니다.

관련 정보