X11 Programming Info


I've had a lot of difficulty finding information about writing nicely-behaving applications using Xlib, so I thought I'd share my experiences. A lot of information was taken directly from source code, even though I'm sure there are easier/better ways. If there are any mistakes on this page, or you'd like to contact me, my contact info is on the top of my homepage.

Informative Links:

Topics:

Xft2 - A Mini API Howto

Xft2 is not Freetype2. Xft2 is a library, linked to by the client X application, that uses FontConfig to load fonts, and Freetype2 to render them. I couldn't find documentation, so I flipped through the Xft source to figure out how to use it. Of course, after I did that I found Keith Packard's tutorial for using it (link above). I suggest you go there, but below are my findings.

#1 - #include <Xft.h>, -I/usr/include/X11/Xft -I/usr/include/freetype2 -lXft

The above line is specific to my system, but it tells you a few things. You have to include the path to the freetype2 headers, or it'll barf. Additionally of note is that you do not seem to need to call XftInit(char *). It's defined in Xft.h, and it does seem to do some initialization of a name database or something, but I've never seen anything use it and my work seems to get along ok without it. So I'm leaving it.

#2 - Get the font

I used XftFontOpenName(Display *, Screen, char * )
The char * is a Xft-style font name. In my hello-world, I just used "verdana" and life was good. But in reality read the Xft.tutorial. Synopsis, use family-size:options. "verdana-16" would be more specific.

#3 - Allocate 'Drawable'

Seems like XftDraw is Xft2's equivalent of a graphics context. Create it, use it, destroy it.
Creating a XftDraw requires a visual and a colormap, fetched with DefaultVisual(dpy, screen) and DefaultColormap(dpy, screen). Then, XftDrawCreate(dpy, drawable /* window or pixmap */, visual, colormap);
Remember, after you've done all your font drawing and such, to destroy the drawable (XftDrawDestroy(XftDraw *)).

#4 - Create an XftColor (my variable names for colour will avenge .ca)

There are 2 possibilities - one (which keith packard says is for bad people) creates the colour by name. This involves a round-trip to the Xserver, asking it to create the colour for you. XftColorAllocName (Display *, Visual *, Colormap, char * name, XftColor * result)
I used that the first time because I hadn't read what an XRenderColor was, and it looked easier to use at a cursory glance. Wrong. The easier (and better) way is to fill in rgba values in a struct XRenderColor { ushort red,green,blue,alpha);. Someone correct me if I'm wrong, but I'm pretty sure ~0 is good for the max value of an unsigned short. Set the alpha value to max if you want your string to be opaque. Then use XftColorAllocValue(Display *, Visual *, Colormap, XRenderColor *in, XftColor *out) Remember to XftColorFree(Display *, Visual *, Colormap, XftColor *) the color after you're done.

#5 - Draw the String

This is easy. for 8 bit chars, use XftDrawString8(XftDraw *, XftColor *, XftFont *, x,y,XftChar8 *, int len);
I just cast my chars to XftChar8, hope thats safe :-/

The end, for now

Remember to clean up with XftDrawDestroy & XftColorFree!

Getting a close button to display for your window

Ok, so if you're anything like me you've read a bunch of tutorials on writing apps with Xlib, and for some (most likely stupid, like me) reason you don't want to use Xt. You'll notice that no matter what options you change when creating your window, the window manager refuses to decorate it with a little 'x' indicating close, like it will for the rest of the windows on the screen. Needless to say, we don't want to be the only kid on the block without this feature. So here's a short HOWTO.

MWM - the _MOTIF_WM_HINTS XAtom

Undocumented in the ICCCM, no where mentioned anywhere useful that I could find except by flipping through window manager code and finding how they put decorations on windows (openbox), I discovered the window property required for your app to get an 'X'.

#1 - Get the _MOTIF_WM_HINTS Atom

XInternAtom(Display *, "_MOTIF_WM_HINTS", 1);
#2 - Create a structure MWMHINTS, set the values

struct mwmhints_t { unsigned int flags, functions, decorations; signed int input_mode; unsigned int status; } mwmhints;
mwmhints.decorations = mwmhints.functions = (1l << 0);
mwmhints.flags = (1l << 0 ) | (1l << 1);
#3 - Change the property of the window

XChangeProperty(Display *, Window, Atom, Atom, 32, PropModeReplace,(unsigned char *)&mwmhints, sizeof(mwmhints)/sizeof(long));
The End