Linux 虚拟鼠标,键盘 之一。

Linux 有自己的 input 子系统,可以统一管理鼠标和键盘事件。
基于输入子系统 实现的 uinput 可以方便的在用户空间模拟鼠标和键盘事件。
当然,也可以自己造轮子, 做一个字符设备接收用户输入,根据输入,投递 input 事件。
还有一种方式就是直接 往 evnent 里写入数据, 都可以达到控制鼠标键盘的功能。

本篇文章就是演示直接写入 event 的方法。
linux/input.h中有定义,这个文件还定义了标准按键的编码等

struct input_event {
    struct timeval time;  //按键时间
    __u16 type; //类型,在下面有定义
    __u16 code; //要模拟成什么按键
    __s32 value;//是按下还是释放
};

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(代码为0x01),指示鼠标中轮子方向REL_WHEEL(代码为0x08).

type:
EV_KEY,键盘
EV_REL,相对坐标
EV_ABS,绝对坐标

value:
事件的值.如果事件的类型代码是EV_KEY,当按键按下时值为1,松开时值为0;如果事件的类型代码是EV_ REL,value的正数值和负数值分别代表两个不同方向的值.
/*
 * Event types
 */

#define EV_SYN            0x00
#define EV_KEY            0x01 //按键
#define EV_REL            0x02 //相对坐标(轨迹球)
#define EV_ABS            0x03 //绝对坐标
#define EV_MSC            0x04 //其他
#define EV_SW            0x05
#define EV_LED            0x11 //LED
#define EV_SND            0x12//声音
#define EV_REP            0x14//repeat
#define EV_FF            0x15
#define EV_PWR            0x16
#define EV_FF_STATUS        0x17
#define EV_MAX            0x1f
#define EV_CNT            (EV_MAX+1)

下面是一个模拟鼠标和键盘输入的例子:

#include <string.h>
#include <stdio.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>

void simulate_key(int fd,int kval)
{
    struct input_event event;
    event.type = EV_KEY;
    event.value = 1;
    event.code = kval;

    gettimeofday(&event.time,0);
    write(fd,&event,sizeof(event)) ;

        event.type = EV_SYN;
        event.code = SYN_REPORT;
        event.value = 0;
        write(fd, &event, sizeof(event));
  
        memset(&event, 0, sizeof(event));
        gettimeofday(&event.time, NULL);
        event.type = EV_KEY;
        event.code = kval;
        event.value = 0;
        write(fd, &event, sizeof(event));
        event.type = EV_SYN;
        event.code = SYN_REPORT;
        event.value = 0;
        write(fd, &event, sizeof(event));

}

void simulate_mouse(int fd)
{
    struct input_event event;
        memset(&event, 0, sizeof(event));
        gettimeofday(&event.time, NULL);
        event.type = EV_REL;
        event.code = REL_X;
        event.value = 10;
        write(fd, &event, sizeof(event));

        event.type = EV_REL;
        event.code = REL_Y;
        event.value = 10;
        write(fd, &event, sizeof(event));

        event.type = EV_SYN;
        event.code = SYN_REPORT;
        event.value = 0;
        write(fd, &event, sizeof(event));
}

int main()
{
    int fd_kbd;
    int fd_mouse;
    fd_kbd = open("/dev/input/event1",O_RDWR);
    if(fd_kbd<=0){
        printf("error open keyboard:/n");
        return -1;

    }

    fd_mouse = open("/dev/input/event2",O_RDWR);
    if(fd_mouse<=0){
        printf("error open mouse/n");
        return -2;
    }

    int i = 0;
    for(i=0; i< 10; i++)
    {
        simulate_key(fd_kbd, KEY_A + i);
        simulate_mouse(fd_mouse);
        sleep(1);
    }

    close(fd_kbd);
}
模拟了鼠标和键盘的输入事件。
关于这里 open 哪个 event , 可以通过 cat /proc/bus/input/devices
I: Bus=0017 Vendor=0001 Product=0001 Version=0100
N: Name="Macintosh mouse button emulation"
P: Phys=
S: Sysfs=/class/input/input0
U: Uniq=
H: Handlers=mouse0 event0
B: EV=7
B: KEY=70000 0 0 0 0 0 0 0 0
B: REL=3

I: Bus=0011 Vendor=0001 Product=0001 Version=ab41
N: Name="AT Translated Set 2 keyboard"
P: Phys=isa0060/serio0/input0
S: Sysfs=/class/input/input1
U: Uniq=
H: Handlers=kbd event1
B: EV=120013
B: KEY=4 2000000 3803078 f800d001 feffffdf ffefffff ffffffff fffffffe
B: MSC=10
B: LED=7

