钩入linux关键事件处理

我想挂钩到Linux桌面的关键事件处理。

按CapsLock应该进入某种命令行。

我想要实现的一些命令:

  • d / x:从当前光标位置删除,直到字符x 。 (由vi启发)
  • a:转到行首,如pos1。 (受emacs启发)。
  • k:删除直到行尾。 (受emacs启发)。

该命令应该在任何文本字段中工作:浏览器,邮件客户端,GNOMEterminal,…

AFAIK低级别的xmodmap在这里不会帮助我。

是这样的可能吗?

我需要在哪里放置钩子?

目前的目标平台是Ubuntu> = 14.04

背景:我想让我的手指指向F和J,并且不用看着键盘就可以使用电脑。 AZ工作几年以来,但像Pos1 / End这样的键并不容易访问。

如果你不明白这个问题的一部分,请留下评论。 谢谢。

更新

这个问题只是关于如何挂钩到关键事件处理。 其他的东西(命令行)是一个不同的主题。 你怎么能抓住例如CapsLock x

Update2我看到有没有简单而直接的解决scheme。 如果你没有答案,但你知道我可以find更多的帮助(如邮件列表FOO问),请告诉我。

Update3因为有些人不明白我想要什么,所以我试着解释一下:如果我使用emacs或bash,我觉得在计算机上可以控制:就像飞行一样,只有很less的动作,我可以告诉计算机做我想要的是。 在webbrowser textarea,LibreOffice或使用thunderbird编辑文本使这种感觉消失。 光标移动很麻烦,感觉不像飞行。 我想要控制桌面,而不仅仅是一个应用程序,并保持我的指针在F和J键。

Solutions Collecting From Web of "钩入linux关键事件处理"

UPDATE

不要告诉X服务器忽略设备,你可以使用EVIOCGRAB ioctl,我将它添加到下面的程序中。

你需要做以下的事情:

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; } 

蛮力的方式将是modyfy /重建xserver-xorg-input-evdev包并替换/usr/lib/xorg/modules/input/evdev_drv.so 。 我首先尝试修改EvdevQueueKbdEvent() xf86-input-evdev-2.9.0/src/evdev.c EvdevQueueKbdEvent()函数。 看起来不是很优雅的解决方案,但我认为你会灵活地修改键盘事件队列。

使用XGRabKey() ( 这里有一些细节)和/或XGrabKeyboard()可能会使用较少侵入性的解决方案。

一些信息,这可能对此有帮助(关于XTest扩展)。

看看你的问题的另一种方法:你想要一些专门的窗口管理器 。 有关详细信息,请阅读EWMH规范。 在阅读X11的概述之前阅读。

或考虑一些现有的X窗口管理器 。 其中有很多。 我怀疑是否可以配置鼠标或xmonad (或者锯齿等)来满足您的需求。 (但我不太了解这些WM)。

在从零开始实施窗口管理器之前请仔细考虑。 这可能意味着多年的工作! AFAIU,WM可以重定向,过滤,抓取或合成键盘或鼠标事件。

当然,有了路径,情况会不一样。

这里也是一个使用uinput驱动的python项目:

http://hetgrotebos.org/wiki/uinput-mapper