저는 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
. xmodmap
xkbd 확장을 사용하여 보다 일반적인 방법으로 수정할 수 있습니다 .
따라서 사용자가 커널에서 사용하지 않고 사용자에게 loadkeys
등을 사용하여 원하는 키맵을 로드하도록 지시하는 경우
두 방법 모두 "신뢰 가능"하지만 의미가 매우 다릅니다.