Skip to content

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.

  1. 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().

  2. 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:

    • 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

    We then give to value_mask the new value. We now describe how to use xcb_configure_window_t in some useful situations.

  3. 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.

  4. 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);
    
  5. 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);
    
  6. 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 and trans 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.