X Window 系统的窗口显示原理

refer:

wiki http://zh.wikipedia.org/zh-cn/X_Window

http://en.wikipedia.org/wiki/X_Window_System#User_interface_issues

http://en.wikipedia.org/wiki/X_Window_System_protocols_and_architecture

http://fanqiang.chinaunix.net/program/other/2001-06-08/2097.shtml


X Window 系统的窗口显示原理


本文介绍 X Window 系统的窗口显示原理。从一个简单的 X 客户端程序入手,介绍了窗口的创建接口 XCreateWindow 和显示接口 XMapWindow 的实现,并结合窗口管理器介绍了 X Server、X Client 和窗口管理器三部分交互的原理。

徐 星, 高级软件工程师, 上海某手机设计公司

2010 年 7 月 01 日

  • +内容

X Window 系统介绍

X Window 系统是一个基于网络的图形界面系统,它于 1984 年在麻省理工学院开发,有将近 20 年的应用历史。X Window 系统广泛的应用于桌面 Linux(如 Fedora、Debian、Ubuntu 等),嵌入式 Linux(如 Nokia 的 Maemo、Intel 的 Moblin 等)。随着 Nokia 和 Intel 高调的将 Maemo 和 Moblin 合并为 Meego,X Window 系统的应用将被推向一个新的高潮。

X Window 是 C/S 架构,涵盖 X Server、X 协议、X Client 三部分内容。其 X Client 有三种开发模式:基于 XLib、基于 GTK、基于 Qt。

本文将以一个基于 XLib 的应用来介绍 X Window 的窗口显示原理。

示例及运行结果

示例代码将显示一个 200X200 的白色背景窗口,并在窗口的中间绘制一个 100 个点,连接成一条横线。按任意按键可以退出该程序。

清单 1. hello.c
 #include <stdio.h> 
 #include <stdlib.h> 
 #include <X11/Xlib.h> 

 #define WINDOW_SIZE 200 
 int main (int argc, char *argv[]) 
 { 
  Display              *dpy; 
  XSetWindowAttributes attributes; 
  Window               win; 
  GC                   gc; 
  XKeyEvent event; 
  int   i; 

  // 连接到 X Server,创建到 X Server 的套接字连接
  dpy = XOpenDisplay(NULL); 

  // 创建 200X200 的白色背景窗口
  attributes.background_pixel = XWhitePixel(dpy, 0);  
  win = XCreateWindow(dpy, XRootWindow(dpy, 0), 
      0, 0, WINDOW_SIZE, WINDOW_SIZE, 0, DefaultDepth(dpy, 0), 
      InputOutput, DefaultVisual(dpy, 0), 
      CWBackPixel,&attributes); 
  // 选择输入事件。
  XSelectInput(dpy, win, ExposureMask | KeyPressMask ); 
  // 创建绘图上下文
  gc = XCreateGC(dpy, win, 0, NULL); 
  //Map 窗口
  XMapWindow(dpy, win); 
  // 事件主循环。主要处理 Expose 事件和 KeyPress 事件
  while(1) 
  { 
    XNextEvent(dpy,(XEvent *)&event); 
    switch(event.type) 
    { 
      // 处理 Expose 事件
      case Expose: 
        { 
          // 绘制 100 个点
          for (i=0;i<WINDOW_SIZE/2;i++) 
            XDrawPoint(dpy, win, gc, WINDOW_SIZE/4+i, WINDOW_SIZE/2); 
        }break; 
      // 处理按键事件
      case KeyPress: 
        { 
          XFreeGC(dpy, gc); 
          XCloseDisplay(dpy); 
          exit(0); 
        }break; 
      default: 
        { 
        }break; 
    } 
  } 
  return(0); 
 }

编译:gcc -o hello hello.c -lX11

图 1. Ubuntu 9.10 运行结果
图 1. Ubuntu 9.10 运行结果
图 2. Maemo Fremantle 模拟器运行结果
图 2. Maemo Fremantle 模拟器运行结果

