Skip to content

Interacting with the window manager

After we have seen how to create windows and draw on them, we take one step back, and look at how our windows are interacting with their environment (the full screen and the other windows). First of all, our application needs to interact with the window manager. The window manager is responsible to decorating drawn windows (i.e. adding a frame, an iconify button, a system menu, a title bar, etc), as well as handling icons shown when windows are being iconified. It also handles ordering of windows on the screen, and other administrative tasks. We need to give it various hints as to how we want it to treat our application's windows.

  1. Window properties

    Many of the parameters communicated to the window manager are passed using data called "properties". These properties are attached by the X server to different windows, and are stored in a format that makes it possible to read them from different machines that may use different architectures (remember that an X client program may run on a remote machine).

    The property and its type (a string, an integer, etc) are Id. Their type are xcb_atom_t:

    typedef uint32_t xcb_atom_t;
    typedef uint32_t xcb_atom_t;

    To change the property of a window, we use the following function:

    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_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 */

    The mode parameter coud be one of the following values (defined in enumeration xcb_prop_mode_t in the xproto.h header file):

    • XCB_PROP_MODE_REPLACE
    • XCB_PROP_MODE_PREPEND
    • XCB_PROP_MODE_APPEND

  2. Setting the window name and icon name

    The first thing we want to do would be to set the name for our window. This is done using the xcb_change_property() function. This name may be used by the window manager as the title of the window (in the title bar), in a task list, etc. The property atom to use to set the name of a window is WM_NAME (and WM_ICON_NAME for the iconified window) and its type is STRING. Here is an example of utilization:

    #include <string.h>
    
    #include <xcb/xcb.h>
    #include <xcb/xcb_atom.h>
    
    int
    main ()
    {
      xcb_connection_t *c;
      xcb_screen_t     *screen;
      xcb_window_t      win;
      char             *title = "Hello World !";
      char             *title_icon = "Hello World ! (iconified)";
    
    
    
      /* Open the connection to the X server */
      c = xcb_connect (NULL, NULL);
    
      /* Get the first screen */
      screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
    
      /* Ask for our window's Id */
      win = xcb_generate_id (c);
    
      /* Create the window */
      xcb_create_window (c,                             /* Connection          */
                         0,                             /* depth               */
                         win,                           /* window Id           */
                         screen->root,                  /* parent window       */
                         0, 0,                          /* x, y                */
                         250, 150,                      /* width, height       */
                         10,                            /* border_width        */
                         XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
                         screen->root_visual,           /* visual              */
                         0, NULL);                      /* masks, not used     */
    
      /* Set the title of the window */
      xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
                           WM_NAME, STRING, 8,
                           strlen (title), title);
    
      /* Set the title of the window icon */
      xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
                           WM_ICON_NAME, STRING, 8,
                           strlen(title_icon), title_icon);
    
      /* Map the window on the screen */
      xcb_map_window (c, win);
    
      xcb_flush (c);
    
      while (1) {}
    
      return 0;
    }
    #include <string.h>
    
    #include <xcb/xcb.h>
    #include <xcb/xcb_atom.h>
    
    int
    main ()
    {
      xcb_connection_t *c;
      xcb_screen_t     *screen;
      xcb_window_t      win;
      char             *title = "Hello World !";
      char             *title_icon = "Hello World ! (iconified)";
    
    
    
      /* Open the connection to the X server */
      c = xcb_connect (NULL, NULL);
    
      /* Get the first screen */
      screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
    
      /* Ask for our window's Id */
      win = xcb_generate_id (c);
    
      /* Create the window */
      xcb_create_window (c,                             /* Connection          */
                         0,                             /* depth               */
                         win,                           /* window Id           */
                         screen->root,                  /* parent window       */
                         0, 0,                          /* x, y                */
                         250, 150,                      /* width, height       */
                         10,                            /* border_width        */
                         XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
                         screen->root_visual,           /* visual              */
                         0, NULL);                      /* masks, not used     */
    
      /* Set the title of the window */
      xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
                           WM_NAME, STRING, 8,
                           strlen (title), title);
    
      /* Set the title of the window icon */
      xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
                           WM_ICON_NAME, STRING, 8,
                           strlen(title_icon), title_icon);
    
      /* Map the window on the screen */
      xcb_map_window (c, win);
    
      xcb_flush (c);
    
      while (1) {}
    
      return 0;
    }

    Note: the use of the atoms needs our program to be compiled and linked against xcb_atom, so that we have to use

    gcc prog.c -o prog `pkg-config --cflags --libs xcb_atom`
    

    for the program to compile fine.