我有一个小程序,它以 ascii 字符的形式输入。我需要能够将这些转换为用于 x11 功能的键码。是否有执行此操作的 xlib 函数或其他库?还是大型开关盒效果最好?
2 回答
这个问题有一个古老的错误答案(来自@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 (Control-A)XK_A
带有XK_CONTROL_R
(or XK_CONTROL_L
) 修饰符。所以你必须发出例如:XK_CONTROL_L
DOWN,XK_A
DOWN,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 受到损害。
您可以使用XStringToKeysym
至少将字母数字字符转换为KeySym
s,然后使用XKeysymToKeycode
for 转换为KeyCode
s:
Display *display = ...;
KeySym sym_a = XStringToKeysym("A");
KeyCode code_a = XKeysymToKeycode(display, sym_a);
正如@BobDoolitle 在他的回答中指出的那样,虽然XStringToKeysym
适用于字母数字单字符串,但它在 ASCII 一般情况下会失败。他提供了一种简单处理大多数 ASCII 字符 ( 0x20
- 0x7F
) 的方法,尽管超出该范围的字符需要更仔细的处理。