This tutorial is based on the
Xlib Tutorial
written by Guy Keren. The
author allowed me to take some parts of his text, mainly the text which
deals with the X Windows generality.

This tutorial is intended for people who want to start to program
with the XCB
library. keep in mind that XCB, like the
Xlib
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,
EWL,
ETK, or use
Cairo.
However,
we need to start somewhere. More than this, knowing how things
work down below is never a bad idea.

After reading this tutorial, one should be able to write very
simple graphical programs, but not programs with decent user
interfaces. For such programs, one of the previously mentioned
libraries should be used.

But what is XCB? Xlib has been
the standard C binding for the X
Window System protocol for many years now. It is an
excellent piece of work, but there are applications for which it
is not ideal, for example:

Small platforms: Xlib is a large piece of code, and
it's difficult to make it smaller

Latency hiding: Xlib requests requiring a reply are
effectively synchronous: they block until the reply appears,
whether the result is needed immediately or not.

Direct access to the protocol: Xlib does quite a
bit of caching, layering, and similar optimizations. While this
is normally a feature, it makes it difficult to simply emit
specified X protocol requests and process specific
responses.

Threaded applications: While Xlib does attempt to
support multithreading, the API makes this difficult and
error-prone.

New extensions: The Xlib infrastructure provides
limited support for the new creation of X extension client side
code.

For these reasons, among others, XCB, an X C binding, has been
designed to solve the above problems and thus provide a base for

The X Window System was developed with one major goal:
flexibility. The idea was that the way things look is one thing,
but the way things work is another matter. Thus, the lower
levels provide the tools required to draw windows, handle user
input, allow drawing graphics using colors (or black and white
screens), etc. To this point, a decision was made to separate
the system into two parts. A client that decides what to do, and
a server that actually draws on the screen and reads user input
in order to send it to the client for processing.

This model is the complete opposite of what is used to when
dealing with clients and servers. In our case, the user sits
near the machine controlled by the server, while the client
might be running on a remote machine. The server controls the
screens, mouse and keyboard. A client may connect to the server,
request that it draws a window (or several windows), and ask the
server to send it any input the user sends to these
windows. Thus, several clients may connect to a single X server
(one might be running mail software, one running a WWW
browser, etc). When input is sent by the user to some window,
the server sends a message to the client controlling this window
for processing. The client decides what to do with this input,
and sends the server requests for drawing in the window.

The whole session is carried out using the X message
protocol. This protocol was originally carried over the TCP/IP
protocol suite, allowing the client to run on any machine
connected to the same network that the server is. Later on, the
X servers were extended to allow clients running on the local
machine with more optimized access to the server (note that an X
protocol message may be several hundreds of KB in size), such as
using shared memory, or using Unix domain sockets (a method for
creating a logical channel on a Unix system between two processes).

Unlike conventional computer programs, that carry some serial
nature, a GUI program usually uses an asynchronous programming
model, also known as "event-driven programming". This means that
that program mostly sits idle, waiting for events sent by the X
server, and then acts upon these events. An event may say "The
user pressed the 1st button mouse in spot (x,y)", or "The window
you control needs to be redrawn". In order for the program to be
responsive to the user input, as well as to refresh requests, it
needs to handle each event in a rather short period of time
(e.g. less that 200 milliseconds, as a rule of thumb).

This also implies that the program may not perform operations
that might take a long time while handling an event (such as
opening a network connection to some remote server, or
connecting to a database server, or even performing a long file
copy operation). Instead, it needs to perform all these
operations in an asynchronous manner. This may be done by using
various asynchronous models to perform the longish operations,
or by performing them in a different process or thread.

So the way a GUI program looks is something like that:

Perform initialization routines.

Connect to the X server.

Perform X-related initialization.

While not finished:

Receive the next event from the X server.

Handle the event, possibly sending various drawing
requests to the X server.

XCB has been created to eliminate the need for
programs to actually implement the X protocol layer. This
library gives a program a very low-level access to any X
server. Since the protocol is standardized, a client using any
implementation of XCB may talk with any X server (the same
occurs for Xlib, of course). We now give a brief description of
the basic XCB notions. They will be detailed later.

The major notion of using XCB is the X Connection. This is a
structure representing the connection we have open with a
given X server. It hides a queue of messages coming from the
server, and a queue of pending requests that our client
intends to send to the server. In XCB, this structure is named
'xcb_connection_t'. It is analogous to the Xlib Display.
When we open a connection to an X server, the
library returns a pointer to such a structure. Later, we
supply this pointer to any XCB function that should send
messages to the X server or receive messages from this server.

To ask for information from the X server, we have to make a request
and ask for a reply. With Xlib, these two tasks are
automatically done: Xlib locks the system, sends a request,
waits for a reply from the X server and unlocks. This is
annoying, especially if one makes a lot of requests to the X
server. Indeed, Xlib has to wait for the end of a reply
before asking for the next request (because of the locks that
Xlib sends). For example, here is a time-line of N=4
requests/replies with Xlib, with a round-trip latency
T_round_trip that is 5 times long as the time required
to write or read a request/reply (T_write/T_read):

