目标:
/*
* 通过操作鼠标设备文件,监听当前鼠标左键双击事件
* 以及长按左键进行区域选择的事件。
*
* 通过键盘设备文件event3进行模拟键盘操作
*
* 当检测到双击或者区域选择操作,在操作结束后,
* 模拟键盘发送CTRL-C
* */
设计思路:
一:鼠标事件检测:
1.只读方式打开鼠标设备文件/dev/input/mice
2.按照协议定义的数据格式,从设备文件读出3个字节的数据存于buf[3]。
buf[0]低3位依次为左键,右键以及中键,按下鼠标的对应键其buf[0]对应位被置1,为了提取出低三位的对应值,作逻辑与操作:&0x7即可。
- buf[0] & 0x07得出鼠标键值,1为左键,2为右键,4为中键
- buf[1] 为 x坐标偏移值
- buf[2] 为y坐标偏移值
3.将获得的鼠标键值存于一个历史数组history[4],且为循环覆盖存入
4.通过判断history[4]数据格式,推断当前鼠标事件
二:模拟键盘操作
1.以读写方式打开键盘设备文件 /dev/input/event3, 不一定是event3,如果使用的是xorg,可以通过以下命令查看键盘对应的设备文件是哪一个:
1 2 3 |
cat /var/log/Xorg.1.log | grep keyboard | awk '{print $4}' | tail -n 1 |
2.通过向键盘设备文件按一定方式写入一定格式的数据模拟键盘操作
三:代码示例
命名:DetectMouse.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
/* 本程序功能: * * 通过操作鼠标设备文件,监听当前鼠标左键双击事件 * 以及长按左键进行区域选择的事件。 * * 通过键盘设备文件event3进行模拟键盘操作 * * 当检测到双击或者区域选择操作,在操作结束后, * 模拟键盘发送CTRL-C * */ #include <string.h> #include <stdlib.h> #include <sys/stat.h> #include <stdio.h> #include <signal.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <linux/input.h> #include <linux/uinput.h> #include <stdio.h> #include <sys/time.h> #include <sys/types.h> #include <unistd.h> /*获取当前数组下标的前一个下标值, *数组元素为4*/ int previous( int n ) { if ( n != 0 ) return n - 1; else return 3; } /*退出前加个回车*/ void quit() { printf("\n"); exit(0); } /*同步键盘*/ void sync_key( int *fd, struct input_event *event, int *len) { event->type = EV_SYN; event->code = SYN_REPORT; event->value = 0; write(*fd, event, *len); } /*发送按键keyCode*/ void press(int fd, int keyCode) { struct input_event event; //发送 event.type = EV_KEY; event.value = 1; event.code = keyCode; gettimeofday(&event.time,0); write(fd,&event,sizeof(event)) ; //同步 int len = (int)sizeof(event); sync_key(&fd, &event, &len); } /*释放按键*/ void release(int fd, int keyCode) { struct input_event event; //释放 event.type = EV_KEY; event.code = keyCode; event.value = 0; gettimeofday(&event.time, NULL); write(fd, &event, sizeof(event)); //同步 int len = (int)sizeof(event); sync_key(&fd, &event, &len); } int main(int argc,char **argv) { int fd, retval, fd_key=0; char buf[3]; fd_set readfds; struct timeval tv; // 打开鼠标设备 fd = open("/dev/input/mice", O_RDONLY ); if ( fd < 0 ) { fprintf(stderr, "Failed to open mice"); exit(1); } else { fprintf(stdout, "Open mice successful\n"); } int history[10]; int i = 0; int n = 0; int m = 0; int j = 0; int q = 0; /*捕捉Ctrl-c退出信号*/ signal(SIGINT, quit); while(1) { // 设置最长等待时间 tv.tv_sec = 5; tv.tv_usec = 0; FD_ZERO( &readfds ); FD_SET( fd, &readfds ); retval = select( fd+1, &readfds, NULL, NULL, &tv ); if(retval==0) { printf( "Time out!\n" ); } if(FD_ISSET(fd,&readfds)) { // 读取鼠标设备中的数据 if(read(fd, buf, 3) <= 0) { continue; } /*循环写入鼠标数据到数组*/ history[i++] = buf[0] & 0x07; if ( i == 4 ) i = 0; /*m为最后得到的鼠标键值*/ m = previous(i); n = previous(m); j = previous(n); q = previous(j); printf("%d - %d - %d - %d\n", history[m],history[n],history[j],history[q]); /* 0 1 表示按下鼠标左键, 则0101表示双击,这里不考虑间隔过久的双击事件, * 0 1 1 1 表示左键一直处于按下状态,进行区域选择,最后释放鼠标左键, * 则最后的值会变成0, 因为所有值都是在4个数组空间里循环,而m表示的是 * 最后一个的值,所以是0111. * * 这里的逻辑是如果检测到鼠标双击或者区域选择事件,则发送ctlr-c进行 * 复制操作.如果是在终端,则发送的ctrl-c将使程序停止运行. * */ if ( ( history[m] == 0 && history[n] == 1 && history[j] == 0 && history[q] == 1 ) || ( history[m] == 0 && history[n] == 1 && history[j] == 1 && history[q] == 1 ) ) { if ( fd_key <= 0 ) fd_key = open("/dev/input/event3", O_RDWR); if(fd_key < 0) { fprintf(stderr, "Open keyboard device failed\n"); exit(1); } //发送CTRL-C press(fd_key, KEY_LEFTCTRL); press(fd_key, KEY_C); release(fd_key, KEY_C); release(fd_key, KEY_LEFTCTRL); } } } close(fd); return 0; } |
编译运行:
1 2 3 4 |
gcc DetectMouse.c -o DetectMouse ./DetectMouse |
程序现象,如果是在终端进行双击或按住左键选择区域,程序停止运行,如果是在其他窗口,选中的文字将被复制到剪贴板。