Linux字符终端如何用鼠标移动一个红色矩形详解
发表于:2024-10-16 作者:千家信息网编辑
千家信息网最后更新 2024年10月16日,一切皆文件! UNIX已经说了。埃里克雷蒙德这样说的,不服吗?既然 /dev/fb0 被抽象成了显示器,可以在字符终端通过操作映射了 /dev/fb0 的内存在屏幕上画32bit真彩图,那么如何操作鼠
千家信息网最后更新 2024年10月16日Linux字符终端如何用鼠标移动一个红色矩形详解
一切皆文件! UNIX已经说了。埃里克雷蒙德这样说的,不服吗?
既然 /dev/fb0 被抽象成了显示器,可以在字符终端通过操作映射了 /dev/fb0 的内存在屏幕上画32bit真彩图,那么如何操作鼠标键盘呢?
/dev/input/mouse0 可以用来读取鼠标事件。当你在字符终端cat它并移动鼠标时,它貌似告诉你有事情发生了,但是你却无法解读:
为了找到解读它的正确方法,要么谷歌,要么百度,要么还有一个最直接的方法,那就是查Linux内核源码中关于mouse0这个文件的read回调函数:
static ssize_t mousedev_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos){ struct mousedev_client *client = file->private_data; struct mousedev *mousedev = client->mousedev; // mousedev_client结构体里查找到ps2的大小是6个字节。 signed char data[sizeof(client->ps2)]; int retval = 0; spin_lock_irq(&client->packet_lock); if (!client->buffer && client->ready) { // 这里就是核心了,继续跟过去 mousedev_packet(client, client->ps2); client->buffer = client->bufsiz; } ...
我们看看 mousedev_packet 是如何组装包的:
static void mousedev_packet(struct mousedev_client *client, signed char *ps2_data){ struct mousedev_motion *p = &client->packets[client->tail]; ps2_data[0] = 0x08 | ((p->dx < 0) << 4) | ((p->dy < 0) << 5) | (p->buttons & 0x07); ps2_data[1] = mousedev_limit_delta(p->dx, 127); ps2_data[2] = mousedev_limit_delta(p->dy, 127); p->dx -= ps2_data[1]; p->dy -= ps2_data[2];...
非常明白,我不管别的,我也没有动机去学,我现在就是想知道鼠标的X,Y坐标:
- p->dx,p->dy从名字上和从代码上都可以看出,这是 相对于上一次 的坐标的变化!
所有信息都有了。
那么,现在,可以写代码了:
#include#include #include #include #include // 正方形边长为100个像素点#define LENGTH 100// 显示器显存的抽象unsigned int *mem = NULL;// 保存上一次的屏幕unsigned int *old_mem = NULL;// 屏幕信息static struct fb_var_screeninfo info;int mouse_fd, fb_fd;// 正方形涂成红色int start = 0xffff0000;int main(int argc, char **argv){ signed char mouse_event[6]; char rel_x, rel_y; int old_x = 0, old_y = 0; int abs_x = 0, abs_y = 0; mouse_fd = open("/dev/input/mouse0", O_RDONLY); fb_fd = open("/dev/fb0", O_RDWR); ioctl(fb_fd, FBIOGET_VSCREENINFO, &info); mem = (unsigned int *)mmap(NULL, info.xres*info.yres*info.bits_per_pixel/8, PROT_READ|PROT_WRITE, MAP_SHARED, fb_fd, 0); while(read(mouse_fd, &mouse_event[0], 6)) { int i, w, h; static int idx = 0; // 按照内核mousedev_packet的定义,解析出相对位移。 rel_x = (char) mouse_event[1]; rel_y = (char) mouse_event[2]; // 计算绝对位移 abs_x += rel_x; abs_y -= rel_y; if (abs_x <= 0 || abs_x >= info.xres - LENGTH || abs_y <= 0 || abs_y >= info.yres - LENGTH) { continue; } if (old_mem == NULL) { old_mem = (unsigned int *)mmap(NULL, info.xres*info.yres*info.bits_per_pixel/8, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, -1, 0); if (old_mem == NULL) { exit(1); } } else { // 恢复上一次正方形区域里的像素 for (w = old_x; w < old_x + LENGTH; w++) { for (h = old_y; h < old_y + LENGTH; h++) { idx = h*info.xres + w; mem[idx] = old_mem[idx]; } } old_x = abs_x; old_y = abs_y; } // 保存当前的像素,以便下一次恢复 for (w = abs_x; w < abs_x + LENGTH; w++) { for (h = abs_y; h < abs_y + LENGTH; h++) { idx = h*info.xres + w; old_mem[idx] = mem[idx]; } } // 根据鼠标的位置涂抹红色矩形 for (w = abs_x; w < abs_x + LENGTH; w++) { for (h = abs_y; h < abs_y + LENGTH; h++) { idx = h*info.xres + w; mem[idx] = start; } } } return 0;}
运行它,然后在字符终端移动鼠标,效果如下:
嗯,矩形随着鼠标而移动,并且不会破坏任何所到之处的字符。
现在,我来回顾一下这个周末做的这些事情,意味着什么。
- 我可以在字符终端上画32位真彩图;
- 我可以检测到鼠标键盘的事件并且反应。
这意味着,如果有时间和精力,我可以实现一个GUI系统了。
当然,GUI系统和网络协议栈那是隔行如隔山,肯定会遇到超级多的麻烦,不是仅仅读写两个文件:
- /dev/fb0
- /dev/input/mouse0
就可以搞定的。
事实上,真正的GUI系统从来不用这种方式。它们貌似在反抗着 UNIX一切皆文件 的理念,并且证明这样会更好!哦,对了,Windows GUI的成功就是一个证明,还有后来最新版本的MacOS…
说什么字符终端,字符也是 画出来的 。没什么大不了的。只不过,想要用像素去设置字符,那就要了解一下 字符点阵 的information了…这又是另一个领域的话题。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,谢谢大家对的支持。
字符
鼠标
终端
就是
像素
文件
移动
屏幕
正方
正方形
系统
要么
上一
矩形
红色
事件
代码
信息
内容
内核
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
网络安全产业爆炸增长
密码数据库查询系统
网络安全股的市盈率平均估值
上海工业网络技术欢迎选购
oracle数据库 面试
数据库技术解析
软件开发工程师等级划分
为什么要开发国产数据库
vfp属于什么型数据库
北京攀克网络技术有限公司
泉州市易宝软件开发
小学网络安全答题
网络技术应用试题答案及解析
深圳市网络安全预案
用数据库登陆
冗余备份软件开发
北京军地联合网络技术有限公司
wdcp怎么导入数据库
关于数据库技术的描述错误
网络安全模式音频
中国运营商的网络技术手段
浏览的数据怎么存入数据库
网络安全股的市盈率平均估值
北京飞马互联网科技有限公司
数据库不能全部打开
二手车数据库管理系统开源
运营商的网络安全解决方案
gps卫星时钟服务器
浙江网络技术转让包括什么
orcl数据库提示path