W-----RW-----RW-----RW-----R

W: Writing request

-: Stalled, waiting for data

R: Reading reply

The total time is N * (T_write + T_round_trip + T_read).

With XCB, we can suppress most of the round-trips as the
requests and the replies are not locked. We usually send a
request, then XCB returns to us a cookie, which is an
identifier. Then, later, we ask for a reply using this
cookie and XCB returns a
pointer to that reply. Hence, with XCB, we can send a lot of
requests, and later in the program, ask for all the replies
when we need them. Here is the time-line for 4
requests/replies when we use this property of XCB:

WWWW--RRRR

The total time is N * T_write + max (0, T_round_trip - (N-1) *
T_write) + N * T_read. Which can be considerably faster than
all those Xlib round-trips.

Here is a program that computes the time to create 500 atoms
with Xlib and XCB. It shows the Xlib way, the bad XCB way
(which is similar to Xlib) and the good XCB way. On my
computer, XCB is 25 times faster than Xlib.

When we perform various drawing operations (graphics, text,
etc), we may specify various options for controlling how the
data will be drawn (what foreground and background colors to
use, how line edges will be connected, what font to use when
drawing some text, etc). In order to avoid the need to supply
hundreds of parameters to each drawing function, a graphical
context structure is used. We set the various drawing options
in this structure, and then we pass a pointer to this
structure to any drawing routines. This is rather handy, as we
often need to perform several drawing requests with the same
options. Thus, we would initialize a graphical context, set
the desired options, and pass this structure to all drawing
functions.

Note that graphic contexts have no client-side structure in
XCB, they're just XIDs. Xlib has a client-side structure
because it caches the GC contents so it can avoid making
redundant requests, but of course XCB doesn't do that.

A structure is used to pass events received from the X
server. XCB supports exactly the events specified in the
protocol (33 events). This structure contains the type
of event received (including a bit for whether it came
from the server or another client), as well as the data associated with the
event (e.g. position on the screen where the event was
generated, mouse button associated with the event, region of
the screen associated with a "redraw" event, etc). The way to
read the event's data depends on the event type.

An X program first needs to open the connection to the X
server. There is a function that opens a connection. It requires
the display name, or NULL. In the latter case, the display name
will be the one in the environment variable DISPLAY.

xcb_connection_t *xcb_connect (constchar *displayname,
int *screenp);

The second parameter returns the screen number used for the
connection. The returned structure describes an XCB connection
and is opaque. Here is how the connection can be opened:

Once we have opened a connection to an X server, we should check some
basic information about it: what screens it has, what is the
size (width and height) of the screen, how many colors it
supports (black and white ? grey scale ?, 256 colors ? more ?),
and so on. We get such information from the xcb_screen_t
structure:

The fact that we created the window does not mean that it will
be drawn on screen. By default, newly created windows are not
mapped on the screen (they are invisible). In order to make our
window visible, we use the function xcb_map_window(), whose
prototype is

In this code, you see one more function - xcb_flush(), not explained
yet. It is used to flush all the pending requests. More
precisely, there are 2 functions that do such things. The first
one is xcb_flush():

int xcb_flush (xcb_connection_t *c);

This function flushes all pending requests to the X server (much
like the fflush() function is used to
flush standard output). The second function is
xcb_aux_sync():

int xcb_aux_sync (xcb_connection_t *c);

