Xlib tutorial part 6 -- user preferences

by Alan at Mon 16th Feb 2009 1:00AM EST

Hello,

This section is about obeying the user's preferences. It's not going to be complete. This is more a sample of what we can do.

First is a couple of helper functions. They read a value from the database of user preferences (of type XrmDatabase) and allocate the correct object from that. getColour allocates a colour based on what's in that database, and getFont allocates a font, both falling back to a default value (def) if for some reason there's nothing in the database, or we can't allocate it, such as if the colour name was not a colour that rgb.txt recognized, or the font name was not valid.


	...
unsigned long getColour(Display *dpy,  XrmDatabase db, char *name,
			char *cl, char *def){
	XrmValue v;
	XColor col1, col2;
	Colormap cmap = DefaultColormap(dpy, DefaultScreen(dpy));
	char * type;

	if (XrmGetResource(db, name, cl, &type, &v)
			&& XAllocNamedColor(dpy, cmap, v.addr, &col1, &col2)) {
	} else {
		XAllocNamedColor(dpy, cmap, def, &col1, &col2);
	}
	return col2.pixel;
}

XFontStruct *getFont(Display *dpy, XrmDatabase db, char *name,
		char *cl, char *def){
	XrmValue v;
	char * type;
	XFontStruct *font = NULL;

	if (XrmGetResource(db, name, cl, &type, &v)){
		if (v.addr)
			font = XLoadQueryFont(dpy, v.addr);
	}
	if (!font) {
		if (v.addr)
		fprintf(stderr, "unable to load preferred font: %s using fixed
", v.addr);
		else 
		fprintf(stderr, "unable to find preferred font
");
		font = XLoadQueryFont(dpy, def);
	}
	return font;
}
	...
	

The colours can actually be in the format #rrggbb where rrggbb are hexadecimals. You can find fonts by running xlsfonts. For portions of the name, you can use *. So -*-helvetica-*-normal-*-14-* should pick a 14 point normal (not italic) helvetica font.

These helper functions are called like this:


	...
	background = getColour(dpy,  db, "xtut6.background", "xtut6.BackGround", "DarkGreen");
	border = getColour(dpy,  db, "xtut6.border", "xtut6.Border", "LightGreen");
	values.foreground = getColour(dpy,  db, "xtut6.foreground", "xtut6.ForeGround", "Red");
	font = getFont(dpy, db, "xtut6.font", "xtut6.Font", "fixed");
	...
	

The 3rd argument is the full description of the preference's name. The 4th argument is what's called the resource's class. This is a fallback so that we can many preferences of the same class that can all be set to the same thing. We'll likely see more about this in a later lesson.

To initialize the database, we need to do two things.

	...
static XrmOptionDescRec xrmTable[] = {
	{"-bg", "*background", XrmoptionSepArg, NULL},
	{"-fg", "*foreground", XrmoptionSepArg, NULL},
	{"-bc", "*bordercolour", XrmoptionSepArg, NULL},
	{"-font", "*font", XrmoptionSepArg, NULL},
};
	...
	XrmDatabase db;

	XrmInitialize();
	db = XrmGetDatabase(dpy);
	XrmParseCommand(&db, xrmTable, sizeof(xrmTable)/sizeof(xrmTable[0]),
		"xtut6", &argc, argv);
	...
	

The xrmTable is a list that explains what to do with command line options. In this case, if it find -bg on the command line, the following argument should be placed in the database to say what the background colour should be. We could have used a line like:


		...
	{"-bg", "xtut6.background", XrmoptionSepArg, NULL},
		...
	

but we could expect to have problems then.

One final change, we've added another bit to the XSelectInput line and changed the switch statement to respond to ButtonRelease instead of ButtonPress. This is so that the window doesn't disappear while the button is still depressed and the ButtonRelease event go to whatever window was underneath.

Things to try:

Comments are closed.