1 <!DOCTYPE html public "-//W3C//DTD HTML 4.01 Transitional//EN"
2 "http://www.w3.org/TR/html4/loose.dtd">
7 <title>Basic Graphics Programming With The XCB Library</title>
8 <meta http-equiv="content-type" content="text/html; charset=iso-8859-1">
9 <link href="xcb.css" rel="stylesheet" type="text/css">
14 Basic Graphics Programming With The XCB Library
18 <li><a class="section" href="#intro">Introduction</a>
19 <li><a class="section" href="#Xmodel">The client and server model of the X window system</a>
20 <li><a class="section" href="#asynch">GUI programming: the asynchronous model</a>
21 <li><a class="section" href="#notions">Basic XCB notions</a>
23 <li><a class="subsection" href="#conn">The X Connection</a>
24 <li><a class="subsection" href="#requestsreplies">Requests and replies: the Xlib killers</a>
25 <li><a class="subsection" href="#gc">The Graphics Context</a>
27 <li>Memory allocation for XCB structures
28 <li><a class="subsection" href="#events">Events</a>
30 <li><a class="section" href="#use">Using XCB-based programs</a>
32 <li><a class="subsection" href="#inst">Installation of XCB</a>
33 <li><a class="subsection" href="#comp">Compiling XCB-based programs</a>
35 <li><a class="section" href="#openconn">Opening and closing the connection to an X server</a>
36 <li><a class="section" href="#screen">Checking basic information about a connection</a>
37 <li><a class="section" href="#helloworld">Creating a basic window - the "hello world" program</a>
38 <li><a class="section" href="#drawing">Drawing in a window</a>
40 <li><a class="subsection" href="#allocgc">Allocating a Graphics Context</a>
41 <li><a class="subsection" href="#changegc">Changing the attributes of a Graphics Context</a>
42 <li><a class="subsection" href="#drawingprim">Drawing primitives: point, line, box, circle,...</a>
44 <li><a class="section" href="#xevents">X Events</a>
46 <li><a class="subsection" href="#register">Registering for event types using event masks</a>
47 <li><a class="subsection" href="#loop">Receiving events: writing the events loop</a>
48 <li><a class="subsection" href="#expose">Expose events</a>
49 <li><a class="subsection" href="#userinput">Getting user input</a>
51 <li><a class="subsubsection" href="#mousepressrelease">Mouse button press and release events</a>
52 <li><a class="subsubsection" href="#mousemvnt">Mouse movement events</a>
53 <li><a class="subsubsection" href="#mouseenter">Mouse pointer enter and leave events</a>
54 <li><a class="subsubsection" href="#focus">The keyboard focus</a>
55 <li><a class="subsubsection" href="#keypress">Keyboard press and release events</a>
57 <li><a class="subsection" href="#eventex">X events: a complete example</a>
59 <li><a class="section" href="#font">Handling text and fonts</a>
61 <li><a class="subsection" href="#fontstruct">The Font structure</a>
62 <li><a class="subsection" href="#openingfont">Opening a Font</a>
63 <li><a class="subsection" href="#assigningfont">Assigning a Font to a Graphic Context</a>
64 <li><a class="subsection" href="#drawingtext">Drawing text in a drawable</a>
65 <li><a class="subsection" href="#fontcompleteexample">Complete example</a>
69 <li>Root, parent and child windows
70 <li>Events propagation
72 <li><a class="section" href="#wm">Interacting with the window manager</a>
74 <li><a class="subsection" href="#wmprop">Window properties</a>
75 <li><a class="subsection" href="#wmname">Setting the window name and icon name</a>
76 <li>Setting preferred window size(s)
77 <li>Setting miscellaneous window manager hints
78 <li>Setting an application's icon
79 <li>Obeying the delete-window protocol
81 <li><a class="section" href="#winop">Simple window operations</a>
83 <li><a class="subsection" href="#winmap">Mapping and unmapping a window</a>
84 <li><a class="subsection" href="#winconf">Configuring a window</a>
85 <li><a class="subsection" href="#winmove">Moving a window around the screen</a>
86 <li><a class="subsection" href="#winsize">Resizing a window</a>
87 <li><a class="subsection" href="#winstack">Changing windows stacking order: raise and lower</a>
88 <li>Iconifying and de-iconifying a window
89 <li><a class="subsection" href="#wingetinfo">Getting informations about a window</a>
91 <li><a class="section" href="#usecolor">Using colors to paint the rainbow</a>
93 <li><a class="subsection" href="#colormap">Color maps</a>
94 <li><a class="subsection" href="#colormapalloc">Allocating and freeing Color Maps</a>
95 <li><a class="subsection" href="#alloccolor">Allocating and freeing a color entry</a>
96 <li>Drawing with a color
98 <li><a class="section" href="#pixmaps">X Bitmaps and Pixmaps</a>
100 <li><a class="subsection" href="#pixmapswhat">What is a X Bitmap ? An X Pixmap ?</a>
101 <li>Loading a bitmap from a file
102 <li>Drawing a bitmap in a window
103 <li><a class="subsection" href="#pixmapscreate">Creating a pixmap</a>
104 <li><a class="subsection" href="#pixmapsdraw">Drawing a pixmap in a window</a>
105 <li><a class="subsection" href="#pixmapsfree">Freeing a pixmap</a>
107 <li><a class="subsection" href="#mousecursor">Messing with the mouse cursor</a>
109 <li><a class="subsection" href="#mousecursorcreate">Creating and destroying a mouse cursor</a>
110 <li><a class="subsection" href="#mousecursorset">Setting a window's mouse cursor</a>
111 <li><a class="subsection" href="#mousecursorexample">Complete example</a>
113 <li><a class="subsection" href="#translation">Translation of basic Xlib functions and macros</a>
115 <li><a class="subsection" href="#displaystructure">Members of the Display structure</a>
117 <li><a class="subsection" href="#ConnectionNumber">ConnectionNumber</a>
118 <li><a class="subsection" href="#DefaultScreen">DefaultScreen</a>
119 <li><a class="subsection" href="#QLength">QLength</a>
120 <li><a class="subsection" href="#ScreenCount">ScreenCount</a>
121 <li><a class="subsection" href="#ServerVendor">ServerVendor</a>
122 <li><a class="subsection" href="#ProtocolVersion">ProtocolVersion</a>
123 <li><a class="subsection" href="#ProtocolRevision">ProtocolRevision</a>
124 <li><a class="subsection" href="#VendorRelease">VendorRelease</a>
125 <li><a class="subsection" href="#DisplayString">DisplayString</a>
126 <li><a class="subsection" href="#BitmapUnit">BitmapUnit</a>
127 <li><a class="subsection" href="#BitmapBitOrder">BitmapBitOrder</a>
128 <li><a class="subsection" href="#BitmapPad">BitmapPad</a>
129 <li><a class="subsection" href="#ImageByteOrder">ImageByteOrder</a>
131 <li><a class="subsection" href="#screenofdisplay">ScreenOfDisplay related functions</a>
133 <li><a class="subsection" href="#ScreenOfDisplay">ScreenOfDisplay</a>
134 <li><a class="subsection" href="#DefaultScreenOfDisplay">DefaultScreenOfDisplay</a>
135 <li><a class="subsection" href="#RootWindow">RootWindow / RootWindowOfScreen</a>
136 <li><a class="subsection" href="#DefaultRootWindow">DefaultRootWindow</a>
137 <li><a class="subsection" href="#DefaultVisual">DefaultVisual / DefaultVisualOfScreen</a>
138 <li><a class="subsection" href="#DefaultGC">DefaultGC / DefaultGCOfScreen</a>
139 <li><a class="subsection" href="#BlackPixel">BlackPixel / BlackPixelOfScreen</a>
140 <li><a class="subsection" href="#WhitePixel">WhitePixel / WhitePixelOfScreen</a>
141 <li><a class="subsection" href="#DisplayWidth">DisplayWidth / WidthOfScreen</a>
142 <li><a class="subsection" href="#DisplayHeight">DisplayHeight / HeightOfScreen</a>
143 <li><a class="subsection" href="#DisplayWidthMM">DisplayWidthMM / WidthMMOfScreen</a>
144 <li><a class="subsection" href="#DisplayHeightMM">DisplayHeightMM / HeightMMOfScreen</a>
145 <li><a class="subsection" href="#DisplayPlanes">DisplayPlanes / DefaultDepth / DefaultDepthOfScreen / PlanesOfScreen</a>
146 <li><a class="subsection" href="#DefaultColormap">DefaultColormap / DefaultColormapOfScreen</a>
147 <li><a class="subsection" href="#MinCmapsOfScreen">MinCmapsOfScreen</a>
148 <li><a class="subsection" href="#MaxCmapsOfScreen">MaxCmapsOfScreen</a>
149 <li><a class="subsection" href="#DoesSaveUnders">DoesSaveUnders</a>
150 <li><a class="subsection" href="#DoesBackingStore">DoesBackingStore</a>
151 <li><a class="subsection" href="#EventMaskOfScreen">EventMaskOfScreen</a>
153 <li><a class="subsection" href="#misc">Miscellaneous macros</a>
155 <li><a class="subsection" href="#DisplayOfScreen">DisplayOfScreen</a>
156 <li><a class="subsection" href="#DisplayCells">DisplayCells / CellsOfScreen</a>
161 <div class="section">
163 <li class="title"><a name="intro">Introduction</a>
165 This tutorial is based on the
166 <a href="http://users.actcom.co.il/~choo/lupg/tutorials/xlib-programming/xlib-programming.html">Xlib Tutorial</a>
167 written by <a href="mailto:choor at atcom dot co dot il">Guy Keren</a>. The
168 author allowed me to take some parts of his text, mainly the text which
169 deals with the X Windows generality.
172 This tutorial is intended for people who want to start to program
173 with the <a href="http://xcb.freedesktop.org">XCB</a>
174 library. keep in mind that XCB, like the
175 <a href="http://tronche.com/gui/x/xlib/introduction">Xlib</a>
176 library, isn't what most programmers wanting to write X
177 applications are looking for. They should use a much higher
178 level GUI toolkit like Motif,
179 <a href="http://www.lesstif.org">LessTiff</a>,
180 <a href="http://www.gtk.org">GTK</a>,
181 <a href="http://www.trolltech.com">QT</a>,
182 <a href="http://www.enlightenment.org">EWL</a>,
183 <a href="http://www.enlightenment.org">ETK</a>, or use
184 <a href="http://cairographics.org">Cairo</a>.
186 we need to start somewhere. More than this, knowing how things
187 work down below is never a bad idea.
190 After reading this tutorial, one should be able to write very
191 simple graphical programs, but not programs with decent user
192 interfaces. For such programs, one of the previously mentioned
193 libraries should be used.
196 But what is XCB? Xlib has been
197 the standard C binding for the <a href="http://www.x.org">X
198 Window System</a> protocol for many years now. It is an
199 excellent piece of work, but there are applications for which it
200 is not ideal, for example:
203 <li><b>Small platforms</b>: Xlib is a large piece of code, and
204 it's difficult to make it smaller
205 <li><b>Latency hiding</b>: Xlib requests requiring a reply are
206 effectively synchronous: they block until the reply appears,
207 whether the result is needed immediately or not.
208 <li><b>Direct access to the protocol</b>: Xlib does quite a
209 bit of caching, layering, and similar optimizations. While this
210 is normally a feature, it makes it difficult to simply emit
211 specified X protocol requests and process specific
213 <li><b>Threaded applications</b>: While Xlib does attempt to
214 support multithreading, the API makes this difficult and
216 <li><b>New extensions</b>: The Xlib infrastructure provides
217 limited support for the new creation of X extension client side
221 For these reasons, among others, XCB, an X C binding, has been
222 designed to solve the above problems and thus provide a base for
225 <li>Toolkit implementation.
226 <li>Direct protocol-level programming.
227 <li>Lightweight emulation of commonly used portions of the
231 <li class="title"><a name="Xmodel">The client and server model of the X window system</a>
233 The X Window System was developed with one major goal:
234 flexibility. The idea was that the way things look is one thing,
235 but the way things work is another matter. Thus, the lower
236 levels provide the tools required to draw windows, handle user
237 input, allow drawing graphics using colors (or black and white
238 screens), etc. To this point, a decision was made to separate
239 the system into two parts. A client that decides what to do, and
240 a server that actually draws on the screen and reads user input
241 in order to send it to the client for processing.
244 This model is the complete opposite of what is used to when
245 dealing with clients and servers. In our case, the user sits
246 near the machine controlled by the server, while the client
247 might be running on a remote machine. The server controls the
248 screens, mouse and keyboard. A client may connect to the server,
249 request that it draws a window (or several windows), and ask the
250 server to send it any input the user sends to these
251 windows. Thus, several clients may connect to a single X server
252 (one might be running mail software, one running a WWW
253 browser, etc). When input is sent by the user to some window,
254 the server sends a message to the client controlling this window
255 for processing. The client decides what to do with this input,
256 and sends the server requests for drawing in the window.
259 The whole session is carried out using the X message
260 protocol. This protocol was originally carried over the TCP/IP
261 protocol suite, allowing the client to run on any machine
262 connected to the same network that the server is. Later on, the
263 X servers were extended to allow clients running on the local
264 machine with more optimized access to the server (note that an X
265 protocol message may be several hundreds of KB in size), such as
266 using shared memory, or using Unix domain sockets (a method for
267 creating a logical channel on a Unix system between two processes).
269 <li class="title"><a name="asynch">GUI programming: the asynchronous model</a>
271 Unlike conventional computer programs, that carry some serial
272 nature, a GUI program usually uses an asynchronous programming
273 model, also known as "event-driven programming". This means that
274 that program mostly sits idle, waiting for events sent by the X
275 server, and then acts upon these events. An event may say "The
276 user pressed the 1st button mouse in spot (x,y)", or "The window
277 you control needs to be redrawn". In order for the program to be
278 responsive to the user input, as well as to refresh requests, it
279 needs to handle each event in a rather short period of time
280 (e.g. less that 200 milliseconds, as a rule of thumb).
283 This also implies that the program may not perform operations
284 that might take a long time while handling an event (such as
285 opening a network connection to some remote server, or
286 connecting to a database server, or even performing a long file
287 copy operation). Instead, it needs to perform all these
288 operations in an asynchronous manner. This may be done by using
289 various asynchronous models to perform the longish operations,
290 or by performing them in a different process or thread.
293 So the way a GUI program looks is something like that:
296 <li>Perform initialization routines.
297 <li>Connect to the X server.
298 <li>Perform X-related initialization.
299 <li>While not finished:
301 <li>Receive the next event from the X server.
302 <li>Handle the event, possibly sending various drawing
303 requests to the X server.
304 <li>If the event was a quit message, exit the loop.
306 <li>Close down the connection to the X server.
307 <li>Perform cleanup operations.
310 <li class="title"><a name="notions">Basic XCB notions</a>
312 XCB has been created to eliminate the need for
313 programs to actually implement the X protocol layer. This
314 library gives a program a very low-level access to any X
315 server. Since the protocol is standardized, a client using any
316 implementation of XCB may talk with any X server (the same
317 occurs for Xlib, of course). We now give a brief description of
318 the basic XCB notions. They will be detailed later.
321 <li class="subtitle"><a name="conn">The X Connection</a>
323 The major notion of using XCB is the X Connection. This is a
324 structure representing the connection we have open with a
325 given X server. It hides a queue of messages coming from the
326 server, and a queue of pending requests that our client
327 intends to send to the server. In XCB, this structure is named
328 'xcb_connection_t'. It is analogous to the Xlib Display.
329 When we open a connection to an X server, the
330 library returns a pointer to such a structure. Later, we
331 supply this pointer to any XCB function that should send
332 messages to the X server or receive messages from this server.
334 <li class="subtitle"><a name="requestsreplies">Requests and
335 replies: the Xlib killers</a>
337 To ask for information from the X server, we have to make a request
338 and ask for a reply. With Xlib, these two tasks are
339 automatically done: Xlib locks the system, sends a request,
340 waits for a reply from the X server and unlocks. This is
341 annoying, especially if one makes a lot of requests to the X
342 server. Indeed, Xlib has to wait for the end of a reply
343 before asking for the next request (because of the locks that
344 Xlib sends). For example, here is a time-line of N=4
345 requests/replies with Xlib, with a round-trip latency
346 <b>T_round_trip</b> that is 5 times long as the time required
347 to write or read a request/reply (<b>T_write/T_read</b>):
350 W-----RW-----RW-----RW-----R
353 <li>W: Writing request
354 <li>-: Stalled, waiting for data
358 The total time is N * (T_write + T_round_trip + T_read).
361 With XCB, we can suppress most of the round-trips as the
362 requests and the replies are not locked. We usually send a
363 request, then XCB returns to us a <b>cookie</b>, which is an
364 identifier. Then, later, we ask for a reply using this
365 <b>cookie</b> and XCB returns a
366 pointer to that reply. Hence, with XCB, we can send a lot of
367 requests, and later in the program, ask for all the replies
368 when we need them. Here is the time-line for 4
369 requests/replies when we use this property of XCB:
375 The total time is N * T_write + max (0, T_round_trip - (N-1) *
376 T_write) + N * T_read. Which can be considerably faster than
377 all those Xlib round-trips.
380 Here is a program that computes the time to create 500 atoms
381 with Xlib and XCB. It shows the Xlib way, the bad XCB way
382 (which is similar to Xlib) and the good XCB way. On my
383 computer, XCB is 25 times faster than Xlib.
386 #include <stdlib.h>
387 #include <stdio.h>
388 #include <string.h>
389 #include <sys/time.h>
391 #include <xcb/xcb.h>
393 #include <X11/Xlib.h>
398 struct timeval timev;
400 gettimeofday(&timev, NULL);
402 return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000);
410 xcb_intern_atom_cookie_t *cs;
423 c = xcb_connect (NULL, NULL);
426 atoms = (xcb_atom_t *)malloc (count * sizeof (atoms));
427 names = (char **)malloc (count * sizeof (char *));
430 for (i = 0; i < count; ++i) {
433 sprintf (buf, "NAME%d", i);
434 names[i] = strdup (buf);
440 for (i = 0; i < count; ++i)
441 atoms[i] = xcb_intern_atom_reply (c,
450 printf ("bad use time : %f\n", diff);
455 cs = (xcb_intern_atom_cookie_t *) malloc (count * sizeof(xcb_intern_atom_cookie_t));
456 for(i = 0; i < count; ++i)
457 cs[i] = xcb_intern_atom (c, 0, strlen(names[i]), names[i]);
459 for(i = 0; i < count; ++i) {
460 xcb_intern_atom_reply_t *r;
462 r = xcb_intern_atom_reply(c, cs[i], 0);
469 printf ("good use time : %f\n", end - start);
470 printf ("ratio : %f\n", diff / (end - start));
480 disp = XOpenDisplay (getenv("DISPLAY"));
482 atoms_x = (Atom *)malloc (count * sizeof (atoms_x));
486 for (i = 0; i < count; ++i)
487 atoms_x[i] = XInternAtom(disp, names[i], 0);
490 diff_x = end - start;
491 printf ("Xlib use time : %f\n", diff_x);
492 printf ("ratio : %f\n", diff_x / diff);
495 for (i = 0; i < count; ++i)
499 XCloseDisplay (disp);
504 <li class="subtitle"><a name="gc">The Graphic Context</a>
506 When we perform various drawing operations (graphics, text,
507 etc), we may specify various options for controlling how the
508 data will be drawn (what foreground and background colors to
509 use, how line edges will be connected, what font to use when
510 drawing some text, etc). In order to avoid the need to supply
511 hundreds of parameters to each drawing function, a graphical
512 context structure is used. We set the various drawing options
513 in this structure, and then we pass a pointer to this
514 structure to any drawing routines. This is rather handy, as we
515 often need to perform several drawing requests with the same
516 options. Thus, we would initialize a graphical context, set
517 the desired options, and pass this structure to all drawing
521 Note that graphic contexts have no client-side structure in
522 XCB, they're just XIDs. Xlib has a client-side structure
523 because it caches the GC contents so it can avoid making
524 redundant requests, but of course XCB doesn't do that.
526 <li class="subtitle"><a name="events">Events</a>
528 A structure is used to pass events received from the X
529 server. XCB supports exactly the events specified in the
530 protocol (33 events). This structure contains the type
531 of event received (including a bit for whether it came
532 from the server or another client), as well as the data associated with the
533 event (e.g. position on the screen where the event was
534 generated, mouse button associated with the event, region of
535 the screen associated with a "redraw" event, etc). The way to
536 read the event's data depends on the event type.
540 <li class="title"><a name="use">Using XCB-based programs</a>
543 <li class="subtitle"><a name="inst">Installation of XCB</a>
545 <b>TODO:</b> These instructions are out of date.
546 Just reference the <a href="http://xcb.freedesktop.org/">main XCB page</a>
547 so we don't have to maintain these instructions in more than
551 To build XCB from source, you need to have installed at
556 <li><a href="http://www.gnu.org/software/automake/">automake 1.7</a>
557 <li><a href="http://www.gnu.org/software/autoconf/">autoconf 2.50</a>
558 <li><a href="http://www.check.org">check</a>
559 <li><a href="http://xmlsoft.org/XSLT/">xsltproc</a>
560 <li><a href="http://www.gnu.org/software/gperf/">gperf 3.0.1</a>
563 You have to checkout in the git repository the following modules:
571 Note that xcb-proto exists only to install header
572 files, so typing 'make' or 'make all' will produce the message
573 "Nothing to be done for 'all'". That's normal.
575 <li class="subtitle"><a name="comp">Compiling XCB-based programs</a>
577 Compiling XCB-based programs requires linking them with the XCB
578 library. This is easily done thanks to pkgconfig:
581 gcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb`
584 <li class="title"><a name="openconn">Opening and closing the connection to an X server</a>
586 An X program first needs to open the connection to the X
587 server. There is a function that opens a connection. It requires
588 the display name, or NULL. In the latter case, the display name
589 will be the one in the environment variable DISPLAY.
592 <span class="type">xcb_connection_t</span> *xcb_connect (<span class="keyword">const</span> <span class="type">char</span> *displayname,
593 <span class="type">int</span> *screenp);
596 The second parameter returns the screen number used for the
597 connection. The returned structure describes an XCB connection
598 and is opaque. Here is how the connection can be opened:
601 #<span class="include">include</span> <span class="string"><xcb/xcb.h></span>
603 <span class="type">int</span>
604 <span class="function">main</span> ()
606 <span class="type">xcb_connection_t</span> *c;
608 /* Open the connection to the X server. Use the DISPLAY environment variable as the default display name */
609 c = xcb_connect (NULL, NULL);
611 <span class="keyword">return</span> 0;
615 To close a connection, it suffices to use:
618 <span class="type">void</span> xcb_disconnect (<span class="type">xcb_connection_t</span> *c);
641 <li>xcb_disconnect ()
646 <li class="title"><a name="screen">Checking basic information about a connection</a>
648 Once we have opened a connection to an X server, we should check some
649 basic information about it: what screens it has, what is the
650 size (width and height) of the screen, how many colors it
651 supports (black and white ? grey scale ?, 256 colors ? more ?),
652 and so on. We get such information from the xcb_screen_t
658 xcb_colormap_t default_colormap;
659 uint32_t white_pixel;
660 uint32_t black_pixel;
661 uint32_t current_input_masks;
662 uint16_t width_in_pixels;
663 uint16_t height_in_pixels;
664 uint16_t width_in_millimeters;
665 uint16_t height_in_millimeters;
666 uint16_t min_installed_maps;
667 uint16_t max_installed_maps;
668 xcb_visualid_t root_visual;
669 uint8_t backing_stores;
672 uint8_t allowed_depths_len;
676 We could retrieve the first screen of the connection by using the
680 xcb_screen_iterator_t xcb_setup_roots_iterator (xcb_setup_t *R);
683 Here is a small program that shows how to use this function:
686 #include <stdio.h>
688 #include <xcb/xcb.h>
694 xcb_screen_t *screen;
696 xcb_screen_iterator_t iter;
698 /* Open the connection to the X server. Use the DISPLAY environment variable */
699 c = xcb_connect (NULL, &screen_nbr);
701 /* Get the screen #screen_nbr */
702 iter = xcb_setup_roots_iterator (xcb_get_setup (c));
703 for (; iter.rem; --screen_nbr, xcb_screen_next (&iter))
704 if (screen_nbr == 0) {
710 printf ("Informations of screen %ld:\n", screen->root);
711 printf (" width.........: %d\n", screen->width_in_pixels);
712 printf (" height........: %d\n", screen->height_in_pixels);
713 printf (" white pixel...: %ld\n", screen->white_pixel);
714 printf (" black pixel...: %ld\n", screen->black_pixel);
720 <li class="title"><a name="helloworld">Creating a basic window - the "hello world" program</a>
722 After we got some basic information about our screen, we can
723 create our first window. In the X Window System, a window is
724 characterized by an Id. So, in XCB, a window is of type:
727 typedef uint32_t xcb_window_t;
730 We first ask for a new Id for our window, with this function:
733 xcb_window_t xcb_generate_id(xcb_connection_t *c);
736 Then, XCB supplies the following function to create new windows:
739 xcb_void_cookie_t xcb_create_window (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */
740 uint8_t depth, /* Depth of the screen */
741 xcb_window_t wid, /* Id of the window */
742 xcb_window_t parent, /* Id of an existing window that should be the parent of the new window */
743 int16_t x, /* X position of the top-left corner of the window (in pixels) */
744 int16_t y, /* Y position of the top-left corner of the window (in pixels) */
745 uint16_t width, /* Width of the window (in pixels) */
746 uint16_t height, /* Height of the window (in pixels) */
747 uint16_t border_width, /* Width of the window's border (in pixels) */
749 xcb_visualid_t visual,
751 const uint32_t *value_list);
754 The fact that we created the window does not mean that it will
755 be drawn on screen. By default, newly created windows are not
756 mapped on the screen (they are invisible). In order to make our
757 window visible, we use the function <span class="code">xcb_map_window()</span>, whose
761 xcb_void_cookie_t xcb_map_window (xcb_connection_t *c,
762 xcb_window_t window);
765 Finally, here is a small program to create a window of size
766 150x150 pixels, positioned at the top-left corner of the screen:
769 #include <unistd.h> /* pause() */
771 #include <xcb/xcb.h>
777 xcb_screen_t *screen;
780 /* Open the connection to the X server */
781 c = xcb_connect (NULL, NULL);
783 /* Get the first screen */
784 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
786 /* Ask for our window's Id */
787 win = xcb_generate_id(c);
789 /* Create the window */
790 xcb_create_window (c, /* Connection */
791 XCB_COPY_FROM_PARENT, /* depth (same as root)*/
793 screen->root, /* parent window */
795 150, 150, /* width, height */
796 10, /* border_width */
797 XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
798 screen->root_visual, /* visual */
799 0, NULL); /* masks, not used yet */
801 /* Map the window on the screen */
802 xcb_map_window (c, win);
804 /* Make sure commands are sent before we pause, so window is shown */
807 pause (); /* hold client until Ctrl-C */
813 In this code, you see one more function - <span class="code">xcb_flush()</span>, not explained
814 yet. It is used to flush all the pending requests. More
815 precisely, there are 2 functions that do such things. The first
816 one is <span class="code">xcb_flush()</span>:
819 int xcb_flush (xcb_connection_t *c);
822 This function flushes all pending requests to the X server (much
823 like the <span class="code">fflush()</span> function is used to
824 flush standard output). The second function is
825 <span class="code">xcb_aux_sync()</span>:
828 int xcb_aux_sync (xcb_connection_t *c);
831 This functions also flushes all pending requests to the X
832 server, and then waits until the X server finishing processing
833 these requests. In a normal program, this will not be necessary
834 (we'll see why when we get to write a normal X program), but for
835 now, we put it there.
838 The window that is created by the above code has a non defined
839 background. This one can be set to a specific color,
840 thanks to the two last parameters of
841 <span class="code">xcb_create_window()</span>, which are not
842 described yet. See the subsections
843 <a href="#winconf">Configuring a window</a> or
844 <a href="#winconf">Registering for event types using event masks</a>
845 for examples on how to use these parameters. In addition, as no
846 events are handled, you have to make a Ctrl-C to interrupt the
850 <b>TODO</b>: one should tell what these functions return and
851 about the generic error
864 <li>xcb_generate_id ()
865 <li>xcb_create_window ()
870 <li class="title"><a name="drawing">Drawing in a window</a>
872 Drawing in a window can be done using various graphical
873 functions (drawing pixels, lines, rectangles, etc). In order to
874 draw in a window, we first need to define various general
875 drawing parameters (what line width to use, which color to draw
876 with, etc). This is done using a graphical context.
879 <li class="subtitle"><a name="allocgc">Allocating a Graphics Context</a>
881 As we said, a graphical context defines several attributes to
882 be used with the various drawing functions. For this, we
883 define a graphical context. We can use more than one graphical
884 context with a single window, in order to draw in multiple
885 styles (different colors, different line widths, etc). In XCB,
886 a Graphics Context is, as a window, characterized by an Id:
889 typedef uint32_t xcb_gcontext_t;
892 We first ask the X server to attribute an Id to our graphic
893 context with this function:
896 xcb_gcontext_t xcb_generate_id (xcb_connection_t *c);
899 Then, we set the attributes of the graphic context with this function:
902 xcb_void_cookie_t xcb_create_gc (xcb_connection_t *c,
904 xcb_drawable_t drawable,
906 const uint32_t *value_list);
909 We give now an example on how to allocate a graphic context
910 that specifies that each drawing function that uses it will
911 draw in foreground with a black color.
914 #include <xcb/xcb.h>
920 xcb_screen_t *screen;
922 xcb_gcontext_t black;
926 /* Open the connection to the X server and get the first screen */
927 c = xcb_connect (NULL, NULL);
928 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
930 /* Create a black graphic context for drawing in the foreground */
931 win = screen->root;
932 black = xcb_generate_id (c);
933 mask = XCB_GC_FOREGROUND;
934 value[0] = screen->black_pixel;
935 xcb_create_gc (c, black, win, mask, value);
941 Note should be taken regarding the role of "value_mask" and
942 "value_list" in the prototype of <span class="code">xcb_create_gc()</span>. Since a
943 graphic context has many attributes, and since we often just
944 want to define a few of them, we need to be able to tell the
945 <span class="code">xcb_create_gc()</span> which attributes we
946 want to set. This is what the "value_mask" parameter is
947 for. We then use the "value_list" parameter to specify actual
948 values for the attribute we defined in "value_mask". Thus, for
949 each constant used in "value_list", we will use the matching
950 constant in "value_mask". In this case, we define a graphic
951 context with one attribute: when drawing (a point, a line,
952 etc), the foreground color will be black. The rest of the
953 attributes of this graphic context will be set to their
957 See the next Subsection for more details.
970 <li>xcb_generate_id ()
976 <li class="subtitle"><a name="changegc">Changing the attributes of a Graphics Context</a>
978 Once we have allocated a Graphic Context, we may need to
979 change its attributes (for example, changing the foreground
980 color we use to draw a line, or changing the attributes of the
981 font we use to display strings. See Subsections Drawing with a
983 <a href="#assigningfont">Assigning a Font to a Graphic Context</a>).
984 This is done by using this function:
987 xcb_void_cookie_t xcb_change_gc (xcb_connection_t *c, /* The XCB Connection */
988 xcb_gcontext_t gc, /* The Graphic Context */
989 uint32_t value_mask, /* Components of the Graphic Context that have to be set */
990 const uint32_t *value_list); /* Value as specified by value_mask */
993 The <span class="code">value_mask</span> parameter could take
994 any combination of these masks from the xcb_gc_t enumeration:
998 <li>XCB_GC_PLANE_MASK
999 <li>XCB_GC_FOREGROUND
1000 <li>XCB_GC_BACKGROUND
1001 <li>XCB_GC_LINE_WIDTH
1002 <li>XCB_GC_LINE_STYLE
1003 <li>XCB_GC_CAP_STYLE
1004 <li>XCB_GC_JOIN_STYLE
1005 <li>XCB_GC_FILL_STYLE
1006 <li>XCB_GC_FILL_RULE
1009 <li>XCB_GC_TILE_STIPPLE_ORIGIN_X
1010 <li>XCB_GC_TILE_STIPPLE_ORIGIN_Y
1012 <li>XCB_GC_SUBWINDOW_MODE
1013 <li>XCB_GC_GRAPHICS_EXPOSURES
1014 <li>XCB_GC_CLIP_ORIGIN_X
1015 <li>XCB_GC_CLIP_ORIGIN_Y
1016 <li>XCB_GC_CLIP_MASK
1017 <li>XCB_GC_DASH_OFFSET
1018 <li>XCB_GC_DASH_LIST
1022 It is possible to set several attributes at the same
1023 time (for example setting the attributes of a font and the
1024 color which will be used to display a string), by OR'ing these
1025 values in <span class="code">value_mask</span>. Then
1026 <span class="code">value_list</span> has to be an array which
1027 lists the value for the respective attributes. <b>These values
1028 must be in the same order as masks listed above.</b> See Subsection
1029 Drawing with a color to have an example.
1032 <b>TODO</b>: set the links of the 3 subsections, once they will
1036 <b>TODO</b>: give an example which sets several attributes.
1038 <li class="subtitle"><a name="drawingprim">Drawing primitives: point, line, box, circle,...</a>
1040 After we have created a Graphic Context, we can draw on a
1041 window using this Graphic Context, with a set of XCB
1042 functions, collectively called "drawing primitives". Let see
1046 To draw a point, or several points, we use
1049 xcb_void_cookie_t xcb_poly_point (xcb_connection_t *c, /* The connection to the X server */
1050 uint8_t coordinate_mode, /* Coordinate mode, usually set to XCB_COORD_MODE_ORIGIN */
1051 xcb_drawable_t drawable, /* The drawable on which we want to draw the point(s) */
1052 xcb_gcontext_t gc, /* The Graphic Context we use to draw the point(s) */
1053 uint32_t points_len, /* The number of points */
1054 const xcb_point_t *points); /* An array of points */
1057 The <span class="code">coordinate_mode</span> parameter
1058 specifies the coordinate mode. Available values are
1061 <li><span class="code">XCB_COORD_MODE_ORIGIN</span>
1062 <li><span class="code">XCB_COORD_MODE_PREVIOUS</span>
1065 If XCB_COORD_MODE_PREVIOUS is used, then all points but the first one
1066 are relative to the immediately previous point.
1069 The <span class="code">xcb_point_t</span> type is just a
1070 structure with two fields (the coordinates of the point):
1079 You could see an example in xpoints.c. <b>TODO</b> Set the link.
1082 To draw a line, or a polygonal line, we use
1085 xcb_void_cookie_t xcb_poly_line (xcb_connection_t *c, /* The connection to the X server */
1086 uint8_t coordinate_mode, /* Coordinate mode, usually set to XCB_COORD_MODE_ORIGIN */
1087 xcb_drawable_t drawable, /* The drawable on which we want to draw the line(s) */
1088 xcb_gcontext_t gc, /* The Graphic Context we use to draw the line(s) */
1089 uint32_t points_len, /* The number of points in the polygonal line */
1090 const xcb_point_t *points); /* An array of points */
1093 This function will draw the line between the first and the
1094 second points, then the line between the second and the third
1098 To draw a segment, or several segments, we use
1101 xcb_void_cookie_t xcb_poly_segment (xcb_connection_t *c, /* The connection to the X server */
1102 xcb_drawable_t drawable, /* The drawable on which we want to draw the segment(s) */
1103 xcb_gcontext_t gc, /* The Graphic Context we use to draw the segment(s) */
1104 uint32_t segments_len, /* The number of segments */
1105 const xcb_segment_t *segments); /* An array of segments */
1108 The <span class="code">xcb_segment_t</span> type is just a
1109 structure with four fields (the coordinates of the two points
1110 that define the segment):
1121 To draw a rectangle, or several rectangles, we use
1124 xcb_void_cookie_t xcb_poly_rectangle (xcb_connection_t *c, /* The connection to the X server */
1125 xcb_drawable_t drawable, /* The drawable on which we want to draw the rectangle(s) */
1126 xcb_gcontext_t gc, /* The Graphic Context we use to draw the rectangle(s) */
1127 uint32_t rectangles_len, /* The number of rectangles */
1128 const xcb_rectangle_t *rectangles); /* An array of rectangles */
1131 The <span class="code">xcb_rectangle_t</span> type is just a
1132 structure with four fields (the coordinates of the top-left
1133 corner of the rectangle, and its width and height):
1143 <!-- There's no coordinate_mode. Is it normal? -->
1144 <!-- [iano] Yes, it's not in the protocol. -->
1146 To draw an elliptical arc, or several elliptical arcs, we use
1149 xcb_void_cookie_t xcb_poly_arc (xcb_connection_t *c, /* The connection to the X server */
1150 xcb_drawable_t drawable, /* The drawable on which we want to draw the arc(s) */
1151 xcb_gcontext_t gc, /* The Graphic Context we use to draw the arc(s) */
1152 uint32_t arcs_len, /* The number of arcs */
1153 const xcb_arc_t *arcs); /* An array of arcs */
1156 The <span class="code">xcb_arc_t</span> type is a structure with
1161 int16_t x; /* Top left x coordinate of the rectangle surrounding the ellipse */
1162 int16_t y; /* Top left y coordinate of the rectangle surrounding the ellipse */
1163 uint16_t width; /* Width of the rectangle surrounding the ellipse */
1164 uint16_t height; /* Height of the rectangle surrounding the ellipse */
1165 int16_t angle1; /* Angle at which the arc begins */
1166 int16_t angle2; /* Angle at which the arc ends */
1171 Note: the angles are expressed in units of 1/64 of a degree,
1172 so to have an angle of 90 degrees, starting at 0,
1173 <span class="code">angle1 = 0</span> and
1174 <span class="code">angle2 = 90 << 6</span>. Positive angles
1175 indicate counterclockwise motion, while negative angles
1176 indicate clockwise motion.
1179 <!-- I think that (x,y) should be the center of the
1180 ellipse, and (width, height) the radius. It's more logical. -->
1181 <!-- iano: Yes, and I bet some toolkits do that.
1182 But the protocol (and many other graphics APIs) define arcs
1183 by bounding rectangles. -->
1185 The corresponding function which fill inside the geometrical
1186 object are listed below, without further explanation, as they
1187 are used as the above functions.
1190 To Fill a polygon defined by the points given as arguments ,
1194 xcb_void_cookie_t xcb_fill_poly (xcb_connection_t *c,
1195 xcb_drawable_t drawable,
1198 uint8_t coordinate_mode,
1199 uint32_t points_len,
1200 const xcb_point_t *points);
1203 The <span class="code">shape</span> parameter specifies a
1204 shape that helps the server to improve performance. Available
1208 <li><span class="code">XCB_POLY_SHAPE_COMPLEX</span>
1209 <li><span class="code">XCB_POLY_SHAPE_NONCONVEX</span>
1210 <li><span class="code">XCB_POLY_SHAPE_CONVEX</span>
1213 To fill one or several rectangles, we use
1216 xcb_void_cookie_t xcb_poly_fill_rectangle (xcb_connection_t *c,
1217 xcb_drawable_t drawable,
1219 uint32_t rectangles_len,
1220 const xcb_rectangle_t *rectangles);
1223 To fill one or several arcs, we use
1226 xcb_void_cookie_t xcb_poly_fill_arc (xcb_connection_t *c,
1227 xcb_drawable_t drawable,
1230 const xcb_arc_t *arcs);
1233 <a name="points.c"></a>
1235 To illustrate these functions, here is an example that draws
1236 four points, a polygonal line, two segments, two rectangles
1237 and two arcs. Remark that we use events for the first time, as
1238 an introduction to the next section.
1241 <b>TODO:</b> Use screen->root_depth for depth parameter.
1244 #include <stdlib.h>
1245 #include <stdio.h>
1247 #include <xcb/xcb.h>
1252 xcb_connection_t *c;
1253 xcb_screen_t *screen;
1255 xcb_gcontext_t foreground;
1256 xcb_generic_event_t *e;
1260 /* geometric objects */
1261 xcb_point_t points[] = {
1267 xcb_point_t polyline[] = {
1269 { 5, 20}, /* rest of points are relative */
1273 xcb_segment_t segments[] = {
1275 {110, 25, 130, 60}};
1277 xcb_rectangle_t rectangles[] = {
1281 xcb_arc_t arcs[] = {
1282 {10, 100, 60, 40, 0, 90 << 6},
1283 {90, 100, 55, 40, 0, 270 << 6}};
1285 /* Open the connection to the X server */
1286 c = xcb_connect (NULL, NULL);
1288 /* Get the first screen */
1289 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
1291 /* Create black (foreground) graphic context */
1292 win = screen->root;
1294 foreground = xcb_generate_id (c);
1295 mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES;
1296 values[0] = screen->black_pixel;
1298 xcb_create_gc (c, foreground, win, mask, values);
1300 /* Ask for our window's Id */
1301 win = xcb_generate_id(c);
1303 /* Create the window */
1304 mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
1305 values[0] = screen->white_pixel;
1306 values[1] = XCB_EVENT_MASK_EXPOSURE;
1307 xcb_create_window (c, /* Connection */
1308 XCB_COPY_FROM_PARENT, /* depth */
1309 win, /* window Id */
1310 screen->root, /* parent window */
1312 150, 150, /* width, height */
1313 10, /* border_width */
1314 XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
1315 screen->root_visual, /* visual */
1316 mask, values); /* masks */
1318 /* Map the window on the screen */
1319 xcb_map_window (c, win);
1322 /* We flush the request */
1325 while ((e = xcb_wait_for_event (c))) {
1326 switch (e->response_type & ~0x80) {
1328 /* We draw the points */
1329 xcb_poly_point (c, XCB_COORD_MODE_ORIGIN, win, foreground, 4, points);
1331 /* We draw the polygonal line */
1332 xcb_poly_line (c, XCB_COORD_MODE_PREVIOUS, win, foreground, 4, polyline);
1334 /* We draw the segments */
1335 xcb_poly_segment (c, win, foreground, 2, segments);
1337 /* We draw the rectangles */
1338 xcb_poly_rectangle (c, win, foreground, 2, rectangles);
1340 /* We draw the arcs */
1341 xcb_poly_arc (c, win, foreground, 2, arcs);
1343 /* We flush the request */
1349 /* Unknown event type, ignore it */
1353 /* Free the Generic Event */
1361 <li class="title"><a name="xevents">X Events</a>
1363 In an X program, everything is driven by events. Event painting
1364 on the screen is sometimes done as a response to an event (an
1365 <span class="code">Expose</span> event). If part of a program's
1366 window that was hidden, gets exposed (e.g. the window was raised
1367 above other widows), the X server will send an "expose" event to
1368 let the program know it should repaint that part of the
1369 window. User input (key presses, mouse movement, etc) is also
1370 received as a set of events.
1373 <li class="subtitle"><a name="register">Registering for event types using event masks</a>
1375 During the creation of a window, you should give it what kind
1376 of events it wishes to receive. Thus, you may register for
1377 various mouse (also called pointer) events, keyboard events,
1378 expose events, and so on. This is done for optimizing the
1379 server-to-client connection (i.e. why send a program (that
1380 might even be running at the other side of the globe) an event
1381 it is not interested in ?)
1384 In XCB, you use the "value_mask" and "value_list" data in the
1385 <span class="code">xcb_create_window()</span> function to
1386 register for events. Here is how we register for
1387 <span class="code">Expose</span> event when creating a window:
1390 mask = XCB_CW_EVENT_MASK;
1391 valwin[0] = XCB_EVENT_MASK_EXPOSURE;
1392 win = xcb_generate_id (c);
1393 xcb_create_window (c, depth, win, root->root,
1395 XCB_WINDOW_CLASS_INPUT_OUTPUT, root->root_visual,
1399 <span class="code">XCB_EVENT_MASK_EXPOSURE</span> is a constant defined
1400 in the xcb_event_mask_t enumeration in the "xproto.h" header file. If we wanted to register for several
1401 event types, we can logically "or" them, as follows:
1404 mask = XCB_CW_EVENT_MASK;
1405 valwin[0] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS;
1406 win = xcb_generate_id (c);
1407 xcb_create_window (c, depth, win, root->root,
1409 XCB_WINDOW_CLASS_INPUT_OUTPUT, root->root_visual,
1413 This registers for <span class="code">Expose</span> events as
1414 well as for mouse button presses inside the created
1415 window. You should note that a mask may represent several
1419 The values that a mask could take are given
1420 by the <span class="code">xcb_cw_t</span> enumeration:
1424 XCB_CW_BACK_PIXMAP = 1L<<0,
1425 XCB_CW_BACK_PIXEL = 1L<<1,
1426 XCB_CW_BORDER_PIXMAP = 1L<<2,
1427 XCB_CW_BORDER_PIXEL = 1L<<3,
1428 XCB_CW_BIT_GRAVITY = 1L<<4,
1429 XCB_CW_WIN_GRAVITY = 1L<<5,
1430 XCB_CW_BACKING_STORE = 1L<<6,
1431 XCB_CW_BACKING_PLANES = 1L<<7,
1432 XCB_CW_BACKING_PIXEL = 1L<<8,
1433 XCB_CW_OVERRIDE_REDIRECT = 1L<<9,
1434 XCB_CW_SAVE_UNDER = 1L<<10,
1435 XCB_CW_EVENT_MASK = 1L<<11,
1436 XCB_CW_DONT_PROPAGATE = 1L<<12,
1437 XCB_CW_COLORMAP = 1L<<13,
1438 XCB_CW_CURSOR = 1L<<14
1442 <p>Note: we must be careful when setting the values of the valwin
1443 parameter, as they have to follow the order the
1444 <span class="code">xcb_cw_t</span> enumeration. Here is an
1449 mask = XCB_CW_EVENT_MASK | XCB_CW_BACK_PIXMAP;
1450 valwin[0] = XCB_NONE; /* for XCB_CW_BACK_PIXMAP (whose value is 1) */
1451 valwin[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS; /* for XCB_CW_EVENT_MASK, whose value (2048) */
1452 /* is greater than the one of XCB_CW_BACK_PIXMAP */
1455 If the window has already been created, we can use the
1456 <span class="code">xcb_change_window_attributes()</span> function to set
1457 the events that the window will receive. The subsection
1458 <a href="#winconf">Configuring a window</a> shows its
1459 prototype. As an example, here is a piece of code that
1460 configures the window to receive the
1461 <span class="code">Expose</span> and
1462 <span class="code">ButtonPress</span> events:
1465 const static uint32_t values[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS };
1467 /* The connection c and the window win are supposed to be defined */
1469 xcb_change_window_attributes (c, win, XCB_CW_EVENT_MASK, values);
1473 Note: A common bug programmers have is adding code to handle new
1474 event types in their program, while forgetting to add the
1475 masks for these events in the creation of the window. Such a
1476 programmer would then sit there for hours debugging their
1477 program, wondering "Why doesn't my program notice that I
1478 released the button?", only to find that they registered for
1479 button press events but not for button release events.
1482 <li class="subtitle"><a name="loop">Receiving events: writing the events loop</a>
1484 After we have registered for the event types we are interested
1485 in, we need to enter a loop of receiving events and handling
1486 them. There are two ways to receive events: a blocking way and
1491 <span class="code">xcb_wait_for_event (xcb_connection_t *c)</span>
1492 is the blocking way. It waits (so blocks...) until an event is
1493 queued in the X server. Then it retrieves it into a newly
1494 allocated structure (it dequeues it from the queue) and returns
1495 it. This structure has to be freed. The function returns
1496 <span class="code">NULL</span> if an error occurs.
1500 <span class="code">xcb_poll_for_event (xcb_connection_t *c, int
1501 *error)</span> is the non-blocking way. It looks at the event
1502 queue and returns (and dequeues too) an existing event into
1503 a newly allocated structure. This structure has to be
1504 freed. It returns <span class="code">NULL</span> if there is
1505 no event. If an error occurs, the parameter <span
1506 class="code">error</span> will be filled with the error
1510 There are various ways to write such a loop. We present two
1511 ways to write such a loop, with the two functions above. The
1512 first one uses <span class="code">xcb_wait_for_event_t</span>, which
1513 is similar to an event Xlib loop using only <span
1514 class="code">XNextEvent</span>:
1517 xcb_generic_event_t *e;
1519 while ((e = xcb_wait_for_event (c))) {
1520 switch (e->response_type & ~0x80) {
1522 /* Handle the Expose event type */
1523 xcb_expose_event_t *ev = (xcb_expose_event_t *)e;
1529 case XCB_BUTTON_PRESS: {
1530 /* Handle the ButtonPress event type */
1531 xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e;
1538 /* Unknown event type, ignore it */
1542 /* Free the Generic Event */
1547 You will certainly want to use <span
1548 class="code">xcb_poll_for_event(xcb_connection_t *c, int
1549 *error)</span> if, in Xlib, you use <span
1550 class="code">XPending</span> or
1551 <span class="code">XCheckMaskEvent</span>:
1554 while (XPending (display)) {
1557 XNextEvent(d, &ev);
1559 /* Manage your event */
1563 Such a loop in XCB looks like:
1566 xcb_generic_event_t *ev;
1568 while ((ev = xcb_poll_for_event (conn, 0))) {
1569 /* Manage your event */
1573 The events are managed in the same way as with <span
1574 class="code">xcb_wait_for_event_t</span>.
1575 Obviously, we will need to give the user some way of
1576 terminating the program. This is usually done by handling a
1577 special "quit" event, as we will soon see.
1590 <li>xcb_wait_for_event ()
1596 <li>XCheckMaskEvent ()
1601 <li>xcb_poll_for_event ()
1606 <li class="subtitle"><a name="expose">Expose events</a>
1608 The <span class="code">Expose</span> event is one of the most
1609 basic (and most used) events an application may receive. It
1610 will be sent to us in one of several cases:
1613 <li>A window that covered part of our window has moved
1614 away, exposing part (or all) of our window.
1615 <li>Our window was raised above other windows.
1616 <li>Our window mapped for the first time.
1617 <li>Our window was de-iconified.
1620 You should note the implicit assumption hidden here: the
1621 contents of our window is lost when it is being obscured
1622 (covered) by either windows. One may wonder why the X server
1623 does not save this contents. The answer is: to save
1624 memory. After all, the number of windows on a display at a
1625 given time may be very large, and storing the contents of all
1626 of them might require a lot of memory. Actually, there is a
1627 way to tell the X server to store the contents of a window in
1628 special cases, as we will see later.
1631 When we get an <span class="code">Expose</span> event, we
1632 should take the event's data from the members of the following
1637 uint8_t response_type; /* The type of the event, here it is XCB_EXPOSE */
1640 xcb_window_t window; /* The Id of the window that receives the event (in case */
1641 /* our application registered for events on several windows */
1642 uint16_t x; /* The x coordinate of the top-left part of the window that needs to be redrawn */
1643 uint16_t y; /* The y coordinate of the top-left part of the window that needs to be redrawn */
1644 uint16_t width; /* The width of the part of the window that needs to be redrawn */
1645 uint16_t height; /* The height of the part of the window that needs to be redrawn */
1647 } xcb_expose_event_t;
1649 <li class="subtitle"><a name="userinput">Getting user input</a>
1651 User input traditionally comes from two sources: the mouse
1652 and the keyboard. Various event types exist to notify us of
1653 user input (a key being presses on the keyboard, a key being
1654 released on the keyboard, the mouse moving over our window,
1655 the mouse entering (or leaving) our window, and so on.
1658 <li class="subsubtitle"><a name="mousepressrelease">Mouse button press and release events</a>
1660 The first event type we will deal with is a mouse
1661 button-press (or button-release) event in our window. In
1662 order to register to such an event type, we should add one
1663 (or more) of the following masks when we create our window:
1666 <li><span class="code">XCB_EVENT_MASK_BUTTON_PRESS</span>: notify us
1667 of any button that was pressed in one of our windows.
1668 <li><span class="code">XCB_EVENT_MASK_BUTTON_RELEASE</span>: notify us
1669 of any button that was released in one of our windows.
1672 The structure to be checked for in our events loop is the
1673 same for these two events, and is the following:
1677 uint8_t response_type; /* The type of the event, here it is xcb_button_press_event_t or xcb_button_release_event_t */
1678 xcb_button_t detail;
1680 xcb_timestamp_t time; /* Time, in milliseconds the event took place in */
1686 int16_t event_x; /* The x coordinate where the mouse has been pressed in the window */
1687 int16_t event_y; /* The y coordinate where the mouse has been pressed in the window */
1688 uint16_t state; /* A mask of the buttons (or keys) during the event */
1689 uint8_t same_screen;
1690 } xcb_button_press_event_t;
1692 typedef xcb_button_press_event_t xcb_button_release_event_t;
1695 The <span class="code">time</span> field may be used to calculate "double-click"
1696 situations by an application (e.g. if the mouse button was
1697 clicked two times in a duration shorter than a given amount
1698 of time, assume this was a double click).
1701 The <span class="code">state</span> field is a mask of the buttons held down during
1702 the event. It is a bitwise OR of any of the following (from the xcb_button_mask_t and
1703 xcb_mod_mask_t enumerations):
1706 <li><span class="code">XCB_BUTTON_MASK_1</span>
1707 <li><span class="code">XCB_BUTTON_MASK_2</span>
1708 <li><span class="code">XCB_BUTTON_MASK_3</span>
1709 <li><span class="code">XCB_BUTTON_MASK_4</span>
1710 <li><span class="code">XCB_BUTTON_MASK_5</span>
1711 <li><span class="code">XCB_MOD_MASK_SHIFT</span>
1712 <li><span class="code">XCB_MOD_MASK_LOCK</span>
1713 <li><span class="code">XCB_MOD_MASK_CONTROL</span>
1714 <li><span class="code">XCB_MOD_MASK_1</span>
1715 <li><span class="code">XCB_MOD_MASK_2</span>
1716 <li><span class="code">XCB_MOD_MASK_3</span>
1717 <li><span class="code">XCB_MOD_MASK_4</span>
1718 <li><span class="code">XCB_MOD_MASK_5</span>
1721 Their names are self explanatory, where the first 5 refer to
1722 the mouse buttons that are being pressed, while the rest
1723 refer to various "special keys" that are being pressed (Mod1
1724 is usually the 'Alt' key or the 'Meta' key).
1727 <b>TODO:</b> Problem: it seems that the state does not
1728 change when clicking with various buttons.
1730 <li class="subsubtitle"><a name="mousemvnt">Mouse movement events</a>
1732 Similar to mouse button press and release events, we also
1733 can be notified of various mouse movement events. These can
1734 be split into two families. One is of mouse pointer
1735 movement while no buttons are pressed, and the second is a
1736 mouse pointer motion while one (or more) of the buttons are
1737 pressed (this is sometimes called "a mouse drag operation",
1738 or just "dragging"). The following event masks may be added
1739 during the creation of our window:
1742 <li><span class="code">XCB_EVENT_MASK_POINTER_MOTION</span>: events of
1743 the pointer moving in one of the windows controlled by our
1744 application, while no mouse button is held pressed.
1745 <li><span class="code">XCB_EVENT_MASK_BUTTON_MOTION</span>: Events of
1746 the pointer moving while one or more of the mouse buttons
1748 <li><span class="code">XCB_EVENT_MASK_BUTTON_1_MOTION</span>: same as
1749 <span class="code">XCB_EVENT_MASK_BUTTON_MOTION</span>, but only when
1750 the 1st mouse button is held pressed.
1751 <li><span class="code">XCB_EVENT_MASK_BUTTON_2_MOTION</span>,
1752 <span class="code">XCB_EVENT_MASK_BUTTON_3_MOTION</span>,
1753 <span class="code">XCB_EVENT_MASK_BUTTON_4_MOTION</span>,
1754 <span class="code">XCB_EVENT_MASK_BUTTON_5_MOTION</span>: same as
1755 <span class="code">XCB_EVENT_MASK_BUTTON_1_MOTION</span>, but
1756 respectively for 2nd, 3rd, 4th and 5th mouse button.
1759 The structure to be checked for in our events loop is the
1760 same for these events, and is the following:
1764 uint8_t response_type; /* The type of the event */
1767 xcb_timestamp_t time; /* Time, in milliseconds the event took place in */
1773 int16_t event_x; /* The x coordinate of the mouse when the event was generated */
1774 int16_t event_y; /* The y coordinate of the mouse when the event was generated */
1775 uint16_t state; /* A mask of the buttons (or keys) during the event */
1776 uint8_t same_screen;
1777 } xcb_motion_notify_event_t;
1779 <li class="subsubtitle"><a name="mouseenter">Mouse pointer enter and leave events</a>
1781 Another type of event that applications might be interested
1782 in, is a mouse pointer entering a window the program
1783 controls, or leaving such a window. Some programs use these
1784 events to show the user that the application is now in
1785 focus. In order to register for such an event type, we
1786 should add one (or more) of the following masks when we
1790 <li><span class="code">xcb_event_enter_window_t</span>: notify us
1791 when the mouse pointer enters any of our controlled
1793 <li><span class="code">xcb_event_leave_window_t</span>: notify us
1794 when the mouse pointer leaves any of our controlled
1798 The structure to be checked for in our events loop is the
1799 same for these two events, and is the following:
1803 uint8_t response_type; /* The type of the event */
1806 xcb_timestamp_t time; /* Time, in milliseconds the event took place in */
1812 int16_t event_x; /* The x coordinate of the mouse when the event was generated */
1813 int16_t event_y; /* The y coordinate of the mouse when the event was generated */
1814 uint16_t state; /* A mask of the buttons (or keys) during the event */
1815 uint8_t mode; /* The number of mouse button that was clicked */
1816 uint8_t same_screen_focus;
1817 } xcb_enter_notify_event_t;
1819 typedef xcb_enter_notify_event_t xcb_leave_notify_event_t;
1821 <li class="subsubtitle"><a name="focus">The keyboard focus</a>
1823 There may be many windows on a screen, but only a single
1824 keyboard attached to them. How does the X server then know
1825 which window should be sent a given keyboard input ? This is
1826 done using the keyboard focus. Only a single window on the
1827 screen may have the keyboard focus at a given time. There
1828 is a XCB function that allows a program to set the keyboard
1829 focus to a given window. The user can usually set the
1830 keyboard focus using the window manager (often by clicking
1831 on the title bar of the desired window). Once our window
1832 has the keyboard focus, every key press or key release will
1833 cause an event to be sent to our program (if it registered
1834 for these event types...).
1836 <li class="subsubtitle"><a name="keypress">Keyboard press and release events</a>
1838 If a window controlled by our program currently holds the
1839 keyboard focus, it can receive key press and key release
1840 events. So, we should add one (or more) of the following
1841 masks when we create our window:
1844 <li><span class="code">XCB_EVENT_MASK_KEY_PRESS</span>: notify us when
1845 a key was pressed while any of our controlled windows had
1847 <li><span class="code">XCB_EVENT_MASK_KEY_RELEASE</span>: notify us
1848 when a key was released while any of our controlled
1849 windows had the keyboard focus.
1852 The structure to be checked for in our events loop is the
1853 same for these two events, and is the following:
1857 uint8_t response_type; /* The type of the event */
1858 xcb_keycode_t detail;
1860 xcb_timestamp_t time; /* Time, in milliseconds the event took place in */
1869 uint8_t same_screen;
1870 } xcb_key_press_event_t;
1872 typedef xcb_key_press_event_t xcb_key_release_event_t;
1875 The <span class="code">detail</span> field refers to the
1876 physical key on the keyboard.
1879 <b>TODO:</b> Talk about getting the ASCII code from the key code.
1882 <li class="subtitle"><a name="eventex">X events: a complete example</a>
1884 As an example for handling events, we show a program that
1885 creates a window, enters an events loop and checks for all the
1886 events described above, and writes on the terminal the relevant
1887 characteristics of the event. With this code, it should be
1888 easy to add drawing operations, like those which have been
1892 #include <stdlib.h>
1893 #include <stdio.h>
1895 #include <xcb/xcb.h>
1898 print_modifiers (uint32_t mask)
1900 const char **mod, *mods[] = {
1901 "Shift", "Lock", "Ctrl", "Alt",
1902 "Mod2", "Mod3", "Mod4", "Mod5",
1903 "Button1", "Button2", "Button3", "Button4", "Button5"
1905 printf ("Modifier mask: ");
1906 for (mod = mods ; mask; mask >>= 1, mod++)
1915 xcb_connection_t *c;
1916 xcb_screen_t *screen;
1918 xcb_generic_event_t *e;
1922 /* Open the connection to the X server */
1923 c = xcb_connect (NULL, NULL);
1925 /* Get the first screen */
1926 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
1928 /* Ask for our window's Id */
1929 win = xcb_generate_id (c);
1931 /* Create the window */
1932 mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
1933 values[0] = screen->white_pixel;
1934 values[1] = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS |
1935 XCB_EVENT_MASK_BUTTON_RELEASE | XCB_EVENT_MASK_POINTER_MOTION |
1936 XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW |
1937 XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE;
1938 xcb_create_window (c, /* Connection */
1940 win, /* window Id */
1941 screen->root, /* parent window */
1943 150, 150, /* width, height */
1944 10, /* border_width */
1945 XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
1946 screen->root_visual, /* visual */
1947 mask, values); /* masks */
1949 /* Map the window on the screen */
1950 xcb_map_window (c, win);
1954 while ((e = xcb_wait_for_event (c))) {
1955 switch (e->response_type & ~0x80) {
1957 xcb_expose_event_t *ev = (xcb_expose_event_t *)e;
1959 printf ("Window %ld exposed. Region to be redrawn at location (%d,%d), with dimension (%d,%d)\n",
1960 ev->window, ev->x, ev->y, ev->width, ev->height);
1963 case XCB_BUTTON_PRESS: {
1964 xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e;
1965 print_modifiers(ev->state);
1967 switch (ev->detail) {
1969 printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n",
1970 ev->event, ev->event_x, ev->event_y);
1973 printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n",
1974 ev->event, ev->event_x, ev->event_y);
1977 printf ("Button %d pressed in window %ld, at coordinates (%d,%d)\n",
1978 ev->detail, ev->event, ev->event_x, ev->event_y);
1982 case XCB_BUTTON_RELEASE: {
1983 xcb_button_release_event_t *ev = (xcb_button_release_event_t *)e;
1984 print_modifiers(ev->state);
1986 printf ("Button %d released in window %ld, at coordinates (%d,%d)\n",
1987 ev->detail, ev->event, ev->event_x, ev->event_y);
1990 case XCB_MOTION_NOTIFY: {
1991 xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)e;
1993 printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n",
1994 ev->event, ev->event_x, ev->event_y);
1997 case XCB_ENTER_NOTIFY: {
1998 xcb_enter_notify_event_t *ev = (xcb_enter_notify_event_t *)e;
2000 printf ("Mouse entered window %ld, at coordinates (%d,%d)\n",
2001 ev->event, ev->event_x, ev->event_y);
2004 case XCB_LEAVE_NOTIFY: {
2005 xcb_leave_notify_event_t *ev = (xcb_leave_notify_event_t *)e;
2007 printf ("Mouse left window %ld, at coordinates (%d,%d)\n",
2008 ev->event, ev->event_x, ev->event_y);
2011 case XCB_KEY_PRESS: {
2012 xcb_key_press_event_t *ev = (xcb_key_press_event_t *)e;
2013 print_modifiers(ev->state);
2015 printf ("Key pressed in window %ld\n",
2019 case XCB_KEY_RELEASE: {
2020 xcb_key_release_event_t *ev = (xcb_key_release_event_t *)e;
2021 print_modifiers(ev->state);
2023 printf ("Key released in window %ld\n",
2028 /* Unknown event type, ignore it */
2029 printf("Unknown event: %d\n", e->response_type);
2032 /* Free the Generic Event */
2040 <li class="title"><a name="font">Handling text and fonts</a>
2042 Besides drawing graphics on a window, we often want to draw
2043 text. Text strings have two major properties: the characters to
2044 be drawn and the font with which they are drawn. In order to
2045 draw text, we need to first request the X server to load a
2046 font. We then assign a font to a Graphic Context, and finally, we
2047 draw the text in a window, using the Graphic Context.
2050 <li class="subtitle"><a name="fontstruct">The Font structure</a>
2052 In order to support flexible fonts, a font type is
2053 defined. You know what ? It's an Id:
2056 typedef uint32_t xcb_font_t;
2059 It is used to contain information about a font, and is passed
2060 to several functions that handle fonts selection and text drawing.
2061 We ask the X server to attribute an Id to our font with the
2065 xcb_font_t xcb_generate_id (xcb_connection_t *c);
2068 <li class="subtitle"><a name="openingfont">Opening a Font</a>
2070 To open a font, we use the following function:
2073 xcb_void_cookie_t xcb_open_font (xcb_connection_t *c,
2079 The <span class="code">fid</span> parameter is the font Id
2080 defined by <span class="code">xcb_generate_id()</span> (see
2081 above). The <span class="code">name</span> parameter is the
2082 name of the font you want to open. Use the command
2083 <span class="code">xlsfonts</span> in a terminal to know which
2084 are the fonts available on your computer. The parameter
2085 <span class="code">name_len</span> is the length of the name
2086 of the font (given by <span class="code">strlen()</span>).
2088 <li class="subtitle"><a name="assigningfont">Assigning a Font to a Graphic Context</a>
2090 Once a font is opened, you have to create a Graphic Context
2091 that will contain the informations about the color of the
2092 foreground and the background used when you draw a text in a
2093 Drawable. Here is an example of a Graphic Context that will
2094 allow us to draw an opened font with a black foreground and a
2099 * c is the connection
2100 * screen is the screen where the window is displayed
2101 * window is the window in which we will draw the text
2102 * font is the opened font
2105 uint32_t value_list[3];
2109 gc = xcb_generate_id (c);
2110 mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
2111 value_list[0] = screen->black_pixel;
2112 value_list[1] = screen->white_pixel;
2113 value_list[2] = font;
2114 xcb_create_gc (c, gc, window, mask, value_list);
2116 /* The font is not needed anymore, so we close it */
2117 xcb_close_font (c, font);
2119 <li class="subtitle"><a name="drawingtext">Drawing text in a drawable</a>
2121 To draw a text in a drawable, we use the following function:
2124 xcb_void_cookie_t xcb_image_text_8 (xcb_connection_t *c,
2126 xcb_drawable_t drawable,
2130 const char *string);
2133 The <span class="code">string</span> parameter is the text to
2134 draw. The location of the drawing is given by the parameters
2135 <span class="code">x</span> and <span class="code">y</span>.
2136 The base line of the text is exactly the parameter
2137 <span class="code">y</span>.
2139 <li class="subtitle"><a name="fontcompleteexample">Complete example</a>
2141 This example draw a text at 10 pixels (for the base line) of
2142 the bottom of a window. Pressing the Esc key exits the program.
2145 #include <stdlib.h>
2146 #include <stdio.h>
2147 #include <string.h>
2149 #include <xcb/xcb.h>
2156 static xcb_gc_t gc_font_get (xcb_connection_t *c,
2157 xcb_screen_t *screen,
2158 xcb_window_t window,
2159 const char *font_name);
2161 static void text_draw (xcb_connection_t *c,
2162 xcb_screen_t *screen,
2163 xcb_window_t window,
2169 text_draw (xcb_connection_t *c,
2170 xcb_screen_t *screen,
2171 xcb_window_t window,
2176 xcb_void_cookie_t cookie_gc;
2177 xcb_void_cookie_t cookie_text;
2178 xcb_generic_error_t *error;
2182 length = strlen (label);
2184 gc = gc_font_get(c, screen, window, "7x13");
2186 cookie_text = xcb_image_text_8_checked (c, length, window, gc,
2189 error = xcb_request_check (c, cookie_text);
2191 fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
2196 cookie_gc = xcb_free_gc (c, gc);
2197 error = xcb_request_check (c, cookie_gc);
2199 fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
2206 gc_font_get (xcb_connection_t *c,
2207 xcb_screen_t *screen,
2208 xcb_window_t window,
2209 const char *font_name)
2211 uint32_t value_list[3];
2212 xcb_void_cookie_t cookie_font;
2213 xcb_void_cookie_t cookie_gc;
2214 xcb_generic_error_t *error;
2219 font = xcb_generate_id (c);
2220 cookie_font = xcb_open_font_checked (c, font,
2224 error = xcb_request_check (c, cookie_font);
2226 fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
2231 gc = xcb_generate_id (c);
2232 mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
2233 value_list[0] = screen->black_pixel;
2234 value_list[1] = screen->white_pixel;
2235 value_list[2] = font;
2236 cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list);
2237 error = xcb_request_check (c, cookie_gc);
2239 fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
2244 cookie_font = xcb_close_font_checked (c, font);
2245 error = xcb_request_check (c, cookie_font);
2247 fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
2257 xcb_screen_iterator_t screen_iter;
2258 xcb_connection_t *c;
2259 const xcb_setup_t *setup;
2260 xcb_screen_t *screen;
2261 xcb_generic_event_t *e;
2262 xcb_generic_error_t *error;
2263 xcb_void_cookie_t cookie_window;
2264 xcb_void_cookie_t cookie_map;
2265 xcb_window_t window;
2270 /* getting the connection */
2271 c = xcb_connect (NULL, &screen_number);
2273 fprintf (stderr, "ERROR: can't connect to an X server\n");
2277 /* getting the current screen */
2278 setup = xcb_get_setup (c);
2281 screen_iter = xcb_setup_roots_iterator (setup);
2282 for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter))
2283 if (screen_number == 0)
2285 screen = screen_iter.data;
2289 fprintf (stderr, "ERROR: can't get the current screen\n");
2294 /* creating the window */
2295 window = xcb_generate_id (c);
2296 mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
2297 values[0] = screen->white_pixel;
2299 XCB_EVENT_MASK_KEY_RELEASE |
2300 XCB_EVENT_MASK_BUTTON_PRESS |
2301 XCB_EVENT_MASK_EXPOSURE |
2302 XCB_EVENT_MASK_POINTER_MOTION;
2303 cookie_window = xcb_create_window_checked (c,
2305 window, screen->root,
2306 20, 200, WIDTH, HEIGHT,
2307 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
2308 screen->root_visual,
2310 cookie_map = xcb_map_window_checked (c, window);
2312 /* error managing */
2313 error = xcb_request_check (c, cookie_window);
2315 fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code);
2319 error = xcb_request_check (c, cookie_map);
2321 fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code);
2329 e = xcb_poll_for_event(c);
2331 switch (e->response_type & ~0x80) {
2335 text = "Press ESC key to exit...";
2336 text_draw (c, screen, window, 10, HEIGHT - 10, text);
2339 case XCB_KEY_RELEASE: {
2340 xcb_key_release_event_t *ev;
2342 ev = (xcb_key_release_event_t *)e;
2344 switch (ev->detail) {
2361 <li class="title"><a name="wm">Interacting with the window manager</a>
2363 After we have seen how to create windows and draw on them, we
2364 take one step back, and look at how our windows are interacting
2365 with their environment (the full screen and the other
2366 windows). First of all, our application needs to interact with
2367 the window manager. The window manager is responsible to
2368 decorating drawn windows (i.e. adding a frame, an iconify
2369 button, a system menu, a title bar, etc), as well as handling
2370 icons shown when windows are being iconified. It also handles
2371 ordering of windows on the screen, and other administrative
2372 tasks. We need to give it various hints as to how we want it to
2373 treat our application's windows.
2376 <li class="subtitle"><a name="wmprop">Window properties</a>
2378 Many of the parameters communicated to the window manager are
2379 passed using data called "properties". These properties are
2380 attached by the X server to different windows, and are stored
2381 in a format that makes it possible to read them from different
2382 machines that may use different architectures (remember that
2383 an X client program may run on a remote machine).
2386 The property and its type (a string, an integer, etc) are
2387 Id. Their type are <span class="code">xcb_atom_t</span>:
2390 typedef uint32_t xcb_atom_t;
2393 To change the property of a window, we use the following
2397 xcb_void_cookie_t xcb_change_property (xcb_connection_t *c, /* Connection to the X server */
2398 uint8_t mode, /* Property mode */
2399 xcb_window_t window, /* Window */
2400 xcb_atom_t property, /* Property to change */
2401 xcb_atom_t type, /* Type of the property */
2402 uint8_t format, /* Format of the property (8, 16, 32) */
2403 uint32_t data_len, /* Length of the data parameter */
2404 const void *data); /* Data */
2407 The <span class="code">mode</span> parameter could be one of
2408 the following values (defined in enumeration xcb_prop_mode_t in
2409 the xproto.h header file):
2412 <li>XCB_PROP_MODE_REPLACE
2413 <li>XCB_PROP_MODE_PREPEND
2414 <li>XCB_PROP_MODE_APPEND
2417 <li class="subtitle"><a name="wmname">Setting the window name and icon name</a>
2419 The first thing we want to do would be to set the name for our
2420 window. This is done using the
2421 <span class="code">xcb_change_property()</span> function. This
2422 name may be used by the window manager as the title of the
2423 window (in the title bar), in a task list, etc. The property
2424 atom to use to set the name of a window is
2425 <span class="code">WM_NAME</span> (and
2426 <span class="code">WM_ICON_NAME</span> for the iconified
2427 window) and its type is <span class="code">STRING</span>. Here
2428 is an example of utilization:
2431 #include <string.h>
2433 #include <xcb/xcb.h>
2434 #include <xcb/xcb_atom.h>
2439 xcb_connection_t *c;
2440 xcb_screen_t *screen;
2442 char *title = "Hello World !";
2443 char *title_icon = "Hello World ! (iconified)";
2447 /* Open the connection to the X server */
2448 c = xcb_connect (NULL, NULL);
2450 /* Get the first screen */
2451 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
2453 /* Ask for our window's Id */
2454 win = xcb_generate_id (c);
2456 /* Create the window */
2457 xcb_create_window (c, /* Connection */
2459 win, /* window Id */
2460 screen->root, /* parent window */
2462 250, 150, /* width, height */
2463 10, /* border_width */
2464 XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */
2465 screen->root_visual, /* visual */
2466 0, NULL); /* masks, not used */
2468 /* Set the title of the window */
2469 xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
2471 strlen (title), title);
2473 /* Set the title of the window icon */
2474 xcb_change_property (c, XCB_PROP_MODE_REPLACE, win,
2475 WM_ICON_NAME, STRING, 8,
2476 strlen(title_icon), title_icon);
2478 /* Map the window on the screen */
2479 xcb_map_window (c, win);
2489 <p>Note: the use of the atoms needs our program to be compiled
2490 and linked against xcb_atom, so that we have to use
2494 gcc prog.c -o prog `pkg-config --cflags --libs xcb_atom`
2498 for the program to compile fine.
2502 <li class="title"><a name="winop">Simple window operations</a>
2504 One more thing we can do to our window is manipulate them on the
2505 screen (resize them, move them, raise or lower them, iconify
2506 them, and so on). Some window operations functions are supplied
2507 by XCB for this purpose.
2510 <li class="subtitle"><a name="winmap">Mapping and un-mapping a window</a>
2512 The first pair of operations we can apply on a window is
2513 mapping it, or un-mapping it. Mapping a window causes the
2514 window to appear on the screen, as we have seen in our simple
2515 window program example. Un-mapping it causes it to be removed
2516 from the screen (although the window as a logical entity still
2517 exists). This gives the effect of making a window hidden
2518 (unmapped) and shown again (mapped). For example, if we have a
2519 dialog box window in our program, instead of creating it every
2520 time the user asks to open it, we can create the window once,
2521 in an un-mapped mode, and when the user asks to open it, we
2522 simply map the window on the screen. When the user clicked the
2523 'OK' or 'Cancel' button, we simply un-map the window. This is
2524 much faster than creating and destroying the window, however,
2525 the cost is wasted resources, both on the client side, and on
2529 To map a window, you use the following function:
2532 xcb_void_cookie_t xcb_map_window (xcb_connection_t *c,
2533 xcb_window_t window);
2536 To have a simple example, see the <a href="#helloworld">example</a>
2537 above. The mapping operation will cause an
2538 <span class="code">Expose</span> event to be sent to our
2539 application, unless the window is completely covered by other
2543 Un-mapping a window is also simple. You use the function
2546 xcb_void_cookie_t xcb_unmap_window (xcb_connection_t *c,
2547 xcb_window_t window);
2550 The utilization of this function is the same as
2551 <span class="code">xcb_map_window()</span>.
2553 <li class="subtitle"><a name="winconf">Configuring a window</a>
2555 As we have seen when we have created our first window, in the
2556 X Events subsection, we can set some attributes for the window
2557 (that is, the position, the size, the events the window will
2558 receive, etc). If we want to modify them, but the window is
2559 already created, we can change them by using the following
2563 xcb_void_cookie_t xcb_configure_window (xcb_connection_t *c, /* The connection to the X server*/
2564 xcb_window_t window, /* The window to configure */
2565 uint16_t value_mask, /* The mask */
2566 const uint32_t *value_list); /* The values to set */
2569 We set the <span class="code">value_mask</span> to one or
2570 several mask values that are in the xcb_config_window_t enumeration in the xproto.h header:
2573 <li><span class="code">XCB_CONFIG_WINDOW_X</span>: new x coordinate of the window's top left corner
2574 <li><span class="code">XCB_CONFIG_WINDOW_Y</span>: new y coordinate of the window's top left corner
2575 <li><span class="code">XCB_CONFIG_WINDOW_WIDTH</span>: new width of the window
2576 <li><span class="code">XCB_CONFIG_WINDOW_HEIGHT</span>: new height of the window
2577 <li><span class="code">XCB_CONFIG_WINDOW_BORDER_WIDTH</span>: new width of the border of the window
2578 <li><span class="code">XCB_CONFIG_WINDOW_SIBLING</span>
2579 <li><span class="code">XCB_CONFIG_WINDOW_STACK_MODE</span>: the new stacking order
2582 We then give to <span class="code">value_mask</span> the new
2583 value. We now describe how to use
2584 <span class="code">xcb_configure_window_t</span> in some useful
2587 <li class="subtitle"><a name="winmove">Moving a window around the screen</a>
2589 An operation we might want to do with windows is to move them
2590 to a different location. This can be done like this:
2593 const static uint32_t values[] = { 10, 20 };
2595 /* The connection c and the window win are supposed to be defined */
2597 /* Move the window to coordinates x = 10 and y = 20 */
2598 xcb_configure_window (c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values);
2601 Note that when the window is moved, it might get partially
2602 exposed or partially hidden by other windows, and thus we
2603 might get <span class="code">Expose</span> events due to this
2606 <li class="subtitle"><a name="winsize">Resizing a window</a>
2608 Yet another operation we can do is to change the size of a
2609 window. This is done using the following code:
2612 const static uint32_t values[] = { 200, 300 };
2614 /* The connection c and the window win are supposed to be defined */
2616 /* Resize the window to width = 10 and height = 20 */
2617 xcb_configure_window (c, win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
2620 We can also combine the move and resize operations using one
2621 single call to <span class="code">xcb_configure_window_t</span>:
2624 const static uint32_t values[] = { 10, 20, 200, 300 };
2626 /* The connection c and the window win are supposed to be defined */
2628 /* Move the window to coordinates x = 10 and y = 20 */
2629 /* and resize the window to width = 10 and height = 20 */
2630 xcb_configure_window (c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values);
2632 <li class="subtitle"><a name="winstack">Changing windows stacking order: raise and lower</a>
2634 Until now, we changed properties of a single window. We'll see
2635 that there are properties that relate to the window and other
2636 windows. One of them is the stacking order. That is, the order
2637 in which the windows are layered on top of each other. The
2638 front-most window is said to be on the top of the stack, while
2639 the back-most window is at the bottom of the stack. Here is
2640 how to manipulate our windows stack order:
2643 const static uint32_t values[] = { XCB_STACK_MODE_ABOVE };
2645 /* The connection c and the window win are supposed to be defined */
2647 /* Move the window on the top of the stack */
2648 xcb_configure_window (c, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
2651 const static uint32_t values[] = { XCB_STACK_MODE_BELOW };
2653 /* The connection c and the window win are supposed to be defined */
2655 /* Move the window on the bottom of the stack */
2656 xcb_configure_window (c, win, XCB_CONFIG_WINDOW_STACK_MODE, values);
2658 <li class="subtitle"><a name="wingetinfo">Getting information about a window</a>
2660 Just like we can set various attributes of our windows, we can
2661 also ask the X server supply the current values of these
2662 attributes. For example, we can check where a window is
2663 located on the screen, what is its current size, whether it is
2664 mapped or not, etc. The structure that contains some of this
2669 uint8_t response_type;
2670 uint8_t depth; /* depth of the window */
2673 xcb_window_t root; /* Id of the root window *>
2674 int16_t x; /* X coordinate of the window's location */
2675 int16_t y; /* Y coordinate of the window's location */
2676 uint16_t width; /* Width of the window */
2677 uint16_t height; /* Height of the window */
2678 uint16_t border_width; /* Width of the window's border */
2679 } xcb_get_geometry_reply_t;
2682 XCB fill this structure with two functions:
2685 xcb_get_geometry_cookie_t xcb_get_geometry (xcb_connection_t *c,
2686 xcb_drawable_t drawable);
2687 xcb_get_geometry_reply_t *xcb_get_geometry_reply (xcb_connection_t *c,
2688 xcb_get_geometry_cookie_t cookie,
2689 xcb_generic_error_t **e);
2692 You use them as follows:
2695 xcb_connection_t *c;
2697 xcb_get_geometry_reply_t *geom;
2699 /* You initialize c and win */
2701 geom = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL);
2703 /* Do something with the fields of geom */
2708 Remark that you have to free the structure, as
2709 <span class="code">xcb_get_geometry_reply_t</span> allocates a
2713 One problem is that the returned location of the window is
2714 relative to its parent window. This makes these coordinates
2715 rather useless for any window manipulation functions, like
2716 moving it on the screen. In order to overcome this problem, we
2717 need to take a two-step operation. First, we find out the Id
2718 of the parent window of our window. We then translate the
2719 above relative coordinates to the screen coordinates.
2722 To get the Id of the parent window, we need this structure:
2726 uint8_t response_type;
2731 xcb_window_t parent; /* Id of the parent window */
2732 uint16_t children_len;
2734 } xcb_query_tree_reply_t;
2737 To fill this structure, we use these two functions:
2740 xcb_query_tree_cookie_t xcb_query_tree (xcb_connection_t *c,
2741 xcb_window_t window);
2742 xcb_query_tree_reply_t *xcb_query_tree_reply (xcb_connection_t *c,
2743 xcb_query_tree_cookie_t cookie,
2744 xcb_generic_error_t **e);
2747 The translated coordinates will be found in this structure:
2751 uint8_t response_type;
2752 uint8_t same_screen;
2756 uint16_t dst_x; /* Translated x coordinate */
2757 uint16_t dst_y; /* Translated y coordinate */
2758 } xcb_translate_coordinates_reply_t;
2761 As usual, we need two functions to fill this structure:
2764 xcb_translate_coordinates_cookie_t xcb_translate_coordinates (xcb_connection_t *c,
2765 xcb_window_t src_window,
2766 xcb_window_t dst_window,
2769 xcb_translate_coordinates_reply_t *xcb_translate_coordinates_reply (xcb_connection_t *c,
2770 xcb_translate_coordinates_cookie_t cookie,
2771 xcb_generic_error_t **e);
2774 We use them as follows:
2777 xcb_connection_t *c;
2779 xcb_get_geometry_reply_t *geom;
2780 xcb_query_tree_reply_t *tree;
2781 xcb_translate_coordinates_reply_t *trans;
2783 /* You initialize c and win */
2785 geom = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL);
2789 tree = xcb_query_tree_reply (c, xcb_query_tree (c, win), NULL);
2793 trans = xcb_translate_coordinates_reply (c,
2794 xcb_translate_coordinates (c,
2797 geom->x, geom->y),
2802 /* the translated coordinates are in trans->dst_x and trans->dst_y */
2809 Of course, as for <span class="code">geom</span>,
2810 <span class="code">tree</span> and
2811 <span class="code">trans</span> have to be freed.
2814 The work is a bit hard, but XCB is a very low-level library.
2817 <b>TODO:</b> the utilization of these functions should be a
2818 prog, which displays the coordinates of the window.
2821 There is another structure that gives informations about our window:
2825 uint8_t response_type;
2826 uint8_t backing_store;
2829 xcb_visualid_t visual; /* Visual of the window */
2831 uint8_t bit_gravity;
2832 uint8_t win_gravity;
2833 uint32_t backing_planes;
2834 uint32_t backing_pixel;
2836 uint8_t map_is_installed;
2837 uint8_t map_state; /* Map state of the window */
2838 uint8_t override_redirect;
2839 xcb_colormap_t colormap; /* Colormap of the window */
2840 uint32_t all_event_masks;
2841 uint32_t your_event_mask;
2842 uint16_t do_not_propagate_mask;
2843 } xcb_get_window_attributes_reply_t;
2846 XCB supplies these two functions to fill it:
2849 xcb_get_window_attributes_cookie_t xcb_get_window_attributes (xcb_connection_t *c,
2850 xcb_window_t window);
2851 xcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (xcb_connection_t *c,
2852 xcb_get_window_attributes_cookie_t cookie,
2853 xcb_generic_error_t **e);
2856 You use them as follows:
2859 xcb_connection_t *c;
2861 xcb_get_window_attributes_reply_t *attr;
2863 /* You initialize c and win */
2865 attr = xcb_get_window_attributes_reply (c, xcb_get_window_attributes (c, win), NULL);
2870 /* Do something with the fields of attr */
2875 As for <span class="code">geom</span>,
2876 <span class="code">attr</span> has to be freed.
2879 <li class="title"><a name="usecolor">Using colors to paint the rainbow</a>
2881 Up until now, all our painting operation were done using black
2882 and white. We will (finally) see now how to draw using colors.
2885 <li class="subtitle"><a name="colormap">Color maps</a>
2887 In the beginning, there were not enough colors. Screen
2888 controllers could only support a limited number of colors
2889 simultaneously (initially 2, then 4, 16 and 256). Because of
2890 this, an application could not just ask to draw in a "light
2891 purple-red" color, and expect that color to be available. Each
2892 application allocated the colors it needed, and when all the
2893 color entries (4, 16, 256 colors) were in use, the next color
2894 allocation would fail.
2897 Thus, the notion of "a color map" was introduced. A color map
2898 is a table whose size is the same as the number of
2899 simultaneous colors a given screen controller. Each entry
2900 contained the RGB (Red, Green and Blue) values of a different
2901 color (all colors can be drawn using some combination of red,
2902 green and blue). When an application wants to draw on the
2903 screen, it does not specify which color to use. Rather, it
2904 specifies which color entry of some color map to be used
2905 during this drawing. Change the value in this color map entry
2906 and the drawing will use a different color.
2909 In order to be able to draw using colors that got something to
2910 do with what the programmer intended, color map allocation
2911 functions are supplied. You could ask to allocate entry for a
2912 color with a set of RGB values. If one already existed, you
2913 would get its index in the table. If none existed, and the
2914 table was not full, a new cell would be allocated to contain
2915 the given RGB values, and its index returned. If the table was
2916 full, the procedure would fail. You could then ask to get a
2917 color map entry with a color that is closest to the one you
2918 were asking for. This would mean that the actual drawing on
2919 the screen would be done using colors similar to what you
2920 wanted, but not the same.
2923 On today's more modern screens where one runs an X server with
2924 support for 16 million colors, this limitation looks a little
2925 silly, but remember that there are still older computers with
2926 older graphics cards out there. Using color map, support for
2927 these screen becomes transparent to you. On a display
2928 supporting 16 million colors, any color entry allocation
2929 request would succeed. On a display supporting a limited
2930 number of colors, some color allocation requests would return
2931 similar colors. It won't look as good, but your application
2934 <li class="subtitle"><a name="colormapalloc">Allocating and freeing Color Maps</a>
2936 When you draw using XCB, you can choose to use the standard
2937 color map of the screen your window is displayed on, or you
2938 can allocate a new color map and apply it to a window. In the
2939 latter case, each time the mouse moves onto your window, the
2940 screen color map will be replaced by your window's color map,
2941 and you'll see all the other windows on screen change their
2942 colors into something quite bizarre. In fact, this is the
2943 effect you get with X applications that use the "-install"
2944 command line option.
2947 In XCB, a color map is (as often in X) an Id:
2950 typedef uint32_t xcb_colormap_t;
2953 In order to access the screen's default color map, you just
2954 have to retrieve the <span class="code">default_colormap</span>
2955 field of the <span class="code">xcb_screen_t</span> structure
2957 <a href="#screen">Checking basic information about a connection</a>):
2960 #include <stdio.h>
2962 #include <xcb/xcb.h>
2967 xcb_connection_t *c;
2968 xcb_screen_t *screen;
2969 xcb_colormap_t colormap;
2971 /* Open the connection to the X server and get the first screen */
2972 c = xcb_connect (NULL, NULL);
2973 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
2975 colormap = screen->default_colormap;
2981 This will return the color map used by default on the first
2982 screen (again, remember that an X server may support several
2983 different screens, each of which might have its own resources).
2986 The other option, that of allocating a new colormap, works as
2987 follows. We first ask the X server to give an Id to our color
2988 map, with this function:
2991 xcb_colormap_t xcb_generate_id (xcb_connection_t *c);
2994 Then, we create the color map with
2997 xcb_void_cookie_t xcb_create_colormap (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */
2998 uint8_t alloc, /* Colormap entries to be allocated (AllocNone or AllocAll) */
2999 xcb_colormap_t mid, /* Id of the color map */
3000 xcb_window_t window, /* Window on whose screen the colormap will be created */
3001 xcb_visualid_t visual); /* Id of the visual supported by the screen */
3004 Here is an example of creation of a new color map:
3007 #include <xcb/xcb.h>
3012 xcb_connection_t *c;
3013 xcb_screen_t *screen;
3017 /* Open the connection to the X server and get the first screen */
3018 c = xcb_connect (NULL, NULL);
3019 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
3021 /* We create the window win here*/
3023 cmap = xcb_generate_id (c);
3024 xcb_create_colormap (c, XCB_COLORMAP_ALLOC_NONE, cmap, win, screen->root_visual);
3030 Note that the window parameter is only used to allow the X
3031 server to create the color map for the given screen. We can
3032 then use this color map for any window drawn on the same screen.
3035 To free a color map, it suffices to use this function:
3038 xcb_void_cookie_t xcb_free_colormap (xcb_connection_t *c, /* The connection */
3039 xcb_colormap_t cmap); /* The color map */
3047 <li>XCreateColormap ()
3052 <li>xcb_generate_id ()
3053 <li>xcb_create_colormap ()
3058 <li>XFreeColormap ()
3063 <li>xcb_free_colormap ()
3068 <li class="subtitle"><a name="alloccolor">Allocating and freeing a color entry</a>
3070 Once we got access to some color map, we can start allocating
3071 colors. The informations related to a color are stored in the
3072 following structure:
3076 uint8_t response_type;
3080 uint16_t red; /* The red component */
3081 uint16_t green; /* The green component */
3082 uint16_t blue; /* The blue component */
3084 uint32_t pixel; /* The entry in the color map, supplied by the X server */
3085 } xcb_alloc_color_reply_t;
3088 XCB supplies these two functions to fill it:
3091 xcb_alloc_color_cookie_t xcb_alloc_color (xcb_connection_t *c,
3092 xcb_colormap_t cmap,
3096 xcb_alloc_color_reply_t *xcb_alloc_color_reply (xcb_connection_t *c,
3097 xcb_alloc_color_cookie_t cookie,
3098 xcb_generic_error_t **e);
3101 The fuction <span class="code">xcb_alloc_color()</span> takes the
3102 3 RGB components as parameters (red, green and blue). Here is an
3103 example of using these functions:
3106 #include <malloc.h>
3108 #include <xcb/xcb.h>
3113 xcb_connection_t *c;
3114 xcb_screen_t *screen;
3116 xcb_colormap_t cmap;
3117 xcb_alloc_color_reply_t *rep;
3119 /* Open the connection to the X server and get the first screen */
3120 c = xcb_connect (NULL, NULL);
3121 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data;
3123 /* We create the window win here*/
3125 cmap = xcb_generate_id (c);
3126 xcb_create_colormap (c, XCB_COLORMAP_ALLOC_NONE, cmap, win, screen->root_visual);
3128 rep = xcb_alloc_color_reply (c, xcb_alloc_color (c, cmap, 65535, 0, 0), NULL);
3133 /* Do something with r->pixel or the components */
3141 As <span class="code">xcb_alloc_color_reply()</span> allocates
3142 memory, you have to free <span class="code">rep</span>.
3145 <b>TODO</b>: Talk about freeing colors.
3148 <li class="title"><a name="pixmaps">X Bitmaps and Pixmaps</a>
3150 One thing many so-called "Multi-Media" applications need to do,
3151 is display images. In the X world, this is done using bitmaps
3152 and pixmaps. We have already seen some usage of them when
3153 setting an icon for our application. Lets study them further,
3154 and see how to draw these images inside a window, along side the
3155 simple graphics and text we have seen so far.
3158 One thing to note before delving further, is that XCB (nor Xlib)
3159 supplies no means of manipulating popular image formats, such as
3160 gif, png, jpeg or tiff. It is up to the programmer (or to higher
3161 level graphics libraries) to translate these image formats into
3162 formats that the X server is familiar with (x bitmaps and x
3166 <li class="subtitle"><a name="pixmapswhat">What is a X Bitmap? An X Pixmap?</a>
3168 An X bitmap is a two-color image stored in a format specific
3169 to the X window system. When stored in a file, the bitmap data
3170 looks like a C source file. It contains variables defining the
3171 width and the height of the bitmap, an array containing the
3172 bit values of the bitmap (the size of the array is
3173 (width+7)/8*height and the bit and byte order are LSB), and
3174 an optional hot-spot location (that will
3175 be explained later, when discussing mouse cursors).
3178 An X pixmap is a format used to stored images in the memory of
3179 an X server. This format can store both black and white images
3180 (such as x bitmaps) as well as color images. It is the only
3181 image format supported by the X protocol, and any image to be
3182 drawn on screen, should be first translated into this format.
3185 In actuality, an X pixmap can be thought of as a window that
3186 does not appear on the screen. Many graphics operations that
3187 work on windows, will also work on pixmaps. Indeed, the type
3188 of X pixmap in XCB is an Id like a window:
3191 typedef uint32_t xcb_pixmap_t;
3194 Like Xlib, there is no difference between a Drawable, a Window
3198 typedef uint32_t xcb_drawable_t;
3201 in order to avoid confusion between a window and a pixmap. The
3202 operations that will work the same on a window or a pixmap
3203 will require a <span class="code">xcb_drawable_t</span>
3207 Remark: In Xlib, there is no specific difference between a
3208 <span class="code">Drawable</span>, a
3209 <span class="code">Pixmap</span> or a
3210 <span class="code">Window</span>: all are 32 bit long
3211 integer. XCB wraps all these different IDs in structures to
3212 provide some measure of type-safety.
3215 <li class="subtitle"><a name="pixmapscreate">Creating a pixmap</a>
3217 Sometimes we want to create an un-initialized pixmap, so we
3218 can later draw into it. This is useful for image drawing
3219 programs (creating a new empty canvas will cause the creation
3220 of a new pixmap on which the drawing can be stored). It is
3221 also useful when reading various image formats: we load the
3222 image data into memory, create a pixmap on the server, and
3223 then draw the decoded image data onto that pixmap.
3226 To create a new pixmap, we first ask the X server to give an
3227 Id to our pixmap, with this function:
3230 xcb_pixmap_t xcb_generate_id (xcb_connection_t *c);
3233 Then, XCB supplies the following function to create new pixmaps:
3236 xcb_void_cookie_t xcb_create_pixmap (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */
3237 uint8_t depth, /* Depth of the screen */
3238 xcb_pixmap_t pid, /* Id of the pixmap */
3239 xcb_drawable_t drawable,
3240 uint16_t width, /* Width of the window (in pixels) */
3241 uint16_t height); /* Height of the window (in pixels) */
3244 <b>TODO</b>: Explain the drawable parameter, and give an
3245 example (like <a href="xpoints.c">xpoints.c</a>)
3247 <li class="subtitle"><a name="pixmapsdraw"></a>Drawing a pixmap in a window
3249 Once we got a handle to a pixmap, we can draw it on some
3250 window, using the following function:
3253 xcb_void_cookie_t xcb_copy_area (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */
3254 xcb_drawable_t src_drawable, /* The Drawable we want to paste */
3255 xcb_drawable_t dst_drawable, /* The Drawable on which we copy the previous Drawable */
3256 xcb_gcontext_t gc, /* A Graphic Context */
3257 int16_t src_x, /* Top left x coordinate of the region we want to copy */
3258 int16_t src_y, /* Top left y coordinate of the region we want to copy */
3259 int16_t dst_x, /* Top left x coordinate of the region where we want to copy */
3260 int16_t dst_y, /* Top left y coordinate of the region where we want to copy */
3261 uint16_t width, /* Width of the region we want to copy */
3262 uint16_t height); /* Height of the region we want to copy */
3265 As you can see, we could copy the whole pixmap, as well as
3266 only a given rectangle of the pixmap. This is useful to
3267 optimize the drawing speed: we could copy only what we have
3268 modified in the pixmap.
3271 <b>One important note should be made</b>: it is possible to
3272 create pixmaps with different depths on the same screen. When
3273 we perform copy operations (a pixmap onto a window, etc), we
3274 should make sure that both source and target have the same
3275 depth. If they have a different depth, the operation would
3276 fail. The exception to this is if we copy a specific bit plane
3277 of the source pixmap using the
3278 <span class="code">xcb_copy_plane_t</span> function. In such an
3279 event, we can copy a specific plane to the target window (in
3280 actuality, setting a specific bit in the color of each pixel
3281 copied). This can be used to generate strange graphic effects
3282 in a window, but that is beyond the scope of this tutorial.
3284 <li class="subtitle"><a name="pixmapsfree"></a>Freeing a pixmap
3286 Finally, when we are done using a given pixmap, we should free
3287 it, in order to free resources of the X server. This is done
3288 using this function:
3291 xcb_void_cookie_t xcb_free_pixmap (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */
3292 xcb_pixmap_t pixmap); /* A given pixmap */
3295 Of course, after having freed it, we must not try accessing
3299 <b>TODO</b>: Give an example, or a link to xpoints.c
3302 <li class="title"><a name="mousecursor">Messing with the mouse cursor</a>
3304 It it possible to modify the shape of the mouse pointer (also
3305 called the X pointer) when in certain states, as we often see in
3306 programs. For example, a busy application would often display
3307 the hourglass cursor over its main window, to give the user a visual
3308 hint that they should wait. Let's see how we can change the mouse
3309 cursor of our windows.
3312 <li class="subtitle"><a name="mousecursorcreate">Creating and destroying a mouse cursor</a>
3314 There are two methods for creating cursors. One of them is by
3315 using a set of predefined cursors, that are supplied by the X
3316 server, the other is by using a user-supplied bitmap.
3319 In the first method, we use a special font named "cursor", and
3320 the function <span class="code">xcb_create_glyph_cursor</span>:
3323 xcb_void_cookie_t xcb_create_glyph_cursor (xcb_connection_t *c,
3325 xcb_font_t source_font, /* font for the source glyph */
3326 xcb_font_t mask_font, /* font for the mask glyph or XCB_NONE */
3327 uint16_t source_char, /* character glyph for the source */
3328 uint16_t mask_char, /* character glyph for the mask */
3329 uint16_t fore_red, /* red value for the foreground of the source */
3330 uint16_t fore_green, /* green value for the foreground of the source */
3331 uint16_t fore_blue, /* blue value for the foreground of the source */
3332 uint16_t back_red, /* red value for the background of the source */
3333 uint16_t back_green, /* green value for the background of the source */
3334 uint16_t back_blue) /* blue value for the background of the source */
3337 <b>TODO</b>: Describe <span class="code">source_char</span>
3338 and <span class="code">mask_char</span>, for example by giving
3339 an example on how to get the values. There is a list there:
3340 <a href="http://tronche.com/gui/x/xlib/appendix/b/">X Font Cursors</a>
3343 So we first open that font (see <a href="#loadfont">Loading a Font</a>)
3344 and create the new cursor. As for every X resource, we have to
3345 ask for an X id with <span class="code">xcb_generate_id</span>
3350 xcb_cursor_t cursor;
3352 /* The connection is set */
3354 font = xcb_generate_id (conn);
3355 xcb_open_font (conn, font, strlen ("cursor"), "cursor");
3357 cursor = xcb_generate_id (conn);
3358 xcb_create_glyph_cursor (conn, cursor, font, font,
3364 We have created the cursor "right hand" by specifying 58 to
3365 the <span class="code">source_fon</span>t argument and 58 + 1
3366 to the <span class="code">mask_font</span>.
3369 The cursor is destroyed by using the function
3372 xcb_void_cookie_t xcb_free_cursor (xcb_connection_t *c,
3373 xcb_cursor_t cursor);
3376 In the second method, we create a new cursor by using a pair
3377 of pixmaps, with depth of one (that is, two colors
3378 pixmaps). One pixmap defines the shape of the cursor, while
3379 the other works as a mask, specifying which pixels of the
3380 cursor will be actually drawn. The rest of the pixels will be
3384 <b>TODO</b>: give an example.
3386 <li class="subtitle"><a name="mousecursorset">Setting a window's mouse cursor</a>
3388 Once the cursor is created, we can modify the cursor of our
3389 window by using <span class="code">xcb_change_window_attributes</span>
3390 and using the <span class="code">XCB_CWCURSOR</span> attribute:
3394 uint32_t value_list;
3396 /* The connection and window are set */
3397 /* The cursor is already created */
3399 mask = XCB_CWCURSOR;
3400 value_list = cursor;
3401 xcb_change_window_attributes (conn, window, mask, &value_list);
3404 Of course, the cursor and the font must be freed.
3406 <li class="subtitle"><a name="mousecursorexample">Complete example</a>
3408 The following example displays a window with a
3409 button. When entering the window, the window cursor is changed
3410 to an arrow. When clicking once on the button, the cursor is
3411 changed to a hand. When clicking again on the button, the
3412 cursor window gets back to the arrow. The Esc key exits the
3416 #include <stdlib.h>
3417 #include <stdio.h>
3418 #include <string.h>
3420 #include <xcb/xcb.h>
3427 static xcb_gc_t gc_font_get (xcb_connection_t *c,
3428 xcb_screen_t *screen,
3429 xcb_window_t window,
3430 const char *font_name);
3432 static void button_draw (xcb_connection_t *c,
3433 xcb_screen_t *screen,
3434 xcb_window_t window,
3439 static void text_draw (xcb_connection_t *c,
3440 xcb_screen_t *screen,
3441 xcb_window_t window,
3446 static void cursor_set (xcb_connection_t *c,
3447 xcb_screen_t *screen,
3448 xcb_window_t window,
3453 button_draw (xcb_connection_t *c,
3454 xcb_screen_t *screen,
3455 xcb_window_t window,
3460 xcb_point_t points[5];
3461 xcb_void_cookie_t cookie_gc;
3462 xcb_void_cookie_t cookie_line;
3463 xcb_void_cookie_t cookie_text;
3464 xcb_generic_error_t *error;
3471 length = strlen (label);
3474 gc = gc_font_get(c, screen, window, "7x13");
3476 width = 7 * length + 2 * (inset + 1);
3477 height = 13 + 2 * (inset + 1);
3480 points[1].x = x1 + width;
3482 points[2].x = x1 + width;
3483 points[2].y = y1 - height;
3485 points[3].y = y1 - height;
3488 cookie_line = xcb_poly_line_checked (c, XCB_COORD_MODE_ORIGIN,
3489 window, gc, 5, points);
3491 error = xcb_request_check (c, cookie_line);
3493 fprintf (stderr, "ERROR: can't draw lines : %d\n", error->error_code);
3498 cookie_text = xcb_image_text_8_checked (c, length, window, gc,
3500 y1 - inset - 1, label);
3501 error = xcb_request_check (c, cookie_text);
3503 fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
3508 cookie_gc = xcb_free_gc (c, gc);
3509 error = xcb_request_check (c, cookie_gc);
3511 fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
3518 text_draw (xcb_connection_t *c,
3519 xcb_screen_t *screen,
3520 xcb_window_t window,
3525 xcb_void_cookie_t cookie_gc;
3526 xcb_void_cookie_t cookie_text;
3527 xcb_generic_error_t *error;
3531 length = strlen (label);
3533 gc = gc_font_get(c, screen, window, "7x13");
3535 cookie_text = xcb_image_text_8_checked (c, length, window, gc,
3538 error = xcb_request_check (c, cookie_text);
3540 fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code);
3545 cookie_gc = xcb_free_gc (c, gc);
3546 error = xcb_request_check (c, cookie_gc);
3548 fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code);
3555 gc_font_get (xcb_connection_t *c,
3556 xcb_screen_t *screen,
3557 xcb_window_t window,
3558 const char *font_name)
3560 uint32_t value_list[3];
3561 xcb_void_cookie_t cookie_font;
3562 xcb_void_cookie_t cookie_gc;
3563 xcb_generic_error_t *error;
3568 font = xcb_generate_id (c);
3569 cookie_font = xcb_open_font_checked (c, font,
3573 error = xcb_request_check (c, cookie_font);
3575 fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
3580 gc = xcb_generate_id (c);
3581 mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
3582 value_list[0] = screen->black_pixel;
3583 value_list[1] = screen->white_pixel;
3584 value_list[2] = font;
3585 cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list);
3586 error = xcb_request_check (c, cookie_gc);
3588 fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
3593 cookie_font = xcb_close_font_checked (c, font);
3594 error = xcb_request_check (c, cookie_font);
3596 fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
3605 cursor_set (xcb_connection_t *c,
3606 xcb_screen_t *screen,
3607 xcb_window_t window,
3610 uint32_t values_list[3];
3611 xcb_void_cookie_t cookie_font;
3612 xcb_void_cookie_t cookie_gc;
3613 xcb_generic_error_t *error;
3615 xcb_cursor_t cursor;
3618 uint32_t value_list;
3620 font = xcb_generate_id (c);
3621 cookie_font = xcb_open_font_checked (c, font,
3624 error = xcb_request_check (c, cookie_font);
3626 fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code);
3631 cursor = xcb_generate_id (c);
3632 xcb_create_glyph_cursor (c, cursor, font, font,
3633 cursor_id, cursor_id + 1,
3637 gc = xcb_generate_id (c);
3638 mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT;
3639 values_list[0] = screen->black_pixel;
3640 values_list[1] = screen->white_pixel;
3641 values_list[2] = font;
3642 cookie_gc = xcb_create_gc_checked (c, gc, window, mask, values_list);
3643 error = xcb_request_check (c, cookie_gc);
3645 fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code);
3650 mask = XCB_CW_CURSOR;
3651 value_list = cursor;
3652 xcb_change_window_attributes (c, window, mask, &value_list);
3654 xcb_free_cursor (c, cursor);
3656 cookie_font = xcb_close_font_checked (c, font);
3657 error = xcb_request_check (c, cookie_font);
3659 fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code);
3667 xcb_screen_iterator_t screen_iter;
3668 xcb_connection_t *c;
3669 const xcb_setup_t *setup;
3670 xcb_screen_t *screen;
3671 xcb_generic_event_t *e;
3672 xcb_generic_error_t *error;
3673 xcb_void_cookie_t cookie_window;
3674 xcb_void_cookie_t cookie_map;
3675 xcb_window_t window;
3679 uint8_t is_hand = 0;
3681 /* getting the connection */
3682 c = xcb_connect (NULL, &screen_number);
3684 fprintf (stderr, "ERROR: can't connect to an X server\n");
3688 /* getting the current screen */
3689 setup = xcb_get_setup (c);
3692 screen_iter = xcb_setup_roots_iterator (setup);
3693 for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter))
3694 if (screen_number == 0)
3696 screen = screen_iter.data;
3700 fprintf (stderr, "ERROR: can't get the current screen\n");
3705 /* creating the window */
3706 window = xcb_generate_id (c);
3707 mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK;
3708 values[0] = screen->white_pixel;
3710 XCB_EVENT_MASK_KEY_RELEASE |
3711 XCB_EVENT_MASK_BUTTON_PRESS |
3712 XCB_EVENT_MASK_EXPOSURE |
3713 XCB_EVENT_MASK_POINTER_MOTION;
3714 cookie_window = xcb_create_window_checked (c,
3716 window, screen->root,
3717 20, 200, WIDTH, HEIGHT,
3718 0, XCB_WINDOW_CLASS_INPUT_OUTPUT,
3719 screen->root_visual,
3721 cookie_map = xcb_map_window_checked (c, window);
3723 /* error managing */
3724 error = xcb_request_check (c, cookie_window);
3726 fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code);
3730 error = xcb_request_check (c, cookie_map);
3732 fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code);
3737 cursor_set (c, screen, window, 68);
3742 e = xcb_poll_for_event(c);
3744 switch (e->response_type & ~0x80) {
3748 text = "click here to change cursor";
3749 button_draw (c, screen, window,
3750 (WIDTH - 7 * strlen(text)) / 2,
3751 (HEIGHT - 16) / 2, text);
3753 text = "Press ESC key to exit...";
3754 text_draw (c, screen, window, 10, HEIGHT - 10, text);
3757 case XCB_BUTTON_PRESS: {
3758 xcb_button_press_event_t *ev;
3761 ev = (xcb_button_press_event_t *)e;
3762 length = strlen ("click here to change cursor");
3764 if ((ev->event_x >= (WIDTH - 7 * length) / 2) &&
3765 (ev->event_x <= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) &&
3766 (ev->event_y >= (HEIGHT - 16) / 2 - 19) &&
3767 (ev->event_y <= ((HEIGHT - 16) / 2)))
3768 is_hand = 1 - is_hand;
3770 is_hand ? cursor_set (c, screen, window, 58) : cursor_set (c, screen, window, 68);
3772 case XCB_KEY_RELEASE: {
3773 xcb_key_release_event_t *ev;
3775 ev = (xcb_key_release_event_t *)e;
3777 switch (ev->detail) {
3794 <li class="title"><a name="translation">Translation of basic Xlib functions and macros</a>
3796 The problem when you want to port an Xlib program to XCB is that
3797 you don't know if the Xlib function that you want to "translate"
3798 is a X Window one or an Xlib macro. In that section, we describe
3799 a way to translate the usual functions or macros that Xlib
3800 provides. It's usually just a member of a structure.
3803 <li class="subtitle"><a name="displaystructure">Members of the Display structure</a>
3805 In this section, we look at how to translate the macros that
3806 return some members of the <span class="code">Display</span>
3807 structure. They are obtained by using a function that requires a
3808 <span class="code">xcb_connection_t *</span> or a member of the
3809 <span class="code">xcb_setup_t</span> structure
3810 (via the function <span class="code">xcb_get_setup</span>), or
3811 a function that requires that structure.
3814 <li class="subtitle"><a name="ConnectionNumber">ConnectionNumber</a>
3816 This number is the file descriptor that connects the client
3817 to the server. You just have to use that function:
3820 int xcb_get_file_descriptor (xcb_connection_t *c);
3822 <li class="subtitle"><a name="DefaultScreen"></a>DefaultScreen
3824 That number is not stored by XCB. It is returned in the
3825 second parameter of the function <span class="code"><a href="#openconn">xcb_connect</a></span>.
3826 Hence, you have to store it yourself if you want to use
3827 it. Then, to get the <span class="code">xcb_screen_t</span>
3828 structure, you have to iterate on the screens.
3829 The equivalent function of the Xlib's
3830 <span class="code">ScreenOfDisplay</span> function can be
3831 found <a href="#ScreenOfDisplay">below</a>. This is also provided in the
3832 xcb_aux_t library as <span class="code">xcb_aux_get_screen()</span>. OK, here is the
3833 small piece of code to get that number:
3836 xcb_connection_t *c;
3837 int screen_default_nbr;
3839 /* you pass the name of the display you want to xcb_connect_t */
3841 c = xcb_connect (display_name, &screen_default_nbr);
3843 /* screen_default_nbr contains now the number of the default screen */
3845 <li class="subtitle"><a name="QLength"></a>QLength
3850 However, this points out a basic difference in philosophy between
3851 Xlib and XCB. Xlib has several functions for filtering and
3852 manipulating the incoming and outgoing X message queues. XCB
3853 wishes to hide this as much as possible from the user, which
3854 allows for more freedom in implementation strategies.
3856 <li class="subtitle"><a name="ScreenCount"></a>ScreenCount
3858 You get the count of screens with the functions
3859 <span class="code">xcb_get_setup</span>
3861 <span class="code">xcb_setup_roots_iterator</span>
3862 (if you need to iterate):
3865 xcb_connection_t *c;
3868 /* you init the connection */
3870 screen_count = xcb_setup_roots_iterator (xcb_get_setup (c)).rem;
3872 /* screen_count contains now the count of screens */
3875 If you don't want to iterate over the screens, a better way
3876 to get that number is to use
3877 <span class="code">xcb_setup_roots_length_t</span>:
3880 xcb_connection_t *c;
3883 /* you init the connection */
3885 screen_count = xcb_setup_roots_length (xcb_get_setup (c));
3887 /* screen_count contains now the count of screens */
3889 <li class="subtitle"><a name="ServerVendor"></a>ServerVendor
3891 You get the name of the vendor of the server hardware with
3892 the functions <span class="code">xcb_get_setup</span>
3895 class="code">xcb_setup_vendor</span>. Beware
3896 that, unlike Xlib, the string returned by XCB is not
3897 necessarily null-terminaled:
3900 xcb_connection_t *c;
3901 char *vendor = NULL;
3904 /* you init the connection */
3905 length = xcb_setup_vendor_length (xcb_get_setup (c));
3906 vendor = (char *)malloc (length + 1);
3908 memcpy (vendor, xcb_setup_vendor (xcb_get_setup (c)), length);
3909 vendor[length] = '\0';
3911 /* vendor contains now the name of the vendor. Must be freed when not used anymore */
3913 <li class="subtitle"><a name="ProtocolVersion"></a>ProtocolVersion
3915 You get the major version of the protocol in the
3916 <span class="code">xcb_setup_t</span>
3917 structure, with the function <span class="code">xcb_get_setup</span>:
3920 xcb_connection_t *c;
3921 uint16_t protocol_major_version;
3923 /* you init the connection */
3925 protocol_major_version = xcb_get_setup (c)->protocol_major_version;
3927 /* protocol_major_version contains now the major version of the protocol */
3929 <li class="subtitle"><a name="ProtocolRevision"></a>ProtocolRevision
3931 You get the minor version of the protocol in the
3932 <span class="code">xcb_setup_t</span>
3933 structure, with the function <span class="code">xcb_get_setup</span>:
3936 xcb_connection_t *c;
3937 uint16_t protocol_minor_version;
3939 /* you init the connection */
3941 protocol_minor_version = xcb_get_setup (c)->protocol_minor_version;
3943 /* protocol_minor_version contains now the minor version of the protocol */
3945 <li class="subtitle"><a name="VendorRelease"></a>VendorRelease
3947 You get the number of the release of the server hardware in the
3948 <span class="code">xcb_setup_t</span>
3949 structure, with the function <span class="code">xcb_get_setup</span>:
3952 xcb_connection_t *c;
3953 uint32_t release_number;
3955 /* you init the connection */
3957 release_number = xcb_get_setup (c)->release_number;
3959 /* release_number contains now the number of the release of the server hardware */
3961 <li class="subtitle"><a name="DisplayString"></a>DisplayString
3963 The name of the display is not stored in XCB. You have to
3964 store it by yourself.
3966 <li class="subtitle"><a name="BitmapUnit"></a>BitmapUnit
3968 You get the bitmap scanline unit in the
3969 <span class="code">xcb_setup_t</span>
3970 structure, with the function <span class="code">xcb_get_setup</span>:
3973 xcb_connection_t *c;
3974 uint8_t bitmap_format_scanline_unit;
3976 /* you init the connection */
3978 bitmap_format_scanline_unit = xcb_get_setup (c)->bitmap_format_scanline_unit;
3980 /* bitmap_format_scanline_unit contains now the bitmap scanline unit */
3982 <li class="subtitle"><a name="BitmapBitOrder"></a>BitmapBitOrder
3984 You get the bitmap bit order in the
3985 <span class="code">xcb_setup_t</span>
3986 structure, with the function <span class="code">xcb_get_setup</span>:
3989 xcb_connection_t *c;
3990 uint8_t bitmap_format_bit_order;
3992 /* you init the connection */
3994 bitmap_format_bit_order = xcb_get_setup (c)->bitmap_format_bit_order;
3996 /* bitmap_format_bit_order contains now the bitmap bit order */
3998 <li class="subtitle"><a name="BitmapPad"></a>BitmapPad
4000 You get the bitmap scanline pad in the
4001 <span class="code">xcb_setup_t</span>
4002 structure, with the function <span class="code">xcb_get_setup</span>:
4005 xcb_connection_t *c;
4006 uint8_t bitmap_format_scanline_pad;
4008 /* you init the connection */
4010 bitmap_format_scanline_pad = xcb_get_setup (c)->bitmap_format_scanline_pad;
4012 /* bitmap_format_scanline_pad contains now the bitmap scanline pad */
4014 <li class="subtitle"><a name="ImageByteOrder"></a>ImageByteOrder
4016 You get the image byte order in the
4017 <span class="code">xcb_setup_t</span>
4018 structure, with the function <span class="code">xcb_get_setup</span>:
4021 xcb_connection_t *c;
4022 uint8_t image_byte_order;
4024 /* you init the connection */
4026 image_byte_order = xcb_get_setup (c)->image_byte_order;
4028 /* image_byte_order contains now the image byte order */
4031 <li class="subtitle"><a name="screenofdisplay">ScreenOfDisplay related functions</a>
4033 in Xlib, <span class="code">ScreenOfDisplay</span> returns a
4034 <span class="code">Screen</span> structure that contains
4035 several characteristics of your screen. XCB has a similar
4036 structure (<span class="code">xcb_screen_t</span>),
4037 but the way to obtain it is a bit different. With
4038 Xlib, you just provide the number of the screen and you grab it
4039 from an array. With XCB, you iterate over all the screens to
4040 obtain the one you want. The complexity of this operation is
4041 O(n). So the best is to store this structure if you use
4042 it often. See <a href="#ScreenOfDisplay">screen_of_display</a> just below.
4045 Xlib provides generally two functions to obtain the characteristics
4046 related to the screen. One with the display and the number of
4047 the screen, which calls <span class="code">ScreenOfDisplay</span>,
4048 and the other that uses the <span class="code">Screen</span> structure.
4049 This might be a bit confusing. As mentioned above, with XCB, it
4050 is better to store the <span class="code">xcb_screen_t</span>
4051 structure. Then, you have to read the members of this
4052 structure. That's why the Xlib functions are put by pairs (or
4053 more) as, with XCB, you will use the same code.
4056 <li class="subtitle"><a name="ScreenOfDisplay">ScreenOfDisplay</a>
4058 This function returns the Xlib <span class="code">Screen</span>
4059 structure. With XCB, you iterate over all the screens and
4060 once you get the one you want, you return it:
4062 <pre class="code"><a name="ScreenOfDisplay"></a>
4063 xcb_screen_t *screen_of_display (xcb_connection_t *c,
4066 xcb_screen_iterator_t iter;
4068 iter = xcb_setup_roots_iterator (xcb_get_setup (c));
4069 for (; iter.rem; --screen, xcb_screen_next (&iter))
4077 As mentioned above, you might want to store the value
4078 returned by this function.
4081 All the functions below will use the result of that
4082 function, as they just grab a specific member of the
4083 <span class="code">xcb_screen_t</span> structure.
4085 <li class="subtitle"><a name="DefaultScreenOfDisplay"></a>DefaultScreenOfDisplay
4087 It is the default screen that you obtain when you connect to
4088 the X server. It suffices to call the <a href="#ScreenOfDisplay">screen_of_display</a>
4089 function above with the connection and the number of the
4093 xcb_connection_t *c;
4094 int screen_default_nbr;
4095 xcb_screen_t *default_screen; /* the returned default screen */
4097 /* you pass the name of the display you want to xcb_connect_t */
4099 c = xcb_connect (display_name, &screen_default_nbr);
4100 default_screen = screen_of_display (c, screen_default_nbr);
4102 /* default_screen contains now the default root window, or a NULL window if no screen is found */
4104 <li class="subtitle"><a name="RootWindow">RootWindow / RootWindowOfScreen</a>
4107 xcb_connection_t *c;
4108 xcb_screen_t *screen;
4110 xcb_window_t root_window = { 0 }; /* the returned window */
4112 /* you init the connection and screen_nbr */
4114 screen = screen_of_display (c, screen_nbr);
4116 root_window = screen->root;
4118 /* root_window contains now the root window, or a NULL window if no screen is found */
4120 <li class="subtitle"><a name="DefaultRootWindow">DefaultRootWindow</a>
4122 It is the root window of the default screen. So, you call
4123 <a name="ScreenOfDisplay">ScreenOfDisplay</a> with the
4124 default screen number and you get the
4125 <a href="#RootWindow">root window</a> as above:
4128 xcb_connection_t *c;
4129 xcb_screen_t *screen;
4130 int screen_default_nbr;
4131 xcb_window_t root_window = { 0 }; /* the returned root window */
4133 /* you pass the name of the display you want to xcb_connect_t */
4135 c = xcb_connect (display_name, &screen_default_nbr);
4136 screen = screen_of_display (c, screen_default_nbr);
4138 root_window = screen->root;
4140 /* root_window contains now the default root window, or a NULL window if no screen is found */
4142 <li class="subtitle"><a name="DefaultVisual">DefaultVisual / DefaultVisualOfScreen</a>
4144 While a Visual is, in Xlib, a structure, in XCB, there are
4145 two types: <span class="code">xcb_visualid_t</span>, which is
4146 the Id of the visual, and <span class="code">xcb_visualtype_t</span>,
4147 which corresponds to the Xlib Visual. To get the Id of the
4148 visual of a screen, just get the
4149 <span class="code">root_visual</span>
4150 member of a <span class="code">xcb_screen_t</span>:
4153 xcb_connection_t *c;
4154 xcb_screen_t *screen;
4156 xcb_visualid_t root_visual = { 0 }; /* the returned visual Id */
4158 /* you init the connection and screen_nbr */
4160 screen = screen_of_display (c, screen_nbr);
4162 root_visual = screen->root_visual;
4164 /* root_visual contains now the value of the Id of the visual, or a NULL visual if no screen is found */
4167 To get the <span class="code">xcb_visualtype_t</span>
4168 structure, it's a bit less easy. You have to get the
4169 <span class="code">xcb_screen_t</span> structure that you want,
4170 get its <span class="code">root_visual</span> member,
4171 then iterate over the <span class="code">xcb_depth_t</span>s
4172 and the <span class="code">xcb_visualtype_t</span>s, and compare
4173 the <span class="code">xcb_visualid_t</span> of these <span class="code">xcb_visualtype_t</span>s:
4174 with <span class="code">root_visual</span>:
4177 xcb_connection_t *c;
4178 xcb_screen_t *screen;
4180 xcb_visualid_t root_visual = { 0 };
4181 xcb_visualtype_t *visual_type = NULL; /* the returned visual type */
4183 /* you init the connection and screen_nbr */
4185 screen = screen_of_display (c, screen_nbr);
4187 xcb_depth_iterator_t depth_iter;
4189 depth_iter = xcb_screen_allowed_depths_iterator (screen);
4190 for (; depth_iter.rem; xcb_depth_next (&depth_iter)) {
4191 xcb_visualtype_iterator_t visual_iter;
4193 visual_iter = xcb_depth_visuals_iterator (depth_iter.data);
4194 for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) {
4195 if (screen->root_visual == visual_iter.data->visual_id) {
4196 visual_type = visual_iter.data;
4203 /* visual_type contains now the visual structure, or a NULL visual structure if no screen is found */
4205 <li class="subtitle"><a name="DefaultGC">DefaultGC / DefaultGCOfScreen</a>
4207 This default Graphic Context is just a newly created Graphic
4208 Context, associated to the root window of a
4209 <span class="code">xcb_screen_t</span>,
4210 using the black white pixels of that screen:
4213 xcb_connection_t *c;
4214 xcb_screen_t *screen;
4216 xcb_gcontext_t gc = { 0 }; /* the returned default graphic context */
4218 /* you init the connection and screen_nbr */
4220 screen = screen_of_display (c, screen_nbr);
4222 xcb_drawable_t draw;
4226 gc = xcb_generate_id (c);
4227 draw = screen->root;
4228 mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND;
4229 values[0] = screen->black_pixel;
4230 values[1] = screen->white_pixel;
4231 xcb_create_gc (c, gc, draw, mask, values);
4234 /* gc contains now the default graphic context */
4236 <li class="subtitle"><a name="BlackPixel">BlackPixel / BlackPixelOfScreen</a>
4238 It is the Id of the black pixel, which is in the structure
4239 of an <span class="code">xcb_screen_t</span>.
4242 xcb_connection_t *c;
4243 xcb_screen_t *screen;
4245 uint32_t black_pixel = 0; /* the returned black pixel */
4247 /* you init the connection and screen_nbr */
4249 screen = screen_of_display (c, screen_nbr);
4251 black_pixel = screen->black_pixel;
4253 /* black_pixel contains now the value of the black pixel, or 0 if no screen is found */
4255 <li class="subtitle"><a name="WhitePixel">WhitePixel / WhitePixelOfScreen</a>
4257 It is the Id of the white pixel, which is in the structure
4258 of an <span class="code">xcb_screen_t</span>.
4261 xcb_connection_t *c;
4262 xcb_screen_t *screen;
4264 uint32_t white_pixel = 0; /* the returned white pixel */
4266 /* you init the connection and screen_nbr */
4268 screen = screen_of_display (c, screen_nbr);
4270 white_pixel = screen->white_pixel;
4272 /* white_pixel contains now the value of the white pixel, or 0 if no screen is found */
4274 <li class="subtitle"><a name="DisplayWidth">DisplayWidth / WidthOfScreen</a>
4276 It is the width in pixels of the screen that you want, and
4277 which is in the structure of the corresponding
4278 <span class="code">xcb_screen_t</span>.
4281 xcb_connection_t *c;
4282 xcb_screen_t *screen;
4284 uint32_t width_in_pixels = 0; /* the returned width in pixels */
4286 /* you init the connection and screen_nbr */
4288 screen = screen_of_display (c, screen_nbr);
4290 width_in_pixels = screen->width_in_pixels;
4292 /* width_in_pixels contains now the width in pixels, or 0 if no screen is found */
4294 <li class="subtitle"><a name="DisplayHeight">DisplayHeight / HeightOfScreen</a>
4296 It is the height in pixels of the screen that you want, and
4297 which is in the structure of the corresponding
4298 <span class="code">xcb_screen_t</span>.
4301 xcb_connection_t *c;
4302 xcb_screen_t *screen;
4304 uint32_t height_in_pixels = 0; /* the returned height in pixels */
4306 /* you init the connection and screen_nbr */
4308 screen = screen_of_display (c, screen_nbr);
4310 height_in_pixels = screen->height_in_pixels;
4312 /* height_in_pixels contains now the height in pixels, or 0 if no screen is found */
4314 <li class="subtitle"><a name="DisplayWidthMM">DisplayWidthMM / WidthMMOfScreen</a>
4316 It is the width in millimeters of the screen that you want, and
4317 which is in the structure of the corresponding
4318 <span class="code">xcb_screen_t</span>.
4321 xcb_connection_t *c;
4322 xcb_screen_t *screen;
4324 uint32_t width_in_millimeters = 0; /* the returned width in millimeters */
4326 /* you init the connection and screen_nbr */
4328 screen = screen_of_display (c, screen_nbr);
4330 width_in_millimeters = screen->width_in_millimeters;
4332 /* width_in_millimeters contains now the width in millimeters, or 0 if no screen is found */
4334 <li class="subtitle"><a name="DisplayHeightMM">DisplayHeightMM / HeightMMOfScreen</a>
4336 It is the height in millimeters of the screen that you want, and
4337 which is in the structure of the corresponding
4338 <span class="code">xcb_screen_t</span>.
4341 xcb_connection_t *c;
4342 xcb_screen_t *screen;
4344 uint32_t height_in_millimeters = 0; /* the returned height in millimeters */
4346 /* you init the connection and screen_nbr */
4348 screen = screen_of_display (c, screen_nbr);
4350 height_in_millimeters = screen->height_in_millimeters;
4352 /* height_in_millimeters contains now the height in millimeters, or 0 if no screen is found */
4354 <li class="subtitle"><a name="DisplayPlanes">DisplayPlanes / DefaultDepth / DefaultDepthOfScreen / PlanesOfScreen</a>
4356 It is the depth (in bits) of the root window of the
4357 screen. You get it from the <span class="code">xcb_screen_t</span> structure.
4360 xcb_connection_t *c;
4361 xcb_screen_t *screen;
4363 uint8_t root_depth = 0; /* the returned depth of the root window */
4365 /* you init the connection and screen_nbr */
4367 screen = screen_of_display (c, screen_nbr);
4369 root_depth = screen->root_depth;
4371 /* root_depth contains now the depth of the root window, or 0 if no screen is found */
4373 <li class="subtitle"><a name="DefaultColormap">DefaultColormap / DefaultColormapOfScreen</a>
4375 This is the default colormap of the screen (and not the
4376 (default) colormap of the default screen !). As usual, you
4377 get it from the <span class="code">xcb_screen_t</span> structure:
4380 xcb_connection_t *c;
4381 xcb_screen_t *screen;
4383 xcb_colormap_t default_colormap = { 0 }; /* the returned default colormap */
4385 /* you init the connection and screen_nbr */
4387 screen = screen_of_display (c, screen_nbr);
4389 default_colormap = screen->default_colormap;
4391 /* default_colormap contains now the default colormap, or a NULL colormap if no screen is found */
4393 <li class="subtitle"><a name="MinCmapsOfScreen"></a>MinCmapsOfScreen
4395 You get the minimum installed colormaps in the <span class="code">xcb_screen_t</span> structure:
4398 xcb_connection_t *c;
4399 xcb_screen_t *screen;
4401 uint16_t min_installed_maps = 0; /* the returned minimum installed colormaps */
4403 /* you init the connection and screen_nbr */
4405 screen = screen_of_display (c, screen_nbr);
4407 min_installed_maps = screen->min_installed_maps;
4409 /* min_installed_maps contains now the minimum installed colormaps, or 0 if no screen is found */
4411 <li class="subtitle"><a name="MaxCmapsOfScreen"></a>MaxCmapsOfScreen
4413 You get the maximum installed colormaps in the <span class="code">xcb_screen_t</span> structure:
4416 xcb_connection_t *c;
4417 xcb_screen_t *screen;
4419 uint16_t max_installed_maps = 0; /* the returned maximum installed colormaps */
4421 /* you init the connection and screen_nbr */
4423 screen = screen_of_display (c, screen_nbr);
4425 max_installed_maps = screen->max_installed_maps;
4427 /* max_installed_maps contains now the maximum installed colormaps, or 0 if no screen is found */
4429 <li class="subtitle"><a name="DoesSaveUnders"></a>DoesSaveUnders
4431 You know if <span class="code">save_unders</span> is set,
4432 by looking in the <span class="code">xcb_screen_t</span> structure:
4435 xcb_connection_t *c;
4436 xcb_screen_t *screen;
4438 uint8_t save_unders = 0; /* the returned value of save_unders */
4440 /* you init the connection and screen_nbr */
4442 screen = screen_of_display (c, screen_nbr);
4444 save_unders = screen->save_unders;
4446 /* save_unders contains now the value of save_unders, or FALSE if no screen is found */
4448 <li class="subtitle"><a name="DoesBackingStore"></a>DoesBackingStore
4450 You know the value of <span class="code">backing_stores</span>,
4451 by looking in the <span class="code">xcb_screen_t</span> structure:
4454 xcb_connection_t *c;
4455 xcb_screen_t *screen;
4457 uint8_t backing_stores = 0; /* the returned value of backing_stores */
4459 /* you init the connection and screen_nbr */
4461 screen = screen_of_display (c, screen_nbr);
4463 backing_stores = screen->backing_stores;
4465 /* backing_stores contains now the value of backing_stores, or FALSE if no screen is found */
4467 <li class="subtitle"><a name="EventMaskOfScreen"></a>EventMaskOfScreen
4469 To get the current input masks,
4470 you look in the <span class="code">xcb_screen_t</span> structure:
4473 xcb_connection_t *c;
4474 xcb_screen_t *screen;
4476 uint32_t current_input_masks = 0; /* the returned value of current input masks */
4478 /* you init the connection and screen_nbr */
4480 screen = screen_of_display (c, screen_nbr);
4482 current_input_masks = screen->current_input_masks;
4484 /* current_input_masks contains now the value of the current input masks, or FALSE if no screen is found */
4487 <li class="subtitle"><a name="misc">Miscellaneous macros</a>
4489 <li class="subtitle"><a name="DisplayOfScreen"></a>DisplayOfScreen
4491 in Xlib, the <span class="code">Screen</span> structure
4492 stores its associated <span class="code">Display</span>
4493 structure. This is not the case in the X Window protocol,
4494 hence, it's also not the case in XCB. So you have to store
4497 <li class="subtitle"><a name="DisplayCells"></a>DisplayCells / CellsOfScreen
4499 To get the colormap entries,
4500 you look in the <span class="code">xcb_visualtype_t</span>
4501 structure, that you grab like <a class="subsection" href="#DefaultVisual">here</a>:
4504 xcb_connection_t *c;
4505 xcb_visualtype_t *visual_type;
4506 uint16_t colormap_entries = 0; /* the returned value of the colormap entries */
4508 /* you init the connection and visual_type */
4511 colormap_entries = visual_type->colormap_entries;
4513 /* colormap_entries contains now the value of the colormap entries, or FALSE if no screen is found */