[Linux] C获取键盘,鼠标数据

发布于:2023-08-24 ⋅ 阅读:(80) ⋅ 点赞:(0)

键盘检测指令:cat /dev/input/event1 | hexdump

鼠标检测指令:cat /dev/input/event2 | hexdump

当键盘/鼠标有输入时,会有对应的一堆16进制输出。它其实对应着input_event结构体【24字节】。

struct input_event 
{
      struct timeval time;
      __u16 type;
      __u16 code;
      __s32 value;
};
//==================获取键盘数据====================
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <linux/input.h>
#include <string.h>
 
int main(void)
{
    #define KEY_PATH	"/dev/input/event1"
	int fd = -1, ret = -1;
	struct input_event ev;
	// 第1步:打开设备文件
	fd = open(KEY_PATH, O_RDONLY);
	if (fd < 0)
	{
		perror("open,error");
		return -1;
	}
    printf("welcome size=%d.\n",sizeof(struct input_event));
	
	while (1)
	{
		// 第2步:读取event事件包
		memset(&ev, 0, sizeof(struct input_event));
		ret = read(fd, &ev, sizeof(struct input_event));
		if (ret != sizeof(struct input_event))
		{
			perror("read,error");
			close(fd);
			return -1;
		}
		
		// 第3步:解析event包.
        printf("========================================================\n");
		printf("[%11u] type: %3d, code: %3d, value: %3d \n",ev.time.tv_sec,ev.type,ev.code,ev.value);
        //type: 1:按键同步
        //code: 键码['a'=30]
        //value:0:按键释放,1:按键按下,2:长按下
	}
 
	// 第4步:关闭设备
	close(fd);	
	return 0;
}

//=======获取鼠标数据=========
#include <X11/Xlib.h>
//LDFLAGS := -lX11
int GetDisplayInfo(int *screen_width,int *screen_height)
{
    Display *display = XOpenDisplay(NULL);
    if (display == NULL)
    {
        printf("Error: cannot open display\n");
        return 1;
    }
    int screen_num = DefaultScreen(display);
    Screen *screen = ScreenOfDisplay(display, screen_num);
    *screen_width = WidthOfScreen(screen);
    *screen_height = HeightOfScreen(screen);
    printf("Screen size: %dx%d pixels\n", WidthOfScreen(screen), HeightOfScreen(screen));
    printf("Screen resolution: %dx%d dpi\n", (int) (WidthOfScreen(screen) * 25.4 / DisplayWidthMM(display, screen_num)), 
                                             (int) (HeightOfScreen(screen) * 25.4 / DisplayHeightMM(display, screen_num)));
    XCloseDisplay(display);
    
    return 0;
}

int get_xy(int fd,struct input_event ts,int *x,int *y)
{
    static int nCnt = 0;
	read(fd,&ts,sizeof(ts));
	if(ts.type == EV_ABS && ts.code == ABS_X)
	{
		*x = ts.value;
        nCnt = (nCnt+1)%3;
		return nCnt;
	}
	if(ts.type == EV_ABS && ts.code == ABS_Y)
	{
		*y = ts.value;
        nCnt = (nCnt+1)%3;
		return nCnt;
	}
	
	return 0;
}


int main(void)
{
   #define MOUSE_PATH	"/dev/input/event2"
	int fd = -1, ret = -1;
	struct input_event ev;
    int data_size = sizeof(struct input_event);

	// 第1步:打开设备文件[需要权限运行]
	fd = open(MOUSE_PATH, O_RDONLY);
	if (fd < 0)
	{
		perror("open,error");
		return -1;
	}
    printf("mouse test [%s],data size=%d.\n",MOUSE_PATH,sizeof(struct input_event));
	
    int screen_width = 0;
    int screen_height = 0;
    if( GetDisplayInfo(&screen_width,&screen_height)>0)
    {
        perror("get display info,error");
        return -2;
    }

	while (1)
	{

       static int raw_x=0;
       static int raw_y=0;
        int tmp =0;

		tmp = get_xy(fd,ev,&raw_x,&raw_y);
        if(tmp==2)
        {
            int curr_x = 0;
            int curr_y = 0;
            curr_x = raw_x*screen_width/0xFFFF;
            curr_y = raw_y*screen_height/0xFFFF;
            printf("mousePos: x=%d,y=%d.\n",curr_x,curr_y);
        }
	}
	close(fd);	
	return 0;
}

方法2:采用SDL2 [simplle directmedia layer]  , 此方法用于GUI项目,事件只针对SDL创建的窗口内有效

#include <stdio.h>
#include <pthread.h>
#include <SDL2/SDL.h>

int main(void *arg)
{
   // 窗口大小
    int screen_w = 800;
    int screen_h = 400;
    // 初始化SDL
    if (SDL_Init(SDL_INIT_EVERYTHING))
    {
        printf("could not initialize SDL: %s\n", SDL_GetError());
        return -1;
    }
  
    SDL_Window *screen = SDL_CreateWindow("SimpleSDL2", 0, 0, screen_w, screen_h, SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);
    if (!screen)
    {
        printf("could not create window: %s\n", SDL_GetError());
        return -1;
    }

    SDL_Event myEvent; // SDL事件
    int quit = 0;
    while (!quit) // 建立事件主循环
    {
        // 注意:事件只针对SDL创建的窗口内有效
        while (SDL_PollEvent(&myEvent)) // 从队列里取出事件
        {
            // printf("event=%d  \n", myEvent.type);
            switch (myEvent.type) // 根据事件类型分门别类去处理
            {
            case SDL_QUIT: // 离开事件[点击窗口关闭]
                quit = 1;  // quit event poll
                break;

            case SDL_MOUSEMOTION: // 鼠标移动
                printf("mouseXY: %d,%d \n", myEvent.motion.x, myEvent.motion.y);
                break;

            case SDL_MOUSEBUTTONDOWN:                             // 鼠标点击
                printf("ButtonClck:%d\n", myEvent.button.button); //0:左键,1:中键,2:右键
                break;

            case SDL_KEYDOWN://键盘按下
                // 键值表在SDL2/SDL_keycode.h文件中定义
                printf("KEY_DOWN:%d\n", myEvent.key.keysym.sym);
                break;

            case SDL_KEYUP://键盘释放
                // 键值表在SDL2/SDL_keycode.h文件中定义
                printf("KEY_UP:%d\n", myEvent.key.keysym.sym);
                break;
            }
        }
    }
    printf("quit screen_monitor_thread.! \n");
    exit(0);
    return 0;
}

 


网站公告

今日签到

点亮在社区的每一天
去签到