使用XCB编写X Window程序(05):使用异步的方式和X Server通讯及获取和设置窗口的属性
2020-12-13 05:12
标签:style blog color 使用 os 数据 在前面的例子中,我们从来没有关心过调用XCB函数时,该函数和X Server的通讯是同步的还是异步的。因为在前面的例子中,我们基本上不关心XCB函数的返回值,只有在上一篇中,由于某些操作需要关心它们是否成功(比如是否成功打开字体、是否成功创建GC等),才涉及到XCB函数的返回值。 在这一篇中会更进一步,因为是获取窗口的属性,所以肯定要关注从X Server获取的数据,这时,将会涉及到XCB函数同X Server的通讯是同步的还是异步的。什么是同步?就是说调用一个函数向X Server发出一个请求后,该函数要一直等到X Server回复的数据函数才返回。什么是异步?就是说调用一个XCB函数向X Server发出一个请求后,不用等X Server回复的数据,该函数直接返回。传统的Xlib使用的是同步的方式,而XCB则是使用的异步方式。很显然,使用异步的方式可以获得更好的效率。这也是XCB取代Xlib的一个主要原因。 那么既然XCB使用的是异步的方式,调用一个XCB函数后没有等到X Server的回复该函数就已经返回了,那么我们真的需要X Server回复的数据怎么办呢?对于这个问题,在XCB中使用的是这样一种解决方式:XCB函数先返回一个cookie,数据传输在后台进行,由XCB自动处理,当需要使用从X Server获取的数据时,再调用另外一个函数通过该cookie获取数据。后面将会看到具体的示例。 操控窗口的属性 前面展示了怎么创建窗口以及怎么在窗口中画图。其实对于窗口,还可以有更多的操作。可以认为这些操作都是通过获取和设置窗口的属性来进行。窗口可以有很多的属性,而且这些属性的设置方式还不一样。下面来回顾一下创建窗口的函数: 可以看到:1、有一部分属性是直接通过xcb_create_window的参数设置的,比如窗口的颜色深度、位置、大小、边框宽度等;2、一部分窗口的属性通过mask、values的方式设置,比如前景色、背景色、需要关注的事件等;3、还有一部分属性需要通过另外一种方式来设置,这种方式我之前没有展示过,那就是通过xcb_change_property函数来设置,这些属性比较特别,每一个都称之为atom。从xcb_create_window的函数签名还可以看出,xcb_create_window确实是返回一个xcb_void_cookie_t类型的值,也就是返回一个cookie。这验证了我之前关于XCB函数是异步的这个说法。 xcb_change_property的函数签名如下: 可以看出,该函数要同时关注atom的id、atom的类型及atom的值,还要关注该值的格式和长度。也就是说,每一个atom由一个id标识,它可以有自己的类型和值。比如一个atom可能是一个数字,而另一atom可能是一个字符串。该函数的mode参数可以取下面值中的一个: 使用atom来表示窗口的属性主要是为了和别的程序之间进行沟通,比如和窗口管理器沟通。下面是一个设置窗口标题以及窗口最小化后任务栏标题的示例: 如果想更改窗口的大小、位置、边框宽度等属性的话,可以通过如下函数进行: 可以看到,该函数再次用到了mask、valuelist这种模式。该函数可操作的属性有如下这些: 写了半天也还没写到XCB函数和X Server异步通讯的用法。为了不把这篇随笔写得又臭又长,xcb_configure_window具体怎么用我就不举例了。大家可以自行阅读XCB的官方教程。下面来看什么是异步。 获取窗口的属性 有很多函数可以获取窗口的属性,比如最常见的 xcb_get_geometry 和 xcb_get_geometry_reply ,看到geometry肯定会想到长宽高、横坐标纵坐标什么的。确实,这两个函数就是用来获取窗口的位置、大小这样一些信息的。而且这两个函数总是成对出现。因为xcb_get_geometry被调用后,它是马上返回的,这时X Server的数据还没传回来呢,所以,等数据传回来了,还得调用xcb_get_geometry_reply把这些数据读出来。这两个函数的签名如下: 可以看到,第一个函数返回一个类型为xcb_get_geometry_cookie_t的cookie,第二个函数再以该cookie为参数,返回具体的geometry信息,这就是异步。该信息是一个类型为xcb_get_geometry_reply_t的指针,该类型定义如下: 前面说过,窗口有很多属性。geometry属性指示窗口属性的一部分,所以,还有一对更猛的获取窗口属性的函数及其使用到的数据结构,如下: 这些都还是基本的。编写简单的窗口程序,了解这些基本的方法就够了。但是GUI编程,总还有一些高深的需求,比如枚举系统中所有的窗口。我这里用到了“枚举”这个词,是因为Win32 API用了这个词。而在X Window中,这样的操作叫做“遍历”。很显然,在GUI系统中,所有的窗口都是通过parent、child这样的方式呈树形组织起来的,所以通过“遍历”窗口树来“枚举”系统中的所有窗口,其实也不难。这个任务需要用到这样的函数和数据结构: 不过该函数好像只能从子窗口查找父窗口,很显然要完成遍历,还必须要能从父窗口查找子窗口。X Window中有通过父窗口查找子窗口的方法吗?大家慢慢研究去吧。 (京山游侠于2014-07-21发布于博客园,转载请注明出处。) 使用XCB编写X Window程序(05):使用异步的方式和X Server通讯及获取和设置窗口的属性,搜素材,soscw.com 使用XCB编写X Window程序(05):使用异步的方式和X Server通讯及获取和设置窗口的属性 标签:style blog color 使用 os 数据 原文地址:http://www.cnblogs.com/youxia/p/gui005.htmlxcb_void_cookie_t xcb_create_window (
xcb_connection_t *connection, /* Pointer to the xcb_connection_t structure */
uint8_t depth, /* Depth of the screen */
xcb_window_t wid, /* Id of the window */
xcb_window_t parent, /* Id of an existing window that should be the parent of the new window */
int16_t x, /* X position of the top-left corner of the window (in pixels) */
int16_t y, /* Y position of the top-left corner of the window (in pixels) */
uint16_t width, /* Width of the window (in pixels) */
uint16_t height, /* Height of the window (in pixels) */
uint16_t border_width, /* Width of the window‘s border (in pixels) */
uint16_t _class,
xcb_visualid_t visual,
uint32_t value_mask,
const uint32_t *value_list
);
xcb_void_cookie_t xcb_change_property (
xcb_connection_t *c, /* Connection to the X server */
uint8_t mode, /* Property mode */
xcb_window_t window, /* Window */
xcb_atom_t property, /* Property to change */
xcb_atom_t type, /* Type of the property */
uint8_t format, /* Format of the property (8, 16, 32) */
uint32_t data_len, /* Length of the data parameter */
const void *data /* Data */
);
XCB_PROP_MODE_REPLACE
XCB_PROP_MODE_PREPEND
XCB_PROP_MODE_APPEND
#include string.h>
#include
xcb_void_cookie_t xcb_configure_window (
xcb_connection_t *c, /* The connection to the X server*/
xcb_window_t window, /* The window to configure */
uint16_t value_mask, /* The mask */
const uint32_t *value_list /* The values to set */
);
XCB_CONFIG_WINDOW_X // new x coordinate of the window‘s top left corner
XCB_CONFIG_WINDOW_Y // new y coordinate of the window‘s top left corner
XCB_CONFIG_WINDOW_WIDTH // new width of the window
XCB_CONFIG_WINDOW_HEIGHT // new height of the window
XCB_CONFIG_WINDOW_BORDER_WIDTH // new width of the border of the window
XCB_CONFIG_WINDOW_SIBLING
XCB_CONFIG_WINDOW_STACK_MODE // the new stacking order
xcb_get_geometry_cookie_t xcb_get_geometry (
xcb_connection_t *connection,
xcb_drawable_t drawable
);
xcb_get_geometry_reply_t *xcb_get_geometry_reply (
xcb_connection_t *connection,
xcb_get_geometry_cookie_t cookie,
xcb_generic_error_t **error
);
typedef struct {
uint8_t response_type;
uint8_t depth; /* depth of the window */
uint16_t sequence;
uint32_t length;
xcb_window_t root; /* Id of the root window *>
int16_t x; /* X coordinate of the window‘s location */
int16_t y; /* Y coordinate of the window‘s location */
uint16_t width; /* Width of the window */
uint16_t height; /* Height of the window */
uint16_t border_width; /* Width of the window‘s border */
} xcb_get_geometry_reply_t;
typedef struct {
uint8_t response_type;
uint8_t backing_store;
uint16_t sequence;
uint32_t length;
xcb_visualid_t visual; /* Visual of the window */
uint16_t _class;
uint8_t bit_gravity;
uint8_t win_gravity;
uint32_t backing_planes;
uint32_t backing_pixel;
uint8_t save_under;
uint8_t map_is_installed;
uint8_t map_state; /* Map state of the window */
uint8_t override_redirect;
xcb_colormap_t colormap; /* Colormap of the window */
uint32_t all_event_masks;
uint32_t your_event_mask;
uint16_t do_not_propagate_mask;
} xcb_get_window_attributes_reply_t;
xcb_get_window_attributes_cookie_t xcb_get_window_attributes (
xcb_connection_t *connection,
xcb_window_t window
);
xcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (
xcb_connection_t *connection,
xcb_get_window_attributes_cookie_t cookie,
xcb_generic_error_t **e
);
typedef struct {
uint8_t response_type;
uint8_t pad0;
uint16_t sequence;
uint32_t length;
xcb_window_t root;
xcb_window_t parent; /* Id of the parent window */
uint16_t children_len;
uint8_t pad1[14];
} xcb_query_tree_reply_t;
xcb_query_tree_cookie_t xcb_query_tree (
xcb_connection_t *connection,
xcb_window_t window
);
xcb_query_tree_reply_t *xcb_query_tree_reply (
xcb_connection_t *connection,
xcb_query_tree_cookie_t cookie,
xcb_generic_error_t **error
);
文章标题:使用XCB编写X Window程序(05):使用异步的方式和X Server通讯及获取和设置窗口的属性
文章链接:http://soscw.com/essay/30582.html