在示例代码 hello.c 中,和窗口显示相关的接口主要有:XCreateWindow,XMapWindow,XDrawPoint。在示例代码之外,X Server 和窗口管理器同时在发挥着各自的关键作用。本文将结合 X Server、窗口管理器、示例 hello.c 代码来解释窗口显示的原理。

创建窗口:XCreateWindow

在 X Window 系统中,客户端申请的 GC、Pixmap、Window 等资源位于服务器 X Server 端。而客户端创建的另一些资源如 XImage,不由 X Server 管理,而是由客户端自行管理。

在客户端调用 XCreateWindow 创建一个窗口时,X Server 会为它建立一个 Window 类型的数据结构。该结构中描述了窗口的大小、坐标等信息。窗口实际上是屏幕的一块区域,子窗口是父窗口的一部分,所有的窗口有一个共同的根即根窗口。

客户端调用 XCreateWindow 接口时,对应的 X Server 实现是 CreateWindow 函数:

清单 2. CreateWindow 实现
 WindowPtr 
 CreateWindow(Window wid, WindowPtr pParent, int x, int y, unsigned w, 
             unsigned h, unsigned bw, unsigned class, Mask vmask, XID *vlist, 
             int depth, ClientPtr client, VisualID visual, int *error) 
 { 
 /* 省略非关键代码部分 */ 
    pScreen = pParent->drawable.pScreen; 
    pWin->drawable = pParent->drawable;/* 子窗口是父窗口的一部分 */ 
    pWin->devPrivates = NULL; 
    pWin->drawable.depth = depth; 
 /* 省略非关键代码部分 */ 
    pWin->origin.x = x + (int)bw; 
    pWin->origin.y = y + (int)bw; 
    pWin->drawable.width = w;/* 窗口管理信息 */ 
    pWin->drawable.height = h; 
    pWin->drawable.x = pParent->drawable.x + x + (int)bw; 
    pWin->drawable.y = pParent->drawable.y + y + (int)bw; 
…
 }

在 GTK 中,调用 gdk_window_new 会创建一个 X 窗口。GTK 提供了三种类型的顶层窗口:GDK_WINDOW_TOPLEVEL、GDK_WINDOW_DIALOG、GDK_WINDOW_TEMP。这些顶层窗口的父亲是 GDK_SCREEN_XROOTWIN,即根窗口。而 GDK_WINDOW_CHILD 类型的窗口其父亲由用户创建窗口时指定。GDK_WINDOW_CHILD 类型的窗口对应的是 GTK 的控件,如 GtkButton、GtkEntry 等。

如前述,所有的窗口都是父窗口的一部分。所有窗口的根是根窗口。根窗口由 X Server 在启动时创建,对应整个屏幕区域。

以 GTK 为例子,GTK 窗口层级视图是下图 3 的样子:

图 3. GTK 窗口层级视图
图 3. GTK 窗口层级视图

对单个应用而言,部分窗口管理器如 Matchbox Window Manager 只支持一个应用级顶层窗口,譬如 Maemo Fremantle 使用的就是该类型的窗口管理器。这就是为什么 Maemo Fremantle 模拟器运行 hello.c 的显示结果 ( 图 2) 不是设定的尺寸 200X200,而是延伸到整个屏幕宽度。在 Maemo Fremantle 模拟器顶部显示的状态条其实是主界面显示的,该部分是 Dock 类型的窗口,和 hello.c 无关。

CreateWindow 调用结束的时候给客户端发送 CreateNotify 事件。但是 GTK 没有处理该事件。

映射窗口:XMapWindow

XMapWindow 对应的 X Server 实现是 MapWindow 函数。该代码较长,而且涉及到 X Client、X Server、窗口管理器的多次交互。

