Преобразовать символ 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().

Другие вопросы по тегам