X window system介绍
X window system采用C/S架构(Client/Server,主从式架构),分为X服务器(X Server)和X客户端(X Client)。
(1)X Server 管理主机上与显示相关的硬件设置(如显卡、硬盘、鼠标等),它负责屏幕画面的绘制与显示,以及将输入设置(如键盘、鼠标)的动作告知 X Client 。
(2)X Client负责事件处理(程序逻辑的处理)。
简单例子:鼠标点击后画三角形
X Server将鼠标点击的事件发送给X Client ,X Clinet 处理好的逻辑(就是告知X Server如何去画三角形)发送给X Server ,X Server根据从X Client得到的信息进行图形绘制。
X Server负责管理硬件,而X Client负责将X Server传来的输入设备行为产生数据并将数据回传给Server,X Server根据回传的数据将它显示在自己的屏幕上。X Client也称之为X App。并且可以有多个X Client,他们相互之间是各自独立的,因此在显示时可能会产生重叠。X Client不需要知道X Server的硬件配置与操作系统,只要遵循网络协议。
X Window Manager介绍
它是一种特殊的X Client,负责管理所有的X Client。上面提到的多个X Client在显示时可能会产生重叠,因此需要一个管理它们的工具,也就是X Window Manager了。负责管理桌面,窗口大小,重叠,窗口移动等参数。Linux下常见的有:GNOME、KDE、TWM、XFCE、MATE等桌面管理器。
X Server和X Client之间通信介绍
X Server和X Client之间的通信方式主要是通过X协议,X协议是一种图形用户界面(GUI)通信协议,用于在计算机之间传递图形用户界面信息。
(1)X协议的原理是客户端和服务器之间通过网络进行通信,客户端和服务器之间交换一系列的命令和响应,以实现各种操作,例如创建窗口、移动窗口、关闭窗口等。
(2)X协议是基于请求-响应模式进行通信的,客户端向服务器发送请求,服务器收到请求后进行处理,然后向客户端发送响应。客户端和服务器之间的通信是异步的,客户端不需要等待服务器处理请求的响应。
(3)X协议的实现是基于Unix的socket通信方式,客户端和服务器之间通过建立一个socket连接来进行通信。客户端和服务器之间交换一系列的命令和响应,以实现各种操作。
X Server和X Client之间的通信过程
(1) X Server启动,监听来自客户端的连接请求。
(2)X Client向X Server发送连接请求,请求连接到X Server。
(3)X Server接受连接请求,并返回一个响应,表示连接成功。
(4)X Client和X Server开始通过X协议进行通信,交换图形用户界面数据和事件信息。
X协议主要部分
(1)显示协议:用于在客户端和服务器之间传输显示缓冲区的数据,包括图形图像和颜色信息。
(2) 输入协议:用于在客户端和服务器之间传输鼠标和键盘事件。
(3)渲染协议:用于在客户端和服务器之间传输窗口和图标数据。
(4)窗口管理协议:用于在客户端和服务器之间交换窗口管理信息,如窗口移动、大小调整等。
X协议的命令和响应类型
1. 请求命令
请求命令包括创建窗口、移动窗口、关闭窗口等命令,客户端向服务器发送请求命令后,服务器会处理请求并返回响应。
2. 响应命令
响应命令是服务器向客户端发送的响应命令,包括处理请求后的结果,例如创建窗口的ID、移动窗口的位置等。
3. 事件命令
事件命令是服务器向客户端发送的事件通知,包括用户输入、窗口变化等事件,客户端收到事件命令后可以进行相应的处理。
调用X11库简单的例子
#include <X11/Xlib.h> #include <stdio.h> int main() { Display *display; Window window; GC gc; XEvent event; int is_mouse_down = 0; int start_x, start_y; display = XOpenDisplay(NULL); // 打开与Xserver的连接 if(display == NULL) { fprintf(stderr, "无法打开显示\n"); return 1; } // 创建窗口 window = XCreateSimpleWindow(display, RootWindow(display, 0), 0, 0, 500, 500, 0, 0, WhitePixel(display, 0)); // 创建绘图环境 gc = XCreateGC(display, window, 0, NULL); // 监听鼠标点击和键盘按键事件 XSelectInput(display, window, ButtonPressMask | KeyPressMask); // 显示窗口 XMapWindow(display, window); // 进入事件循环 while(1) { // 处理事件 XNextEvent(display, &event); if(event.type == ButtonPress) { if(event.xbutton.button == Button1) // 鼠标左键按下 { is_mouse_down = 1; start_x = event.xbutton.x; start_y = event.xbutton.y; } } else if(event.type == MotionNotify) { if(is_mouse_down) { // 绘制直线 XDrawLine(display, window, gc, start_x, start_y, event.xmotion.x, event.xmotion.y); // 更新起始点 start_x = event.xmotion.x; start_y = event.xmotion.y; } } else if(event.type == ButtonRelease) { if(event.xbutton.button == Button1) // 鼠标左键释放 { is_mouse_down = 0; } } else if(event.type == KeyPress) { // 清除绘制的线条 XClearWindow(display, window); } } // 清理资源 XFreeGC(display, gc); XDestroyWindow(display, window); XCloseDisplay(display); return 0; }
编译的时候记得链接X11动态库
gcc x11demo.c -o x11demo -lX11
运行结果如图所示:
可以在窗口中通过鼠标点击画线。
还有X11部分的例子可以去参考:
Xlib-demo: Xlib 样例 - Gitee.com
源码链接:
通过学习例子去熟悉X11库如何使用,可以调用函数进行图形界面编写。不过X11库写界面不如QT用快,个人感觉只需要熟悉X window system的机制就可以了,除非在字符界面没有桌面,否则还是用QT进行编写图形界面比较实用