I: Bus=0019 Vendor=0000 Product=0002 Version=0000
N: Name="Power Button (FF)"
P: Phys=LNXPWRBN/button/input0
S: Sysfs=/class/input/input3
U: Uniq=
H: Handlers=kbd event3
B: EV=3
B: KEY=100000 0 0 0

I: Bus=0019 Vendor=0000 Product=0001 Version=0000
N: Name="Power Button (CM)"
P: Phys=PNP0C0C/button/input0
S: Sysfs=/class/input/input4
U: Uniq=
H: Handlers=kbd event4
B: EV=3
B: KEY=100000 0 0 0

I: Bus=0003 Vendor=046d Product=c018 Version=0111
N: Name="Logitech 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

我的鼠标是 罗技 的 Logitech USB Optical Mouse, 所以 鼠标是 event2
下面是一个读取 鼠标和键盘事件的例子:
#include <stdio.h>
#include <stdlib.h>
#include <linux/input.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

static void show_event(struct input_event* event)
{
        printf("%d %d %d/n", event->type, event->code, event->value);

        return;
}

int main(int argc, char* argv[])
{
        struct input_event event = {{0}, 0};
        const char* file_name = argc == 2 ? argv[1] : "/dev/input/event2";

        int fd = open(file_name, O_RDWR);


        if(fd > 0)
        {

                while(1)
                {
                        int ret = read(fd, &event, sizeof(event));
                        if(ret == sizeof(event))
                        {
                                show_event(&event);
                        }
                        else
                        {
                                break;
                        }
                }
                close(fd);
        }

        return 0;
}

很多人对于 如何模拟 CTRL + SPACE 感兴趣, 下面也给个例子,呵呵。
void simulate_ctrl_space(int fd)
{
        struct input_event event;

     //先发送一个 CTRL 按下去的事件。
        event.type = EV_KEY;
        event.value = 1;
        event.code = KEY_LEFTCTRL;
        gettimeofday(&event.time,0);
        write(fd,&event,sizeof(event)) ;

        event.type = EV_SYN;
        event.code = SYN_REPORT;
        event.value = 0;
        write(fd, &event, sizeof(event));

     //先发送一个 SPACE 按下去的事件。
        event.type = EV_KEY;
        event.value = 1;
        event.code = KEY_SPACE;
        gettimeofday(&event.time,0);
        write(fd,&event,sizeof(event)) ;

     //发送一个 释放 SPACE 的事件
        memset(&event, 0, sizeof(event));
        gettimeofday(&event.time, NULL);
        event.type = EV_KEY;
        event.code = KEY_SPACE;
        event.value = 0;
        write(fd, &event, sizeof(event));

        event.type = EV_SYN;
        event.code = SYN_REPORT;
        event.value = 0;
        write(fd, &event, sizeof(event));


     //发送一个 释放 CTRL 的事件
        memset(&event, 0, sizeof(event));
        gettimeofday(&event.time, NULL);
        event.type = EV_KEY;
        event.code = KEY_LEFTCTRL;
        event.value = 0;
        write(fd, &event, sizeof(event));


        event.type = EV_SYN;
        event.code = SYN_REPORT;
        event.value = 0;
        write(fd, &event, sizeof(event));

}



接下来分析一下 uinput 和 linux 的 input 子系统。

  • 0
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Linux下的PyQt虚拟键盘是一种软件工具,它允许用户在没有物理键盘的设备上模拟键盘输入。 PyQt是一个基于Python语言的图形用户界面(GUI)开发工具包,它提供了多种功能和工具,可以用于开发各种类型的程序,包括虚拟键盘虚拟键盘在一些特定场景下非常有用。比如在一些设备上,由于空间限制或其他原因无法使用物理键盘,这时通过软件实现一个虚拟键盘可以提供方便的用户输入操作。 在Linux系统中,我们可以使用PyQt来开发一个虚拟键盘应用程序。这个应用程序可以使用PyQt提供的图形界面组件来创建一个界面,其中包括模拟的按键按钮。当用户点击这些按钮时,相应的键盘输入就会被模拟发送到系统。 实现虚拟键盘的关键是需要处理按键事件。在PyQt中,我们可以使用事件处理机制来监听按钮的点击事件,并在事件发生时执行相应的操作。通过一些特定的函数和方法,我们可以将模拟的键盘输入发送给系统,从而实现虚拟键盘的功能。 总结来说,Linux下的PyQt虚拟键盘是一种通过软件实现的工具,它可以模拟物理键盘的输入功能。我们可以利用PyQt提供的功能和组件来创建一个界面,并通过事件处理机制来实现按钮点击事件的监听和键盘输入的模拟发送。这样,用户就可以在没有物理键盘的设备上进行方便的输入操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值