XTest:XTestFakeKeyEvent 根据单布局或多布局表现不同

XTest: XTestFakeKeyEvent behaves differently based on single or multilayout

我有一个关于 XTestFakeKeyEvent 的小问题 我已经编写了这个示例程序来演示这个问题:

#include <stdio.h>
#include <stdlib.h>
#include <X11/X.h>
#include <X11/XKBlib.h>
#include <X11/extensions/XTest.h>
#include <unistd.h>

int main(int argc, const char * argv[]) {
    Display * display;

    //Try to attach to the default X11 display.
    display = XOpenDisplay(NULL);
    if(display == NULL) {
        printf("Error: Could not open display!\n");
        return EXIT_FAILURE;
    }

    KeyCode inject = 29; // Should be XKB_KEY_Y

    sleep(10);

    XTestFakeKeyEvent(display, inject, True, 0);
    XTestFakeKeyEvent(display, inject, False, 0);
    XFlush(display);

    return 0;
}

编译:gcc -o xkb_test xkb_test.c -lX11 -lXtst

此程序的作用:它连接到 X11 服务器,等待 10 秒,然后在键盘上注入键码 29,对应于美式键盘上的 y 键。

现在的问题是:我有一个德语键盘布局(例如,与美国相比,z 和 y 被切换)并且该程序将基于此注入 yz条件:

A z 当我在 MATE 中配置多个布局时被注入(所以我在状态栏中有这个布局切换小程序) 当我在 MATE

中只配置了一个布局时,注入了一个 y

为什么这会有所不同?我怎样才能激发一致的行为?

XTestFakeKeyEvent 接受键码。键码对应于物理键,而不是映射到它们的字符。如果你想发送一个字符,你需要弄清楚它映射到当前布局中的哪个键。

在现代系统中,您可能会使用 Xkb,并且 Xkb 布局称为组。你可以用XkbGetState获取XkbStateRec中的当前组,然后一个一个翻译有效的keycode,直到你得到你需要的keysym。

用 Xkb 翻译键码可能有点令人生畏,而且我不知道有什么简单的防弹方法。 This SO answer 有一个工作程序,它唯一缺少的是组(它使用 group = 0,你需要用 state.group 替换它,其中 state 是你从 XkbGetState).

请注意,最终将发送的符号取决于当前的移位和大写锁定状态。如果您需要特定的字符大小写,则必须在注入键码之前修改键盘状态。