Linux下鼠标和键盘的模拟控制,也就是为手势和语音控制鼠标和键盘部分服务的。

有关于本系统构建的文章结构都会由三个部分来组织,一是该功能模块的介绍和在Linux下简单应用程序的实现;二是将该功能模块整合到交互系统(先以TLD为地基)中去;三是分析目前存在的问题与未来的解决构思。

一、input子系统和模拟程序编写:

Linux 输入子系统是 Linux内核用于管理各种输入设备(键盘,鼠标,遥控杆,书写板等等)的。输入子系统分为三块: input core, drivers和 event handlers。正常的路径是从底层硬件到驱动,从驱动到input core,从 input core到 event handler,从 event handler到 user space。

这么说吧:如果是没有这个input子系统的话,假如我们用键盘按下了一个键A,键盘会有一个linux的设备驱动文件,假设是/dev/keyboard,我们的用户空间的应用程序就会打开并访问这个设备文件/dev/keyboard,应用程序会轮询这个文件,一旦你按下了一个键A了,它就会返回给用户程序说你按下了键A。那么如果有了input子系统的话,我们的用户空间的应用程序就不是直接打开和访问键盘的设备驱动文件了,而是访问由键盘驱动在input子系统中注册的event事件文件,例如/dev/input/event3,而对于键盘驱动来说,它也是实现由input子系统提供的接口就可以了。按下键了,就发送给input子系统。不再直接与用户空间的应用程序直接面对面了。这样,就很方便的对驱动和应用程序都统一了接口,而且同一种接口还适合管理多种硬件。好像很简单的问题给我啰嗦化了,不知道有没有说错,呵呵。

这个input子系统可以很容易地让我们在用户空间模拟鼠标和键盘事件。例如,你可以写一个应用程序,往input子系统的/dev/input/event3设备文件(假设这个是键盘设备文件)写入A,这样就相当于你通过键盘按下了A,而这个A对系统任意的一个当前活动窗口有效(捕捉)。

要实现这个功能,我们需要回答一下几个问题:

1、往什么设备文件写?

也就是如何查看哪些设备文件是键盘的,哪些是鼠标的,找到这些设备文件,我们才可以通过应用程序来打开和写入键值(或者鼠标的控制信息)。

通过 #cat /proc/bus/input/devices可以查看到当前input子系统下面的所有event设备,我们找到鼠标和键盘的即可。

例如:

I: Bus=0003 Vendor=046d Product=c018 Version=0111

N: Name=" USB Optical Mouse"

P: Phys=usb-0000:00:1d.1-2/input0

S: Sysfs=/class/input/input24

U: Uniq=

H: Handlers=mouse1 event2

B: EV=7

B: KEY=70000 0 0 0 0 0 0 0 0

B: REL=103

上面Name处可以看到这个鼠标设备,然后对应的句柄Handlers是event2;

2、怎么写入:

大家都知道,Linux下万物皆文件,所以对于文件操作我们只需要:open()和write()就可以了。

3、要写入什么东西(键值的编码):

在/usr/include/linux/input.h中有定义,这个文件定义了event事件的结构体,API和标准按键的编码等;我们需要将要写入的按键编码填充到结构体中,然后写入键盘或者鼠标的事件设备驱动文件中。

输入事件的结构体:

struct input_event {

struct timeval time;  //按键时间

__u16 type;  //事件的类型

__u16 code;  //要模拟成什么按键

__s32 value;  //是按下1还是释放0

};

标准按键的编码:(只列举部分)

type:

事件的类型:

EV_KEY, 按键事件,如键盘的按键(按下哪个键),鼠标的左键右键(是非击下)等;

EV_REL, 相对坐标,主要是指鼠标的移动事件(相对位移);

EV_ABS, 绝对坐标,主要指触摸屏的移动事件,但好像这个不能用在鼠标上面,也就是说无法通过这个来获取鼠标的绝对坐标(鼠标是一个相对位移的设备)。

code:

事件的代码:

如果事件的类型代码是EV_KEY,该代码code为设备键盘代码。代码植0~127为键盘上的按键代码,0x110~0x116为鼠标上按键代码,其中0x110(BTN_ LEFT)为鼠标左键,0x111(BTN_RIGHT)为鼠标右键,0x112(BTN_ MIDDLE)为鼠标中键。其它代码含义请参看include/linux /input.h文件。该文件中会定义相应的宏来代表不同的按键。