This functions also flushes all pending requests to the X
server, and then waits until the X server finishing processing
these requests. In a normal program, this will not be necessary
(we'll see why when we get to write a normal X program), but for
now, we put it there.

The window that is created by the above code has a non defined
background. This one can be set to a specific color,
thanks to the two last parameters of
xcb_create_window(), which are not
described yet. See the subsections
Configuring a window or
Registering for event types using event masks
for examples on how to use these parameters. In addition, as no
events are handled, you have to make a Ctrl-C to interrupt the
program.

TODO: one should tell what these functions return and
about the generic error

Drawing in a window can be done using various graphical
functions (drawing pixels, lines, rectangles, etc). In order to
draw in a window, we first need to define various general
drawing parameters (what line width to use, which color to draw
with, etc). This is done using a graphical context.

As we said, a graphical context defines several attributes to
be used with the various drawing functions. For this, we
define a graphical context. We can use more than one graphical
context with a single window, in order to draw in multiple
styles (different colors, different line widths, etc). In XCB,
a Graphics Context is, as a window, characterized by an Id:

typedef uint32_t xcb_gcontext_t;

We first ask the X server to attribute an Id to our graphic
context with this function:

xcb_gcontext_t xcb_generate_id (xcb_connection_t *c);

Then, we set the attributes of the graphic context with this function:

Note should be taken regarding the role of "value_mask" and
"value_list" in the prototype of xcb_create_gc(). Since a
graphic context has many attributes, and since we often just
want to define a few of them, we need to be able to tell the
xcb_create_gc() which attributes we
want to set. This is what the "value_mask" parameter is
for. We then use the "value_list" parameter to specify actual
values for the attribute we defined in "value_mask". Thus, for
each constant used in "value_list", we will use the matching
constant in "value_mask". In this case, we define a graphic
context with one attribute: when drawing (a point, a line,
etc), the foreground color will be black. The rest of the
attributes of this graphic context will be set to their
default values.

Once we have allocated a Graphic Context, we may need to
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:

The value_mask parameter could take
any combination of these masks from the xcb_gc_t enumeration:

XCB_GC_FUNCTION

XCB_GC_PLANE_MASK

XCB_GC_FOREGROUND

XCB_GC_BACKGROUND

XCB_GC_LINE_WIDTH

XCB_GC_LINE_STYLE

XCB_GC_CAP_STYLE

XCB_GC_JOIN_STYLE

XCB_GC_FILL_STYLE

XCB_GC_FILL_RULE

XCB_GC_TILE

XCB_GC_STIPPLE

XCB_GC_TILE_STIPPLE_ORIGIN_X

XCB_GC_TILE_STIPPLE_ORIGIN_Y

XCB_GC_FONT

XCB_GC_SUBWINDOW_MODE

XCB_GC_GRAPHICS_EXPOSURES

XCB_GC_CLIP_ORIGIN_X

XCB_GC_CLIP_ORIGIN_Y

XCB_GC_CLIP_MASK

XCB_GC_DASH_OFFSET

XCB_GC_DASH_LIST

XCB_GC_ARC_MODE

It is possible to set several attributes at the same
time (for example setting the attributes of a font and the
color which will be used to display a string), by OR'ing these
values in value_mask. Then
value_list has to be an array which
lists the value for the respective attributes. These values
must be in the same order as masks listed above. See Subsection
Drawing with a color to have an example.

TODO: set the links of the 3 subsections, once they will
be written :)

After we have created a Graphic Context, we can draw on a
window using this Graphic Context, with a set of XCB
functions, collectively called "drawing primitives". Let see
how they are used.

To draw a point, or several points, we use

xcb_void_cookie_t xcb_poly_point (xcb_connection_t *c, /* The connection to the X server */
uint8_t coordinate_mode, /* Coordinate mode, usually set to XCB_COORD_MODE_ORIGIN */
xcb_drawable_t drawable, /* The drawable on which we want to draw the point(s) */
xcb_gcontext_t gc, /* The Graphic Context we use to draw the point(s) */
uint32_t points_len, /* The number of points */
const xcb_point_t *points); /* An array of points */

The coordinate_mode parameter
specifies the coordinate mode. Available values are

XCB_COORD_MODE_ORIGIN

XCB_COORD_MODE_PREVIOUS

If XCB_COORD_MODE_PREVIOUS is used, then all points but the first one
are relative to the immediately previous point.

The xcb_point_t type is just a
structure with two fields (the coordinates of the point):

typedef struct {
int16_t x;
int16_t y;
} xcb_point_t;

You could see an example in xpoints.c. TODO Set the link.

To draw a line, or a polygonal line, we use

xcb_void_cookie_t xcb_poly_line (xcb_connection_t *c, /* The connection to the X server */
uint8_t coordinate_mode, /* Coordinate mode, usually set to XCB_COORD_MODE_ORIGIN */
xcb_drawable_t drawable, /* The drawable on which we want to draw the line(s) */
xcb_gcontext_t gc, /* The Graphic Context we use to draw the line(s) */
uint32_t points_len, /* The number of points in the polygonal line */
const xcb_point_t *points); /* An array of points */

This function will draw the line between the first and the
second points, then the line between the second and the third
points, and so on.

To draw a segment, or several segments, we use

xcb_void_cookie_t xcb_poly_segment (xcb_connection_t *c, /* The connection to the X server */
xcb_drawable_t drawable, /* The drawable on which we want to draw the segment(s) */
xcb_gcontext_t gc, /* The Graphic Context we use to draw the segment(s) */
uint32_t segments_len, /* The number of segments */
const xcb_segment_t *segments); /* An array of segments */

The xcb_segment_t type is just a
structure with four fields (the coordinates of the two points
that define the segment):

xcb_void_cookie_t xcb_poly_rectangle (xcb_connection_t *c, /* The connection to the X server */
xcb_drawable_t drawable, /* The drawable on which we want to draw the rectangle(s) */
xcb_gcontext_t gc, /* The Graphic Context we use to draw the rectangle(s) */
uint32_t rectangles_len, /* The number of rectangles */
const xcb_rectangle_t *rectangles); /* An array of rectangles */

The xcb_rectangle_t type is just a
structure with four fields (the coordinates of the top-left
corner of the rectangle, and its width and height):

