Преобразовать символ ASCII в код x11
У меня есть небольшая программа, которая принимает ввод в виде символов ascii. Мне нужно иметь возможность преобразовать их в коды клавиш для использования с функциями x11. Есть ли функция xlib для этой или другой библиотеки? Или лучше будет работать большой корпус переключателя?
3 ответа
Ты можешь использовать XStringToKeysym
преобразовать в KeySym
, с последующим XKeysymToKeycode
для преобразования в KeyCode
,
Display *display = ...;
KeySym sym_a = XStringToKeysym("A");
KeyCode code_a = XKeysymToKeycode(display, sym_a);
На этот вопрос есть старый неправильный ответ (от @oldrinb), который, как ни странно, никогда не оспаривался. Как указано в комментарии, вы не можете использовать XStringToKeysym для общего сопоставления символов с KeySyms. Он будет работать для букв и цифр, но это все, потому что имя KeySym отображается непосредственно для этих символов ASCII. Для других символов ASCII, таких как знаки препинания или пробел, это не сработает.
Но вы можете сделать лучше, чем это. Если вы посмотрите на <X11/keysymdef.h>
вы найдете это для ASCII
0x20-0xFF, символы отображаются прямо на XKeySyms
, Итак, я бы сказал, что проще просто использовать этот диапазон символов как KeySyms
и просто сопоставьте оставшиеся 32 символа с соответствующими им KeyCodes
, Так что я бы сказал, что код должен быть более правильным:
Display *display = ...;
if ((int)c >= 0x20) {
XKeysymToKeycode(display, (KeySym)c);
} else {
... // Exercise left to the reader :-)
}
Предложение else требует многократного KeyCodes
так как например ASCII
1 (контроль-A) XK_A
с XK_CONTROL_R
(или же XK_CONTROL_L
Модификатор. Так что вам нужно выдать, например: XK_CONTROL_L
ВНИЗ, XK_A
ВНИЗ, XK_A
UP, XK_CONTROL_L
UP.
Вот игрушечная программа, которая демонстрирует это, повторяя первый аргумент через смоделированные события клавиатуры:
#include <stdio.h>
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <xcb/xcb.h>
#include <xcb/xcb_event.h>
#include <xcb/xtest.h>
main(int argc, char **argv)
{
char *pc;
xcb_connection_t *xconn;
KeyCode code_a;
Display *dpy = XOpenDisplay(NULL);
xconn = XGetXCBConnection(dpy);
for (pc = argv[1]; *pc != '\0'; ++pc) {
if (*pc >= (char)0x20) {
code_a = XKeysymToKeycode(dpy, (KeySym)*pc);
xcb_test_fake_input(xconn, XCB_KEY_PRESS, code_a, XCB_CURRENT_TIME, XCB_NONE, 0, 0, 0);
xcb_test_fake_input(xconn, XCB_KEY_RELEASE, code_a, XCB_CURRENT_TIME, XCB_NONE, 0, 0, 0);
xcb_flush(xconn);
} else {
fprintf(stderr, "Eeek - out-of-range character 0x%x\n", (unsigned int)*pc);
}
}
XCloseDisplay(dpy);
}
Вы должны связать это с: -lX11 -lxcb -lxcb-xtest -lX11-xcb
Отказ от ответственности: при написании этого кода не было причинено вреда KeySyms.
Вы также можете реализовать сопоставление вручную, скажем, из выводаxmodmap -pke
(но это сломается на установках X11, которые не имеют такого же сопоставления). Что-то вроде этого (для ASCII):
typedef struct{
xcb_keycode_t code;
u16 state;
}x11_key_t;
x11_key_t X11_ASCII_TO_KEY[] = {
['1'] ={10,0x0000}, ['!'] ={10,0x0001},
['2'] ={11,0x0000}, ['@'] ={11,0x0001},
['3'] ={12,0x0000}, ['#'] ={12,0x0001},
['4'] ={13,0x0000}, ['$'] ={13,0x0001},
['5'] ={14,0x0000}, ['%'] ={14,0x0001},
['6'] ={15,0x0000}, ['^'] ={15,0x0001},
['7'] ={16,0x0000}, ['&'] ={16,0x0001},
['8'] ={17,0x0000}, ['*'] ={17,0x0001},
['9'] ={18,0x0000}, ['('] ={18,0x0001},
['0'] ={19,0x0000}, [')'] ={19,0x0001},
['-'] ={20,0x0000}, ['_'] ={20,0x0001},
['='] ={21,0x0000}, ['+'] ={21,0x0001},
['q'] ={24,0x0000}, ['Q'] ={24,0x0001},
['w'] ={25,0x0000}, ['W'] ={25,0x0001},
['e'] ={26,0x0000}, ['E'] ={26,0x0001},
['r'] ={27,0x0000}, ['R'] ={27,0x0001},
['t'] ={28,0x0000}, ['T'] ={28,0x0001},
['y'] ={29,0x0000}, ['Y'] ={29,0x0001},
['u'] ={30,0x0000}, ['U'] ={30,0x0001},
['i'] ={31,0x0000}, ['I'] ={31,0x0001},
['o'] ={32,0x0000}, ['O'] ={32,0x0001},
['p'] ={33,0x0000}, ['P'] ={33,0x0001},
['['] ={34,0x0000}, ['{'] ={34,0x0001},
[']'] ={35,0x0000}, ['}'] ={35,0x0001},
['\n']={36,0x0000},
['a'] ={38,0x0000}, ['A'] ={38,0x0001},
['s'] ={39,0x0000}, ['S'] ={39,0x0001},
['d'] ={40,0x0000}, ['D'] ={40,0x0001},
['f'] ={41,0x0000}, ['F'] ={41,0x0001},
['g'] ={42,0x0000}, ['G'] ={42,0x0001},
['h'] ={43,0x0000}, ['H'] ={43,0x0001},
['j'] ={44,0x0000}, ['J'] ={44,0x0001},
['k'] ={45,0x0000}, ['K'] ={45,0x0001},
['l'] ={46,0x0000}, ['L'] ={46,0x0001},
[';'] ={47,0x0000}, [':'] ={47,0x0001},
['\'']={48,0x0000}, ['"'] ={48,0x0001},
['`'] ={49,0x0000}, ['~'] ={49,0x0001},
['?'] ={51,0x0000}, ['|'] ={51,0x0001},
['z'] ={52,0x0000}, ['Z'] ={52,0x0001},
['x'] ={53,0x0000}, ['X'] ={53,0x0001},
['c'] ={54,0x0000}, ['C'] ={54,0x0001},
['v'] ={55,0x0000}, ['V'] ={55,0x0001},
['b'] ={56,0x0000}, ['B'] ={56,0x0001},
['n'] ={57,0x0000}, ['N'] ={57,0x0001},
['m'] ={58,0x0000}, ['M'] ={58,0x0001},
[','] ={59,0x0000}, ['<'] ={59,0x0001},
['.'] ={60,0x0000}, ['>'] ={60,0x0001},
['/'] ={61,0x0000}, ['\\']={61,0x0001},
[' '] ={65,0x000},
};
И затем вы называете это так:
i64 bdim = 2;
char* data = "hi";
fori(i, 0,bdim){
x11_key_t key = X11_ASCII_TO_KEY[data[i]];
printf("%02x %04x\n", key.code, key.state);
}
Вы также можете реализовать это программно, используя вывод изxcb_get_keyboard_mapping_unchecked()
иxcb_get_modifier_mapping_unchecked()
.