如果事件的类型代码是EV_REL,code值表示轨迹的类型。如指示鼠标的X轴方向 REL_X(代码为0x00),指示鼠标的Y轴方向REL_Y,指示鼠标中轮子方向REL_WHEEL。

value:

事件的值:

如果事件的类型代码是EV_KEY,当按键按下时值为1,松开时值为0;

如果事件的类型代码是EV_ REL,value的正数值和负数值分别代表两个不同方向的值。例如:如果code是REL_X,value是10的话,就表示鼠标相对于上一次的坐标,往x轴向右移动10个像素点。

在Linux下写的简单的模拟鼠标和键盘事件的程序:

#include <stdio.h>

#include <linux/input.h>

#include <fcntl.h>

#include <sys/time.h>

#include <unistd.h>

//按键模拟,按键包含按下和松开两个环节

void simulate_key(int fd, int kval)

{

struct input_event event;

gettimeofday(&event.time, 0);

//按下kval键

event.type = EV_KEY;

event.value = 1;

event.code = kval;

write(fd, &event, sizeof(event));

//同步,也就是把它报告给系统

event.type = EV_SYN;

event.value = 0;

event.code = SYN_REPORT;

write(fd, &event, sizeof(event));

memset(&event, 0, sizeof(event));

gettimeofday(&event.time, 0);

//松开kval键

event.type = EV_KEY;

event.value = 0;

event.code = kval;

write(fd, &event, sizeof(event));

//同步,也就是把它报告给系统

event.type = EV_SYN;

event.value = 0;

event.code = SYN_REPORT;

write(fd, &event, sizeof(event));

}

//鼠标移动模拟

void simulate_mouse(int fd, int rel_x, int rel_y)

{

struct input_event event;

gettimeofday(&event.time, 0);

//x轴坐标的相对位移

event.type = EV_REL;

event.value = rel_x;

event.code = REL_X;

write(fd, &event, sizeof(event));

//y轴坐标的相对位移

event.type = EV_REL;

event.value = rel_y;

event.code = REL_Y;

write(fd, &event, sizeof(event));

//同步

event.type = EV_SYN;

event.value = 0;

event.code = SYN_REPORT;

write(fd, &event, sizeof(event));

}

int main(int argc, char **argv)

{

int fd_mouse = -1;

int fd_kbd = -1;

int i = 0;

fd_kbd = open("/dev/input/event3", O_RDWR);

if(fd_kbd <= 0)

{

printf("Can not open keyboard input file\n");

return -1;

}

fd_mouse = open("/dev/input/event2", O_RDWR);

if(fd_mouse <= 0)

{

printf("Can not open mouse input file\n");

return -1;

}

for (i = 0; i < 50; i++)

{

simulate_key(fd_mouse, BTN_LEFT);  //模拟按下鼠标左键

//if (i % 3 == 0)

//      simulate_key(fd_kbd, KEY_A);  //模拟按下键盘A键

//模拟鼠标相对上次x和y轴相应移动10个像素

//simulate_mouse(fd_mouse, 10, 10);

sleep(3);

}

close(fd_kbd);

close(fd_mouse);

}

那么如何模拟组合键呢?其实和大家平时按键盘的过程是一样的,我们用程序按照这个过程来模拟就可以了。以CTRL + SPACE为例:

//先发送一个 CTRL按下去的事件

//再发送一个 SPACE按下去的事件

//然后发送一个释放 SPACE的事件

//再发送一个释放 CTRL的事件

得注意每步的发送都需要同步一次。

