index.html revision b9526c6a
1<!DOCTYPE html public "-//W3C//DTD HTML 4.01 Transitional//EN" 2"http://www.w3.org/TR/html4/loose.dtd"> 3 4<html> 5 6<head> 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"> 10</head> 11 12<body> 13 <div class="title"> 14 Basic Graphics Programming With The XCB Library 15 </div> 16 <div class="toc"> 17 <ol> 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> 22 <ol> 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> 26 <li>Object handles 27 <li>Memory allocation for XCB structures 28 <li><a class="subsection" href="#events">Events</a> 29 </ol> 30 <li><a class="section" href="#use">Using XCB-based programs</a> 31 <ol> 32 <li><a class="subsection" href="#inst">Installation of XCB</a> 33 <li><a class="subsection" href="#comp">Compiling XCB-based programs</a> 34 </ol> 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> 39 <ol> 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> 43 </ol> 44 <li><a class="section" href="#xevents">X Events</a> 45 <ol> 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> 50 <ol> 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> 56 </ol> 57 <li><a class="subsection" href="#eventex">X events: a complete example</a> 58 </ol> 59 <li><a class="section" href="#font">Handling text and fonts</a> 60 <ol> 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> 66 </ol> 67 <li>Windows hierarchy 68 <ol> 69 <li>Root, parent and child windows 70 <li>Events propagation 71 </ol> 72 <li><a class="section" href="#wm">Interacting with the window manager</a> 73 <ol> 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 80 </ol> 81 <li><a class="section" href="#winop">Simple window operations</a> 82 <ol> 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> 90 </ol> 91 <li><a class="section" href="#usecolor">Using colors to paint the rainbow</a> 92 <ol> 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 97 </ol> 98 <li><a class="section" href="#pixmaps">X Bitmaps and Pixmaps</a> 99 <ol> 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> 106 </ol> 107 <li><a class="subsection" href="#mousecursor">Messing with the mouse cursor</a> 108 <ol> 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> 112 </ol> 113 <li><a class="subsection" href="#translation">Translation of basic Xlib functions and macros</a> 114 <ol> 115 <li><a class="subsection" href="#displaystructure">Members of the Display structure</a> 116 <ol> 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> 130 </ol> 131 <li><a class="subsection" href="#screenofdisplay">ScreenOfDisplay related functions</a> 132 <ol> 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> 152 </ol> 153 <li><a class="subsection" href="#misc">Miscellaneous macros</a> 154 <ol> 155 <li><a class="subsection" href="#DisplayOfScreen">DisplayOfScreen</a> 156 <li><a class="subsection" href="#DisplayCells">DisplayCells / CellsOfScreen</a> 157 </ol> 158 </ol> 159 </ol> 160 </div> 161 <div class="section"> 162 <ol> 163 <li class="title"><a name="intro">Introduction</a> 164 <p> 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. 170 </p> 171 <p> 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>. 185 However, 186 we need to start somewhere. More than this, knowing how things 187 work down below is never a bad idea. 188 </p> 189 <p> 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. 194 </p> 195 <p> 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: 201 </p> 202 <ul> 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 212 responses. 213 <li><b>Threaded applications</b>: While Xlib does attempt to 214 support multithreading, the API makes this difficult and 215 error-prone. 216 <li><b>New extensions</b>: The Xlib infrastructure provides 217 limited support for the new creation of X extension client side 218 code. 219 </ul> 220 <p> 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 223 </p> 224 <ul> 225 <li>Toolkit implementation. 226 <li>Direct protocol-level programming. 227 <li>Lightweight emulation of commonly used portions of the 228 Xlib API. 229 </ul> 230 <br> 231 <li class="title"><a name="Xmodel">The client and server model of the X window system</a> 232 <p> 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. 242 </p> 243 <p> 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. 257 </p> 258 <p> 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). 268 </p> 269 <li class="title"><a name="asynch">GUI programming: the asynchronous model</a> 270 <p> 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). 281 </p> 282 <p> 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. 291 </p> 292 <p> 293 So the way a GUI program looks is something like that: 294 </p> 295 <ol> 296 <li>Perform initialization routines. 297 <li>Connect to the X server. 298 <li>Perform X-related initialization. 299 <li>While not finished: 300 <ol> 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. 305 </ol> 306 <li>Close down the connection to the X server. 307 <li>Perform cleanup operations. 308 </ol> 309 <br> 310 <li class="title"><a name="notions">Basic XCB notions</a> 311 <p> 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. 319 </p> 320 <ol> 321 <li class="subtitle"><a name="conn">The X Connection</a> 322 <p> 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. 333 </p> 334 <li class="subtitle"><a name="requestsreplies">Requests and 335 replies: the Xlib killers</a> 336 <p> 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>): 348 </p> 349 <pre class="text"> 350 W-----RW-----RW-----RW-----R 351</pre> 352 <ul> 353 <li>W: Writing request 354 <li>-: Stalled, waiting for data 355 <li>R: Reading reply 356 </ul> 357 <p> 358 The total time is N * (T_write + T_round_trip + T_read). 359 </p> 360 <p> 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: 370 </p> 371 <pre class="text"> 372 WWWW--RRRR 373</pre> 374 <p> 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. 378 </p> 379 <p> 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. 384 </p> 385 <pre class="code"> 386#include <stdlib.h> 387#include <stdio.h> 388#include <string.h> 389#include <sys/time.h> 390 391#include <xcb/xcb.h> 392 393#include <X11/Xlib.h> 394 395double 396get_time(void) 397{ 398 struct timeval timev; 399 400 gettimeofday(&timev, NULL); 401 402 return (double)timev.tv_sec + (((double)timev.tv_usec) / 1000000); 403} 404 405int 406main () 407{ 408 xcb_connection_t *c; 409 xcb_atom_t *atoms; 410 xcb_intern_atom_cookie_t *cs; 411 char **names; 412 int count; 413 int i; 414 double start; 415 double end; 416 double diff; 417 418 /* Xlib */ 419 Display *disp; 420 Atom *atoms_x; 421 double diff_x; 422 423 c = xcb_connect (NULL, NULL); 424 425 count = 500; 426 atoms = (xcb_atom_t *)malloc (count * sizeof (atoms)); 427 names = (char **)malloc (count * sizeof (char *)); 428 429 /* init names */ 430 for (i = 0; i < count; ++i) { 431 char buf[100]; 432 433 sprintf (buf, "NAME%d", i); 434 names[i] = strdup (buf); 435 } 436 437 /* bad use */ 438 start = get_time (); 439 440 for (i = 0; i < count; ++i) 441 atoms[i] = xcb_intern_atom_reply (c, 442 xcb_intern_atom (c, 443 0, 444 strlen(names[i]), 445 names[i]), 446 NULL)->atom; 447 448 end = get_time (); 449 diff = end - start; 450 printf ("bad use time : %f\n", diff); 451 452 /* good use */ 453 start = get_time (); 454 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]); 458 459 for(i = 0; i < count; ++i) { 460 xcb_intern_atom_reply_t *r; 461 462 r = xcb_intern_atom_reply(c, cs[i], 0); 463 if(r) 464 atoms[i] = r->atom; 465 free(r); 466 } 467 468 end = get_time (); 469 printf ("good use time : %f\n", end - start); 470 printf ("ratio : %f\n", diff / (end - start)); 471 diff = end - start; 472 473 /* free var */ 474 free (atoms); 475 free (cs); 476 477 xcb_disconnect (c); 478 479 /* Xlib */ 480 disp = XOpenDisplay (getenv("DISPLAY")); 481 482 atoms_x = (Atom *)malloc (count * sizeof (atoms_x)); 483 484 start = get_time (); 485 486 for (i = 0; i < count; ++i) 487 atoms_x[i] = XInternAtom(disp, names[i], 0); 488 489 end = get_time (); 490 diff_x = end - start; 491 printf ("Xlib use time : %f\n", diff_x); 492 printf ("ratio : %f\n", diff_x / diff); 493 494 free (atoms_x); 495 for (i = 0; i < count; ++i) 496 free (names[i]); 497 free (names); 498 499 XCloseDisplay (disp); 500 501 return 0; 502} 503</pre> 504 <li class="subtitle"><a name="gc">The Graphic Context</a> 505 <p> 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 518 functions. 519 </p> 520 <p> 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. 525 </p> 526 <li class="subtitle"><a name="events">Events</a> 527 <p> 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. 537 </p> 538 </ol> 539 <br> 540 <li class="title"><a name="use">Using XCB-based programs</a> 541 <br> 542 <ol> 543 <li class="subtitle"><a name="inst">Installation of XCB</a> 544 <p> 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 548 one place. 549 </p> 550 <p> 551 To build XCB from source, you need to have installed at 552 least: 553 </p> 554 <ul> 555 <li>pkgconfig 0.15.0 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> 561 </ul> 562 <p> 563 You have to checkout in the git repository the following modules: 564 </p> 565 <ul> 566 <li>Xau from xlibs 567 <li>xcb-proto 568 <li>xcb 569 </ul> 570 <p> 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. 574 </p> 575 <li class="subtitle"><a name="comp">Compiling XCB-based programs</a> 576 <p> 577 Compiling XCB-based programs requires linking them with the XCB 578 library. This is easily done thanks to pkgconfig: 579 </p> 580 <pre class="text"> 581gcc -Wall prog.c -o prog `pkg-config --cflags --libs xcb` 582</pre> 583 </ol> 584 <li class="title"><a name="openconn">Opening and closing the connection to an X server</a> 585 <p> 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. 590 </p> 591 <pre class="code"> 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); 594</pre> 595 <p> 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: 599 </p> 600 <pre class="code"> 601#<span class="include">include</span> <span class="string"><xcb/xcb.h></span> 602 603<span class="type">int</span> 604<span class="function">main</span> () 605{ 606 <span class="type">xcb_connection_t</span> *c; 607 608 /* Open the connection to the X server. Use the DISPLAY environment variable as the default display name */ 609 c = xcb_connect (NULL, NULL); 610 611 <span class="keyword">return</span> 0; 612} 613</pre> 614 <p> 615 To close a connection, it suffices to use: 616 </p> 617 <pre class="code"> 618<span class="type">void</span> xcb_disconnect (<span class="type">xcb_connection_t</span> *c); 619</pre> 620 <div class="comp"> 621 <div class="title"> 622 Comparison Xlib/XCB 623 </div> 624 <div class="xlib"> 625 <ul> 626 <li>XOpenDisplay () 627 </ul> 628 </div> 629 <div class="xcb"> 630 <ul> 631 <li>xcb_connect () 632 </ul> 633 </div> 634 <div class="xlib"> 635 <ul> 636 <li>XCloseDisplay () 637 </ul> 638 </div> 639 <div class="xcb"> 640 <ul> 641 <li>xcb_disconnect () 642 </ul> 643 </div> 644 </div> 645 <br> 646 <li class="title"><a name="screen">Checking basic information about a connection</a> 647 <p> 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 653 structure: 654 </p> 655 <pre class="code"> 656typedef struct { 657 xcb_window_t root; 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; 670 uint8_t save_unders; 671 uint8_t root_depth; 672 uint8_t allowed_depths_len; 673} xcb_screen_t; 674</pre> 675 <p> 676 We could retrieve the first screen of the connection by using the 677 following function: 678 </p> 679 <pre class="code"> 680xcb_screen_iterator_t xcb_setup_roots_iterator (xcb_setup_t *R); 681</pre> 682 <p> 683 Here is a small program that shows how to use this function: 684 </p> 685 <pre class="code"> 686#include <stdio.h> 687 688#include <xcb/xcb.h> 689 690int 691main () 692{ 693 xcb_connection_t *c; 694 xcb_screen_t *screen; 695 int screen_nbr; 696 xcb_screen_iterator_t iter; 697 698 /* Open the connection to the X server. Use the DISPLAY environment variable */ 699 c = xcb_connect (NULL, &screen_nbr); 700 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) { 705 screen = iter.data; 706 break; 707 } 708 709 printf ("\n"); 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); 715 printf ("\n"); 716 717 return 0; 718} 719</pre> 720 <li class="title"><a name="helloworld">Creating a basic window - the "hello world" program</a> 721 <p> 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: 725 </p> 726 <pre class="code"> 727typedef uint32_t xcb_window_t; 728</pre> 729 <p> 730 We first ask for a new Id for our window, with this function: 731 </p> 732 <pre class="code"> 733xcb_window_t xcb_generate_id(xcb_connection_t *c); 734</pre> 735 <p> 736 Then, XCB supplies the following function to create new windows: 737 </p> 738 <pre class="code"> 739xcb_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) */ 748 uint16_t _class, 749 xcb_visualid_t visual, 750 uint32_t value_mask, 751 const uint32_t *value_list); 752</pre> 753 <p> 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 758 prototype is 759 </p> 760 <pre class="code"> 761xcb_void_cookie_t xcb_map_window (xcb_connection_t *c, 762 xcb_window_t window); 763</pre> 764 <p> 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: 767 </p> 768 <pre class="code"> 769#include <unistd.h> /* pause() */ 770 771#include <xcb/xcb.h> 772 773int 774main () 775{ 776 xcb_connection_t *c; 777 xcb_screen_t *screen; 778 xcb_window_t win; 779 780 /* Open the connection to the X server */ 781 c = xcb_connect (NULL, NULL); 782 783 /* Get the first screen */ 784 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; 785 786 /* Ask for our window's Id */ 787 win = xcb_generate_id(c); 788 789 /* Create the window */ 790 xcb_create_window (c, /* Connection */ 791 XCB_COPY_FROM_PARENT, /* depth (same as root)*/ 792 win, /* window Id */ 793 screen->root, /* parent window */ 794 0, 0, /* x, y */ 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 */ 800 801 /* Map the window on the screen */ 802 xcb_map_window (c, win); 803 804 /* Make sure commands are sent before we pause, so window is shown */ 805 xcb_flush (c); 806 807 pause (); /* hold client until Ctrl-C */ 808 809 return 0; 810} 811</pre> 812 <p> 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>: 817 </p> 818 <pre class="code"> 819int xcb_flush (xcb_connection_t *c); 820</pre> 821 <p> 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>: 826 </p> 827 <pre class="code"> 828int xcb_aux_sync (xcb_connection_t *c); 829</pre> 830 <p> 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. 836 </p> 837 <p> 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 847 program. 848 </p> 849 <p> 850 <b>TODO</b>: one should tell what these functions return and 851 about the generic error 852 </p> 853 <div class="comp"> 854 <div class="title"> 855 Comparison Xlib/XCB 856 </div> 857 <div class="xlib"> 858 <ul> 859 <li>XCreateWindow () 860 </ul> 861 </div> 862 <div class="xcb"> 863 <ul> 864 <li>xcb_generate_id () 865 <li>xcb_create_window () 866 </ul> 867 </div> 868 </div> 869 <br> 870 <li class="title"><a name="drawing">Drawing in a window</a> 871 <p> 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. 877 </p> 878 <ol> 879 <li class="subtitle"><a name="allocgc">Allocating a Graphics Context</a> 880 <p> 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: 887 </p> 888 <pre class="code"> 889typedef uint32_t xcb_gcontext_t; 890</pre> 891 <p> 892 We first ask the X server to attribute an Id to our graphic 893 context with this function: 894 </p> 895 <pre class="code"> 896xcb_gcontext_t xcb_generate_id (xcb_connection_t *c); 897</pre> 898 <p> 899 Then, we set the attributes of the graphic context with this function: 900 </p> 901 <pre class="code"> 902xcb_void_cookie_t xcb_create_gc (xcb_connection_t *c, 903 xcb_gcontext_t cid, 904 xcb_drawable_t drawable, 905 uint32_t value_mask, 906 const uint32_t *value_list); 907</pre> 908 <p> 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. 912 </p> 913 <pre class="code"> 914#include <xcb/xcb.h> 915 916int 917main () 918{ 919 xcb_connection_t *c; 920 xcb_screen_t *screen; 921 xcb_drawable_t win; 922 xcb_gcontext_t black; 923 uint32_t mask; 924 uint32_t value[1]; 925 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; 929 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); 936 937 return 0; 938} 939</pre> 940 <p> 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 954 default values. 955 </p> 956 <p> 957 See the next Subsection for more details. 958 </p> 959 <div class="comp"> 960 <div class="title"> 961 Comparison Xlib/XCB 962 </div> 963 <div class="xlib"> 964 <ul> 965 <li>XCreateGC () 966 </ul> 967 </div> 968 <div class="xcb"> 969 <ul> 970 <li>xcb_generate_id () 971 <li>xcb_create_gc () 972 </ul> 973 </div> 974 </div> 975 <br> 976 <li class="subtitle"><a name="changegc">Changing the attributes of a Graphics Context</a> 977 <p> 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 982 color and 983 <a href="#assigningfont">Assigning a Font to a Graphic Context</a>). 984 This is done by using this function: 985 </p> 986 <pre class="code"> 987xcb_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 */ 991</pre> 992 <p> 993 The <span class="code">value_mask</span> parameter could take 994 any combination of these masks from the xcb_gc_t enumeration: 995 </p> 996 <ul> 997 <li>XCB_GC_FUNCTION 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 1007 <li>XCB_GC_TILE 1008 <li>XCB_GC_STIPPLE 1009 <li>XCB_GC_TILE_STIPPLE_ORIGIN_X 1010 <li>XCB_GC_TILE_STIPPLE_ORIGIN_Y 1011 <li>XCB_GC_FONT 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 1019 <li>XCB_GC_ARC_MODE 1020 </ul> 1021 <p> 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. 1030 </p> 1031 <p> 1032 <b>TODO</b>: set the links of the 3 subsections, once they will 1033 be written :) 1034 </p> 1035 <p> 1036 <b>TODO</b>: give an example which sets several attributes. 1037 </p> 1038 <li class="subtitle"><a name="drawingprim">Drawing primitives: point, line, box, circle,...</a> 1039 <p> 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 1043 how they are used. 1044 </p> 1045 <p> 1046 To draw a point, or several points, we use 1047 </p> 1048 <pre class="code"> 1049xcb_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 */ 1055</pre> 1056 <p> 1057 The <span class="code">coordinate_mode</span> parameter 1058 specifies the coordinate mode. Available values are 1059 </p> 1060 <ul> 1061 <li><span class="code">XCB_COORD_MODE_ORIGIN</span> 1062 <li><span class="code">XCB_COORD_MODE_PREVIOUS</span> 1063 </ul> 1064 <p> 1065 If XCB_COORD_MODE_PREVIOUS is used, then all points but the first one 1066 are relative to the immediately previous point. 1067 </p> 1068 <p> 1069 The <span class="code">xcb_point_t</span> type is just a 1070 structure with two fields (the coordinates of the point): 1071 </p> 1072 <pre class="code"> 1073typedef struct { 1074 int16_t x; 1075 int16_t y; 1076} xcb_point_t; 1077</pre> 1078 <p> 1079 You could see an example in xpoints.c. <b>TODO</b> Set the link. 1080 </p> 1081 <p> 1082 To draw a line, or a polygonal line, we use 1083 </p> 1084 <pre class="code"> 1085xcb_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 */ 1091</pre> 1092 <p> 1093 This function will draw the line between the first and the 1094 second points, then the line between the second and the third 1095 points, and so on. 1096 </p> 1097 <p> 1098 To draw a segment, or several segments, we use 1099 </p> 1100 <pre class="code"> 1101xcb_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 */ 1106</pre> 1107 <p> 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): 1111 </p> 1112 <pre class="code"> 1113typedef struct { 1114 int16_t x1; 1115 int16_t y1; 1116 int16_t x2; 1117 int16_t y2; 1118} xcb_segment_t; 1119</pre> 1120 <p> 1121 To draw a rectangle, or several rectangles, we use 1122 </p> 1123 <pre class="code"> 1124xcb_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 */ 1129</pre> 1130 <p> 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): 1134 </p> 1135 <pre class="code"> 1136typedef struct { 1137 int16_t x; 1138 int16_t y; 1139 uint16_t width; 1140 uint16_t height; 1141} xcb_rectangle_t; 1142</pre> 1143 <!-- There's no coordinate_mode. Is it normal? --> 1144 <!-- [iano] Yes, it's not in the protocol. --> 1145 <p> 1146 To draw an elliptical arc, or several elliptical arcs, we use 1147 </p> 1148 <pre class="code"> 1149xcb_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 */ 1154</pre> 1155 <p> 1156 The <span class="code">xcb_arc_t</span> type is a structure with 1157 six fields: 1158 </p> 1159 <pre class="code"> 1160typedef struct { 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 */ 1167} xcb_arc_t; 1168</pre> 1169 <div class="emph"> 1170 <p> 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. 1177 </p> 1178 </div> 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. --> 1184 <p> 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. 1188 </p> 1189 <p> 1190 To Fill a polygon defined by the points given as arguments , 1191 we use 1192 </p> 1193 <pre class="code"> 1194xcb_void_cookie_t xcb_fill_poly (xcb_connection_t *c, 1195 xcb_drawable_t drawable, 1196 xcb_gcontext_t gc, 1197 uint8_t shape, 1198 uint8_t coordinate_mode, 1199 uint32_t points_len, 1200 const xcb_point_t *points); 1201</pre> 1202 <p> 1203 The <span class="code">shape</span> parameter specifies a 1204 shape that helps the server to improve performance. Available 1205 values are 1206 </p> 1207 <ul> 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> 1211 </ul> 1212 <p> 1213 To fill one or several rectangles, we use 1214 </p> 1215 <pre class="code"> 1216xcb_void_cookie_t xcb_poly_fill_rectangle (xcb_connection_t *c, 1217 xcb_drawable_t drawable, 1218 xcb_gcontext_t gc, 1219 uint32_t rectangles_len, 1220 const xcb_rectangle_t *rectangles); 1221</pre> 1222 <p> 1223 To fill one or several arcs, we use 1224 </p> 1225 <pre class="code"> 1226xcb_void_cookie_t xcb_poly_fill_arc (xcb_connection_t *c, 1227 xcb_drawable_t drawable, 1228 xcb_gcontext_t gc, 1229 uint32_t arcs_len, 1230 const xcb_arc_t *arcs); 1231</pre> 1232 <br> 1233 <a name="points.c"></a> 1234 <p> 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. 1239 </p> 1240 <p> 1241 <b>TODO:</b> Use screen->root_depth for depth parameter. 1242 </p> 1243 <pre class="code"> 1244#include <stdlib.h> 1245#include <stdio.h> 1246 1247#include <xcb/xcb.h> 1248 1249int 1250main () 1251{ 1252 xcb_connection_t *c; 1253 xcb_screen_t *screen; 1254 xcb_drawable_t win; 1255 xcb_gcontext_t foreground; 1256 xcb_generic_event_t *e; 1257 uint32_t mask = 0; 1258 uint32_t values[2]; 1259 1260 /* geometric objects */ 1261 xcb_point_t points[] = { 1262 {10, 10}, 1263 {10, 20}, 1264 {20, 10}, 1265 {20, 20}}; 1266 1267 xcb_point_t polyline[] = { 1268 {50, 10}, 1269 { 5, 20}, /* rest of points are relative */ 1270 {25,-20}, 1271 {10, 10}}; 1272 1273 xcb_segment_t segments[] = { 1274 {100, 10, 140, 30}, 1275 {110, 25, 130, 60}}; 1276 1277 xcb_rectangle_t rectangles[] = { 1278 { 10, 50, 40, 20}, 1279 { 80, 50, 10, 40}}; 1280 1281 xcb_arc_t arcs[] = { 1282 {10, 100, 60, 40, 0, 90 << 6}, 1283 {90, 100, 55, 40, 0, 270 << 6}}; 1284 1285 /* Open the connection to the X server */ 1286 c = xcb_connect (NULL, NULL); 1287 1288 /* Get the first screen */ 1289 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; 1290 1291 /* Create black (foreground) graphic context */ 1292 win = screen->root; 1293 1294 foreground = xcb_generate_id (c); 1295 mask = XCB_GC_FOREGROUND | XCB_GC_GRAPHICS_EXPOSURES; 1296 values[0] = screen->black_pixel; 1297 values[1] = 0; 1298 xcb_create_gc (c, foreground, win, mask, values); 1299 1300 /* Ask for our window's Id */ 1301 win = xcb_generate_id(c); 1302 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 */ 1311 0, 0, /* x, y */ 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 */ 1317 1318 /* Map the window on the screen */ 1319 xcb_map_window (c, win); 1320 1321 1322 /* We flush the request */ 1323 xcb_flush (c); 1324 1325 while ((e = xcb_wait_for_event (c))) { 1326 switch (e->response_type & ~0x80) { 1327 case XCB_EXPOSE: { 1328 /* We draw the points */ 1329 xcb_poly_point (c, XCB_COORD_MODE_ORIGIN, win, foreground, 4, points); 1330 1331 /* We draw the polygonal line */ 1332 xcb_poly_line (c, XCB_COORD_MODE_PREVIOUS, win, foreground, 4, polyline); 1333 1334 /* We draw the segments */ 1335 xcb_poly_segment (c, win, foreground, 2, segments); 1336 1337 /* We draw the rectangles */ 1338 xcb_poly_rectangle (c, win, foreground, 2, rectangles); 1339 1340 /* We draw the arcs */ 1341 xcb_poly_arc (c, win, foreground, 2, arcs); 1342 1343 /* We flush the request */ 1344 xcb_flush (c); 1345 1346 break; 1347 } 1348 default: { 1349 /* Unknown event type, ignore it */ 1350 break; 1351 } 1352 } 1353 /* Free the Generic Event */ 1354 free (e); 1355 } 1356 1357 return 0; 1358} 1359</pre> 1360 </ol> 1361 <li class="title"><a name="xevents">X Events</a> 1362 <p> 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. 1371 </p> 1372 <ol> 1373 <li class="subtitle"><a name="register">Registering for event types using event masks</a> 1374 <p> 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 ?) 1382 </p> 1383 <p> 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: 1388 </p> 1389 <pre class="code"> 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, 1394 0, 0, 150, 150, 10, 1395 XCB_WINDOW_CLASS_INPUT_OUTPUT, root->root_visual, 1396 mask, valwin); 1397</pre> 1398 <p> 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: 1402 </p> 1403 <pre class="code"> 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, 1408 0, 0, 150, 150, 10, 1409 XCB_WINDOW_CLASS_INPUT_OUTPUT, root->root_visual, 1410 mask, valwin); 1411</pre> 1412 <p> 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 1416 event sub-types. 1417 </p> 1418 <p> 1419 The values that a mask could take are given 1420 by the <span class="code">xcb_cw_t</span> enumeration: 1421 </p> 1422 <pre class="code"> 1423typedef enum { 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 1439} xcb_cw_t; 1440</pre> 1441 <div class="emph"> 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 1445 example: 1446 </p> 1447 </div> 1448 <pre class="code"> 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 */ 1453</pre> 1454 <p> 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: 1463 </p> 1464 <pre class="code"> 1465const static uint32_t values[] = { XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_BUTTON_PRESS }; 1466 1467/* The connection c and the window win are supposed to be defined */ 1468 1469xcb_change_window_attributes (c, win, XCB_CW_EVENT_MASK, values); 1470</pre> 1471 <div class="emph"> 1472 <p> 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. 1480 </p> 1481 </div> 1482 <li class="subtitle"><a name="loop">Receiving events: writing the events loop</a> 1483 <p> 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 1487 a non-blocking way: 1488 </p> 1489 <ul> 1490 <li> 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. 1497 1498 <br> 1499 <li> 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 1507 status. 1508 </ul> 1509 <p> 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>: 1515 </p> 1516 <pre class="code"> 1517 xcb_generic_event_t *e; 1518 1519 while ((e = xcb_wait_for_event (c))) { 1520 switch (e->response_type & ~0x80) { 1521 case XCB_EXPOSE: { 1522 /* Handle the Expose event type */ 1523 xcb_expose_event_t *ev = (xcb_expose_event_t *)e; 1524 1525 /* ... */ 1526 1527 break; 1528 } 1529 case XCB_BUTTON_PRESS: { 1530 /* Handle the ButtonPress event type */ 1531 xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e; 1532 1533 /* ... */ 1534 1535 break; 1536 } 1537 default: { 1538 /* Unknown event type, ignore it */ 1539 break; 1540 } 1541 } 1542 /* Free the Generic Event */ 1543 free (e); 1544 } 1545</pre> 1546 <p> 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>: 1552 </p> 1553 <pre class="code"> 1554 while (XPending (display)) { 1555 XEvent ev; 1556 1557 XNextEvent(d, &ev); 1558 1559 /* Manage your event */ 1560 } 1561</pre> 1562 <p> 1563 Such a loop in XCB looks like: 1564 </p> 1565 <pre class="code"> 1566 xcb_generic_event_t *ev; 1567 1568 while ((ev = xcb_poll_for_event (conn, 0))) { 1569 /* Manage your event */ 1570 } 1571</pre> 1572 <p> 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. 1578 </p> 1579 <div class="comp"> 1580 <div class="title"> 1581 Comparison Xlib/XCB 1582 </div> 1583 <div class="xlib"> 1584 <ul> 1585 <li>XNextEvent () 1586 </ul> 1587 </div> 1588 <div class="xcb"> 1589 <ul> 1590 <li>xcb_wait_for_event () 1591 </ul> 1592 </div> 1593 <div class="xlib"> 1594 <ul> 1595 <li>XPending () 1596 <li>XCheckMaskEvent () 1597 </ul> 1598 </div> 1599 <div class="xcb"> 1600 <ul> 1601 <li>xcb_poll_for_event () 1602 </ul> 1603 </div> 1604 </div> 1605 <br> 1606 <li class="subtitle"><a name="expose">Expose events</a> 1607 <p> 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: 1611 </p> 1612 <ul> 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. 1618 </ul> 1619 <p> 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. 1629 </p> 1630 <p> 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 1633 structure: 1634 </p> 1635 <pre class="code"> 1636typedef struct { 1637 uint8_t response_type; /* The type of the event, here it is XCB_EXPOSE */ 1638 uint8_t pad0; 1639 uint16_t sequence; 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 */ 1646 uint16_t count; 1647} xcb_expose_event_t; 1648</pre> 1649 <li class="subtitle"><a name="userinput">Getting user input</a> 1650 <p> 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. 1656 </p> 1657 <ol> 1658 <li class="subsubtitle"><a name="mousepressrelease">Mouse button press and release events</a> 1659 <p> 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: 1664 </p> 1665 <ul> 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. 1670 </ul> 1671 <p> 1672 The structure to be checked for in our events loop is the 1673 same for these two events, and is the following: 1674 </p> 1675 <pre class="code"> 1676typedef struct { 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; 1679 uint16_t sequence; 1680 xcb_timestamp_t time; /* Time, in milliseconds the event took place in */ 1681 xcb_window_t root; 1682 xcb_window_t event; 1683 xcb_window_t child; 1684 int16_t root_x; 1685 int16_t root_y; 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; 1691 1692typedef xcb_button_press_event_t xcb_button_release_event_t; 1693</pre> 1694 <p> 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). 1699 </p> 1700 <p> 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): 1704 </p> 1705 <ul> 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> 1719 </ul> 1720 <p> 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). 1725 </p> 1726 <p> 1727 <b>TODO:</b> Problem: it seems that the state does not 1728 change when clicking with various buttons. 1729 </p> 1730 <li class="subsubtitle"><a name="mousemvnt">Mouse movement events</a> 1731 <p> 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: 1740 </p> 1741 <ul> 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 1747 is held pressed. 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. 1757 </ul> 1758 <p> 1759 The structure to be checked for in our events loop is the 1760 same for these events, and is the following: 1761 </p> 1762 <pre class="code"> 1763typedef struct { 1764 uint8_t response_type; /* The type of the event */ 1765 uint8_t detail; 1766 uint16_t sequence; 1767 xcb_timestamp_t time; /* Time, in milliseconds the event took place in */ 1768 xcb_window_t root; 1769 xcb_window_t event; 1770 xcb_window_t child; 1771 int16_t root_x; 1772 int16_t root_y; 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; 1778</pre> 1779 <li class="subsubtitle"><a name="mouseenter">Mouse pointer enter and leave events</a> 1780 <p> 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 1787 create our window: 1788 </p> 1789 <ul> 1790 <li><span class="code">xcb_event_enter_window_t</span>: notify us 1791 when the mouse pointer enters any of our controlled 1792 windows. 1793 <li><span class="code">xcb_event_leave_window_t</span>: notify us 1794 when the mouse pointer leaves any of our controlled 1795 windows. 1796 </ul> 1797 <p> 1798 The structure to be checked for in our events loop is the 1799 same for these two events, and is the following: 1800 </p> 1801 <pre class="code"> 1802typedef struct { 1803 uint8_t response_type; /* The type of the event */ 1804 uint8_t detail; 1805 uint16_t sequence; 1806 xcb_timestamp_t time; /* Time, in milliseconds the event took place in */ 1807 xcb_window_t root; 1808 xcb_window_t event; 1809 xcb_window_t child; 1810 int16_t root_x; 1811 int16_t root_y; 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; 1818 1819typedef xcb_enter_notify_event_t xcb_leave_notify_event_t; 1820</pre> 1821 <li class="subsubtitle"><a name="focus">The keyboard focus</a> 1822 <p> 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...). 1835 </p> 1836 <li class="subsubtitle"><a name="keypress">Keyboard press and release events</a> 1837 <p> 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: 1842 </p> 1843 <ul> 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 1846 the keyboard focus. 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. 1850 </ul> 1851 <p> 1852 The structure to be checked for in our events loop is the 1853 same for these two events, and is the following: 1854 </p> 1855 <pre class="code"> 1856typedef struct { 1857 uint8_t response_type; /* The type of the event */ 1858 xcb_keycode_t detail; 1859 uint16_t sequence; 1860 xcb_timestamp_t time; /* Time, in milliseconds the event took place in */ 1861 xcb_window_t root; 1862 xcb_window_t event; 1863 xcb_window_t child; 1864 int16_t root_x; 1865 int16_t root_y; 1866 int16_t event_x; 1867 int16_t event_y; 1868 uint16_t state; 1869 uint8_t same_screen; 1870} xcb_key_press_event_t; 1871 1872typedef xcb_key_press_event_t xcb_key_release_event_t; 1873</pre> 1874 <p> 1875 The <span class="code">detail</span> field refers to the 1876 physical key on the keyboard. 1877 </p> 1878 <p> 1879 <b>TODO:</b> Talk about getting the ASCII code from the key code. 1880 </p> 1881 </ol> 1882 <li class="subtitle"><a name="eventex">X events: a complete example</a> 1883 <p> 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 1889 described above. 1890 </p> 1891 <pre class="code"> 1892#include <stdlib.h> 1893#include <stdio.h> 1894 1895#include <xcb/xcb.h> 1896 1897void 1898print_modifiers (uint32_t mask) 1899{ 1900 const char **mod, *mods[] = { 1901 "Shift", "Lock", "Ctrl", "Alt", 1902 "Mod2", "Mod3", "Mod4", "Mod5", 1903 "Button1", "Button2", "Button3", "Button4", "Button5" 1904 }; 1905 printf ("Modifier mask: "); 1906 for (mod = mods ; mask; mask >>= 1, mod++) 1907 if (mask & 1) 1908 printf(*mod); 1909 putchar ('\n'); 1910} 1911 1912int 1913main () 1914{ 1915 xcb_connection_t *c; 1916 xcb_screen_t *screen; 1917 xcb_window_t win; 1918 xcb_generic_event_t *e; 1919 uint32_t mask = 0; 1920 uint32_t values[2]; 1921 1922 /* Open the connection to the X server */ 1923 c = xcb_connect (NULL, NULL); 1924 1925 /* Get the first screen */ 1926 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; 1927 1928 /* Ask for our window's Id */ 1929 win = xcb_generate_id (c); 1930 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 */ 1939 0, /* depth */ 1940 win, /* window Id */ 1941 screen->root, /* parent window */ 1942 0, 0, /* x, y */ 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 */ 1948 1949 /* Map the window on the screen */ 1950 xcb_map_window (c, win); 1951 1952 xcb_flush (c); 1953 1954 while ((e = xcb_wait_for_event (c))) { 1955 switch (e->response_type & ~0x80) { 1956 case XCB_EXPOSE: { 1957 xcb_expose_event_t *ev = (xcb_expose_event_t *)e; 1958 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); 1961 break; 1962 } 1963 case XCB_BUTTON_PRESS: { 1964 xcb_button_press_event_t *ev = (xcb_button_press_event_t *)e; 1965 print_modifiers(ev->state); 1966 1967 switch (ev->detail) { 1968 case 4: 1969 printf ("Wheel Button up in window %ld, at coordinates (%d,%d)\n", 1970 ev->event, ev->event_x, ev->event_y); 1971 break; 1972 case 5: 1973 printf ("Wheel Button down in window %ld, at coordinates (%d,%d)\n", 1974 ev->event, ev->event_x, ev->event_y); 1975 break; 1976 default: 1977 printf ("Button %d pressed in window %ld, at coordinates (%d,%d)\n", 1978 ev->detail, ev->event, ev->event_x, ev->event_y); 1979 } 1980 break; 1981 } 1982 case XCB_BUTTON_RELEASE: { 1983 xcb_button_release_event_t *ev = (xcb_button_release_event_t *)e; 1984 print_modifiers(ev->state); 1985 1986 printf ("Button %d released in window %ld, at coordinates (%d,%d)\n", 1987 ev->detail, ev->event, ev->event_x, ev->event_y); 1988 break; 1989 } 1990 case XCB_MOTION_NOTIFY: { 1991 xcb_motion_notify_event_t *ev = (xcb_motion_notify_event_t *)e; 1992 1993 printf ("Mouse moved in window %ld, at coordinates (%d,%d)\n", 1994 ev->event, ev->event_x, ev->event_y); 1995 break; 1996 } 1997 case XCB_ENTER_NOTIFY: { 1998 xcb_enter_notify_event_t *ev = (xcb_enter_notify_event_t *)e; 1999 2000 printf ("Mouse entered window %ld, at coordinates (%d,%d)\n", 2001 ev->event, ev->event_x, ev->event_y); 2002 break; 2003 } 2004 case XCB_LEAVE_NOTIFY: { 2005 xcb_leave_notify_event_t *ev = (xcb_leave_notify_event_t *)e; 2006 2007 printf ("Mouse left window %ld, at coordinates (%d,%d)\n", 2008 ev->event, ev->event_x, ev->event_y); 2009 break; 2010 } 2011 case XCB_KEY_PRESS: { 2012 xcb_key_press_event_t *ev = (xcb_key_press_event_t *)e; 2013 print_modifiers(ev->state); 2014 2015 printf ("Key pressed in window %ld\n", 2016 ev->event); 2017 break; 2018 } 2019 case XCB_KEY_RELEASE: { 2020 xcb_key_release_event_t *ev = (xcb_key_release_event_t *)e; 2021 print_modifiers(ev->state); 2022 2023 printf ("Key released in window %ld\n", 2024 ev->event); 2025 break; 2026 } 2027 default: 2028 /* Unknown event type, ignore it */ 2029 printf("Unknown event: %d\n", e->response_type); 2030 break; 2031 } 2032 /* Free the Generic Event */ 2033 free (e); 2034 } 2035 2036 return 0; 2037} 2038</pre> 2039 </ol> 2040 <li class="title"><a name="font">Handling text and fonts</a> 2041 <p> 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. 2048 </p> 2049 <ol> 2050 <li class="subtitle"><a name="fontstruct">The Font structure</a> 2051 <p> 2052 In order to support flexible fonts, a font type is 2053 defined. You know what ? It's an Id: 2054 </p> 2055 <pre class="code"> 2056typedef uint32_t xcb_font_t; 2057</pre> 2058 <p> 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 2062 function: 2063 </p> 2064 <pre class="code"> 2065xcb_font_t xcb_generate_id (xcb_connection_t *c); 2066</pre> 2067 <br> 2068 <li class="subtitle"><a name="openingfont">Opening a Font</a> 2069 <p> 2070 To open a font, we use the following function: 2071 </p> 2072 <pre class="code"> 2073xcb_void_cookie_t xcb_open_font (xcb_connection_t *c, 2074 xcb_font_t fid, 2075 uint16_t name_len, 2076 const char *name); 2077</pre> 2078 <p> 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>). 2087 </p> 2088 <li class="subtitle"><a name="assigningfont">Assigning a Font to a Graphic Context</a> 2089 <p> 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 2095 white background: 2096 </p> 2097 <pre class="code"> 2098 /* 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 2103 */ 2104 2105 uint32_t value_list[3]; 2106 xcb_gcontext_t gc; 2107 uint32_t mask; 2108 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); 2115 2116 /* The font is not needed anymore, so we close it */ 2117 xcb_close_font (c, font); 2118</pre> 2119 <li class="subtitle"><a name="drawingtext">Drawing text in a drawable</a> 2120 <p> 2121 To draw a text in a drawable, we use the following function: 2122 </p> 2123 <pre class="code"> 2124xcb_void_cookie_t xcb_image_text_8 (xcb_connection_t *c, 2125 uint8_t string_len, 2126 xcb_drawable_t drawable, 2127 xcb_gcontext_t gc, 2128 int16_t x, 2129 int16_t y, 2130 const char *string); 2131</pre> 2132 <p> 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>. 2138 </p> 2139 <li class="subtitle"><a name="fontcompleteexample">Complete example</a> 2140 <p> 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. 2143 </p> 2144 <pre class="code"> 2145#include <stdlib.h> 2146#include <stdio.h> 2147#include <string.h> 2148 2149#include <xcb/xcb.h> 2150 2151#define WIDTH 300 2152#define HEIGHT 100 2153 2154 2155 2156static 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); 2160 2161static void text_draw (xcb_connection_t *c, 2162 xcb_screen_t *screen, 2163 xcb_window_t window, 2164 int16_t x1, 2165 int16_t y1, 2166 const char *label); 2167 2168static void 2169text_draw (xcb_connection_t *c, 2170 xcb_screen_t *screen, 2171 xcb_window_t window, 2172 int16_t x1, 2173 int16_t y1, 2174 const char *label) 2175{ 2176 xcb_void_cookie_t cookie_gc; 2177 xcb_void_cookie_t cookie_text; 2178 xcb_generic_error_t *error; 2179 xcb_gcontext_t gc; 2180 uint8_t length; 2181 2182 length = strlen (label); 2183 2184 gc = gc_font_get(c, screen, window, "7x13"); 2185 2186 cookie_text = xcb_image_text_8_checked (c, length, window, gc, 2187 x1, 2188 y1, label); 2189 error = xcb_request_check (c, cookie_text); 2190 if (error) { 2191 fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code); 2192 xcb_disconnect (c); 2193 exit (-1); 2194 } 2195 2196 cookie_gc = xcb_free_gc (c, gc); 2197 error = xcb_request_check (c, cookie_gc); 2198 if (error) { 2199 fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code); 2200 xcb_disconnect (c); 2201 exit (-1); 2202 } 2203} 2204 2205static xcb_gc_t 2206gc_font_get (xcb_connection_t *c, 2207 xcb_screen_t *screen, 2208 xcb_window_t window, 2209 const char *font_name) 2210{ 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; 2215 xcb_font_t font; 2216 xcb_gcontext_t gc; 2217 uint32_t mask; 2218 2219 font = xcb_generate_id (c); 2220 cookie_font = xcb_open_font_checked (c, font, 2221 strlen (font_name), 2222 font_name); 2223 2224 error = xcb_request_check (c, cookie_font); 2225 if (error) { 2226 fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code); 2227 xcb_disconnect (c); 2228 return -1; 2229 } 2230 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); 2238 if (error) { 2239 fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code); 2240 xcb_disconnect (c); 2241 exit (-1); 2242 } 2243 2244 cookie_font = xcb_close_font_checked (c, font); 2245 error = xcb_request_check (c, cookie_font); 2246 if (error) { 2247 fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code); 2248 xcb_disconnect (c); 2249 exit (-1); 2250 } 2251 2252 return gc; 2253} 2254 2255int main () 2256{ 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; 2266 uint32_t mask; 2267 uint32_t values[2]; 2268 int screen_number; 2269 2270 /* getting the connection */ 2271 c = xcb_connect (NULL, &screen_number); 2272 if (!c) { 2273 fprintf (stderr, "ERROR: can't connect to an X server\n"); 2274 return -1; 2275 } 2276 2277 /* getting the current screen */ 2278 setup = xcb_get_setup (c); 2279 2280 screen = NULL; 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) 2284 { 2285 screen = screen_iter.data; 2286 break; 2287 } 2288 if (!screen) { 2289 fprintf (stderr, "ERROR: can't get the current screen\n"); 2290 xcb_disconnect (c); 2291 return -1; 2292 } 2293 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; 2298 values[1] = 2299 XCB_EVENT_MASK_KEY_RELEASE | 2300 XCB_EVENT_MASK_EXPOSURE; 2301 cookie_window = xcb_create_window_checked (c, 2302 screen->root_depth, 2303 window, screen->root, 2304 20, 200, WIDTH, HEIGHT, 2305 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, 2306 screen->root_visual, 2307 mask, values); 2308 cookie_map = xcb_map_window_checked (c, window); 2309 2310 /* error managing */ 2311 error = xcb_request_check (c, cookie_window); 2312 if (error) { 2313 fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code); 2314 xcb_disconnect (c); 2315 return -1; 2316 } 2317 error = xcb_request_check (c, cookie_map); 2318 if (error) { 2319 fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code); 2320 xcb_disconnect (c); 2321 return -1; 2322 } 2323 2324 xcb_flush(c); 2325 2326 while (1) { 2327 e = xcb_poll_for_event(c); 2328 if (e) { 2329 switch (e->response_type & ~0x80) { 2330 case XCB_EXPOSE: { 2331 char *text; 2332 2333 text = "Press ESC key to exit..."; 2334 text_draw (c, screen, window, 10, HEIGHT - 10, text); 2335 break; 2336 } 2337 case XCB_KEY_RELEASE: { 2338 xcb_key_release_event_t *ev; 2339 2340 ev = (xcb_key_release_event_t *)e; 2341 2342 switch (ev->detail) { 2343 /* ESC */ 2344 case 9: 2345 free (e); 2346 xcb_disconnect (c); 2347 return 0; 2348 } 2349 } 2350 } 2351 free (e); 2352 } 2353 } 2354 2355 return 0; 2356} 2357</pre> 2358 </ol> 2359 <li class="title"><a name="wm">Interacting with the window manager</a> 2360 <p> 2361 After we have seen how to create windows and draw on them, we 2362 take one step back, and look at how our windows are interacting 2363 with their environment (the full screen and the other 2364 windows). First of all, our application needs to interact with 2365 the window manager. The window manager is responsible to 2366 decorating drawn windows (i.e. adding a frame, an iconify 2367 button, a system menu, a title bar, etc), as well as handling 2368 icons shown when windows are being iconified. It also handles 2369 ordering of windows on the screen, and other administrative 2370 tasks. We need to give it various hints as to how we want it to 2371 treat our application's windows. 2372 </p> 2373 <ol> 2374 <li class="subtitle"><a name="wmprop">Window properties</a> 2375 <p> 2376 Many of the parameters communicated to the window manager are 2377 passed using data called "properties". These properties are 2378 attached by the X server to different windows, and are stored 2379 in a format that makes it possible to read them from different 2380 machines that may use different architectures (remember that 2381 an X client program may run on a remote machine). 2382 </p> 2383 <p> 2384 The property and its type (a string, an integer, etc) are 2385 Id. Their type are <span class="code">xcb_atom_t</span>: 2386 </p> 2387 <pre class="code"> 2388typedef uint32_t xcb_atom_t; 2389</pre> 2390 <p> 2391 To change the property of a window, we use the following 2392 function: 2393 </p> 2394 <pre class="code"> 2395xcb_void_cookie_t xcb_change_property (xcb_connection_t *c, /* Connection to the X server */ 2396 uint8_t mode, /* Property mode */ 2397 xcb_window_t window, /* Window */ 2398 xcb_atom_t property, /* Property to change */ 2399 xcb_atom_t type, /* Type of the property */ 2400 uint8_t format, /* Format of the property (8, 16, 32) */ 2401 uint32_t data_len, /* Length of the data parameter */ 2402 const void *data); /* Data */ 2403</pre> 2404 <p> 2405 The <span class="code">mode</span> parameter could be one of 2406 the following values (defined in enumeration xcb_prop_mode_t in 2407 the xproto.h header file): 2408 </p> 2409 <ul> 2410 <li>XCB_PROP_MODE_REPLACE 2411 <li>XCB_PROP_MODE_PREPEND 2412 <li>XCB_PROP_MODE_APPEND 2413 </ul> 2414 <br> 2415 <li class="subtitle"><a name="wmname">Setting the window name and icon name</a> 2416 <p> 2417 The first thing we want to do would be to set the name for our 2418 window. This is done using the 2419 <span class="code">xcb_change_property()</span> function. This 2420 name may be used by the window manager as the title of the 2421 window (in the title bar), in a task list, etc. The property 2422 atom to use to set the name of a window is 2423 <span class="code">WM_NAME</span> (and 2424 <span class="code">WM_ICON_NAME</span> for the iconified 2425 window) and its type is <span class="code">STRING</span>. Here 2426 is an example of utilization: 2427 </p> 2428 <pre class="code"> 2429#include <string.h> 2430 2431#include <xcb/xcb.h> 2432#include <xcb/xcb_atom.h> 2433 2434int 2435main () 2436{ 2437 xcb_connection_t *c; 2438 xcb_screen_t *screen; 2439 xcb_window_t win; 2440 char *title = "Hello World !"; 2441 char *title_icon = "Hello World ! (iconified)"; 2442 2443 2444 2445 /* Open the connection to the X server */ 2446 c = xcb_connect (NULL, NULL); 2447 2448 /* Get the first screen */ 2449 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; 2450 2451 /* Ask for our window's Id */ 2452 win = xcb_generate_id (c); 2453 2454 /* Create the window */ 2455 xcb_create_window (c, /* Connection */ 2456 0, /* depth */ 2457 win, /* window Id */ 2458 screen->root, /* parent window */ 2459 0, 0, /* x, y */ 2460 250, 150, /* width, height */ 2461 10, /* border_width */ 2462 XCB_WINDOW_CLASS_INPUT_OUTPUT, /* class */ 2463 screen->root_visual, /* visual */ 2464 0, NULL); /* masks, not used */ 2465 2466 /* Set the title of the window */ 2467 xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, 2468 WM_NAME, STRING, 8, 2469 strlen (title), title); 2470 2471 /* Set the title of the window icon */ 2472 xcb_change_property (c, XCB_PROP_MODE_REPLACE, win, 2473 WM_ICON_NAME, STRING, 8, 2474 strlen(title_icon), title_icon); 2475 2476 /* Map the window on the screen */ 2477 xcb_map_window (c, win); 2478 2479 xcb_flush (c); 2480 2481 while (1) {} 2482 2483 return 0; 2484} 2485</pre> 2486 <div class="emph"> 2487 <p>Note: the use of the atoms needs our program to be compiled 2488 and linked against xcb_atom, so that we have to use 2489 </p> 2490 </div> 2491 <pre class="text"> 2492gcc prog.c -o prog `pkg-config --cflags --libs xcb_atom` 2493</pre> 2494 <div class="emph"> 2495 <p> 2496 for the program to compile fine. 2497 </p> 2498 </div> 2499 </ol> 2500 <li class="title"><a name="winop">Simple window operations</a> 2501 <p> 2502 One more thing we can do to our window is manipulate them on the 2503 screen (resize them, move them, raise or lower them, iconify 2504 them, and so on). Some window operations functions are supplied 2505 by XCB for this purpose. 2506 </p> 2507 <ol> 2508 <li class="subtitle"><a name="winmap">Mapping and un-mapping a window</a> 2509 <p> 2510 The first pair of operations we can apply on a window is 2511 mapping it, or un-mapping it. Mapping a window causes the 2512 window to appear on the screen, as we have seen in our simple 2513 window program example. Un-mapping it causes it to be removed 2514 from the screen (although the window as a logical entity still 2515 exists). This gives the effect of making a window hidden 2516 (unmapped) and shown again (mapped). For example, if we have a 2517 dialog box window in our program, instead of creating it every 2518 time the user asks to open it, we can create the window once, 2519 in an un-mapped mode, and when the user asks to open it, we 2520 simply map the window on the screen. When the user clicked the 2521 'OK' or 'Cancel' button, we simply un-map the window. This is 2522 much faster than creating and destroying the window, however, 2523 the cost is wasted resources, both on the client side, and on 2524 the X server side. 2525 </p> 2526 <p> 2527 To map a window, you use the following function: 2528 </p> 2529 <pre class="code"> 2530xcb_void_cookie_t xcb_map_window (xcb_connection_t *c, 2531 xcb_window_t window); 2532</pre> 2533 <p> 2534 To have a simple example, see the <a href="#helloworld">example</a> 2535 above. The mapping operation will cause an 2536 <span class="code">Expose</span> event to be sent to our 2537 application, unless the window is completely covered by other 2538 windows. 2539 </p> 2540 <p> 2541 Un-mapping a window is also simple. You use the function 2542 </p> 2543 <pre class="code"> 2544xcb_void_cookie_t xcb_unmap_window (xcb_connection_t *c, 2545 xcb_window_t window); 2546</pre> 2547 <p> 2548 The utilization of this function is the same as 2549 <span class="code">xcb_map_window()</span>. 2550 </p> 2551 <li class="subtitle"><a name="winconf">Configuring a window</a> 2552 <p> 2553 As we have seen when we have created our first window, in the 2554 X Events subsection, we can set some attributes for the window 2555 (that is, the position, the size, the events the window will 2556 receive, etc). If we want to modify them, but the window is 2557 already created, we can change them by using the following 2558 function: 2559 </p> 2560 <pre class="code"> 2561xcb_void_cookie_t xcb_configure_window (xcb_connection_t *c, /* The connection to the X server*/ 2562 xcb_window_t window, /* The window to configure */ 2563 uint16_t value_mask, /* The mask */ 2564 const uint32_t *value_list); /* The values to set */ 2565</pre> 2566 <p> 2567 We set the <span class="code">value_mask</span> to one or 2568 several mask values that are in the xcb_config_window_t enumeration in the xproto.h header: 2569 </p> 2570 <ul> 2571 <li><span class="code">XCB_CONFIG_WINDOW_X</span>: new x coordinate of the window's top left corner 2572 <li><span class="code">XCB_CONFIG_WINDOW_Y</span>: new y coordinate of the window's top left corner 2573 <li><span class="code">XCB_CONFIG_WINDOW_WIDTH</span>: new width of the window 2574 <li><span class="code">XCB_CONFIG_WINDOW_HEIGHT</span>: new height of the window 2575 <li><span class="code">XCB_CONFIG_WINDOW_BORDER_WIDTH</span>: new width of the border of the window 2576 <li><span class="code">XCB_CONFIG_WINDOW_SIBLING</span> 2577 <li><span class="code">XCB_CONFIG_WINDOW_STACK_MODE</span>: the new stacking order 2578 </ul> 2579 <p> 2580 We then give to <span class="code">value_mask</span> the new 2581 value. We now describe how to use 2582 <span class="code">xcb_configure_window_t</span> in some useful 2583 situations. 2584 </p> 2585 <li class="subtitle"><a name="winmove">Moving a window around the screen</a> 2586 <p> 2587 An operation we might want to do with windows is to move them 2588 to a different location. This can be done like this: 2589 </p> 2590 <pre class="code"> 2591const static uint32_t values[] = { 10, 20 }; 2592 2593/* The connection c and the window win are supposed to be defined */ 2594 2595/* Move the window to coordinates x = 10 and y = 20 */ 2596xcb_configure_window (c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y, values); 2597</pre> 2598 <p> 2599 Note that when the window is moved, it might get partially 2600 exposed or partially hidden by other windows, and thus we 2601 might get <span class="code">Expose</span> events due to this 2602 operation. 2603 </p> 2604 <li class="subtitle"><a name="winsize">Resizing a window</a> 2605 <p> 2606 Yet another operation we can do is to change the size of a 2607 window. This is done using the following code: 2608 </p> 2609 <pre class="code"> 2610const static uint32_t values[] = { 200, 300 }; 2611 2612/* The connection c and the window win are supposed to be defined */ 2613 2614/* Resize the window to width = 10 and height = 20 */ 2615xcb_configure_window (c, win, XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); 2616</pre> 2617 <p> 2618 We can also combine the move and resize operations using one 2619 single call to <span class="code">xcb_configure_window_t</span>: 2620 </p> 2621 <pre class="code"> 2622const static uint32_t values[] = { 10, 20, 200, 300 }; 2623 2624/* The connection c and the window win are supposed to be defined */ 2625 2626/* Move the window to coordinates x = 10 and y = 20 */ 2627/* and resize the window to width = 10 and height = 20 */ 2628xcb_configure_window (c, win, XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT, values); 2629</pre> 2630 <li class="subtitle"><a name="winstack">Changing windows stacking order: raise and lower</a> 2631 <p> 2632 Until now, we changed properties of a single window. We'll see 2633 that there are properties that relate to the window and other 2634 windows. One of them is the stacking order. That is, the order 2635 in which the windows are layered on top of each other. The 2636 front-most window is said to be on the top of the stack, while 2637 the back-most window is at the bottom of the stack. Here is 2638 how to manipulate our windows stack order: 2639 </p> 2640 <pre class="code"> 2641const static uint32_t values[] = { XCB_STACK_MODE_ABOVE }; 2642 2643/* The connection c and the window win are supposed to be defined */ 2644 2645/* Move the window on the top of the stack */ 2646xcb_configure_window (c, win, XCB_CONFIG_WINDOW_STACK_MODE, values); 2647</pre> 2648 <pre class="code"> 2649const static uint32_t values[] = { XCB_STACK_MODE_BELOW }; 2650 2651/* The connection c and the window win are supposed to be defined */ 2652 2653/* Move the window on the bottom of the stack */ 2654xcb_configure_window (c, win, XCB_CONFIG_WINDOW_STACK_MODE, values); 2655</pre> 2656 <li class="subtitle"><a name="wingetinfo">Getting information about a window</a> 2657 <p> 2658 Just like we can set various attributes of our windows, we can 2659 also ask the X server supply the current values of these 2660 attributes. For example, we can check where a window is 2661 located on the screen, what is its current size, whether it is 2662 mapped or not, etc. The structure that contains some of this 2663 information is 2664 </p> 2665 <pre class="code"> 2666typedef struct { 2667 uint8_t response_type; 2668 uint8_t depth; /* depth of the window */ 2669 uint16_t sequence; 2670 uint32_t length; 2671 xcb_window_t root; /* Id of the root window *> 2672 int16_t x; /* X coordinate of the window's location */ 2673 int16_t y; /* Y coordinate of the window's location */ 2674 uint16_t width; /* Width of the window */ 2675 uint16_t height; /* Height of the window */ 2676 uint16_t border_width; /* Width of the window's border */ 2677} xcb_get_geometry_reply_t; 2678</pre> 2679 <p> 2680 XCB fill this structure with two functions: 2681 </p> 2682 <pre class="code"> 2683xcb_get_geometry_cookie_t xcb_get_geometry (xcb_connection_t *c, 2684 xcb_drawable_t drawable); 2685xcb_get_geometry_reply_t *xcb_get_geometry_reply (xcb_connection_t *c, 2686 xcb_get_geometry_cookie_t cookie, 2687 xcb_generic_error_t **e); 2688</pre> 2689 <p> 2690 You use them as follows: 2691 </p> 2692 <pre class="code"> 2693 xcb_connection_t *c; 2694 xcb_drawable_t win; 2695 xcb_get_geometry_reply_t *geom; 2696 2697 /* You initialize c and win */ 2698 2699 geom = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL); 2700 2701 /* Do something with the fields of geom */ 2702 2703 free (geom); 2704</pre> 2705 <p> 2706 Remark that you have to free the structure, as 2707 <span class="code">xcb_get_geometry_reply_t</span> allocates a 2708 newly one. 2709 </p> 2710 <p> 2711 One problem is that the returned location of the window is 2712 relative to its parent window. This makes these coordinates 2713 rather useless for any window manipulation functions, like 2714 moving it on the screen. In order to overcome this problem, we 2715 need to take a two-step operation. First, we find out the Id 2716 of the parent window of our window. We then translate the 2717 above relative coordinates to the screen coordinates. 2718 </p> 2719 <p> 2720 To get the Id of the parent window, we need this structure: 2721 </p> 2722 <pre class="code"> 2723typedef struct { 2724 uint8_t response_type; 2725 uint8_t pad0; 2726 uint16_t sequence; 2727 uint32_t length; 2728 xcb_window_t root; 2729 xcb_window_t parent; /* Id of the parent window */ 2730 uint16_t children_len; 2731 uint8_t pad1[14]; 2732} xcb_query_tree_reply_t; 2733</pre> 2734 <p> 2735 To fill this structure, we use these two functions: 2736 </p> 2737 <pre class="code"> 2738xcb_query_tree_cookie_t xcb_query_tree (xcb_connection_t *c, 2739 xcb_window_t window); 2740xcb_query_tree_reply_t *xcb_query_tree_reply (xcb_connection_t *c, 2741 xcb_query_tree_cookie_t cookie, 2742 xcb_generic_error_t **e); 2743</pre> 2744 <p> 2745 The translated coordinates will be found in this structure: 2746 </p> 2747 <pre class="code"> 2748typedef struct { 2749 uint8_t response_type; 2750 uint8_t same_screen; 2751 uint16_t sequence; 2752 uint32_t length; 2753 xcb_window_t child; 2754 uint16_t dst_x; /* Translated x coordinate */ 2755 uint16_t dst_y; /* Translated y coordinate */ 2756} xcb_translate_coordinates_reply_t; 2757</pre> 2758 <p> 2759 As usual, we need two functions to fill this structure: 2760 </p> 2761 <pre class="code"> 2762xcb_translate_coordinates_cookie_t xcb_translate_coordinates (xcb_connection_t *c, 2763 xcb_window_t src_window, 2764 xcb_window_t dst_window, 2765 int16_t src_x, 2766 int16_t src_y); 2767xcb_translate_coordinates_reply_t *xcb_translate_coordinates_reply (xcb_connection_t *c, 2768 xcb_translate_coordinates_cookie_t cookie, 2769 xcb_generic_error_t **e); 2770</pre> 2771 <p> 2772 We use them as follows: 2773 </p> 2774 <pre class="code"> 2775 xcb_connection_t *c; 2776 xcb_drawable_t win; 2777 xcb_get_geometry_reply_t *geom; 2778 xcb_query_tree_reply_t *tree; 2779 xcb_translate_coordinates_reply_t *trans; 2780 2781 /* You initialize c and win */ 2782 2783 geom = xcb_get_geometry_reply (c, xcb_get_geometry (c, win), NULL); 2784 if (!geom) 2785 return 0; 2786 2787 tree = xcb_query_tree_reply (c, xcb_query_tree (c, win), NULL); 2788 if (!tree) 2789 return 0; 2790 2791 trans = xcb_translate_coordinates_reply (c, 2792 xcb_translate_coordinates (c, 2793 win, 2794 tree->parent, 2795 geom->x, geom->y), 2796 NULL); 2797 if (!trans) 2798 return 0; 2799 2800 /* the translated coordinates are in trans->dst_x and trans->dst_y */ 2801 2802 free (trans); 2803 free (tree); 2804 free (geom); 2805</pre> 2806 <p> 2807 Of course, as for <span class="code">geom</span>, 2808 <span class="code">tree</span> and 2809 <span class="code">trans</span> have to be freed. 2810 </p> 2811 <p> 2812 The work is a bit hard, but XCB is a very low-level library. 2813 </p> 2814 <p> 2815 <b>TODO:</b> the utilization of these functions should be a 2816 prog, which displays the coordinates of the window. 2817 </p> 2818 <p> 2819 There is another structure that gives informations about our window: 2820 </p> 2821 <pre class="code"> 2822typedef struct { 2823 uint8_t response_type; 2824 uint8_t backing_store; 2825 uint16_t sequence; 2826 uint32_t length; 2827 xcb_visualid_t visual; /* Visual of the window */ 2828 uint16_t _class; 2829 uint8_t bit_gravity; 2830 uint8_t win_gravity; 2831 uint32_t backing_planes; 2832 uint32_t backing_pixel; 2833 uint8_t save_under; 2834 uint8_t map_is_installed; 2835 uint8_t map_state; /* Map state of the window */ 2836 uint8_t override_redirect; 2837 xcb_colormap_t colormap; /* Colormap of the window */ 2838 uint32_t all_event_masks; 2839 uint32_t your_event_mask; 2840 uint16_t do_not_propagate_mask; 2841} xcb_get_window_attributes_reply_t; 2842</pre> 2843 <p> 2844 XCB supplies these two functions to fill it: 2845 </p> 2846 <pre class="code"> 2847xcb_get_window_attributes_cookie_t xcb_get_window_attributes (xcb_connection_t *c, 2848 xcb_window_t window); 2849xcb_get_window_attributes_reply_t *xcb_get_window_attributes_reply (xcb_connection_t *c, 2850 xcb_get_window_attributes_cookie_t cookie, 2851 xcb_generic_error_t **e); 2852</pre> 2853 <p> 2854 You use them as follows: 2855 </p> 2856 <pre class="code"> 2857 xcb_connection_t *c; 2858 xcb_drawable_t win; 2859 xcb_get_window_attributes_reply_t *attr; 2860 2861 /* You initialize c and win */ 2862 2863 attr = xcb_get_window_attributes_reply (c, xcb_get_window_attributes (c, win), NULL); 2864 2865 if (!attr) 2866 return 0; 2867 2868 /* Do something with the fields of attr */ 2869 2870 free (attr); 2871</pre> 2872 <p> 2873 As for <span class="code">geom</span>, 2874 <span class="code">attr</span> has to be freed. 2875 </p> 2876 </ol> 2877 <li class="title"><a name="usecolor">Using colors to paint the rainbow</a> 2878 <p> 2879 Up until now, all our painting operation were done using black 2880 and white. We will (finally) see now how to draw using colors. 2881 </p> 2882 <ol> 2883 <li class="subtitle"><a name="colormap">Color maps</a> 2884 <p> 2885 In the beginning, there were not enough colors. Screen 2886 controllers could only support a limited number of colors 2887 simultaneously (initially 2, then 4, 16 and 256). Because of 2888 this, an application could not just ask to draw in a "light 2889 purple-red" color, and expect that color to be available. Each 2890 application allocated the colors it needed, and when all the 2891 color entries (4, 16, 256 colors) were in use, the next color 2892 allocation would fail. 2893 </p> 2894 <p> 2895 Thus, the notion of "a color map" was introduced. A color map 2896 is a table whose size is the same as the number of 2897 simultaneous colors a given screen controller. Each entry 2898 contained the RGB (Red, Green and Blue) values of a different 2899 color (all colors can be drawn using some combination of red, 2900 green and blue). When an application wants to draw on the 2901 screen, it does not specify which color to use. Rather, it 2902 specifies which color entry of some color map to be used 2903 during this drawing. Change the value in this color map entry 2904 and the drawing will use a different color. 2905 </p> 2906 <p> 2907 In order to be able to draw using colors that got something to 2908 do with what the programmer intended, color map allocation 2909 functions are supplied. You could ask to allocate entry for a 2910 color with a set of RGB values. If one already existed, you 2911 would get its index in the table. If none existed, and the 2912 table was not full, a new cell would be allocated to contain 2913 the given RGB values, and its index returned. If the table was 2914 full, the procedure would fail. You could then ask to get a 2915 color map entry with a color that is closest to the one you 2916 were asking for. This would mean that the actual drawing on 2917 the screen would be done using colors similar to what you 2918 wanted, but not the same. 2919 </p> 2920 <p> 2921 On today's more modern screens where one runs an X server with 2922 support for 16 million colors, this limitation looks a little 2923 silly, but remember that there are still older computers with 2924 older graphics cards out there. Using color map, support for 2925 these screen becomes transparent to you. On a display 2926 supporting 16 million colors, any color entry allocation 2927 request would succeed. On a display supporting a limited 2928 number of colors, some color allocation requests would return 2929 similar colors. It won't look as good, but your application 2930 would still work. 2931 </p> 2932 <li class="subtitle"><a name="colormapalloc">Allocating and freeing Color Maps</a> 2933 <p> 2934 When you draw using XCB, you can choose to use the standard 2935 color map of the screen your window is displayed on, or you 2936 can allocate a new color map and apply it to a window. In the 2937 latter case, each time the mouse moves onto your window, the 2938 screen color map will be replaced by your window's color map, 2939 and you'll see all the other windows on screen change their 2940 colors into something quite bizarre. In fact, this is the 2941 effect you get with X applications that use the "-install" 2942 command line option. 2943 </p> 2944 <p> 2945 In XCB, a color map is (as often in X) an Id: 2946 </p> 2947 <pre class="code"> 2948typedef uint32_t xcb_colormap_t; 2949</pre> 2950 <p> 2951 In order to access the screen's default color map, you just 2952 have to retrieve the <span class="code">default_colormap</span> 2953 field of the <span class="code">xcb_screen_t</span> structure 2954 (see Section 2955 <a href="#screen">Checking basic information about a connection</a>): 2956 </p> 2957 <pre class="code"> 2958#include <stdio.h> 2959 2960#include <xcb/xcb.h> 2961 2962int 2963main () 2964{ 2965 xcb_connection_t *c; 2966 xcb_screen_t *screen; 2967 xcb_colormap_t colormap; 2968 2969 /* Open the connection to the X server and get the first screen */ 2970 c = xcb_connect (NULL, NULL); 2971 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; 2972 2973 colormap = screen->default_colormap; 2974 2975 return 0; 2976} 2977</pre> 2978 <p> 2979 This will return the color map used by default on the first 2980 screen (again, remember that an X server may support several 2981 different screens, each of which might have its own resources). 2982 </p> 2983 <p> 2984 The other option, that of allocating a new colormap, works as 2985 follows. We first ask the X server to give an Id to our color 2986 map, with this function: 2987 </p> 2988 <pre class="code"> 2989xcb_colormap_t xcb_generate_id (xcb_connection_t *c); 2990</pre> 2991 <p> 2992 Then, we create the color map with 2993 </p> 2994 <pre class="code"> 2995xcb_void_cookie_t xcb_create_colormap (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */ 2996 uint8_t alloc, /* Colormap entries to be allocated (AllocNone or AllocAll) */ 2997 xcb_colormap_t mid, /* Id of the color map */ 2998 xcb_window_t window, /* Window on whose screen the colormap will be created */ 2999 xcb_visualid_t visual); /* Id of the visual supported by the screen */ 3000</pre> 3001 <p> 3002 Here is an example of creation of a new color map: 3003 </p> 3004 <pre class="code"> 3005#include <xcb/xcb.h> 3006 3007int 3008main () 3009{ 3010 xcb_connection_t *c; 3011 xcb_screen_t *screen; 3012 xcb_window_t win; 3013 xcb_colormap_t cmap 3014 3015 /* Open the connection to the X server and get the first screen */ 3016 c = xcb_connect (NULL, NULL); 3017 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; 3018 3019 /* We create the window win here*/ 3020 3021 cmap = xcb_generate_id (c); 3022 xcb_create_colormap (c, XCB_COLORMAP_ALLOC_NONE, cmap, win, screen->root_visual); 3023 3024 return 0; 3025} 3026</pre> 3027 <p> 3028 Note that the window parameter is only used to allow the X 3029 server to create the color map for the given screen. We can 3030 then use this color map for any window drawn on the same screen. 3031 </p> 3032 <p> 3033 To free a color map, it suffices to use this function: 3034 </p> 3035 <pre class="code"> 3036xcb_void_cookie_t xcb_free_colormap (xcb_connection_t *c, /* The connection */ 3037 xcb_colormap_t cmap); /* The color map */ 3038</pre> 3039 <div class="comp"> 3040 <div class="title"> 3041 Comparison Xlib/XCB 3042 </div> 3043 <div class="xlib"> 3044 <ul> 3045 <li>XCreateColormap () 3046 </ul> 3047 </div> 3048 <div class="xcb"> 3049 <ul> 3050 <li>xcb_generate_id () 3051 <li>xcb_create_colormap () 3052 </ul> 3053 </div> 3054 <div class="xlib"> 3055 <ul> 3056 <li>XFreeColormap () 3057 </ul> 3058 </div> 3059 <div class="xcb"> 3060 <ul> 3061 <li>xcb_free_colormap () 3062 </ul> 3063 </div> 3064 </div> 3065 <br> 3066 <li class="subtitle"><a name="alloccolor">Allocating and freeing a color entry</a> 3067 <p> 3068 Once we got access to some color map, we can start allocating 3069 colors. The informations related to a color are stored in the 3070 following structure: 3071 </p> 3072 <pre class="code"> 3073typedef struct { 3074 uint8_t response_type; 3075 uint8_t pad0; 3076 uint16_t sequence; 3077 uint32_t length; 3078 uint16_t red; /* The red component */ 3079 uint16_t green; /* The green component */ 3080 uint16_t blue; /* The blue component */ 3081 uint8_t pad1[2]; 3082 uint32_t pixel; /* The entry in the color map, supplied by the X server */ 3083} xcb_alloc_color_reply_t; 3084</pre> 3085 <p> 3086 XCB supplies these two functions to fill it: 3087 </p> 3088 <pre class="code"> 3089xcb_alloc_color_cookie_t xcb_alloc_color (xcb_connection_t *c, 3090 xcb_colormap_t cmap, 3091 uint16_t red, 3092 uint16_t green, 3093 uint16_t blue); 3094xcb_alloc_color_reply_t *xcb_alloc_color_reply (xcb_connection_t *c, 3095 xcb_alloc_color_cookie_t cookie, 3096 xcb_generic_error_t **e); 3097</pre> 3098 <p> 3099 The fuction <span class="code">xcb_alloc_color()</span> takes the 3100 3 RGB components as parameters (red, green and blue). Here is an 3101 example of using these functions: 3102 </p> 3103 <pre class="code"> 3104#include <malloc.h> 3105 3106#include <xcb/xcb.h> 3107 3108int 3109main () 3110{ 3111 xcb_connection_t *c; 3112 xcb_screen_t *screen; 3113 xcb_window_t win; 3114 xcb_colormap_t cmap; 3115 xcb_alloc_color_reply_t *rep; 3116 3117 /* Open the connection to the X server and get the first screen */ 3118 c = xcb_connect (NULL, NULL); 3119 screen = xcb_setup_roots_iterator (xcb_get_setup (c)).data; 3120 3121 /* We create the window win here*/ 3122 3123 cmap = xcb_generate_id (c); 3124 xcb_create_colormap (c, XCB_COLORMAP_ALLOC_NONE, cmap, win, screen->root_visual); 3125 3126 rep = xcb_alloc_color_reply (c, xcb_alloc_color (c, cmap, 65535, 0, 0), NULL); 3127 3128 if (!rep) 3129 return 0; 3130 3131 /* Do something with r->pixel or the components */ 3132 3133 free (rep); 3134 3135 return 0; 3136} 3137</pre> 3138 <p> 3139 As <span class="code">xcb_alloc_color_reply()</span> allocates 3140 memory, you have to free <span class="code">rep</span>. 3141 </p> 3142 <p> 3143 <b>TODO</b>: Talk about freeing colors. 3144 </p> 3145 </ol> 3146 <li class="title"><a name="pixmaps">X Bitmaps and Pixmaps</a> 3147 <p> 3148 One thing many so-called "Multi-Media" applications need to do, 3149 is display images. In the X world, this is done using bitmaps 3150 and pixmaps. We have already seen some usage of them when 3151 setting an icon for our application. Lets study them further, 3152 and see how to draw these images inside a window, along side the 3153 simple graphics and text we have seen so far. 3154 </p> 3155 <p> 3156 One thing to note before delving further, is that XCB (nor Xlib) 3157 supplies no means of manipulating popular image formats, such as 3158 gif, png, jpeg or tiff. It is up to the programmer (or to higher 3159 level graphics libraries) to translate these image formats into 3160 formats that the X server is familiar with (x bitmaps and x 3161 pixmaps). 3162 </p> 3163 <ol> 3164 <li class="subtitle"><a name="pixmapswhat">What is a X Bitmap? An X Pixmap?</a> 3165 <p> 3166 An X bitmap is a two-color image stored in a format specific 3167 to the X window system. When stored in a file, the bitmap data 3168 looks like a C source file. It contains variables defining the 3169 width and the height of the bitmap, an array containing the 3170 bit values of the bitmap (the size of the array is 3171 (width+7)/8*height and the bit and byte order are LSB), and 3172 an optional hot-spot location (that will 3173 be explained later, when discussing mouse cursors). 3174 </p> 3175 <p> 3176 An X pixmap is a format used to stored images in the memory of 3177 an X server. This format can store both black and white images 3178 (such as x bitmaps) as well as color images. It is the only 3179 image format supported by the X protocol, and any image to be 3180 drawn on screen, should be first translated into this format. 3181 </p> 3182 <p> 3183 In actuality, an X pixmap can be thought of as a window that 3184 does not appear on the screen. Many graphics operations that 3185 work on windows, will also work on pixmaps. Indeed, the type 3186 of X pixmap in XCB is an Id like a window: 3187 </p> 3188 <pre class="code"> 3189typedef uint32_t xcb_pixmap_t; 3190</pre> 3191 <p> 3192 Like Xlib, there is no difference between a Drawable, a Window 3193 or a Pixmap: 3194 </p> 3195 <pre class="code"> 3196typedef uint32_t xcb_drawable_t; 3197</pre> 3198 <p> 3199 in order to avoid confusion between a window and a pixmap. The 3200 operations that will work the same on a window or a pixmap 3201 will require a <span class="code">xcb_drawable_t</span> 3202 </p> 3203 <div class="emph"> 3204 <p> 3205 Remark: In Xlib, there is no specific difference between a 3206 <span class="code">Drawable</span>, a 3207 <span class="code">Pixmap</span> or a 3208 <span class="code">Window</span>: all are 32 bit long 3209 integer. XCB wraps all these different IDs in structures to 3210 provide some measure of type-safety. 3211 </p> 3212 </div> 3213 <li class="subtitle"><a name="pixmapscreate">Creating a pixmap</a> 3214 <p> 3215 Sometimes we want to create an un-initialized pixmap, so we 3216 can later draw into it. This is useful for image drawing 3217 programs (creating a new empty canvas will cause the creation 3218 of a new pixmap on which the drawing can be stored). It is 3219 also useful when reading various image formats: we load the 3220 image data into memory, create a pixmap on the server, and 3221 then draw the decoded image data onto that pixmap. 3222 </p> 3223 <p> 3224 To create a new pixmap, we first ask the X server to give an 3225 Id to our pixmap, with this function: 3226 </p> 3227 <pre class="code"> 3228xcb_pixmap_t xcb_generate_id (xcb_connection_t *c); 3229</pre> 3230 <p> 3231 Then, XCB supplies the following function to create new pixmaps: 3232 </p> 3233 <pre class="code"> 3234xcb_void_cookie_t xcb_create_pixmap (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */ 3235 uint8_t depth, /* Depth of the screen */ 3236 xcb_pixmap_t pid, /* Id of the pixmap */ 3237 xcb_drawable_t drawable, 3238 uint16_t width, /* Width of the window (in pixels) */ 3239 uint16_t height); /* Height of the window (in pixels) */ 3240</pre> 3241 <p> 3242 <b>TODO</b>: Explain the drawable parameter, and give an 3243 example (like <a href="xpoints.c">xpoints.c</a>) 3244 </p> 3245 <li class="subtitle"><a name="pixmapsdraw"></a>Drawing a pixmap in a window 3246 <p> 3247 Once we got a handle to a pixmap, we can draw it on some 3248 window, using the following function: 3249 </p> 3250 <pre class="code"> 3251xcb_void_cookie_t xcb_copy_area (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */ 3252 xcb_drawable_t src_drawable, /* The Drawable we want to paste */ 3253 xcb_drawable_t dst_drawable, /* The Drawable on which we copy the previous Drawable */ 3254 xcb_gcontext_t gc, /* A Graphic Context */ 3255 int16_t src_x, /* Top left x coordinate of the region we want to copy */ 3256 int16_t src_y, /* Top left y coordinate of the region we want to copy */ 3257 int16_t dst_x, /* Top left x coordinate of the region where we want to copy */ 3258 int16_t dst_y, /* Top left y coordinate of the region where we want to copy */ 3259 uint16_t width, /* Width of the region we want to copy */ 3260 uint16_t height); /* Height of the region we want to copy */ 3261</pre> 3262 <p> 3263 As you can see, we could copy the whole pixmap, as well as 3264 only a given rectangle of the pixmap. This is useful to 3265 optimize the drawing speed: we could copy only what we have 3266 modified in the pixmap. 3267 </p> 3268 <p> 3269 <b>One important note should be made</b>: it is possible to 3270 create pixmaps with different depths on the same screen. When 3271 we perform copy operations (a pixmap onto a window, etc), we 3272 should make sure that both source and target have the same 3273 depth. If they have a different depth, the operation would 3274 fail. The exception to this is if we copy a specific bit plane 3275 of the source pixmap using the 3276 <span class="code">xcb_copy_plane_t</span> function. In such an 3277 event, we can copy a specific plane to the target window (in 3278 actuality, setting a specific bit in the color of each pixel 3279 copied). This can be used to generate strange graphic effects 3280 in a window, but that is beyond the scope of this tutorial. 3281 </p> 3282 <li class="subtitle"><a name="pixmapsfree"></a>Freeing a pixmap 3283 <p> 3284 Finally, when we are done using a given pixmap, we should free 3285 it, in order to free resources of the X server. This is done 3286 using this function: 3287 </p> 3288 <pre class="code"> 3289xcb_void_cookie_t xcb_free_pixmap (xcb_connection_t *c, /* Pointer to the xcb_connection_t structure */ 3290 xcb_pixmap_t pixmap); /* A given pixmap */ 3291</pre> 3292 <p> 3293 Of course, after having freed it, we must not try accessing 3294 the pixmap again. 3295 </p> 3296 <p> 3297 <b>TODO</b>: Give an example, or a link to xpoints.c 3298 </p> 3299 </ol> 3300 <li class="title"><a name="mousecursor">Messing with the mouse cursor</a> 3301 <p> 3302 It it possible to modify the shape of the mouse pointer (also 3303 called the X pointer) when in certain states, as we often see in 3304 programs. For example, a busy application would often display 3305 the hourglass cursor over its main window, to give the user a visual 3306 hint that they should wait. Let's see how we can change the mouse 3307 cursor of our windows. 3308 </p> 3309 <ol> 3310 <li class="subtitle"><a name="mousecursorcreate">Creating and destroying a mouse cursor</a> 3311 <p> 3312 There are two methods for creating cursors. One of them is by 3313 using a set of predefined cursors, that are supplied by the X 3314 server, the other is by using a user-supplied bitmap. 3315 </p> 3316 <p> 3317 In the first method, we use a special font named "cursor", and 3318 the function <span class="code">xcb_create_glyph_cursor</span>: 3319 </p> 3320 <pre class="code"> 3321xcb_void_cookie_t xcb_create_glyph_cursor (xcb_connection_t *c, 3322 xcb_cursor_t cid, 3323 xcb_font_t source_font, /* font for the source glyph */ 3324 xcb_font_t mask_font, /* font for the mask glyph or XCB_NONE */ 3325 uint16_t source_char, /* character glyph for the source */ 3326 uint16_t mask_char, /* character glyph for the mask */ 3327 uint16_t fore_red, /* red value for the foreground of the source */ 3328 uint16_t fore_green, /* green value for the foreground of the source */ 3329 uint16_t fore_blue, /* blue value for the foreground of the source */ 3330 uint16_t back_red, /* red value for the background of the source */ 3331 uint16_t back_green, /* green value for the background of the source */ 3332 uint16_t back_blue) /* blue value for the background of the source */ 3333</pre> 3334 <p> 3335 <b>TODO</b>: Describe <span class="code">source_char</span> 3336 and <span class="code">mask_char</span>, for example by giving 3337 an example on how to get the values. There is a list there: 3338 <a href="http://tronche.com/gui/x/xlib/appendix/b/">X Font Cursors</a> 3339 </p> 3340 <p> 3341 So we first open that font (see <a href="#loadfont">Loading a Font</a>) 3342 and create the new cursor. As for every X resource, we have to 3343 ask for an X id with <span class="code">xcb_generate_id</span> 3344 first: 3345 </p> 3346 <pre class="code"> 3347xcb_font_t font; 3348xcb_cursor_t cursor; 3349 3350/* The connection is set */ 3351 3352font = xcb_generate_id (conn); 3353xcb_open_font (conn, font, strlen ("cursor"), "cursor"); 3354 3355cursor = xcb_generate_id (conn); 3356xcb_create_glyph_cursor (conn, cursor, font, font, 3357 58, 58 + 1, 3358 0, 0, 0, 3359 0, 0, 0); 3360</pre> 3361 <p> 3362 We have created the cursor "right hand" by specifying 58 to 3363 the <span class="code">source_fon</span>t argument and 58 + 1 3364 to the <span class="code">mask_font</span>. 3365 </p> 3366 <p> 3367 The cursor is destroyed by using the function 3368 </p> 3369 <pre class="code"> 3370xcb_void_cookie_t xcb_free_cursor (xcb_connection_t *c, 3371 xcb_cursor_t cursor); 3372</pre> 3373 <p> 3374 In the second method, we create a new cursor by using a pair 3375 of pixmaps, with depth of one (that is, two colors 3376 pixmaps). One pixmap defines the shape of the cursor, while 3377 the other works as a mask, specifying which pixels of the 3378 cursor will be actually drawn. The rest of the pixels will be 3379 transparent. 3380 </p> 3381 <p> 3382 <b>TODO</b>: give an example. 3383 </p> 3384 <li class="subtitle"><a name="mousecursorset">Setting a window's mouse cursor</a> 3385 <p> 3386 Once the cursor is created, we can modify the cursor of our 3387 window by using <span class="code">xcb_change_window_attributes</span> 3388 and using the <span class="code">XCB_CWCURSOR</span> attribute: 3389 </p> 3390 <pre class="code"> 3391uint32_t mask; 3392uint32_t value_list; 3393 3394/* The connection and window are set */ 3395/* The cursor is already created */ 3396 3397mask = XCB_CWCURSOR; 3398value_list = cursor; 3399xcb_change_window_attributes (conn, window, mask, &value_list); 3400</pre> 3401 <p> 3402 Of course, the cursor and the font must be freed. 3403 </p> 3404 <li class="subtitle"><a name="mousecursorexample">Complete example</a> 3405 <p> 3406 The following example displays a window with a 3407 button. When entering the window, the window cursor is changed 3408 to an arrow. When clicking once on the button, the cursor is 3409 changed to a hand. When clicking again on the button, the 3410 cursor window gets back to the arrow. The Esc key exits the 3411 application. 3412 </p> 3413 <pre class="code"> 3414#include <stdlib.h> 3415#include <stdio.h> 3416#include <string.h> 3417 3418#include <xcb/xcb.h> 3419 3420#define WIDTH 300 3421#define HEIGHT 150 3422 3423 3424 3425static xcb_gc_t gc_font_get (xcb_connection_t *c, 3426 xcb_screen_t *screen, 3427 xcb_window_t window, 3428 const char *font_name); 3429 3430static void button_draw (xcb_connection_t *c, 3431 xcb_screen_t *screen, 3432 xcb_window_t window, 3433 int16_t x1, 3434 int16_t y1, 3435 const char *label); 3436 3437static void text_draw (xcb_connection_t *c, 3438 xcb_screen_t *screen, 3439 xcb_window_t window, 3440 int16_t x1, 3441 int16_t y1, 3442 const char *label); 3443 3444static void cursor_set (xcb_connection_t *c, 3445 xcb_screen_t *screen, 3446 xcb_window_t window, 3447 int cursor_id); 3448 3449 3450static void 3451button_draw (xcb_connection_t *c, 3452 xcb_screen_t *screen, 3453 xcb_window_t window, 3454 int16_t x1, 3455 int16_t y1, 3456 const char *label) 3457{ 3458 xcb_point_t points[5]; 3459 xcb_void_cookie_t cookie_gc; 3460 xcb_void_cookie_t cookie_line; 3461 xcb_void_cookie_t cookie_text; 3462 xcb_generic_error_t *error; 3463 xcb_gcontext_t gc; 3464 int16_t width; 3465 int16_t height; 3466 uint8_t length; 3467 int16_t inset; 3468 3469 length = strlen (label); 3470 inset = 2; 3471 3472 gc = gc_font_get(c, screen, window, "7x13"); 3473 3474 width = 7 * length + 2 * (inset + 1); 3475 height = 13 + 2 * (inset + 1); 3476 points[0].x = x1; 3477 points[0].y = y1; 3478 points[1].x = x1 + width; 3479 points[1].y = y1; 3480 points[2].x = x1 + width; 3481 points[2].y = y1 - height; 3482 points[3].x = x1; 3483 points[3].y = y1 - height; 3484 points[4].x = x1; 3485 points[4].y = y1; 3486 cookie_line = xcb_poly_line_checked (c, XCB_COORD_MODE_ORIGIN, 3487 window, gc, 5, points); 3488 3489 error = xcb_request_check (c, cookie_line); 3490 if (error) { 3491 fprintf (stderr, "ERROR: can't draw lines : %d\n", error->error_code); 3492 xcb_disconnect (c); 3493 exit (-1); 3494 } 3495 3496 cookie_text = xcb_image_text_8_checked (c, length, window, gc, 3497 x1 + inset + 1, 3498 y1 - inset - 1, label); 3499 error = xcb_request_check (c, cookie_text); 3500 if (error) { 3501 fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code); 3502 xcb_disconnect (c); 3503 exit (-1); 3504 } 3505 3506 cookie_gc = xcb_free_gc (c, gc); 3507 error = xcb_request_check (c, cookie_gc); 3508 if (error) { 3509 fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code); 3510 xcb_disconnect (c); 3511 exit (-1); 3512 } 3513} 3514 3515static void 3516text_draw (xcb_connection_t *c, 3517 xcb_screen_t *screen, 3518 xcb_window_t window, 3519 int16_t x1, 3520 int16_t y1, 3521 const char *label) 3522{ 3523 xcb_void_cookie_t cookie_gc; 3524 xcb_void_cookie_t cookie_text; 3525 xcb_generic_error_t *error; 3526 xcb_gcontext_t gc; 3527 uint8_t length; 3528 3529 length = strlen (label); 3530 3531 gc = gc_font_get(c, screen, window, "7x13"); 3532 3533 cookie_text = xcb_image_text_8_checked (c, length, window, gc, 3534 x1, 3535 y1, label); 3536 error = xcb_request_check (c, cookie_text); 3537 if (error) { 3538 fprintf (stderr, "ERROR: can't paste text : %d\n", error->error_code); 3539 xcb_disconnect (c); 3540 exit (-1); 3541 } 3542 3543 cookie_gc = xcb_free_gc (c, gc); 3544 error = xcb_request_check (c, cookie_gc); 3545 if (error) { 3546 fprintf (stderr, "ERROR: can't free gc : %d\n", error->error_code); 3547 xcb_disconnect (c); 3548 exit (-1); 3549 } 3550} 3551 3552static xcb_gc_t 3553gc_font_get (xcb_connection_t *c, 3554 xcb_screen_t *screen, 3555 xcb_window_t window, 3556 const char *font_name) 3557{ 3558 uint32_t value_list[3]; 3559 xcb_void_cookie_t cookie_font; 3560 xcb_void_cookie_t cookie_gc; 3561 xcb_generic_error_t *error; 3562 xcb_font_t font; 3563 xcb_gcontext_t gc; 3564 uint32_t mask; 3565 3566 font = xcb_generate_id (c); 3567 cookie_font = xcb_open_font_checked (c, font, 3568 strlen (font_name), 3569 font_name); 3570 3571 error = xcb_request_check (c, cookie_font); 3572 if (error) { 3573 fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code); 3574 xcb_disconnect (c); 3575 return -1; 3576 } 3577 3578 gc = xcb_generate_id (c); 3579 mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT; 3580 value_list[0] = screen->black_pixel; 3581 value_list[1] = screen->white_pixel; 3582 value_list[2] = font; 3583 cookie_gc = xcb_create_gc_checked (c, gc, window, mask, value_list); 3584 error = xcb_request_check (c, cookie_gc); 3585 if (error) { 3586 fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code); 3587 xcb_disconnect (c); 3588 exit (-1); 3589 } 3590 3591 cookie_font = xcb_close_font_checked (c, font); 3592 error = xcb_request_check (c, cookie_font); 3593 if (error) { 3594 fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code); 3595 xcb_disconnect (c); 3596 exit (-1); 3597 } 3598 3599 return gc; 3600} 3601 3602static void 3603cursor_set (xcb_connection_t *c, 3604 xcb_screen_t *screen, 3605 xcb_window_t window, 3606 int cursor_id) 3607{ 3608 uint32_t values_list[3]; 3609 xcb_void_cookie_t cookie_font; 3610 xcb_void_cookie_t cookie_gc; 3611 xcb_generic_error_t *error; 3612 xcb_font_t font; 3613 xcb_cursor_t cursor; 3614 xcb_gcontext_t gc; 3615 uint32_t mask; 3616 uint32_t value_list; 3617 3618 font = xcb_generate_id (c); 3619 cookie_font = xcb_open_font_checked (c, font, 3620 strlen ("cursor"), 3621 "cursor"); 3622 error = xcb_request_check (c, cookie_font); 3623 if (error) { 3624 fprintf (stderr, "ERROR: can't open font : %d\n", error->error_code); 3625 xcb_disconnect (c); 3626 exit (-1); 3627 } 3628 3629 cursor = xcb_generate_id (c); 3630 xcb_create_glyph_cursor (c, cursor, font, font, 3631 cursor_id, cursor_id + 1, 3632 0, 0, 0, 3633 0, 0, 0); 3634 3635 gc = xcb_generate_id (c); 3636 mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND | XCB_GC_FONT; 3637 values_list[0] = screen->black_pixel; 3638 values_list[1] = screen->white_pixel; 3639 values_list[2] = font; 3640 cookie_gc = xcb_create_gc_checked (c, gc, window, mask, values_list); 3641 error = xcb_request_check (c, cookie_gc); 3642 if (error) { 3643 fprintf (stderr, "ERROR: can't create gc : %d\n", error->error_code); 3644 xcb_disconnect (c); 3645 exit (-1); 3646 } 3647 3648 mask = XCB_CW_CURSOR; 3649 value_list = cursor; 3650 xcb_change_window_attributes (c, window, mask, &value_list); 3651 3652 xcb_free_cursor (c, cursor); 3653 3654 cookie_font = xcb_close_font_checked (c, font); 3655 error = xcb_request_check (c, cookie_font); 3656 if (error) { 3657 fprintf (stderr, "ERROR: can't close font : %d\n", error->error_code); 3658 xcb_disconnect (c); 3659 exit (-1); 3660 } 3661} 3662 3663int main () 3664{ 3665 xcb_screen_iterator_t screen_iter; 3666 xcb_connection_t *c; 3667 const xcb_setup_t *setup; 3668 xcb_screen_t *screen; 3669 xcb_generic_event_t *e; 3670 xcb_generic_error_t *error; 3671 xcb_void_cookie_t cookie_window; 3672 xcb_void_cookie_t cookie_map; 3673 xcb_window_t window; 3674 uint32_t mask; 3675 uint32_t values[2]; 3676 int screen_number; 3677 uint8_t is_hand = 0; 3678 3679 /* getting the connection */ 3680 c = xcb_connect (NULL, &screen_number); 3681 if (!c) { 3682 fprintf (stderr, "ERROR: can't connect to an X server\n"); 3683 return -1; 3684 } 3685 3686 /* getting the current screen */ 3687 setup = xcb_get_setup (c); 3688 3689 screen = NULL; 3690 screen_iter = xcb_setup_roots_iterator (setup); 3691 for (; screen_iter.rem != 0; --screen_number, xcb_screen_next (&screen_iter)) 3692 if (screen_number == 0) 3693 { 3694 screen = screen_iter.data; 3695 break; 3696 } 3697 if (!screen) { 3698 fprintf (stderr, "ERROR: can't get the current screen\n"); 3699 xcb_disconnect (c); 3700 return -1; 3701 } 3702 3703 /* creating the window */ 3704 window = xcb_generate_id (c); 3705 mask = XCB_CW_BACK_PIXEL | XCB_CW_EVENT_MASK; 3706 values[0] = screen->white_pixel; 3707 values[1] = 3708 XCB_EVENT_MASK_KEY_RELEASE | 3709 XCB_EVENT_MASK_BUTTON_PRESS | 3710 XCB_EVENT_MASK_EXPOSURE | 3711 XCB_EVENT_MASK_POINTER_MOTION; 3712 cookie_window = xcb_create_window_checked (c, 3713 screen->root_depth, 3714 window, screen->root, 3715 20, 200, WIDTH, HEIGHT, 3716 0, XCB_WINDOW_CLASS_INPUT_OUTPUT, 3717 screen->root_visual, 3718 mask, values); 3719 cookie_map = xcb_map_window_checked (c, window); 3720 3721 /* error managing */ 3722 error = xcb_request_check (c, cookie_window); 3723 if (error) { 3724 fprintf (stderr, "ERROR: can't create window : %d\n", error->error_code); 3725 xcb_disconnect (c); 3726 return -1; 3727 } 3728 error = xcb_request_check (c, cookie_map); 3729 if (error) { 3730 fprintf (stderr, "ERROR: can't map window : %d\n", error->error_code); 3731 xcb_disconnect (c); 3732 return -1; 3733 } 3734 3735 cursor_set (c, screen, window, 68); 3736 3737 xcb_flush(c); 3738 3739 while (1) { 3740 e = xcb_poll_for_event(c); 3741 if (e) { 3742 switch (e->response_type & ~0x80) { 3743 case XCB_EXPOSE: { 3744 char *text; 3745 3746 text = "click here to change cursor"; 3747 button_draw (c, screen, window, 3748 (WIDTH - 7 * strlen(text)) / 2, 3749 (HEIGHT - 16) / 2, text); 3750 3751 text = "Press ESC key to exit..."; 3752 text_draw (c, screen, window, 10, HEIGHT - 10, text); 3753 break; 3754 } 3755 case XCB_BUTTON_PRESS: { 3756 xcb_button_press_event_t *ev; 3757 int length; 3758 3759 ev = (xcb_button_press_event_t *)e; 3760 length = strlen ("click here to change cursor"); 3761 3762 if ((ev->event_x >= (WIDTH - 7 * length) / 2) && 3763 (ev->event_x <= ((WIDTH - 7 * length) / 2 + 7 * length + 6)) && 3764 (ev->event_y >= (HEIGHT - 16) / 2 - 19) && 3765 (ev->event_y <= ((HEIGHT - 16) / 2))) 3766 is_hand = 1 - is_hand; 3767 3768 is_hand ? cursor_set (c, screen, window, 58) : cursor_set (c, screen, window, 68); 3769 } 3770 case XCB_KEY_RELEASE: { 3771 xcb_key_release_event_t *ev; 3772 3773 ev = (xcb_key_release_event_t *)e; 3774 3775 switch (ev->detail) { 3776 /* ESC */ 3777 case 9: 3778 free (e); 3779 xcb_disconnect (c); 3780 return 0; 3781 } 3782 } 3783 } 3784 free (e); 3785 } 3786 } 3787 3788 return 0; 3789} 3790</pre> 3791 </ol> 3792 <li class="title"><a name="translation">Translation of basic Xlib functions and macros</a> 3793 <p> 3794 The problem when you want to port an Xlib program to XCB is that 3795 you don't know if the Xlib function that you want to "translate" 3796 is a X Window one or an Xlib macro. In that section, we describe 3797 a way to translate the usual functions or macros that Xlib 3798 provides. It's usually just a member of a structure. 3799 </p> 3800 <ol> 3801 <li class="subtitle"><a name="displaystructure">Members of the Display structure</a> 3802 <p> 3803 In this section, we look at how to translate the macros that 3804 return some members of the <span class="code">Display</span> 3805 structure. They are obtained by using a function that requires a 3806 <span class="code">xcb_connection_t *</span> or a member of the 3807 <span class="code">xcb_setup_t</span> structure 3808 (via the function <span class="code">xcb_get_setup</span>), or 3809 a function that requires that structure. 3810 </p> 3811 <ol> 3812 <li class="subtitle"><a name="ConnectionNumber">ConnectionNumber</a> 3813 <p> 3814 This number is the file descriptor that connects the client 3815 to the server. You just have to use that function: 3816 </p> 3817 <pre class="code"> 3818int xcb_get_file_descriptor (xcb_connection_t *c); 3819</pre> 3820 <li class="subtitle"><a name="DefaultScreen"></a>DefaultScreen 3821 <p> 3822 That number is not stored by XCB. It is returned in the 3823 second parameter of the function <span class="code"><a href="#openconn">xcb_connect</a></span>. 3824 Hence, you have to store it yourself if you want to use 3825 it. Then, to get the <span class="code">xcb_screen_t</span> 3826 structure, you have to iterate on the screens. 3827 The equivalent function of the Xlib's 3828 <span class="code">ScreenOfDisplay</span> function can be 3829 found <a href="#ScreenOfDisplay">below</a>. This is also provided in the 3830 xcb_aux_t library as <span class="code">xcb_aux_get_screen()</span>. OK, here is the 3831 small piece of code to get that number: 3832 </p> 3833 <pre class="code"> 3834xcb_connection_t *c; 3835int screen_default_nbr; 3836 3837/* you pass the name of the display you want to xcb_connect_t */ 3838 3839c = xcb_connect (display_name, &screen_default_nbr); 3840 3841/* screen_default_nbr contains now the number of the default screen */ 3842</pre> 3843 <li class="subtitle"><a name="QLength"></a>QLength 3844 <p> 3845 Not documented yet. 3846 </p> 3847 <p> 3848 However, this points out a basic difference in philosophy between 3849 Xlib and XCB. Xlib has several functions for filtering and 3850 manipulating the incoming and outgoing X message queues. XCB 3851 wishes to hide this as much as possible from the user, which 3852 allows for more freedom in implementation strategies. 3853 </p> 3854 <li class="subtitle"><a name="ScreenCount"></a>ScreenCount 3855 <p> 3856 You get the count of screens with the functions 3857 <span class="code">xcb_get_setup</span> 3858 and 3859 <span class="code">xcb_setup_roots_iterator</span> 3860 (if you need to iterate): 3861 </p> 3862 <pre class="code"> 3863xcb_connection_t *c; 3864int screen_count; 3865 3866/* you init the connection */ 3867 3868screen_count = xcb_setup_roots_iterator (xcb_get_setup (c)).rem; 3869 3870/* screen_count contains now the count of screens */ 3871</pre> 3872 <p> 3873 If you don't want to iterate over the screens, a better way 3874 to get that number is to use 3875 <span class="code">xcb_setup_roots_length_t</span>: 3876 </p> 3877 <pre class="code"> 3878xcb_connection_t *c; 3879int screen_count; 3880 3881/* you init the connection */ 3882 3883screen_count = xcb_setup_roots_length (xcb_get_setup (c)); 3884 3885/* screen_count contains now the count of screens */ 3886</pre> 3887 <li class="subtitle"><a name="ServerVendor"></a>ServerVendor 3888 <p> 3889 You get the name of the vendor of the server hardware with 3890 the functions <span class="code">xcb_get_setup</span> 3891 and 3892 <span 3893 class="code">xcb_setup_vendor</span>. Beware 3894 that, unlike Xlib, the string returned by XCB is not 3895 necessarily null-terminaled: 3896 </p> 3897 <pre class="code"> 3898xcb_connection_t *c; 3899char *vendor = NULL; 3900int length; 3901 3902/* you init the connection */ 3903length = xcb_setup_vendor_length (xcb_get_setup (c)); 3904vendor = (char *)malloc (length + 1); 3905if (vendor) 3906memcpy (vendor, xcb_setup_vendor (xcb_get_setup (c)), length); 3907vendor[length] = '\0'; 3908 3909/* vendor contains now the name of the vendor. Must be freed when not used anymore */ 3910</pre> 3911 <li class="subtitle"><a name="ProtocolVersion"></a>ProtocolVersion 3912 <p> 3913 You get the major version of the protocol in the 3914 <span class="code">xcb_setup_t</span> 3915 structure, with the function <span class="code">xcb_get_setup</span>: 3916 </p> 3917 <pre class="code"> 3918xcb_connection_t *c; 3919uint16_t protocol_major_version; 3920 3921/* you init the connection */ 3922 3923protocol_major_version = xcb_get_setup (c)->protocol_major_version; 3924 3925/* protocol_major_version contains now the major version of the protocol */ 3926</pre> 3927 <li class="subtitle"><a name="ProtocolRevision"></a>ProtocolRevision 3928 <p> 3929 You get the minor version of the protocol in the 3930 <span class="code">xcb_setup_t</span> 3931 structure, with the function <span class="code">xcb_get_setup</span>: 3932 </p> 3933 <pre class="code"> 3934xcb_connection_t *c; 3935uint16_t protocol_minor_version; 3936 3937/* you init the connection */ 3938 3939protocol_minor_version = xcb_get_setup (c)->protocol_minor_version; 3940 3941/* protocol_minor_version contains now the minor version of the protocol */ 3942</pre> 3943 <li class="subtitle"><a name="VendorRelease"></a>VendorRelease 3944 <p> 3945 You get the number of the release of the server hardware in the 3946 <span class="code">xcb_setup_t</span> 3947 structure, with the function <span class="code">xcb_get_setup</span>: 3948 </p> 3949 <pre class="code"> 3950xcb_connection_t *c; 3951uint32_t release_number; 3952 3953/* you init the connection */ 3954 3955release_number = xcb_get_setup (c)->release_number; 3956 3957/* release_number contains now the number of the release of the server hardware */ 3958</pre> 3959 <li class="subtitle"><a name="DisplayString"></a>DisplayString 3960 <p> 3961 The name of the display is not stored in XCB. You have to 3962 store it by yourself. 3963 </p> 3964 <li class="subtitle"><a name="BitmapUnit"></a>BitmapUnit 3965 <p> 3966 You get the bitmap scanline unit in the 3967 <span class="code">xcb_setup_t</span> 3968 structure, with the function <span class="code">xcb_get_setup</span>: 3969 </p> 3970 <pre class="code"> 3971xcb_connection_t *c; 3972uint8_t bitmap_format_scanline_unit; 3973 3974/* you init the connection */ 3975 3976bitmap_format_scanline_unit = xcb_get_setup (c)->bitmap_format_scanline_unit; 3977 3978/* bitmap_format_scanline_unit contains now the bitmap scanline unit */ 3979</pre> 3980 <li class="subtitle"><a name="BitmapBitOrder"></a>BitmapBitOrder 3981 <p> 3982 You get the bitmap bit order in the 3983 <span class="code">xcb_setup_t</span> 3984 structure, with the function <span class="code">xcb_get_setup</span>: 3985 </p> 3986 <pre class="code"> 3987xcb_connection_t *c; 3988uint8_t bitmap_format_bit_order; 3989 3990/* you init the connection */ 3991 3992bitmap_format_bit_order = xcb_get_setup (c)->bitmap_format_bit_order; 3993 3994/* bitmap_format_bit_order contains now the bitmap bit order */ 3995</pre> 3996 <li class="subtitle"><a name="BitmapPad"></a>BitmapPad 3997 <p> 3998 You get the bitmap scanline pad in the 3999 <span class="code">xcb_setup_t</span> 4000 structure, with the function <span class="code">xcb_get_setup</span>: 4001 </p> 4002 <pre class="code"> 4003xcb_connection_t *c; 4004uint8_t bitmap_format_scanline_pad; 4005 4006/* you init the connection */ 4007 4008bitmap_format_scanline_pad = xcb_get_setup (c)->bitmap_format_scanline_pad; 4009 4010/* bitmap_format_scanline_pad contains now the bitmap scanline pad */ 4011</pre> 4012 <li class="subtitle"><a name="ImageByteOrder"></a>ImageByteOrder 4013 <p> 4014 You get the image byte order in the 4015 <span class="code">xcb_setup_t</span> 4016 structure, with the function <span class="code">xcb_get_setup</span>: 4017 </p> 4018 <pre class="code"> 4019xcb_connection_t *c; 4020uint8_t image_byte_order; 4021 4022/* you init the connection */ 4023 4024image_byte_order = xcb_get_setup (c)->image_byte_order; 4025 4026/* image_byte_order contains now the image byte order */ 4027</pre> 4028 </ol> 4029 <li class="subtitle"><a name="screenofdisplay">ScreenOfDisplay related functions</a> 4030 <p> 4031 in Xlib, <span class="code">ScreenOfDisplay</span> returns a 4032 <span class="code">Screen</span> structure that contains 4033 several characteristics of your screen. XCB has a similar 4034 structure (<span class="code">xcb_screen_t</span>), 4035 but the way to obtain it is a bit different. With 4036 Xlib, you just provide the number of the screen and you grab it 4037 from an array. With XCB, you iterate over all the screens to 4038 obtain the one you want. The complexity of this operation is 4039 O(n). So the best is to store this structure if you use 4040 it often. See <a href="#ScreenOfDisplay">screen_of_display</a> just below. 4041 </p> 4042 <p> 4043 Xlib provides generally two functions to obtain the characteristics 4044 related to the screen. One with the display and the number of 4045 the screen, which calls <span class="code">ScreenOfDisplay</span>, 4046 and the other that uses the <span class="code">Screen</span> structure. 4047 This might be a bit confusing. As mentioned above, with XCB, it 4048 is better to store the <span class="code">xcb_screen_t</span> 4049 structure. Then, you have to read the members of this 4050 structure. That's why the Xlib functions are put by pairs (or 4051 more) as, with XCB, you will use the same code. 4052 </p> 4053 <ol> 4054 <li class="subtitle"><a name="ScreenOfDisplay">ScreenOfDisplay</a> 4055 <p> 4056 This function returns the Xlib <span class="code">Screen</span> 4057 structure. With XCB, you iterate over all the screens and 4058 once you get the one you want, you return it: 4059 </p> 4060 <pre class="code"><a name="ScreenOfDisplay"></a> 4061xcb_screen_t *screen_of_display (xcb_connection_t *c, 4062 int screen) 4063{ 4064 xcb_screen_iterator_t iter; 4065 4066 iter = xcb_setup_roots_iterator (xcb_get_setup (c)); 4067 for (; iter.rem; --screen, xcb_screen_next (&iter)) 4068 if (screen == 0) 4069 return iter.data; 4070 4071 return NULL; 4072} 4073</pre> 4074 <p> 4075 As mentioned above, you might want to store the value 4076 returned by this function. 4077 </p> 4078 <p> 4079 All the functions below will use the result of that 4080 function, as they just grab a specific member of the 4081 <span class="code">xcb_screen_t</span> structure. 4082 </p> 4083 <li class="subtitle"><a name="DefaultScreenOfDisplay"></a>DefaultScreenOfDisplay 4084 <p> 4085 It is the default screen that you obtain when you connect to 4086 the X server. It suffices to call the <a href="#ScreenOfDisplay">screen_of_display</a> 4087 function above with the connection and the number of the 4088 default screen. 4089 </p> 4090 <pre class="code"> 4091xcb_connection_t *c; 4092int screen_default_nbr; 4093xcb_screen_t *default_screen; /* the returned default screen */ 4094 4095/* you pass the name of the display you want to xcb_connect_t */ 4096 4097c = xcb_connect (display_name, &screen_default_nbr); 4098default_screen = screen_of_display (c, screen_default_nbr); 4099 4100/* default_screen contains now the default root window, or a NULL window if no screen is found */ 4101</pre> 4102 <li class="subtitle"><a name="RootWindow">RootWindow / RootWindowOfScreen</a> 4103 <br> 4104 <pre class="code"> 4105xcb_connection_t *c; 4106xcb_screen_t *screen; 4107int screen_nbr; 4108xcb_window_t root_window = { 0 }; /* the returned window */ 4109 4110/* you init the connection and screen_nbr */ 4111 4112screen = screen_of_display (c, screen_nbr); 4113if (screen) 4114 root_window = screen->root; 4115 4116/* root_window contains now the root window, or a NULL window if no screen is found */ 4117</pre> 4118 <li class="subtitle"><a name="DefaultRootWindow">DefaultRootWindow</a> 4119 <p> 4120 It is the root window of the default screen. So, you call 4121 <a name="ScreenOfDisplay">ScreenOfDisplay</a> with the 4122 default screen number and you get the 4123 <a href="#RootWindow">root window</a> as above: 4124 </p> 4125 <pre class="code"> 4126xcb_connection_t *c; 4127xcb_screen_t *screen; 4128int screen_default_nbr; 4129xcb_window_t root_window = { 0 }; /* the returned root window */ 4130 4131/* you pass the name of the display you want to xcb_connect_t */ 4132 4133c = xcb_connect (display_name, &screen_default_nbr); 4134screen = screen_of_display (c, screen_default_nbr); 4135if (screen) 4136 root_window = screen->root; 4137 4138/* root_window contains now the default root window, or a NULL window if no screen is found */ 4139</pre> 4140 <li class="subtitle"><a name="DefaultVisual">DefaultVisual / DefaultVisualOfScreen</a> 4141 <p> 4142 While a Visual is, in Xlib, a structure, in XCB, there are 4143 two types: <span class="code">xcb_visualid_t</span>, which is 4144 the Id of the visual, and <span class="code">xcb_visualtype_t</span>, 4145 which corresponds to the Xlib Visual. To get the Id of the 4146 visual of a screen, just get the 4147 <span class="code">root_visual</span> 4148 member of a <span class="code">xcb_screen_t</span>: 4149 </p> 4150 <pre class="code"> 4151xcb_connection_t *c; 4152xcb_screen_t *screen; 4153int screen_nbr; 4154xcb_visualid_t root_visual = { 0 }; /* the returned visual Id */ 4155 4156/* you init the connection and screen_nbr */ 4157 4158screen = screen_of_display (c, screen_nbr); 4159if (screen) 4160 root_visual = screen->root_visual; 4161 4162/* root_visual contains now the value of the Id of the visual, or a NULL visual if no screen is found */ 4163</pre> 4164 <p> 4165 To get the <span class="code">xcb_visualtype_t</span> 4166 structure, it's a bit less easy. You have to get the 4167 <span class="code">xcb_screen_t</span> structure that you want, 4168 get its <span class="code">root_visual</span> member, 4169 then iterate over the <span class="code">xcb_depth_t</span>s 4170 and the <span class="code">xcb_visualtype_t</span>s, and compare 4171 the <span class="code">xcb_visualid_t</span> of these <span class="code">xcb_visualtype_t</span>s: 4172 with <span class="code">root_visual</span>: 4173 </p> 4174 <pre class="code"> 4175xcb_connection_t *c; 4176xcb_screen_t *screen; 4177int screen_nbr; 4178xcb_visualid_t root_visual = { 0 }; 4179xcb_visualtype_t *visual_type = NULL; /* the returned visual type */ 4180 4181/* you init the connection and screen_nbr */ 4182 4183screen = screen_of_display (c, screen_nbr); 4184if (screen) { 4185 xcb_depth_iterator_t depth_iter; 4186 4187 depth_iter = xcb_screen_allowed_depths_iterator (screen); 4188 for (; depth_iter.rem; xcb_depth_next (&depth_iter)) { 4189 xcb_visualtype_iterator_t visual_iter; 4190 4191 visual_iter = xcb_depth_visuals_iterator (depth_iter.data); 4192 for (; visual_iter.rem; xcb_visualtype_next (&visual_iter)) { 4193 if (screen->root_visual == visual_iter.data->visual_id) { 4194 visual_type = visual_iter.data; 4195 break; 4196 } 4197 } 4198 } 4199} 4200 4201/* visual_type contains now the visual structure, or a NULL visual structure if no screen is found */ 4202</pre> 4203 <li class="subtitle"><a name="DefaultGC">DefaultGC / DefaultGCOfScreen</a> 4204 <p> 4205 This default Graphic Context is just a newly created Graphic 4206 Context, associated to the root window of a 4207 <span class="code">xcb_screen_t</span>, 4208 using the black white pixels of that screen: 4209 </p> 4210 <pre class="code"> 4211xcb_connection_t *c; 4212xcb_screen_t *screen; 4213int screen_nbr; 4214xcb_gcontext_t gc = { 0 }; /* the returned default graphic context */ 4215 4216/* you init the connection and screen_nbr */ 4217 4218screen = screen_of_display (c, screen_nbr); 4219if (screen) { 4220 xcb_drawable_t draw; 4221 uint32_t mask; 4222 uint32_t values[2]; 4223 4224 gc = xcb_generate_id (c); 4225 draw = screen->root; 4226 mask = XCB_GC_FOREGROUND | XCB_GC_BACKGROUND; 4227 values[0] = screen->black_pixel; 4228 values[1] = screen->white_pixel; 4229 xcb_create_gc (c, gc, draw, mask, values); 4230} 4231 4232/* gc contains now the default graphic context */ 4233</pre> 4234 <li class="subtitle"><a name="BlackPixel">BlackPixel / BlackPixelOfScreen</a> 4235 <p> 4236 It is the Id of the black pixel, which is in the structure 4237 of an <span class="code">xcb_screen_t</span>. 4238 </p> 4239 <pre class="code"> 4240xcb_connection_t *c; 4241xcb_screen_t *screen; 4242int screen_nbr; 4243uint32_t black_pixel = 0; /* the returned black pixel */ 4244 4245/* you init the connection and screen_nbr */ 4246 4247screen = screen_of_display (c, screen_nbr); 4248if (screen) 4249 black_pixel = screen->black_pixel; 4250 4251/* black_pixel contains now the value of the black pixel, or 0 if no screen is found */ 4252</pre> 4253 <li class="subtitle"><a name="WhitePixel">WhitePixel / WhitePixelOfScreen</a> 4254 <p> 4255 It is the Id of the white pixel, which is in the structure 4256 of an <span class="code">xcb_screen_t</span>. 4257 </p> 4258 <pre class="code"> 4259xcb_connection_t *c; 4260xcb_screen_t *screen; 4261int screen_nbr; 4262uint32_t white_pixel = 0; /* the returned white pixel */ 4263 4264/* you init the connection and screen_nbr */ 4265 4266screen = screen_of_display (c, screen_nbr); 4267if (screen) 4268 white_pixel = screen->white_pixel; 4269 4270/* white_pixel contains now the value of the white pixel, or 0 if no screen is found */ 4271</pre> 4272 <li class="subtitle"><a name="DisplayWidth">DisplayWidth / WidthOfScreen</a> 4273 <p> 4274 It is the width in pixels of the screen that you want, and 4275 which is in the structure of the corresponding 4276 <span class="code">xcb_screen_t</span>. 4277 </p> 4278 <pre class="code"> 4279xcb_connection_t *c; 4280xcb_screen_t *screen; 4281int screen_nbr; 4282uint32_t width_in_pixels = 0; /* the returned width in pixels */ 4283 4284/* you init the connection and screen_nbr */ 4285 4286screen = screen_of_display (c, screen_nbr); 4287if (screen) 4288 width_in_pixels = screen->width_in_pixels; 4289 4290/* width_in_pixels contains now the width in pixels, or 0 if no screen is found */ 4291</pre> 4292 <li class="subtitle"><a name="DisplayHeight">DisplayHeight / HeightOfScreen</a> 4293 <p> 4294 It is the height in pixels of the screen that you want, and 4295 which is in the structure of the corresponding 4296 <span class="code">xcb_screen_t</span>. 4297 </p> 4298 <pre class="code"> 4299xcb_connection_t *c; 4300xcb_screen_t *screen; 4301int screen_nbr; 4302uint32_t height_in_pixels = 0; /* the returned height in pixels */ 4303 4304/* you init the connection and screen_nbr */ 4305 4306screen = screen_of_display (c, screen_nbr); 4307if (screen) 4308 height_in_pixels = screen->height_in_pixels; 4309 4310/* height_in_pixels contains now the height in pixels, or 0 if no screen is found */ 4311</pre> 4312 <li class="subtitle"><a name="DisplayWidthMM">DisplayWidthMM / WidthMMOfScreen</a> 4313 <p> 4314 It is the width in millimeters of the screen that you want, and 4315 which is in the structure of the corresponding 4316 <span class="code">xcb_screen_t</span>. 4317 </p> 4318 <pre class="code"> 4319xcb_connection_t *c; 4320xcb_screen_t *screen; 4321int screen_nbr; 4322uint32_t width_in_millimeters = 0; /* the returned width in millimeters */ 4323 4324/* you init the connection and screen_nbr */ 4325 4326screen = screen_of_display (c, screen_nbr); 4327if (screen) 4328 width_in_millimeters = screen->width_in_millimeters; 4329 4330/* width_in_millimeters contains now the width in millimeters, or 0 if no screen is found */ 4331</pre> 4332 <li class="subtitle"><a name="DisplayHeightMM">DisplayHeightMM / HeightMMOfScreen</a> 4333 <p> 4334 It is the height in millimeters of the screen that you want, and 4335 which is in the structure of the corresponding 4336 <span class="code">xcb_screen_t</span>. 4337 </p> 4338 <pre class="code"> 4339xcb_connection_t *c; 4340xcb_screen_t *screen; 4341int screen_nbr; 4342uint32_t height_in_millimeters = 0; /* the returned height in millimeters */ 4343 4344/* you init the connection and screen_nbr */ 4345 4346screen = screen_of_display (c, screen_nbr); 4347if (screen) 4348 height_in_millimeters = screen->height_in_millimeters; 4349 4350/* height_in_millimeters contains now the height in millimeters, or 0 if no screen is found */ 4351</pre> 4352 <li class="subtitle"><a name="DisplayPlanes">DisplayPlanes / DefaultDepth / DefaultDepthOfScreen / PlanesOfScreen</a> 4353 <p> 4354 It is the depth (in bits) of the root window of the 4355 screen. You get it from the <span class="code">xcb_screen_t</span> structure. 4356 </p> 4357 <pre class="code"> 4358xcb_connection_t *c; 4359xcb_screen_t *screen; 4360int screen_nbr; 4361uint8_t root_depth = 0; /* the returned depth of the root window */ 4362 4363/* you init the connection and screen_nbr */ 4364 4365screen = screen_of_display (c, screen_nbr); 4366if (screen) 4367 root_depth = screen->root_depth; 4368 4369/* root_depth contains now the depth of the root window, or 0 if no screen is found */ 4370</pre> 4371 <li class="subtitle"><a name="DefaultColormap">DefaultColormap / DefaultColormapOfScreen</a> 4372 <p> 4373 This is the default colormap of the screen (and not the 4374 (default) colormap of the default screen !). As usual, you 4375 get it from the <span class="code">xcb_screen_t</span> structure: 4376 </p> 4377 <pre class="code"> 4378xcb_connection_t *c; 4379xcb_screen_t *screen; 4380int screen_nbr; 4381xcb_colormap_t default_colormap = { 0 }; /* the returned default colormap */ 4382 4383/* you init the connection and screen_nbr */ 4384 4385screen = screen_of_display (c, screen_nbr); 4386if (screen) 4387 default_colormap = screen->default_colormap; 4388 4389/* default_colormap contains now the default colormap, or a NULL colormap if no screen is found */ 4390</pre> 4391 <li class="subtitle"><a name="MinCmapsOfScreen"></a>MinCmapsOfScreen 4392 <p> 4393 You get the minimum installed colormaps in the <span class="code">xcb_screen_t</span> structure: 4394 </p> 4395 <pre class="code"> 4396xcb_connection_t *c; 4397xcb_screen_t *screen; 4398int screen_nbr; 4399uint16_t min_installed_maps = 0; /* the returned minimum installed colormaps */ 4400 4401/* you init the connection and screen_nbr */ 4402 4403screen = screen_of_display (c, screen_nbr); 4404if (screen) 4405 min_installed_maps = screen->min_installed_maps; 4406 4407/* min_installed_maps contains now the minimum installed colormaps, or 0 if no screen is found */ 4408</pre> 4409 <li class="subtitle"><a name="MaxCmapsOfScreen"></a>MaxCmapsOfScreen 4410 <p> 4411 You get the maximum installed colormaps in the <span class="code">xcb_screen_t</span> structure: 4412 </p> 4413 <pre class="code"> 4414xcb_connection_t *c; 4415xcb_screen_t *screen; 4416int screen_nbr; 4417uint16_t max_installed_maps = 0; /* the returned maximum installed colormaps */ 4418 4419/* you init the connection and screen_nbr */ 4420 4421screen = screen_of_display (c, screen_nbr); 4422if (screen) 4423 max_installed_maps = screen->max_installed_maps; 4424 4425/* max_installed_maps contains now the maximum installed colormaps, or 0 if no screen is found */ 4426</pre> 4427 <li class="subtitle"><a name="DoesSaveUnders"></a>DoesSaveUnders 4428 <p> 4429 You know if <span class="code">save_unders</span> is set, 4430 by looking in the <span class="code">xcb_screen_t</span> structure: 4431 </p> 4432 <pre class="code"> 4433xcb_connection_t *c; 4434xcb_screen_t *screen; 4435int screen_nbr; 4436uint8_t save_unders = 0; /* the returned value of save_unders */ 4437 4438/* you init the connection and screen_nbr */ 4439 4440screen = screen_of_display (c, screen_nbr); 4441if (screen) 4442 save_unders = screen->save_unders; 4443 4444/* save_unders contains now the value of save_unders, or FALSE if no screen is found */ 4445</pre> 4446 <li class="subtitle"><a name="DoesBackingStore"></a>DoesBackingStore 4447 <p> 4448 You know the value of <span class="code">backing_stores</span>, 4449 by looking in the <span class="code">xcb_screen_t</span> structure: 4450 </p> 4451 <pre class="code"> 4452xcb_connection_t *c; 4453xcb_screen_t *screen; 4454int screen_nbr; 4455uint8_t backing_stores = 0; /* the returned value of backing_stores */ 4456 4457/* you init the connection and screen_nbr */ 4458 4459screen = screen_of_display (c, screen_nbr); 4460if (screen) 4461 backing_stores = screen->backing_stores; 4462 4463/* backing_stores contains now the value of backing_stores, or FALSE if no screen is found */ 4464</pre> 4465 <li class="subtitle"><a name="EventMaskOfScreen"></a>EventMaskOfScreen 4466 <p> 4467 To get the current input masks, 4468 you look in the <span class="code">xcb_screen_t</span> structure: 4469 </p> 4470 <pre class="code"> 4471xcb_connection_t *c; 4472xcb_screen_t *screen; 4473int screen_nbr; 4474uint32_t current_input_masks = 0; /* the returned value of current input masks */ 4475 4476/* you init the connection and screen_nbr */ 4477 4478screen = screen_of_display (c, screen_nbr); 4479if (screen) 4480 current_input_masks = screen->current_input_masks; 4481 4482/* current_input_masks contains now the value of the current input masks, or FALSE if no screen is found */ 4483</pre> 4484 </ol> 4485 <li class="subtitle"><a name="misc">Miscellaneous macros</a> 4486 <ol> 4487 <li class="subtitle"><a name="DisplayOfScreen"></a>DisplayOfScreen 4488 <p> 4489 in Xlib, the <span class="code">Screen</span> structure 4490 stores its associated <span class="code">Display</span> 4491 structure. This is not the case in the X Window protocol, 4492 hence, it's also not the case in XCB. So you have to store 4493 it by yourself. 4494 </p> 4495 <li class="subtitle"><a name="DisplayCells"></a>DisplayCells / CellsOfScreen 4496 <p> 4497 To get the colormap entries, 4498 you look in the <span class="code">xcb_visualtype_t</span> 4499 structure, that you grab like <a class="subsection" href="#DefaultVisual">here</a>: 4500 </p> 4501 <pre class="code"> 4502xcb_connection_t *c; 4503xcb_visualtype_t *visual_type; 4504uint16_t colormap_entries = 0; /* the returned value of the colormap entries */ 4505 4506/* you init the connection and visual_type */ 4507 4508if (visual_type) 4509 colormap_entries = visual_type->colormap_entries; 4510 4511/* colormap_entries contains now the value of the colormap entries, or FALSE if no screen is found */ 4512</pre> 4513 </ol> 4514 </ol> 4515 </ol> 4516 </div> 4517</body> 4518 4519</html> 4520