X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=doc%2Ftutorial%2Findex.html;h=ea083374503701bc0fd0a5f6119ca2628a460cf9;hb=422458b66380e4103c4937f0e2e8bb93e31f273a;hp=2e62c7da2d7edeb00aaa61af474e3ace326b9a39;hpb=342e9cefcc7d942714488f6b424fee7a5bdc741f;p=free-sw%2Fxcb%2Flibxcb diff --git a/doc/tutorial/index.html b/doc/tutorial/index.html index 2e62c7d..ea08337 100644 --- a/doc/tutorial/index.html +++ b/doc/tutorial/index.html @@ -59,9 +59,10 @@
  • Handling text and fonts
    1. The Font structure -
    2. Loading a Font -
    3. Assigning a Font to a Graphic Context -
    4. Drawing text in a window +
    5. Opening a Font +
    6. Assigning a Font to a Graphic Context +
    7. Drawing text in a drawable +
    8. Complete example
  • Windows hierarchy
      @@ -149,7 +150,7 @@
    1. DoesBackingStore
    2. EventMaskOfScreen
    -
  • Miscellaneaous macros +
  • Miscellaneous macros
    1. DisplayOfScreen
    2. DisplayCells / CellsOfScreen @@ -172,13 +173,14 @@ with the XCB library. keep in mind that XCB, like the Xlib - library, isn't what post programmers wanting to write X + library, isn't what most programmers wanting to write X applications are looking for. They should use a much higher level GUI toolkit like Motif, LessTiff, GTK, - QT or - EWL, or use + QT, + EWL, + ETK, or use Cairo. However, we need to start somewhere. More than this, knowing how things @@ -469,8 +471,6 @@ main () diff = end - start; /* free var */ - for (i = 0; i < count; ++i) - free (names[i]); free (atoms); free (cs); @@ -492,6 +492,8 @@ main () printf ("ratio : %f\n", diff_x / diff); free (atoms_x); + for (i = 0; i < count; ++i) + free (names[i]); free (names); XCloseDisplay (disp); @@ -587,8 +589,8 @@ gcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb` will be the one in the environment variable DISPLAY.

      -xcb_connection_t *xcb_connect (const char *displayname,
      -                               int        *screenp);
      +xcb_connection_t *xcb_connect (const char *displayname,
      +                               int        *screenp);
       

      The second parameter returns the screen number used for the @@ -596,24 +598,24 @@ gcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb` and is opaque. Here is how the connection can be opened:

      -#include <xcb/xcb.h>
      +#include <xcb/xcb.h>
       
      -int
      -main ()
      +int
      +main ()
       {
      -  xcb_connection_t *c;
      +  xcb_connection_t *c;
       
         /* Open the connection to the X server. Use the DISPLAY environment variable as the default display name */
         c = xcb_connect (NULL, NULL);
       
      -  return 0;
      +  return 0;
       }
       

      To close a connection, it suffices to use:

      -void xcb_disconnect (xcb_connection_t *c);
      +void xcb_disconnect (xcb_connection_t *c);
       
      @@ -640,8 +642,7 @@ gcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb`
      -

      -

      +
    3. Checking basic information about a connection

      Once we have opened a connection to an X server, we should check some @@ -706,7 +707,7 @@ main () } printf ("\n"); - printf ("Informations of screen %ld:\n", screen->root.xid); + printf ("Informations of screen %ld:\n", screen->root); printf (" width.........: %d\n", screen->width_in_pixels); printf (" height........: %d\n", screen->height_in_pixels); printf (" white pixel...: %ld\n", screen->white_pixel); @@ -723,9 +724,7 @@ main () characterized by an Id. So, in XCB, a window is of type:

      -typedef struct {
      -    uint32_t xid;
      -} xcb_window_t;
      +typedef uint32_t xcb_window_t;
       

      We first ask for a new Id for our window, with this function: @@ -887,9 +886,7 @@ int xcb_aux_sync (xcb_connection_t *c); a Graphics Context is, as a window, characterized by an Id:

      -typedef struct {
      -    uint32_t xid;
      -} xcb_gcontext_t;
      +typedef uint32_t xcb_gcontext_t;
       

      We first ask the X server to attribute an Id to our graphic @@ -982,8 +979,9 @@ main () change its attributes (for example, changing the foreground color we use to draw a line, or changing the attributes of the font we use to display strings. See Subsections Drawing with a - color and Assigning a Font to a Graphic Context). This is done - by using this function: + color and + Assigning a Font to a Graphic Context). + This is done by using this function:

       xcb_void_cookie_t xcb_change_gc (xcb_connection_t *c,           /* The XCB Connection */
      @@ -1333,7 +1331,7 @@ main ()
             /* We draw the polygonal line */
             xcb_poly_line (c, XCB_COORD_MODE_PREVIOUS, win, foreground, 4, polyline);
       
      -      /* We draw the segements */
      +      /* We draw the segments */
             xcb_poly_segment (c, win, foreground, 2, segments);
       
             /* We draw the rectangles */
      @@ -1455,7 +1453,7 @@ typedef enum {
       

      If the window has already been created, we can use the - xcb_configure_window() function to set + xcb_change_window_attributes() function to set the events that the window will receive. The subsection Configuring a window shows its prototype. As an example, here is a piece of code that @@ -1468,14 +1466,14 @@ const static uint32_t values[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTT /* The connection c and the window win are supposed to be defined */ -xcb_configure_window (c, win, XCB_CW_EVENT_MASK, values); +xcb_change_window_attributes (c, win, XCB_CW_EVENT_MASK, values);

      - Note: A common bug programmers do is adding code to handle new + Note: A common bug programmers have is adding code to handle new event types in their program, while forgetting to add the masks for these events in the creation of the window. Such a - programmer then should sit down for hours debugging his + programmer would then sit there for hours debugging their program, wondering "Why doesn't my program notice that I released the button?", only to find that they registered for button press events but not for button release events. @@ -1832,7 +1830,7 @@ typedef xcb_enter_notify_event_t xcb_leave_notify_event_t; keyboard focus using the window manager (often by clicking on the title bar of the desired window). Once our window has the keyboard focus, every key press or key release will - cause an event to be sent to our program (if it regsitered + cause an event to be sent to our program (if it registered for these event types...).

    4. Keyboard press and release events @@ -1959,25 +1957,25 @@ main () xcb_expose_event_t *ev = (xcb_expose_event_t *)e; printf ("Window %ld exposed. Region to be redrawn at location (%d,%d), with dimension (%d,%d)\n", - ev->window.xid, ev->x, ev->y, ev->width, ev->height); + ev->window, ev->x, ev->y, ev->width, ev->height); break; } case XCB_BUTTON_PRESS: { xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e; print_modifiers(ev->state); - switch (ev->detail.id) { + switch (ev->detail) { case 4: printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); break; case 5: printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); break; default: printf ("Button %d pressed in window %ld, at coordinates (%d,%d)\n", - ev->detail.id, ev->event.xid, ev->event_x, ev->event_y); + ev->detail, ev->event, ev->event_x, ev->event_y); } break; } @@ -1986,28 +1984,28 @@ main () print_modifiers(ev->state); printf ("Button %d released in window %ld, at coordinates (%d,%d)\n", - ev->detail.id, ev->event.xid, ev->event_x, ev->event_y); + ev->detail, ev->event, ev->event_x, ev->event_y); break; } case XCB_MOTION_NOTIFY: { xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)e; printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); break; } case XCB_ENTER_NOTIFY: { xcb_enter_notify_event_t *ev = (xcb_enter_notify_event_t *)e; printf ("Mouse entered window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); break; } case XCB_LEAVE_NOTIFY: { xcb_leave_notify_event_t *ev = (xcb_leave_notify_event_t *)e; printf ("Mouse left window %ld, at coordinates (%d,%d)\n", - ev->event.xid, ev->event_x, ev->event_y); + ev->event, ev->event_x, ev->event_y); break; } case XCB_KEY_PRESS: { @@ -2015,7 +2013,7 @@ main () print_modifiers(ev->state); printf ("Key pressed in window %ld\n", - ev->event.xid); + ev->event); break; } case XCB_KEY_RELEASE: { @@ -2023,7 +2021,7 @@ main () print_modifiers(ev->state); printf ("Key released in window %ld\n", - ev->event.xid); + ev->event); break; } default: @@ -2051,22 +2049,314 @@ main ()
      1. The Font structure

        - In order to support flexible fonts, a font structure is + In order to support flexible fonts, a font type is defined. You know what ? It's an Id:

        -typedef struct {
        -    uint32_t xid;
        -} xcb_font_t;
        +typedef uint32_t xcb_font_t;
         

        It is used to contain information about a font, and is passed to several functions that handle fonts selection and text drawing. + We ask the X server to attribute an Id to our font with the + function: +

        +
        +xcb_font_t xcb_generate_id (xcb_connection_t *c);
        +
        +
        +
      2. Opening a Font +

        + To open a font, we use the following function: +

        +
        +xcb_void_cookie_t xcb_open_font (xcb_connection_t *c,
        +                                 xcb_font_t        fid,
        +                                 uint16_t          name_len,
        +                                 const char       *name);
        +
        +

        + The fid parameter is the font Id + defined by xcb_generate_id() (see + above). The name parameter is the + name of the font you want to open. Use the command + xlsfonts in a terminal to know which + are the fonts available on your computer. The parameter + name_len is the length of the name + of the font (given by strlen()). +

        +
      3. Assigning a Font to a Graphic Context +

        + Once a font is opened, you have to create a Graphic Context + that will contain the informations about the color of the + foreground and the background used when you draw a text in a + Drawable. Here is an example of a Graphic Context that will + allow us to draw an opened font with a black foreground and a + white background:

        +
        +  /*
        +   * c is the connection
        +   * screen is the screen where the window is displayed
        +   * window is the window in which we will draw the text
        +   * font is the opened font
        +   */
        +
        +  uint32_t             value_list[3];
        +  xcb_gcontext_t       gc;
        +  uint32_t             mask;
        +
        +  gc = xcb_generate_id (c);
        +  mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
        +  value_list[0] = screen->black_pixel;
        +  value_list[1] = screen->white_pixel;
        +  value_list[2] = font;
        +  xcb_create_gc (c, gc, window, mask, value_list);
        +
        +  /* The font is not needed anymore, so we close it */
        +  xcb_close_font (c, font);
        +
        +
      4. Drawing text in a drawable +

        + To draw a text in a drawable, we use the following function: +

        +
        +xcb_void_cookie_t xcb_image_text_8 (xcb_connection_t *c,
        +                                    uint8_t           string_len,
        +                                    xcb_drawable_t    drawable,
        +                                    xcb_gcontext_t    gc,
        +                                    int16_t           x,
        +                                    int16_t           y,
        +                                    const char       *string);
        +
        +

        + The string parameter is the text to + draw. The location of the drawing is given by the parameters + x and y. + The base line of the text is exactly the parameter + y. +

        +
      5. Complete example

        - TODO: example for picking a font and displaying some text. - Even better, also demonstrate translating keypresses to text. + This example draw a text at 10 pixels (for the base line) of + the bottom of a window. Pressing the Esc key exits the program.

        +
        +#include <stdlib.h>
        +#include <stdio.h>
        +#include <string.h>
        +
        +#include <xcb/xcb.h>
        +
        +#define WIDTH 300
        +#define HEIGHT 100
        +
        +
        +
        +static xcb_gc_t gc_font_get (xcb_connection_t *c,
        +                             xcb_screen_t     *screen,
        +                             xcb_window_t      window,
        +                             const char       *font_name);
        +
        +static void text_draw (xcb_connection_t *c,
        +                       xcb_screen_t     *screen,
        +                       xcb_window_t      window,
        +                       int16_t           x1,
        +                       int16_t           y1,
        +                       const char       *label);
        +
        +static void
        +text_draw (xcb_connection_t *c,
        +           xcb_screen_t     *screen,
        +           xcb_window_t      window,
        +           int16_t           x1,
        +           int16_t           y1,
        +           const char       *label)
        +{
        +  xcb_void_cookie_t    cookie_gc;
        +  xcb_void_cookie_t    cookie_text;
        +  xcb_generic_error_t *error;
        +  xcb_gcontext_t       gc;
        +  uint8_t              length;
        +
        +  length = strlen (label);
        +
        +  gc = gc_font_get(c, screen, window, "7x13");
        +
        +  cookie_text = xcb_image_text_8_checked (c, length, window, gc,
        +                                          x1,
        +                                          y1, label);
        +  error = xcb_request_check (c, cookie_text);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  cookie_gc = xcb_free_gc (c, gc);
        +  error = xcb_request_check (c, cookie_gc);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +}
        +
        +static xcb_gc_t
        +gc_font_get (xcb_connection_t *c,
        +             xcb_screen_t     *screen,
        +             xcb_window_t      window,
        +             const char       *font_name)
        +{
        +  uint32_t             value_list[3];
        +  xcb_void_cookie_t    cookie_font;
        +  xcb_void_cookie_t    cookie_gc;
        +  xcb_generic_error_t *error;
        +  xcb_font_t           font;
        +  xcb_gcontext_t       gc;
        +  uint32_t             mask;
        +
        +  font = xcb_generate_id (c);
        +  cookie_font = xcb_open_font_checked (c, font,
        +                                       strlen (font_name),
        +                                       font_name);
        +
        +  error = xcb_request_check (c, cookie_font);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    return -1;
        +  }
        +
        +  gc = xcb_generate_id (c);
        +  mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
        +  value_list[0] = screen->black_pixel;
        +  value_list[1] = screen->white_pixel;
        +  value_list[2] = font;
        +  cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list);
        +  error = xcb_request_check (c, cookie_gc);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  cookie_font = xcb_close_font_checked (c, font);
        +  error = xcb_request_check (c, cookie_font);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  return gc;
        +}
        +
        +int main ()
        +{
        +  xcb_screen_iterator_t screen_iter;
        +  xcb_connection_t     *c;
        +  const xcb_setup_t    *setup;
        +  xcb_screen_t         *screen;
        +  xcb_generic_event_t  *e;
        +  xcb_generic_error_t  *error;
        +  xcb_void_cookie_t     cookie_window;
        +  xcb_void_cookie_t     cookie_map;
        +  xcb_window_t          window;
        +  uint32_t              mask;
        +  uint32_t              values[2];
        +  int                   screen_number;
        +
        +  /* getting the connection */
        +  c = xcb_connect (NULL, &screen_number);
        +  if (!c) {
        +    fprintf (stderr, "ERROR: can't connect to an X server\n");
        +    return -1;
        +  }
        +
        +  /* getting the current screen */
        +  setup = xcb_get_setup (c);
        +
        +  screen = NULL;
        +  screen_iter = xcb_setup_roots_iterator (setup);
        +  for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter))
        +    if (screen_number == 0)
        +      {
        +        screen = screen_iter.data;
        +        break;
        +      }
        +  if (!screen) {
        +    fprintf (stderr, "ERROR: can't get the current screen\n");
        +    xcb_disconnect (c);
        +    return -1;
        +  }
        +
        +  /* creating the window */
        +  window = xcb_generate_id (c);
        +  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
        +  values[0] = screen->white_pixel;
        +  values[1] =
        +    XCB_EVENT_MASK_KEY_RELEASE |
        +    XCB_EVENT_MASK_BUTTON_PRESS |
        +    XCB_EVENT_MASK_EXPOSURE |
        +    XCB_EVENT_MASK_POINTER_MOTION;
        +  cookie_window = xcb_create_window_checked (c,
        +                                             screen->root_depth,
        +                                             window, screen->root,
        +                                             20, 200, WIDTH, HEIGHT,
        +                                             0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
        +                                             screen->root_visual,
        +                                             mask, values);
        +  cookie_map = xcb_map_window_checked (c, window);
        +
        +  /* error managing */
        +  error = xcb_request_check (c, cookie_window);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    return -1;
        +  }
        +  error = xcb_request_check (c, cookie_map);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    return -1;
        +  }
        +
        +  xcb_flush(c);
        +
        +  while (1) {
        +    e = xcb_poll_for_event(c);
        +    if (e) {
        +      switch (e->response_type & ~0x80) {
        +      case XCB_EXPOSE: {
        +        char *text;
        +
        +        text = "Press ESC key to exit...";
        +        text_draw (c, screen, window, 10, HEIGHT - 10, text);
        +        break;
        +      }
        +      case XCB_KEY_RELEASE: {
        +        xcb_key_release_event_t *ev;
        +
        +        ev = (xcb_key_release_event_t *)e;
        +
        +        switch (ev->detail) {
        +          /* ESC */
        +        case 9:
        +          free (e);
        +          xcb_disconnect (c);
        +          return 0;
        +        }
        +      }
        +      }
        +      free (e);
        +    }
        +  }
        +
        +  return 0;
        +}
        +
    5. Interacting with the window manager

      @@ -2097,9 +2387,7 @@ typedef struct { Id. Their type are xcb_atom_t:

      -typedef struct {
      -    uint32_t xid;
      -} xcb_atom_t;
      +typedef uint32_t xcb_atom_t;
       

      To change the property of a window, we use the following @@ -2116,7 +2404,7 @@ xcb_void_cookie_t xcb_change_property (xcb_connection_t *c, /* Connection const void *data); /* Data */

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

      @@ -2651,7 +2939,7 @@ xcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (xcb_connecti latter case, each time the mouse moves onto your window, the screen color map will be replaced by your window's color map, and you'll see all the other windows on screen change their - colors into something quite bizzare. In fact, this is the + colors into something quite bizarre. In fact, this is the effect you get with X applications that use the "-install" command line option.

      @@ -2659,9 +2947,7 @@ xcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (xcb_connecti In XCB, a color map is (as often in X) an Id:

      -typedef struct {
      -    uint32_t xid;
      -} xcb_colormap_t;
      +typedef uint32_t xcb_colormap_t;
       

      In order to access the screen's default color map, you just @@ -2902,19 +3188,14 @@ main () of X pixmap in XCB is an Id like a window:

      -typedef struct {
      -    uint32_t xid;
      -} xcb_pixmap_t;
      +typedef uint32_t xcb_pixmap_t;
       

      - In order to make the difference between a window and a pixmap, - XCB introduces a drawable type, which is a union + Like Xlib, there is no difference between a Drawable, a Window + or a Pixmap:

      -typedef union {
      -    xcb_window_t window;
      -    xcb_pixmap_t pixmap;
      -} xcb_drawable_t;
      +typedef uint32_t xcb_drawable_t;
       

      in order to avoid confusion between a window and a pixmap. The @@ -3021,10 +3302,10 @@ xcb_void_cookie_t xcb_free_pixmap (xcb_connection_t *c, /* Pointer to the

    6. Messing with the mouse cursor

      It it possible to modify the shape of the mouse pointer (also - called the X pointer) when in certain states, as we otfen see in + called the X pointer) when in certain states, as we often see in programs. For example, a busy application would often display - the sand clock over its main window, to give the user a visual - hint that he should wait. Let's see how we can change the mouse + the hourglass cursor over its main window, to give the user a visual + hint that they should wait. Let's see how we can change the mouse cursor of our windows.

        @@ -3039,18 +3320,18 @@ xcb_void_cookie_t xcb_free_pixmap (xcb_connection_t *c, /* Pointer to the the function xcb_create_glyph_cursor:

        -xcb_void_cookie_t xcb_create_glyph_cursor_checked (xcb_connection_t *c,
        -                                                   xcb_cursor_t      cid,
        -                                                   xcb_font_t        source_font, /* font for the source glyph */
        -                                                   xcb_font_t        mask_font,   /* font for the mask glyph or XCB_NONE */
        -                                                   uint16_t          source_char, /* character glyph for the source */
        -                                                   uint16_t          mask_char,   /* character glyph for the mask */
        -                                                   uint16_t          fore_red,    /* red value for the foreground of the source */
        -                                                   uint16_t          fore_green,  /* green value for the foreground of the source */
        -                                                   uint16_t          fore_blue,   /* blue value for the foreground of the source */
        -                                                   uint16_t          back_red,    /* red value for the background of the source */
        -                                                   uint16_t          back_green,  /* green value for the background of the source */
        -                                                   uint16_t          back_blue)   /* blue value for the background of the source */
        +xcb_void_cookie_t xcb_create_glyph_cursor (xcb_connection_t *c,
        +                                           xcb_cursor_t      cid,
        +                                           xcb_font_t        source_font, /* font for the source glyph */
        +                                           xcb_font_t        mask_font,   /* font for the mask glyph or XCB_NONE */
        +                                           uint16_t          source_char, /* character glyph for the source */
        +                                           uint16_t          mask_char,   /* character glyph for the mask */
        +                                           uint16_t          fore_red,    /* red value for the foreground of the source */
        +                                           uint16_t          fore_green,  /* green value for the foreground of the source */
        +                                           uint16_t          fore_blue,   /* blue value for the foreground of the source */
        +                                           uint16_t          back_red,    /* red value for the background of the source */
        +                                           uint16_t          back_green,  /* green value for the background of the source */
        +                                           uint16_t          back_blue)   /* blue value for the background of the source */
         

        TODO: Describe source_char @@ -3060,7 +3341,7 @@ xcb_void_cookie_t xcb_create_glyph_cursor_checked (xcb_connection_t *c,

        So we first open that font (see Loading a Font) - and create the new cursor. As for every X ressource, we have to + and create the new cursor. As for every X resource, we have to ask for an X id with xcb_generate_id first:

        @@ -3116,7 +3397,7 @@ uint32_t value_list; /* The cursor is already created */ mask = XCB_CWCURSOR; -value_list = cursor.xid; +value_list = cursor; xcb_change_window_attributes (conn, window, mask, &value_list);

        @@ -3124,8 +3405,391 @@ xcb_change_window_attributes (conn, window, mask, &value_list);

      1. Complete example

        - TODO: to do... + The following example displays a window with a + button. When entering the window, the window cursor is changed + to an arrow. When clicking once on the button, the cursor is + changed to a hand. When clicking again on the button, the + cursor window gets back to the arrow. The Esc key exits the + application.

        +
        +#include <stdlib.h>
        +#include <stdio.h>
        +#include <string.h>
        +
        +#include <xcb/xcb.h>
        +
        +#define WIDTH 300
        +#define HEIGHT 150
        +
        +
        +
        +static xcb_gc_t gc_font_get (xcb_connection_t *c,
        +                             xcb_screen_t     *screen,
        +                             xcb_window_t      window,
        +                             const char       *font_name);
        +
        +static void button_draw (xcb_connection_t *c,
        +                         xcb_screen_t     *screen,
        +                         xcb_window_t      window,
        +                         int16_t           x1,
        +                         int16_t           y1,
        +                         const char       *label);
        +
        +static void text_draw (xcb_connection_t *c,
        +                       xcb_screen_t     *screen,
        +                       xcb_window_t      window,
        +                       int16_t           x1,
        +                       int16_t           y1,
        +                       const char       *label);
        +
        +static void cursor_set (xcb_connection_t *c,
        +                        xcb_screen_t     *screen,
        +                        xcb_window_t      window,
        +                        int               cursor_id);
        +
        +
        +static void
        +button_draw (xcb_connection_t *c,
        +             xcb_screen_t     *screen,
        +             xcb_window_t      window,
        +             int16_t           x1,
        +             int16_t           y1,
        +             const char       *label)
        +{
        +  xcb_point_t          points[5];
        +  xcb_void_cookie_t    cookie_gc;
        +  xcb_void_cookie_t    cookie_line;
        +  xcb_void_cookie_t    cookie_text;
        +  xcb_generic_error_t *error;
        +  xcb_gcontext_t       gc;
        +  int16_t              width;
        +  int16_t              height;
        +  uint8_t              length;
        +  int16_t              inset;
        +
        +  length = strlen (label);
        +  inset = 2;
        +
        +  gc = gc_font_get(c, screen, window, "7x13");
        +
        +  width = 7 * length + 2 * (inset + 1);
        +  height = 13 + 2 * (inset + 1);
        +  points[0].x = x1;
        +  points[0].y = y1;
        +  points[1].x = x1 + width;
        +  points[1].y = y1;
        +  points[2].x = x1 + width;
        +  points[2].y = y1 - height;
        +  points[3].x = x1;
        +  points[3].y = y1 - height;
        +  points[4].x = x1;
        +  points[4].y = y1;
        +  cookie_line = xcb_poly_line_checked (c, XCB_COORD_MODE_ORIGIN,
        +                                       window, gc, 5, points);
        +
        +  error = xcb_request_check (c, cookie_line);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't draw lines : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  cookie_text = xcb_image_text_8_checked (c, length, window, gc,
        +                                          x1 + inset + 1,
        +                                          y1 - inset - 1, label);
        +  error = xcb_request_check (c, cookie_text);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  cookie_gc = xcb_free_gc (c, gc);
        +  error = xcb_request_check (c, cookie_gc);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +}
        +
        +static void
        +text_draw (xcb_connection_t *c,
        +           xcb_screen_t     *screen,
        +           xcb_window_t      window,
        +           int16_t           x1,
        +           int16_t           y1,
        +           const char       *label)
        +{
        +  xcb_void_cookie_t    cookie_gc;
        +  xcb_void_cookie_t    cookie_text;
        +  xcb_generic_error_t *error;
        +  xcb_gcontext_t       gc;
        +  uint8_t              length;
        +
        +  length = strlen (label);
        +
        +  gc = gc_font_get(c, screen, window, "7x13");
        +
        +  cookie_text = xcb_image_text_8_checked (c, length, window, gc,
        +                                          x1,
        +                                          y1, label);
        +  error = xcb_request_check (c, cookie_text);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  cookie_gc = xcb_free_gc (c, gc);
        +  error = xcb_request_check (c, cookie_gc);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +}
        +
        +static xcb_gc_t
        +gc_font_get (xcb_connection_t *c,
        +             xcb_screen_t     *screen,
        +             xcb_window_t      window,
        +             const char       *font_name)
        +{
        +  uint32_t             value_list[3];
        +  xcb_void_cookie_t    cookie_font;
        +  xcb_void_cookie_t    cookie_gc;
        +  xcb_generic_error_t *error;
        +  xcb_font_t           font;
        +  xcb_gcontext_t       gc;
        +  uint32_t             mask;
        +
        +  font = xcb_generate_id (c);
        +  cookie_font = xcb_open_font_checked (c, font,
        +                                       strlen (font_name),
        +                                       font_name);
        +
        +  error = xcb_request_check (c, cookie_font);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    return -1;
        +  }
        +
        +  gc = xcb_generate_id (c);
        +  mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
        +  value_list[0] = screen->black_pixel;
        +  value_list[1] = screen->white_pixel;
        +  value_list[2] = font;
        +  cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list);
        +  error = xcb_request_check (c, cookie_gc);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  cookie_font = xcb_close_font_checked (c, font);
        +  error = xcb_request_check (c, cookie_font);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  return gc;
        +}
        +
        +static void
        +cursor_set (xcb_connection_t *c,
        +            xcb_screen_t     *screen,
        +            xcb_window_t      window,
        +            int               cursor_id)
        +{
        +  uint32_t             values_list[3];
        +  xcb_void_cookie_t    cookie_font;
        +  xcb_void_cookie_t    cookie_gc;
        +  xcb_generic_error_t *error;
        +  xcb_font_t           font;
        +  xcb_cursor_t         cursor;
        +  xcb_gcontext_t       gc;
        +  uint32_t             mask;
        +  uint32_t             value_list;
        +
        +  font = xcb_generate_id (c);
        +  cookie_font = xcb_open_font_checked (c, font,
        +                                       strlen ("cursor"),
        +                                       "cursor");
        +  error = xcb_request_check (c, cookie_font);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  cursor = xcb_generate_id (c);
        +  xcb_create_glyph_cursor (c, cursor, font, font,
        +                           cursor_id, cursor_id + 1,
        +                           0, 0, 0,
        +                           0, 0, 0);
        +
        +  gc = xcb_generate_id (c);
        +  mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
        +  values_list[0] = screen->black_pixel;
        +  values_list[1] = screen->white_pixel;
        +  values_list[2] = font;
        +  cookie_gc = xcb_create_gc_checked (c, gc, window, mask, values_list);
        +  error = xcb_request_check (c, cookie_gc);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +
        +  mask = XCB_CW_CURSOR;
        +  value_list = cursor;
        +  xcb_change_window_attributes (c, window, mask, &value_list);
        +
        +  xcb_free_cursor (c, cursor);
        +
        +  cookie_font = xcb_close_font_checked (c, font);
        +  error = xcb_request_check (c, cookie_font);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    exit (-1);
        +  }
        +}
        +
        +int main ()
        +{
        +  xcb_screen_iterator_t screen_iter;
        +  xcb_connection_t     *c;
        +  const xcb_setup_t    *setup;
        +  xcb_screen_t         *screen;
        +  xcb_generic_event_t  *e;
        +  xcb_generic_error_t  *error;
        +  xcb_void_cookie_t     cookie_window;
        +  xcb_void_cookie_t     cookie_map;
        +  xcb_window_t          window;
        +  uint32_t              mask;
        +  uint32_t              values[2];
        +  int                   screen_number;
        +  uint8_t               is_hand = 0;
        +
        +  /* getting the connection */
        +  c = xcb_connect (NULL, &screen_number);
        +  if (!c) {
        +    fprintf (stderr, "ERROR: can't connect to an X server\n");
        +    return -1;
        +  }
        +
        +  /* getting the current screen */
        +  setup = xcb_get_setup (c);
        +
        +  screen = NULL;
        +  screen_iter = xcb_setup_roots_iterator (setup);
        +  for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter))
        +    if (screen_number == 0)
        +      {
        +        screen = screen_iter.data;
        +        break;
        +      }
        +  if (!screen) {
        +    fprintf (stderr, "ERROR: can't get the current screen\n");
        +    xcb_disconnect (c);
        +    return -1;
        +  }
        +
        +  /* creating the window */
        +  window = xcb_generate_id (c);
        +  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
        +  values[0] = screen->white_pixel;
        +  values[1] =
        +    XCB_EVENT_MASK_KEY_RELEASE |
        +    XCB_EVENT_MASK_BUTTON_PRESS |
        +    XCB_EVENT_MASK_EXPOSURE |
        +    XCB_EVENT_MASK_POINTER_MOTION;
        +  cookie_window = xcb_create_window_checked (c,
        +                                             screen->root_depth,
        +                                             window, screen->root,
        +                                             20, 200, WIDTH, HEIGHT,
        +                                             0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
        +                                             screen->root_visual,
        +                                             mask, values);
        +  cookie_map = xcb_map_window_checked (c, window);
        +
        +  /* error managing */
        +  error = xcb_request_check (c, cookie_window);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    return -1;
        +  }
        +  error = xcb_request_check (c, cookie_map);
        +  if (error) {
        +    fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code);
        +    xcb_disconnect (c);
        +    return -1;
        +  }
        +
        +  cursor_set (c, screen, window, 68);
        +
        +  xcb_flush(c);
        +
        +  while (1) {
        +    e = xcb_poll_for_event(c);
        +    if (e) {
        +      switch (e->response_type & ~0x80) {
        +      case XCB_EXPOSE: {
        +        char *text;
        +
        +        text = "click here to change cursor";
        +        button_draw (c, screen, window,
        +                     (WIDTH - 7 * strlen(text)) / 2,
        +                     (HEIGHT - 16) / 2, text);
        +
        +        text = "Press ESC key to exit...";
        +        text_draw (c, screen, window, 10, HEIGHT - 10, text);
        +        break;
        +      }
        +      case XCB_BUTTON_PRESS: {
        +        xcb_button_press_event_t *ev;
        +        int                       length;
        +
        +        ev = (xcb_button_press_event_t *)e;
        +        length = strlen ("click here to change cursor");
        +
        +        if ((ev->event_x >= (WIDTH - 7 * length) / 2) &&
        +            (ev->event_x <= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) &&
        +            (ev->event_y >= (HEIGHT - 16) / 2 - 19) &&
        +            (ev->event_y <= ((HEIGHT - 16) / 2)))
        +          is_hand = 1 - is_hand;
        +
        +        is_hand ? cursor_set (c, screen, window, 58) : cursor_set (c, screen, window, 68);
        +      }
        +      case XCB_KEY_RELEASE: {
        +        xcb_key_release_event_t *ev;
        +
        +        ev = (xcb_key_release_event_t *)e;
        +
        +        switch (ev->detail) {
        +          /* ESC */
        +        case 9:
        +          free (e);
        +          xcb_disconnect (c);
        +          return 0;
        +        }
        +      }
        +      }
        +      free (e);
        +    }
        +  }
        +
        +  return 0;
        +}
        +
    7. Translation of basic Xlib functions and macros

      @@ -3438,8 +4102,7 @@ default_screen = screen_of_display (c, screen_default_nbr); /* default_screen contains now the default root window, or a NULL window if no screen is found */

    8. RootWindow / RootWindowOfScreen -

      -

      +
       xcb_connection_t *c;
       xcb_screen_t     *screen;
      @@ -3529,7 +4192,7 @@ if (screen) {
       
           visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
           for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) {
      -      if (screen->root_visual.id == visual_iter.data->visual_id.id) {
      +      if (screen->root_visual == visual_iter.data->visual_id) {
               visual_type = visual_iter.data;
               break;
             }