xcb_void_cookie_t xcb_poly_arc (xcb_connection_t *c, /* The connection to the X server */
xcb_drawable_t drawable, /* The drawable on which we want to draw the arc(s) */
xcb_gcontext_t gc, /* The Graphic Context we use to draw the arc(s) */
uint32_t arcs_len, /* The number of arcs */
const xcb_arc_t *arcs); /* An array of arcs */

Note: the angles are expressed in units of 1/64 of a degree,
so to have an angle of 90 degrees, starting at 0,
angle1 = 0 and
angle2 = 90 << 6. Positive angles
indicate counterclockwise motion, while negative angles
indicate clockwise motion.

The corresponding function which fill inside the geometrical
object are listed below, without further explanation, as they
are used as the above functions.

To illustrate these functions, here is an example that draws
four points, a polygonal line, two segments, two rectangles
and two arcs. Remark that we use events for the first time, as
an introduction to the next section.

In an X program, everything is driven by events. Event painting
on the screen is sometimes done as a response to an event (an
Expose event). If part of a program's
window that was hidden, gets exposed (e.g. the window was raised
above other widows), the X server will send an "expose" event to
let the program know it should repaint that part of the
window. User input (key presses, mouse movement, etc) is also
received as a set of events.

During the creation of a window, you should give it what kind
of events it wishes to receive. Thus, you may register for
various mouse (also called pointer) events, keyboard events,
expose events, and so on. This is done for optimizing the
server-to-client connection (i.e. why send a program (that
might even be running at the other side of the globe) an event
it is not interested in ?)

In XCB, you use the "value_mask" and "value_list" data in the
xcb_create_window() function to
register for events. Here is how we register for
Expose event when creating a window:

XCB_EVENT_MASK_EXPOSURE is a constant defined
in the xcb_event_mask_t enumeration in the "xproto.h" header file. If we wanted to register for several
event types, we can logically "or" them, as follows:

If the window has already been created, we can use the
xcb_configure_window() 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
configures the window to receive the
Expose and
ButtonPress events:

Note: A common bug programmers do 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
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.

After we have registered for the event types we are interested
in, we need to enter a loop of receiving events and handling
them. There are two ways to receive events: a blocking way and
a non-blocking way:

xcb_wait_for_event (xcb_connection_t *c)
is the blocking way. It waits (so blocks...) until an event is
queued in the X server. Then it retrieves it into a newly
allocated structure (it dequeues it from the queue) and returns
it. This structure has to be freed. The function returns
NULL if an error occurs.

xcb_poll_for_event (xcb_connection_t *c, int
*error) is the non-blocking way. It looks at the event
queue and returns (and dequeues too) an existing event into
a newly allocated structure. This structure has to be
freed. It returns NULL if there is
no event. If an error occurs, the parameter error will be filled with the error
status.

There are various ways to write such a loop. We present two
ways to write such a loop, with the two functions above. The
first one uses xcb_wait_for_event_t, which
is similar to an event Xlib loop using only XNextEvent:

The events are managed in the same way as with xcb_wait_for_event_t.
Obviously, we will need to give the user some way of
terminating the program. This is usually done by handling a
special "quit" event, as we will soon see.

The Expose event is one of the most
basic (and most used) events an application may receive. It
will be sent to us in one of several cases:

A window that covered part of our window has moved
away, exposing part (or all) of our window.

Our window was raised above other windows.

Our window mapped for the first time.

Our window was de-iconified.

You should note the implicit assumption hidden here: the
contents of our window is lost when it is being obscured
(covered) by either windows. One may wonder why the X server
does not save this contents. The answer is: to save
memory. After all, the number of windows on a display at a
given time may be very large, and storing the contents of all
of them might require a lot of memory. Actually, there is a
way to tell the X server to store the contents of a window in
special cases, as we will see later.

When we get an Expose event, we
should take the event's data from the members of the following
structure:

typedef struct {
uint8_t response_type; /* The type of the event, here it is XCB_EXPOSE */
uint8_t pad0;
uint16_t sequence;
xcb_window_t window; /* The Id of the window that receives the event (in case */
/* our application registered for events on several windows */
uint16_t x; /* The x coordinate of the top-left part of the window that needs to be redrawn */
uint16_t y; /* The y coordinate of the top-left part of the window that needs to be redrawn */
uint16_t width; /* The width of the part of the window that needs to be redrawn */
uint16_t height; /* The height of the part of the window that needs to be redrawn */
uint16_t count;
} xcb_expose_event_t;

