X-Git-Url: http://git.demorecorder.com/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=doc%2Ftutorial%2Findex.html;h=c5404263f76764e66f28adc74ad0cbd3618268d6;hb=25e59ccc0dc8baf344145d6d739229e8120330db;hp=e39ee2ee8e01908a9f5849c94ef22e7f9ae9a48b;hpb=818811a7ac660e46d0dca1cbf9e53ad0475af330;p=free-sw%2Fxcb%2Flibxcb diff --git a/doc/tutorial/index.html b/doc/tutorial/index.html index e39ee2e..c540426 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
      @@ -177,8 +178,9 @@ 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 @@ -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`
      -

      -

      +
    1. 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: @@ -776,7 +775,7 @@ main () { xcb_connection_t *c; xcb_screen_t *screen; - xcb_drawable_t win; + xcb_window_t win; /* Open the connection to the X server */ c = xcb_connect (NULL, NULL); @@ -785,12 +784,12 @@ main () screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; /* Ask for our window's Id */ - win.window = xcb_generate_id(c); + win = xcb_generate_id(c); /* Create the window */ xcb_create_window (c, /* Connection */ XCB_COPY_FROM_PARENT, /* depth (same as root)*/ - win.window, /* window Id */ + win, /* window Id */ screen->root, /* parent window */ 0, 0, /* x, y */ 150, 150, /* width, height */ @@ -800,7 +799,7 @@ main () 0, NULL); /* masks, not used yet */ /* Map the window on the screen */ - xcb_map_window (c, win.window); + xcb_map_window (c, win); /* Make sure commands are sent before we pause, so window is shown */ xcb_flush (c); @@ -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 @@ -931,7 +928,7 @@ main () screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; /* Create a black graphic context for drawing in the foreground */ - win.window = screen->root; + win = screen->root; black = xcb_generate_id (c); mask = XCB_GC_FOREGROUND; value[0] = screen->black_pixel; @@ -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 */
      @@ -1291,7 +1289,7 @@ main ()
         screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
       
         /* Create black (foreground) graphic context */
      -  win.window = screen->root;
      +  win = screen->root;
       
         foreground = xcb_generate_id (c);
         mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
      @@ -1300,7 +1298,7 @@ main ()
         xcb_create_gc (c, foreground, win, mask, values);
       
         /* Ask for our window's Id */
      -  win.window = xcb_generate_id(c);
      +  win = xcb_generate_id(c);
       
         /* Create the window */
         mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
      @@ -1308,7 +1306,7 @@ main ()
         values[1] = XCB_EVENT_MASK_EXPOSURE;
         xcb_create_window (c,                             /* Connection          */
                            XCB_COPY_FROM_PARENT,          /* depth               */
      -                     win.window,                    /* window Id           */
      +                     win,                           /* window Id           */
                            screen->root,                  /* parent window       */
                            0, 0,                          /* x, y                */
                            150, 150,                      /* width, height       */
      @@ -1318,7 +1316,7 @@ main ()
                            mask, values);                 /* masks */
       
         /* Map the window on the screen */
      -  xcb_map_window (c, win.window);
      +  xcb_map_window (c, win);
       
       
         /* We flush the request */
      @@ -1391,8 +1389,8 @@ main ()
               
         mask = XCB_CW_EVENT_MASK;
         valwin[0] = XCB_EVENT_MASK_EXPOSURE;
      -  win.window = xcb_generate_id (c);
      -  xcb_create_window (c, depth, win.window, root->root,
      +  win = xcb_generate_id (c);
      +  xcb_create_window (c, depth, win, root->root,
                            0, 0, 150, 150, 10,
                            XCB_WINDOW_CLASS_INPUT_OUTPUT, root->root_visual,
                            mask, valwin);
      @@ -1405,8 +1403,8 @@ main ()
               
         mask = XCB_CW_EVENT_MASK;
         valwin[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS;
      -  win.window = xcb_generate_id (c);
      -  xcb_create_window (c, depth, win.window, root->root,
      +  win = xcb_generate_id (c);
      +  xcb_create_window (c, depth, win, root->root,
                            0, 0, 150, 150, 10,
                            XCB_WINDOW_CLASS_INPUT_OUTPUT, root->root_visual,
                            mask, valwin);
      @@ -1916,7 +1914,7 @@ main ()
       {
         xcb_connection_t    *c;
         xcb_screen_t        *screen;
      -  xcb_drawable_t       win;
      +  xcb_window_t         win;
         xcb_generic_event_t *e;
         uint32_t             mask = 0;
         uint32_t             values[2];
      @@ -1928,7 +1926,7 @@ main ()
         screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
       
         /* Ask for our window's Id */
      -  win.window = xcb_generate_id (c);
      +  win = xcb_generate_id (c);
       
         /* Create the window */
         mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
      @@ -1939,7 +1937,7 @@ main ()
                     XCB_EVENT_MASK_KEY_PRESS      | XCB_EVENT_MASK_KEY_RELEASE;
         xcb_create_window (c,                             /* Connection          */
                            0,                             /* depth               */
      -                     win.window,                    /* window Id           */
      +                     win,                           /* window Id           */
                            screen->root,                  /* parent window       */
                            0, 0,                          /* x, y                */
                            150, 150,                      /* width, height       */
      @@ -1949,7 +1947,7 @@ main ()
                            mask, values);                 /* masks */
       
         /* Map the window on the screen */
      -  xcb_map_window (c, win.window);
      +  xcb_map_window (c, win);
       
         xcb_flush (c);
       
      @@ -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 exemple 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

        - TODO: example for picking a font and displaying some text. - Even better, also demonstrate translating keypresses to text. + 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 +

        + 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;
        +}
        +
    2. 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 @@ -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 @@ -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 @@ -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);

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

    4. 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;
      +}
      +
  • 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 */

  • 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;
           }
    @@ -3561,7 +4224,7 @@ if (screen) {
       uint32_t       values[2];
     
       gc = xcb_generate_id (c);
    -  draw.window = screen->root;
    +  draw = screen->root;
       mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
       values[0] = screen->black_pixel;
       values[1] = screen->white_pixel;