MapWindow 的工作原理是:

  1. 客户端调用 MapWindow 请求映射 Client 窗口。如果该窗口的 overrideRedirect 为假,表示该 MapWindow 调用为普通客户端发起。则发送 MapRequest 到窗口管理器。请求窗口管理器进一步处理。
  2. 窗口管理器收到 MapRequest,创建一个 Frame 窗口,并通过 XReparentWindow 调用,将客户端的窗口设置为 Frame 窗口的子窗口。Frame 窗口的 overrideRedirect 为真。
  3. 窗口管理器调用 XMapSubwindows,第二个参数为 Frame 窗口。由于 Frame 窗口的 overrideRedirect 为真,MapSubwindows 会对该 Frame 窗口的子窗口做映射。并发送 MapNotify 事件、Expose 事件给客户端。客户端在 Expose 事件中绘制客户端窗口内容。
  4. 窗口管理器调用 XMapWindow,第二个参数为 Frame 窗口。同样由于 Frame 窗口的 overrideRedirect 为真,这次 MapWindow 也不发射 MapRequest 事件了,从而映射了 Frame 窗口。
  5. X Server 在映射 Frame 窗口之后,发送 Expose 事件给窗口管理器,以通知窗口管理器绘制窗口的边框等。

至此,客户端窗口的内容,窗口的边框都被显示在屏幕上了。

下图 4 是 X Client、X Server、窗口管理器的交互序列图:

图 4. X Client、X Server、窗口管理器交互序列图
图 4. X Client、X Server、窗口管理器交互序列图

结束语

X Window 是一个功能非常强大的 C/S 图形显示系统,具有很好的跨网络性能,也易于进行扩展。了解其窗口显示原理对程序员进行 GTK/QT 编程是有帮助的。

参考资料



六 linux X window system

分类: linux学习 601人阅读 评论(0) 收藏 举报
为啥图形窗口接口要称为 X 呢?因为就英文字母来看 X 是在
W(indow) 后面,因此,人们就戏称这一版的窗口接口为 X ,有下一版新窗口之意


X系统由3个相关的部分组合起来的。 
  服务端(Server)
  Server是控制显示器和输入设备(键盘和鼠标)等硬件的软件。
它负责检测具体那个设备有什么动作,如键盘按下、鼠标滑动,但它不能将这些动作转化为绘图数据。
它还负责 设备发出动作以后,到底该如何显示。

客户端(Client)
  Client的主要工作是接受服务器传来的动作,将其转化为绘图数据,再将这写数据送去服务端。

Server和Client之间的通信
  Server和Client通信的方式大致有两类,对应于X系统的两种基本操作模式。
  第一类,Server和Client在同一台机器上执行,它们可以共同使用机器上任何可用的通信方式做互动式信息处理。在这种模式下,X可以同其他传统的视窗系统一样高效工作。
  第二类,Client在一台机器上运行,而显示器和Server则在另一台机器上运行。因此两者的信息交换就必须通过彼此都遵守的网络协议进行,最常用的协议为TCP/IP。这种通信方式一般被称为网络透明性,这也几乎是X独一无二的特性。


用windows 远程访问 linux时
windows作为通常的c端,需要装x系统中的 x server。
我们在 Windows 中将鼠标向右移动时,首先,X server 会侦测到鼠标移动,但是他不知道应该怎么绘图!他将鼠标这个动作告知 linux 下的X Client, X Client 就会去运算,得到其实要将鼠标向右移动几个位素的,然后将这个结果告知 X server , 接下来,您就会看到 X Server 将鼠标向右移动了。

X Window Manager:特殊的 X Client ,负责管理所有的 X client 软件
刚刚前面提到,X Client 的主要工作是将来自 X Server 的数据处理成为绘图数据,再回传给 X server
而已, 所以 X client 本身是不知道他在 X Server 当中的位置、大小以及其他相关信息的。这也是上面
我们谈到的, X client 彼此不知道对方在屏幕的哪个位置啊!为了克服这个问题,因此就有 Window
Manager (WM, 窗口管理器) 的产生了。 窗口管理器也是 X client ,只是他主要在负责全部 X client
的控管,还包括提供某些特殊的功能,例如:
提供许多的控制元素,包括任务栏、背景桌面的设定等等;
管理虚拟桌面 (virtual desktop);
提供窗口控制参数,这包括窗口的大小、窗口的重迭显示、窗口的移动、窗口的最小化等等。
我们常常吩到的 KDE, GNOME, XFCE ,都是一些窗口管理器的项目。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值