挂钩到 linux 关键事件处理 [英] hook into linux key event handling

查看:19
本文介绍了挂钩到 linux 关键事件处理的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想挂钩到 linux 桌面按键事件处理.

I want to hook into linux desktop key event handling.

按下 CapsLock 应该会进入某种命令行.

Pressing CapsLock should enter some sort of command line.

我想实现的一些命令:

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

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

The commands should work in any text field: Browser, Mail Client, gnome terminal, ...

AFAIK 低级 xmodmap 在这里帮不了我.

AFAIK low level xmodmap won't help me here.

这样的事情可能吗?

我需要把钩子放在哪里?

Where do I need to place the hook?

当前目标平台是 Ubuntu >= 14.04

Current target platform is Ubuntu >= 14.04

背景:我想把手指放在F和J上,不用看键盘就可以使用电脑.多年来一直适用于 A-Z,但像 Pos1/End 这样的键并不容易访问.

Background: I want to keep my pointing fingers on F and J, and use the computer without looking at the keyboard. Works for A-Z since several years, but keys like Pos1/End are not easy to access.

如果您不理解此问题的一部分,请发表评论.谢谢.

Please leave a comment if you don't understand a part of this question. Thank you.

更新

这个问题只是关于如何挂钩关键事件处理.其他东西(命令行)是一个不同的主题.例如,您如何捕获 CapsLock x?

This question is only about how to hook into the key event handling. The other stuff (command line) is a different topic. How can you catch for example CapsLock x?

更新2我看到没有简单直接的解决方案.如果你没有答案,但你知道我可以在哪里找到更多帮助(比如在邮件列表 FOO 上提问),请告诉我.

Update2 I see there is no easy and straight forward solution. If you have no answer, but you know where I can find more help (like ask on mailing list FOO), please tell me.

更新3由于有些人不明白我想要什么,所以我尝试解释一下:如果我使用 emacs 或 bash,我感觉就像在控制计算机:就像飞行一样,只有很少的动作我可以告诉计算机做什么我想.在 webbrowser textarea、LibreOffice 或使用 Thunderbird 中编辑文本会让这种感觉消失.光标移动很麻烦,感觉不像在飞.我想控制桌面,而不仅仅是单个应用程序,并且将手指放在 F 和 J 键上.

Update3 Since some people do not understand what I want, I try to explain it: If I use emacs or bash I feel like being in control if the computer: it is like flying, with only very few movements I can tell the computer to do what I want. Editing text in webbrowser textarea, LibreOffice or using thunderbird makes this feeling go away. Cursor movements are cumbersome, it does not feel like flying. I want to control the desktop, not just a single application, and keep my pointing fingers on the F and J keys.

推荐答案

更新

您可以使用 EVIOCGRAB ioctl,而不是告诉 X 服务器忽略设备,我在下面的程序中添加了它.

Instead of telling the X server to ignore the device, you can use EVIOCGRAB ioctl, which I added to the program below.

你需要做以下事情:

1.确保您已编译并加载了 CONFIG_UINPUT 模块.我相信 Ubuntu 已经有了它.如果您没有看到 /dev/uinput 设备,请尝试运行 modprobe -v uinput 来加载模块.

1.Make sure you have CONFIG_UINPUT module compiled and loaded. I believe Ubuntu already has it. If you don't see /dev/uinput device, try running modprobe -v uinput to load the module.

2.以root身份运行以下程序,并给它键盘设备的路径,例如:

2.Run the following program as root and give it the path of the keyboard device, eg:

./process/dev/input/by-id/usb-Microsoft_Wired_Keyboard_600-event-kbd

以下程序创建一个名为 uinput-sample 的假输入设备,并将所有事件从给定输入设备转发到它.我根据 http://thiemonge.org/getting-started-with-uinput 中给出的示例对其进行了改编

The following program creates a fake input device called uinput-sample and forwards all events from a given input device to it. I adapted it from the sample given in http://thiemonge.org/getting-started-with-uinput

你可以修改它来做你想做的事情.

You can modify it to do things you want to do.

#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 关键事件处理的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