gpt4 book ai didi

c - Linux C-keyMapping keyCodes

转载 作者:太空宇宙 更新时间:2023-11-04 08:18:14 25 4
gpt4 key购买 nike

我目前正在为Linux(在Raspberry Pi硬件下)开发GUI,并且我对键盘有一个(很基本的)问题。
我可以通过使用input/eventX文件来处理keypressed,keyreleased ...,但是我得到的唯一是keyCode(显然)。

我想知道如何映射这些keyCode以从中获取字符?

最佳答案

此映射由控制台控制台的内核完成(请参阅dumpkeys或运行sudo dumpkeys -l以查看当前控制台映射),并由X服务器针对X服务器应用程序(使用xmodmap -pm -pk查看映射;第一列没有任何修饰符,第二列)单独使用第一个修饰符,第三列使用第二个修饰符,第四列使用两个第一个修饰符,第五列使用第三个修饰符,依此类推。通常,键盘映射文件在man 5 keymaps中描述。

您的问题是,如何自己进行映射。

首先,您需要了解映射的工作方式。在Linux输入子系统中,有9个修饰符,即逻辑状态,可以组合以产生29 = 512个不同的修饰符状态中的任何一个。它们具有完全任意的名称,与任何特定密钥本身无关,均为而不是。 (它们是Shift(20 = 1),AltGr(21 = 2),Control(22 = 4),Alt(23 = 8),ShiftL(24 = 16),ShiftR(25 = 32),CtrlL(26 = 64) ),CtrlR(27 = 128)和CapsShift(28 = 256)。将“ Activity ”项相加,以获得实际的修改器状态。)

假设您使用int描述每个键盘结果;对于Unicode代码点(字符)为正,对于自定义操作键(如“向上光标”,“向下翻页”等)为负。然后,可以使用以下最小示例来描述每个键的映射:

struct mod_one {
__u16 down; /* State change when pressed */
__u16 up; /* State change when released */
};

struct key_one {
size_t count; /* Number of states for this keycode */
unsigned short *state; /* Array of states */
int *result; /* Array of keyboard_event() return values */
};

struct key_map {
/* Modifier keys */
size_t mod_count;
__u16 *mod_code;
struct mod_one *mod_xor;

/* Non-modifier keys */
size_t key_count;
__u16 *key_code;
struct key_one *key_map;
};

int keyboard_event(const struct input_event *const ev, unsigned short *const state, const struct key_map *const map)
{
/* Note: Uses linear search for simplicity.
* In practice, you want the arrays to be sorted,
* and use a binary search instead.
*/

/* Sanity check for NULL pointers. */
if (!ev || !state || !map)
return 0;

if (ev->type == EV_KEY) {
size_t i, k;

/* Is it a modifier key? */
for (i = 0; i < map->mod_count; i++)
if (ev->code == map->mod_code[i]) {
/* Yes. Apply the state change. */
if (ev->code == 0)
*state ^= map->mod_xor[i].down;
else
if (ev->code == 1)
*state ^= map->mod_xor[i].up;
break;
}

/* Does this event map to a keypress?
* We rely on kernel/device autorepeat. */
if (ev->code == 0 || ev->code == 2)
for (i = 0; i < map->key_count; i++)
if (ev->key == map->key_code[i]) {
for (k = 0; k < map->key_map[i].count; k++)
if (*state == map->key_map[i].state[k])
return map->key_map[i].result[k];
}
}

return 0;
}

请注意,以上内容实际上是绝对最小值,未经测试。

它不支持Uncaps_Shift(在不按Caps Lock键的情况下释放Capslock),并且从键盘映射文件定义 struct key_map有点繁琐。但是,希望您可以看到逻辑(也许可以通过简单的 struct key_map尝试一下,并观察 *state的更改和返回值)。在实际程序中,我想我将分别处理shift/capslock状态,并为每个修饰键使用单个掩码(按下时为或键状态,释放时为nand(而非键),带有shift和caps锁定状态互为异或,因此,如果修改器状态因某种原因感到困惑,那么多次敲击这些键将始终可以修复状态。

就个人而言,我建议(应用户要求)使用Unicode,而不要使用ASCII或Windows-1252或ISO-8859-x。将Unicode代码转换为普通的UTF-8字符串并检查它们需要多少 char是很简单的。但是,如果在编辑过程中使用Unicode字符串,则编辑字符串(尤其是将光标移至字符串中以及删除单个字符)会更加容易。 (我更喜欢将UTF-8用于“不可变的”字符串,但是在编辑小部件时,为了简单起见,将它们转换为 wchar_t或类似的代码。UTF-8⇔UCS4转换很简单。)

(以防万一,您还可以在大多数欧洲键盘上将€用作AltGr + E。它是Unicode U + 20AC或代码8364,在UTF-8中由三个字符 \xE2\x82\xAC表示。如果您不能支持它,不要指望欧洲人使用您的UI。而且,不,ISO-8859-15也不会真正削减它,即使它确实有€。)

最后,对于您的UI,我建议您在程序中使用单个专用的pthread来读取输入事件设备(所有键盘,鼠标和指针),并将按键(以及指针更改的通知)提供给循环缓冲区,使用原子计数器和信号量,或互斥体和条件变量来维护线程之间的缓冲区状态。专用线程只需要一个最小的堆栈(即16384或32768字节就足够了),并且由于它在大多数时间都阻止等待新事件,因此根本不会占用太多资源。

使专用线程同时维护键盘和指针输入设备(并移动指针或对输入缓冲区执行“字符”操作)意味着您的程序可以使用简单的循环来检查用户输入。每当用户按下一个键或移动一个指针时,循环就会迭代。您不需要轮询。它对于简单的基于帧缓冲区的图形界面非常有效。

关于c - Linux C-keyMapping keyCodes,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34582279/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com