| Basic Overview |
|---|
| The intention of this tutorial is to teach you how to use the Xlib interface for programming X, and how to learn more so that you can write advanced applications that require the speed or power of Xlib. |
| The Design of X |
| X is designed to make communication between the application and the drawing layer over a network be abstract. The user application is known as a client, and the program that draws what the client requests is known as a server. A client/application connects to a server using XOpenDisplay(). XOpenDisplay() returns a pointer to a Display structure. This display structure is passed to most Xlib calls to communicate with the server. |
| Fundamental Types |
X has fundamental types that are used to represent drawable surfaces. The following types are classified as Drawables:
|
| Windows and Layers of Windows |
| A common misconception is that a window is only what is dragged around on a desktop. X has layers of windows. The root window is also known as the background window. It can have a background image, animation, and other fun things. Immediate children of the root window are generally reparented into windows with titlebars, and buttons. Most applications are made up of many windows, and windows within windows. |
| Definition of a Widget |
A widget is usually associated with a window. A few simple examples of widgets are:
|
| Definition of a Gadget |
| A gadget is typically an item that is drawn onto its parent, and doesn't have a window for itself. Text labels are implemented in some toolkits as gadgets. |
| Pixmaps |
| A Pixmap is a Drawable that is offscreen. A Pixmap can be drawn on, and then copied to a window. It's also possible to copy a Pixmap to another Pixmap. A Pixmap is useful for buffering what you will draw. |
| Events and their place in X |
The X server sends messages known as events, to a client so that it may know of:
|
| The XEvent Structure |
| An XEvent structure contains a union of structures for the various types of events. For example, an XButtonEvent is contained in the XEvent structure with the name "xbutton" These structures are documented in the manual pages for their respective names. |
| The Event Queue |
| When events are generated by user interaction or background tasks, they are placed into a queue that is specific to each display connection. This queue of events is then processed by the client. A common function for the purpose of retrieving and removing an item from the queue is XNextEvent(). There are several other functions that deal with the event queue. Some check for events without removing them from the queue, others check for specific classes of events. |
| The Request Buffer |
| Xlib functions that send requests are buffered. In many cases an XFlush (dis); is needed to force the buffered requests to be sent/flushed to the server. Another related function is XSync which flushes and then waits until the processing of a request is complete. |
| Colors |
| X has been ported to dozens of different kinds of machines. From black and white displays, to 32-bit or higher displays. Most common displays are now using 16, 24, or 32 bits for each pixel. Older displays may only allow for 8 bits. Colors may be represented differently depending on the system. Some systems may have colormaps that retain a variable number of color cells. XParseColor() is used to convert a symbolic name to a series of RGB values for an XColor structure. XAllocColor is used after a color is parsed, and its RGB components stored in a structure. XAllocColor will match the color's RGB components to a cell in the colormap for the display. |
| Images |
X uses an XImage structure for storage of regions of the display, that can be manipulated as sequential bytes of memory in the ->data member of the structure, or via the XPutPixel()/XGetPixel() functions. The format of the XImage ->data member is dependent on the visual, and byte order of the display. An X server may run on a Sparc while the client runs on an Intel Pentium. This means that the data will need to be reformated, because the byte order is different on these two processors. If the data is not reformatted then the colors may be incorrect. There are two formats for the ->byte_order member; LSBFirst (least significant byte first), and MSBFirst (most significant byte first). See XPutImage below. The XPutPixel and XGetPixel functions know how to properly handle the display's visual formats, and translate as needed. However, the large number of function calls needed for setting/manipulating an image may cause a slowdown if they are used. |
| XCreateImage |
| The XCreateImage() function is used to create an XImage structure that represents the image data. This structure is then passed to the XPutImage() function to transfer the content to a Pixmap or Window or XdbeBackBuffer. By default the ->byte_order member of an XImage returned is in the format of server (MSBFirst or LSBFirst (see above)). |
| XPutImage |
| The XPutImage() function is used to transfer an image to the server. It also performs byte order conversions if the ->byte_order of the XImage is different than the server's byte order. |
| Finding the Byte Order |
This is best done at configuration time of your software, before it's compiled. A simple function that can be used to find the byte order is:
int get_byte_order (void) {
union {
char c[sizeof(short)];
short s;
} order;
order.s = 1;
if ((1 == order.c[0])) {
return LSBFirst;
}
return MSBFirst;
}
|
| Mapping/Displaying Windows |
| After a window is created it isn't visible on the screen. To display a window the XMapWindow() function is used. There are other functions that perform mapping as well, and they are documented on the man page for the XMapWindow function. |
| Unmapping/Hiding Windows |
| The function XUnmapWindow() is typically used to unmap a window. The contents of the display will be lost in most cases, and you will need to redraw it, after mapping it again (if you do remap in the future). |
| Helping Yourself |
| The X man pages are vital when programming with Xlib. A very common way to help yourself is to run man -k keyword. When the documentation isn't clear you may find it useful to consult the postscript documentation that is available with the X sources. The X sources are also useful when the documentation is unclear. The Xlib sources can be found in xsrc/xc/lib/X11. It's very useful to understand how to use grep when finding how a function is implemented, such as which file, and which line. For example: grep 'XCreateGC[ \t](' * |
| Learn by Example |
| The various utilities distributed with the X distribution are incredibly useful for learning how to use Xlib, and its many features. |
| Help!? I'm stuck! |
| This happens to most X programmers. Some aspects of X may be confusing you, or you're uncertain of something, or misunderstand a key concept. If the steps outlined in Helping Yourself above don't help then I suggest you study the Usenet archives for comp.windows.x at Google Groups |