x程序 Linux,使用XCB编写X Window程序(01):快速起步
估计现在已经没有谁使用XCB这么底层的库写应用程序了,要用也是用经过精心封装的Motif, LessTiff, GTK, Qt, EWL, ETK或者Cairo等高层次的库。我之所以这么费心地去折腾XCB,其实主要也是为了学习。毕竟,使用最接近底层的UI库写代码是学习X协议及GUI编程原理的最好方法。
XCB的主要教程可以参考这里:http://xcb.freedesktop.org/tutorial/
和X协议有关的文档,在这里:http://www.x.org/releases/X11R7.7/doc/
在这里要继续吐槽freedesktop.org。没错,XCB的官网又是在freedesktop.org,而且正如我前几篇随笔中提到的Xft、Freetype一样,文档极其不完善。不过在其XcbApi页面有这样的提示“Refactoring this page...please be patient...”,那就耐心等待吧。好在代码是最好的文档,在Fedora 20中安装libxcb-devel软件包后,可以直接到/usr/include/xcb目录下查看XCB库的头文件,所以真要学习XCB也不是很难。如下图,我系统中的XCB库的头文件:
下面是一个最简单的XCB程序,它的功能是创建一个窗口。由于没有任何事件处理的机制,所以使用了pause()让程序暂停,要退出程序,必须得按Ctrl+C。
1 #include
2 #include
3 #include
4 #include
5 #include
6
7 double get_time(){
8 struct timeval timeval;
9 gettimeofday(&timeval, NULL);
10 return (double)timeval.tv_sec + (((double)timeval.tv_usec)/1000000);
11 }
12
13 int main(){
14 double start_time = get_time();
15
16 xcb_connection_t *connection = xcb_connect(NULL, NULL);
17 const xcb_setup_t *setup = xcb_get_setup(connection);
18 xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
19 xcb_screen_t *screen = iter.data;
20
21 xcb_window_t window = xcb_generate_id(connection);
22 xcb_create_window(
23 connection,
24 XCB_COPY_FROM_PARENT,
25 window,
26 screen->root,
27 100,100,
28 400, 300,
29 10,
30 XCB_WINDOW_CLASS_INPUT_OUTPUT,
31 screen->root_visual,
32 0, NULL);
33 xcb_map_window(connection, window);
34 xcb_flush(connection);
35
36 printf("花费时间:%f秒。",get_time()-start_time);
37 fflush(stdout);
38
39 pause();
40 xcb_disconnect(connection);
41 return 0;
42 }
从这段代码可以看出,要创建一个简单的窗口程序,必须经过如下步骤:
1、连接到XServer的Display,通过xcb_connect()函数进行,返回一个xcb_connection_t的指针,在这一步中,同时可以获得当前屏幕的Screen number;
2、获得xcb_setup,通过xcb_get_setup()函数进行。xcb_setup里面保存的是应用程序和XServer之间通讯时需要用到的信息,包括协议的版本、字节的顺序等。一般情况下,我们不需要关注这些细节;
3、获得Screen对象,这一步很重要,也很复杂。重要是因为只有获得一个Screen后,才能在屏幕上创建窗口,创建窗口时需要用到Screen中的一些信息。复杂是因为一个Display可以有多个Screen,所以通过xcb_setup_roots_iterator()函数返回的是一个迭代器,可以通过该迭代器对所有的Screen进行遍历。如果只有一个Screen,则返回的第一个迭代器中的data就指向该Screen。XCB中使用xcb_screen_t结构来保存Screen的信息;
4、创建窗口并显示窗口,这需要三步,第一步先使用xcb_generate_id()函数生成一个ID,第二步使用xcb_create_window()函数创建一个窗口,第三步使用xcb_map_window让窗口显示出来。
通过以上的代码,我还学到了一个技巧,那就是使用gettimeofday()函数来获取一个精确到微秒的时间,用来查看应用程序的耗时。
程序运行如下图:
这个新创建的窗口自己没有背景,所以它创建的时候屏幕上有什么,它窗口里面就有什么。对于程序中用到的数据结构和枚举的含义,可以直接查看xcb的头文件,配合ctags和taglist.vim插件使用的话,只需要按Ctrl+]键,就可以自动跳转到这些数据结构的定义处(在Vim中使用taglist的方法见这里Linux江湖02:打造属于自己的Vim),如下两图:
最后,我对第一个简单的程序进行适当的扩展,看看怎么获取Display中有几个Screen以及怎么遍历Screen,最后显示Screen的一些信息。程序如下:
1 #include
2 #include
3 #include
4 #include
5 #include
6
7 double get_time(){
8 struct timeval timeval;
9 gettimeofday(&timeval, NULL);
10 return (double)timeval.tv_sec + (((double)timeval.tv_usec)/1000000);
11 }
12
13 int main(){
14 double start_time = get_time();
15 int screen_number;
16
17 xcb_connection_t *connection = xcb_connect(NULL, &screen_number);
18 const xcb_setup_t *setup = xcb_get_setup(connection);
19 xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
20 printf("当前的Screen Number为:%d\n",screen_number);
21 printf("iter.rem = %d,下面开始遍历:\n",iter.rem);
22
23 xcb_screen_t *screen;
24 for(; iter.rem!=0; xcb_screen_next(&iter)){
25 screen = iter.data;
26 printf("*****看到多少行这个提示,就说明有多少个Screen。*****\n");
27 printf(" Screen->root:%d\n",screen->root);
28 printf(" Screen->root_depth:%d\n",screen->root_depth);
29 printf(" Screen->white_pixel:%d\n",screen->white_pixel);
30 printf(" Screen->black_pixel:%d\n",screen->black_pixel);
31 printf(" Screen->width_in_pixels:%d\n",screen->width_in_pixels);
32 printf(" Screen->height_in_pixels:%d\n",screen->height_in_pixels);
33 printf(" Screen->width_in_millimeters:%d\n",screen->width_in_millimeters);
34 printf(" Screen->height_in_millimeters:%d\n",screen->height_in_millimeters);
35 }
36
37
38 xcb_window_t window = xcb_generate_id(connection);
39 xcb_create_window(
40 connection,
41 XCB_COPY_FROM_PARENT,
42 window,
43 screen->root,
44 100,100,
45 400, 300,
46 10,
47 XCB_WINDOW_CLASS_INPUT_OUTPUT,
48 screen->root_visual,
49 0, NULL);
50 xcb_map_window(connection, window);
51 xcb_flush(connection);
52
53 printf("花费时间:%f秒。",get_time()-start_time);
54 fflush(stdout);
55
56 pause();
57 xcb_disconnect(connection);
58 return 0;
59 }
最后运行效果如下图:
(京山游侠于2014-06-25发布于博客园,转载请注明出处。)
x程序 Linux,使用XCB编写X Window程序(01):快速起步相关推荐
- 用linux如何用vi编写c程序,linux中VI编写C程序。。。
在linux中编写C程序时不像编写shell那样开头要#!/bin/bash,但是在C程序中要指定头文件(头文件是指输入输出,宏等,而且要首先声明,也是必须要开始就声明的) 写好C代码后要给C文件赋予 ...
- Linux环境下编写一个shell程序,此程序的功能:随机生成一个1-100的数(答案)让用户猜
题目:编写一个shell程序,此程序的功能:随机生成一个1-100的数(答案)让用户猜,如果用户猜的数大于答案,则提示大了,如果用户猜的数小于答案,则提示小了.当用户猜对时提示:猜对了. #! /bi ...
- linux编写运行shell程序,Linux的Shell编程运行Shell程序的方法有哪些呢?
用户可以用任何编辑程序来编写Shell程序.因为Shell程序是解释执行的,所以不需要编译成目的程序.按照Shell编程的惯例,以 bash为例,程序的第一行一般为"#!/bin/bash& ...
- java application程序_如何Java编写的application程序像exe一样方便shy;的运行
Java编写的application程序是否能够最终形成一个类似于exe一样的可执行文件,难道就只能用命令行运行??? ---------------------------------------- ...
- python程序分析,用Python编写分析Python程序性能的工具的教程
用Python编写分析Python程序性能的工具的教程 来源:中文源码网 浏览: 次 日期:2018年9月2日 [下载文档: 用Python编写分析Python程序性能的工具的教程.tx ...
- linux如何运行java程序,Linux环境下运行简单java程序
一.安装java 1.下载jdk8 选择对应jdk版本下载.(Tips:可在Windows下载完成后,通过FTP或者SSH到发送到Linux上) 2. 登录Linux,切换到root用户 su roo ...
- linux系统如何卸载所有程序,Linux系统中完全卸载删除程序的命令
如果您在数据中心服务器或本地服务器中使用Ubuntu或任何其他基于debian的发行版系统,您可能会遇到需要卸载软件的情况.一般情况下,您会登录并运行命令:sudo apt-get remove pa ...
- java俄罗斯方块程序_使用JAVA编写的俄罗斯方块程序, 具有非常全面的功能.
Lastsong-Tetris 使用JAVA编写的俄罗斯方块程序, 具有非常全面的功能. 游戏基本规则: 1.打开游戏窗口后, 点击开始按钮进行游戏; 2.每消一行就会增加10分和1消行数,当分数累计 ...
- 编写并运行php程序,上传所编写的PHP程序代码,并上传运行后的效果截图
上传所编写的PHP程序代码,并上传运行后的效果截图 更多相关问题 [多选] 对税务机关的下列行政行为,纳税人可以申请行政复议的有(). [多选] 纳税人收到税务机关的行政处罚决定书之后,在法定期限内可 ...
- 用c语言编写MIDI程序,使用C语言编写钢琴小程序
网上搜索键盘钢琴,可以搜索到不少小游戏,最常玩的就是Flash小游戏,26个按键的. 后来想用C语言自己实现一个,没有界面--控制台的. 原理很简单,先在控制台中获取按键事件,在按键事件中,开一个线程 ...
最新文章
- 崛起的Python,真的影响了76万人?
- 谈谈WPF中的CollectionView与CollectionViewSource
- MVCAction接收数据方式
- 如何在JavaScript / jQuery中查找数组是否包含特定字符串? [重复]
- cv::Mat dst 这句话从语法是怎么理解?
- DIP第三章习题解答
- 【转】名企献身说法:我们喜欢这样的简历
- 海量数据持久层解决方案_爱数AnyBackup重磅发布海量非结构化数据超可用解决方案...
- 目前网络时间服务有哪几种协议?
- Multi-View 3D Reconstruction
- SonarLint黄线警告python:S125
- dijkstra算法学习笔记
- win10下载ios及安装方法
- next项目部署到服务器pm2进程守护
- 大学生论文发表的费用需要多少
- 计算机更改虚拟内存有用吗,电脑虚拟内存有什么用(小白必知虚拟内存作用及设置技巧)...
- 【原创】2009年8月25日老谷项目管理MSN群专题—敏捷生态
- Linux飞鸽传书源码,图解Ubuntu下编译安装飞鸽传书IPMsg步骤
- 将一句话里的单词进行倒置,标点符号不倒换P228
- Cisco无线AP无法注册至控制器故障
热门文章
- 计算机主机运行显示屏黑屏,解决方案:打开计算机后显示器黑屏的原因和解决方法...
- 麦子学院彭亮python基础_麦子学院Python视频
- 'javac'不是内部或外部命令,也不是可运行的程序或批处理文件.
- 为promise增加abort功能
- yarn add 添加依赖的各种类型(指定版本安装、git中安装、tgz包安装、文件夹安装)
- 01-----图形化代码管理工具TortoiseGit,及配合Putty将本地项目push到远程仓库
- 整理一个将qq音乐的歌单导入到苹果音乐中的方法
- vue 修改标题栏_在Vue中如何实现动态修改页面title
- UML(用例图,类图,对象图,包图)
- 轻量化安装 TKEStack:让已有 K8s 集群拥有企业级容器云平台的能力