我想加入 linux 桌面键事件处理。
按 CapsLock 应该会进入某种命令行。
我要实现的一些命令:
- d/x: 从当前光标位置删除直到字符
x
。 (灵感来自 vi) - a: 转到行首,如 pos1。 (灵感来自 emacs)。
- k:删除直到行尾。 (灵感来自 emacs)。
- ...
这些命令应该适用于任何文本字段:浏览器、邮件客户端、gnome 终端......
AFAIK 低级 xmodmap 在这里帮不了我。
这样的事情可能吗?
我需要把 Hook 放在哪里?
当前目标平台是 Ubuntu >= 14.04
背景:我想 Handlebars 指放在 F 和 J 上,不看键盘就可以使用计算机。多年来一直为 A-Z 工作,但 Pos1/End 等键不容易访问。
如果您不理解此问题的一部分,请发表评论。谢谢。
更新
这个问题只是关于如何hook到按键事件处理上。其他东西(命令行)是一个不同的话题。例如,您如何捕捉 CapsLock x
?
更新2 我发现没有简单直接的解决方案。如果您没有答案,但您知道在哪里可以找到更多帮助(例如在邮件列表 FOO 上提问),请告诉我。
更新3 由于有些人不明白我想要什么,我试着解释一下:如果我使用emacs或bash,我感觉就像在控制计算机:它就像飞翔,只需很少的 Action 我就可以告诉计算机做什么我想。在网络浏览器文本区域、LibreOffice 或使用 thunderbird 中编辑文本会让这种感觉消失。光标移动比较笨重,没有飞起来的感觉。我想控制桌面,而不仅仅是单个应用程序,并将我的手指放在 F 和 J 键上。
更新 4:解决方案:输入重映射器
我找到了一个很好的解决方案:input-remapper .看我的小文章Ten Flying Fingers (more comfortable touch typing)
最佳答案
更新
您可以使用 EVIOCGRAB
ioctl,而不是告诉 X 服务器忽略该设备,我将其添加到下面的程序中。
您需要做以下事情:
1.确保您已编译并加载 CONFIG_UINPUT 模块。我相信 Ubuntu 已经有了它。如果您没有看到 /dev/uinput
设备,请尝试运行 modprobe -v uinput
来加载模块。
2.以root身份运行以下程序并为其提供键盘设备的路径,例如:
./process/dev/input/by-id/usb-Microsoft_Wired_Keyboard_600-event-kbd
以下程序创建了一个名为 uinput-sample
的假输入设备,并将给定输入设备的所有事件转发给它。我根据 http://thiemonge.org/getting-started-with-uinput 中给出的示例改编了它
你可以修改它来做你想做的事情。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <linux/uinput.h>
#define die(str, args...) do { \
perror(str); \
exit(EXIT_FAILURE); \
} while(0)
int
main(int argc, char* argv[])
{
int fdo, fdi;
struct uinput_user_dev uidev;
struct input_event ev;
int i;
if(argc != 2) die("error: specify input device");
fdo = open("/dev/uinput", O_WRONLY | O_NONBLOCK);
if(fdo < 0) die("error: open");
fdi = open(argv[1], O_RDONLY);
if(fdi < 0) die("error: open");
if(ioctl(fdi, EVIOCGRAB, 1) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_SYN) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_KEY) < 0) die("error: ioctl");
if(ioctl(fdo, UI_SET_EVBIT, EV_MSC) < 0) die("error: ioctl");
for(i = 0; i < KEY_MAX; ++i)
if(ioctl(fdo, UI_SET_KEYBIT, i) < 0) die("error: ioctl");
memset(&uidev, 0, sizeof(uidev));
snprintf(uidev.name, UINPUT_MAX_NAME_SIZE, "uinput-sample");
uidev.id.bustype = BUS_USB;
uidev.id.vendor = 0x1;
uidev.id.product = 0x1;
uidev.id.version = 1;
if(write(fdo, &uidev, sizeof(uidev)) < 0) die("error: write");
if(ioctl(fdo, UI_DEV_CREATE) < 0) die("error: ioctl");
while(1)
{
if(read(fdi, &ev, sizeof(struct input_event)) < 0)
die("error: read");
ev.time.tv_sec = 0;
ev.time.tv_usec = 0;
if(write(fdo, &ev, sizeof(struct input_event)) < 0)
die("error: write");
}
if(ioctl(fdo, UI_DEV_DESTROY) < 0) die("error: ioctl");
close(fdi);
close(fdo);
return 0;
}
关于linux - Hook 到 linux 键事件处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27581500/