1500字范文,内容丰富有趣,写作好帮手!
1500字范文 > Linux捕捉鼠标事件和键盘事件的方法

Linux捕捉鼠标事件和键盘事件的方法

时间:2021-07-16 07:32:07

相关推荐

Linux捕捉鼠标事件和键盘事件的方法

前段时间,工作中需要完成一个判断一段时间内是否人工操作操作的功能,基本思路就是要在后台监听键盘和鼠标的输入事件。那么如何能够捕捉鼠标和键盘的事件呢?下面分享我们的实现原来及方法。

捕捉设备输入事件的原理

打开/dev/input目录,执行ls命令,我们可以看到类似下面的文件列表。

$ ls -ltotal 0crw-r-----. 1 root root 13, 64 Jan 29 event0crw-r-----. 1 root root 13, 65 Jan 29 event1crw-r-----. 1 root root 13, 66 Jan 29 event2crw-r-----. 1 root root 13, 67 Jan 29 event3crw-r-----. 1 root root 13, 68 Jan 29 event4crw-r-----. 1 root root 13, 63 Jan 29 micecrw-r-----. 1 root root 13, 32 Jan 29 mouse0crw-r-----. 1 root root 13, 33 Jan 29 mouse1crw-r-----. 1 root root 13, 34 Jan 29 mouse2

熟悉Linux的朋友一定已经知道这里列出的文件是设备文件。在Linux环境中,/dev/input目录下的事件文件(event*)都是在驱动中调用input_register_device(struct input_dev *dev)产生的。每个event将上报指定的事件,如触摸、Mouse、按键等。读取这些事件文件将获取该事件文件对应设备的输入信息。

事件数据结构

在linux/input.h文件中定义了event事件的输入数据的结构体,该结构体定义如下:

struct input_event { struct timeval time; __u16 type; __u16 code; __s32 value;};

time, 指事件发生的时间,具体定义如下:

struct timeval{ __time_t tv_sec; /* Seconds. */ __suseconds_t tv_usec; /* Microseconds. */};

type,指事件类型,常见的事件类型有:EV_KEY,按键事件,键盘的按键,鼠标的左键右键等;EV_REL,相对坐标,主要用于鼠标的移动事件;EV_ABS,绝对坐标,主要用于触摸屏的移动事件。

code 事件代码,当事件类型为EV_KEY时,该代码为设备键盘代码,在input.h文件中以KEY_开头定义;value 事件的值,当事件类型代码是EV_KEY时,按键操作值为1,释放操作值为0,事件类型代码为EV_REL是,value为正数值和负数值分别代表连个不同方向的值。

如何确定那个事件文件对应哪个设备

/proc/bus/input/device文件中描述了与event对应的相关设备信息,例如如下信息:

$cat devicesI: Bus=0019 Vendor=0000 Product=0001 Version=0000N: Name="Power Button"P: Phys=LNXPWRBN/button/input0S: Sysfs=/devices/LNXSYSTM:00/LNXPWRBN:00/input/input0U: Uniq=H: Handlers=kbd event0B: EV=3B: KEY=10000000000000 0I: Bus=0017 Vendor=0001 Product=0001 Version=0100N: Name="Macintosh mouse button emulation"P: Phys=S: Sysfs=/devices/virtual/input/input1U: Uniq=H: Handlers=mouse0 event1B: EV=7B: KEY=70000 0 0 0 0B: REL=3I: Bus=0011 Vendor=0001 Product=0001 Version=ab41N: Name="AT Translated Set 2 keyboard"P: Phys=isa0060/serio0/input0S: Sysfs=/devices/platform/i8042/serio0/input/input2U: Uniq=H: Handlers=kbd event2B: EV=120013B: KEY=402000000 3803078f800d001 feffffdfffefffff fffffffffffffffeB: MSC=10B: LED=7I: Bus=0011 Vendor=0002 Product=0005 Version=0000N: Name="ImPS/2 Generic Wheel Mouse"P: Phys=isa0060/serio1/input0S: Sysfs=/devices/platform/i8042/serio1/input/input3U: Uniq=H: Handlers=mouse1 event3B: EV=7B: KEY=70000 0 0 0 0B: REL=103

在上面的H:中可以看到对应的eventxx。

捕捉键盘事件的实现方法

通过上节列出的文件,我们可以获得键盘对应的事件文件。通常键盘对应的事件文件为event2。监听这个文件,我们就能捕获到键盘的事件。以下代码是我实现的监听键盘事件的函数代码,20秒内没有键盘事件,程序退出:

#include <sys/types.h>#include <fcntl.h>#include <time.h>#include <stdio.h>#include <unistd.h>#include <linux/input.h>void listen_device(const char *dev, int timeout){ int retval; fd_set readfds; struct timeval tv; int fd = open(dev, O_RDONLY); struct input_event event; if (fd < 0) { perror(dev); return; } while (1) { FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = timeout; tv.tv_usec = 0; if((retval = select(fd+1, &readfds, NULL, NULL, &tv)) == 1) { if (read(fd, &event, sizeof(event)) == sizeof(event)) {if (event.type == EV_KEY){if (event.value == 0 || event.value == 1){ printf("key %d %s\n", event.code, event.value ? "Pressed" : "Released");}}else{printf("type=%x %d %d\n", event.type, event.code, event.value);} } } else { break; } } close(fd);}void listen_keyboard(int timeout){ listen_device("/dev/input/event2", timeout);}int main(int argc, char **argv){ listen_keyboard(20); printf("keyboard timeout\n"); return 0;}

捕捉鼠标事件的实现方法

我们也可以通过上面的方面获取鼠标的event文件,从而实现鼠标事件的捕获。但事实上鼠标有更方便的捕获方法,就是同目录下的mice文件,通过该文件可以获取解析后的鼠标事件。具体方法如下:(1)打开"/dev/input/mice"文件。(2)读3个字节。三个字节的值分别是“Button类型”,“X的相对位移”,“Y的相对位移”。这里先用Button, xRel, yRel表示。(3)取Button的低3位(Button & 0x07)。0x00 = LeftButtonUp, 0x01 = LeftButtonDown, 0x02 = RightButtonDown.

以下代码是我实现的监鼠标事件的函数代码:

#include <sys/types.h>#include <fcntl.h>#include <time.h>#include <stdio.h>#include <unistd.h>#include <linux/input.h>void listen_mice(const char *dev, int timeout){ char buf[256]; int n_len; int retval; fd_set readfds; struct timeval tv; int fd = open(dev, O_RDONLY); if (fd < 0) { perror(dev); return; } while (1) { FD_ZERO(&readfds); FD_SET(fd, &readfds); tv.tv_sec = timeout; tv.tv_usec = 0; if((retval = select(fd+1, &readfds, NULL, NULL, &tv)) == 1) { if ((n_len = read(fd, buf, sizeof(buf))) > 0) {if (n_len == 3){printf("Button: %d, xRef=%d, yRef=%d\n", buf[0]&0x07, buf[1], buf[2]);} } } else { break; } } close(fd);}void listen_mouse(int timeout){ listen_mice("/dev/input/mice", timeout);}int main(int argc, char **argv){ listen_mouse (20); printf("mouse timeout\n"); return 0;}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。