Linux字符终端如何用鼠标移动一个红色矩形详解
发表于:2025-12-01 作者:千家信息网编辑
千家信息网最后更新 2025年12月01日,一切皆文件! UNIX已经说了。埃里克雷蒙德这样说的,不服吗?既然 /dev/fb0 被抽象成了显示器,可以在字符终端通过操作映射了 /dev/fb0 的内存在屏幕上画32bit真彩图,那么如何操作鼠
千家信息网最后更新 2025年12月01日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安全错误
数据库的锁怎样保障安全
我的网络安全观
区块链网络安全基金
征婚软件开发
江苏省青少年网络安全知识竞赛题
软件开发者协会翻译
服务器实训心得
2台服务器的集群搭建
重庆涪陵蔬菜配送软件开发
吴忠网络技术调试
6.数据库对象命名规范
数据库文件导出后缀名
面对网络安全我应该如何去做
医学与网络技术的结合
生活中的网络技术有哪些
不思议迷宫游戏无法连接服务器
计算机云服务器怎么管理
主机跟服务器的区别
深度学习云服务器
上海c语言软件开发价格表
网络安全等级保护测评报价
免费软件开发服务好吗
汽车电子平台软件开发
北京市公安局网络安全性
软件开发与层次化思维方式
武汉招商帮网络技术有限公司
有死亡原因的数据库
面对更为严峻的网络安全威胁
世界级网络安全公司
手机斗牛游戏软件开发
服务器与操作系统间的区别