User input traditionally comes from two sources: the mouse
and the keyboard. Various event types exist to notify us of
user input (a key being presses on the keyboard, a key being
released on the keyboard, the mouse moving over our window,
the mouse entering (or leaving) our window, and so on.

The first event type we will deal with is a mouse
button-press (or button-release) event in our window. In
order to register to such an event type, we should add one
(or more) of the following masks when we create our window:

XCB_EVENT_MASK_BUTTON_PRESS: notify us
of any button that was pressed in one of our windows.

XCB_EVENT_MASK_BUTTON_RELEASE: notify us
of any button that was released in one of our windows.

The structure to be checked for in our events loop is the
same for these two events, and is the following:

typedef struct {
uint8_t response_type; /* The type of the event, here it is xcb_button_press_event_t or xcb_button_release_event_t */
xcb_button_t detail;
uint16_t sequence;
xcb_timestamp_t time; /* Time, in milliseconds the event took place in */
xcb_window_t root;
xcb_window_t event;
xcb_window_t child;
int16_t root_x;
int16_t root_y;
int16_t event_x; /* The x coordinate where the mouse has been pressed in the window */
int16_t event_y; /* The y coordinate where the mouse has been pressed in the window */
uint16_t state; /* A mask of the buttons (or keys) during the event */
uint8_t same_screen;
} xcb_button_press_event_t;
typedef xcb_button_press_event_t xcb_button_release_event_t;

The time field may be used to calculate "double-click"
situations by an application (e.g. if the mouse button was
clicked two times in a duration shorter than a given amount
of time, assume this was a double click).

The state field is a mask of the buttons held down during
the event. It is a bitwise OR of any of the following (from the xcb_button_mask_t and
xcb_mod_mask_t enumerations):

XCB_BUTTON_MASK_1

XCB_BUTTON_MASK_2

XCB_BUTTON_MASK_3

XCB_BUTTON_MASK_4

XCB_BUTTON_MASK_5

XCB_MOD_MASK_SHIFT

XCB_MOD_MASK_LOCK

XCB_MOD_MASK_CONTROL

XCB_MOD_MASK_1

XCB_MOD_MASK_2

XCB_MOD_MASK_3

XCB_MOD_MASK_4

XCB_MOD_MASK_5

Their names are self explanatory, where the first 5 refer to
the mouse buttons that are being pressed, while the rest
refer to various "special keys" that are being pressed (Mod1
is usually the 'Alt' key or the 'Meta' key).

TODO: Problem: it seems that the state does not
change when clicking with various buttons.

Similar to mouse button press and release events, we also
can be notified of various mouse movement events. These can
be split into two families. One is of mouse pointer
movement while no buttons are pressed, and the second is a
mouse pointer motion while one (or more) of the buttons are
pressed (this is sometimes called "a mouse drag operation",
or just "dragging"). The following event masks may be added
during the creation of our window:

XCB_EVENT_MASK_POINTER_MOTION: events of
the pointer moving in one of the windows controlled by our
application, while no mouse button is held pressed.

XCB_EVENT_MASK_BUTTON_MOTION: Events of
the pointer moving while one or more of the mouse buttons
is held pressed.

XCB_EVENT_MASK_BUTTON_1_MOTION: same as
XCB_EVENT_MASK_BUTTON_MOTION, but only when
the 1st mouse button is held pressed.

Another type of event that applications might be interested
in, is a mouse pointer entering a window the program
controls, or leaving such a window. Some programs use these
events to show the user that the application is now in
focus. In order to register for such an event type, we
should add one (or more) of the following masks when we
create our window:

xcb_event_enter_window_t: notify us
when the mouse pointer enters any of our controlled
windows.

xcb_event_leave_window_t: notify us
when the mouse pointer leaves any of our controlled
windows.

The structure to be checked for in our events loop is the
same for these two events, and is the following:

typedef struct {
uint8_t response_type; /* The type of the event */
uint8_t detail;
uint16_t sequence;
xcb_timestamp_t time; /* Time, in milliseconds the event took place in */
xcb_window_t root;
xcb_window_t event;
xcb_window_t child;
int16_t root_x;
int16_t root_y;
int16_t event_x; /* The x coordinate of the mouse when the event was generated */
int16_t event_y; /* The y coordinate of the mouse when the event was generated */
uint16_t state; /* A mask of the buttons (or keys) during the event */
uint8_t mode; /* The number of mouse button that was clicked */
uint8_t same_screen_focus;
} xcb_enter_notify_event_t;
typedef xcb_enter_notify_event_t xcb_leave_notify_event_t;

There may be many windows on a screen, but only a single
keyboard attached to them. How does the X server then know
which window should be sent a given keyboard input ? This is
done using the keyboard focus. Only a single window on the
screen may have the keyboard focus at a given time. There
is a XCB function that allows a program to set the keyboard
focus to a given window. The user can usually set the
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
for these event types...).

If a window controlled by our program currently holds the
keyboard focus, it can receive key press and key release
events. So, we should add one (or more) of the following
masks when we create our window:

XCB_EVENT_MASK_KEY_PRESS: notify us when
a key was pressed while any of our controlled windows had
the keyboard focus.

XCB_EVENT_MASK_KEY_RELEASE: notify us
when a key was released while any of our controlled
windows had the keyboard focus.

The structure to be checked for in our events loop is the
same for these two events, and is the following:

