linux - 了解Linux上从hid usage id到gdk keyval的方法

标签 linux hid gdk

我想了解从键盘的 hid usage id 通过系统到 GDK keyval 包含布局转换的方式。或者更具体地说:我有一个 UTF-8 字符串,不想创建外部设备必须播放才能获得相同结果的隐藏键列表。

到目前为止我尝试了什么:

(没有 shift/alt 处理的精简版)

#include <glib.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>

static GdkKeymapKey *get_key_with_group_0(GdkKeymapKey *keys, gint n_keys) {
gint i;

for (i = 0; i < n_keys; ++i)
    if (keys[i].group == 0)
        return &keys[i];

/* fallback: return first element */
g_warning("can't find keycode for group 0");
return keys;
}

static guint keycode_to_keyval(guint keycode) {
GdkKeymap *keymap;
GdkKeymapKey key = {keycode, 0, 0};
guint keyval;

keymap = gdk_keymap_get_default();
keyval = gdk_keymap_lookup_key(keymap, &key);
if (keyval == 0)
    g_warning("keycode %i has no keyval!\n", keycode);
return keyval;
}

/* Hid usage tables v1.12 chapter 10 and /usr/include/gtk-2.0/gdk/gdkkeysyms.h */
/* stores keyvals without modifiers */
static guint const table_hid_usage_id_to_keyval[232] = {
/*   0       1       2       3       4       5       6       7       8       9       A       B       C       D       E       F */
0x0000, 0x0000, 0x0000, 0x0000, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, /* 0 */
0x006d, 0x006e, 0x006f, 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x0031, 0x0032, /* 1 */
0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x0030, 0xff0d, 0xff1b, 0xff08, 0xff09, 0x0020, 0x00df, 0x00b4, 0x00fc, /* 2 */
0x002b, 0x005c, 0x0023, 0x00f6, 0x00e4, 0x005e, 0x002c, 0x002e, 0x002d, 0xffe5, 0xffbe, 0xffbf, 0xffc0, 0xffc1, 0xffc2, 0xffc3, /* 3 */
0xffc4, 0xffc5, 0xffc6, 0xffc7, 0xffc8, 0xffc9, 0x0000, 0xff14, 0xff13, 0xff63, 0xff50, 0xff55, 0xffff, 0xff57, 0xff56, 0xff53, /* 4 */
0xff51, 0xff54, 0xff52, 0xff7f, 0xffaf, 0xffaa, 0xffad, 0xffab, 0xff8d, 0xff9c, 0xff99, 0xff9b, 0xff96, 0xff9d, 0xff98, 0xff95, /* 5 */
0xff97, 0xff9a, 0xff9e, 0xff9f, 0x003c, 0xff67, 0x0000, 0x0000, 0xffca, 0xffcb, 0xffcc, 0xffcd, 0xffce, 0xffcf, 0xffd0, 0xffd1, /* 6 */
0xffd2, 0xffd3, 0xffd4, 0xffd5, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 7 */
0x0000, 0x0000, 0xffe5, 0x0000, 0xff14, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 8 */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 9 */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* A */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xff89, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* B */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xff80, 0x0000, 0x0000, /* C */
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0xffae, 0x0000, 0x0000, 0x0000, /* D */
0xffe3, 0xffe1, 0xffe9, 0xffeb, 0xffe4, 0xffe2, 0xffea, 0xff67 /* E */
};

// Needs keyval without modifications
static guint8 keyval_to_hid(guint keyval) {
guint i;
for (i = 0; i < 232; ++i) {
    if (table_hid_usage_id_to_keyval[i] == keyval)
        return i;
}
return 0;
}

static void do_it(gchar const *text) {
gchar const *iter;
guint keyval;
gunichar character;
GdkKeymapKey *keys;
GdkKeymapKey *key;
gint n_keys;
GdkKeymap *keymap;

iter = text;

keymap = gdk_keymap_get_default();

while(TRUE) {
    character = g_utf8_get_char_validated(iter, -1);
    if (character == 0)
        break;

    keyval = gdk_unicode_to_keyval(character);

            /* get keyval without modifications */
    if (!gdk_keymap_get_entries_for_keyval(keymap, keyval, &keys, &n_keys)) {
        g_warning("keyval 0x%04x has no keycode!", keyval);
        iter = g_utf8_find_next_char(iter, NULL);
        break;
    }
    key = get_key_with_group_0(keys, n_keys);
    keyval = keycode_to_keyval(key->keycode);

    g_print("0x%04x\n", keyval_to_hid(keyval));

    g_free(keys);

    iter = g_utf8_find_next_char(iter, NULL);
}
}

int main(int argc, char **argv) {
g_type_init();
gtk_init(&argc, &argv);

do_it("Testing z");

return 0;
}

我的问题:

键盘布局转换在哪里以及如何完成? 在我的德语键盘上,我得到了这个:

  1. 按下“z”按钮
  2. 设备发送 HID 使用 id 0x1c(y 和 Y)
  3. xev 表示键码 29;键符 0x7a; “z”

这个翻译是在哪里完成的,我该如何返回?

最佳答案

回答我自己的问题:

GTK 返回的键码是 X 使用的键码,与键映射无关。 通过静态查找将 xkeycode 转换为 keyval 并返回 hid usage id 是错误的,因为 keyval 依赖于键映射。

可以使用静态表 [1] 将 xkeycode 传输回内核 keycode。内核键码到隐藏使用 id 的进一步转换也是使用静态表 [2] 完成的。

[1] http://lists.x.org/archives/xorg/2006-June/015633.html

[2] https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/drivers/hid/hid-input.c?id=refs/tags/v3.9

关于linux - 了解Linux上从hid usage id到gdk keyval的方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14527037/

相关文章:

c - 以编程方式或来自 procfs 的 netstat 进程名称信息

linux - Linux下如何写入CM108芯片的GPIO管脚?

android - 如何在 Android 上使用 UsbDeviceConnection 从 HID 设备请求 USB HID 报告描述符

c - 多线程、gtk3 和 cairo : drawing in a cairo surface

python - 在 Python 中使用 gtk.gdk 获取事件根窗口

linux - bash 函数未能给出返回值

安卓 fanotify_init : Function not implemented

linux - 有没有人能够创建 PE COFF 和 ELF 的混合体?

macos - 在 Mac OS X 中禁用鼠标加速

c - GDK 线程不允许 gtk 更改(制作计时器)