在Linux上用C语言跟踪键盘和鼠标事件

4

我该如何在Linux中使用C语言追踪键盘或鼠标事件?

比如,如果用户按下了ESCShift等键,我需要跟踪它。同样的方法用于鼠标。如果用户移动鼠标或左右单击,我也应该能够跟踪到。

实现的想法是创建一个带有计时器的小屏幕保护程序,但我不知道如何追踪键盘或鼠标事件以重置计时器。

2个回答

3

有一种可能性是使用输入子系统。 请参阅此文章:使用输入子系统 (http://www.linuxjournal.com/article/6429)

另一种方法是创建一个工作线程,尝试读取文件/dev/input/event*,例如这里的键盘:

// (const char *)ptr - pass your device like "/dev/input/event2" here
fd = open((const char *)ptr, O_RDONLY);

if (fd < 0)
{
    fprintf(stderr, "failed to open input device %s: %s\n", (const char *)ptr, strerror(errno));
    return NULL;
}

struct timeval escapeDown = { 0, 0};
int code;
while (1)
{
    if (read(fd, &ev, sizeof(struct input_event)) < 0)
    {
        fprintf(stderr, "failed to read input event from input device %s: %s\n", (const char *)ptr, strerror(errno));
        if (errno == EINTR)
            continue;
        break;
    }

    code = -1;
    if (ev.type == EV_KEY)
    {
        switch (ev.code)
        {
        case eEsc:
            if (ev.value == 1)
            {
                escapeDown = ev.time;
                printf("DOWN: ESC\n");
            }
            else if (ev.value == 0 && escapeDown.tv_sec)
            {
                printf("UP:   ESC\n");
                if (isLongPressed(&escapeDown, &ev.time))
                    code = eEscLong;
                else
                    code = eEsc;

                escapeDown.tv_sec  = 0;
                escapeDown.tv_usec = 0;
            }
            break;
        case eOk:
        case eUp:
        case eRight:
        case eLeft:
        case eDown:
            if (ev.value == 0)
            {
                printf("UP:   %s\n", keyName(ev.code));
                code = ev.code;
            }
            else if (ev.value == 1)
            {
                printf("DOWN: %s\n", keyName(ev.code));
            }
            escapeDown.tv_sec  = 0;
            escapeDown.tv_usec = 0;
            break;
        default:
            break;
        }
    }
    if (code > 0)
    {
        struct sMsg* pMsg = malloc(sizeof(struct sMsg));
        if (pMsg)
        {
            pMsg->nMsgType = eMsgKeyLogger;
            pMsg->nIntValue= code;
            postMsg(pMsg);
        }
        printf("generated keyboard event: %u %s\n",
               code,
               keyName(code));
    }
    else
        usleep(100);
}

close(fd);

谢谢,这对我很有用。但是我该如何检查哪个文件是键盘的?因为对于鼠标,更改始终发生在 /dev/input/mouse0 或 /dev/input/mice 中,但如果对于键盘,每次更改键盘或重新启动机器时,更改都会发生在 /dev/input/event1 或 event4 等位置。所以一旦系统启动后,有没有办法找到仅负责键盘和鼠标的文件? - Naggappan Ramukannan
你可以尝试查找所有 /dev/input/event* 设备,或者查看 /var/log/Xorg.0.log 确定使用哪个设备作为你的键盘。 - Leo Chapiro
你可以查看 /dev/input/by-path/*。其中应该有一个文件名中包含 kbd。对于我来说,它是 /dev/input/by-path/platform-i8042-serio-0-event-kbd - user8110523

2
考虑到您的项目规模和性质,您可能想要看看GLUT。它实际上是OpenGL的一个方便库,并提供易于使用的跨平台输入处理和定时器功能。以防将来要移至其他平台。除此之外,它还能很好地融入您应用程序的图形特性中。 编辑:我提供的这个项目实际上是原始GLUT的继承者,具有整体增强的API。如需原始API参考,请查看此处
在您的情况下,您可以使用类似以下的东西:
void keyboardFunc(unsigned char key, int x, int y)
{
    switch (key)
    {
    case 'a':
        break;
    /* etc */
    }
}

void displayFunc()
{
    /* Statements issuing the drawing of your screensaver */
}

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

    /* Other initialization code */

    glutKeyboardFunc(keyboardFunc);
    glutDisplayFunc(displayFunc);

    glutMainLoop();
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接