Convert ASCII character to x11 keycode

青春壹個敷衍的年華 提交于 2019-11-29 10:47:23

You can use XStringToKeysym to convert to KeySym, followed by XKeysymToKeycode for conversion to KeyCode.

Display *display = ...;
KeySym sym_a = XStringToKeysym("A");
KeyCode code_a = XKeysymToKeycode(display, sym_a);

This question has an old, wrong answer (from @oldrinb), that oddly has never been challenged. As stated in the comment, you can't use XStringToKeysym to map chars to KeySyms in a general way. It will work for letters and numbers, but that's about it, because the KeySym name happens to map directly for those ASCII characters. For other ASCII characters such as punctuation or space it won't work.

But you can do better than that. If you look at <X11/keysymdef.h> you find that for ASCII 0x20-0xFF, the characters map directly to XKeySyms. So, I'd say it's simpler to just use that range of characters directly as KeySyms, and just map the remaining 32 characters to their corresponding KeyCodes. So I'd say the code should more properly be:

Display *display = ...;
if ((int)c >= 0x20) {
    XKeysymToKeycode(display, (KeySym)c);
} else {
    ... // Exercise left to the reader :-)
}

The 'else' clause will require multiple KeyCodes since for example ASCII 1 (Control-A) is XK_A with the XK_CONTROL_R (or XK_CONTROL_L) Modifier. So you'd have to issue for example: XK_CONTROL_L DOWN, XK_A DOWN, XK_A UP, XK_CONTROL_L UP.

Here's a toy program that demonstrates this by echoing the first argument via simulated keyboard events:

#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);
}

You need to link it with: -lX11 -lxcb -lxcb-xtest -lX11-xcb

Disclaimer: No KeySyms were harmed in the writing of this code.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!