linux 处理键盘 鼠标事件的更多相关文章

  1. Android查询:模拟键盘鼠标事件(adb shell 实现)

    1. 发送键盘事件: 命令格式1:adb shell input keyevent “value” 其中value以及对应的key code如下表所列: KeyEvent Value KEYCODE ...

  2. 【pyHook】 监测键盘鼠标事件等

    [pyHook] pyHook是一个用来进行键盘.鼠标等层面事件监控的库.这个库的正常工作需要pythoncom等操作系统的API的支持.首先来说说如何安装. 直接pip install pyHook ...

  3. soeasy的键盘鼠标事件

    在web自动化中,我们可能会遇到需要通过键盘或者鼠标去操作某些元素,那么我们就需要用到键盘事件和鼠标事件了,今天对键盘和鼠标操作进行一个总结 鼠标事件 鼠标事件需要引入ActionChains类,查看 ...

  4. 【JS】键盘鼠标事件

    一,键盘 keydown 表示按下键盘 keypress 表示按下键盘 keyup 表示键盘弹起 这三者的区别分别表现在发生的 先后顺序,获取到的键盘按钮值,已经对输入框的文本取值这三方面 先后顺序: ...

  5. (转)C#模拟键盘鼠标事件

    原文 1.模拟键盘事件System.Windows.Forms.SendKeys以下是   SendKeys   的一些特殊键代码表.     键   代码       BACKSPACE   {BA ...

  6. C#模拟键盘鼠标事件 SendKeys 的特殊键代码表(转)

    使用 SendKeys 将键击和组合键击发送到活动应用程序.此类无法实例化.若要发送一个键击给某个类并立即继续程序流,请使用 Send.若要等待键击启动的任何进程,请使用 SendWait. 每个键都 ...

  7. winform中键盘和鼠标事件的捕捉和重写(转)

    在 编写winform应用程序时,有时需要无论在哪个控件获取焦点时,对某一个键盘输入或者鼠标事件都进行同样的操作.比如编写一个处理图片的应用程序时, 希望无论当前哪个控件获得焦点,当用户按上.下.左. ...

  8. Selenium2+python自动化12-操作元素(键盘和鼠标事件)

    前言 在前面的几篇中重点介绍了一些元素的到位方法,到位到元素后,接下来就是需要操作元素了.本篇总结了web页面常用的一些操作元素方法,可以统称为行为事件 有些web界面的选项菜单需要鼠标悬停在某个元素 ...

  9. lufylegend库 鼠标事件 循环事件 键盘事件

    lufylegend库 鼠标事件 循环事件 键盘事件 <!DOCTYPE html> <html lang="en"> <head> <m ...

随机推荐

  1. list容器详解

    首先说说STL ( STL的目的是标准化组件,这样就不用重新开发,可以使用现成的组件.STL现在是C++的一部分,因此不用额外安装什么.它被内建在你的编译器之内.因为STL的list是一个简单的容器, ...

  2. 【交叉染色法判断二分图】Claw Decomposition UVA - 11396

    题目链接:https://cn.vjudge.net/contest/209473#problem/C 先谈一下二分图相关: 一个图是二分图的充分必要条件: 该图对应无向图的所有回路必定是偶环(构成该 ...

  3. 工具栏(UIToolbar)

    工具栏一般用来显示弹出框,以至于UIPopoverController类包含方法presentPopoverFromBarButtonItem:permittedArrowDirections:ani ...

  4. 【BZOJ 3136】 3136: [Baltic2013]brunhilda (数论?)

    3136: [Baltic2013]brunhilda Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 238  Solved: 73[Submit][ ...

  5. POJ 3764 The xor-longest Path trie树解决位运算贪心

    http://poj.org/problem?id=3764 题意 :  一颗树,每个边有个值,在树上找一条简单路径,使得这条路径上的边权异或值最大 先找到所有节点到一点的距离 , 显然dis( x ...

  6. Linux的十个最危险的命令

    Linux命令行佷有用.很高效,也很有趣,但有时候也很危险,尤其是在你不确定你自己在正在做什么时候. 这篇文章将会向你介绍十条命令,但你最好不要尝试着去使用. 当然,以下命令通常都是在root权限下才 ...

  7. 更换mac电脑后证书过期的解决办法

    http://stackoverflow.com/questions/32821189/xcode-7-error-missing-ios-distribution-signing-identity- ...

  8. [CodeForces-440D]Berland Federalization

    题目大意: 给你一棵树,你可以删掉一些边,使得分除去的子树中至少有一棵大小为k. 问最少删去多少边,以及删边的具体方案. 思路: 树形DP. f[i][j]表示以i为根,子树中去掉j个点最少要删边的数 ...

  9. Google图片和NASA 网站图片的爬虫

    1.根据关键字爬取NASA网站上的图片 首先针对需要爬取的网站进行分析,输入关键字查找需要的内容 通过关键字请求,网页每次会加载20张的缩略图,分析网页源码能够很容易的找到缩略图的url: 然后再点开 ...

  10. 使用牛顿迭代法和二分法求解一个数的平方根(python语言实现)

    #牛顿迭代法 def sqrt1(x): y = 1.0 while abs(y * y - x) > 1e-6: y = (y + x/y)/2 return y #使用二分法 def sqr ...