Получить scancode вместо keycode на Linux с помощью X11
Я пытаюсь прослушать ввод с клавиатуры (используя цикл событий X11) и получить сканкоды. Эти сканкоды должны ссылаться на физическое расположение ключа, а не на символ, который он вводит. Проблема в том, что все, что я могу получить, - это KeySyms и KeyCodes, которые отображаются по-разному для разных языков (например, QWERTY vs QWERTZ).
Мое текущее решение-прочитать файл" /usr/share/X11/xkb/keycodes/evdev". Он содержит сопоставления ключевых местоположений с ключевыми кодами. Используя это я могу просто перевести любой ключ обратно в скан. Я думаю, что это не стабильный способ делать вещи, хотя. Я вообще мало что знаю о Linux. Вот почему я подумал, что спросить Здесь может быть хорошей идеей.
Можно ли с уверенностью предположить, что эти отображения evdev используются большинством машин пользователя? Если нет, то где еще я могу найти ключевые сопоставления, которые на самом деле используются? Или есть лучшее решение для всего этого?
1 ответ:
У меня была та же проблема, и я только что нашел решение. Давайте начнем с очевидного первого.
Если вы хотите получить определенные ключи, такие как" W "или" 4", независимо от того, где они расположены, вы можете просто преобразовать код ключа, полученный от события, в KeySym. В этом случае "W" - это
Однако иногда вы хотите получить ключи, такие как"NTh ключ mth строки". Вам нужны ключевые имена, чтобы сделать тот. В этом случае "W" - этоXK_WиXK_w, а" 4 " - этоXK_4(иXK_dollarна большинстве клавиатур).AD02, а" 4 " -AE04на клавиатурах QWERTY. Предположим, вы создаете игру, в которой игрок должен использовать клавиши WASD для перемещения. Если вы ищете KeySyms, он будет отлично работать на клавиатурах QWERTY, но у людей, использующих другие раскладки клавиатуры, такие как AZERTY, QWERTZ и DVORAK, возникнут проблемы. Поэтому в этом случае лучше использовать имена ключей.Использовать имена ключей на самом деле довольно легко, но документация очень грязная (но я все еще рекомендую вам взглянуть на него). Мне пришлось взглянуть на исходный кодGLFW (в частности, src/x11_init.c ), потому что я был невежествен. Этот метод требует Xkb, но вы уже использовали его, так что я думаю, что это не проблема.
Сначала вам нужно получить карту клавиатуры и получить символические имена. Нам нужны только имена ключей, поэтому мы используем
XkbKeyNamesMask.#include <X11/XKBlib.h> XkbDescPtr KbDesc = XkbGetMap(XDisplay, 0, XkbUseCoreKbd); XkbGetNames(XDisplay, XkbKeyNamesMask, KbDesc);Затем в цикле событий вы можете использовать массив KbDesc->names->keys, чтобы получить имя ключа для конкретного код ключа:
XEvent Event; XNextEvent(XDisplay, &Event); switch (Event.type) { case KeyPress: /* I'm not sure this 'if' is necessary, but better safe than sorry */ if ((Event.xkey.keycode >= KbDesc->min_key_code) && (Event.xkey.keycode <= KbDesc->max_key_code)) { /* Copy key name into Name */ char Name[XkbKeyNameLength + 1]; memcpy(Name, KbDesc->names->keys[Event.xkey.keycode].name, XkbKeyNameLength); Name[XkbKeyNameLength] = '\0'; /* Null terminator */ if (strcmp(Name, "AD02") == 0) /* Is it W (for QWERTY and QWERTZ) / Z (for AZERTY) / comma (for DVORAK) / ц (for Russian) etc... ? */ { /* Do something... */ } else if (strcmp(Name, "AE04") == 0) /* Is it 4 (for most keyboards) / whatever's in its place? */ { /* Do something... */ } /* ... */ } /* ... */ }И это все. Похоже, пока что это работает довольно хорошо. Я хотел бы отметить, что специальные ключи имеют очень разные имена ключей. Например, сдвиг влево - это
LFSH, Управление влево-этоLCTL, пространство-этоSPCE, а побег-этоESC.Я надеюсь, что это помогает.
Comments