Я пишу класс, который отслеживает события ввода в Linux. Он будет использоваться в демоне, который воздействует на нажатия клавиш пользователя в программах с графическим интерфейсом, чтобы дать визуальную обратную связь на устройстве с USB-подсветкой.

Я использую события ввода, которые я читаю из /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 ------------

То, что на самом деле печатается на экране без каких-либо клавиш-модификаторов, - это маленькая буква «а»

Обратите внимание на «код 16 (Q)» — число 16 является кодом ключа с основанием 10.

Теперь мне нужно сопоставить этот «Q» с моей раскладкой клавиатуры, и в этом случае он должен регистрировать «a». Для этого я использую программу dumpkeys для получения текущих таблиц перевода моего ядра.

Что касается этого конкретного примера, он выводит сокращенные данные (показаны только 4 столбца):

keycode  16 = +a               +A               at               VoidSymbol

Или в более подходящем формате:

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

По умолчанию + означает возможность переключения. На данном этапе я не уверен, нужно ли это учитывать, поэтому я убираю это.

Насколько я понимаю, программа dumpkeys добавляет 0xb00 к правильному числу, поэтому я опускаю +, вычитаю 0x0b00 из 0x0b61, чтобы получить 0x0061.

0x0061 — это номер Юникода U+0061 для «a», и я сохраняю эту QString в векторе в ячейке 0, поэтому первый столбец, насколько это касается ключей дампа.

Теперь о проблемах:

Некоторые клавиши в порядке. Если я интерпретирую данные для физического ключа, имеющего символы '1' '&' '|' на моей клавиатуре все проверяется клавишами-модификаторами.

Но для этого примера (физический ключ имеет только заглавную букву «А») это не нормально.

В соответствии с правилами модификаторов, описанными в keymaps(5) - man-странице Linux, должно произойти следующее:

Я нажимаю код 16 без какой-либо клавиши-модификатора и получаю U + 0061 или «a» -> ok - номер действия ноль (из 1-го столбца)

Я нажимаю код 16 с клавишей модификатора сдвига и получаю U+0041 или 'A' -> ok, так как модификатор сдвига имеет вес 1, поэтому действие номер один (из 2-го столбца)

Я нажимаю код 16 с клавишей-модификатором AltGr и получаю U+0040 или '@' -> ok, вес AltGr 2 - поэтому действие номер два (из 3-го столбца)

Теперь, если я нажму код клавиши 16 вместе с Shift и AltGr, вес в сумме составит 3, поэтому действие номер три (из 4-го столбца), также известное как VoidSymbol, так что ничего не должно произойти. Однако я получаю заглавную омегу «Ω». Почему?

Что касается этого VoidSymbol, то U+0200 на самом деле Ȁ (латинская заглавная буква a с двойной гравировкой). Как напечатать этот символ, если его значение Unicode используется как 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
ZoOl007 29 Сен 2019 в 20:08
Вы используете X (графическую среду)? Если да, дает ли xev правильные ключи? Если да, является ли это жестким требованием, чтобы вы использовали входной слой ядра, или вы могли бы также перехватывать ключи на уровне X?
 – 
dirkt
30 Сен 2019 в 12:01
Да, использование X.xev дает правильные ключи. Я знаю некоторых пользователей, которые не используют X, хотя это редкость. Я посмотрю на перехват ударов по клавиатуре на уровне x-сервера, но я бы предпочел придерживаться слоя ввода ядра - если это возможно, конечно. Если вы знаете, почему у меня возникают проблемы с уровнем ядра, пожалуйста, поделитесь. Также приветствуется небольшой код C++ для событий клавиатуры x-сервера.
 – 
ZoOl007
30 Сен 2019 в 18:13
Пока похоже, что ваша бельгийская клавиатура выбрана только на слое X, поэтому вы не видите правильных клавиш на слое ввода ядра. Попробуйте loadkeys с бельгийской раскладкой в ​​​​/usr/share/keymaps/i386/azerty, сначала на консоли, а затем посмотрите, работает ли она также с X.
 – 
dirkt
30 Сен 2019 в 20:56
Я установил консольные данные. Я загрузил be-latin1.kmap.gz, и если я запускаю dumpkeys, у меня теперь есть правильный код ключа 7 = шестой абзац dead_circumflex VoidSymbol Control_asciicircum VoidSymbol для одного из ключей, которые я описал выше, так что теперь все выглядит нормально. Что это значит для самого класса... Мне нужно немного вникнуть. Как можно надежно обнаружить ключи? Я не вижу этого атм.
 – 
ZoOl007
30 Сен 2019 в 21:14

1 ответ

Лучший ответ

Linux использует два набора сопоставлений клавиш. Один работает на уровне входного слоя ядра и назначает код клавиши скан-коду. Вы можете использовать loadkeys, чтобы изменить это сопоставление. Это то, что вы видите в evtest.

Другой работает на уровне X-сервера. X имеет (среди прочего) общий драйвер evdev, который собирает входные события из входного слоя ядра, а затем отображает их в так называемые символы ключей. Это то, что вы видите в xev. Вы можете изменить это с помощью xmodmap и через расширения xkbd более общим способом.

Таким образом, если у вас есть пользователи, которые не используют X, у вас есть два варианта: воздействовать на скан-код клавиши (т. е. положение клавиши на клавиатуре, поэтому вы реализуете собственное сопоставление клавиш) или действовать на клавишу как переведенную. в ядре и проинструктируйте своих пользователей использовать loadkeys и т. д. для загрузки выбранной ими раскладки клавиш.

Оба метода «надежны», но имеют очень разную семантику.

1
dirkt 30 Сен 2019 в 21:32
Хорошо, спасибо за разъяснение. Я смогу разобраться с информацией, которую вы мне дали.
 – 
ZoOl007
30 Сен 2019 в 22:02
Я еще раз смотрю, и для кода 16, который я описал выше, у меня все еще нет Ω в столбце 4 в раскладке. Вы знаете, как это работает?
 – 
ZoOl007
1 Окт 2019 в 18:04