As an example for handling events, we show a program that
creates a window, enters an events loop and checks for all the
events described above, and writes on the terminal the relevant
characteristics of the event. With this code, it should be
easy to add drawing operations, like those which have been
described above.

Besides drawing graphics on a window, we often want to draw
text. Text strings have two major properties: the characters to
be drawn and the font with which they are drawn. In order to
draw text, we need to first request the X server to load a
font. We then assign a font to a Graphic Context, and finally, we
draw the text in a window, using the Graphic Context.

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

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:

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.

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:

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:

One more thing we can do to our window is manipulate them on the
screen (resize them, move them, raise or lower them, iconify
them, and so on). Some window operations functions are supplied
by XCB for this purpose.

The first pair of operations we can apply on a window is
mapping it, or un-mapping it. Mapping a window causes the
window to appear on the screen, as we have seen in our simple
window program example. Un-mapping it causes it to be removed
from the screen (although the window as a logical entity still
exists). This gives the effect of making a window hidden
(unmapped) and shown again (mapped). For example, if we have a
dialog box window in our program, instead of creating it every
time the user asks to open it, we can create the window once,
in an un-mapped mode, and when the user asks to open it, we
simply map the window on the screen. When the user clicked the
'OK' or 'Cancel' button, we simply un-map the window. This is
much faster than creating and destroying the window, however,
the cost is wasted resources, both on the client side, and on
the X server side.

As we have seen when we have created our first window, in the
X Events subsection, we can set some attributes for the window
(that is, the position, the size, the events the window will
receive, etc). If we want to modify them, but the window is
already created, we can change them by using the following
function:

Until now, we changed properties of a single window. We'll see
that there are properties that relate to the window and other
windows. One of them is the stacking order. That is, the order
in which the windows are layered on top of each other. The
front-most window is said to be on the top of the stack, while
the back-most window is at the bottom of the stack. Here is
how to manipulate our windows stack order:

const static uint32_t values[] = { XCB_STACK_MODE_ABOVE };
/* The connection c and the window win are supposed to be defined */
/* Move the window on the top of the stack */
xcb_configure_window (c, win, XCB_CONFIG_WINDOW_STACK_MODE, values);

Just like we can set various attributes of our windows, we can
also ask the X server supply the current values of these
attributes. For example, we can check where a window is
located on the screen, what is its current size, whether it is
mapped or not, etc. The structure that contains some of this
information is

Remark that you have to free the structure, as
xcb_get_geometry_reply_t allocates a
newly one.

One problem is that the returned location of the window is
relative to its parent window. This makes these coordinates
rather useless for any window manipulation functions, like
moving it on the screen. In order to overcome this problem, we
need to take a two-step operation. First, we find out the Id
of the parent window of our window. We then translate the
above relative coordinates to the screen coordinates.

In the beginning, there were not enough colors. Screen
controllers could only support a limited number of colors
simultaneously (initially 2, then 4, 16 and 256). Because of
this, an application could not just ask to draw in a "light
purple-red" color, and expect that color to be available. Each
application allocated the colors it needed, and when all the
color entries (4, 16, 256 colors) were in use, the next color
allocation would fail.

Thus, the notion of "a color map" was introduced. A color map
is a table whose size is the same as the number of
simultaneous colors a given screen controller. Each entry
contained the RGB (Red, Green and Blue) values of a different
color (all colors can be drawn using some combination of red,
green and blue). When an application wants to draw on the
screen, it does not specify which color to use. Rather, it
specifies which color entry of some color map to be used
during this drawing. Change the value in this color map entry
and the drawing will use a different color.

In order to be able to draw using colors that got something to
do with what the programmer intended, color map allocation
functions are supplied. You could ask to allocate entry for a
color with a set of RGB values. If one already existed, you
would get its index in the table. If none existed, and the
table was not full, a new cell would be allocated to contain
the given RGB values, and its index returned. If the table was
full, the procedure would fail. You could then ask to get a
color map entry with a color that is closest to the one you
were asking for. This would mean that the actual drawing on
the screen would be done using colors similar to what you
wanted, but not the same.

On today's more modern screens where one runs an X server with
support for 16 million colors, this limitation looks a little
silly, but remember that there are still older computers with
older graphics cards out there. Using color map, support for
these screen becomes transparent to you. On a display
supporting 16 million colors, any color entry allocation
request would succeed. On a display supporting a limited
number of colors, some color allocation requests would return
similar colors. It won't look as good, but your application
would still work.

When you draw using XCB, you can choose to use the standard
color map of the screen your window is displayed on, or you
can allocate a new color map and apply it to a window. In the
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
effect you get with X applications that use the "-install"
command line option.

One thing many so-called "Multi-Media" applications need to do,
is display images. In the X world, this is done using bitmaps
and pixmaps. We have already seen some usage of them when
setting an icon for our application. Lets study them further,
and see how to draw these images inside a window, along side the
simple graphics and text we have seen so far.

