1602e473dSmrg<!DOCTYPE html public "-//W3C//DTD HTML 4.01 Transitional//EN"
2602e473dSmrg"http://www.w3.org/TR/html4/loose.dtd">
3602e473dSmrg
4602e473dSmrg<html>
5602e473dSmrg
6602e473dSmrg<head>
7602e473dSmrg  <title>Basic Graphics Programming With The XCB Library</title>
8602e473dSmrg  <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
9602e473dSmrg  <link href="xcb.css" rel="stylesheet" type="text/css">
10602e473dSmrg</head>
11602e473dSmrg
12602e473dSmrg<body>
13602e473dSmrg  <div class="title">
14602e473dSmrg    Basic Graphics Programming With The XCB Library
15602e473dSmrg  </div>
16602e473dSmrg  <div class="toc">
17602e473dSmrg  <ol>
18602e473dSmrg    <li><a class="section" href="#intro">Introduction</a>
19602e473dSmrg    <li><a class="section" href="#Xmodel">The client and server model of the X window system</a>
20602e473dSmrg    <li><a class="section" href="#asynch">GUI programming: the asynchronous model</a>
21602e473dSmrg    <li><a class="section" href="#notions">Basic XCB notions</a>
22602e473dSmrg      <ol>
23602e473dSmrg        <li><a class="subsection" href="#conn">The X Connection</a>
24602e473dSmrg        <li><a class="subsection" href="#requestsreplies">Requests and replies: the Xlib killers</a>
25602e473dSmrg        <li><a class="subsection" href="#gc">The Graphics Context</a>
26602e473dSmrg        <li>Object handles
27602e473dSmrg        <li>Memory allocation for XCB structures
28602e473dSmrg        <li><a class="subsection" href="#events">Events</a>
29602e473dSmrg      </ol>
30602e473dSmrg    <li><a class="section" href="#use">Using XCB-based programs</a>
31602e473dSmrg      <ol>
32602e473dSmrg        <li><a class="subsection" href="#inst">Installation of XCB</a>
33602e473dSmrg        <li><a class="subsection" href="#comp">Compiling XCB-based programs</a>
34602e473dSmrg      </ol>
35602e473dSmrg    <li><a class="section" href="#openconn">Opening and closing the connection to an X server</a>
36602e473dSmrg    <li><a class="section" href="#screen">Checking basic information about a connection</a>
37602e473dSmrg    <li><a class="section" href="#helloworld">Creating a basic window - the "hello world" program</a>
38602e473dSmrg    <li><a class="section" href="#drawing">Drawing in a window</a>
39602e473dSmrg      <ol>
40602e473dSmrg        <li><a class="subsection" href="#allocgc">Allocating a Graphics Context</a>
41602e473dSmrg        <li><a class="subsection" href="#changegc">Changing the attributes of a Graphics Context</a>
42602e473dSmrg        <li><a class="subsection" href="#drawingprim">Drawing primitives: point, line, box, circle,...</a>
43602e473dSmrg      </ol>
44602e473dSmrg    <li><a class="section" href="#xevents">X Events</a>
45602e473dSmrg      <ol>
46602e473dSmrg        <li><a class="subsection" href="#register">Registering for event types using event masks</a>
47602e473dSmrg        <li><a class="subsection" href="#loop">Receiving events: writing the events loop</a>
48602e473dSmrg        <li><a class="subsection" href="#expose">Expose events</a>
49602e473dSmrg        <li><a class="subsection" href="#userinput">Getting user input</a>
50602e473dSmrg          <ol>
51602e473dSmrg            <li><a class="subsubsection" href="#mousepressrelease">Mouse button press and release events</a>
52602e473dSmrg            <li><a class="subsubsection" href="#mousemvnt">Mouse movement events</a>
53602e473dSmrg            <li><a class="subsubsection" href="#mouseenter">Mouse pointer enter and leave events</a>
54602e473dSmrg            <li><a class="subsubsection" href="#focus">The keyboard focus</a>
55602e473dSmrg            <li><a class="subsubsection" href="#keypress">Keyboard press and release events</a>
56602e473dSmrg          </ol>
57602e473dSmrg        <li><a class="subsection" href="#eventex">X events: a complete example</a>
58602e473dSmrg      </ol>
59602e473dSmrg    <li><a class="section" href="#font">Handling text and fonts</a>
60602e473dSmrg      <ol>
61602e473dSmrg        <li><a class="subsection" href="#fontstruct">The Font structure</a>
62602e473dSmrg        <li><a class="subsection" href="#openingfont">Opening a Font</a>
63602e473dSmrg        <li><a class="subsection" href="#assigningfont">Assigning a Font to a Graphic Context</a>
64602e473dSmrg        <li><a class="subsection" href="#drawingtext">Drawing text in a drawable</a>
65602e473dSmrg        <li><a class="subsection" href="#fontcompleteexample">Complete example</a>
66602e473dSmrg      </ol>
67602e473dSmrg    <li>Windows hierarchy
68602e473dSmrg      <ol>
69602e473dSmrg        <li>Root, parent and child windows
70602e473dSmrg        <li>Events propagation
71602e473dSmrg      </ol>
72602e473dSmrg    <li><a class="section" href="#wm">Interacting with the window manager</a>
73602e473dSmrg      <ol>
74602e473dSmrg        <li><a class="subsection" href="#wmprop">Window properties</a>
75602e473dSmrg        <li><a class="subsection" href="#wmname">Setting the window name and icon name</a>
76602e473dSmrg        <li>Setting preferred window size(s)
77602e473dSmrg        <li>Setting miscellaneous window manager hints
78602e473dSmrg        <li>Setting an application's icon
79602e473dSmrg        <li>Obeying the delete-window protocol
80602e473dSmrg      </ol>
81602e473dSmrg    <li><a class="section" href="#winop">Simple window operations</a>
82602e473dSmrg      <ol>
83602e473dSmrg        <li><a class="subsection" href="#winmap">Mapping and unmapping a window</a>
84602e473dSmrg        <li><a class="subsection" href="#winconf">Configuring a window</a>
85602e473dSmrg        <li><a class="subsection" href="#winmove">Moving a window around the screen</a>
86602e473dSmrg        <li><a class="subsection" href="#winsize">Resizing a window</a>
87602e473dSmrg        <li><a class="subsection" href="#winstack">Changing windows stacking order: raise and lower</a>
88602e473dSmrg        <li>Iconifying and de-iconifying a window
89602e473dSmrg        <li><a class="subsection" href="#wingetinfo">Getting informations about a window</a>
90602e473dSmrg      </ol>
91602e473dSmrg    <li><a class="section" href="#usecolor">Using colors to paint the rainbow</a>
92602e473dSmrg      <ol>
93602e473dSmrg        <li><a class="subsection" href="#colormap">Color maps</a>
94602e473dSmrg        <li><a class="subsection" href="#colormapalloc">Allocating and freeing Color Maps</a>
95602e473dSmrg        <li><a class="subsection" href="#alloccolor">Allocating and freeing a color entry</a>
96602e473dSmrg        <li>Drawing with a color
97602e473dSmrg      </ol>
98602e473dSmrg    <li><a class="section" href="#pixmaps">X Bitmaps and Pixmaps</a>
99602e473dSmrg      <ol>
100602e473dSmrg        <li><a class="subsection" href="#pixmapswhat">What is a X Bitmap ? An X Pixmap ?</a>
101602e473dSmrg        <li>Loading a bitmap from a file
102602e473dSmrg        <li>Drawing a bitmap in a window
103602e473dSmrg        <li><a class="subsection" href="#pixmapscreate">Creating a pixmap</a>
104602e473dSmrg        <li><a class="subsection" href="#pixmapsdraw">Drawing a pixmap in a window</a>
105602e473dSmrg        <li><a class="subsection" href="#pixmapsfree">Freeing a pixmap</a>
106602e473dSmrg      </ol>
107602e473dSmrg    <li><a class="subsection" href="#mousecursor">Messing with the mouse cursor</a>
108602e473dSmrg      <ol>
109602e473dSmrg        <li><a class="subsection" href="#mousecursorcreate">Creating and destroying a mouse cursor</a>
110602e473dSmrg        <li><a class="subsection" href="#mousecursorset">Setting a window's mouse cursor</a>
111602e473dSmrg        <li><a class="subsection" href="#mousecursorexample">Complete example</a>
112602e473dSmrg      </ol>
113602e473dSmrg    <li><a class="subsection" href="#translation">Translation of basic Xlib functions and macros</a>
114602e473dSmrg      <ol>
115602e473dSmrg        <li><a class="subsection" href="#displaystructure">Members of the Display structure</a>
116602e473dSmrg          <ol>
117602e473dSmrg            <li><a class="subsection" href="#ConnectionNumber">ConnectionNumber</a>
118602e473dSmrg            <li><a class="subsection" href="#DefaultScreen">DefaultScreen</a>
119602e473dSmrg            <li><a class="subsection" href="#QLength">QLength</a>
120602e473dSmrg            <li><a class="subsection" href="#ScreenCount">ScreenCount</a>
121602e473dSmrg            <li><a class="subsection" href="#ServerVendor">ServerVendor</a>
122602e473dSmrg            <li><a class="subsection" href="#ProtocolVersion">ProtocolVersion</a>
123602e473dSmrg            <li><a class="subsection" href="#ProtocolRevision">ProtocolRevision</a>
124602e473dSmrg            <li><a class="subsection" href="#VendorRelease">VendorRelease</a>
125602e473dSmrg            <li><a class="subsection" href="#DisplayString">DisplayString</a>
126602e473dSmrg            <li><a class="subsection" href="#BitmapUnit">BitmapUnit</a>
127602e473dSmrg            <li><a class="subsection" href="#BitmapBitOrder">BitmapBitOrder</a>
128602e473dSmrg            <li><a class="subsection" href="#BitmapPad">BitmapPad</a>
129602e473dSmrg            <li><a class="subsection" href="#ImageByteOrder">ImageByteOrder</a>
130602e473dSmrg          </ol>
131602e473dSmrg        <li><a class="subsection" href="#screenofdisplay">ScreenOfDisplay related functions</a>
132602e473dSmrg          <ol>
133602e473dSmrg            <li><a class="subsection" href="#ScreenOfDisplay">ScreenOfDisplay</a>
134602e473dSmrg            <li><a class="subsection" href="#DefaultScreenOfDisplay">DefaultScreenOfDisplay</a>
135602e473dSmrg            <li><a class="subsection" href="#RootWindow">RootWindow / RootWindowOfScreen</a>
136602e473dSmrg            <li><a class="subsection" href="#DefaultRootWindow">DefaultRootWindow</a>
137602e473dSmrg            <li><a class="subsection" href="#DefaultVisual">DefaultVisual / DefaultVisualOfScreen</a>
138602e473dSmrg            <li><a class="subsection" href="#DefaultGC">DefaultGC / DefaultGCOfScreen</a>
139602e473dSmrg            <li><a class="subsection" href="#BlackPixel">BlackPixel / BlackPixelOfScreen</a>
140602e473dSmrg            <li><a class="subsection" href="#WhitePixel">WhitePixel / WhitePixelOfScreen</a>
141602e473dSmrg            <li><a class="subsection" href="#DisplayWidth">DisplayWidth / WidthOfScreen</a>
142602e473dSmrg            <li><a class="subsection" href="#DisplayHeight">DisplayHeight / HeightOfScreen</a>
143602e473dSmrg            <li><a class="subsection" href="#DisplayWidthMM">DisplayWidthMM / WidthMMOfScreen</a>
144602e473dSmrg            <li><a class="subsection" href="#DisplayHeightMM">DisplayHeightMM / HeightMMOfScreen</a>
145602e473dSmrg            <li><a class="subsection" href="#DisplayPlanes">DisplayPlanes / DefaultDepth / DefaultDepthOfScreen / PlanesOfScreen</a>
146602e473dSmrg            <li><a class="subsection" href="#DefaultColormap">DefaultColormap / DefaultColormapOfScreen</a>
147602e473dSmrg            <li><a class="subsection" href="#MinCmapsOfScreen">MinCmapsOfScreen</a>
148602e473dSmrg            <li><a class="subsection" href="#MaxCmapsOfScreen">MaxCmapsOfScreen</a>
149602e473dSmrg            <li><a class="subsection" href="#DoesSaveUnders">DoesSaveUnders</a>
150602e473dSmrg            <li><a class="subsection" href="#DoesBackingStore">DoesBackingStore</a>
151602e473dSmrg            <li><a class="subsection" href="#EventMaskOfScreen">EventMaskOfScreen</a>
152602e473dSmrg          </ol>
1531c7386f4Smrg        <li><a class="subsection" href="#misc">Miscellaneous macros</a>
154602e473dSmrg          <ol>
155602e473dSmrg            <li><a class="subsection" href="#DisplayOfScreen">DisplayOfScreen</a>
156602e473dSmrg            <li><a class="subsection" href="#DisplayCells">DisplayCells / CellsOfScreen</a>
157602e473dSmrg          </ol>
158602e473dSmrg      </ol>
159602e473dSmrg  </ol>
160602e473dSmrg  </div>
161602e473dSmrg  <div class="section">
162602e473dSmrg    <ol>
163602e473dSmrg      <li class="title"><a name="intro">Introduction</a>
164602e473dSmrg      <p>
165602e473dSmrg      This tutorial is based on the
166602e473dSmrg      <a href="http://users.actcom.co.il/~choo/lupg/tutorials/xlib-programming/xlib-programming.html">Xlib Tutorial</a>
167602e473dSmrg      written by <a href="mailto:choor at atcom dot co dot il">Guy Keren</a>. The
168602e473dSmrg      author allowed me to take some parts of his text, mainly the text which
169602e473dSmrg      deals with the X Windows generality.
170602e473dSmrg      </p>
171602e473dSmrg      <p>
172602e473dSmrg      This tutorial is intended for people who want to start to program
173602e473dSmrg      with the <a href="http://xcb.freedesktop.org">XCB</a>
174602e473dSmrg      library. keep in mind that XCB, like the
175602e473dSmrg      <a href="http://tronche.com/gui/x/xlib/introduction">Xlib</a>
176602e473dSmrg      library, isn't what most programmers wanting to write X
177602e473dSmrg      applications are looking for. They should use a much higher
178602e473dSmrg      level GUI toolkit like Motif,
179602e473dSmrg      <a href="http://www.lesstif.org">LessTiff</a>,
180602e473dSmrg      <a href="http://www.gtk.org">GTK</a>,
181602e473dSmrg      <a href="http://www.trolltech.com">QT</a>,
182602e473dSmrg      <a href="http://www.enlightenment.org">EWL</a>,
183602e473dSmrg      <a href="http://www.enlightenment.org">ETK</a>, or use
184602e473dSmrg      <a href="http://cairographics.org">Cairo</a>.
185602e473dSmrg      However,
186602e473dSmrg      we need to start somewhere. More than this, knowing how things
187602e473dSmrg      work down below is never a bad idea.
188602e473dSmrg      </p>
189602e473dSmrg      <p>
190602e473dSmrg      After reading this tutorial, one should be able to write very
191602e473dSmrg      simple graphical programs, but not programs with decent user
192602e473dSmrg      interfaces. For such programs, one of the previously mentioned
193602e473dSmrg      libraries should be used.
194602e473dSmrg      </p>
195602e473dSmrg      <p>
196602e473dSmrg      But what is XCB? Xlib has been
197602e473dSmrg      the standard C binding for the <a href="http://www.x.org">X
198602e473dSmrg      Window System</a> protocol for many years now. It is an
199602e473dSmrg      excellent piece of work, but there are applications for which it
200602e473dSmrg      is not ideal, for example:
201602e473dSmrg      </p>
202602e473dSmrg      <ul>
203602e473dSmrg        <li><b>Small platforms</b>: Xlib is a large piece of code, and
204602e473dSmrg        it's difficult to make it smaller
205602e473dSmrg        <li><b>Latency hiding</b>: Xlib requests requiring a reply are
206602e473dSmrg        effectively synchronous: they block until the reply appears,
207602e473dSmrg        whether the result is needed immediately or not.
208602e473dSmrg        <li><b>Direct access to the protocol</b>: Xlib does quite a
209602e473dSmrg        bit of caching, layering, and similar optimizations. While this
210602e473dSmrg        is normally a feature, it makes it difficult to simply emit
211602e473dSmrg        specified X protocol requests and process specific
212602e473dSmrg        responses.
213602e473dSmrg        <li><b>Threaded applications</b>: While Xlib does attempt to
214602e473dSmrg        support multithreading, the API makes this difficult and
215602e473dSmrg        error-prone.
216602e473dSmrg        <li><b>New extensions</b>: The Xlib infrastructure provides
217602e473dSmrg        limited support for the new creation of X extension client side
218602e473dSmrg        code.
219602e473dSmrg      </ul>
220602e473dSmrg      <p>
221602e473dSmrg      For these reasons, among others, XCB, an X C binding, has been
222602e473dSmrg      designed to solve the above problems and thus provide a base for
223602e473dSmrg      </p>
224602e473dSmrg      <ul>
225602e473dSmrg        <li>Toolkit implementation.
226602e473dSmrg        <li>Direct protocol-level programming.
227602e473dSmrg        <li>Lightweight emulation of commonly used portions of the
228602e473dSmrg        Xlib API.
229602e473dSmrg      </ul>
230602e473dSmrg      <br>
231602e473dSmrg      <li class="title"><a name="Xmodel">The client and server model of the X window system</a>
232602e473dSmrg      <p>
233602e473dSmrg      The X Window System was developed with one major goal:
234602e473dSmrg      flexibility. The idea was that the way things look is one thing,
235602e473dSmrg      but the way things work is another matter. Thus, the lower
236602e473dSmrg      levels provide the tools required to draw windows, handle user
237602e473dSmrg      input, allow drawing graphics using colors (or black and white
238602e473dSmrg      screens), etc. To this point, a decision was made to separate
239602e473dSmrg      the system into two parts. A client that decides what to do, and
240602e473dSmrg      a server that actually draws on the screen and reads user input
241602e473dSmrg      in order to send it to the client for processing.
242602e473dSmrg      </p>
243602e473dSmrg      <p>
244602e473dSmrg      This model is the complete opposite of what is used to when
245602e473dSmrg      dealing with clients and servers. In our case, the user sits
246602e473dSmrg      near the machine controlled by the server, while the client
247602e473dSmrg      might be running on a remote machine. The server controls the
248602e473dSmrg      screens, mouse and keyboard. A client may connect to the server,
249602e473dSmrg      request that it draws a window (or several windows), and ask the
250602e473dSmrg      server to send it any input the user sends to these
251602e473dSmrg      windows. Thus, several clients may connect to a single X server
252602e473dSmrg      (one might be running mail software, one running a WWW
253602e473dSmrg      browser, etc). When input is sent by the user to some window,
254602e473dSmrg      the server sends a message to the client controlling this window
255602e473dSmrg      for processing. The client decides what to do with this input,
256602e473dSmrg      and sends the server requests for drawing in the window.
257602e473dSmrg      </p>
258602e473dSmrg      <p>
259602e473dSmrg      The whole session is carried out using the X message
260602e473dSmrg      protocol. This protocol was originally carried over the TCP/IP
261602e473dSmrg      protocol suite, allowing the client to run on any machine
262602e473dSmrg      connected to the same network that the server is. Later on, the
263602e473dSmrg      X servers were extended to allow clients running on the local
264602e473dSmrg      machine with more optimized access to the server (note that an X
265602e473dSmrg      protocol message may be several hundreds of KB in size), such as
266602e473dSmrg      using shared memory, or using Unix domain sockets (a method for
267602e473dSmrg      creating a logical channel on a Unix system between two processes).
268602e473dSmrg      </p>
269602e473dSmrg      <li class="title"><a name="asynch">GUI programming: the asynchronous model</a>
270602e473dSmrg      <p>
271602e473dSmrg      Unlike conventional computer programs, that carry some serial
272602e473dSmrg      nature, a GUI program usually uses an asynchronous programming
273602e473dSmrg      model, also known as "event-driven programming". This means that
274602e473dSmrg      that program mostly sits idle, waiting for events sent by the X
275602e473dSmrg      server, and then acts upon these events. An event may say "The
276602e473dSmrg      user pressed the 1st button mouse in spot (x,y)", or "The window
277602e473dSmrg      you control needs to be redrawn". In order for the program to be
278602e473dSmrg      responsive to the user input, as well as to refresh requests, it
279602e473dSmrg      needs to handle each event in a rather short period of time
280602e473dSmrg      (e.g. less that 200 milliseconds, as a rule of thumb).
281602e473dSmrg      </p>
282602e473dSmrg      <p>
283602e473dSmrg      This also implies that the program may not perform operations
284602e473dSmrg      that might take a long time while handling an event (such as
285602e473dSmrg      opening a network connection to some remote server, or
286602e473dSmrg      connecting to a database server, or even performing a long file
287602e473dSmrg      copy operation). Instead, it needs to perform all these
288602e473dSmrg      operations in an asynchronous manner. This may be done by using
289602e473dSmrg      various asynchronous models to perform the longish operations,
290602e473dSmrg      or by performing them in a different process or thread.
291602e473dSmrg      </p>
292602e473dSmrg      <p>
293602e473dSmrg      So the way a GUI program looks is something like that:
294602e473dSmrg      </p>
295602e473dSmrg      <ol>
296602e473dSmrg        <li>Perform initialization routines.
297602e473dSmrg        <li>Connect to the X server.
298602e473dSmrg        <li>Perform X-related initialization.
299602e473dSmrg        <li>While not finished:
300602e473dSmrg          <ol>
301602e473dSmrg            <li>Receive the next event from the X server.
302602e473dSmrg            <li>Handle the event, possibly sending various drawing
303602e473dSmrg            requests to the X server.
304602e473dSmrg            <li>If the event was a quit message, exit the loop.
305602e473dSmrg          </ol>
306602e473dSmrg        <li>Close down the connection to the X server.
307602e473dSmrg        <li>Perform cleanup operations.
308602e473dSmrg      </ol>
309602e473dSmrg      <br>
310602e473dSmrg      <li class="title"><a name="notions">Basic XCB notions</a>
311602e473dSmrg      <p>
312602e473dSmrg      XCB has been created to eliminate the need for
313602e473dSmrg      programs to actually implement the X protocol layer. This
314602e473dSmrg      library gives a program a very low-level access to any X
315602e473dSmrg      server. Since the protocol is standardized, a client using any
316602e473dSmrg      implementation of XCB may talk with any X server (the same
317602e473dSmrg      occurs for Xlib, of course). We now give a brief description of
318602e473dSmrg      the basic XCB notions. They will be detailed later.
319602e473dSmrg      </p>
320602e473dSmrg      <ol>
321602e473dSmrg        <li class="subtitle"><a name="conn">The X Connection</a>
322602e473dSmrg        <p>
323602e473dSmrg        The major notion of using XCB is the X Connection. This is a
324602e473dSmrg        structure representing the connection we have open with a
325602e473dSmrg        given X server. It hides a queue of messages coming from the
326602e473dSmrg        server, and a queue of pending requests that our client
327602e473dSmrg        intends to send to the server. In XCB, this structure is named
328602e473dSmrg        'xcb_connection_t'. It is analogous to the Xlib Display.
329602e473dSmrg        When we open a connection to an X server, the
330602e473dSmrg        library returns a pointer to such a structure. Later, we
331602e473dSmrg        supply this pointer to any XCB function that should send
332602e473dSmrg        messages to the X server or receive messages from this server.
333602e473dSmrg        </p>
334602e473dSmrg        <li class="subtitle"><a name="requestsreplies">Requests and
335602e473dSmrg        replies: the Xlib killers</a>
336602e473dSmrg        <p>
337602e473dSmrg        To ask for information from the X server, we have to make a request
338602e473dSmrg        and ask for a reply. With Xlib, these two tasks are
339602e473dSmrg        automatically done: Xlib locks the system, sends a request,
340602e473dSmrg        waits for a reply from the X server and unlocks. This is
341602e473dSmrg        annoying, especially if one makes a lot of requests to the X
342602e473dSmrg        server. Indeed, Xlib has to wait for the end of a reply
343602e473dSmrg        before asking for the next request (because of the locks that
344602e473dSmrg        Xlib sends). For example, here is a time-line of N=4
345602e473dSmrg        requests/replies with Xlib, with a round-trip latency
346602e473dSmrg        <b>T_round_trip</b> that is 5 times long as the time required
347602e473dSmrg        to write or read a request/reply (<b>T_write/T_read</b>):
348602e473dSmrg        </p>
349602e473dSmrg        <pre class="text">
350602e473dSmrg  W-----RW-----RW-----RW-----R
351602e473dSmrg</pre>
352602e473dSmrg        <ul>
353602e473dSmrg          <li>W: Writing request
354602e473dSmrg          <li>-: Stalled, waiting for data
355602e473dSmrg          <li>R: Reading reply
356602e473dSmrg        </ul>
357602e473dSmrg        <p>
358602e473dSmrg        The total time is N * (T_write + T_round_trip + T_read).
359602e473dSmrg        </p>
360602e473dSmrg        <p>
361602e473dSmrg        With XCB, we can suppress most of the round-trips as the
362602e473dSmrg        requests and the replies are not locked. We usually send a
363602e473dSmrg        request, then XCB returns to us a <b>cookie</b>, which is an
364602e473dSmrg        identifier. Then, later, we ask for a reply using this
365602e473dSmrg        <b>cookie</b> and XCB returns a
366602e473dSmrg        pointer to that reply. Hence, with XCB, we can send a lot of
367602e473dSmrg        requests, and later in the program, ask for all the replies
368602e473dSmrg        when we need them. Here is the time-line for 4
369602e473dSmrg        requests/replies when we use this property of XCB:
370602e473dSmrg        </p>
371602e473dSmrg        <pre class="text">
372602e473dSmrg  WWWW--RRRR
373602e473dSmrg</pre>
374602e473dSmrg        <p>
375602e473dSmrg        The total time is N * T_write + max (0, T_round_trip - (N-1) *
376602e473dSmrg        T_write) + N * T_read. Which can be considerably faster than
377602e473dSmrg        all those Xlib round-trips.
378602e473dSmrg        </p>
379602e473dSmrg        <p>
380602e473dSmrg        Here is a program that computes the time to create 500 atoms
381602e473dSmrg        with Xlib and XCB. It shows the Xlib way, the bad XCB way
382602e473dSmrg        (which is similar to Xlib) and the good XCB way. On my
383602e473dSmrg        computer, XCB is 25 times faster than Xlib.
384602e473dSmrg        </p>
385602e473dSmrg      <pre class="code">
386602e473dSmrg#include &lt;stdlib.h&gt;
387602e473dSmrg#include &lt;stdio.h&gt;
388602e473dSmrg#include &lt;string.h&gt;
389602e473dSmrg#include &lt;sys/time.h&gt;
390602e473dSmrg
391602e473dSmrg#include &lt;xcb/xcb.h&gt;
392602e473dSmrg
393602e473dSmrg#include &lt;X11/Xlib.h&gt;
394602e473dSmrg
395602e473dSmrgdouble
396602e473dSmrgget_time(void)
397602e473dSmrg{
398602e473dSmrg  struct timeval timev;
399602e473dSmrg
400602e473dSmrg  gettimeofday(&amp;timev, NULL);
401602e473dSmrg
402602e473dSmrg  return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
403602e473dSmrg}
404602e473dSmrg
405602e473dSmrgint
406602e473dSmrgmain ()
407602e473dSmrg{
408602e473dSmrg  xcb_connection_t         *c;
409602e473dSmrg  xcb_atom_t               *atoms;
410602e473dSmrg  xcb_intern_atom_cookie_t *cs;
411602e473dSmrg  char                    **names;
412602e473dSmrg  int                       count;
413602e473dSmrg  int                       i;
414602e473dSmrg  double                    start;
415602e473dSmrg  double                    end;
416602e473dSmrg  double                    diff;
417602e473dSmrg
418602e473dSmrg  /* Xlib */
419602e473dSmrg  Display *disp;
420602e473dSmrg  Atom    *atoms_x;
421602e473dSmrg  double   diff_x;
422602e473dSmrg
423602e473dSmrg  c = xcb_connect (NULL, NULL);
424602e473dSmrg
425602e473dSmrg  count = 500;
426602e473dSmrg  atoms = (xcb_atom_t *)malloc (count * sizeof (atoms));
427602e473dSmrg  names = (char **)malloc (count * sizeof (char *));
428602e473dSmrg
429602e473dSmrg  /* init names */
430602e473dSmrg  for (i = 0; i &lt; count; ++i) {
431602e473dSmrg    char buf[100];
432602e473dSmrg
433602e473dSmrg    sprintf (buf, "NAME%d", i);
434602e473dSmrg    names[i] = strdup (buf);
435602e473dSmrg  }
436602e473dSmrg
437602e473dSmrg  /* bad use */
438602e473dSmrg  start = get_time ();
439602e473dSmrg
440602e473dSmrg  for (i = 0; i &lt; count; ++i)
441602e473dSmrg    atoms[i] = xcb_intern_atom_reply (c,
442602e473dSmrg                                      xcb_intern_atom (c,
443602e473dSmrg                                                       0,
444602e473dSmrg                                                       strlen(names[i]),
445602e473dSmrg                                                       names[i]),
446602e473dSmrg                                      NULL)->atom;
447602e473dSmrg
448602e473dSmrg  end = get_time ();
449602e473dSmrg  diff = end - start;
450602e473dSmrg  printf ("bad use time  : %f\n", diff);
451602e473dSmrg
452602e473dSmrg  /* good use */
453602e473dSmrg  start = get_time ();
454602e473dSmrg
455602e473dSmrg  cs = (xcb_intern_atom_cookie_t *) malloc (count * sizeof(xcb_intern_atom_cookie_t));
456602e473dSmrg  for(i = 0; i &lt; count; ++i)
457602e473dSmrg    cs[i] = xcb_intern_atom (c, 0, strlen(names[i]), names[i]);
458602e473dSmrg
459602e473dSmrg  for(i = 0; i &lt; count; ++i) {
460602e473dSmrg    xcb_intern_atom_reply_t *r;
461602e473dSmrg
462602e473dSmrg    r = xcb_intern_atom_reply(c, cs[i], 0);
463602e473dSmrg    if(r)
464602e473dSmrg      atoms[i] = r->atom;
465602e473dSmrg    free(r);
466602e473dSmrg  }
467602e473dSmrg
468602e473dSmrg  end = get_time ();
469602e473dSmrg  printf ("good use time : %f\n", end - start);
470602e473dSmrg  printf ("ratio         : %f\n", diff / (end - start));
471602e473dSmrg  diff = end - start;
472602e473dSmrg
473602e473dSmrg  /* free var */
474602e473dSmrg  free (atoms);
475602e473dSmrg  free (cs);
476602e473dSmrg
477602e473dSmrg  xcb_disconnect (c);
478602e473dSmrg
479602e473dSmrg  /* Xlib */
480602e473dSmrg  disp = XOpenDisplay (getenv("DISPLAY"));
481602e473dSmrg
482602e473dSmrg  atoms_x = (Atom *)malloc (count * sizeof (atoms_x));
483602e473dSmrg
484602e473dSmrg  start = get_time ();
485602e473dSmrg
486602e473dSmrg  for (i = 0; i &lt; count; ++i)
487602e473dSmrg    atoms_x[i] = XInternAtom(disp, names[i], 0);
488602e473dSmrg
489602e473dSmrg  end = get_time ();
490602e473dSmrg  diff_x = end - start;
491602e473dSmrg  printf ("Xlib use time : %f\n", diff_x);
492602e473dSmrg  printf ("ratio         : %f\n", diff_x / diff);
493602e473dSmrg
494602e473dSmrg  free (atoms_x);
495602e473dSmrg  for (i = 0; i &lt; count; ++i)
496602e473dSmrg    free (names[i]);
497602e473dSmrg  free (names);
498602e473dSmrg
499602e473dSmrg  XCloseDisplay (disp);
500602e473dSmrg
501602e473dSmrg  return 0;
502602e473dSmrg}
503602e473dSmrg</pre>
504602e473dSmrg        <li class="subtitle"><a name="gc">The Graphic Context</a>
505602e473dSmrg        <p>
506602e473dSmrg        When we perform various drawing operations (graphics, text,
507602e473dSmrg        etc), we may specify various options for controlling how the
508602e473dSmrg        data will be drawn (what foreground and background colors to
509602e473dSmrg        use, how line edges will be connected, what font to use when
510602e473dSmrg        drawing some text, etc). In order to avoid the need to supply
511602e473dSmrg        hundreds of parameters to each drawing function, a graphical
512602e473dSmrg        context structure is used. We set the various drawing options
513602e473dSmrg        in this structure, and then we pass a pointer to this
514602e473dSmrg        structure to any drawing routines. This is rather handy, as we
515602e473dSmrg        often need to perform several drawing requests with the same
516602e473dSmrg        options. Thus, we would initialize a graphical context, set
517602e473dSmrg        the desired options, and pass this structure to all drawing
518602e473dSmrg        functions.
519602e473dSmrg        </p>
520602e473dSmrg        <p>
521602e473dSmrg        Note that graphic contexts have no client-side structure in
522602e473dSmrg        XCB, they're just XIDs. Xlib has a client-side structure
523602e473dSmrg        because it caches the GC contents so it can avoid making
524602e473dSmrg        redundant requests, but of course XCB doesn't do that.
525602e473dSmrg        </p>
526602e473dSmrg        <li class="subtitle"><a name="events">Events</a>
527602e473dSmrg        <p>
528602e473dSmrg        A structure is used to pass events received from the X
529602e473dSmrg        server. XCB supports exactly the events specified in the
530602e473dSmrg        protocol (33 events). This structure contains the type
531602e473dSmrg        of event received (including a bit for whether it came
532602e473dSmrg        from the server or another client), as well as the data associated with the
533602e473dSmrg        event (e.g. position on the screen where the event was
534602e473dSmrg        generated, mouse button associated with the event, region of
535602e473dSmrg        the screen associated with a "redraw" event, etc). The way to
536602e473dSmrg        read the event's data depends on the event type.
537602e473dSmrg        </p>
538602e473dSmrg      </ol>
539602e473dSmrg      <br>
540602e473dSmrg      <li class="title"><a name="use">Using XCB-based programs</a>
541602e473dSmrg      <br>
542602e473dSmrg      <ol>
543602e473dSmrg        <li class="subtitle"><a name="inst">Installation of XCB</a>
544602e473dSmrg        <p>
545602e473dSmrg        <b>TODO:</b> These instructions are out of date.
546602e473dSmrg        Just reference the <a href="http://xcb.freedesktop.org/">main XCB page</a>
547602e473dSmrg        so we don't have to maintain these instructions in more than
548602e473dSmrg        one place.
549602e473dSmrg        </p>
550602e473dSmrg        <p>
551602e473dSmrg        To build XCB from source, you need to have installed at
552602e473dSmrg        least:
553602e473dSmrg        </p>
554602e473dSmrg        <ul>
555602e473dSmrg          <li>pkgconfig 0.15.0
556602e473dSmrg          <li><a href="http://www.gnu.org/software/automake/">automake 1.7</a>
557602e473dSmrg          <li><a href="http://www.gnu.org/software/autoconf/">autoconf 2.50</a>
558602e473dSmrg          <li><a href="http://www.check.org">check</a>
559602e473dSmrg          <li><a href="http://xmlsoft.org/XSLT/">xsltproc</a>
560602e473dSmrg          <li><a href="http://www.gnu.org/software/gperf/">gperf 3.0.1</a>
561602e473dSmrg        </ul>
562602e473dSmrg        <p>
563602e473dSmrg        You have to checkout in the git repository the following modules:
564602e473dSmrg        </p>
565602e473dSmrg        <ul>
566602e473dSmrg          <li>Xau from xlibs
567602e473dSmrg          <li>xcb-proto
568602e473dSmrg          <li>xcb
569602e473dSmrg        </ul>
570602e473dSmrg        <p>
571602e473dSmrg        Note that xcb-proto exists only to install header
572602e473dSmrg        files, so typing 'make' or 'make all' will produce the message
573602e473dSmrg        "Nothing to be done for 'all'". That's normal.
574602e473dSmrg        </p>
575602e473dSmrg        <li class="subtitle"><a name="comp">Compiling XCB-based programs</a>
576602e473dSmrg        <p>
577602e473dSmrg        Compiling XCB-based programs requires linking them with the XCB
578602e473dSmrg        library. This is easily done thanks to pkgconfig:
579602e473dSmrg        </p>
580602e473dSmrg        <pre class="text">
581602e473dSmrggcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb`
582602e473dSmrg</pre>
583602e473dSmrg      </ol>
584602e473dSmrg      <li class="title"><a name="openconn">Opening and closing the connection to an X server</a>
585602e473dSmrg      <p>
586602e473dSmrg      An X program first needs to open the connection to the X
587602e473dSmrg      server. There is a function that opens a connection. It requires
588602e473dSmrg      the display name, or NULL. In the latter case, the display name
589602e473dSmrg      will be the one in the environment variable DISPLAY.
590602e473dSmrg      </p>
591602e473dSmrg      <pre class="code">
592602e473dSmrg<span class="type">xcb_connection_t</span> *xcb_connect (<span class="keyword">const</span> <span class="type">char</span> *displayname,
593602e473dSmrg                               <span class="type">int</span>        *screenp);
594602e473dSmrg</pre>
595602e473dSmrg      <p>
596602e473dSmrg      The second parameter returns the screen number used for the
597602e473dSmrg      connection. The returned structure describes an XCB connection
598602e473dSmrg      and is opaque. Here is how the connection can be opened:
599602e473dSmrg      </p>
600602e473dSmrg      <pre class="code">
601602e473dSmrg#<span class="include">include</span> <span class="string">&lt;xcb/xcb.h&gt;</span>
602602e473dSmrg
603602e473dSmrg<span class="type">int</span>
604602e473dSmrg<span class="function">main</span> ()
605602e473dSmrg{
606602e473dSmrg  <span class="type">xcb_connection_t</span> *c;
607602e473dSmrg
608602e473dSmrg  /* Open the connection to the X server. Use the DISPLAY environment variable as the default display name */
609602e473dSmrg  c = xcb_connect (NULL, NULL);
610602e473dSmrg
611602e473dSmrg  <span class="keyword">return</span> 0;
612602e473dSmrg}
613602e473dSmrg</pre>
614602e473dSmrg      <p>
615602e473dSmrg      To close a connection, it suffices to use:
616602e473dSmrg      </p>
617602e473dSmrg      <pre class="code">
618602e473dSmrg<span class="type">void</span> xcb_disconnect (<span class="type">xcb_connection_t</span> *c);
619602e473dSmrg</pre>
620602e473dSmrg      <div class="comp">
621602e473dSmrg        <div class="title">
622602e473dSmrg        Comparison Xlib/XCB
623602e473dSmrg        </div>
624602e473dSmrg        <div class="xlib">
625602e473dSmrg        <ul>
626602e473dSmrg          <li>XOpenDisplay ()
627602e473dSmrg        </ul>
628602e473dSmrg        </div>
629602e473dSmrg        <div class="xcb">
630602e473dSmrg        <ul>
631602e473dSmrg          <li>xcb_connect ()
632602e473dSmrg        </ul>
633602e473dSmrg        </div>
634602e473dSmrg        <div class="xlib">
635602e473dSmrg        <ul>
636602e473dSmrg          <li>XCloseDisplay ()
637602e473dSmrg        </ul>
638602e473dSmrg        </div>
639602e473dSmrg        <div class="xcb">
640602e473dSmrg        <ul>
641602e473dSmrg          <li>xcb_disconnect ()
642602e473dSmrg        </ul>
643602e473dSmrg        </div>
644602e473dSmrg      </div>
645602e473dSmrg      <br>
646602e473dSmrg      <li class="title"><a name="screen">Checking basic information about a connection</a>
647602e473dSmrg      <p>
648602e473dSmrg      Once we have opened a connection to an X server, we should check some
649602e473dSmrg      basic information about it: what screens it has, what is the
650602e473dSmrg      size (width and height) of the screen, how many colors it
651602e473dSmrg      supports (black and white ? grey scale ?, 256 colors ? more ?),
652602e473dSmrg      and so on. We get such information from the xcb_screen_t
653602e473dSmrg      structure:
654602e473dSmrg      </p>
655602e473dSmrg      <pre class="code">
656602e473dSmrgtypedef struct {
657602e473dSmrg    xcb_window_t   root;
658602e473dSmrg    xcb_colormap_t default_colormap;
659602e473dSmrg    uint32_t       white_pixel;
660602e473dSmrg    uint32_t       black_pixel;
661602e473dSmrg    uint32_t       current_input_masks;
662602e473dSmrg    uint16_t       width_in_pixels;
663602e473dSmrg    uint16_t       height_in_pixels;
664602e473dSmrg    uint16_t       width_in_millimeters;
665602e473dSmrg    uint16_t       height_in_millimeters;
666602e473dSmrg    uint16_t       min_installed_maps;
667602e473dSmrg    uint16_t       max_installed_maps;
668602e473dSmrg    xcb_visualid_t root_visual;
669602e473dSmrg    uint8_t        backing_stores;
670602e473dSmrg    uint8_t        save_unders;
671602e473dSmrg    uint8_t        root_depth;
672602e473dSmrg    uint8_t        allowed_depths_len;
673602e473dSmrg} xcb_screen_t;
674602e473dSmrg</pre>
675602e473dSmrg      <p>
676602e473dSmrg      We could retrieve the first screen of the connection by using the
677602e473dSmrg      following function:
678602e473dSmrg      </p>
679602e473dSmrg      <pre class="code">
680602e473dSmrgxcb_screen_iterator_t xcb_setup_roots_iterator (xcb_setup_t *R);
681602e473dSmrg</pre>
682602e473dSmrg      <p>
683602e473dSmrg      Here is a small program that shows how to use this function:
684602e473dSmrg      </p>
685602e473dSmrg      <pre class="code">
686602e473dSmrg#include &lt;stdio.h&gt;
687602e473dSmrg
688602e473dSmrg#include &lt;xcb/xcb.h&gt;
689602e473dSmrg
690602e473dSmrgint
691602e473dSmrgmain ()
692602e473dSmrg{
693602e473dSmrg  xcb_connection_t     *c;
694602e473dSmrg  xcb_screen_t         *screen;
695602e473dSmrg  int                   screen_nbr;
696602e473dSmrg  xcb_screen_iterator_t iter;
697602e473dSmrg
698602e473dSmrg  /* Open the connection to the X server. Use the DISPLAY environment variable */
699602e473dSmrg  c = xcb_connect (NULL, &amp;screen_nbr);
700602e473dSmrg
701602e473dSmrg  /* Get the screen #screen_nbr */
702602e473dSmrg  iter = xcb_setup_roots_iterator (xcb_get_setup (c));
703602e473dSmrg  for (; iter.rem; --screen_nbr, xcb_screen_next (&amp;iter))
704602e473dSmrg    if (screen_nbr == 0) {
705602e473dSmrg      screen = iter.data;
706602e473dSmrg      break;
707602e473dSmrg    }
708602e473dSmrg
709602e473dSmrg  printf ("\n");
710602e473dSmrg  printf ("Informations of screen %ld:\n", screen-&gt;root);
711602e473dSmrg  printf ("  width.........: %d\n", screen-&gt;width_in_pixels);
712602e473dSmrg  printf ("  height........: %d\n", screen-&gt;height_in_pixels);
713602e473dSmrg  printf ("  white pixel...: %ld\n", screen-&gt;white_pixel);
714602e473dSmrg  printf ("  black pixel...: %ld\n", screen-&gt;black_pixel);
715602e473dSmrg  printf ("\n");
716602e473dSmrg
717602e473dSmrg  return 0;
718602e473dSmrg}
719602e473dSmrg</pre>
720602e473dSmrg      <li class="title"><a name="helloworld">Creating a basic window - the "hello world" program</a>
721602e473dSmrg      <p>
722602e473dSmrg      After we got some basic information about our screen, we can
723602e473dSmrg      create our first window. In the X Window System, a window is
724602e473dSmrg      characterized by an Id. So, in XCB, a window is of type:
725602e473dSmrg      </p>
726602e473dSmrg      <pre class="code">
727602e473dSmrgtypedef uint32_t xcb_window_t;
728602e473dSmrg</pre>
729602e473dSmrg      <p>
730602e473dSmrg      We first ask for a new Id for our window, with this function:
731602e473dSmrg      </p>
732602e473dSmrg      <pre class="code">
733602e473dSmrgxcb_window_t xcb_generate_id(xcb_connection_t *c);
734602e473dSmrg</pre>
735602e473dSmrg      <p>
736602e473dSmrg      Then, XCB supplies the following function to create new windows:
737602e473dSmrg      </p>
738602e473dSmrg      <pre class="code">
739602e473dSmrgxcb_void_cookie_t xcb_create_window (xcb_connection_t *c,             /* Pointer to the xcb_connection_t structure */
740602e473dSmrg                                     uint8_t           depth,         /* Depth of the screen */
741602e473dSmrg                                     xcb_window_t      wid,           /* Id of the window */
742602e473dSmrg                                     xcb_window_t      parent,        /* Id of an existing window that should be the parent of the new window */
743602e473dSmrg                                     int16_t           x,             /* X position of the top-left corner of the window (in pixels) */
744602e473dSmrg                                     int16_t           y,             /* Y position of the top-left corner of the window (in pixels) */
745602e473dSmrg                                     uint16_t          width,         /* Width of the window (in pixels) */
746602e473dSmrg                                     uint16_t          height,        /* Height of the window (in pixels) */
747602e473dSmrg                                     uint16_t          border_width,  /* Width of the window's border (in pixels) */
748602e473dSmrg                                     uint16_t          _class,
749602e473dSmrg                                     xcb_visualid_t    visual,
750602e473dSmrg                                     uint32_t          value_mask,
751602e473dSmrg                                     const uint32_t   *value_list);
752602e473dSmrg</pre>
753602e473dSmrg      <p>
754602e473dSmrg      The fact that we created the window does not mean that it will
755602e473dSmrg      be drawn on screen. By default, newly created windows are not
756602e473dSmrg      mapped on the screen (they are invisible). In order to make our
757602e473dSmrg      window visible, we use the function <span class="code">xcb_map_window()</span>, whose
758602e473dSmrg      prototype is
759602e473dSmrg      </p>
760602e473dSmrg      <pre class="code">
761602e473dSmrgxcb_void_cookie_t xcb_map_window (xcb_connection_t *c,
762602e473dSmrg                                  xcb_window_t      window);
763602e473dSmrg</pre>
764602e473dSmrg      <p>
765602e473dSmrg      Finally, here is a small program to create a window of size
766602e473dSmrg      150x150 pixels, positioned at the top-left corner of the screen:
767602e473dSmrg      </p>
768602e473dSmrg      <pre class="code">
769602e473dSmrg#include &lt;unistd.h&gt;      /* pause() */
770602e473dSmrg
771602e473dSmrg#include &lt;xcb/xcb.h&gt;
772602e473dSmrg
773602e473dSmrgint
774602e473dSmrgmain ()
775602e473dSmrg{
776602e473dSmrg  xcb_connection_t *c;
777602e473dSmrg  xcb_screen_t     *screen;
778602e473dSmrg  xcb_window_t      win;
779602e473dSmrg
780602e473dSmrg  /* Open the connection to the X server */
781602e473dSmrg  c = xcb_connect (NULL, NULL);
782602e473dSmrg
783602e473dSmrg  /* Get the first screen */
784602e473dSmrg  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
785602e473dSmrg
786602e473dSmrg  /* Ask for our window's Id */
787602e473dSmrg  win = xcb_generate_id(c);
788602e473dSmrg
789602e473dSmrg  /* Create the window */
790602e473dSmrg  xcb_create_window (c,                             /* Connection          */
791602e473dSmrg                     XCB_COPY_FROM_PARENT,          /* depth (same as root)*/
792602e473dSmrg                     win,                           /* window Id           */
793602e473dSmrg                     screen-&gt;root,                  /* parent window       */
794602e473dSmrg                     0, 0,                          /* x, y                */
795602e473dSmrg                     150, 150,                      /* width, height       */
796602e473dSmrg                     10,                            /* border_width        */
797602e473dSmrg                     XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
798602e473dSmrg                     screen-&gt;root_visual,           /* visual              */
799602e473dSmrg                     0, NULL);                      /* masks, not used yet */
800602e473dSmrg
801602e473dSmrg  /* Map the window on the screen */
802602e473dSmrg  xcb_map_window (c, win);
803602e473dSmrg
804602e473dSmrg  /* Make sure commands are sent before we pause, so window is shown */
805602e473dSmrg  xcb_flush (c);
806602e473dSmrg
807602e473dSmrg  pause ();    /* hold client until Ctrl-C */
808602e473dSmrg
809602e473dSmrg  return 0;
810602e473dSmrg}
811602e473dSmrg</pre>
812602e473dSmrg      <p>
813602e473dSmrg      In this code, you see one more function - <span class="code">xcb_flush()</span>, not explained
814602e473dSmrg      yet. It is used to flush all the pending requests. More
815602e473dSmrg      precisely, there are 2 functions that do such things. The first
816602e473dSmrg      one is <span class="code">xcb_flush()</span>:
817602e473dSmrg      </p>
818602e473dSmrg      <pre class="code">
819602e473dSmrgint xcb_flush (xcb_connection_t *c);
820602e473dSmrg</pre>
821602e473dSmrg      <p>
822602e473dSmrg      This function flushes all pending requests to the X server (much
823602e473dSmrg      like the <span class="code">fflush()</span> function is used to
824602e473dSmrg      flush standard output). The second function is
825602e473dSmrg      <span class="code">xcb_aux_sync()</span>:
826602e473dSmrg      </p>
827602e473dSmrg      <pre class="code">
828602e473dSmrgint xcb_aux_sync (xcb_connection_t *c);
829602e473dSmrg</pre>
830602e473dSmrg      <p>
831602e473dSmrg      This functions also flushes all pending requests to the X
832602e473dSmrg      server, and then waits until the X server finishing processing
833602e473dSmrg      these requests. In a normal program, this will not be necessary
834602e473dSmrg      (we'll see why when we get to write a normal X program), but for
835602e473dSmrg      now, we put it there.
836602e473dSmrg      </p>
837602e473dSmrg      <p>
838602e473dSmrg      The window that is created by the above code has a non defined
839602e473dSmrg      background. This one can be set to a specific color,
840602e473dSmrg      thanks to the two last parameters of
841602e473dSmrg      <span class="code">xcb_create_window()</span>, which are not
842602e473dSmrg      described yet. See the subsections
843602e473dSmrg      <a href="#winconf">Configuring a window</a> or
844602e473dSmrg      <a href="#winconf">Registering for event types using event masks</a>
845602e473dSmrg      for examples on how to use these parameters. In addition, as no
846602e473dSmrg      events are handled, you have to make a Ctrl-C to interrupt the
847602e473dSmrg      program.
848602e473dSmrg      </p>
849602e473dSmrg      <p>
850602e473dSmrg      <b>TODO</b>: one should tell what these functions return and
851602e473dSmrg      about the generic error
852602e473dSmrg      </p>
853602e473dSmrg      <div class="comp">
854602e473dSmrg        <div class="title">
855602e473dSmrg        Comparison Xlib/XCB
856602e473dSmrg        </div>
857602e473dSmrg        <div class="xlib">
858602e473dSmrg        <ul>
859602e473dSmrg          <li>XCreateWindow ()
860602e473dSmrg        </ul>
861602e473dSmrg        </div>
862602e473dSmrg        <div class="xcb">
863602e473dSmrg        <ul>
864602e473dSmrg          <li>xcb_generate_id ()
865602e473dSmrg          <li>xcb_create_window ()
866602e473dSmrg        </ul>
867602e473dSmrg        </div>
868602e473dSmrg      </div>
869602e473dSmrg      <br>
870602e473dSmrg      <li class="title"><a name="drawing">Drawing in a window</a>
871602e473dSmrg      <p>
872602e473dSmrg      Drawing in a window can be done using various graphical
873602e473dSmrg      functions (drawing pixels, lines, rectangles, etc). In order to
874602e473dSmrg      draw in a window, we first need to define various general
875602e473dSmrg      drawing parameters (what line width to use, which color to draw
876602e473dSmrg      with, etc). This is done using a graphical context.
877602e473dSmrg      </p>
878602e473dSmrg      <ol>
879602e473dSmrg        <li class="subtitle"><a name="allocgc">Allocating a Graphics Context</a>
880602e473dSmrg        <p>
881602e473dSmrg        As we said, a graphical context defines several attributes to
882602e473dSmrg        be used with the various drawing functions. For this, we
883602e473dSmrg        define a graphical context. We can use more than one graphical
884602e473dSmrg        context with a single window, in order to draw in multiple
885602e473dSmrg        styles (different colors, different line widths, etc). In XCB,
886602e473dSmrg        a Graphics Context is, as a window, characterized by an Id:
887602e473dSmrg        </p>
888602e473dSmrg        <pre class="code">
889602e473dSmrgtypedef uint32_t xcb_gcontext_t;
890602e473dSmrg</pre>
891602e473dSmrg        <p>
892602e473dSmrg        We first ask the X server to attribute an Id to our graphic
893602e473dSmrg        context with this function:
894602e473dSmrg        </p>
895602e473dSmrg        <pre class="code">
896602e473dSmrgxcb_gcontext_t xcb_generate_id (xcb_connection_t *c);
897602e473dSmrg</pre>
898602e473dSmrg        <p>
899602e473dSmrg        Then, we set the attributes of the graphic context with this function:
900602e473dSmrg        </p>
901602e473dSmrg        <pre class="code">
902602e473dSmrgxcb_void_cookie_t xcb_create_gc (xcb_connection_t *c,
903602e473dSmrg                                 xcb_gcontext_t    cid,
904602e473dSmrg                                 xcb_drawable_t    drawable,
905602e473dSmrg                                 uint32_t          value_mask,
906602e473dSmrg                                 const uint32_t   *value_list);
907602e473dSmrg</pre>
908602e473dSmrg        <p>
909602e473dSmrg        We give now an example on how to allocate a graphic context
910602e473dSmrg        that specifies that each drawing function that uses it will
911602e473dSmrg        draw in foreground with a black color.
912602e473dSmrg        </p>
913602e473dSmrg        <pre class="code">
914602e473dSmrg#include &lt;xcb/xcb.h&gt;
915602e473dSmrg
916602e473dSmrgint
917602e473dSmrgmain ()
918602e473dSmrg{
919602e473dSmrg  xcb_connection_t *c;
920602e473dSmrg  xcb_screen_t     *screen;
921602e473dSmrg  xcb_drawable_t    win;
922602e473dSmrg  xcb_gcontext_t    black;
923602e473dSmrg  uint32_t          mask;
924602e473dSmrg  uint32_t          value[1];
925602e473dSmrg
926602e473dSmrg  /* Open the connection to the X server and get the first screen */
927602e473dSmrg  c = xcb_connect (NULL, NULL);
928602e473dSmrg  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
929602e473dSmrg
930602e473dSmrg  /* Create a black graphic context for drawing in the foreground */
931602e473dSmrg  win = screen-&gt;root;
932602e473dSmrg  black = xcb_generate_id (c);
933602e473dSmrg  mask = XCB_GC_FOREGROUND;
934602e473dSmrg  value[0] = screen-&gt;black_pixel;
935602e473dSmrg  xcb_create_gc (c, black, win, mask, value);
936602e473dSmrg
937602e473dSmrg  return 0;
938602e473dSmrg}
939602e473dSmrg</pre>
940602e473dSmrg        <p>
941602e473dSmrg        Note should be taken regarding the role of "value_mask" and
942602e473dSmrg        "value_list" in the prototype of <span class="code">xcb_create_gc()</span>. Since a
943602e473dSmrg        graphic context has many attributes, and since we often just
944602e473dSmrg        want to define a few of them, we need to be able to tell the
945602e473dSmrg        <span class="code">xcb_create_gc()</span> which attributes we
946602e473dSmrg        want to set. This is what the "value_mask" parameter is
947602e473dSmrg        for. We then use the "value_list" parameter to specify actual
948602e473dSmrg        values for the attribute we defined in "value_mask". Thus, for
949602e473dSmrg        each constant used in "value_list", we will use the matching
950602e473dSmrg        constant in "value_mask". In this case, we define a graphic
951602e473dSmrg        context with one attribute: when drawing (a point, a line,
952602e473dSmrg        etc), the foreground color will be black. The rest of the
953602e473dSmrg        attributes of this graphic context will be set to their
954602e473dSmrg        default values.
955602e473dSmrg        </p>
956602e473dSmrg        <p>
957602e473dSmrg        See the next Subsection for more details.
958602e473dSmrg        </p>
959602e473dSmrg        <div class="comp">
960602e473dSmrg          <div class="title">
961602e473dSmrg          Comparison Xlib/XCB
962602e473dSmrg          </div>
963602e473dSmrg          <div class="xlib">
964602e473dSmrg          <ul>
965602e473dSmrg            <li>XCreateGC ()
966602e473dSmrg          </ul>
967602e473dSmrg          </div>
968602e473dSmrg          <div class="xcb">
969602e473dSmrg          <ul>
970602e473dSmrg            <li>xcb_generate_id ()
971602e473dSmrg            <li>xcb_create_gc ()
972602e473dSmrg          </ul>
973602e473dSmrg          </div>
974602e473dSmrg        </div>
975602e473dSmrg        <br>
976602e473dSmrg        <li class="subtitle"><a name="changegc">Changing the attributes of a Graphics Context</a>
977602e473dSmrg        <p>
978602e473dSmrg        Once we have allocated a Graphic Context, we may need to
979602e473dSmrg        change its attributes (for example, changing the foreground
980602e473dSmrg        color we use to draw a line, or changing the attributes of the
981602e473dSmrg        font we use to display strings. See Subsections Drawing with a
982602e473dSmrg        color and
983602e473dSmrg        <a href="#assigningfont">Assigning a Font to a Graphic Context</a>).
984602e473dSmrg        This is done by using this function:
985602e473dSmrg        </p>
986602e473dSmrg        <pre class="code">
987602e473dSmrgxcb_void_cookie_t xcb_change_gc (xcb_connection_t *c,           /* The XCB Connection */
988602e473dSmrg                                 xcb_gcontext_t    gc,          /* The Graphic Context */
989602e473dSmrg                                 uint32_t          value_mask,  /* Components of the Graphic Context that have to be set */
990602e473dSmrg                                 const uint32_t   *value_list); /* Value as specified by value_mask */
991602e473dSmrg</pre>
992602e473dSmrg        <p>
993602e473dSmrg        The <span class="code">value_mask</span> parameter could take
994602e473dSmrg        any combination of these masks from the xcb_gc_t enumeration:
995602e473dSmrg        </p>
996602e473dSmrg        <ul>
997602e473dSmrg          <li>XCB_GC_FUNCTION
998602e473dSmrg          <li>XCB_GC_PLANE_MASK
999602e473dSmrg          <li>XCB_GC_FOREGROUND
1000602e473dSmrg          <li>XCB_GC_BACKGROUND
1001602e473dSmrg          <li>XCB_GC_LINE_WIDTH
1002602e473dSmrg          <li>XCB_GC_LINE_STYLE
1003602e473dSmrg          <li>XCB_GC_CAP_STYLE
1004602e473dSmrg          <li>XCB_GC_JOIN_STYLE
1005602e473dSmrg          <li>XCB_GC_FILL_STYLE
1006602e473dSmrg          <li>XCB_GC_FILL_RULE
1007602e473dSmrg          <li>XCB_GC_TILE
1008602e473dSmrg          <li>XCB_GC_STIPPLE
1009602e473dSmrg          <li>XCB_GC_TILE_STIPPLE_ORIGIN_X
1010602e473dSmrg          <li>XCB_GC_TILE_STIPPLE_ORIGIN_Y
1011602e473dSmrg          <li>XCB_GC_FONT
1012602e473dSmrg          <li>XCB_GC_SUBWINDOW_MODE
1013602e473dSmrg          <li>XCB_GC_GRAPHICS_EXPOSURES
1014602e473dSmrg          <li>XCB_GC_CLIP_ORIGIN_X
1015602e473dSmrg          <li>XCB_GC_CLIP_ORIGIN_Y
1016602e473dSmrg          <li>XCB_GC_CLIP_MASK
1017602e473dSmrg          <li>XCB_GC_DASH_OFFSET
1018602e473dSmrg          <li>XCB_GC_DASH_LIST
1019602e473dSmrg          <li>XCB_GC_ARC_MODE
1020602e473dSmrg        </ul>
1021602e473dSmrg        <p>
1022602e473dSmrg        It is possible to set several attributes at the same
1023602e473dSmrg        time (for example setting the attributes of a font and the
1024602e473dSmrg        color which will be used to display a string), by OR'ing these
1025602e473dSmrg        values in <span class="code">value_mask</span>. Then
1026602e473dSmrg        <span class="code">value_list</span> has to be an array which
1027602e473dSmrg        lists the value for the respective attributes.  <b>These values
1028602e473dSmrg        must be in the same order as masks listed above.</b> See Subsection
1029602e473dSmrg        Drawing with a color to have an example.
1030602e473dSmrg        </p>
1031602e473dSmrg        <p>
1032602e473dSmrg        <b>TODO</b>: set the links of the 3 subsections, once they will
1033602e473dSmrg        be written :)
1034602e473dSmrg        </p>
1035602e473dSmrg        <p>
1036602e473dSmrg        <b>TODO</b>: give an example which sets several attributes.
1037602e473dSmrg        </p>
1038602e473dSmrg        <li class="subtitle"><a name="drawingprim">Drawing primitives: point, line, box, circle,...</a>
1039602e473dSmrg        <p>
1040602e473dSmrg        After we have created a Graphic Context, we can draw on a
1041602e473dSmrg        window using this Graphic Context, with a set of XCB
1042602e473dSmrg        functions, collectively called "drawing primitives". Let see
1043602e473dSmrg        how they are used.
1044602e473dSmrg        </p>
1045602e473dSmrg        <p>
1046602e473dSmrg        To draw a point, or several points, we use
1047602e473dSmrg        </p>
1048602e473dSmrg        <pre class="code">
1049602e473dSmrgxcb_void_cookie_t xcb_poly_point (xcb_connection_t  *c,               /* The connection to the X server */
1050602e473dSmrg                                  uint8_t            coordinate_mode, /* Coordinate mode, usually set to XCB_COORD_MODE_ORIGIN */
1051602e473dSmrg                                  xcb_drawable_t     drawable,        /* The drawable on which we want to draw the point(s) */
1052602e473dSmrg                                  xcb_gcontext_t     gc,              /* The Graphic Context we use to draw the point(s) */
1053602e473dSmrg                                  uint32_t           points_len,      /* The number of points */
1054602e473dSmrg                                  const xcb_point_t *points);         /* An array of points */
1055602e473dSmrg</pre>
1056602e473dSmrg        <p>
1057602e473dSmrg        The <span class="code">coordinate_mode</span> parameter
1058602e473dSmrg        specifies the coordinate mode.  Available values are
1059602e473dSmrg        </p>
1060602e473dSmrg        <ul>
1061602e473dSmrg          <li><span class="code">XCB_COORD_MODE_ORIGIN</span>
1062602e473dSmrg          <li><span class="code">XCB_COORD_MODE_PREVIOUS</span>
1063602e473dSmrg        </ul>
1064602e473dSmrg        <p>
1065602e473dSmrg        If XCB_COORD_MODE_PREVIOUS is used, then all points but the first one
1066602e473dSmrg        are relative to the immediately previous point.
1067602e473dSmrg        </p>
1068602e473dSmrg        <p>
1069602e473dSmrg        The <span class="code">xcb_point_t</span> type is just a
1070602e473dSmrg        structure with two fields (the coordinates of the point):
1071602e473dSmrg        </p>
1072602e473dSmrg        <pre class="code">
1073602e473dSmrgtypedef struct {
1074602e473dSmrg    int16_t x;
1075602e473dSmrg    int16_t y;
1076602e473dSmrg} xcb_point_t;
1077602e473dSmrg</pre>
1078602e473dSmrg        <p>
1079602e473dSmrg        You could see an example in xpoints.c. <b>TODO</b> Set the link.
1080602e473dSmrg        </p>
1081602e473dSmrg        <p>
1082602e473dSmrg        To draw a line, or a polygonal line, we use
1083602e473dSmrg        </p>
1084602e473dSmrg        <pre class="code">
1085602e473dSmrgxcb_void_cookie_t xcb_poly_line (xcb_connection_t  *c,               /* The connection to the X server */
1086602e473dSmrg                                 uint8_t            coordinate_mode, /* Coordinate mode, usually set to XCB_COORD_MODE_ORIGIN */
1087602e473dSmrg                                 xcb_drawable_t     drawable,        /* The drawable on which we want to draw the line(s) */
1088602e473dSmrg                                 xcb_gcontext_t     gc,              /* The Graphic Context we use to draw the line(s) */
1089602e473dSmrg                                 uint32_t           points_len,      /* The number of points in the polygonal line */
1090602e473dSmrg                                 const xcb_point_t *points);         /* An array of points */
1091602e473dSmrg</pre>
1092602e473dSmrg        <p>
1093602e473dSmrg        This function will draw the line between the first and the
1094602e473dSmrg        second points, then the line between the second and the third
1095602e473dSmrg        points, and so on.
1096602e473dSmrg        </p>
1097602e473dSmrg        <p>
1098602e473dSmrg        To draw a segment, or several segments, we use
1099602e473dSmrg        </p>
1100602e473dSmrg        <pre class="code">
1101602e473dSmrgxcb_void_cookie_t xcb_poly_segment (xcb_connection_t    *c,              /* The connection to the X server */
1102602e473dSmrg                                    xcb_drawable_t       drawable,       /* The drawable on which we want to draw the segment(s) */
1103602e473dSmrg                                    xcb_gcontext_t       gc,             /* The Graphic Context we use to draw the segment(s) */
1104602e473dSmrg                                    uint32_t             segments_len,   /* The number of segments */
1105602e473dSmrg                                    const xcb_segment_t *segments);      /* An array of segments */
1106602e473dSmrg</pre>
1107602e473dSmrg        <p>
1108602e473dSmrg        The <span class="code">xcb_segment_t</span> type is just a
1109602e473dSmrg        structure with four fields (the coordinates of the two points
1110602e473dSmrg        that define the segment):
1111602e473dSmrg        </p>
1112602e473dSmrg        <pre class="code">
1113602e473dSmrgtypedef struct {
1114602e473dSmrg    int16_t x1;
1115602e473dSmrg    int16_t y1;
1116602e473dSmrg    int16_t x2;
1117602e473dSmrg    int16_t y2;
1118602e473dSmrg} xcb_segment_t;
1119602e473dSmrg</pre>
1120602e473dSmrg        <p>
1121602e473dSmrg        To draw a rectangle, or several rectangles, we use
1122602e473dSmrg        </p>
1123602e473dSmrg        <pre class="code">
1124602e473dSmrgxcb_void_cookie_t xcb_poly_rectangle (xcb_connection_t      *c,              /* The connection to the X server */
1125602e473dSmrg                                      xcb_drawable_t         drawable,       /* The drawable on which we want to draw the rectangle(s) */
1126602e473dSmrg                                      xcb_gcontext_t         gc,             /* The Graphic Context we use to draw the rectangle(s) */
1127602e473dSmrg                                      uint32_t               rectangles_len, /* The number of rectangles */
1128602e473dSmrg                                      const xcb_rectangle_t *rectangles);    /* An array of rectangles */
1129602e473dSmrg</pre>
1130602e473dSmrg        <p>
1131602e473dSmrg        The <span class="code">xcb_rectangle_t</span> type is just a
1132602e473dSmrg        structure with four fields (the coordinates of the top-left
1133602e473dSmrg        corner of the rectangle, and its width and height):
1134602e473dSmrg        </p>
1135602e473dSmrg        <pre class="code">
1136602e473dSmrgtypedef struct {
1137602e473dSmrg    int16_t  x;
1138602e473dSmrg    int16_t  y;
1139602e473dSmrg    uint16_t width;
1140602e473dSmrg    uint16_t height;
1141602e473dSmrg} xcb_rectangle_t;
1142602e473dSmrg</pre>
1143602e473dSmrg        <!-- There's no coordinate_mode. Is it normal? -->
1144602e473dSmrg        <!-- [iano] Yes, it's not in the protocol. -->
1145602e473dSmrg        <p>
1146602e473dSmrg        To draw an elliptical arc, or several elliptical arcs, we use
1147602e473dSmrg        </p>
1148602e473dSmrg        <pre class="code">
1149602e473dSmrgxcb_void_cookie_t xcb_poly_arc (xcb_connection_t *c,          /* The connection to the X server */
1150602e473dSmrg                                xcb_drawable_t    drawable,   /* The drawable on which we want to draw the arc(s) */
1151602e473dSmrg                                xcb_gcontext_t    gc,         /* The Graphic Context we use to draw the arc(s) */
1152602e473dSmrg                                uint32_t          arcs_len,   /* The number of arcs */
1153602e473dSmrg                                const xcb_arc_t  *arcs);      /* An array of arcs */
1154602e473dSmrg</pre>
1155602e473dSmrg        <p>
1156602e473dSmrg        The <span class="code">xcb_arc_t</span> type is a structure with
1157602e473dSmrg        six fields:
1158602e473dSmrg        </p>
1159602e473dSmrg        <pre class="code">
1160602e473dSmrgtypedef struct {
1161602e473dSmrg    int16_t  x;       /* Top left x coordinate of the rectangle surrounding the ellipse */
1162602e473dSmrg    int16_t  y;       /* Top left y coordinate of the rectangle surrounding the ellipse */
1163602e473dSmrg    uint16_t width;   /* Width of the rectangle surrounding the ellipse */
1164602e473dSmrg    uint16_t height;  /* Height of the rectangle surrounding the ellipse */
1165602e473dSmrg    int16_t  angle1;  /* Angle at which the arc begins */
1166602e473dSmrg    int16_t  angle2;  /* Angle at which the arc ends */
1167602e473dSmrg} xcb_arc_t;
1168602e473dSmrg</pre>
1169602e473dSmrg        <div class="emph">
1170602e473dSmrg        <p>
1171602e473dSmrg        Note: the angles are expressed in units of 1/64 of a degree,
1172602e473dSmrg        so to have an angle of 90 degrees, starting at 0,
1173602e473dSmrg        <span class="code">angle1 = 0</span> and
1174602e473dSmrg        <span class="code">angle2 = 90 &lt;&lt; 6</span>. Positive angles
1175602e473dSmrg        indicate counterclockwise motion, while  negative angles
1176602e473dSmrg        indicate clockwise motion.
1177602e473dSmrg        </p>
1178602e473dSmrg        </div>
1179602e473dSmrg        <!-- I think that (x,y) should be the center of the
1180602e473dSmrg        ellipse, and (width, height) the radius. It's more logical. -->
1181602e473dSmrg        <!-- iano: Yes, and I bet some toolkits do that.
1182602e473dSmrg         But the protocol (and many other graphics APIs) define arcs
1183602e473dSmrg         by bounding rectangles. -->
1184602e473dSmrg        <p>
1185602e473dSmrg        The corresponding function which fill inside the geometrical
1186602e473dSmrg        object are listed below, without  further explanation, as they
1187602e473dSmrg        are used as the above functions.
1188602e473dSmrg        </p>
1189602e473dSmrg        <p>
1190602e473dSmrg        To Fill a polygon defined by the points given as arguments ,
1191602e473dSmrg        we use
1192602e473dSmrg        </p>
1193602e473dSmrg        <pre class="code">
1194602e473dSmrgxcb_void_cookie_t xcb_fill_poly (xcb_connection_t  *c,
1195602e473dSmrg                                 xcb_drawable_t     drawable,
1196602e473dSmrg                                 xcb_gcontext_t     gc,
1197602e473dSmrg                                 uint8_t            shape,
1198602e473dSmrg                                 uint8_t            coordinate_mode,
1199602e473dSmrg                                 uint32_t           points_len,
1200602e473dSmrg                                 const xcb_point_t *points);
1201602e473dSmrg</pre>
1202602e473dSmrg        <p>
1203602e473dSmrg        The <span class="code">shape</span> parameter specifies a
1204602e473dSmrg        shape that helps the server to improve performance. Available
1205602e473dSmrg        values are
1206602e473dSmrg        </p>
1207602e473dSmrg        <ul>
1208602e473dSmrg          <li><span class="code">XCB_POLY_SHAPE_COMPLEX</span>
1209602e473dSmrg          <li><span class="code">XCB_POLY_SHAPE_NONCONVEX</span>
1210602e473dSmrg          <li><span class="code">XCB_POLY_SHAPE_CONVEX</span>
1211602e473dSmrg        </ul>
1212602e473dSmrg        <p>
1213602e473dSmrg        To fill one or several rectangles, we use
1214602e473dSmrg        </p>
1215602e473dSmrg        <pre class="code">
1216602e473dSmrgxcb_void_cookie_t xcb_poly_fill_rectangle (xcb_connection_t      *c,
1217602e473dSmrg                                           xcb_drawable_t         drawable,
1218602e473dSmrg                                           xcb_gcontext_t         gc,
1219602e473dSmrg                                           uint32_t               rectangles_len,
1220602e473dSmrg                                           const xcb_rectangle_t *rectangles);
1221602e473dSmrg</pre>
1222602e473dSmrg        <p>
1223602e473dSmrg        To fill one or several arcs, we use
1224602e473dSmrg        </p>
1225602e473dSmrg        <pre class="code">
1226602e473dSmrgxcb_void_cookie_t xcb_poly_fill_arc (xcb_connection_t *c,
1227602e473dSmrg                                     xcb_drawable_t    drawable,
1228602e473dSmrg                                     xcb_gcontext_t    gc,
1229602e473dSmrg                                     uint32_t          arcs_len,
1230602e473dSmrg                                     const xcb_arc_t  *arcs);
1231602e473dSmrg</pre>
1232602e473dSmrg        <br>
1233602e473dSmrg        <a name="points.c"></a>
1234602e473dSmrg        <p>
1235602e473dSmrg        To illustrate these functions, here is an example that draws
1236602e473dSmrg        four points, a polygonal line, two segments, two rectangles
1237602e473dSmrg        and two arcs. Remark that we use events for the first time, as
1238602e473dSmrg        an introduction to the next section.
1239602e473dSmrg        </p>
1240602e473dSmrg        <p>
1241602e473dSmrg        <b>TODO:</b> Use screen-&gt;root_depth for depth parameter.
1242602e473dSmrg        </p>
1243602e473dSmrg        <pre class="code">
1244602e473dSmrg#include &lt;stdlib.h&gt;
1245602e473dSmrg#include &lt;stdio.h&gt;
1246602e473dSmrg
1247602e473dSmrg#include &lt;xcb/xcb.h&gt;
1248602e473dSmrg
1249602e473dSmrgint
1250602e473dSmrgmain ()
1251602e473dSmrg{
1252602e473dSmrg  xcb_connection_t    *c;
1253602e473dSmrg  xcb_screen_t        *screen;
1254602e473dSmrg  xcb_drawable_t       win;
1255602e473dSmrg  xcb_gcontext_t       foreground;
1256602e473dSmrg  xcb_generic_event_t *e;
1257602e473dSmrg  uint32_t             mask = 0;
1258602e473dSmrg  uint32_t             values[2];
1259602e473dSmrg
1260602e473dSmrg  /* geometric objects */
1261602e473dSmrg  xcb_point_t          points[] = {
1262602e473dSmrg    {10, 10},
1263602e473dSmrg    {10, 20},
1264602e473dSmrg    {20, 10},
1265602e473dSmrg    {20, 20}};
1266602e473dSmrg
1267602e473dSmrg  xcb_point_t          polyline[] = {
1268602e473dSmrg    {50, 10},
1269602e473dSmrg    { 5, 20},     /* rest of points are relative */
1270602e473dSmrg    {25,-20},
1271602e473dSmrg    {10, 10}};
1272602e473dSmrg
1273602e473dSmrg  xcb_segment_t        segments[] = {
1274602e473dSmrg    {100, 10, 140, 30},
1275602e473dSmrg    {110, 25, 130, 60}};
1276602e473dSmrg
1277602e473dSmrg  xcb_rectangle_t      rectangles[] = {
1278602e473dSmrg    { 10, 50, 40, 20},
1279602e473dSmrg    { 80, 50, 10, 40}};
1280602e473dSmrg
1281602e473dSmrg  xcb_arc_t            arcs[] = {
1282602e473dSmrg    {10, 100, 60, 40, 0, 90 &lt;&lt; 6},
1283602e473dSmrg    {90, 100, 55, 40, 0, 270 &lt;&lt; 6}};
1284602e473dSmrg
1285602e473dSmrg  /* Open the connection to the X server */
1286602e473dSmrg  c = xcb_connect (NULL, NULL);
1287602e473dSmrg
1288602e473dSmrg  /* Get the first screen */
1289602e473dSmrg  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
1290602e473dSmrg
1291602e473dSmrg  /* Create black (foreground) graphic context */
1292602e473dSmrg  win = screen-&gt;root;
1293602e473dSmrg
1294602e473dSmrg  foreground = xcb_generate_id (c);
1295602e473dSmrg  mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
1296602e473dSmrg  values[0] = screen-&gt;black_pixel;
1297602e473dSmrg  values[1] = 0;
1298602e473dSmrg  xcb_create_gc (c, foreground, win, mask, values);
1299602e473dSmrg
1300602e473dSmrg  /* Ask for our window's Id */
1301602e473dSmrg  win = xcb_generate_id(c);
1302602e473dSmrg
1303602e473dSmrg  /* Create the window */
1304602e473dSmrg  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
1305602e473dSmrg  values[0] = screen-&gt;white_pixel;
1306602e473dSmrg  values[1] = XCB_EVENT_MASK_EXPOSURE;
1307602e473dSmrg  xcb_create_window (c,                             /* Connection          */
1308602e473dSmrg                     XCB_COPY_FROM_PARENT,          /* depth               */
1309602e473dSmrg                     win,                           /* window Id           */
1310602e473dSmrg                     screen-&gt;root,                  /* parent window       */
1311602e473dSmrg                     0, 0,                          /* x, y                */
1312602e473dSmrg                     150, 150,                      /* width, height       */
1313602e473dSmrg                     10,                            /* border_width        */
1314602e473dSmrg                     XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
1315602e473dSmrg                     screen-&gt;root_visual,           /* visual              */
1316602e473dSmrg                     mask, values);                 /* masks */
1317602e473dSmrg
1318602e473dSmrg  /* Map the window on the screen */
1319602e473dSmrg  xcb_map_window (c, win);
1320602e473dSmrg
1321602e473dSmrg
1322602e473dSmrg  /* We flush the request */
1323602e473dSmrg  xcb_flush (c);
1324602e473dSmrg
1325602e473dSmrg  while ((e = xcb_wait_for_event (c))) {
1326602e473dSmrg    switch (e-&gt;response_type &amp; ~0x80) {
1327602e473dSmrg    case XCB_EXPOSE: {
1328602e473dSmrg      /* We draw the points */
1329602e473dSmrg      xcb_poly_point (c, XCB_COORD_MODE_ORIGIN, win, foreground, 4, points);
1330602e473dSmrg
1331602e473dSmrg      /* We draw the polygonal line */
1332602e473dSmrg      xcb_poly_line (c, XCB_COORD_MODE_PREVIOUS, win, foreground, 4, polyline);
1333602e473dSmrg
13341c7386f4Smrg      /* We draw the segments */
1335602e473dSmrg      xcb_poly_segment (c, win, foreground, 2, segments);
1336602e473dSmrg
1337602e473dSmrg      /* We draw the rectangles */
1338602e473dSmrg      xcb_poly_rectangle (c, win, foreground, 2, rectangles);
1339602e473dSmrg
1340602e473dSmrg      /* We draw the arcs */
1341602e473dSmrg      xcb_poly_arc (c, win, foreground, 2, arcs);
1342602e473dSmrg
1343602e473dSmrg      /* We flush the request */
1344602e473dSmrg      xcb_flush (c);
1345602e473dSmrg
1346602e473dSmrg      break;
1347602e473dSmrg    }
1348602e473dSmrg    default: {
1349602e473dSmrg      /* Unknown event type, ignore it */
1350602e473dSmrg      break;
1351602e473dSmrg    }
1352602e473dSmrg    }
1353602e473dSmrg    /* Free the Generic Event */
1354602e473dSmrg    free (e);
1355602e473dSmrg  }
1356602e473dSmrg
1357602e473dSmrg  return 0;
1358602e473dSmrg}
1359602e473dSmrg</pre>
1360602e473dSmrg      </ol>
1361602e473dSmrg      <li class="title"><a name="xevents">X Events</a>
1362602e473dSmrg      <p>
1363602e473dSmrg      In an X program, everything is driven by events. Event painting
1364602e473dSmrg      on the screen is sometimes done as a response to an event (an
1365602e473dSmrg      <span class="code">Expose</span> event). If part of a program's
1366602e473dSmrg      window that was hidden, gets exposed (e.g. the window was raised
1367602e473dSmrg      above other widows), the X server will send an "expose" event to
1368602e473dSmrg      let the program know it should repaint that part of the
1369602e473dSmrg      window. User input (key presses, mouse movement, etc) is also
1370602e473dSmrg      received as a set of events.
1371602e473dSmrg      </p>
1372602e473dSmrg      <ol>
1373602e473dSmrg        <li class="subtitle"><a name="register">Registering for event types using event masks</a>
1374602e473dSmrg        <p>
1375602e473dSmrg        During the creation of a window, you should give it what kind
1376602e473dSmrg        of events it wishes to receive. Thus, you may register for
1377602e473dSmrg        various mouse (also called pointer) events, keyboard events,
1378602e473dSmrg        expose events, and so on. This is done for optimizing the
1379602e473dSmrg        server-to-client connection (i.e. why send a program (that
1380602e473dSmrg        might even be running at the other side of the globe) an event
1381602e473dSmrg        it is not interested in ?)
1382602e473dSmrg        </p>
1383602e473dSmrg        <p>
1384602e473dSmrg        In XCB, you use the "value_mask" and "value_list" data in the
1385602e473dSmrg        <span class="code">xcb_create_window()</span> function to
1386602e473dSmrg        register for events. Here is how we register for
1387602e473dSmrg        <span class="code">Expose</span> event when creating a window:
1388602e473dSmrg        </p>
1389602e473dSmrg        <pre class="code">
1390602e473dSmrg  mask = XCB_CW_EVENT_MASK;
1391602e473dSmrg  valwin[0] = XCB_EVENT_MASK_EXPOSURE;
1392602e473dSmrg  win = xcb_generate_id (c);
1393602e473dSmrg  xcb_create_window (c, depth, win, root-&gt;root,
1394602e473dSmrg                     0, 0, 150, 150, 10,
1395602e473dSmrg                     XCB_WINDOW_CLASS_INPUT_OUTPUT, root-&gt;root_visual,
1396602e473dSmrg                     mask, valwin);
1397602e473dSmrg</pre>
1398602e473dSmrg        <p>
1399602e473dSmrg        <span class="code">XCB_EVENT_MASK_EXPOSURE</span> is a constant defined
1400602e473dSmrg        in the xcb_event_mask_t enumeration in the "xproto.h" header file. If we wanted to register for several
1401602e473dSmrg        event types, we can logically "or" them, as follows:
1402602e473dSmrg        </p>
1403602e473dSmrg        <pre class="code">
1404602e473dSmrg  mask = XCB_CW_EVENT_MASK;
1405602e473dSmrg  valwin[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS;
1406602e473dSmrg  win = xcb_generate_id (c);
1407602e473dSmrg  xcb_create_window (c, depth, win, root-&gt;root,
1408602e473dSmrg                     0, 0, 150, 150, 10,
1409602e473dSmrg                     XCB_WINDOW_CLASS_INPUT_OUTPUT, root-&gt;root_visual,
1410602e473dSmrg                     mask, valwin);
1411602e473dSmrg</pre>
1412602e473dSmrg        <p>
1413602e473dSmrg        This registers for <span class="code">Expose</span> events as
1414602e473dSmrg        well as for mouse button presses inside the created
1415602e473dSmrg        window. You should note that a mask may represent several
1416602e473dSmrg        event sub-types.
1417602e473dSmrg        </p>
1418602e473dSmrg        <p>
1419602e473dSmrg        The values that a mask could take are given
1420602e473dSmrg        by the <span class="code">xcb_cw_t</span> enumeration:
1421602e473dSmrg        </p>
1422602e473dSmrg        <pre class="code">
1423602e473dSmrgtypedef enum {
1424602e473dSmrg    XCB_CW_BACK_PIXMAP       = 1L<<0,
1425602e473dSmrg    XCB_CW_BACK_PIXEL        = 1L<<1,
1426602e473dSmrg    XCB_CW_BORDER_PIXMAP     = 1L<<2,
1427602e473dSmrg    XCB_CW_BORDER_PIXEL      = 1L<<3,
1428602e473dSmrg    XCB_CW_BIT_GRAVITY       = 1L<<4,
1429602e473dSmrg    XCB_CW_WIN_GRAVITY       = 1L<<5,
1430602e473dSmrg    XCB_CW_BACKING_STORE     = 1L<<6,
1431602e473dSmrg    XCB_CW_BACKING_PLANES    = 1L<<7,
1432602e473dSmrg    XCB_CW_BACKING_PIXEL     = 1L<<8,
1433602e473dSmrg    XCB_CW_OVERRIDE_REDIRECT = 1L<<9,
1434602e473dSmrg    XCB_CW_SAVE_UNDER        = 1L<<10,
1435602e473dSmrg    XCB_CW_EVENT_MASK        = 1L<<11,
1436602e473dSmrg    XCB_CW_DONT_PROPAGATE    = 1L<<12,
1437602e473dSmrg    XCB_CW_COLORMAP          = 1L<<13,
1438602e473dSmrg    XCB_CW_CURSOR            = 1L<<14
1439602e473dSmrg} xcb_cw_t;
1440602e473dSmrg</pre>
1441602e473dSmrg        <div class="emph">
1442602e473dSmrg        <p>Note: we must be careful when setting the values of the valwin
1443602e473dSmrg        parameter, as they have to follow the order the
1444602e473dSmrg        <span class="code">xcb_cw_t</span> enumeration. Here is an
1445602e473dSmrg        example:
1446602e473dSmrg        </p>
1447602e473dSmrg        </div>
1448602e473dSmrg        <pre class="code">
1449602e473dSmrg  mask = XCB_CW_EVENT_MASK | XCB_CW_BACK_PIXMAP;
1450602e473dSmrg  valwin[0] = XCB_NONE;                                              /* for XCB_CW_BACK_PIXMAP (whose value is 1)     */
1451602e473dSmrg  valwin[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS; /* for XCB_CW_EVENT_MASK, whose value (2048)     */
1452602e473dSmrg                                                                     /* is greater than the one of XCB_CW_BACK_PIXMAP */
1453602e473dSmrg</pre>
1454602e473dSmrg        <p>
1455602e473dSmrg        If the window has already been created, we can use the
1456b20a2039Smrg        <span class="code">xcb_change_window_attributes()</span> function to set
1457602e473dSmrg        the events that the window will receive. The subsection
1458602e473dSmrg        <a href="#winconf">Configuring a window</a> shows its
1459602e473dSmrg        prototype. As an example, here is a piece of code that
1460602e473dSmrg        configures the window to receive the
1461602e473dSmrg        <span class="code">Expose</span> and
1462602e473dSmrg        <span class="code">ButtonPress</span> events:
1463602e473dSmrg        </p>
1464602e473dSmrg        <pre class="code">
1465602e473dSmrgconst static uint32_t values[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS };
1466602e473dSmrg
1467602e473dSmrg/* The connection c and the window win are supposed to be defined */
1468602e473dSmrg
1469b20a2039Smrgxcb_change_window_attributes (c, win, XCB_CW_EVENT_MASK, values);
1470602e473dSmrg</pre>
1471602e473dSmrg        <div class="emph">
1472602e473dSmrg        <p>
14731c7386f4Smrg        Note: A common bug programmers have is adding code to handle new
1474602e473dSmrg        event types in their program, while forgetting to add the
1475602e473dSmrg        masks for these events in the creation of the window. Such a
14761c7386f4Smrg        programmer would then sit there for hours debugging their
1477602e473dSmrg        program, wondering "Why doesn't my program notice that I
1478602e473dSmrg        released the button?", only to find that they registered for
1479602e473dSmrg        button press events but not for button release events.
1480602e473dSmrg        </p>
1481602e473dSmrg        </div>
1482602e473dSmrg        <li class="subtitle"><a name="loop">Receiving events: writing the events loop</a>
1483602e473dSmrg        <p>
1484602e473dSmrg        After we have registered for the event types we are interested
1485602e473dSmrg        in, we need to enter a loop of receiving events and handling
1486602e473dSmrg        them. There are two ways to receive events: a blocking way and
1487602e473dSmrg        a non-blocking way:
1488602e473dSmrg        </p>
1489602e473dSmrg        <ul>
1490602e473dSmrg          <li>
1491602e473dSmrg          <span class="code">xcb_wait_for_event (xcb_connection_t *c)</span>
1492602e473dSmrg          is the blocking way. It waits (so blocks...) until an event is
1493602e473dSmrg          queued in the X server. Then it retrieves it into a newly
1494602e473dSmrg          allocated structure (it dequeues it from the queue) and returns
1495602e473dSmrg          it. This structure has to be freed. The function returns
1496602e473dSmrg          <span class="code">NULL</span> if an error occurs.
1497602e473dSmrg
1498602e473dSmrg          <br>
1499602e473dSmrg          <li>
1500602e473dSmrg          <span class="code">xcb_poll_for_event (xcb_connection_t *c, int
1501602e473dSmrg          *error)</span> is the non-blocking way. It looks at the event
1502602e473dSmrg          queue and returns (and dequeues too) an existing event into
1503602e473dSmrg          a newly allocated structure. This structure has to be
1504602e473dSmrg          freed. It returns <span class="code">NULL</span> if there is
1505602e473dSmrg          no event. If an error occurs, the parameter <span
1506602e473dSmrg          class="code">error</span> will be filled with the error
1507602e473dSmrg          status.
1508602e473dSmrg        </ul>
1509602e473dSmrg        <p>
1510602e473dSmrg        There are various ways to write such a loop. We present two
1511602e473dSmrg        ways to write such a loop, with the two functions above. The
1512602e473dSmrg        first one uses <span class="code">xcb_wait_for_event_t</span>, which
1513602e473dSmrg        is similar to an event Xlib loop using only <span
1514602e473dSmrg        class="code">XNextEvent</span>:
1515602e473dSmrg        </p>
1516602e473dSmrg        <pre class="code">
1517602e473dSmrg  xcb_generic_event_t *e;
1518602e473dSmrg
1519602e473dSmrg  while ((e = xcb_wait_for_event (c))) {
1520602e473dSmrg    switch (e-&gt;response_type &amp; ~0x80) {
1521602e473dSmrg    case XCB_EXPOSE: {
1522602e473dSmrg      /* Handle the Expose event type */
1523602e473dSmrg      xcb_expose_event_t *ev = (xcb_expose_event_t *)e;
1524602e473dSmrg
1525602e473dSmrg      /* ... */
1526602e473dSmrg
1527602e473dSmrg      break;
1528602e473dSmrg    }
1529602e473dSmrg    case XCB_BUTTON_PRESS: {
1530602e473dSmrg      /* Handle the ButtonPress event type */
1531602e473dSmrg      xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e;
1532602e473dSmrg
1533602e473dSmrg      /* ... */
1534602e473dSmrg
1535602e473dSmrg      break;
1536602e473dSmrg    }
1537602e473dSmrg    default: {
1538602e473dSmrg      /* Unknown event type, ignore it */
1539602e473dSmrg      break;
1540602e473dSmrg    }
1541602e473dSmrg    }
1542602e473dSmrg    /* Free the Generic Event */
1543602e473dSmrg    free (e);
1544602e473dSmrg  }
1545602e473dSmrg</pre>
1546602e473dSmrg        <p>
1547602e473dSmrg        You will certainly want to use <span
1548602e473dSmrg        class="code">xcb_poll_for_event(xcb_connection_t *c, int
1549602e473dSmrg        *error)</span> if, in Xlib, you use <span
1550602e473dSmrg        class="code">XPending</span> or
1551602e473dSmrg        <span class="code">XCheckMaskEvent</span>:
1552602e473dSmrg        </p>
1553602e473dSmrg        <pre class="code">
1554602e473dSmrg  while (XPending (display)) {
1555602e473dSmrg    XEvent ev;
1556602e473dSmrg
1557602e473dSmrg    XNextEvent(d, &amp;ev);
1558602e473dSmrg
1559602e473dSmrg    /* Manage your event */
1560602e473dSmrg  }
1561602e473dSmrg</pre>
1562602e473dSmrg        <p>
1563602e473dSmrg        Such a loop in XCB looks like:
1564602e473dSmrg        </p>
1565602e473dSmrg        <pre class="code">
1566602e473dSmrg  xcb_generic_event_t *ev;
1567602e473dSmrg
1568602e473dSmrg  while ((ev = xcb_poll_for_event (conn, 0))) {
1569602e473dSmrg    /* Manage your event */
1570602e473dSmrg  }
1571602e473dSmrg</pre>
1572602e473dSmrg        <p>
1573602e473dSmrg        The events are managed in the same way as with <span
1574602e473dSmrg        class="code">xcb_wait_for_event_t</span>.
1575602e473dSmrg        Obviously, we will need to give the user some way of
1576602e473dSmrg        terminating the program. This is usually done by handling a
1577602e473dSmrg        special "quit" event, as we will soon see.
1578602e473dSmrg        </p>
1579602e473dSmrg        <div class="comp">
1580602e473dSmrg          <div class="title">
1581602e473dSmrg            Comparison Xlib/XCB
1582602e473dSmrg          </div>
1583602e473dSmrg          <div class="xlib">
1584602e473dSmrg            <ul>
1585602e473dSmrg              <li>XNextEvent ()
1586602e473dSmrg              </ul>
1587602e473dSmrg          </div>
1588602e473dSmrg          <div class="xcb">
1589602e473dSmrg            <ul>
1590602e473dSmrg              <li>xcb_wait_for_event ()
1591602e473dSmrg            </ul>
1592602e473dSmrg          </div>
1593602e473dSmrg          <div class="xlib">
1594602e473dSmrg            <ul>
1595602e473dSmrg              <li>XPending ()
1596602e473dSmrg              <li>XCheckMaskEvent ()
1597602e473dSmrg            </ul>
1598602e473dSmrg          </div>
1599602e473dSmrg          <div class="xcb">
1600602e473dSmrg            <ul>
1601602e473dSmrg              <li>xcb_poll_for_event ()
1602602e473dSmrg            </ul>
1603602e473dSmrg          </div>
1604602e473dSmrg        </div>
1605602e473dSmrg        <br>
1606602e473dSmrg        <li class="subtitle"><a name="expose">Expose events</a>
1607602e473dSmrg        <p>
1608602e473dSmrg        The <span class="code">Expose</span> event is one of the most
1609602e473dSmrg        basic (and most used) events an application may receive. It
1610602e473dSmrg        will be sent to us in one of several cases:
1611602e473dSmrg        </p>
1612602e473dSmrg        <ul>
1613602e473dSmrg          <li>A window that covered part of our window has moved
1614602e473dSmrg              away, exposing part (or all) of our window.
1615602e473dSmrg          <li>Our window was raised above other windows.
1616602e473dSmrg          <li>Our window mapped for the first time.
1617602e473dSmrg          <li>Our window was de-iconified.
1618602e473dSmrg        </ul>
1619602e473dSmrg        <p>
1620602e473dSmrg        You should note the implicit assumption hidden here: the
1621602e473dSmrg        contents of our window is lost when it is being obscured
1622602e473dSmrg        (covered) by either windows. One may wonder why the X server
1623602e473dSmrg        does not save this contents. The answer is: to save
1624602e473dSmrg        memory. After all, the number of windows on a display at a
1625602e473dSmrg        given time may be very large, and storing the contents of all
1626602e473dSmrg        of them might require a lot of memory. Actually, there is a
1627602e473dSmrg        way to tell the X server to store  the contents of a window in
1628602e473dSmrg        special cases, as we will see later.
1629602e473dSmrg        </p>
1630602e473dSmrg        <p>
1631602e473dSmrg        When we get an <span class="code">Expose</span> event, we
1632602e473dSmrg        should take the event's data from the members of the following
1633602e473dSmrg        structure:
1634602e473dSmrg        </p>
1635602e473dSmrg        <pre class="code">
1636602e473dSmrgtypedef struct {
1637602e473dSmrg    uint8_t      response_type; /* The type of the event, here it is XCB_EXPOSE */
1638602e473dSmrg    uint8_t      pad0;
1639602e473dSmrg    uint16_t     sequence;
1640602e473dSmrg    xcb_window_t window;        /* The Id of the window that receives the event (in case */
1641602e473dSmrg                                /* our application registered for events on several windows */
1642602e473dSmrg    uint16_t     x;             /* The x coordinate of the top-left part of the window that needs to be redrawn */
1643602e473dSmrg    uint16_t     y;             /* The y coordinate of the top-left part of the window that needs to be redrawn */
1644602e473dSmrg    uint16_t     width;         /* The width of the part of the window that needs to be redrawn */
1645602e473dSmrg    uint16_t     height;        /* The height of the part of the window that needs to be redrawn */
1646602e473dSmrg    uint16_t     count;
1647602e473dSmrg} xcb_expose_event_t;
1648602e473dSmrg</pre>
1649602e473dSmrg        <li class="subtitle"><a name="userinput">Getting user input</a>
1650602e473dSmrg        <p>
1651602e473dSmrg        User input traditionally comes from two sources: the mouse
1652602e473dSmrg        and the keyboard. Various event types exist to notify us of
1653602e473dSmrg        user input (a key being presses on the keyboard, a key being
1654602e473dSmrg        released on the keyboard, the mouse moving over our window,
1655602e473dSmrg        the mouse entering (or leaving) our window, and so on.
1656602e473dSmrg        </p>
1657602e473dSmrg        <ol>
1658602e473dSmrg            <li class="subsubtitle"><a name="mousepressrelease">Mouse button press and release events</a>
1659602e473dSmrg          <p>
1660602e473dSmrg          The first event type we will deal with is a mouse
1661602e473dSmrg          button-press (or button-release) event in our window. In
1662602e473dSmrg          order to register to such an event type, we should add one
1663602e473dSmrg          (or more) of the following masks when we create our window:
1664602e473dSmrg          </p>
1665602e473dSmrg          <ul>
1666602e473dSmrg            <li><span class="code">XCB_EVENT_MASK_BUTTON_PRESS</span>: notify us
1667602e473dSmrg            of any button that was pressed in one of our windows.
1668602e473dSmrg            <li><span class="code">XCB_EVENT_MASK_BUTTON_RELEASE</span>: notify us
1669602e473dSmrg            of any button that was released in one of our windows.
1670602e473dSmrg          </ul>
1671602e473dSmrg          <p>
1672602e473dSmrg          The structure to be checked for in our events loop is the
1673602e473dSmrg          same for these two events, and is the following:
1674602e473dSmrg          </p>
1675602e473dSmrg          <pre class="code">
1676602e473dSmrgtypedef struct {
1677602e473dSmrg    uint8_t         response_type; /* The type of the event, here it is xcb_button_press_event_t or xcb_button_release_event_t */
1678602e473dSmrg    xcb_button_t    detail;
1679602e473dSmrg    uint16_t        sequence;
1680602e473dSmrg    xcb_timestamp_t time;          /* Time, in milliseconds the event took place in */
1681602e473dSmrg    xcb_window_t    root;
1682602e473dSmrg    xcb_window_t    event;
1683602e473dSmrg    xcb_window_t    child;
1684602e473dSmrg    int16_t         root_x;
1685602e473dSmrg    int16_t         root_y;
1686602e473dSmrg    int16_t         event_x;       /* The x coordinate where the mouse has been pressed in the window */
1687602e473dSmrg    int16_t         event_y;       /* The y coordinate where the mouse has been pressed in the window */
1688602e473dSmrg    uint16_t        state;         /* A mask of the buttons (or keys) during the event */
1689602e473dSmrg    uint8_t         same_screen;
1690602e473dSmrg} xcb_button_press_event_t;
1691602e473dSmrg
1692602e473dSmrgtypedef xcb_button_press_event_t xcb_button_release_event_t;
1693602e473dSmrg</pre>
1694602e473dSmrg          <p>
1695602e473dSmrg          The <span class="code">time</span> field may be used to calculate "double-click"
1696602e473dSmrg          situations by an application (e.g. if the mouse button was
1697602e473dSmrg          clicked two times in a duration shorter than a given amount
1698602e473dSmrg          of time, assume this was a double click).
1699602e473dSmrg          </p>
1700602e473dSmrg          <p>
1701602e473dSmrg          The <span class="code">state</span> field is a mask of the buttons held down during
1702602e473dSmrg          the event. It is a bitwise OR of any of the following (from the xcb_button_mask_t and
1703602e473dSmrg          xcb_mod_mask_t enumerations):
1704602e473dSmrg          </p>
1705602e473dSmrg          <ul>
1706602e473dSmrg            <li><span class="code">XCB_BUTTON_MASK_1</span>
1707602e473dSmrg            <li><span class="code">XCB_BUTTON_MASK_2</span>
1708602e473dSmrg            <li><span class="code">XCB_BUTTON_MASK_3</span>
1709602e473dSmrg            <li><span class="code">XCB_BUTTON_MASK_4</span>
1710602e473dSmrg            <li><span class="code">XCB_BUTTON_MASK_5</span>
1711602e473dSmrg            <li><span class="code">XCB_MOD_MASK_SHIFT</span>
1712602e473dSmrg            <li><span class="code">XCB_MOD_MASK_LOCK</span>
1713602e473dSmrg            <li><span class="code">XCB_MOD_MASK_CONTROL</span>
1714602e473dSmrg            <li><span class="code">XCB_MOD_MASK_1</span>
1715602e473dSmrg            <li><span class="code">XCB_MOD_MASK_2</span>
1716602e473dSmrg            <li><span class="code">XCB_MOD_MASK_3</span>
1717602e473dSmrg            <li><span class="code">XCB_MOD_MASK_4</span>
1718602e473dSmrg            <li><span class="code">XCB_MOD_MASK_5</span>
1719602e473dSmrg          </ul>
1720602e473dSmrg          <p>
1721602e473dSmrg          Their names are self explanatory, where the first 5 refer to
1722602e473dSmrg          the mouse buttons that are being pressed, while the rest
1723602e473dSmrg          refer to various "special keys" that are being pressed (Mod1
1724602e473dSmrg          is usually the 'Alt' key or the 'Meta' key).
1725602e473dSmrg          </p>
1726602e473dSmrg          <p>
1727602e473dSmrg          <b>TODO:</b> Problem: it seems that the state does not
1728602e473dSmrg          change when clicking with various buttons.
1729602e473dSmrg          </p>
1730602e473dSmrg            <li class="subsubtitle"><a name="mousemvnt">Mouse movement events</a>
1731602e473dSmrg          <p>
1732602e473dSmrg          Similar to mouse button press and release events, we also
1733602e473dSmrg          can be notified of various mouse movement events. These can
1734602e473dSmrg          be split into two families. One is of mouse pointer
1735602e473dSmrg          movement while no buttons are pressed, and the second is a
1736602e473dSmrg          mouse pointer motion while one (or more) of the buttons are
1737602e473dSmrg          pressed (this is sometimes called "a mouse drag operation",
1738602e473dSmrg          or just "dragging"). The following event masks may be added
1739602e473dSmrg          during the creation of our window:
1740602e473dSmrg          </p>
1741602e473dSmrg          <ul>
1742602e473dSmrg            <li><span class="code">XCB_EVENT_MASK_POINTER_MOTION</span>: events of
1743602e473dSmrg            the pointer moving in one of the windows controlled by our
1744602e473dSmrg            application, while no mouse button is held pressed.
1745602e473dSmrg            <li><span class="code">XCB_EVENT_MASK_BUTTON_MOTION</span>: Events of
1746602e473dSmrg            the pointer moving while one or more of the mouse buttons
1747602e473dSmrg            is held pressed.
1748602e473dSmrg            <li><span class="code">XCB_EVENT_MASK_BUTTON_1_MOTION</span>: same as
1749602e473dSmrg            <span class="code">XCB_EVENT_MASK_BUTTON_MOTION</span>, but only when
1750602e473dSmrg            the 1st mouse button is held pressed.
1751602e473dSmrg            <li><span class="code">XCB_EVENT_MASK_BUTTON_2_MOTION</span>,
1752602e473dSmrg            <span class="code">XCB_EVENT_MASK_BUTTON_3_MOTION</span>,
1753602e473dSmrg            <span class="code">XCB_EVENT_MASK_BUTTON_4_MOTION</span>,
1754602e473dSmrg            <span class="code">XCB_EVENT_MASK_BUTTON_5_MOTION</span>: same as
1755602e473dSmrg            <span class="code">XCB_EVENT_MASK_BUTTON_1_MOTION</span>, but
1756602e473dSmrg            respectively for 2nd, 3rd, 4th and 5th mouse button.
1757602e473dSmrg          </ul>
1758602e473dSmrg          <p>
1759602e473dSmrg          The structure to be checked for in our events loop is the
1760602e473dSmrg          same for these events, and is the following:
1761602e473dSmrg          </p>
1762602e473dSmrg          <pre class="code">
1763602e473dSmrgtypedef struct {
1764602e473dSmrg    uint8_t         response_type; /* The type of the event */
1765602e473dSmrg    uint8_t         detail;
1766602e473dSmrg    uint16_t        sequence;
1767602e473dSmrg    xcb_timestamp_t time;          /* Time, in milliseconds the event took place in */
1768602e473dSmrg    xcb_window_t    root;
1769602e473dSmrg    xcb_window_t    event;
1770602e473dSmrg    xcb_window_t    child;
1771602e473dSmrg    int16_t         root_x;
1772602e473dSmrg    int16_t         root_y;
1773602e473dSmrg    int16_t         event_x;       /* The x coordinate of the mouse when the  event was generated */
1774602e473dSmrg    int16_t         event_y;       /* The y coordinate of the mouse when the  event was generated */
1775602e473dSmrg    uint16_t        state;         /* A mask of the buttons (or keys) during the event */
1776602e473dSmrg    uint8_t         same_screen;
1777602e473dSmrg} xcb_motion_notify_event_t;
1778602e473dSmrg</pre>
1779602e473dSmrg            <li class="subsubtitle"><a name="mouseenter">Mouse pointer enter and leave events</a>
1780602e473dSmrg          <p>
1781602e473dSmrg          Another type of event that applications might be interested
1782602e473dSmrg          in, is a mouse pointer entering a window the program
1783602e473dSmrg          controls, or leaving such a window. Some programs use these
1784602e473dSmrg          events to show the user that the application is now in
1785602e473dSmrg          focus. In order to register for such an event type, we
1786602e473dSmrg          should add one (or more) of the following masks when we
1787602e473dSmrg          create our window:
1788602e473dSmrg          </p>
1789602e473dSmrg          <ul>
1790602e473dSmrg            <li><span class="code">xcb_event_enter_window_t</span>: notify us
1791602e473dSmrg            when the mouse pointer enters any of our controlled
1792602e473dSmrg            windows.
1793602e473dSmrg            <li><span class="code">xcb_event_leave_window_t</span>: notify us
1794602e473dSmrg            when the mouse pointer leaves any of our controlled
1795602e473dSmrg            windows.
1796602e473dSmrg          </ul>
1797602e473dSmrg          <p>
1798602e473dSmrg          The structure to be checked for in our events loop is the
1799602e473dSmrg          same for these two events, and is the following:
1800602e473dSmrg          </p>
1801602e473dSmrg          <pre class="code">
1802602e473dSmrgtypedef struct {
1803602e473dSmrg    uint8_t         response_type; /* The type of the event */
1804602e473dSmrg    uint8_t         detail;
1805602e473dSmrg    uint16_t        sequence;
1806602e473dSmrg    xcb_timestamp_t time;          /* Time, in milliseconds the event took place in */
1807602e473dSmrg    xcb_window_t    root;
1808602e473dSmrg    xcb_window_t    event;
1809602e473dSmrg    xcb_window_t    child;
1810602e473dSmrg    int16_t         root_x;
1811602e473dSmrg    int16_t         root_y;
1812602e473dSmrg    int16_t         event_x;       /* The x coordinate of the mouse when the  event was generated */
1813602e473dSmrg    int16_t         event_y;       /* The y coordinate of the mouse when the  event was generated */
1814602e473dSmrg    uint16_t        state;         /* A mask of the buttons (or keys) during the event */
1815602e473dSmrg    uint8_t         mode;          /* The number of mouse button that was clicked */
1816602e473dSmrg    uint8_t         same_screen_focus;
1817602e473dSmrg} xcb_enter_notify_event_t;
1818602e473dSmrg
1819602e473dSmrgtypedef xcb_enter_notify_event_t xcb_leave_notify_event_t;
1820602e473dSmrg</pre>
1821602e473dSmrg          <li class="subsubtitle"><a name="focus">The keyboard focus</a>
1822602e473dSmrg          <p>
1823602e473dSmrg          There may be many windows on a screen, but only a single
1824602e473dSmrg          keyboard attached to them. How does the X server then know
1825602e473dSmrg          which window should be sent a given keyboard input ? This is
1826602e473dSmrg          done using the keyboard focus. Only a single window on the
1827602e473dSmrg          screen may have the keyboard focus at a given time. There
1828602e473dSmrg          is a XCB function that allows a program to set the keyboard
1829602e473dSmrg          focus to a given window. The user can usually set the
1830602e473dSmrg          keyboard focus using the window manager (often by clicking
1831602e473dSmrg          on the title bar of the desired window). Once our window
1832602e473dSmrg          has the keyboard focus, every key press or key release will
18331c7386f4Smrg          cause an event to be sent to our program (if it registered
1834602e473dSmrg          for these event types...).
1835602e473dSmrg          </p>
1836602e473dSmrg          <li class="subsubtitle"><a name="keypress">Keyboard press and release events</a>
1837602e473dSmrg          <p>
1838602e473dSmrg          If a window controlled by our program currently holds the
1839602e473dSmrg          keyboard focus, it can receive key press and key release
1840602e473dSmrg          events. So, we should add one (or more) of the following
1841602e473dSmrg          masks when we create our window:
1842602e473dSmrg          </p>
1843602e473dSmrg          <ul>
1844602e473dSmrg            <li><span class="code">XCB_EVENT_MASK_KEY_PRESS</span>: notify us when
1845602e473dSmrg            a key was pressed while any of our controlled windows had
1846602e473dSmrg            the keyboard focus.
1847602e473dSmrg            <li><span class="code">XCB_EVENT_MASK_KEY_RELEASE</span>: notify us
1848602e473dSmrg            when a key was released while any of our controlled
1849602e473dSmrg            windows had the keyboard focus.
1850602e473dSmrg          </ul>
1851602e473dSmrg          <p>
1852602e473dSmrg          The structure to be checked for in our events loop is the
1853602e473dSmrg          same for these two events, and is the following:
1854602e473dSmrg          </p>
1855602e473dSmrg          <pre class="code">
1856602e473dSmrgtypedef struct {
1857602e473dSmrg    uint8_t         response_type; /* The type of the event */
1858602e473dSmrg    xcb_keycode_t   detail;
1859602e473dSmrg    uint16_t        sequence;
1860602e473dSmrg    xcb_timestamp_t time;          /* Time, in milliseconds the event took place in */
1861602e473dSmrg    xcb_window_t    root;
1862602e473dSmrg    xcb_window_t    event;
1863602e473dSmrg    xcb_window_t    child;
1864602e473dSmrg    int16_t         root_x;
1865602e473dSmrg    int16_t         root_y;
1866602e473dSmrg    int16_t         event_x;
1867602e473dSmrg    int16_t         event_y;
1868602e473dSmrg    uint16_t        state;
1869602e473dSmrg    uint8_t         same_screen;
1870602e473dSmrg} xcb_key_press_event_t;
1871602e473dSmrg
1872602e473dSmrgtypedef xcb_key_press_event_t xcb_key_release_event_t;
1873602e473dSmrg</pre>
1874602e473dSmrg        <p>
1875602e473dSmrg        The <span class="code">detail</span> field refers to the
1876602e473dSmrg        physical key on the keyboard.
1877602e473dSmrg        </p>
1878602e473dSmrg        <p>
1879602e473dSmrg        <b>TODO:</b> Talk about getting the ASCII code from the key code.
1880602e473dSmrg        </p>
1881602e473dSmrg        </ol>
1882602e473dSmrg        <li class="subtitle"><a name="eventex">X events: a complete example</a>
1883602e473dSmrg        <p>
1884602e473dSmrg        As an example for handling events, we show a program that
1885602e473dSmrg        creates a window, enters an events loop and checks for all the
1886602e473dSmrg        events described above, and writes on the terminal the relevant
1887602e473dSmrg        characteristics of the event. With this code, it should be
1888602e473dSmrg        easy to add drawing operations, like those which have been
1889602e473dSmrg        described above.
1890602e473dSmrg        </p>
1891602e473dSmrg        <pre class="code">
1892602e473dSmrg#include &lt;stdlib.h&gt;
1893602e473dSmrg#include &lt;stdio.h&gt;
1894602e473dSmrg
1895602e473dSmrg#include &lt;xcb/xcb.h&gt;
1896602e473dSmrg
1897602e473dSmrgvoid
1898602e473dSmrgprint_modifiers (uint32_t mask)
1899602e473dSmrg{
1900602e473dSmrg  const char **mod, *mods[] = {
1901602e473dSmrg    "Shift", "Lock", "Ctrl", "Alt",
1902602e473dSmrg    "Mod2", "Mod3", "Mod4", "Mod5",
1903602e473dSmrg    "Button1", "Button2", "Button3", "Button4", "Button5"
1904602e473dSmrg  };
1905602e473dSmrg  printf ("Modifier mask: ");
1906602e473dSmrg  for (mod = mods ; mask; mask &gt;&gt;= 1, mod++)
1907602e473dSmrg    if (mask &amp; 1)
1908602e473dSmrg      printf(*mod);
1909602e473dSmrg  putchar ('\n');
1910602e473dSmrg}
1911602e473dSmrg
1912602e473dSmrgint
1913602e473dSmrgmain ()
1914602e473dSmrg{
1915602e473dSmrg  xcb_connection_t    *c;
1916602e473dSmrg  xcb_screen_t        *screen;
1917602e473dSmrg  xcb_window_t         win;
1918602e473dSmrg  xcb_generic_event_t *e;
1919602e473dSmrg  uint32_t             mask = 0;
1920602e473dSmrg  uint32_t             values[2];
1921602e473dSmrg
1922602e473dSmrg  /* Open the connection to the X server */
1923602e473dSmrg  c = xcb_connect (NULL, NULL);
1924602e473dSmrg
1925602e473dSmrg  /* Get the first screen */
1926602e473dSmrg  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
1927602e473dSmrg
1928602e473dSmrg  /* Ask for our window's Id */
1929602e473dSmrg  win = xcb_generate_id (c);
1930602e473dSmrg
1931602e473dSmrg  /* Create the window */
1932602e473dSmrg  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
1933602e473dSmrg  values[0] = screen-&gt;white_pixel;
1934602e473dSmrg  values[1] = XCB_EVENT_MASK_EXPOSURE       | XCB_EVENT_MASK_BUTTON_PRESS   |
1935602e473dSmrg              XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION |
1936602e473dSmrg              XCB_EVENT_MASK_ENTER_WINDOW   | XCB_EVENT_MASK_LEAVE_WINDOW   |
1937602e473dSmrg              XCB_EVENT_MASK_KEY_PRESS      | XCB_EVENT_MASK_KEY_RELEASE;
1938602e473dSmrg  xcb_create_window (c,                             /* Connection          */
1939602e473dSmrg                     0,                             /* depth               */
1940602e473dSmrg                     win,                           /* window Id           */
1941602e473dSmrg                     screen-&gt;root,                  /* parent window       */
1942602e473dSmrg                     0, 0,                          /* x, y                */
1943602e473dSmrg                     150, 150,                      /* width, height       */
1944602e473dSmrg                     10,                            /* border_width        */
1945602e473dSmrg                     XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
1946602e473dSmrg                     screen-&gt;root_visual,           /* visual              */
1947602e473dSmrg                     mask, values);                 /* masks */
1948602e473dSmrg
1949602e473dSmrg  /* Map the window on the screen */
1950602e473dSmrg  xcb_map_window (c, win);
1951602e473dSmrg
1952602e473dSmrg  xcb_flush (c);
1953602e473dSmrg
1954602e473dSmrg  while ((e = xcb_wait_for_event (c))) {
1955602e473dSmrg    switch (e-&gt;response_type &amp; ~0x80) {
1956602e473dSmrg    case XCB_EXPOSE: {
1957602e473dSmrg      xcb_expose_event_t *ev = (xcb_expose_event_t *)e;
1958602e473dSmrg
1959602e473dSmrg      printf ("Window %ld exposed. Region to be redrawn at location (%d,%d), with dimension (%d,%d)\n",
1960602e473dSmrg              ev-&gt;window, ev-&gt;x, ev-&gt;y, ev-&gt;width, ev-&gt;height);
1961602e473dSmrg      break;
1962602e473dSmrg    }
1963602e473dSmrg    case XCB_BUTTON_PRESS: {
1964602e473dSmrg      xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e;
1965602e473dSmrg      print_modifiers(ev-&gt;state);
1966602e473dSmrg
1967602e473dSmrg      switch (ev-&gt;detail) {
1968602e473dSmrg      case 4:
1969602e473dSmrg        printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n",
1970602e473dSmrg                ev-&gt;event, ev-&gt;event_x, ev-&gt;event_y);
1971602e473dSmrg        break;
1972602e473dSmrg      case 5:
1973602e473dSmrg        printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n",
1974602e473dSmrg                ev-&gt;event, ev-&gt;event_x, ev-&gt;event_y);
1975602e473dSmrg        break;
1976602e473dSmrg      default:
1977602e473dSmrg        printf ("Button %d pressed in window %ld, at coordinates (%d,%d)\n",
1978602e473dSmrg                ev-&gt;detail, ev-&gt;event, ev-&gt;event_x, ev-&gt;event_y);
1979602e473dSmrg      }
1980602e473dSmrg      break;
1981602e473dSmrg    }
1982602e473dSmrg    case XCB_BUTTON_RELEASE: {
1983602e473dSmrg      xcb_button_release_event_t *ev = (xcb_button_release_event_t *)e;
1984602e473dSmrg      print_modifiers(ev-&gt;state);
1985602e473dSmrg
1986602e473dSmrg      printf ("Button %d released in window %ld, at coordinates (%d,%d)\n",
1987602e473dSmrg              ev-&gt;detail, ev-&gt;event, ev-&gt;event_x, ev-&gt;event_y);
1988602e473dSmrg      break;
1989602e473dSmrg    }
1990602e473dSmrg    case XCB_MOTION_NOTIFY: {
1991602e473dSmrg      xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)e;
1992602e473dSmrg
1993602e473dSmrg      printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n",
1994602e473dSmrg              ev-&gt;event, ev-&gt;event_x, ev-&gt;event_y);
1995602e473dSmrg      break;
1996602e473dSmrg    }
1997602e473dSmrg    case XCB_ENTER_NOTIFY: {
1998602e473dSmrg      xcb_enter_notify_event_t *ev = (xcb_enter_notify_event_t *)e;
1999602e473dSmrg
2000602e473dSmrg      printf ("Mouse entered window %ld, at coordinates (%d,%d)\n",
2001602e473dSmrg              ev-&gt;event, ev-&gt;event_x, ev-&gt;event_y);
2002602e473dSmrg      break;
2003602e473dSmrg    }
2004602e473dSmrg    case XCB_LEAVE_NOTIFY: {
2005602e473dSmrg      xcb_leave_notify_event_t *ev = (xcb_leave_notify_event_t *)e;
2006602e473dSmrg
2007602e473dSmrg      printf ("Mouse left window %ld, at coordinates (%d,%d)\n",
2008602e473dSmrg              ev-&gt;event, ev-&gt;event_x, ev-&gt;event_y);
2009602e473dSmrg      break;
2010602e473dSmrg    }
2011602e473dSmrg    case XCB_KEY_PRESS: {
2012602e473dSmrg      xcb_key_press_event_t *ev = (xcb_key_press_event_t *)e;
2013602e473dSmrg      print_modifiers(ev-&gt;state);
2014602e473dSmrg
2015602e473dSmrg      printf ("Key pressed in window %ld\n",
2016602e473dSmrg              ev-&gt;event);
2017602e473dSmrg      break;
2018602e473dSmrg    }
2019602e473dSmrg    case XCB_KEY_RELEASE: {
2020602e473dSmrg      xcb_key_release_event_t *ev = (xcb_key_release_event_t *)e;
2021602e473dSmrg      print_modifiers(ev-&gt;state);
2022602e473dSmrg
2023602e473dSmrg      printf ("Key released in window %ld\n",
2024602e473dSmrg              ev-&gt;event);
2025602e473dSmrg      break;
2026602e473dSmrg    }
2027602e473dSmrg    default:
2028602e473dSmrg      /* Unknown event type, ignore it */
2029602e473dSmrg      printf("Unknown event: %d\n", e-&gt;response_type);
2030602e473dSmrg      break;
2031602e473dSmrg    }
2032602e473dSmrg    /* Free the Generic Event */
2033602e473dSmrg    free (e);
2034602e473dSmrg  }
2035602e473dSmrg
2036602e473dSmrg  return 0;
2037602e473dSmrg}
2038602e473dSmrg</pre>
2039602e473dSmrg      </ol>
2040602e473dSmrg      <li class="title"><a name="font">Handling text and fonts</a>
2041602e473dSmrg      <p>
2042602e473dSmrg      Besides drawing graphics on a window, we often want to draw
2043602e473dSmrg      text. Text strings have two major properties: the characters to
2044602e473dSmrg      be drawn and the font with which they are drawn. In order to
2045602e473dSmrg      draw text, we need to first request the X server to load a
2046602e473dSmrg      font. We then assign a font to a Graphic Context, and finally, we
2047602e473dSmrg      draw the text in a window, using the Graphic Context.
2048602e473dSmrg      </p>
2049602e473dSmrg      <ol>
2050602e473dSmrg        <li class="subtitle"><a name="fontstruct">The Font structure</a>
2051602e473dSmrg        <p>
2052602e473dSmrg        In order to support flexible fonts, a font type is
2053602e473dSmrg        defined. You know what ? It's an Id:
2054602e473dSmrg        </p>
2055602e473dSmrg        <pre class="code">
2056602e473dSmrgtypedef uint32_t xcb_font_t;
2057602e473dSmrg</pre>
2058602e473dSmrg        <p>
2059602e473dSmrg        It is used to contain information about a font, and is passed
2060602e473dSmrg        to several functions that handle fonts selection and text drawing.
2061602e473dSmrg        We ask the X server to attribute an  Id to our font with the
2062602e473dSmrg        function:
2063602e473dSmrg        </p>
2064602e473dSmrg        <pre class="code">
2065602e473dSmrgxcb_font_t xcb_generate_id (xcb_connection_t *c);
2066602e473dSmrg</pre>
2067602e473dSmrg        <br>
2068602e473dSmrg        <li class="subtitle"><a name="openingfont">Opening a Font</a>
2069602e473dSmrg        <p>
2070602e473dSmrg        To open a font, we use the following function:
2071602e473dSmrg        </p>
2072602e473dSmrg        <pre class="code">
2073602e473dSmrgxcb_void_cookie_t xcb_open_font (xcb_connection_t *c,
2074602e473dSmrg                                 xcb_font_t        fid,
2075602e473dSmrg                                 uint16_t          name_len,
2076602e473dSmrg                                 const char       *name);
2077602e473dSmrg</pre>
2078602e473dSmrg        <p>
2079602e473dSmrg        The <span class="code">fid</span> parameter is the font Id
2080602e473dSmrg        defined by <span class="code">xcb_generate_id()</span> (see
2081602e473dSmrg        above). The <span class="code">name</span> parameter is the
2082602e473dSmrg        name of the font you want to open. Use the command
2083602e473dSmrg        <span class="code">xlsfonts</span> in a terminal to know which
2084602e473dSmrg        are the fonts available on your computer. The parameter
2085602e473dSmrg        <span class="code">name_len</span> is the length of the name
2086602e473dSmrg        of the font (given by <span class="code">strlen()</span>).
2087602e473dSmrg        </p>
2088602e473dSmrg        <li class="subtitle"><a name="assigningfont">Assigning a Font to a Graphic Context</a>
2089602e473dSmrg        <p>
2090602e473dSmrg        Once a font is opened, you have to create a Graphic Context
2091602e473dSmrg        that will contain the informations about the color of the
2092602e473dSmrg        foreground and the background used when you draw a text in a
20931c7386f4Smrg        Drawable. Here is an example of a Graphic Context that will
2094602e473dSmrg        allow us to draw an opened font with a black foreground and a
2095602e473dSmrg        white background:
2096602e473dSmrg        </p>
2097602e473dSmrg        <pre class="code">
2098602e473dSmrg  /*
2099602e473dSmrg   * c is the connection
2100602e473dSmrg   * screen is the screen where the window is displayed
2101602e473dSmrg   * window is the window in which we will draw the text
2102602e473dSmrg   * font is the opened font
2103602e473dSmrg   */
2104602e473dSmrg
2105602e473dSmrg  uint32_t             value_list[3];
2106602e473dSmrg  xcb_gcontext_t       gc;
2107602e473dSmrg  uint32_t             mask;
2108602e473dSmrg
2109602e473dSmrg  gc = xcb_generate_id (c);
2110602e473dSmrg  mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
2111602e473dSmrg  value_list[0] = screen->black_pixel;
2112602e473dSmrg  value_list[1] = screen->white_pixel;
2113602e473dSmrg  value_list[2] = font;
2114602e473dSmrg  xcb_create_gc (c, gc, window, mask, value_list);
2115602e473dSmrg
2116602e473dSmrg  /* The font is not needed anymore, so we close it */
2117602e473dSmrg  xcb_close_font (c, font);
2118602e473dSmrg</pre>
2119602e473dSmrg        <li class="subtitle"><a name="drawingtext">Drawing text in a drawable</a>
2120602e473dSmrg        <p>
2121602e473dSmrg        To draw a text in a drawable, we use the following function:
2122602e473dSmrg        </p>
2123602e473dSmrg        <pre class="code">
2124602e473dSmrgxcb_void_cookie_t xcb_image_text_8 (xcb_connection_t *c,
2125602e473dSmrg                                    uint8_t           string_len,
2126602e473dSmrg                                    xcb_drawable_t    drawable,
2127602e473dSmrg                                    xcb_gcontext_t    gc,
2128602e473dSmrg                                    int16_t           x,
2129602e473dSmrg                                    int16_t           y,
2130602e473dSmrg                                    const char       *string);
2131602e473dSmrg</pre>
2132602e473dSmrg        <p>
2133602e473dSmrg        The <span class="code">string</span> parameter is the text to
2134602e473dSmrg        draw. The location of the drawing is given by the parameters
2135602e473dSmrg        <span class="code">x</span> and <span class="code">y</span>.
2136602e473dSmrg        The base line of the text is exactly the parameter
2137602e473dSmrg        <span class="code">y</span>.
2138602e473dSmrg        </p>
2139602e473dSmrg        <li class="subtitle"><a name="fontcompleteexample">Complete example</a>
2140602e473dSmrg        <p>
2141602e473dSmrg        This example draw a text at 10 pixels (for the base line) of
2142602e473dSmrg        the bottom of a window. Pressing the Esc key exits the program.
2143602e473dSmrg        </p>
2144602e473dSmrg        <pre class="code">
2145602e473dSmrg#include &lt;stdlib.h&gt;
2146602e473dSmrg#include &lt;stdio.h&gt;
2147602e473dSmrg#include &lt;string.h&gt;
2148602e473dSmrg
2149602e473dSmrg#include &lt;xcb/xcb.h&gt;
2150602e473dSmrg
2151602e473dSmrg#define WIDTH 300
2152602e473dSmrg#define HEIGHT 100
2153602e473dSmrg
2154602e473dSmrg
2155602e473dSmrg
2156602e473dSmrgstatic xcb_gc_t gc_font_get (xcb_connection_t *c,
2157602e473dSmrg                             xcb_screen_t     *screen,
2158602e473dSmrg                             xcb_window_t      window,
2159602e473dSmrg                             const char       *font_name);
2160602e473dSmrg
2161602e473dSmrgstatic void text_draw (xcb_connection_t *c,
2162602e473dSmrg                       xcb_screen_t     *screen,
2163602e473dSmrg                       xcb_window_t      window,
2164602e473dSmrg                       int16_t           x1,
2165602e473dSmrg                       int16_t           y1,
2166602e473dSmrg                       const char       *label);
2167602e473dSmrg
2168602e473dSmrgstatic void
2169602e473dSmrgtext_draw (xcb_connection_t *c,
2170602e473dSmrg           xcb_screen_t     *screen,
2171602e473dSmrg           xcb_window_t      window,
2172602e473dSmrg           int16_t           x1,
2173602e473dSmrg           int16_t           y1,
2174602e473dSmrg           const char       *label)
2175602e473dSmrg{
2176602e473dSmrg  xcb_void_cookie_t    cookie_gc;
2177602e473dSmrg  xcb_void_cookie_t    cookie_text;
2178602e473dSmrg  xcb_generic_error_t *error;
2179602e473dSmrg  xcb_gcontext_t       gc;
2180602e473dSmrg  uint8_t              length;
2181602e473dSmrg
2182602e473dSmrg  length = strlen (label);
2183602e473dSmrg
2184602e473dSmrg  gc = gc_font_get(c, screen, window, "7x13");
2185602e473dSmrg
2186602e473dSmrg  cookie_text = xcb_image_text_8_checked (c, length, window, gc,
2187602e473dSmrg                                          x1,
2188602e473dSmrg                                          y1, label);
2189602e473dSmrg  error = xcb_request_check (c, cookie_text);
2190602e473dSmrg  if (error) {
2191602e473dSmrg    fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
2192602e473dSmrg    xcb_disconnect (c);
2193602e473dSmrg    exit (-1);
2194602e473dSmrg  }
2195602e473dSmrg
2196602e473dSmrg  cookie_gc = xcb_free_gc (c, gc);
2197602e473dSmrg  error = xcb_request_check (c, cookie_gc);
2198602e473dSmrg  if (error) {
2199602e473dSmrg    fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
2200602e473dSmrg    xcb_disconnect (c);
2201602e473dSmrg    exit (-1);
2202602e473dSmrg  }
2203602e473dSmrg}
2204602e473dSmrg
2205602e473dSmrgstatic xcb_gc_t
2206602e473dSmrggc_font_get (xcb_connection_t *c,
2207602e473dSmrg             xcb_screen_t     *screen,
2208602e473dSmrg             xcb_window_t      window,
2209602e473dSmrg             const char       *font_name)
2210602e473dSmrg{
2211602e473dSmrg  uint32_t             value_list[3];
2212602e473dSmrg  xcb_void_cookie_t    cookie_font;
2213602e473dSmrg  xcb_void_cookie_t    cookie_gc;
2214602e473dSmrg  xcb_generic_error_t *error;
2215602e473dSmrg  xcb_font_t           font;
2216602e473dSmrg  xcb_gcontext_t       gc;
2217602e473dSmrg  uint32_t             mask;
2218602e473dSmrg
2219602e473dSmrg  font = xcb_generate_id (c);
2220602e473dSmrg  cookie_font = xcb_open_font_checked (c, font,
2221602e473dSmrg                                       strlen (font_name),
2222602e473dSmrg                                       font_name);
2223602e473dSmrg
2224602e473dSmrg  error = xcb_request_check (c, cookie_font);
2225602e473dSmrg  if (error) {
2226602e473dSmrg    fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
2227602e473dSmrg    xcb_disconnect (c);
2228602e473dSmrg    return -1;
2229602e473dSmrg  }
2230602e473dSmrg
2231602e473dSmrg  gc = xcb_generate_id (c);
2232602e473dSmrg  mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
2233602e473dSmrg  value_list[0] = screen->black_pixel;
2234602e473dSmrg  value_list[1] = screen->white_pixel;
2235602e473dSmrg  value_list[2] = font;
2236602e473dSmrg  cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list);
2237602e473dSmrg  error = xcb_request_check (c, cookie_gc);
2238602e473dSmrg  if (error) {
2239602e473dSmrg    fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
2240602e473dSmrg    xcb_disconnect (c);
2241602e473dSmrg    exit (-1);
2242602e473dSmrg  }
2243602e473dSmrg
2244602e473dSmrg  cookie_font = xcb_close_font_checked (c, font);
2245602e473dSmrg  error = xcb_request_check (c, cookie_font);
2246602e473dSmrg  if (error) {
2247602e473dSmrg    fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
2248602e473dSmrg    xcb_disconnect (c);
2249602e473dSmrg    exit (-1);
2250602e473dSmrg  }
2251602e473dSmrg
2252602e473dSmrg  return gc;
2253602e473dSmrg}
2254602e473dSmrg
2255602e473dSmrgint main ()
2256602e473dSmrg{
2257602e473dSmrg  xcb_screen_iterator_t screen_iter;
2258602e473dSmrg  xcb_connection_t     *c;
2259602e473dSmrg  const xcb_setup_t    *setup;
2260602e473dSmrg  xcb_screen_t         *screen;
2261602e473dSmrg  xcb_generic_event_t  *e;
2262602e473dSmrg  xcb_generic_error_t  *error;
2263602e473dSmrg  xcb_void_cookie_t     cookie_window;
2264602e473dSmrg  xcb_void_cookie_t     cookie_map;
2265602e473dSmrg  xcb_window_t          window;
2266602e473dSmrg  uint32_t              mask;
2267602e473dSmrg  uint32_t              values[2];
2268602e473dSmrg  int                   screen_number;
2269602e473dSmrg
2270602e473dSmrg  /* getting the connection */
2271602e473dSmrg  c = xcb_connect (NULL, &amp;screen_number);
2272602e473dSmrg  if (!c) {
2273602e473dSmrg    fprintf (stderr, "ERROR: can't connect to an X server\n");
2274602e473dSmrg    return -1;
2275602e473dSmrg  }
2276602e473dSmrg
2277602e473dSmrg  /* getting the current screen */
2278602e473dSmrg  setup = xcb_get_setup (c);
2279602e473dSmrg
2280602e473dSmrg  screen = NULL;
2281602e473dSmrg  screen_iter = xcb_setup_roots_iterator (setup);
2282602e473dSmrg  for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&amp;screen_iter))
2283602e473dSmrg    if (screen_number == 0)
2284602e473dSmrg      {
2285602e473dSmrg        screen = screen_iter.data;
2286602e473dSmrg        break;
2287602e473dSmrg      }
2288602e473dSmrg  if (!screen) {
2289602e473dSmrg    fprintf (stderr, "ERROR: can't get the current screen\n");
2290602e473dSmrg    xcb_disconnect (c);
2291602e473dSmrg    return -1;
2292602e473dSmrg  }
2293602e473dSmrg
2294602e473dSmrg  /* creating the window */
2295602e473dSmrg  window = xcb_generate_id (c);
2296602e473dSmrg  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
2297602e473dSmrg  values[0] = screen->white_pixel;
2298602e473dSmrg  values[1] =
2299602e473dSmrg    XCB_EVENT_MASK_KEY_RELEASE |
2300b9526c6aSmrg    XCB_EVENT_MASK_EXPOSURE;
2301602e473dSmrg  cookie_window = xcb_create_window_checked (c,
2302602e473dSmrg                                             screen->root_depth,
2303602e473dSmrg                                             window, screen->root,
2304602e473dSmrg                                             20, 200, WIDTH, HEIGHT,
2305602e473dSmrg                                             0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
2306602e473dSmrg                                             screen->root_visual,
2307602e473dSmrg                                             mask, values);
2308602e473dSmrg  cookie_map = xcb_map_window_checked (c, window);
2309602e473dSmrg
2310602e473dSmrg  /* error managing */
2311602e473dSmrg  error = xcb_request_check (c, cookie_window);
2312602e473dSmrg  if (error) {
2313602e473dSmrg    fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code);
2314602e473dSmrg    xcb_disconnect (c);
2315602e473dSmrg    return -1;
2316602e473dSmrg  }
2317602e473dSmrg  error = xcb_request_check (c, cookie_map);
2318602e473dSmrg  if (error) {
2319602e473dSmrg    fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code);
2320602e473dSmrg    xcb_disconnect (c);
2321602e473dSmrg    return -1;
2322602e473dSmrg  }
2323602e473dSmrg
2324602e473dSmrg  xcb_flush(c);
2325602e473dSmrg
2326602e473dSmrg  while (1) {
2327602e473dSmrg    e = xcb_poll_for_event(c);
2328602e473dSmrg    if (e) {
2329602e473dSmrg      switch (e->response_type &amp; ~0x80) {
2330602e473dSmrg      case XCB_EXPOSE: {
2331602e473dSmrg        char *text;
2332602e473dSmrg
2333602e473dSmrg        text = "Press ESC key to exit...";
2334602e473dSmrg        text_draw (c, screen, window, 10, HEIGHT - 10, text);
2335602e473dSmrg        break;
2336602e473dSmrg      }
2337602e473dSmrg      case XCB_KEY_RELEASE: {
2338602e473dSmrg        xcb_key_release_event_t *ev;
2339602e473dSmrg
2340602e473dSmrg        ev = (xcb_key_release_event_t *)e;
2341602e473dSmrg
2342602e473dSmrg        switch (ev->detail) {
2343602e473dSmrg          /* ESC */
2344602e473dSmrg        case 9:
2345602e473dSmrg          free (e);
2346602e473dSmrg          xcb_disconnect (c);
2347602e473dSmrg          return 0;
2348602e473dSmrg        }
2349602e473dSmrg      }
2350602e473dSmrg      }
2351602e473dSmrg      free (e);
2352602e473dSmrg    }
2353602e473dSmrg  }
2354602e473dSmrg
2355602e473dSmrg  return 0;
2356602e473dSmrg}
2357602e473dSmrg</pre>
2358602e473dSmrg      </ol>
2359602e473dSmrg      <li class="title"><a name="wm">Interacting with the window manager</a>
2360602e473dSmrg      <p>
2361602e473dSmrg      After we have seen how to create windows and draw on them, we
2362602e473dSmrg      take one step back, and look at how our windows are interacting
2363602e473dSmrg      with their environment (the full screen and the other
2364602e473dSmrg      windows). First of all, our application needs to interact with
2365602e473dSmrg      the window manager. The window manager is responsible to
2366602e473dSmrg      decorating drawn windows (i.e. adding a frame, an iconify
2367602e473dSmrg      button, a system menu, a title bar, etc), as well as handling
2368602e473dSmrg      icons shown when windows are being iconified. It also handles
2369602e473dSmrg      ordering of windows on the screen, and other administrative
2370602e473dSmrg      tasks. We need to give it various hints as to how we want it to
2371602e473dSmrg      treat our application's windows.
2372602e473dSmrg      </p>
2373602e473dSmrg      <ol>
2374602e473dSmrg        <li class="subtitle"><a name="wmprop">Window properties</a>
2375602e473dSmrg        <p>
2376602e473dSmrg        Many of the parameters communicated to the window manager are
2377602e473dSmrg        passed using data called "properties". These properties are
2378602e473dSmrg        attached by the X server to different windows, and are stored
2379602e473dSmrg        in a format that makes it possible to read them from different
2380602e473dSmrg        machines that may use different architectures (remember that
2381602e473dSmrg        an X client program may run on a remote machine).
2382602e473dSmrg        </p>
2383602e473dSmrg        <p>
2384602e473dSmrg        The property and its type (a string, an integer, etc) are
2385602e473dSmrg        Id. Their type are <span class="code">xcb_atom_t</span>:
2386602e473dSmrg        </p>
2387602e473dSmrg        <pre class="code">
2388602e473dSmrgtypedef uint32_t xcb_atom_t;
2389602e473dSmrg</pre>
2390602e473dSmrg        <p>
2391602e473dSmrg        To change the property of a window, we use the following
2392602e473dSmrg        function:
2393602e473dSmrg        </p>
2394602e473dSmrg        <pre class="code">
2395602e473dSmrgxcb_void_cookie_t xcb_change_property (xcb_connection_t *c,       /* Connection to the X server */
2396602e473dSmrg                                       uint8_t          mode,     /* Property mode */
2397602e473dSmrg                                       xcb_window_t     window,   /* Window */
2398602e473dSmrg                                       xcb_atom_t       property, /* Property to change */
2399602e473dSmrg                                       xcb_atom_t       type,     /* Type of the property */
2400602e473dSmrg                                       uint8_t          format,   /* Format of the property (8, 16, 32) */
2401602e473dSmrg                                       uint32_t         data_len, /* Length of the data parameter */
2402602e473dSmrg                                       const void      *data);    /* Data */
2403602e473dSmrg</pre>
2404602e473dSmrg        <p>
24051c7386f4Smrg        The <span class="code">mode</span> parameter could be one of
2406602e473dSmrg        the following values (defined in enumeration xcb_prop_mode_t in
2407602e473dSmrg        the xproto.h header file):
2408602e473dSmrg        </p>
2409602e473dSmrg        <ul>
2410602e473dSmrg          <li>XCB_PROP_MODE_REPLACE
2411602e473dSmrg          <li>XCB_PROP_MODE_PREPEND
2412602e473dSmrg          <li>XCB_PROP_MODE_APPEND
2413602e473dSmrg        </ul>
2414602e473dSmrg        <br>
2415602e473dSmrg        <li class="subtitle"><a name="wmname">Setting the window name and icon name</a>
2416602e473dSmrg        <p>
2417602e473dSmrg        The first thing we want to do would be to set the name for our
2418602e473dSmrg        window. This is done using the
2419602e473dSmrg        <span class="code">xcb_change_property()</span> function. This
2420602e473dSmrg        name may be used by the window manager as the title of the
2421602e473dSmrg        window (in the title bar), in a task list, etc. The property
2422602e473dSmrg        atom to use to set the name of a window is
2423602e473dSmrg        <span class="code">WM_NAME</span> (and
2424602e473dSmrg        <span class="code">WM_ICON_NAME</span> for the iconified
2425602e473dSmrg        window) and its type is <span class="code">STRING</span>. Here
2426602e473dSmrg        is an example of utilization:
2427602e473dSmrg        </p>
2428602e473dSmrg        <pre class="code">
2429602e473dSmrg#include &lt;string.h&gt;
2430602e473dSmrg
2431602e473dSmrg#include &lt;xcb/xcb.h&gt;
2432602e473dSmrg#include &lt;xcb/xcb_atom.h&gt;
2433602e473dSmrg
2434602e473dSmrgint
2435602e473dSmrgmain ()
2436602e473dSmrg{
2437602e473dSmrg  xcb_connection_t *c;
2438602e473dSmrg  xcb_screen_t     *screen;
2439602e473dSmrg  xcb_window_t      win;
2440602e473dSmrg  char             *title = "Hello World !";
2441602e473dSmrg  char             *title_icon = "Hello World ! (iconified)";
2442602e473dSmrg
2443602e473dSmrg
2444602e473dSmrg
2445602e473dSmrg  /* Open the connection to the X server */
2446602e473dSmrg  c = xcb_connect (NULL, NULL);
2447602e473dSmrg
2448602e473dSmrg  /* Get the first screen */
2449602e473dSmrg  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
2450602e473dSmrg
2451602e473dSmrg  /* Ask for our window's Id */
2452602e473dSmrg  win = xcb_generate_id (c);
2453602e473dSmrg
2454602e473dSmrg  /* Create the window */
2455602e473dSmrg  xcb_create_window (c,                             /* Connection          */
2456602e473dSmrg                     0,                             /* depth               */
2457602e473dSmrg                     win,                           /* window Id           */
2458602e473dSmrg                     screen-&gt;root,                  /* parent window       */
2459602e473dSmrg                     0, 0,                          /* x, y                */
2460602e473dSmrg                     250, 150,                      /* width, height       */
2461602e473dSmrg                     10,                            /* border_width        */
2462602e473dSmrg                     XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class               */
2463602e473dSmrg                     screen-&gt;root_visual,           /* visual              */
2464602e473dSmrg                     0, NULL);                      /* masks, not used     */
2465602e473dSmrg
2466602e473dSmrg  /* Set the title of the window */
2467602e473dSmrg  xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
2468602e473dSmrg                       WM_NAME, STRING, 8,
2469602e473dSmrg                       strlen (title), title);
2470602e473dSmrg
2471602e473dSmrg  /* Set the title of the window icon */
2472602e473dSmrg  xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
2473602e473dSmrg                       WM_ICON_NAME, STRING, 8,
2474602e473dSmrg                       strlen(title_icon), title_icon);
2475602e473dSmrg
2476602e473dSmrg  /* Map the window on the screen */
2477602e473dSmrg  xcb_map_window (c, win);
2478602e473dSmrg
2479602e473dSmrg  xcb_flush (c);
2480602e473dSmrg
2481602e473dSmrg  while (1) {}
2482602e473dSmrg
2483602e473dSmrg  return 0;
2484602e473dSmrg}
2485602e473dSmrg</pre>
2486602e473dSmrg        <div class="emph">
2487602e473dSmrg        <p>Note: the use of the atoms needs our program to be compiled
2488602e473dSmrg        and linked against xcb_atom, so that we have to use
2489602e473dSmrg        </p>
2490602e473dSmrg        </div>
2491602e473dSmrg        <pre class="text">
2492602e473dSmrggcc prog.c -o prog `pkg-config --cflags --libs xcb_atom`
2493602e473dSmrg</pre>
2494602e473dSmrg        <div class="emph">
2495602e473dSmrg        <p>
2496602e473dSmrg        for the program to compile fine.
2497602e473dSmrg        </p>
2498602e473dSmrg        </div>
2499602e473dSmrg      </ol>
2500602e473dSmrg      <li class="title"><a name="winop">Simple window operations</a>
2501602e473dSmrg      <p>
2502602e473dSmrg      One more thing we can do to our window is manipulate them on the
2503602e473dSmrg      screen (resize them, move them, raise or lower them, iconify
2504602e473dSmrg      them, and so on). Some window operations functions are supplied
2505602e473dSmrg      by XCB for this purpose.
2506602e473dSmrg      </p>
2507602e473dSmrg      <ol>
2508602e473dSmrg        <li class="subtitle"><a name="winmap">Mapping and un-mapping a window</a>
2509602e473dSmrg        <p>
2510602e473dSmrg        The first pair of operations we can apply on a window is
2511602e473dSmrg        mapping it, or un-mapping it. Mapping a window causes the
2512602e473dSmrg        window to appear on the screen, as we have seen in our simple
2513602e473dSmrg        window program example. Un-mapping it causes it to be removed
2514602e473dSmrg        from the screen (although the window as a logical entity still
2515602e473dSmrg        exists). This gives the effect of making a window hidden
2516602e473dSmrg        (unmapped) and shown again (mapped). For example, if we have a
2517602e473dSmrg        dialog box window in our program, instead of creating it every
2518602e473dSmrg        time the user asks to open it, we can create the window once,
2519602e473dSmrg        in an un-mapped mode, and when the user asks to open it, we
2520602e473dSmrg        simply map the window on the screen. When the user clicked the
2521602e473dSmrg        'OK' or 'Cancel' button, we simply un-map the window. This is
2522602e473dSmrg        much faster than creating and destroying the window, however,
2523602e473dSmrg        the cost is wasted resources, both on the client side, and on
2524602e473dSmrg        the X server side.
2525602e473dSmrg        </p>
2526602e473dSmrg        <p>
2527602e473dSmrg        To map a window, you use the following function:
2528602e473dSmrg        </p>
2529602e473dSmrg        <pre class="code">
2530602e473dSmrgxcb_void_cookie_t xcb_map_window (xcb_connection_t *c,
2531602e473dSmrg                                  xcb_window_t      window);
2532602e473dSmrg</pre>
2533602e473dSmrg        <p>
2534602e473dSmrg        To have a simple example, see the <a href="#helloworld">example</a>
2535602e473dSmrg        above. The mapping operation will cause an
2536602e473dSmrg        <span class="code">Expose</span> event to be sent to our
2537602e473dSmrg        application, unless the window is completely covered by other
2538602e473dSmrg        windows.
2539602e473dSmrg        </p>
2540602e473dSmrg        <p>
2541602e473dSmrg        Un-mapping a window is also simple. You use the function
2542602e473dSmrg        </p>
2543602e473dSmrg        <pre class="code">
2544602e473dSmrgxcb_void_cookie_t xcb_unmap_window (xcb_connection_t *c,
2545602e473dSmrg                                    xcb_window_t      window);
2546602e473dSmrg</pre>
2547602e473dSmrg        <p>
2548602e473dSmrg        The utilization of this function is the same as
2549602e473dSmrg        <span class="code">xcb_map_window()</span>.
2550602e473dSmrg        </p>
2551602e473dSmrg        <li class="subtitle"><a name="winconf">Configuring a window</a>
2552602e473dSmrg        <p>
2553602e473dSmrg        As we have seen when we have created our first window, in the
2554602e473dSmrg        X Events subsection, we can set some attributes for the window
2555602e473dSmrg        (that is, the position, the size, the events the window will
2556602e473dSmrg        receive, etc). If we want to modify them, but the window is
2557602e473dSmrg        already created, we can change them by using the following
2558602e473dSmrg        function:
2559602e473dSmrg        </p>
2560602e473dSmrg        <pre class="code">
2561602e473dSmrgxcb_void_cookie_t xcb_configure_window (xcb_connection_t *c,            /* The connection to the X server*/
2562602e473dSmrg                                        xcb_window_t      window,       /* The window to configure */
2563602e473dSmrg                                        uint16_t          value_mask,   /* The mask */
2564602e473dSmrg                                        const uint32_t   *value_list);  /* The values to set */
2565602e473dSmrg</pre>
2566602e473dSmrg        <p>
2567602e473dSmrg        We set the <span class="code">value_mask</span> to one or
2568602e473dSmrg        several mask values that are in the xcb_config_window_t enumeration in the xproto.h header:
2569602e473dSmrg        </p>
2570602e473dSmrg        <ul>
2571602e473dSmrg          <li><span class="code">XCB_CONFIG_WINDOW_X</span>: new x coordinate of the window's top left corner
2572602e473dSmrg          <li><span class="code">XCB_CONFIG_WINDOW_Y</span>: new y coordinate of the window's top left corner
2573602e473dSmrg          <li><span class="code">XCB_CONFIG_WINDOW_WIDTH</span>: new width of the window
2574602e473dSmrg          <li><span class="code">XCB_CONFIG_WINDOW_HEIGHT</span>: new height of the window
2575602e473dSmrg          <li><span class="code">XCB_CONFIG_WINDOW_BORDER_WIDTH</span>: new width of the border of the window
2576602e473dSmrg          <li><span class="code">XCB_CONFIG_WINDOW_SIBLING</span>
2577602e473dSmrg          <li><span class="code">XCB_CONFIG_WINDOW_STACK_MODE</span>: the new stacking order
2578602e473dSmrg        </ul>
2579602e473dSmrg        <p>
2580602e473dSmrg        We then give to <span class="code">value_mask</span> the new
2581602e473dSmrg        value. We now describe how to use
2582602e473dSmrg        <span class="code">xcb_configure_window_t</span> in some useful
2583602e473dSmrg        situations.
2584602e473dSmrg        </p>
2585602e473dSmrg        <li class="subtitle"><a name="winmove">Moving a window around the screen</a>
2586602e473dSmrg        <p>
2587602e473dSmrg        An operation we might want to do with windows is to move them
2588602e473dSmrg        to a different location. This can be done like this:
2589602e473dSmrg        </p>
2590602e473dSmrg        <pre class="code">
2591602e473dSmrgconst static uint32_t values[] = { 10, 20 };
2592602e473dSmrg
2593602e473dSmrg/* The connection c and the window win are supposed to be defined */
2594602e473dSmrg
2595602e473dSmrg/* Move the window to coordinates x = 10 and y = 20 */
2596602e473dSmrgxcb_configure_window (c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
2597602e473dSmrg</pre>
2598602e473dSmrg        <p>
2599602e473dSmrg        Note that when the window is moved, it might get partially
2600602e473dSmrg        exposed or partially hidden by other windows, and thus we
2601602e473dSmrg        might get <span class="code">Expose</span> events due to this
2602602e473dSmrg        operation.
2603602e473dSmrg        </p>
2604602e473dSmrg        <li class="subtitle"><a name="winsize">Resizing a window</a>
2605602e473dSmrg        <p>
2606602e473dSmrg        Yet another operation we can do is to change the size of a
2607602e473dSmrg        window. This is done using the following code:
2608602e473dSmrg        </p>
2609602e473dSmrg        <pre class="code">
2610602e473dSmrgconst static uint32_t values[] = { 200, 300 };
2611602e473dSmrg
2612602e473dSmrg/* The connection c and the window win are supposed to be defined */
2613602e473dSmrg
2614602e473dSmrg/* Resize the window to width = 10 and height = 20 */
2615602e473dSmrgxcb_configure_window (c, win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
2616602e473dSmrg</pre>
2617602e473dSmrg        <p>
2618602e473dSmrg        We can also combine the move and resize operations using one
2619602e473dSmrg        single call to <span class="code">xcb_configure_window_t</span>:
2620602e473dSmrg        </p>
2621602e473dSmrg        <pre class="code">
2622602e473dSmrgconst static uint32_t values[] = { 10, 20, 200, 300 };
2623602e473dSmrg
2624602e473dSmrg/* The connection c and the window win are supposed to be defined */
2625602e473dSmrg
2626602e473dSmrg/* Move the window to coordinates x = 10 and y = 20 */
2627602e473dSmrg/* and resize the window to width = 10 and height = 20 */
2628602e473dSmrgxcb_configure_window (c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
2629602e473dSmrg</pre>
2630602e473dSmrg        <li class="subtitle"><a name="winstack">Changing windows stacking order: raise and lower</a>
2631602e473dSmrg        <p>
2632602e473dSmrg        Until now, we changed properties of a single window. We'll see
2633602e473dSmrg        that there are properties that relate to the window and other
2634602e473dSmrg        windows. One of them is the stacking order. That is, the order
2635602e473dSmrg        in which the windows are layered on top of each other. The
2636602e473dSmrg        front-most window is said to be on the top of the stack, while
2637602e473dSmrg        the back-most window is at the bottom of the stack. Here is
2638602e473dSmrg        how to manipulate our windows stack order:
2639602e473dSmrg        </p>
2640602e473dSmrg        <pre class="code">
2641602e473dSmrgconst static uint32_t values[] = { XCB_STACK_MODE_ABOVE };
2642602e473dSmrg
2643602e473dSmrg/* The connection c and the window win are supposed to be defined */
2644602e473dSmrg
2645602e473dSmrg/* Move the window on the top of the stack */
2646602e473dSmrgxcb_configure_window (c, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
2647602e473dSmrg</pre>
2648602e473dSmrg        <pre class="code">
2649602e473dSmrgconst static uint32_t values[] = { XCB_STACK_MODE_BELOW };
2650602e473dSmrg
2651602e473dSmrg/* The connection c and the window win are supposed to be defined */
2652602e473dSmrg
2653602e473dSmrg/* Move the window on the bottom of the stack */
2654602e473dSmrgxcb_configure_window (c, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
2655602e473dSmrg</pre>
2656602e473dSmrg        <li class="subtitle"><a name="wingetinfo">Getting information about a window</a>
2657602e473dSmrg        <p>
2658602e473dSmrg        Just like we can set various attributes of our windows, we can
2659602e473dSmrg        also ask the X server supply the current values of these
2660602e473dSmrg        attributes. For example, we can check where a window is
2661602e473dSmrg        located on the screen, what is its current size, whether it is
2662602e473dSmrg        mapped or not, etc. The structure that contains some of this
2663602e473dSmrg        information is
2664602e473dSmrg        </p>
2665602e473dSmrg        <pre class="code">
2666602e473dSmrgtypedef struct {
2667602e473dSmrg    uint8_t      response_type;
2668602e473dSmrg    uint8_t      depth;         /* depth of the window */
2669602e473dSmrg    uint16_t     sequence;
2670602e473dSmrg    uint32_t     length;
2671602e473dSmrg    xcb_window_t root;          /* Id of the root window *>
2672602e473dSmrg    int16_t      x;             /* X coordinate of the window's location */
2673602e473dSmrg    int16_t      y;             /* Y coordinate of the window's location */
2674602e473dSmrg    uint16_t     width;         /* Width of the window */
2675602e473dSmrg    uint16_t     height;        /* Height of the window */
2676602e473dSmrg    uint16_t     border_width;  /* Width of the window's border */
2677602e473dSmrg} xcb_get_geometry_reply_t;
2678602e473dSmrg</pre>
2679602e473dSmrg        <p>
2680602e473dSmrg        XCB fill this structure with two functions:
2681602e473dSmrg        </p>
2682602e473dSmrg        <pre class="code">
2683602e473dSmrgxcb_get_geometry_cookie_t  xcb_get_geometry       (xcb_connection_t         *c,
2684602e473dSmrg                                                   xcb_drawable_t            drawable);
2685602e473dSmrgxcb_get_geometry_reply_t  *xcb_get_geometry_reply (xcb_connection_t         *c,
2686602e473dSmrg                                                   xcb_get_geometry_cookie_t cookie,
2687602e473dSmrg                                                   xcb_generic_error_t     **e);
2688602e473dSmrg</pre>
2689602e473dSmrg        <p>
2690602e473dSmrg        You use them as follows:
2691602e473dSmrg        </p>
2692602e473dSmrg        <pre class="code">
2693602e473dSmrg  xcb_connection_t         *c;
2694602e473dSmrg  xcb_drawable_t            win;
2695602e473dSmrg  xcb_get_geometry_reply_t *geom;
2696602e473dSmrg
2697602e473dSmrg  /* You initialize c and win */
2698602e473dSmrg
2699602e473dSmrg  geom = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL);
2700602e473dSmrg
2701602e473dSmrg  /* Do something with the fields of geom */
2702602e473dSmrg
2703602e473dSmrg  free (geom);
2704602e473dSmrg</pre>
2705602e473dSmrg        <p>
2706602e473dSmrg        Remark that you have to free the structure, as
2707602e473dSmrg        <span class="code">xcb_get_geometry_reply_t</span> allocates a
2708602e473dSmrg        newly one.
2709602e473dSmrg        </p>
2710602e473dSmrg        <p>
2711602e473dSmrg        One problem is that the returned location of the window is
2712602e473dSmrg        relative to its parent window. This makes these coordinates
2713602e473dSmrg        rather useless for any window manipulation functions, like
2714602e473dSmrg        moving it on the screen. In order to overcome this problem, we
2715602e473dSmrg        need to take a two-step operation. First, we find out the Id
2716602e473dSmrg        of the parent window of our window. We then translate the
2717602e473dSmrg        above relative coordinates to the screen coordinates.
2718602e473dSmrg        </p>
2719602e473dSmrg        <p>
2720602e473dSmrg        To get the Id of the parent window, we need this structure:
2721602e473dSmrg        </p>
2722602e473dSmrg        <pre class="code">
2723602e473dSmrgtypedef struct {
2724602e473dSmrg    uint8_t      response_type;
2725602e473dSmrg    uint8_t      pad0;
2726602e473dSmrg    uint16_t     sequence;
2727602e473dSmrg    uint32_t     length;
2728602e473dSmrg    xcb_window_t root;
2729602e473dSmrg    xcb_window_t parent;       /* Id of the parent window */
2730602e473dSmrg    uint16_t     children_len;
2731602e473dSmrg    uint8_t      pad1[14];
2732602e473dSmrg} xcb_query_tree_reply_t;
2733602e473dSmrg</pre>
2734602e473dSmrg        <p>
2735602e473dSmrg        To fill this structure, we use these two functions:
2736602e473dSmrg        </p>
2737602e473dSmrg        <pre class="code">
2738602e473dSmrgxcb_query_tree_cookie_t xcb_query_tree       (xcb_connection_t        *c,
2739602e473dSmrg                                              xcb_window_t             window);
2740602e473dSmrgxcb_query_tree_reply_t *xcb_query_tree_reply (xcb_connection_t        *c,
2741602e473dSmrg                                              xcb_query_tree_cookie_t  cookie,
2742602e473dSmrg                                              xcb_generic_error_t    **e);
2743602e473dSmrg</pre>
2744602e473dSmrg        <p>
2745602e473dSmrg        The translated coordinates will be found in this structure:
2746602e473dSmrg        </p>
2747602e473dSmrg        <pre class="code">
2748602e473dSmrgtypedef struct {
2749602e473dSmrg    uint8_t      response_type;
2750602e473dSmrg    uint8_t      same_screen;
2751602e473dSmrg    uint16_t     sequence;
2752602e473dSmrg    uint32_t     length;
2753602e473dSmrg    xcb_window_t child;
2754602e473dSmrg    uint16_t     dst_x;        /* Translated x coordinate */
2755602e473dSmrg    uint16_t     dst_y;        /* Translated y coordinate */
2756602e473dSmrg} xcb_translate_coordinates_reply_t;
2757602e473dSmrg</pre>
2758602e473dSmrg        <p>
2759602e473dSmrg        As usual, we need two functions to fill this structure:
2760602e473dSmrg        </p>
2761602e473dSmrg        <pre class="code">
2762602e473dSmrgxcb_translate_coordinates_cookie_t xcb_translate_coordinates       (xcb_connection_t                  *c,
2763602e473dSmrg                                                                    xcb_window_t                       src_window,
2764602e473dSmrg                                                                    xcb_window_t                       dst_window,
2765602e473dSmrg                                                                    int16_t                            src_x,
2766602e473dSmrg                                                                    int16_t                            src_y);
2767602e473dSmrgxcb_translate_coordinates_reply_t *xcb_translate_coordinates_reply (xcb_connection_t                  *c,
2768602e473dSmrg                                                                    xcb_translate_coordinates_cookie_t cookie,
2769602e473dSmrg                                                                    xcb_generic_error_t              **e);
2770602e473dSmrg</pre>
2771602e473dSmrg        <p>
2772602e473dSmrg        We use them as follows:
2773602e473dSmrg        </p>
2774602e473dSmrg        <pre class="code">
2775602e473dSmrg  xcb_connection_t                  *c;
2776602e473dSmrg  xcb_drawable_t                     win;
2777602e473dSmrg  xcb_get_geometry_reply_t          *geom;
2778602e473dSmrg  xcb_query_tree_reply_t            *tree;
2779602e473dSmrg  xcb_translate_coordinates_reply_t *trans;
2780602e473dSmrg
2781602e473dSmrg  /* You initialize c and win */
2782602e473dSmrg
2783602e473dSmrg  geom  = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL);
2784602e473dSmrg  if (!geom)
2785602e473dSmrg    return 0;
2786602e473dSmrg
2787602e473dSmrg  tree  = xcb_query_tree_reply (c, xcb_query_tree (c, win), NULL);
2788602e473dSmrg  if (!tree)
2789602e473dSmrg    return 0;
2790602e473dSmrg
2791602e473dSmrg  trans = xcb_translate_coordinates_reply (c,
2792602e473dSmrg                                           xcb_translate_coordinates (c,
2793602e473dSmrg                                                                      win,
2794602e473dSmrg                                                                      tree-&gt;parent,
2795602e473dSmrg                                                                      geom-&gt;x, geom-&gt;y),
2796602e473dSmrg                                           NULL);
2797602e473dSmrg  if (!trans)
2798602e473dSmrg    return 0;
2799602e473dSmrg
2800602e473dSmrg  /* the translated coordinates are in trans-&gt;dst_x and trans-&gt;dst_y */
2801602e473dSmrg
2802602e473dSmrg  free (trans);
2803602e473dSmrg  free (tree);
2804602e473dSmrg  free (geom);
2805602e473dSmrg</pre>
2806602e473dSmrg        <p>
2807602e473dSmrg        Of course, as for <span class="code">geom</span>,
2808602e473dSmrg        <span class="code">tree</span> and
2809602e473dSmrg        <span class="code">trans</span> have to be freed.
2810602e473dSmrg        </p>
2811602e473dSmrg        <p>
2812602e473dSmrg        The work is a bit hard, but XCB is a very low-level library.
2813602e473dSmrg        </p>
2814602e473dSmrg        <p>
2815602e473dSmrg        <b>TODO:</b> the utilization of these functions should be a
2816602e473dSmrg        prog, which displays the coordinates of the window.
2817602e473dSmrg        </p>
2818602e473dSmrg        <p>
2819602e473dSmrg        There is another structure that gives informations about our window:
2820602e473dSmrg        </p>
2821602e473dSmrg        <pre class="code">
2822602e473dSmrgtypedef struct {
2823602e473dSmrg    uint8_t        response_type;
2824602e473dSmrg    uint8_t        backing_store;
2825602e473dSmrg    uint16_t       sequence;
2826602e473dSmrg    uint32_t       length;
2827602e473dSmrg    xcb_visualid_t visual;                /* Visual of the window */
2828602e473dSmrg    uint16_t       _class;
2829602e473dSmrg    uint8_t        bit_gravity;
2830602e473dSmrg    uint8_t        win_gravity;
2831602e473dSmrg    uint32_t       backing_planes;
2832602e473dSmrg    uint32_t       backing_pixel;
2833602e473dSmrg    uint8_t        save_under;
2834602e473dSmrg    uint8_t        map_is_installed;
2835602e473dSmrg    uint8_t        map_state;             /* Map state of the window */
2836602e473dSmrg    uint8_t        override_redirect;
2837602e473dSmrg    xcb_colormap_t colormap;              /* Colormap of the window */
2838602e473dSmrg    uint32_t       all_event_masks;
2839602e473dSmrg    uint32_t       your_event_mask;
2840602e473dSmrg    uint16_t       do_not_propagate_mask;
2841602e473dSmrg} xcb_get_window_attributes_reply_t;
2842602e473dSmrg</pre>
2843602e473dSmrg        <p>
2844602e473dSmrg        XCB supplies these two functions to fill it:
2845602e473dSmrg        </p>
2846602e473dSmrg        <pre class="code">
2847602e473dSmrgxcb_get_window_attributes_cookie_t xcb_get_window_attributes       (xcb_connection_t                  *c,
2848602e473dSmrg                                                                    xcb_window_t                       window);
2849602e473dSmrgxcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (xcb_connection_t                  *c,
2850602e473dSmrg                                                                    xcb_get_window_attributes_cookie_t cookie,
2851602e473dSmrg                                                                    xcb_generic_error_t              **e);
2852602e473dSmrg</pre>
2853602e473dSmrg        <p>
2854602e473dSmrg        You use them as follows:
2855602e473dSmrg        </p>
2856602e473dSmrg        <pre class="code">
2857602e473dSmrg  xcb_connection_t                  *c;
2858602e473dSmrg  xcb_drawable_t                     win;
2859602e473dSmrg  xcb_get_window_attributes_reply_t *attr;
2860602e473dSmrg
2861602e473dSmrg  /* You initialize c and win */
2862602e473dSmrg
2863602e473dSmrg  attr = xcb_get_window_attributes_reply (c, xcb_get_window_attributes (c, win), NULL);
2864602e473dSmrg
2865602e473dSmrg  if (!attr)
2866602e473dSmrg    return 0;
2867602e473dSmrg
2868602e473dSmrg  /* Do something with the fields of attr */
2869602e473dSmrg
2870602e473dSmrg  free (attr);
2871602e473dSmrg</pre>
2872602e473dSmrg        <p>
2873602e473dSmrg        As for <span class="code">geom</span>,
2874602e473dSmrg        <span class="code">attr</span> has to be freed.
2875602e473dSmrg        </p>
2876602e473dSmrg      </ol>
2877602e473dSmrg      <li class="title"><a name="usecolor">Using colors to paint the rainbow</a>
2878602e473dSmrg      <p>
2879602e473dSmrg      Up until now, all our painting operation were done using black
2880602e473dSmrg      and white. We will (finally) see now how to draw using colors.
2881602e473dSmrg      </p>
2882602e473dSmrg      <ol>
2883602e473dSmrg        <li class="subtitle"><a name="colormap">Color maps</a>
2884602e473dSmrg        <p>
2885602e473dSmrg        In the beginning, there were not enough colors. Screen
2886602e473dSmrg        controllers could only support a limited number of colors
2887602e473dSmrg        simultaneously (initially 2, then 4, 16 and 256). Because of
2888602e473dSmrg        this, an application could not just ask to draw in a "light
2889602e473dSmrg        purple-red" color, and expect that color to be available. Each
2890602e473dSmrg        application allocated the colors it needed, and when all the
2891602e473dSmrg        color entries (4, 16, 256 colors) were in use, the next color
2892602e473dSmrg        allocation would fail.
2893602e473dSmrg        </p>
2894602e473dSmrg        <p>
2895602e473dSmrg        Thus, the notion of "a color map" was introduced. A color map
2896602e473dSmrg        is a table whose size is the same as the number of
2897602e473dSmrg        simultaneous colors a given screen controller. Each entry
2898602e473dSmrg        contained the RGB (Red, Green and Blue) values of a different
2899602e473dSmrg        color (all colors can be drawn using some combination of red,
2900602e473dSmrg        green and blue). When an application wants to draw on the
2901602e473dSmrg        screen, it does not specify which color to use. Rather, it
2902602e473dSmrg        specifies which color entry of some color map to be used
2903602e473dSmrg        during this drawing. Change the value in this color map entry
2904602e473dSmrg        and the drawing will use a different color.
2905602e473dSmrg        </p>
2906602e473dSmrg        <p>
2907602e473dSmrg        In order to be able to draw using colors that got something to
2908602e473dSmrg        do with what the programmer intended, color map allocation
2909602e473dSmrg        functions are supplied. You could ask to allocate entry for a
2910602e473dSmrg        color with a set of RGB values. If one already existed, you
2911602e473dSmrg        would get its index in the table. If none existed, and the
2912602e473dSmrg        table was not full, a new cell would be allocated to contain
2913602e473dSmrg        the given RGB values, and its index returned. If the table was
2914602e473dSmrg        full, the procedure would fail. You could then ask to get a
2915602e473dSmrg        color map entry with a color that is closest to the one you
2916602e473dSmrg        were asking for. This would mean that the actual drawing on
2917602e473dSmrg        the screen would be done using colors similar to what you
2918602e473dSmrg        wanted, but not the same.
2919602e473dSmrg        </p>
2920602e473dSmrg        <p>
2921602e473dSmrg        On today's more modern screens where one runs an X server with
2922602e473dSmrg        support for 16 million colors, this limitation looks a little
2923602e473dSmrg        silly, but remember that there are still older computers with
2924602e473dSmrg        older graphics cards out there. Using color map, support for
2925602e473dSmrg        these screen becomes transparent to you. On a display
2926602e473dSmrg        supporting 16 million colors, any color entry allocation
2927602e473dSmrg        request would succeed. On a display supporting a limited
2928602e473dSmrg        number of colors, some color allocation requests would return
2929602e473dSmrg        similar colors. It won't look as good, but your application
2930602e473dSmrg        would still work.
2931602e473dSmrg        </p>
2932602e473dSmrg        <li class="subtitle"><a name="colormapalloc">Allocating and freeing Color Maps</a>
2933602e473dSmrg        <p>
2934602e473dSmrg        When you draw using XCB, you can choose to use the standard
2935602e473dSmrg        color map of the screen your window is displayed on, or you
2936602e473dSmrg        can allocate a new color map and apply it to a window. In the
2937602e473dSmrg        latter case, each time the mouse moves onto your window, the
2938602e473dSmrg        screen color map will be replaced by your window's color map,
2939602e473dSmrg        and you'll see all the other windows on screen change their
29401c7386f4Smrg        colors into something quite bizarre. In fact, this is the
2941602e473dSmrg        effect you get with X applications that use the "-install"
2942602e473dSmrg        command line option.
2943602e473dSmrg        </p>
2944602e473dSmrg        <p>
2945602e473dSmrg        In XCB, a color map is (as often in X) an Id:
2946602e473dSmrg        </p>
2947602e473dSmrg        <pre class="code">
2948602e473dSmrgtypedef uint32_t xcb_colormap_t;
2949602e473dSmrg</pre>
2950602e473dSmrg        <p>
2951602e473dSmrg        In order to access the screen's default color map, you just
2952602e473dSmrg        have to retrieve the <span class="code">default_colormap</span>
2953602e473dSmrg        field of the <span class="code">xcb_screen_t</span> structure
2954602e473dSmrg        (see Section
2955602e473dSmrg        <a href="#screen">Checking basic information about a connection</a>):
2956602e473dSmrg        </p>
2957602e473dSmrg        <pre class="code">
2958602e473dSmrg#include &lt;stdio.h&gt;
2959602e473dSmrg
2960602e473dSmrg#include &lt;xcb/xcb.h&gt;
2961602e473dSmrg
2962602e473dSmrgint
2963602e473dSmrgmain ()
2964602e473dSmrg{
2965602e473dSmrg  xcb_connection_t *c;
2966602e473dSmrg  xcb_screen_t     *screen;
2967602e473dSmrg  xcb_colormap_t    colormap;
2968602e473dSmrg
2969602e473dSmrg  /* Open the connection to the X server and get the first screen */
2970602e473dSmrg  c = xcb_connect (NULL, NULL);
2971602e473dSmrg  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
2972602e473dSmrg
2973602e473dSmrg  colormap = screen-&gt;default_colormap;
2974602e473dSmrg
2975602e473dSmrg  return 0;
2976602e473dSmrg}
2977602e473dSmrg</pre>
2978602e473dSmrg        <p>
2979602e473dSmrg        This will return the color map used by default on the first
2980602e473dSmrg        screen (again, remember that an X server may support several
2981602e473dSmrg        different screens, each of which might have its own resources).
2982602e473dSmrg        </p>
2983602e473dSmrg        <p>
2984602e473dSmrg        The other option, that of allocating a new colormap, works as
2985602e473dSmrg        follows.  We first ask the X server to give an Id to our color
2986602e473dSmrg        map, with this function:
2987602e473dSmrg        </p>
2988602e473dSmrg        <pre class="code">
2989602e473dSmrgxcb_colormap_t xcb_generate_id (xcb_connection_t *c);
2990602e473dSmrg</pre>
2991602e473dSmrg        <p>
2992602e473dSmrg        Then, we create the color map with
2993602e473dSmrg        </p>
2994602e473dSmrg        <pre class="code">
2995602e473dSmrgxcb_void_cookie_t xcb_create_colormap (xcb_connection_t *c,       /* Pointer to the xcb_connection_t structure */
2996602e473dSmrg                                       uint8_t           alloc,   /* Colormap entries to be allocated (AllocNone or AllocAll) */
2997602e473dSmrg                                       xcb_colormap_t    mid,     /* Id of the color map */
2998602e473dSmrg                                       xcb_window_t      window,  /* Window on whose screen the colormap will be created */
2999602e473dSmrg                                       xcb_visualid_t    visual); /* Id of the visual supported by the screen */
3000602e473dSmrg</pre>
3001602e473dSmrg        <p>
3002602e473dSmrg        Here is an example of creation of a new color map:
3003602e473dSmrg        </p>
3004602e473dSmrg        <pre class="code">
3005602e473dSmrg#include &lt;xcb/xcb.h&gt;
3006602e473dSmrg
3007602e473dSmrgint
3008602e473dSmrgmain ()
3009602e473dSmrg{
3010602e473dSmrg  xcb_connection_t *c;
3011602e473dSmrg  xcb_screen_t     *screen;
3012602e473dSmrg  xcb_window_t      win;
3013602e473dSmrg  xcb_colormap_t    cmap
3014602e473dSmrg
3015602e473dSmrg  /* Open the connection to the X server and get the first screen */
3016602e473dSmrg  c = xcb_connect (NULL, NULL);
3017602e473dSmrg  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
3018602e473dSmrg
3019602e473dSmrg  /* We create the window win here*/
3020602e473dSmrg
3021602e473dSmrg  cmap = xcb_generate_id (c);
3022602e473dSmrg  xcb_create_colormap (c, XCB_COLORMAP_ALLOC_NONE, cmap, win, screen-&gt;root_visual);
3023602e473dSmrg
3024602e473dSmrg  return 0;
3025602e473dSmrg}
3026602e473dSmrg</pre>
3027602e473dSmrg        <p>
3028602e473dSmrg        Note that the window parameter is only used to allow the X
3029602e473dSmrg        server to create the color map for the given screen. We can
3030602e473dSmrg        then use this color map for any window drawn on the same screen.
3031602e473dSmrg        </p>
3032602e473dSmrg        <p>
3033602e473dSmrg        To free  a color map, it suffices to use this function:
3034602e473dSmrg        </p>
3035602e473dSmrg        <pre class="code">
3036602e473dSmrgxcb_void_cookie_t xcb_free_colormap (xcb_connection_t *c,   /* The connection */
3037602e473dSmrg                                     xcb_colormap_t cmap);  /* The color map */
3038602e473dSmrg</pre>
3039602e473dSmrg        <div class="comp">
3040602e473dSmrg          <div class="title">
3041602e473dSmrg            Comparison Xlib/XCB
3042602e473dSmrg          </div>
3043602e473dSmrg          <div class="xlib">
3044602e473dSmrg            <ul>
3045602e473dSmrg              <li>XCreateColormap ()
3046602e473dSmrg            </ul>
3047602e473dSmrg          </div>
3048602e473dSmrg          <div class="xcb">
3049602e473dSmrg            <ul>
3050602e473dSmrg              <li>xcb_generate_id ()
3051602e473dSmrg              <li>xcb_create_colormap ()
3052602e473dSmrg            </ul>
3053602e473dSmrg          </div>
3054602e473dSmrg          <div class="xlib">
3055602e473dSmrg            <ul>
3056602e473dSmrg              <li>XFreeColormap ()
3057602e473dSmrg            </ul>
3058602e473dSmrg          </div>
3059602e473dSmrg          <div class="xcb">
3060602e473dSmrg            <ul>
3061602e473dSmrg              <li>xcb_free_colormap ()
3062602e473dSmrg            </ul>
3063602e473dSmrg          </div>
3064602e473dSmrg        </div>
3065602e473dSmrg        <br>
3066602e473dSmrg        <li class="subtitle"><a name="alloccolor">Allocating and freeing a color entry</a>
3067602e473dSmrg        <p>
3068602e473dSmrg        Once we got access to some color map, we can start allocating
3069602e473dSmrg        colors. The informations related to a color are stored in the
3070602e473dSmrg        following structure:
3071602e473dSmrg        </p>
3072602e473dSmrg        <pre class="code">
3073602e473dSmrgtypedef struct {
3074602e473dSmrg    uint8_t  response_type;
3075602e473dSmrg    uint8_t  pad0;
3076602e473dSmrg    uint16_t sequence;
3077602e473dSmrg    uint32_t length;
3078602e473dSmrg    uint16_t red;          /* The red component   */
3079602e473dSmrg    uint16_t green;        /* The green component */
3080602e473dSmrg    uint16_t blue;         /* The blue component  */
3081602e473dSmrg    uint8_t  pad1[2];
3082602e473dSmrg    uint32_t pixel;        /* The entry in the color map, supplied by the X server */
3083602e473dSmrg} xcb_alloc_color_reply_t;
3084602e473dSmrg</pre>
3085602e473dSmrg      <p>
3086602e473dSmrg      XCB supplies these two functions to fill it:
3087602e473dSmrg      </p>
3088602e473dSmrg      <pre class="code">
3089602e473dSmrgxcb_alloc_color_cookie_t xcb_alloc_color       (xcb_connection_t        *c,
3090602e473dSmrg                                                xcb_colormap_t           cmap,
3091602e473dSmrg                                                uint16_t                 red,
3092602e473dSmrg                                                uint16_t                 green,
3093602e473dSmrg                                                uint16_t                 blue);
3094602e473dSmrgxcb_alloc_color_reply_t *xcb_alloc_color_reply (xcb_connection_t        *c,
3095602e473dSmrg                                                xcb_alloc_color_cookie_t cookie,
3096602e473dSmrg                                                xcb_generic_error_t    **e);
3097602e473dSmrg</pre>
3098602e473dSmrg      <p>
3099602e473dSmrg      The fuction <span class="code">xcb_alloc_color()</span> takes the
3100602e473dSmrg      3 RGB components as parameters (red, green and blue). Here is an
3101602e473dSmrg      example of using these functions:
3102602e473dSmrg      </p>
3103602e473dSmrg      <pre class="code">
3104602e473dSmrg#include &lt;malloc.h&gt;
3105602e473dSmrg
3106602e473dSmrg#include &lt;xcb/xcb.h&gt;
3107602e473dSmrg
3108602e473dSmrgint
3109602e473dSmrgmain ()
3110602e473dSmrg{
3111602e473dSmrg  xcb_connection_t        *c;
3112602e473dSmrg  xcb_screen_t            *screen;
3113602e473dSmrg  xcb_window_t             win;
3114602e473dSmrg  xcb_colormap_t           cmap;
3115602e473dSmrg  xcb_alloc_color_reply_t *rep;
3116602e473dSmrg
3117602e473dSmrg  /* Open the connection to the X server and get the first screen */
3118602e473dSmrg  c = xcb_connect (NULL, NULL);
3119602e473dSmrg  screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
3120602e473dSmrg
3121602e473dSmrg  /* We create the window win here*/
3122602e473dSmrg
3123602e473dSmrg  cmap = xcb_generate_id (c);
3124602e473dSmrg  xcb_create_colormap (c, XCB_COLORMAP_ALLOC_NONE, cmap, win, screen-&gt;root_visual);
3125602e473dSmrg
3126602e473dSmrg  rep = xcb_alloc_color_reply (c, xcb_alloc_color (c, cmap, 65535, 0, 0), NULL);
3127602e473dSmrg
3128602e473dSmrg  if (!rep)
3129602e473dSmrg    return 0;
3130602e473dSmrg
3131602e473dSmrg  /* Do something with r-&gt;pixel or the components */
3132602e473dSmrg
3133602e473dSmrg  free (rep);
3134602e473dSmrg
3135602e473dSmrg  return 0;
3136602e473dSmrg}
3137602e473dSmrg</pre>
3138602e473dSmrg      <p>
3139602e473dSmrg      As <span class="code">xcb_alloc_color_reply()</span> allocates
3140602e473dSmrg      memory, you have to free <span class="code">rep</span>.
3141602e473dSmrg      </p>
3142602e473dSmrg      <p>
3143602e473dSmrg      <b>TODO</b>: Talk about freeing colors.
3144602e473dSmrg      </p>
3145602e473dSmrg      </ol>
3146602e473dSmrg      <li class="title"><a name="pixmaps">X Bitmaps and Pixmaps</a>
3147602e473dSmrg      <p>
3148602e473dSmrg      One thing many so-called "Multi-Media" applications need to do,
3149602e473dSmrg      is display images. In the X world, this is done using bitmaps
3150602e473dSmrg      and pixmaps. We have already seen some usage of them when
3151602e473dSmrg      setting an icon for our application. Lets study them further,
3152602e473dSmrg      and see how to draw these images inside a window, along side the
3153602e473dSmrg      simple graphics and text we have seen so far.
3154602e473dSmrg      </p>
3155602e473dSmrg      <p>
3156602e473dSmrg      One thing to note before delving further, is that XCB (nor Xlib)
3157602e473dSmrg      supplies no means of manipulating popular image formats, such as
3158602e473dSmrg      gif, png, jpeg or tiff. It is up to the programmer (or to higher
3159602e473dSmrg      level graphics libraries) to translate these image formats into
3160602e473dSmrg      formats that the X server is familiar with (x bitmaps and x
3161602e473dSmrg      pixmaps).
3162602e473dSmrg      </p>
3163602e473dSmrg      <ol>
3164602e473dSmrg        <li class="subtitle"><a name="pixmapswhat">What is a X Bitmap? An X Pixmap?</a>
3165602e473dSmrg        <p>
3166602e473dSmrg        An X bitmap is a two-color image stored in a format specific
3167602e473dSmrg        to the X window system. When stored in a file, the bitmap data
3168602e473dSmrg        looks like a C source file. It contains variables defining the
3169602e473dSmrg        width and the height of the bitmap, an array containing the
3170602e473dSmrg        bit values of the bitmap (the size of the array is
3171602e473dSmrg        (width+7)/8*height and the bit and byte order are LSB), and
3172602e473dSmrg        an optional hot-spot location (that will
3173602e473dSmrg        be explained later, when discussing mouse cursors).
3174602e473dSmrg        </p>
3175602e473dSmrg        <p>
3176602e473dSmrg        An X pixmap is a format used to stored images in the memory of
3177602e473dSmrg        an X server. This format can store both black and white images
3178602e473dSmrg        (such as x bitmaps) as well as color images. It is the only
3179602e473dSmrg        image format supported by the X protocol, and any image to be
3180602e473dSmrg        drawn on screen, should be first translated into this format.
3181602e473dSmrg        </p>
3182602e473dSmrg        <p>
3183602e473dSmrg        In actuality, an X pixmap can be thought of as a window that
3184602e473dSmrg        does not appear on the screen. Many graphics operations that
3185602e473dSmrg        work on windows, will also work on pixmaps. Indeed, the type
3186602e473dSmrg        of X pixmap in XCB is an Id like a window:
3187602e473dSmrg        </p>
3188602e473dSmrg        <pre class="code">
3189602e473dSmrgtypedef uint32_t xcb_pixmap_t;
3190602e473dSmrg</pre>
3191602e473dSmrg        <p>
3192602e473dSmrg        Like Xlib, there is no difference between a Drawable, a Window
3193602e473dSmrg        or a Pixmap:
3194602e473dSmrg        </p>
3195602e473dSmrg        <pre class="code">
3196602e473dSmrgtypedef uint32_t xcb_drawable_t;
3197602e473dSmrg</pre>
3198602e473dSmrg        <p>
3199602e473dSmrg        in order to avoid confusion between a window and a pixmap. The
3200602e473dSmrg        operations that will work the same on a window or a pixmap
3201602e473dSmrg        will require a <span class="code">xcb_drawable_t</span>
3202602e473dSmrg        </p>
3203602e473dSmrg        <div class="emph">
3204602e473dSmrg        <p>
3205602e473dSmrg        Remark: In Xlib, there is no specific difference between a
3206602e473dSmrg        <span class="code">Drawable</span>, a
3207602e473dSmrg        <span class="code">Pixmap</span> or a
3208602e473dSmrg        <span class="code">Window</span>: all are 32 bit long
3209602e473dSmrg        integer.  XCB wraps all these different IDs in structures to
3210602e473dSmrg        provide some measure of type-safety.
3211602e473dSmrg        </p>
3212602e473dSmrg        </div>
3213602e473dSmrg        <li class="subtitle"><a name="pixmapscreate">Creating a pixmap</a>
3214602e473dSmrg        <p>
3215602e473dSmrg        Sometimes we want to create an un-initialized pixmap, so we
3216602e473dSmrg        can later draw into it. This is useful for image drawing
3217602e473dSmrg        programs (creating a new empty canvas will cause the creation
3218602e473dSmrg        of a new pixmap on which the drawing can be stored). It is
3219602e473dSmrg        also useful when reading various image formats: we load the
3220602e473dSmrg        image data into memory, create a pixmap on the server, and
3221602e473dSmrg        then draw the decoded image data onto that pixmap.
3222602e473dSmrg        </p>
3223602e473dSmrg        <p>
3224602e473dSmrg        To create a new pixmap, we first ask the X server to give an
3225602e473dSmrg        Id to our pixmap, with this function:
3226602e473dSmrg        </p>
3227602e473dSmrg        <pre class="code">
3228602e473dSmrgxcb_pixmap_t xcb_generate_id (xcb_connection_t *c);
3229602e473dSmrg</pre>
3230602e473dSmrg        <p>
3231602e473dSmrg         Then, XCB supplies the following function to create new pixmaps:
3232602e473dSmrg        </p>
3233602e473dSmrg        <pre class="code">
3234602e473dSmrgxcb_void_cookie_t xcb_create_pixmap (xcb_connection_t *c,         /* Pointer to the xcb_connection_t structure */
3235602e473dSmrg                                     uint8_t           depth,     /* Depth of the screen */
3236602e473dSmrg                                     xcb_pixmap_t      pid,       /* Id of the pixmap */
3237602e473dSmrg                                     xcb_drawable_t    drawable,
3238602e473dSmrg                                     uint16_t          width,     /* Width of the window (in pixels) */
3239602e473dSmrg                                     uint16_t          height);   /* Height of the window (in pixels) */
3240602e473dSmrg</pre>
3241602e473dSmrg        <p>
3242602e473dSmrg        <b>TODO</b>: Explain the drawable parameter, and give an
3243602e473dSmrg        example (like <a href="xpoints.c">xpoints.c</a>)
3244602e473dSmrg        </p>
3245602e473dSmrg        <li class="subtitle"><a name="pixmapsdraw"></a>Drawing a pixmap in a window
3246602e473dSmrg        <p>
3247602e473dSmrg        Once we got a handle to a pixmap, we can draw it on some
3248602e473dSmrg        window, using the following function:
3249602e473dSmrg        </p>
3250602e473dSmrg        <pre class="code">
3251602e473dSmrgxcb_void_cookie_t xcb_copy_area (xcb_connection_t *c,             /* Pointer to the xcb_connection_t structure */
3252602e473dSmrg                                 xcb_drawable_t    src_drawable,  /* The Drawable we want to paste */
3253602e473dSmrg                                 xcb_drawable_t    dst_drawable,  /* The Drawable on which we copy the previous Drawable */
3254602e473dSmrg                                 xcb_gcontext_t    gc,            /* A Graphic Context */
3255602e473dSmrg                                 int16_t           src_x,         /* Top left x coordinate of the region we want to copy */
3256602e473dSmrg                                 int16_t           src_y,         /* Top left y coordinate of the region we want to copy */
3257602e473dSmrg                                 int16_t           dst_x,         /* Top left x coordinate of the region where we want to copy */
3258602e473dSmrg                                 int16_t           dst_y,         /* Top left y coordinate of the region where we want to copy */
3259602e473dSmrg                                 uint16_t          width,         /* Width of the region we want to copy */
3260602e473dSmrg                                 uint16_t          height);       /* Height of the region we want to copy */
3261602e473dSmrg</pre>
3262602e473dSmrg        <p>
3263602e473dSmrg        As you can see, we could copy the whole pixmap, as well as
3264602e473dSmrg        only a given rectangle of the pixmap. This is useful to
3265602e473dSmrg        optimize the drawing speed: we could copy only what we have
3266602e473dSmrg        modified in the pixmap.
3267602e473dSmrg        </p>
3268602e473dSmrg        <p>
3269602e473dSmrg        <b>One important note should be made</b>: it is possible to
3270602e473dSmrg        create pixmaps with different depths on the same screen. When
3271602e473dSmrg        we perform copy operations (a pixmap onto a window, etc), we
3272602e473dSmrg        should make sure that both source and target have the same
3273602e473dSmrg        depth. If they have a different depth, the operation would
3274602e473dSmrg        fail. The exception to this is if we copy a specific bit plane
3275602e473dSmrg        of the source pixmap using the
3276602e473dSmrg        <span class="code">xcb_copy_plane_t</span> function. In such an
3277602e473dSmrg        event, we can copy a specific plane to the target window (in
3278602e473dSmrg        actuality, setting a specific bit in the color of each pixel
3279602e473dSmrg        copied). This can be used to generate strange graphic effects
3280602e473dSmrg        in a window, but that is beyond the scope of this tutorial.
3281602e473dSmrg        </p>
3282602e473dSmrg        <li class="subtitle"><a name="pixmapsfree"></a>Freeing a pixmap
3283602e473dSmrg        <p>
3284602e473dSmrg        Finally, when we are done using a given pixmap, we should free
3285602e473dSmrg        it, in order to free resources of the X server. This is done
3286602e473dSmrg        using this function:
3287602e473dSmrg        </p>
3288602e473dSmrg        <pre class="code">
3289602e473dSmrgxcb_void_cookie_t xcb_free_pixmap (xcb_connection_t *c,        /* Pointer to the xcb_connection_t structure */
3290602e473dSmrg                                   xcb_pixmap_t      pixmap);  /* A given pixmap */
3291602e473dSmrg</pre>
3292602e473dSmrg        <p>
3293602e473dSmrg        Of course, after having freed it, we must not try accessing
3294602e473dSmrg        the pixmap again.
3295602e473dSmrg        </p>
3296602e473dSmrg        <p>
3297602e473dSmrg        <b>TODO</b>: Give an example, or a link to xpoints.c
3298602e473dSmrg        </p>
3299602e473dSmrg      </ol>
3300602e473dSmrg      <li class="title"><a name="mousecursor">Messing with the mouse cursor</a>
3301602e473dSmrg      <p>
3302602e473dSmrg      It it possible to modify the shape of the mouse pointer (also
33031c7386f4Smrg      called the X pointer) when in certain states, as we often see in
3304602e473dSmrg      programs. For example, a busy application would often display
33051c7386f4Smrg      the hourglass cursor over its main window, to give the user a visual
33061c7386f4Smrg      hint that they should wait. Let's see how we can change the mouse
3307602e473dSmrg      cursor of our windows.
3308602e473dSmrg      </p>
3309602e473dSmrg      <ol>
3310602e473dSmrg        <li class="subtitle"><a name="mousecursorcreate">Creating and destroying a mouse cursor</a>
3311602e473dSmrg        <p>
3312602e473dSmrg        There are two methods for creating cursors. One of them is by
3313602e473dSmrg        using a set of predefined cursors, that are supplied by the X
3314602e473dSmrg        server, the other is by using a user-supplied bitmap.
3315602e473dSmrg        </p>
3316602e473dSmrg        <p>
3317602e473dSmrg        In the first method, we use a special font named "cursor", and
3318602e473dSmrg        the function <span class="code">xcb_create_glyph_cursor</span>:
3319602e473dSmrg        </p>
3320602e473dSmrg        <pre class="code">
3321602e473dSmrgxcb_void_cookie_t xcb_create_glyph_cursor (xcb_connection_t *c,
3322602e473dSmrg                                           xcb_cursor_t      cid,
3323602e473dSmrg                                           xcb_font_t        source_font, /* font for the source glyph */
3324602e473dSmrg                                           xcb_font_t        mask_font,   /* font for the mask glyph or XCB_NONE */
3325602e473dSmrg                                           uint16_t          source_char, /* character glyph for the source */
3326602e473dSmrg                                           uint16_t          mask_char,   /* character glyph for the mask */
3327602e473dSmrg                                           uint16_t          fore_red,    /* red value for the foreground of the source */
3328602e473dSmrg                                           uint16_t          fore_green,  /* green value for the foreground of the source */
3329602e473dSmrg                                           uint16_t          fore_blue,   /* blue value for the foreground of the source */
3330602e473dSmrg                                           uint16_t          back_red,    /* red value for the background of the source */
3331602e473dSmrg                                           uint16_t          back_green,  /* green value for the background of the source */
3332602e473dSmrg                                           uint16_t          back_blue)   /* blue value for the background of the source */
3333602e473dSmrg</pre>
3334602e473dSmrg        <p>
3335602e473dSmrg        <b>TODO</b>: Describe <span class="code">source_char</span>
3336602e473dSmrg        and <span class="code">mask_char</span>, for example by giving
3337602e473dSmrg        an example on how to get the values. There is a list there:
3338602e473dSmrg        <a href="http://tronche.com/gui/x/xlib/appendix/b/">X Font Cursors</a>
3339602e473dSmrg        </p>
3340602e473dSmrg        <p>
3341602e473dSmrg        So we first open that font (see <a href="#loadfont">Loading a Font</a>)
33421c7386f4Smrg        and create the new cursor. As for every X resource, we have to
3343602e473dSmrg        ask for an X id with <span class="code">xcb_generate_id</span>
3344602e473dSmrg        first:
3345602e473dSmrg        </p>
3346602e473dSmrg        <pre class="code">
3347602e473dSmrgxcb_font_t           font;
3348602e473dSmrgxcb_cursor_t         cursor;
3349602e473dSmrg
3350602e473dSmrg/* The connection is set */
3351602e473dSmrg
3352602e473dSmrgfont = xcb_generate_id (conn);
3353602e473dSmrgxcb_open_font (conn, font, strlen ("cursor"), "cursor");
3354602e473dSmrg
3355602e473dSmrgcursor = xcb_generate_id (conn);
3356602e473dSmrgxcb_create_glyph_cursor (conn, cursor, font, font,
3357602e473dSmrg                         58, 58 + 1,
3358602e473dSmrg                         0, 0, 0,
3359602e473dSmrg                         0, 0, 0);
3360602e473dSmrg</pre>
3361602e473dSmrg        <p>
3362602e473dSmrg        We have created the cursor "right hand" by specifying 58 to
3363602e473dSmrg        the <span class="code">source_fon</span>t argument and 58 + 1
3364602e473dSmrg        to the <span class="code">mask_font</span>.
3365602e473dSmrg        </p>
3366602e473dSmrg        <p>
3367602e473dSmrg        The cursor is destroyed by using the function
3368602e473dSmrg        </p>
3369602e473dSmrg        <pre class="code">
3370602e473dSmrgxcb_void_cookie_t xcb_free_cursor (xcb_connection_t *c,
3371602e473dSmrg                                   xcb_cursor_t      cursor);
3372602e473dSmrg</pre>
3373602e473dSmrg        <p>
3374602e473dSmrg        In the second method, we create a new cursor by using a pair
3375602e473dSmrg        of pixmaps, with depth of one (that is, two colors
3376602e473dSmrg        pixmaps). One pixmap defines the shape of the cursor, while
3377602e473dSmrg        the other works as a mask, specifying which pixels of the
3378602e473dSmrg        cursor will be actually drawn. The rest of the pixels will be
3379602e473dSmrg        transparent.
3380602e473dSmrg        </p>
3381602e473dSmrg        <p>
3382602e473dSmrg        <b>TODO</b>: give an example.
3383602e473dSmrg        </p>
3384602e473dSmrg        <li class="subtitle"><a name="mousecursorset">Setting a window's mouse cursor</a>
3385602e473dSmrg        <p>
3386602e473dSmrg        Once the cursor is created, we can modify the cursor of our
3387602e473dSmrg        window by using <span class="code">xcb_change_window_attributes</span>
3388602e473dSmrg        and using the <span class="code">XCB_CWCURSOR</span> attribute:
3389602e473dSmrg        </p>
3390602e473dSmrg        <pre class="code">
3391602e473dSmrguint32_t mask;
3392602e473dSmrguint32_t value_list;
3393602e473dSmrg
3394602e473dSmrg/* The connection and window are set */
3395602e473dSmrg/* The cursor is already created */
3396602e473dSmrg
3397602e473dSmrgmask = XCB_CWCURSOR;
3398602e473dSmrgvalue_list = cursor;
3399602e473dSmrgxcb_change_window_attributes (conn, window, mask, &amp;value_list);
3400602e473dSmrg</pre>
3401602e473dSmrg        <p>
3402602e473dSmrg        Of course, the cursor and the font must be freed.
3403602e473dSmrg        </p>
3404602e473dSmrg        <li class="subtitle"><a name="mousecursorexample">Complete example</a>
3405602e473dSmrg        <p>
3406602e473dSmrg        The following example displays a window with a
3407602e473dSmrg        button. When entering the window, the window cursor is changed
3408602e473dSmrg        to an arrow. When clicking once on the button, the cursor is
3409602e473dSmrg        changed to a hand. When clicking again on the button, the
3410602e473dSmrg        cursor window gets back to the arrow. The Esc key exits the
3411602e473dSmrg        application.
3412602e473dSmrg        </p>
3413602e473dSmrg        <pre class="code">
3414602e473dSmrg#include &lt;stdlib.h&gt;
3415602e473dSmrg#include &lt;stdio.h&gt;
3416602e473dSmrg#include &lt;string.h&gt;
3417602e473dSmrg
3418602e473dSmrg#include &lt;xcb/xcb.h&gt;
3419602e473dSmrg
3420602e473dSmrg#define WIDTH 300
3421602e473dSmrg#define HEIGHT 150
3422602e473dSmrg
3423602e473dSmrg
3424602e473dSmrg
3425602e473dSmrgstatic xcb_gc_t gc_font_get (xcb_connection_t *c,
3426602e473dSmrg                             xcb_screen_t     *screen,
3427602e473dSmrg                             xcb_window_t      window,
3428602e473dSmrg                             const char       *font_name);
3429602e473dSmrg
3430602e473dSmrgstatic void button_draw (xcb_connection_t *c,
3431602e473dSmrg                         xcb_screen_t     *screen,
3432602e473dSmrg                         xcb_window_t      window,
3433602e473dSmrg                         int16_t           x1,
3434602e473dSmrg                         int16_t           y1,
3435602e473dSmrg                         const char       *label);
3436602e473dSmrg
3437602e473dSmrgstatic void text_draw (xcb_connection_t *c,
3438602e473dSmrg                       xcb_screen_t     *screen,
3439602e473dSmrg                       xcb_window_t      window,
3440602e473dSmrg                       int16_t           x1,
3441602e473dSmrg                       int16_t           y1,
3442602e473dSmrg                       const char       *label);
3443602e473dSmrg
3444602e473dSmrgstatic void cursor_set (xcb_connection_t *c,
3445602e473dSmrg                        xcb_screen_t     *screen,
3446602e473dSmrg                        xcb_window_t      window,
3447602e473dSmrg                        int               cursor_id);
3448602e473dSmrg
3449602e473dSmrg
3450602e473dSmrgstatic void
3451602e473dSmrgbutton_draw (xcb_connection_t *c,
3452602e473dSmrg             xcb_screen_t     *screen,
3453602e473dSmrg             xcb_window_t      window,
3454602e473dSmrg             int16_t           x1,
3455602e473dSmrg             int16_t           y1,
3456602e473dSmrg             const char       *label)
3457602e473dSmrg{
3458602e473dSmrg  xcb_point_t          points[5];
3459602e473dSmrg  xcb_void_cookie_t    cookie_gc;
3460602e473dSmrg  xcb_void_cookie_t    cookie_line;
3461602e473dSmrg  xcb_void_cookie_t    cookie_text;
3462602e473dSmrg  xcb_generic_error_t *error;
3463602e473dSmrg  xcb_gcontext_t       gc;
3464602e473dSmrg  int16_t              width;
3465602e473dSmrg  int16_t              height;
3466602e473dSmrg  uint8_t              length;
3467602e473dSmrg  int16_t              inset;
3468602e473dSmrg
3469602e473dSmrg  length = strlen (label);
3470602e473dSmrg  inset = 2;
3471602e473dSmrg
3472602e473dSmrg  gc = gc_font_get(c, screen, window, "7x13");
3473602e473dSmrg
3474602e473dSmrg  width = 7 * length + 2 * (inset + 1);
3475602e473dSmrg  height = 13 + 2 * (inset + 1);
3476602e473dSmrg  points[0].x = x1;
3477602e473dSmrg  points[0].y = y1;
3478602e473dSmrg  points[1].x = x1 + width;
3479602e473dSmrg  points[1].y = y1;
3480602e473dSmrg  points[2].x = x1 + width;
3481602e473dSmrg  points[2].y = y1 - height;
3482602e473dSmrg  points[3].x = x1;
3483602e473dSmrg  points[3].y = y1 - height;
3484602e473dSmrg  points[4].x = x1;
3485602e473dSmrg  points[4].y = y1;
3486602e473dSmrg  cookie_line = xcb_poly_line_checked (c, XCB_COORD_MODE_ORIGIN,
3487602e473dSmrg                                       window, gc, 5, points);
3488602e473dSmrg
3489602e473dSmrg  error = xcb_request_check (c, cookie_line);
3490602e473dSmrg  if (error) {
3491602e473dSmrg    fprintf (stderr, "ERROR: can't draw lines : %d\n", error->error_code);
3492602e473dSmrg    xcb_disconnect (c);
3493602e473dSmrg    exit (-1);
3494602e473dSmrg  }
3495602e473dSmrg
3496602e473dSmrg  cookie_text = xcb_image_text_8_checked (c, length, window, gc,
3497602e473dSmrg                                          x1 + inset + 1,
3498602e473dSmrg                                          y1 - inset - 1, label);
3499602e473dSmrg  error = xcb_request_check (c, cookie_text);
3500602e473dSmrg  if (error) {
3501602e473dSmrg    fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
3502602e473dSmrg    xcb_disconnect (c);
3503602e473dSmrg    exit (-1);
3504602e473dSmrg  }
3505602e473dSmrg
3506602e473dSmrg  cookie_gc = xcb_free_gc (c, gc);
3507602e473dSmrg  error = xcb_request_check (c, cookie_gc);
3508602e473dSmrg  if (error) {
3509602e473dSmrg    fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
3510602e473dSmrg    xcb_disconnect (c);
3511602e473dSmrg    exit (-1);
3512602e473dSmrg  }
3513602e473dSmrg}
3514602e473dSmrg
3515602e473dSmrgstatic void
3516602e473dSmrgtext_draw (xcb_connection_t *c,
3517602e473dSmrg           xcb_screen_t     *screen,
3518602e473dSmrg           xcb_window_t      window,
3519602e473dSmrg           int16_t           x1,
3520602e473dSmrg           int16_t           y1,
3521602e473dSmrg           const char       *label)
3522602e473dSmrg{
3523602e473dSmrg  xcb_void_cookie_t    cookie_gc;
3524602e473dSmrg  xcb_void_cookie_t    cookie_text;
3525602e473dSmrg  xcb_generic_error_t *error;
3526602e473dSmrg  xcb_gcontext_t       gc;
3527602e473dSmrg  uint8_t              length;
3528602e473dSmrg
3529602e473dSmrg  length = strlen (label);
3530602e473dSmrg
3531602e473dSmrg  gc = gc_font_get(c, screen, window, "7x13");
3532602e473dSmrg
3533602e473dSmrg  cookie_text = xcb_image_text_8_checked (c, length, window, gc,
3534602e473dSmrg                                          x1,
3535602e473dSmrg                                          y1, label);
3536602e473dSmrg  error = xcb_request_check (c, cookie_text);
3537602e473dSmrg  if (error) {
3538602e473dSmrg    fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
3539602e473dSmrg    xcb_disconnect (c);
3540602e473dSmrg    exit (-1);
3541602e473dSmrg  }
3542602e473dSmrg
3543602e473dSmrg  cookie_gc = xcb_free_gc (c, gc);
3544602e473dSmrg  error = xcb_request_check (c, cookie_gc);
3545602e473dSmrg  if (error) {
3546602e473dSmrg    fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
3547602e473dSmrg    xcb_disconnect (c);
3548602e473dSmrg    exit (-1);
3549602e473dSmrg  }
3550602e473dSmrg}
3551602e473dSmrg
3552602e473dSmrgstatic xcb_gc_t
3553602e473dSmrggc_font_get (xcb_connection_t *c,
3554602e473dSmrg             xcb_screen_t     *screen,
3555602e473dSmrg             xcb_window_t      window,
3556602e473dSmrg             const char       *font_name)
3557602e473dSmrg{
3558602e473dSmrg  uint32_t             value_list[3];
3559602e473dSmrg  xcb_void_cookie_t    cookie_font;
3560602e473dSmrg  xcb_void_cookie_t    cookie_gc;
3561602e473dSmrg  xcb_generic_error_t *error;
3562602e473dSmrg  xcb_font_t           font;
3563602e473dSmrg  xcb_gcontext_t       gc;
3564602e473dSmrg  uint32_t             mask;
3565602e473dSmrg
3566602e473dSmrg  font = xcb_generate_id (c);
3567602e473dSmrg  cookie_font = xcb_open_font_checked (c, font,
3568602e473dSmrg                                       strlen (font_name),
3569602e473dSmrg                                       font_name);
3570602e473dSmrg
3571602e473dSmrg  error = xcb_request_check (c, cookie_font);
3572602e473dSmrg  if (error) {
3573602e473dSmrg    fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
3574602e473dSmrg    xcb_disconnect (c);
3575602e473dSmrg    return -1;
3576602e473dSmrg  }
3577602e473dSmrg
3578602e473dSmrg  gc = xcb_generate_id (c);
3579602e473dSmrg  mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
3580602e473dSmrg  value_list[0] = screen->black_pixel;
3581602e473dSmrg  value_list[1] = screen->white_pixel;
3582602e473dSmrg  value_list[2] = font;
3583602e473dSmrg  cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list);
3584602e473dSmrg  error = xcb_request_check (c, cookie_gc);
3585602e473dSmrg  if (error) {
3586602e473dSmrg    fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
3587602e473dSmrg    xcb_disconnect (c);
3588602e473dSmrg    exit (-1);
3589602e473dSmrg  }
3590602e473dSmrg
3591602e473dSmrg  cookie_font = xcb_close_font_checked (c, font);
3592602e473dSmrg  error = xcb_request_check (c, cookie_font);
3593602e473dSmrg  if (error) {
3594602e473dSmrg    fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
3595602e473dSmrg    xcb_disconnect (c);
3596602e473dSmrg    exit (-1);
3597602e473dSmrg  }
3598602e473dSmrg
3599602e473dSmrg  return gc;
3600602e473dSmrg}
3601602e473dSmrg
3602602e473dSmrgstatic void
3603602e473dSmrgcursor_set (xcb_connection_t *c,
3604602e473dSmrg            xcb_screen_t     *screen,
3605602e473dSmrg            xcb_window_t      window,
3606602e473dSmrg            int               cursor_id)
3607602e473dSmrg{
3608602e473dSmrg  uint32_t             values_list[3];
3609602e473dSmrg  xcb_void_cookie_t    cookie_font;
3610602e473dSmrg  xcb_void_cookie_t    cookie_gc;
3611602e473dSmrg  xcb_generic_error_t *error;
3612602e473dSmrg  xcb_font_t           font;
3613602e473dSmrg  xcb_cursor_t         cursor;
3614602e473dSmrg  xcb_gcontext_t       gc;
3615602e473dSmrg  uint32_t             mask;
3616602e473dSmrg  uint32_t             value_list;
3617602e473dSmrg
3618602e473dSmrg  font = xcb_generate_id (c);
3619602e473dSmrg  cookie_font = xcb_open_font_checked (c, font,
3620602e473dSmrg                                       strlen ("cursor"),
3621602e473dSmrg                                       "cursor");
3622602e473dSmrg  error = xcb_request_check (c, cookie_font);
3623602e473dSmrg  if (error) {
3624602e473dSmrg    fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
3625602e473dSmrg    xcb_disconnect (c);
3626602e473dSmrg    exit (-1);
3627602e473dSmrg  }
3628602e473dSmrg
3629602e473dSmrg  cursor = xcb_generate_id (c);
3630602e473dSmrg  xcb_create_glyph_cursor (c, cursor, font, font,
3631602e473dSmrg                           cursor_id, cursor_id + 1,
3632602e473dSmrg                           0, 0, 0,
3633602e473dSmrg                           0, 0, 0);
3634602e473dSmrg
3635602e473dSmrg  gc = xcb_generate_id (c);
3636602e473dSmrg  mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
3637602e473dSmrg  values_list[0] = screen->black_pixel;
3638602e473dSmrg  values_list[1] = screen->white_pixel;
3639602e473dSmrg  values_list[2] = font;
3640602e473dSmrg  cookie_gc = xcb_create_gc_checked (c, gc, window, mask, values_list);
3641602e473dSmrg  error = xcb_request_check (c, cookie_gc);
3642602e473dSmrg  if (error) {
3643602e473dSmrg    fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
3644602e473dSmrg    xcb_disconnect (c);
3645602e473dSmrg    exit (-1);
3646602e473dSmrg  }
3647602e473dSmrg
3648602e473dSmrg  mask = XCB_CW_CURSOR;
3649602e473dSmrg  value_list = cursor;
3650602e473dSmrg  xcb_change_window_attributes (c, window, mask, &amp;value_list);
3651602e473dSmrg
3652602e473dSmrg  xcb_free_cursor (c, cursor);
3653602e473dSmrg
3654602e473dSmrg  cookie_font = xcb_close_font_checked (c, font);
3655602e473dSmrg  error = xcb_request_check (c, cookie_font);
3656602e473dSmrg  if (error) {
3657602e473dSmrg    fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
3658602e473dSmrg    xcb_disconnect (c);
3659602e473dSmrg    exit (-1);
3660602e473dSmrg  }
3661602e473dSmrg}
3662602e473dSmrg
3663602e473dSmrgint main ()
3664602e473dSmrg{
3665602e473dSmrg  xcb_screen_iterator_t screen_iter;
3666602e473dSmrg  xcb_connection_t     *c;
3667602e473dSmrg  const xcb_setup_t    *setup;
3668602e473dSmrg  xcb_screen_t         *screen;
3669602e473dSmrg  xcb_generic_event_t  *e;
3670602e473dSmrg  xcb_generic_error_t  *error;
3671602e473dSmrg  xcb_void_cookie_t     cookie_window;
3672602e473dSmrg  xcb_void_cookie_t     cookie_map;
3673602e473dSmrg  xcb_window_t          window;
3674602e473dSmrg  uint32_t              mask;
3675602e473dSmrg  uint32_t              values[2];
3676602e473dSmrg  int                   screen_number;
3677602e473dSmrg  uint8_t               is_hand = 0;
3678602e473dSmrg
3679602e473dSmrg  /* getting the connection */
3680602e473dSmrg  c = xcb_connect (NULL, &amp;screen_number);
3681602e473dSmrg  if (!c) {
3682602e473dSmrg    fprintf (stderr, "ERROR: can't connect to an X server\n");
3683602e473dSmrg    return -1;
3684602e473dSmrg  }
3685602e473dSmrg
3686602e473dSmrg  /* getting the current screen */
3687602e473dSmrg  setup = xcb_get_setup (c);
3688602e473dSmrg
3689602e473dSmrg  screen = NULL;
3690602e473dSmrg  screen_iter = xcb_setup_roots_iterator (setup);
3691602e473dSmrg  for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&amp;screen_iter))
3692602e473dSmrg    if (screen_number == 0)
3693602e473dSmrg      {
3694602e473dSmrg        screen = screen_iter.data;
3695602e473dSmrg        break;
3696602e473dSmrg      }
3697602e473dSmrg  if (!screen) {
3698602e473dSmrg    fprintf (stderr, "ERROR: can't get the current screen\n");
3699602e473dSmrg    xcb_disconnect (c);
3700602e473dSmrg    return -1;
3701602e473dSmrg  }
3702602e473dSmrg
3703602e473dSmrg  /* creating the window */
3704602e473dSmrg  window = xcb_generate_id (c);
3705602e473dSmrg  mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
3706602e473dSmrg  values[0] = screen->white_pixel;
3707602e473dSmrg  values[1] =
3708602e473dSmrg    XCB_EVENT_MASK_KEY_RELEASE |
3709602e473dSmrg    XCB_EVENT_MASK_BUTTON_PRESS |
3710602e473dSmrg    XCB_EVENT_MASK_EXPOSURE |
3711602e473dSmrg    XCB_EVENT_MASK_POINTER_MOTION;
3712602e473dSmrg  cookie_window = xcb_create_window_checked (c,
3713602e473dSmrg                                             screen->root_depth,
3714602e473dSmrg                                             window, screen->root,
3715602e473dSmrg                                             20, 200, WIDTH, HEIGHT,
3716602e473dSmrg                                             0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
3717602e473dSmrg                                             screen->root_visual,
3718602e473dSmrg                                             mask, values);
3719602e473dSmrg  cookie_map = xcb_map_window_checked (c, window);
3720602e473dSmrg
3721602e473dSmrg  /* error managing */
3722602e473dSmrg  error = xcb_request_check (c, cookie_window);
3723602e473dSmrg  if (error) {
3724602e473dSmrg    fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code);
3725602e473dSmrg    xcb_disconnect (c);
3726602e473dSmrg    return -1;
3727602e473dSmrg  }
3728602e473dSmrg  error = xcb_request_check (c, cookie_map);
3729602e473dSmrg  if (error) {
3730602e473dSmrg    fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code);
3731602e473dSmrg    xcb_disconnect (c);
3732602e473dSmrg    return -1;
3733602e473dSmrg  }
3734602e473dSmrg
3735602e473dSmrg  cursor_set (c, screen, window, 68);
3736602e473dSmrg
3737602e473dSmrg  xcb_flush(c);
3738602e473dSmrg
3739602e473dSmrg  while (1) {
3740602e473dSmrg    e = xcb_poll_for_event(c);
3741602e473dSmrg    if (e) {
3742602e473dSmrg      switch (e->response_type &amp; ~0x80) {
3743602e473dSmrg      case XCB_EXPOSE: {
3744602e473dSmrg        char *text;
3745602e473dSmrg
3746602e473dSmrg        text = "click here to change cursor";
3747602e473dSmrg        button_draw (c, screen, window,
3748602e473dSmrg                     (WIDTH - 7 * strlen(text)) / 2,
3749602e473dSmrg                     (HEIGHT - 16) / 2, text);
3750602e473dSmrg
3751602e473dSmrg        text = "Press ESC key to exit...";
3752602e473dSmrg        text_draw (c, screen, window, 10, HEIGHT - 10, text);
3753602e473dSmrg        break;
3754602e473dSmrg      }
3755602e473dSmrg      case XCB_BUTTON_PRESS: {
3756602e473dSmrg        xcb_button_press_event_t *ev;
3757602e473dSmrg        int                       length;
3758602e473dSmrg
3759602e473dSmrg        ev = (xcb_button_press_event_t *)e;
3760602e473dSmrg        length = strlen ("click here to change cursor");
3761602e473dSmrg
3762602e473dSmrg        if ((ev->event_x &gt;= (WIDTH - 7 * length) / 2) &amp;&amp;
3763602e473dSmrg            (ev->event_x &lt;= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) &amp;&amp;
3764602e473dSmrg            (ev->event_y &gt;= (HEIGHT - 16) / 2 - 19) &amp;&amp;
3765602e473dSmrg            (ev->event_y &lt;= ((HEIGHT - 16) / 2)))
3766602e473dSmrg          is_hand = 1 - is_hand;
3767602e473dSmrg
3768602e473dSmrg        is_hand ? cursor_set (c, screen, window, 58) : cursor_set (c, screen, window, 68);
3769602e473dSmrg      }
3770602e473dSmrg      case XCB_KEY_RELEASE: {
3771602e473dSmrg        xcb_key_release_event_t *ev;
3772602e473dSmrg
3773602e473dSmrg        ev = (xcb_key_release_event_t *)e;
3774602e473dSmrg
3775602e473dSmrg        switch (ev->detail) {
3776602e473dSmrg          /* ESC */
3777602e473dSmrg        case 9:
3778602e473dSmrg          free (e);
3779602e473dSmrg          xcb_disconnect (c);
3780602e473dSmrg          return 0;
3781602e473dSmrg        }
3782602e473dSmrg      }
3783602e473dSmrg      }
3784602e473dSmrg      free (e);
3785602e473dSmrg    }
3786602e473dSmrg  }
3787602e473dSmrg
3788602e473dSmrg  return 0;
3789602e473dSmrg}
3790602e473dSmrg</pre>
3791602e473dSmrg      </ol>
3792602e473dSmrg      <li class="title"><a name="translation">Translation of basic Xlib functions and macros</a>
3793602e473dSmrg      <p>
3794602e473dSmrg      The problem when you want to port an Xlib program to XCB is that
3795602e473dSmrg      you don't know if the Xlib function that you want to "translate"
3796602e473dSmrg      is a X Window one or an Xlib macro. In that section, we describe
3797602e473dSmrg      a way to translate the usual functions or macros that Xlib
3798602e473dSmrg      provides. It's usually just a member of a structure.
3799602e473dSmrg      </p>
3800602e473dSmrg      <ol>
3801602e473dSmrg        <li class="subtitle"><a name="displaystructure">Members of the Display structure</a>
3802602e473dSmrg        <p>
3803602e473dSmrg        In this section, we look at how to translate the macros that
3804602e473dSmrg        return some members of the <span class="code">Display</span>
3805602e473dSmrg        structure. They are obtained by using a function that requires a
3806602e473dSmrg        <span class="code">xcb_connection_t *</span> or a member of the
3807602e473dSmrg        <span class="code">xcb_setup_t</span> structure
3808602e473dSmrg        (via the function <span class="code">xcb_get_setup</span>), or
3809602e473dSmrg        a function that requires that structure.
3810602e473dSmrg        </p>
3811602e473dSmrg        <ol>
3812602e473dSmrg          <li class="subtitle"><a name="ConnectionNumber">ConnectionNumber</a>
3813602e473dSmrg          <p>
3814602e473dSmrg          This number is the file descriptor that connects the client
3815602e473dSmrg          to the server. You just have to use that function:
3816602e473dSmrg          </p>
3817602e473dSmrg          <pre class="code">
3818602e473dSmrgint xcb_get_file_descriptor (xcb_connection_t *c);
3819602e473dSmrg</pre>
3820602e473dSmrg          <li class="subtitle"><a name="DefaultScreen"></a>DefaultScreen
3821602e473dSmrg          <p>
3822602e473dSmrg          That number is not stored by XCB. It is returned in the
3823602e473dSmrg          second parameter of the function <span class="code"><a href="#openconn">xcb_connect</a></span>.
3824602e473dSmrg          Hence, you have to store it yourself if you want to use
3825602e473dSmrg          it. Then, to get the <span class="code">xcb_screen_t</span>
3826602e473dSmrg          structure, you have to iterate on the screens.
3827602e473dSmrg          The equivalent function of the Xlib's
3828602e473dSmrg          <span class="code">ScreenOfDisplay</span> function can be
3829602e473dSmrg          found <a href="#ScreenOfDisplay">below</a>. This is also provided in the
3830602e473dSmrg          xcb_aux_t library as <span class="code">xcb_aux_get_screen()</span>. OK, here is the
3831602e473dSmrg          small piece of code to get that number:
3832602e473dSmrg          </p>
3833602e473dSmrg          <pre class="code">
3834602e473dSmrgxcb_connection_t *c;
3835602e473dSmrgint               screen_default_nbr;
3836602e473dSmrg
3837602e473dSmrg/* you pass the name of the display you want to xcb_connect_t */
3838602e473dSmrg
3839602e473dSmrgc = xcb_connect (display_name, &amp;screen_default_nbr);
3840602e473dSmrg
3841602e473dSmrg/* screen_default_nbr contains now the number of the default screen */
3842602e473dSmrg</pre>
3843602e473dSmrg          <li class="subtitle"><a name="QLength"></a>QLength
3844602e473dSmrg          <p>
3845602e473dSmrg          Not documented yet.
3846602e473dSmrg          </p>
3847602e473dSmrg          <p>
3848602e473dSmrg          However, this points out a basic difference in philosophy between
3849602e473dSmrg          Xlib and XCB.  Xlib has several functions for filtering and
3850602e473dSmrg          manipulating the incoming and outgoing X message queues.  XCB
3851602e473dSmrg          wishes to hide this as much as possible from the user, which
3852602e473dSmrg          allows for more freedom in implementation strategies.
3853602e473dSmrg          </p>
3854602e473dSmrg          <li class="subtitle"><a name="ScreenCount"></a>ScreenCount
3855602e473dSmrg          <p>
3856602e473dSmrg          You get the count of screens with the functions
3857602e473dSmrg          <span class="code">xcb_get_setup</span>
3858602e473dSmrg          and
3859602e473dSmrg          <span class="code">xcb_setup_roots_iterator</span>
3860602e473dSmrg          (if you need to iterate):
3861602e473dSmrg          </p>
3862602e473dSmrg          <pre class="code">
3863602e473dSmrgxcb_connection_t *c;
3864602e473dSmrgint               screen_count;
3865602e473dSmrg
3866602e473dSmrg/* you init the connection */
3867602e473dSmrg
3868602e473dSmrgscreen_count = xcb_setup_roots_iterator (xcb_get_setup (c)).rem;
3869602e473dSmrg
3870602e473dSmrg/* screen_count contains now the count of screens */
3871602e473dSmrg</pre>
3872602e473dSmrg          <p>
3873602e473dSmrg          If you don't want to iterate over the screens, a better way
3874602e473dSmrg          to get that number is to use
3875602e473dSmrg          <span class="code">xcb_setup_roots_length_t</span>:
3876602e473dSmrg          </p>
3877602e473dSmrg          <pre class="code">
3878602e473dSmrgxcb_connection_t *c;
3879602e473dSmrgint               screen_count;
3880602e473dSmrg
3881602e473dSmrg/* you init the connection */
3882602e473dSmrg
3883602e473dSmrgscreen_count = xcb_setup_roots_length (xcb_get_setup (c));
3884602e473dSmrg
3885602e473dSmrg/* screen_count contains now the count of screens */
3886602e473dSmrg</pre>
3887602e473dSmrg          <li class="subtitle"><a name="ServerVendor"></a>ServerVendor
3888602e473dSmrg          <p>
3889602e473dSmrg          You get the name of the vendor of the server hardware with
3890602e473dSmrg          the functions <span class="code">xcb_get_setup</span>
3891602e473dSmrg          and
3892602e473dSmrg          <span
3893602e473dSmrg          class="code">xcb_setup_vendor</span>. Beware
3894602e473dSmrg          that, unlike Xlib, the string returned by XCB is not
3895602e473dSmrg          necessarily null-terminaled:
3896602e473dSmrg          </p>
3897602e473dSmrg          <pre class="code">
3898602e473dSmrgxcb_connection_t *c;
3899602e473dSmrgchar             *vendor = NULL;
3900602e473dSmrgint               length;
3901602e473dSmrg
3902602e473dSmrg/* you init the connection */
3903602e473dSmrglength = xcb_setup_vendor_length (xcb_get_setup (c));
3904602e473dSmrgvendor = (char *)malloc (length + 1);
3905602e473dSmrgif (vendor)
3906602e473dSmrgmemcpy (vendor, xcb_setup_vendor (xcb_get_setup (c)), length);
3907602e473dSmrgvendor[length] = '\0';
3908602e473dSmrg
3909602e473dSmrg/* vendor contains now the name of the vendor. Must be freed when not used anymore */
3910602e473dSmrg</pre>
3911602e473dSmrg          <li class="subtitle"><a name="ProtocolVersion"></a>ProtocolVersion
3912602e473dSmrg          <p>
3913602e473dSmrg          You get the major version of the protocol in the
3914602e473dSmrg          <span class="code">xcb_setup_t</span>
3915602e473dSmrg          structure, with the function <span class="code">xcb_get_setup</span>:
3916602e473dSmrg          </p>
3917602e473dSmrg          <pre class="code">
3918602e473dSmrgxcb_connection_t *c;
3919602e473dSmrguint16_t          protocol_major_version;
3920602e473dSmrg
3921602e473dSmrg/* you init the connection */
3922602e473dSmrg
3923602e473dSmrgprotocol_major_version = xcb_get_setup (c)-&gt;protocol_major_version;
3924602e473dSmrg
3925602e473dSmrg/* protocol_major_version contains now the major version of the protocol */
3926602e473dSmrg</pre>
3927602e473dSmrg          <li class="subtitle"><a name="ProtocolRevision"></a>ProtocolRevision
3928602e473dSmrg          <p>
3929602e473dSmrg          You get the minor version of the protocol in the
3930602e473dSmrg          <span class="code">xcb_setup_t</span>
3931602e473dSmrg          structure, with the function <span class="code">xcb_get_setup</span>:
3932602e473dSmrg          </p>
3933602e473dSmrg          <pre class="code">
3934602e473dSmrgxcb_connection_t *c;
3935602e473dSmrguint16_t          protocol_minor_version;
3936602e473dSmrg
3937602e473dSmrg/* you init the connection */
3938602e473dSmrg
3939602e473dSmrgprotocol_minor_version = xcb_get_setup (c)-&gt;protocol_minor_version;
3940602e473dSmrg
3941602e473dSmrg/* protocol_minor_version contains now the minor version of the protocol */
3942602e473dSmrg</pre>
3943602e473dSmrg          <li class="subtitle"><a name="VendorRelease"></a>VendorRelease
3944602e473dSmrg          <p>
3945602e473dSmrg          You get the number of the release of the server hardware in the
3946602e473dSmrg          <span class="code">xcb_setup_t</span>
3947602e473dSmrg          structure, with the function <span class="code">xcb_get_setup</span>:
3948602e473dSmrg          </p>
3949602e473dSmrg          <pre class="code">
3950602e473dSmrgxcb_connection_t *c;
3951602e473dSmrguint32_t          release_number;
3952602e473dSmrg
3953602e473dSmrg/* you init the connection */
3954602e473dSmrg
3955602e473dSmrgrelease_number = xcb_get_setup (c)-&gt;release_number;
3956602e473dSmrg
3957602e473dSmrg/* release_number contains now the number of the release of the server hardware */
3958602e473dSmrg</pre>
3959602e473dSmrg          <li class="subtitle"><a name="DisplayString"></a>DisplayString
3960602e473dSmrg          <p>
3961602e473dSmrg          The name of the display is not stored in XCB. You have to
3962602e473dSmrg          store it by yourself.
3963602e473dSmrg          </p>
3964602e473dSmrg          <li class="subtitle"><a name="BitmapUnit"></a>BitmapUnit
3965602e473dSmrg          <p>
3966602e473dSmrg          You get the bitmap scanline unit in the
3967602e473dSmrg          <span class="code">xcb_setup_t</span>
3968602e473dSmrg          structure, with the function <span class="code">xcb_get_setup</span>:
3969602e473dSmrg          </p>
3970602e473dSmrg          <pre class="code">
3971602e473dSmrgxcb_connection_t *c;
3972602e473dSmrguint8_t           bitmap_format_scanline_unit;
3973602e473dSmrg
3974602e473dSmrg/* you init the connection */
3975602e473dSmrg
3976602e473dSmrgbitmap_format_scanline_unit = xcb_get_setup (c)-&gt;bitmap_format_scanline_unit;
3977602e473dSmrg
3978602e473dSmrg/* bitmap_format_scanline_unit contains now the bitmap scanline unit */
3979602e473dSmrg</pre>
3980602e473dSmrg          <li class="subtitle"><a name="BitmapBitOrder"></a>BitmapBitOrder
3981602e473dSmrg          <p>
3982602e473dSmrg          You get the bitmap bit order in the
3983602e473dSmrg          <span class="code">xcb_setup_t</span>
3984602e473dSmrg          structure, with the function <span class="code">xcb_get_setup</span>:
3985602e473dSmrg          </p>
3986602e473dSmrg          <pre class="code">
3987602e473dSmrgxcb_connection_t *c;
3988602e473dSmrguint8_t           bitmap_format_bit_order;
3989602e473dSmrg
3990602e473dSmrg/* you init the connection */
3991602e473dSmrg
3992602e473dSmrgbitmap_format_bit_order = xcb_get_setup (c)-&gt;bitmap_format_bit_order;
3993602e473dSmrg
3994602e473dSmrg/* bitmap_format_bit_order contains now the bitmap bit order */
3995602e473dSmrg</pre>
3996602e473dSmrg          <li class="subtitle"><a name="BitmapPad"></a>BitmapPad
3997602e473dSmrg          <p>
3998602e473dSmrg          You get the bitmap scanline pad in the
3999602e473dSmrg          <span class="code">xcb_setup_t</span>
4000602e473dSmrg          structure, with the function <span class="code">xcb_get_setup</span>:
4001602e473dSmrg          </p>
4002602e473dSmrg          <pre class="code">
4003602e473dSmrgxcb_connection_t *c;
4004602e473dSmrguint8_t           bitmap_format_scanline_pad;
4005602e473dSmrg
4006602e473dSmrg/* you init the connection */
4007602e473dSmrg
4008602e473dSmrgbitmap_format_scanline_pad = xcb_get_setup (c)-&gt;bitmap_format_scanline_pad;
4009602e473dSmrg
4010602e473dSmrg/* bitmap_format_scanline_pad contains now the bitmap scanline pad */
4011602e473dSmrg</pre>
4012602e473dSmrg          <li class="subtitle"><a name="ImageByteOrder"></a>ImageByteOrder
4013602e473dSmrg          <p>
4014602e473dSmrg          You get the image byte order in the
4015602e473dSmrg          <span class="code">xcb_setup_t</span>
4016602e473dSmrg          structure, with the function <span class="code">xcb_get_setup</span>:
4017602e473dSmrg          </p>
4018602e473dSmrg          <pre class="code">
4019602e473dSmrgxcb_connection_t *c;
4020602e473dSmrguint8_t           image_byte_order;
4021602e473dSmrg
4022602e473dSmrg/* you init the connection */
4023602e473dSmrg
4024602e473dSmrgimage_byte_order = xcb_get_setup (c)-&gt;image_byte_order;
4025602e473dSmrg
4026602e473dSmrg/* image_byte_order contains now the image byte order */
4027602e473dSmrg</pre>
4028602e473dSmrg        </ol>
4029602e473dSmrg      <li class="subtitle"><a name="screenofdisplay">ScreenOfDisplay related functions</a>
4030602e473dSmrg      <p>
4031602e473dSmrg      in Xlib, <span class="code">ScreenOfDisplay</span> returns a
4032602e473dSmrg      <span class="code">Screen</span> structure that contains
4033602e473dSmrg      several characteristics of your screen. XCB has a similar
4034602e473dSmrg      structure (<span class="code">xcb_screen_t</span>),
4035602e473dSmrg      but the way to obtain it is a bit different. With
4036602e473dSmrg      Xlib, you just provide the number of the screen and you grab it
4037602e473dSmrg      from an array. With XCB, you iterate over all the screens to
4038602e473dSmrg      obtain the one you want. The complexity of this operation is
4039602e473dSmrg      O(n). So the best is to store this structure if you use
4040602e473dSmrg      it often. See <a href="#ScreenOfDisplay">screen_of_display</a> just below.
4041602e473dSmrg      </p>
4042602e473dSmrg      <p>
4043602e473dSmrg      Xlib provides generally two functions to obtain the characteristics
4044602e473dSmrg      related to the screen. One with the display and the number of
4045602e473dSmrg      the screen, which calls <span class="code">ScreenOfDisplay</span>,
4046602e473dSmrg      and the other that uses the <span class="code">Screen</span> structure.
4047602e473dSmrg      This might be a bit confusing. As mentioned above, with XCB, it
4048602e473dSmrg      is better to store the <span class="code">xcb_screen_t</span>
4049602e473dSmrg      structure. Then, you have to read the members of this
4050602e473dSmrg      structure. That's why the Xlib functions are put by pairs (or
4051602e473dSmrg      more) as, with XCB, you will use the same code.
4052602e473dSmrg      </p>
4053602e473dSmrg        <ol>
4054602e473dSmrg          <li class="subtitle"><a name="ScreenOfDisplay">ScreenOfDisplay</a>
4055602e473dSmrg          <p>
4056602e473dSmrg          This function returns the Xlib <span class="code">Screen</span>
4057602e473dSmrg          structure. With XCB, you iterate over all the screens and
4058602e473dSmrg          once you get the one you want, you return it:
4059602e473dSmrg          </p>
4060602e473dSmrg          <pre class="code"><a name="ScreenOfDisplay"></a>
4061602e473dSmrgxcb_screen_t *screen_of_display (xcb_connection_t *c,
4062602e473dSmrg                                 int               screen)
4063602e473dSmrg{
4064602e473dSmrg  xcb_screen_iterator_t iter;
4065602e473dSmrg
4066602e473dSmrg  iter = xcb_setup_roots_iterator (xcb_get_setup (c));
4067602e473dSmrg  for (; iter.rem; --screen, xcb_screen_next (&amp;iter))
4068602e473dSmrg    if (screen == 0)
4069602e473dSmrg      return iter.data;
4070602e473dSmrg
4071602e473dSmrg  return NULL;
4072602e473dSmrg}
4073602e473dSmrg</pre>
4074602e473dSmrg          <p>
4075602e473dSmrg          As mentioned above, you might want to store the value
4076602e473dSmrg          returned by this function.
4077602e473dSmrg          </p>
4078602e473dSmrg          <p>
4079602e473dSmrg          All the functions below will use the result of that
4080602e473dSmrg          function, as they just grab a specific member of the
4081602e473dSmrg          <span class="code">xcb_screen_t</span> structure.
4082602e473dSmrg          </p>
4083602e473dSmrg          <li class="subtitle"><a name="DefaultScreenOfDisplay"></a>DefaultScreenOfDisplay
4084602e473dSmrg          <p>
4085602e473dSmrg          It is the default screen that you obtain when you connect to
4086602e473dSmrg          the X server. It suffices to call the <a href="#ScreenOfDisplay">screen_of_display</a>
4087602e473dSmrg          function above with the connection and the number of the
4088602e473dSmrg          default screen.
4089602e473dSmrg          </p>
4090602e473dSmrg          <pre class="code">
4091602e473dSmrgxcb_connection_t *c;
4092602e473dSmrgint               screen_default_nbr;
4093602e473dSmrgxcb_screen_t     *default_screen;  /* the returned default screen */
4094602e473dSmrg
4095602e473dSmrg/* you pass the name of the display you want to xcb_connect_t */
4096602e473dSmrg
4097602e473dSmrgc = xcb_connect (display_name, &amp;screen_default_nbr);
4098602e473dSmrgdefault_screen = screen_of_display (c, screen_default_nbr);
4099602e473dSmrg
4100602e473dSmrg/* default_screen contains now the default root window, or a NULL window if no screen is found */
4101602e473dSmrg</pre>
4102602e473dSmrg          <li class="subtitle"><a name="RootWindow">RootWindow / RootWindowOfScreen</a>
4103602e473dSmrg          <br>
4104602e473dSmrg          <pre class="code">
4105602e473dSmrgxcb_connection_t *c;
4106602e473dSmrgxcb_screen_t     *screen;
4107602e473dSmrgint               screen_nbr;
4108602e473dSmrgxcb_window_t      root_window = { 0 };  /* the returned window */
4109602e473dSmrg
4110602e473dSmrg/* you init the connection and screen_nbr */
4111602e473dSmrg
4112602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4113602e473dSmrgif (screen)
4114602e473dSmrg  root_window = screen-&gt;root;
4115602e473dSmrg
4116602e473dSmrg/* root_window contains now the root window, or a NULL window if no screen is found */
4117602e473dSmrg</pre>
4118602e473dSmrg          <li class="subtitle"><a name="DefaultRootWindow">DefaultRootWindow</a>
4119602e473dSmrg          <p>
4120602e473dSmrg          It is the root window of the default screen. So, you call
4121602e473dSmrg          <a name="ScreenOfDisplay">ScreenOfDisplay</a> with the
4122602e473dSmrg          default screen number and you get the
4123602e473dSmrg          <a href="#RootWindow">root window</a> as above:
4124602e473dSmrg          </p>
4125602e473dSmrg          <pre class="code">
4126602e473dSmrgxcb_connection_t *c;
4127602e473dSmrgxcb_screen_t     *screen;
4128602e473dSmrgint               screen_default_nbr;
4129602e473dSmrgxcb_window_t      root_window = { 0 };  /* the returned root window */
4130602e473dSmrg
4131602e473dSmrg/* you pass the name of the display you want to xcb_connect_t */
4132602e473dSmrg
4133602e473dSmrgc = xcb_connect (display_name, &amp;screen_default_nbr);
4134602e473dSmrgscreen = screen_of_display (c, screen_default_nbr);
4135602e473dSmrgif (screen)
4136602e473dSmrg  root_window = screen-&gt;root;
4137602e473dSmrg
4138602e473dSmrg/* root_window contains now the default root window, or a NULL window if no screen is found */
4139602e473dSmrg</pre>
4140602e473dSmrg          <li class="subtitle"><a name="DefaultVisual">DefaultVisual / DefaultVisualOfScreen</a>
4141602e473dSmrg          <p>
4142602e473dSmrg          While a Visual is, in Xlib, a structure, in XCB, there are
4143602e473dSmrg          two types: <span class="code">xcb_visualid_t</span>, which is
4144602e473dSmrg          the Id of the visual, and <span class="code">xcb_visualtype_t</span>,
4145602e473dSmrg          which corresponds to the Xlib Visual. To get the Id of the
4146602e473dSmrg          visual of a screen, just get the
4147602e473dSmrg           <span class="code">root_visual</span>
4148602e473dSmrg           member of a <span class="code">xcb_screen_t</span>:
4149602e473dSmrg          </p>
4150602e473dSmrg          <pre class="code">
4151602e473dSmrgxcb_connection_t *c;
4152602e473dSmrgxcb_screen_t     *screen;
4153602e473dSmrgint               screen_nbr;
4154602e473dSmrgxcb_visualid_t    root_visual = { 0 };    /* the returned visual Id */
4155602e473dSmrg
4156602e473dSmrg/* you init the connection and screen_nbr */
4157602e473dSmrg
4158602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4159602e473dSmrgif (screen)
4160602e473dSmrg  root_visual = screen-&gt;root_visual;
4161602e473dSmrg
4162602e473dSmrg/* root_visual contains now the value of the Id of the visual, or a NULL visual if no screen is found */
4163602e473dSmrg</pre>
4164602e473dSmrg          <p>
4165602e473dSmrg          To get the <span class="code">xcb_visualtype_t</span>
4166602e473dSmrg          structure, it's a bit less easy. You have to get the
4167602e473dSmrg          <span class="code">xcb_screen_t</span> structure that you want,
4168602e473dSmrg          get its <span class="code">root_visual</span> member,
4169602e473dSmrg          then iterate over the <span class="code">xcb_depth_t</span>s
4170602e473dSmrg          and the <span class="code">xcb_visualtype_t</span>s, and compare
4171602e473dSmrg          the <span class="code">xcb_visualid_t</span> of these <span class="code">xcb_visualtype_t</span>s:
4172602e473dSmrg          with <span class="code">root_visual</span>:
4173602e473dSmrg          </p>
4174602e473dSmrg          <pre class="code">
4175602e473dSmrgxcb_connection_t *c;
4176602e473dSmrgxcb_screen_t     *screen;
4177602e473dSmrgint               screen_nbr;
4178602e473dSmrgxcb_visualid_t    root_visual = { 0 };
4179602e473dSmrgxcb_visualtype_t  *visual_type = NULL;    /* the returned visual type */
4180602e473dSmrg
4181602e473dSmrg/* you init the connection and screen_nbr */
4182602e473dSmrg
4183602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4184602e473dSmrgif (screen) {
4185602e473dSmrg  xcb_depth_iterator_t depth_iter;
4186602e473dSmrg
4187602e473dSmrg  depth_iter = xcb_screen_allowed_depths_iterator (screen);
4188602e473dSmrg  for (; depth_iter.rem; xcb_depth_next (&amp;depth_iter)) {
4189602e473dSmrg    xcb_visualtype_iterator_t visual_iter;
4190602e473dSmrg
4191602e473dSmrg    visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
4192602e473dSmrg    for (; visual_iter.rem; xcb_visualtype_next (&amp;visual_iter)) {
4193602e473dSmrg      if (screen-&gt;root_visual == visual_iter.data-&gt;visual_id) {
4194602e473dSmrg        visual_type = visual_iter.data;
4195602e473dSmrg        break;
4196602e473dSmrg      }
4197602e473dSmrg    }
4198602e473dSmrg  }
4199602e473dSmrg}
4200602e473dSmrg
4201602e473dSmrg/* visual_type contains now the visual structure, or a NULL visual structure if no screen is found */
4202602e473dSmrg</pre>
4203602e473dSmrg          <li class="subtitle"><a name="DefaultGC">DefaultGC / DefaultGCOfScreen</a>
4204602e473dSmrg          <p>
4205602e473dSmrg          This default Graphic Context is just a newly created Graphic
4206602e473dSmrg          Context, associated to the root window of a
4207602e473dSmrg          <span class="code">xcb_screen_t</span>,
4208602e473dSmrg          using the black white pixels of that screen:
4209602e473dSmrg          </p>
4210602e473dSmrg          <pre class="code">
4211602e473dSmrgxcb_connection_t *c;
4212602e473dSmrgxcb_screen_t     *screen;
4213602e473dSmrgint               screen_nbr;
4214602e473dSmrgxcb_gcontext_t    gc = { 0 };    /* the returned default graphic context */
4215602e473dSmrg
4216602e473dSmrg/* you init the connection and screen_nbr */
4217602e473dSmrg
4218602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4219602e473dSmrgif (screen) {
4220602e473dSmrg  xcb_drawable_t draw;
4221602e473dSmrg  uint32_t       mask;
4222602e473dSmrg  uint32_t       values[2];
4223602e473dSmrg
4224602e473dSmrg  gc = xcb_generate_id (c);
4225602e473dSmrg  draw = screen-&gt;root;
4226602e473dSmrg  mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
4227602e473dSmrg  values[0] = screen-&gt;black_pixel;
4228602e473dSmrg  values[1] = screen-&gt;white_pixel;
4229602e473dSmrg  xcb_create_gc (c, gc, draw, mask, values);
4230602e473dSmrg}
4231602e473dSmrg
4232602e473dSmrg/* gc contains now the default graphic context */
4233602e473dSmrg</pre>
4234602e473dSmrg          <li class="subtitle"><a name="BlackPixel">BlackPixel / BlackPixelOfScreen</a>
4235602e473dSmrg          <p>
4236602e473dSmrg          It is the Id of the black pixel, which is in the structure
4237602e473dSmrg          of an <span class="code">xcb_screen_t</span>.
4238602e473dSmrg          </p>
4239602e473dSmrg          <pre class="code">
4240602e473dSmrgxcb_connection_t *c;
4241602e473dSmrgxcb_screen_t     *screen;
4242602e473dSmrgint               screen_nbr;
4243602e473dSmrguint32_t          black_pixel = 0;    /* the returned black pixel */
4244602e473dSmrg
4245602e473dSmrg/* you init the connection and screen_nbr */
4246602e473dSmrg
4247602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4248602e473dSmrgif (screen)
4249602e473dSmrg  black_pixel = screen-&gt;black_pixel;
4250602e473dSmrg
4251602e473dSmrg/* black_pixel contains now the value of the black pixel, or 0 if no screen is found */
4252602e473dSmrg</pre>
4253602e473dSmrg          <li class="subtitle"><a name="WhitePixel">WhitePixel / WhitePixelOfScreen</a>
4254602e473dSmrg          <p>
4255602e473dSmrg          It is the Id of the white pixel, which is in the structure
4256602e473dSmrg          of an <span class="code">xcb_screen_t</span>.
4257602e473dSmrg          </p>
4258602e473dSmrg          <pre class="code">
4259602e473dSmrgxcb_connection_t *c;
4260602e473dSmrgxcb_screen_t     *screen;
4261602e473dSmrgint               screen_nbr;
4262602e473dSmrguint32_t          white_pixel = 0;    /* the returned white pixel */
4263602e473dSmrg
4264602e473dSmrg/* you init the connection and screen_nbr */
4265602e473dSmrg
4266602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4267602e473dSmrgif (screen)
4268602e473dSmrg  white_pixel = screen-&gt;white_pixel;
4269602e473dSmrg
4270602e473dSmrg/* white_pixel contains now the value of the white pixel, or 0 if no screen is found */
4271602e473dSmrg</pre>
4272602e473dSmrg          <li class="subtitle"><a name="DisplayWidth">DisplayWidth / WidthOfScreen</a>
4273602e473dSmrg          <p>
4274602e473dSmrg          It is the width in pixels of the screen that you want, and
4275602e473dSmrg          which is in the structure of the corresponding
4276602e473dSmrg          <span class="code">xcb_screen_t</span>.
4277602e473dSmrg          </p>
4278602e473dSmrg          <pre class="code">
4279602e473dSmrgxcb_connection_t *c;
4280602e473dSmrgxcb_screen_t     *screen;
4281602e473dSmrgint               screen_nbr;
4282602e473dSmrguint32_t          width_in_pixels = 0;    /* the returned width in pixels */
4283602e473dSmrg
4284602e473dSmrg/* you init the connection and screen_nbr */
4285602e473dSmrg
4286602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4287602e473dSmrgif (screen)
4288602e473dSmrg  width_in_pixels = screen-&gt;width_in_pixels;
4289602e473dSmrg
4290602e473dSmrg/* width_in_pixels contains now the width in pixels, or 0 if no screen is found */
4291602e473dSmrg</pre>
4292602e473dSmrg          <li class="subtitle"><a name="DisplayHeight">DisplayHeight / HeightOfScreen</a>
4293602e473dSmrg          <p>
4294602e473dSmrg          It is the height in pixels of the screen that you want, and
4295602e473dSmrg          which is in the structure of the corresponding
4296602e473dSmrg          <span class="code">xcb_screen_t</span>.
4297602e473dSmrg          </p>
4298602e473dSmrg          <pre class="code">
4299602e473dSmrgxcb_connection_t *c;
4300602e473dSmrgxcb_screen_t     *screen;
4301602e473dSmrgint               screen_nbr;
4302602e473dSmrguint32_t          height_in_pixels = 0;    /* the returned height in pixels */
4303602e473dSmrg
4304602e473dSmrg/* you init the connection and screen_nbr */
4305602e473dSmrg
4306602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4307602e473dSmrgif (screen)
4308602e473dSmrg  height_in_pixels = screen-&gt;height_in_pixels;
4309602e473dSmrg
4310602e473dSmrg/* height_in_pixels contains now the height in pixels, or 0 if no screen is found */
4311602e473dSmrg</pre>
4312602e473dSmrg          <li class="subtitle"><a name="DisplayWidthMM">DisplayWidthMM / WidthMMOfScreen</a>
4313602e473dSmrg          <p>
4314602e473dSmrg          It is the width in millimeters of the screen that you want, and
4315602e473dSmrg          which is in the structure of the corresponding
4316602e473dSmrg          <span class="code">xcb_screen_t</span>.
4317602e473dSmrg          </p>
4318602e473dSmrg          <pre class="code">
4319602e473dSmrgxcb_connection_t *c;
4320602e473dSmrgxcb_screen_t     *screen;
4321602e473dSmrgint               screen_nbr;
4322602e473dSmrguint32_t          width_in_millimeters = 0;    /* the returned width in millimeters */
4323602e473dSmrg
4324602e473dSmrg/* you init the connection and screen_nbr */
4325602e473dSmrg
4326602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4327602e473dSmrgif (screen)
4328602e473dSmrg  width_in_millimeters = screen-&gt;width_in_millimeters;
4329602e473dSmrg
4330602e473dSmrg/* width_in_millimeters contains now the width in millimeters, or 0 if no screen is found */
4331602e473dSmrg</pre>
4332602e473dSmrg          <li class="subtitle"><a name="DisplayHeightMM">DisplayHeightMM / HeightMMOfScreen</a>
4333602e473dSmrg          <p>
4334602e473dSmrg          It is the height in millimeters of the screen that you want, and
4335602e473dSmrg          which is in the structure of the corresponding
4336602e473dSmrg          <span class="code">xcb_screen_t</span>.
4337602e473dSmrg          </p>
4338602e473dSmrg          <pre class="code">
4339602e473dSmrgxcb_connection_t *c;
4340602e473dSmrgxcb_screen_t     *screen;
4341602e473dSmrgint               screen_nbr;
4342602e473dSmrguint32_t          height_in_millimeters = 0;    /* the returned height in millimeters */
4343602e473dSmrg
4344602e473dSmrg/* you init the connection and screen_nbr */
4345602e473dSmrg
4346602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4347602e473dSmrgif (screen)
4348602e473dSmrg  height_in_millimeters = screen-&gt;height_in_millimeters;
4349602e473dSmrg
4350602e473dSmrg/* height_in_millimeters contains now the height in millimeters, or 0 if no screen is found */
4351602e473dSmrg</pre>
4352602e473dSmrg          <li class="subtitle"><a name="DisplayPlanes">DisplayPlanes / DefaultDepth / DefaultDepthOfScreen / PlanesOfScreen</a>
4353602e473dSmrg          <p>
4354602e473dSmrg          It is the depth (in bits) of the root window of the
4355602e473dSmrg          screen. You get it from the <span class="code">xcb_screen_t</span> structure.
4356602e473dSmrg          </p>
4357602e473dSmrg          <pre class="code">
4358602e473dSmrgxcb_connection_t *c;
4359602e473dSmrgxcb_screen_t     *screen;
4360602e473dSmrgint               screen_nbr;
4361602e473dSmrguint8_t           root_depth = 0;  /* the returned depth of the root window */
4362602e473dSmrg
4363602e473dSmrg/* you init the connection and screen_nbr */
4364602e473dSmrg
4365602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4366602e473dSmrgif (screen)
4367602e473dSmrg  root_depth = screen-&gt;root_depth;
4368602e473dSmrg
4369602e473dSmrg/* root_depth contains now the depth of the root window, or 0 if no screen is found */
4370602e473dSmrg</pre>
4371602e473dSmrg          <li class="subtitle"><a name="DefaultColormap">DefaultColormap / DefaultColormapOfScreen</a>
4372602e473dSmrg          <p>
4373602e473dSmrg          This is the default colormap of the screen (and not the
4374602e473dSmrg          (default) colormap of the default screen !). As usual, you
4375602e473dSmrg          get it from the <span class="code">xcb_screen_t</span> structure:
4376602e473dSmrg          </p>
4377602e473dSmrg          <pre class="code">
4378602e473dSmrgxcb_connection_t *c;
4379602e473dSmrgxcb_screen_t     *screen;
4380602e473dSmrgint               screen_nbr;
4381602e473dSmrgxcb_colormap_t    default_colormap = { 0 };  /* the returned default colormap */
4382602e473dSmrg
4383602e473dSmrg/* you init the connection and screen_nbr */
4384602e473dSmrg
4385602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4386602e473dSmrgif (screen)
4387602e473dSmrg  default_colormap = screen-&gt;default_colormap;
4388602e473dSmrg
4389602e473dSmrg/* default_colormap contains now the default colormap, or a NULL colormap if no screen is found */
4390602e473dSmrg</pre>
4391602e473dSmrg          <li class="subtitle"><a name="MinCmapsOfScreen"></a>MinCmapsOfScreen
4392602e473dSmrg          <p>
4393602e473dSmrg          You get the minimum installed colormaps in the <span class="code">xcb_screen_t</span> structure:
4394602e473dSmrg          </p>
4395602e473dSmrg          <pre class="code">
4396602e473dSmrgxcb_connection_t *c;
4397602e473dSmrgxcb_screen_t     *screen;
4398602e473dSmrgint               screen_nbr;
4399602e473dSmrguint16_t          min_installed_maps = 0;  /* the returned minimum installed colormaps */
4400602e473dSmrg
4401602e473dSmrg/* you init the connection and screen_nbr */
4402602e473dSmrg
4403602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4404602e473dSmrgif (screen)
4405602e473dSmrg  min_installed_maps = screen-&gt;min_installed_maps;
4406602e473dSmrg
4407602e473dSmrg/* min_installed_maps contains now the minimum installed colormaps, or 0 if no screen is found */
4408602e473dSmrg</pre>
4409602e473dSmrg          <li class="subtitle"><a name="MaxCmapsOfScreen"></a>MaxCmapsOfScreen
4410602e473dSmrg          <p>
4411602e473dSmrg          You get the maximum installed colormaps in the <span class="code">xcb_screen_t</span> structure:
4412602e473dSmrg          </p>
4413602e473dSmrg          <pre class="code">
4414602e473dSmrgxcb_connection_t *c;
4415602e473dSmrgxcb_screen_t     *screen;
4416602e473dSmrgint               screen_nbr;
4417602e473dSmrguint16_t          max_installed_maps = 0;  /* the returned maximum installed colormaps */
4418602e473dSmrg
4419602e473dSmrg/* you init the connection and screen_nbr */
4420602e473dSmrg
4421602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4422602e473dSmrgif (screen)
4423602e473dSmrg  max_installed_maps = screen-&gt;max_installed_maps;
4424602e473dSmrg
4425602e473dSmrg/* max_installed_maps contains now the maximum installed colormaps, or 0 if no screen is found */
4426602e473dSmrg</pre>
4427602e473dSmrg          <li class="subtitle"><a name="DoesSaveUnders"></a>DoesSaveUnders
4428602e473dSmrg          <p>
4429602e473dSmrg          You know if <span class="code">save_unders</span> is set,
4430602e473dSmrg          by looking in the <span class="code">xcb_screen_t</span> structure:
4431602e473dSmrg          </p>
4432602e473dSmrg          <pre class="code">
4433602e473dSmrgxcb_connection_t *c;
4434602e473dSmrgxcb_screen_t     *screen;
4435602e473dSmrgint               screen_nbr;
4436602e473dSmrguint8_t           save_unders = 0;  /* the returned value of save_unders */
4437602e473dSmrg
4438602e473dSmrg/* you init the connection and screen_nbr */
4439602e473dSmrg
4440602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4441602e473dSmrgif (screen)
4442602e473dSmrg  save_unders = screen-&gt;save_unders;
4443602e473dSmrg
4444602e473dSmrg/* save_unders contains now the value of save_unders, or FALSE if no screen is found */
4445602e473dSmrg</pre>
4446602e473dSmrg          <li class="subtitle"><a name="DoesBackingStore"></a>DoesBackingStore
4447602e473dSmrg          <p>
4448602e473dSmrg          You know the value of <span class="code">backing_stores</span>,
4449602e473dSmrg          by looking in the <span class="code">xcb_screen_t</span> structure:
4450602e473dSmrg          </p>
4451602e473dSmrg          <pre class="code">
4452602e473dSmrgxcb_connection_t *c;
4453602e473dSmrgxcb_screen_t     *screen;
4454602e473dSmrgint               screen_nbr;
4455602e473dSmrguint8_t           backing_stores = 0;  /* the returned value of backing_stores */
4456602e473dSmrg
4457602e473dSmrg/* you init the connection and screen_nbr */
4458602e473dSmrg
4459602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4460602e473dSmrgif (screen)
4461602e473dSmrg  backing_stores = screen-&gt;backing_stores;
4462602e473dSmrg
4463602e473dSmrg/* backing_stores contains now the value of backing_stores, or FALSE if no screen is found */
4464602e473dSmrg</pre>
4465602e473dSmrg          <li class="subtitle"><a name="EventMaskOfScreen"></a>EventMaskOfScreen
4466602e473dSmrg          <p>
4467602e473dSmrg          To get the current input masks,
4468602e473dSmrg          you look in the <span class="code">xcb_screen_t</span> structure:
4469602e473dSmrg          </p>
4470602e473dSmrg          <pre class="code">
4471602e473dSmrgxcb_connection_t *c;
4472602e473dSmrgxcb_screen_t     *screen;
4473602e473dSmrgint               screen_nbr;
4474602e473dSmrguint32_t          current_input_masks = 0;  /* the returned value of current input masks */
4475602e473dSmrg
4476602e473dSmrg/* you init the connection and screen_nbr */
4477602e473dSmrg
4478602e473dSmrgscreen = screen_of_display (c, screen_nbr);
4479602e473dSmrgif (screen)
4480602e473dSmrg  current_input_masks = screen-&gt;current_input_masks;
4481602e473dSmrg
4482602e473dSmrg/* current_input_masks contains now the value of the current input masks, or FALSE if no screen is found */
4483602e473dSmrg</pre>
4484602e473dSmrg        </ol>
4485602e473dSmrg      <li class="subtitle"><a name="misc">Miscellaneous macros</a>
4486602e473dSmrg        <ol>
4487602e473dSmrg          <li class="subtitle"><a name="DisplayOfScreen"></a>DisplayOfScreen
4488602e473dSmrg          <p>
4489602e473dSmrg          in Xlib, the <span class="code">Screen</span> structure
4490602e473dSmrg          stores its associated <span class="code">Display</span>
4491602e473dSmrg          structure. This is not the case in the X Window protocol,
4492602e473dSmrg          hence, it's also not the case in XCB. So you have to store
4493602e473dSmrg          it by yourself.
4494602e473dSmrg          </p>
4495602e473dSmrg          <li class="subtitle"><a name="DisplayCells"></a>DisplayCells / CellsOfScreen
4496602e473dSmrg          <p>
4497602e473dSmrg          To get the colormap entries,
4498602e473dSmrg          you look in the <span class="code">xcb_visualtype_t</span>
4499602e473dSmrg          structure, that you grab like <a class="subsection" href="#DefaultVisual">here</a>:
4500602e473dSmrg          </p>
4501602e473dSmrg          <pre class="code">
4502602e473dSmrgxcb_connection_t *c;
4503602e473dSmrgxcb_visualtype_t *visual_type;
4504602e473dSmrguint16_t          colormap_entries = 0;  /* the returned value of the colormap entries */
4505602e473dSmrg
4506602e473dSmrg/* you init the connection and visual_type */
4507602e473dSmrg
4508602e473dSmrgif (visual_type)
4509602e473dSmrg  colormap_entries = visual_type-&gt;colormap_entries;
4510602e473dSmrg
4511602e473dSmrg/* colormap_entries contains now the value of the colormap entries, or FALSE if no screen is found */
4512602e473dSmrg</pre>
4513602e473dSmrg        </ol>
4514602e473dSmrg      </ol>
4515602e473dSmrg    </ol>
4516602e473dSmrg  </div>
4517602e473dSmrg</body>
4518602e473dSmrg
4519602e473dSmrg</html>
4520