Simple window operations
One more thing we can do to our window is manipulate them on the screen (resize them, move them, raise or lower them, iconify them, and so on). Some window operations functions are supplied by XCB for this purpose.
Mapping and un-mapping a window
The first pair of operations we can apply on a window is mapping it, or un-mapping it. Mapping a window causes the window to appear on the screen, as we have seen in our simple window program example. Un-mapping it causes it to be removed from the screen (although the window as a logical entity still exists). This gives the effect of making a window hidden (unmapped) and shown again (mapped). For example, if we have a dialog box window in our program, instead of creating it every time the user asks to open it, we can create the window once, in an un-mapped mode, and when the user asks to open it, we simply map the window on the screen. When the user clicked the 'OK' or 'Cancel' button, we simply un-map the window. This is much faster than creating and destroying the window, however, the cost is wasted resources, both on the client side, and on the X server side.
To map a window, you use the following function:
xcb_void_cookie_t xcb_map_window (xcb_connection_t *c, xcb_window_t window);
xcb_void_cookie_t xcb_map_window (xcb_connection_t *c, xcb_window_t window);
To have a simple example, see the example above. The mapping operation will cause an
Expose
event to be sent to our application, unless the window is completely covered by other windows.Un-mapping a window is also simple. You use the function
xcb_void_cookie_t xcb_unmap_window (xcb_connection_t *c, xcb_window_t window);
xcb_void_cookie_t xcb_unmap_window (xcb_connection_t *c, xcb_window_t window);
The utilization of this function is the same as
xcb_map_window()
.Configuring a window
As we have seen when we have created our first window, in the X Events subsection, we can set some attributes for the window (that is, the position, the size, the events the window will receive, etc). If we want to modify them, but the window is already created, we can change them by using the following function:
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_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 */
We set the
value_mask
to one or several mask values that are in the xcb_config_window_t enumeration in the xproto.h header:- : new x coordinate of the window's top left corner
XCB_CONFIG_WINDOW_X
- : new y coordinate of the window's top left corner
XCB_CONFIG_WINDOW_Y
- : new width of the window
XCB_CONFIG_WINDOW_WIDTH
- : new height of the window
XCB_CONFIG_WINDOW_HEIGHT
- : new width of the border of the window
XCB_CONFIG_WINDOW_BORDER_WIDTH
XCB_CONFIG_WINDOW_SIBLING
- : the new stacking order
XCB_CONFIG_WINDOW_STACK_MODE
We then give to
value_mask
the new value. We now describe how to usexcb_configure_window_t
in some useful situations.Moving a window around the screen
An operation we might want to do with windows is to move them to a different location. This can be done like this:
const static uint32_t values[] = { 10, 20 }; /* The connection c and the window win are supposed to be defined */ /* Move the window to coordinates x = 10 and y = 20 */ xcb_configure_window (c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
Note that when the window is moved, it might get partially exposed or partially hidden by other windows, and thus we might get
Expose
events due to this operation.Resizing a window
Yet another operation we can do is to change the size of a window. This is done using the following code:
const static uint32_t values[] = { 200, 300 }; /* The connection c and the window win are supposed to be defined */ /* Resize the window to width = 10 and height = 20 */ xcb_configure_window (c, win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
We can also combine the move and resize operations using one single call to
xcb_configure_window_t
:const static uint32_t values[] = { 10, 20, 200, 300 }; /* The connection c and the window win are supposed to be defined */ /* Move the window to coordinates x = 10 and y = 20 */ /* and resize the window to width = 10 and height = 20 */ xcb_configure_window (c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
Changing windows stacking order: raise and lower
Until now, we changed properties of a single window. We'll see that there are properties that relate to the window and other windows. One of them is the stacking order. That is, the order in which the windows are layered on top of each other. The front-most window is said to be on the top of the stack, while the back-most window is at the bottom of the stack. Here is how to manipulate our windows stack order:
const static uint32_t values[] = { XCB_STACK_MODE_ABOVE }; /* The connection c and the window win are supposed to be defined */ /* Move the window on the top of the stack */ xcb_configure_window (c, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
const static uint32_t values[] = { XCB_STACK_MODE_BELOW }; /* The connection c and the window win are supposed to be defined */ /* Move the window on the bottom of the stack */ xcb_configure_window (c, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
Getting information about a window
Just like we can set various attributes of our windows, we can also ask the X server supply the current values of these attributes. For example, we can check where a window is located on the screen, what is its current size, whether it is mapped or not, etc. The structure that contains some of this information is
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 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;
XCB fill this structure with two functions:
xcb_get_geometry_cookie_t xcb_get_geometry (xcb_connection_t *c, xcb_drawable_t drawable); xcb_get_geometry_reply_t *xcb_get_geometry_reply (xcb_connection_t *c, xcb_get_geometry_cookie_t cookie, xcb_generic_error_t **e);
xcb_get_geometry_cookie_t xcb_get_geometry (xcb_connection_t *c, xcb_drawable_t drawable); xcb_get_geometry_reply_t *xcb_get_geometry_reply (xcb_connection_t *c, xcb_get_geometry_cookie_t cookie, xcb_generic_error_t **e);
You use them as follows:
xcb_connection_t *c; xcb_drawable_t win; xcb_get_geometry_reply_t *geom; /* You initialize c and win */ geom = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL); /* Do something with the fields of geom */ free (geom);
xcb_connection_t *c; xcb_drawable_t win; xcb_get_geometry_reply_t *geom; /* You initialize c and win */ geom = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL); /* Do something with the fields of geom */ free (geom);
Remark that you have to free the structure, as
xcb_get_geometry_reply_t
allocates a newly one.One problem is that the returned location of the window is relative to its parent window. This makes these coordinates rather useless for any window manipulation functions, like moving it on the screen. In order to overcome this problem, we need to take a two-step operation. First, we find out the Id of the parent window of our window. We then translate the above relative coordinates to the screen coordinates.
To get the Id of the parent window, we need this structure:
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;
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;
To fill this structure, we use these two functions:
xcb_query_tree_cookie_t xcb_query_tree (xcb_connection_t *c, xcb_window_t window); xcb_query_tree_reply_t *xcb_query_tree_reply (xcb_connection_t *c, xcb_query_tree_cookie_t cookie, xcb_generic_error_t **e);
xcb_query_tree_cookie_t xcb_query_tree (xcb_connection_t *c, xcb_window_t window); xcb_query_tree_reply_t *xcb_query_tree_reply (xcb_connection_t *c, xcb_query_tree_cookie_t cookie, xcb_generic_error_t **e);
The translated coordinates will be found in this structure:
typedef struct { uint8_t response_type; uint8_t same_screen; uint16_t sequence; uint32_t length; xcb_window_t child; uint16_t dst_x; /* Translated x coordinate */ uint16_t dst_y; /* Translated y coordinate */ } xcb_translate_coordinates_reply_t;
typedef struct { uint8_t response_type; uint8_t same_screen; uint16_t sequence; uint32_t length; xcb_window_t child; uint16_t dst_x; /* Translated x coordinate */ uint16_t dst_y; /* Translated y coordinate */ } xcb_translate_coordinates_reply_t;
As usual, we need two functions to fill this structure:
xcb_translate_coordinates_cookie_t xcb_translate_coordinates (xcb_connection_t *c, xcb_window_t src_window, xcb_window_t dst_window, int16_t src_x, int16_t src_y); xcb_translate_coordinates_reply_t *xcb_translate_coordinates_reply (xcb_connection_t *c, xcb_translate_coordinates_cookie_t cookie, xcb_generic_error_t **e);
xcb_translate_coordinates_cookie_t xcb_translate_coordinates (xcb_connection_t *c, xcb_window_t src_window, xcb_window_t dst_window, int16_t src_x, int16_t src_y); xcb_translate_coordinates_reply_t *xcb_translate_coordinates_reply (xcb_connection_t *c, xcb_translate_coordinates_cookie_t cookie, xcb_generic_error_t **e);
We use them as follows:
xcb_connection_t *c; xcb_drawable_t win; xcb_get_geometry_reply_t *geom; xcb_query_tree_reply_t *tree; xcb_translate_coordinates_reply_t *trans; /* You initialize c and win */ geom = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL); if (!geom) return 0; tree = xcb_query_tree_reply (c, xcb_query_tree (c, win), NULL); if (!tree) return 0; trans = xcb_translate_coordinates_reply (c, xcb_translate_coordinates (c, win, tree->parent, geom->x, geom->y), NULL); if (!trans) return 0; /* the translated coordinates are in trans->dst_x and trans->dst_y */ free (trans); free (tree); free (geom);
xcb_connection_t *c; xcb_drawable_t win; xcb_get_geometry_reply_t *geom; xcb_query_tree_reply_t *tree; xcb_translate_coordinates_reply_t *trans; /* You initialize c and win */ geom = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL); if (!geom) return 0; tree = xcb_query_tree_reply (c, xcb_query_tree (c, win), NULL); if (!tree) return 0; trans = xcb_translate_coordinates_reply (c, xcb_translate_coordinates (c, win, tree->parent, geom->x, geom->y), NULL); if (!trans) return 0; /* the translated coordinates are in trans->dst_x and trans->dst_y */ free (trans); free (tree); free (geom);
Of course, as for
geom
,tree
andtrans
have to be freed.The work is a bit hard, but XCB is a very low-level library.
TODO: the utilization of these functions should be a prog, which displays the coordinates of the window.
There is another structure that gives informations about our window:
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;
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 supplies these two functions to fill it:
xcb_get_window_attributes_cookie_t xcb_get_window_attributes (xcb_connection_t *c, xcb_window_t window); xcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (xcb_connection_t *c, xcb_get_window_attributes_cookie_t cookie, xcb_generic_error_t **e);
xcb_get_window_attributes_cookie_t xcb_get_window_attributes (xcb_connection_t *c, xcb_window_t window); xcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (xcb_connection_t *c, xcb_get_window_attributes_cookie_t cookie, xcb_generic_error_t **e);
You use them as follows:
xcb_connection_t *c; xcb_drawable_t win; xcb_get_window_attributes_reply_t *attr; /* You initialize c and win */ attr = xcb_get_window_attributes_reply (c, xcb_get_window_attributes (c, win), NULL); if (!attr) return 0; /* Do something with the fields of attr */ free (attr);
xcb_connection_t *c; xcb_drawable_t win; xcb_get_window_attributes_reply_t *attr; /* You initialize c and win */ attr = xcb_get_window_attributes_reply (c, xcb_get_window_attributes (c, win), NULL); if (!attr) return 0; /* Do something with the fields of attr */ free (attr);
As for
geom
,attr
has to be freed.