One thing to note before delving further, is that XCB (nor Xlib)
supplies no means of manipulating popular image formats, such as
gif, png, jpeg or tiff. It is up to the programmer (or to higher
level graphics libraries) to translate these image formats into
formats that the X server is familiar with (x bitmaps and x
pixmaps).

An X bitmap is a two-color image stored in a format specific
to the X window system. When stored in a file, the bitmap data
looks like a C source file. It contains variables defining the
width and the height of the bitmap, an array containing the
bit values of the bitmap (the size of the array is
(width+7)/8*height and the bit and byte order are LSB), and
an optional hot-spot location (that will
be explained later, when discussing mouse cursors).

An X pixmap is a format used to stored images in the memory of
an X server. This format can store both black and white images
(such as x bitmaps) as well as color images. It is the only
image format supported by the X protocol, and any image to be
drawn on screen, should be first translated into this format.

In actuality, an X pixmap can be thought of as a window that
does not appear on the screen. Many graphics operations that
work on windows, will also work on pixmaps. Indeed, the type
of X pixmap in XCB is an Id like a window:

typedef uint32_t xcb_pixmap_t;

Like Xlib, there is no difference between a Drawable, a Window
or a Pixmap:

typedef uint32_t xcb_drawable_t;

in order to avoid confusion between a window and a pixmap. The
operations that will work the same on a window or a pixmap
will require a xcb_drawable_t

Remark: In Xlib, there is no specific difference between a
Drawable, a
Pixmap or a
Window: all are 32 bit long
integer. XCB wraps all these different IDs in structures to
provide some measure of type-safety.

Sometimes we want to create an un-initialized pixmap, so we
can later draw into it. This is useful for image drawing
programs (creating a new empty canvas will cause the creation
of a new pixmap on which the drawing can be stored). It is
also useful when reading various image formats: we load the
image data into memory, create a pixmap on the server, and
then draw the decoded image data onto that pixmap.

To create a new pixmap, we first ask the X server to give an
Id to our pixmap, with this function:

Once we got a handle to a pixmap, we can draw it on some
window, using the following function:

xcb_void_cookie_t xcb_copy_area (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */
xcb_drawable_t src_drawable, /* The Drawable we want to paste */
xcb_drawable_t dst_drawable, /* The Drawable on which we copy the previous Drawable */
xcb_gcontext_t gc, /* A Graphic Context */
int16_t src_x, /* Top left x coordinate of the region we want to copy */
int16_t src_y, /* Top left y coordinate of the region we want to copy */
int16_t dst_x, /* Top left x coordinate of the region where we want to copy */
int16_t dst_y, /* Top left y coordinate of the region where we want to copy */
uint16_t width, /* Width of the region we want to copy */
uint16_t height); /* Height of the region we want to copy */

As you can see, we could copy the whole pixmap, as well as
only a given rectangle of the pixmap. This is useful to
optimize the drawing speed: we could copy only what we have
modified in the pixmap.

One important note should be made: it is possible to
create pixmaps with different depths on the same screen. When
we perform copy operations (a pixmap onto a window, etc), we
should make sure that both source and target have the same
depth. If they have a different depth, the operation would
fail. The exception to this is if we copy a specific bit plane
of the source pixmap using the
xcb_copy_plane_t function. In such an
event, we can copy a specific plane to the target window (in
actuality, setting a specific bit in the color of each pixel
copied). This can be used to generate strange graphic effects
in a window, but that is beyond the scope of this tutorial.

Freeing a pixmap

Finally, when we are done using a given pixmap, we should free
it, in order to free resources of the X server. This is done
using this function:

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
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
cursor of our windows.

In the second method, we create a new cursor by using a pair
of pixmaps, with depth of one (that is, two colors
pixmaps). One pixmap defines the shape of the cursor, while
the other works as a mask, specifying which pixels of the
cursor will be actually drawn. The rest of the pixels will be
transparent.

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.

The problem when you want to port an Xlib program to XCB is that
you don't know if the Xlib function that you want to "translate"
is a X Window one or an Xlib macro. In that section, we describe
a way to translate the usual functions or macros that Xlib
provides. It's usually just a member of a structure.

In this section, we look at how to translate the macros that
return some members of the Display
structure. They are obtained by using a function that requires a
xcb_connection_t * or a member of the
xcb_setup_t structure
(via the function xcb_get_setup), or
a function that requires that structure.

This number is the file descriptor that connects the client
to the server. You just have to use that function:

int xcb_get_file_descriptor (xcb_connection_t *c);

DefaultScreen

That number is not stored by XCB. It is returned in the
second parameter of the function xcb_connect.
Hence, you have to store it yourself if you want to use
it. Then, to get the xcb_screen_t
structure, you have to iterate on the screens.
The equivalent function of the Xlib's
ScreenOfDisplay function can be
found below. This is also provided in the
xcb_aux_t library as xcb_aux_get_screen(). OK, here is the
small piece of code to get that number:

xcb_connection_t *c;
int screen_default_nbr;
/* you pass the name of the display you want to xcb_connect_t */
c = xcb_connect (display_name, &screen_default_nbr);
/* screen_default_nbr contains now the number of the default screen */

QLength

Not documented yet.

However, this points out a basic difference in philosophy between
Xlib and XCB. Xlib has several functions for filtering and
manipulating the incoming and outgoing X message queues. XCB
wishes to hide this as much as possible from the user, which
allows for more freedom in implementation strategies.

ScreenCount

You get the count of screens with the functions
xcb_get_setup
and
xcb_setup_roots_iterator
(if you need to iterate):

You get the major version of the protocol in the
xcb_setup_t
structure, with the function xcb_get_setup:

xcb_connection_t *c;
uint16_t protocol_major_version;
/* you init the connection */
protocol_major_version = xcb_get_setup (c)->protocol_major_version;
/* protocol_major_version contains now the major version of the protocol */

ProtocolRevision

You get the minor version of the protocol in the
xcb_setup_t
structure, with the function xcb_get_setup:

You get the number of the release of the server hardware in the
xcb_setup_t
structure, with the function xcb_get_setup:

xcb_connection_t *c;
uint32_t release_number;
/* you init the connection */
release_number = xcb_get_setup (c)->release_number;
/* release_number contains now the number of the release of the server hardware */

DisplayString

The name of the display is not stored in XCB. You have to
store it by yourself.

BitmapUnit

You get the bitmap scanline unit in the
xcb_setup_t
structure, with the function xcb_get_setup:

in Xlib, ScreenOfDisplay returns a
Screen structure that contains
several characteristics of your screen. XCB has a similar
structure (xcb_screen_t),
but the way to obtain it is a bit different. With
Xlib, you just provide the number of the screen and you grab it
from an array. With XCB, you iterate over all the screens to
obtain the one you want. The complexity of this operation is
O(n). So the best is to store this structure if you use
it often. See screen_of_display just below.

Xlib provides generally two functions to obtain the characteristics
related to the screen. One with the display and the number of
the screen, which calls ScreenOfDisplay,
and the other that uses the Screen structure.
This might be a bit confusing. As mentioned above, with XCB, it
is better to store the xcb_screen_t
structure. Then, you have to read the members of this
structure. That's why the Xlib functions are put by pairs (or
more) as, with XCB, you will use the same code.

As mentioned above, you might want to store the value
returned by this function.

All the functions below will use the result of that
function, as they just grab a specific member of the
xcb_screen_t structure.

DefaultScreenOfDisplay

It is the default screen that you obtain when you connect to
the X server. It suffices to call the screen_of_display
function above with the connection and the number of the
default screen.

xcb_connection_t *c;
int screen_default_nbr;
xcb_screen_t *default_screen; /* the returned default screen */
/* you pass the name of the display you want to xcb_connect_t */
c = xcb_connect (display_name, &screen_default_nbr);
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 */

While a Visual is, in Xlib, a structure, in XCB, there are
two types: xcb_visualid_t, which is
the Id of the visual, and xcb_visualtype_t,
which corresponds to the Xlib Visual. To get the Id of the
visual of a screen, just get the
root_visual
member of a xcb_screen_t:

xcb_connection_t *c;
xcb_screen_t *screen;
int screen_nbr;
xcb_visualid_t root_visual = { 0 }; /* the returned visual Id */
/* you init the connection and screen_nbr */
screen = screen_of_display (c, screen_nbr);
if (screen)
root_visual = screen->root_visual;
/* root_visual contains now the value of the Id of the visual, or a NULL visual if no screen is found */

To get the xcb_visualtype_t
structure, it's a bit less easy. You have to get the
xcb_screen_t structure that you want,
get its root_visual member,
then iterate over the xcb_depth_ts
and the xcb_visualtype_ts, and compare
the xcb_visualid_t of these xcb_visualtype_ts:
with root_visual:

To get the current input masks,
you look in the xcb_screen_t structure:

xcb_connection_t *c;
xcb_screen_t *screen;
int screen_nbr;
uint32_t current_input_masks = 0; /* the returned value of current input masks */
/* you init the connection and screen_nbr */
screen = screen_of_display (c, screen_nbr);
if (screen)
current_input_masks = screen->current_input_masks;
/* current_input_masks contains now the value of the current input masks, or FALSE if no screen is found */

in Xlib, the Screen structure
stores its associated Display
structure. This is not the case in the X Window protocol,
hence, it's also not the case in XCB. So you have to store
it by yourself.

DisplayCells / CellsOfScreen

To get the colormap entries,
you look in the xcb_visualtype_t
structure, that you grab like here:

xcb_connection_t *c;
xcb_visualtype_t *visual_type;
uint16_t colormap_entries = 0; /* the returned value of the colormap entries */
/* you init the connection and visual_type */
if (visual_type)
colormap_entries = visual_type->colormap_entries;
/* colormap_entries contains now the value of the colormap entries, or FALSE if no screen is found */