The simplest screensaver module: simplesquares.c

This is a description of the xscreensaver module simplesquares.c, which is (almost) the simplest module that does something visible. It draw white squares in random places of the screen.

Any module must perform these operations:

  1. Open the display: this is used to connect to the X server, and allows the program to draw.
  2. Determine the root window: this is the window that is used by xscreensaver modules as a canvas for drawing.
  3. Create a graphic context: a graphic context tells how drawing is made (for example, it contains the foreground color).
  4. Draw something.
  5. Flush the output (make drawing visible).
We now show how these steps are implemented in simplesquares.c.

The files to include are the following ones: Xlib.h for the prototypes of the X Window routines; and vroot.h, which is used to define the virtual root window, which is where xscreensaver modules draw. So, the beginning of the source code of the module will be:


#include "vroot.h"
The first operation of our program is to connect to the X server. This is done by defining a variable dpy of type Display *, and then using the function XOpenDisplay.
main ()
  Display *dpy;
  /* other variables: see below */

  /* open the display (connect to the X server) */
  dpy = XOpenDisplay (getenv ("DISPLAY"));
The second thing to do is to determine the root window. This is needed because all graphic functions takes an argument of type Window: for the functions that draw something, this is the window in which the drawing is made. We define a variable Window root; at the beginning of the main, and use the function DefaultRootOfDisplay to determine the root window.
  /* get the root window */
  root = DefaultRootWindow (dpy);
Now, we are connected to the X server, and we know which window we want to draw into. However, no drawing can be made using only dpy and root. What is still missing is a graphic context, a structure that contains all parameters used by the drawing functions. For instance, the graphic context contains the foreground color for drawing, the font to use to draw characters, the filling style, etc. Graphic context are defined by the type GC, and are created by the function XCreateGC. We define a variable GC g; at the beginning of the program, and then
  /* create a GC for drawing in the window */
  g = XCreateGC (dpy, root, 0, NULL);
to create the graphic contenxt. For a full description of the arguments of XCreateGC see the man page.

The last thing to do, before actually start drawing, is to set the foreground color. For this example, we decide to use the white only (a following section is about colors).

  /* set foreground color */
  XSetForeground(dpy, g, WhitePixelOfScreen(DefaultScreenOfDisplay(dpy)) );

Now, we are ready to draw. The program simplesquares.c draw squares in random positions of the screen, clearing the screen once in a while.

  /* draw something */
  while (1)
      /* draw a square */
      XFillRectangle (dpy, root, g, random()%500, random()%500, 50, 40);

      /* once in a while, clear all */
      if( random()%500<1 )
        XClearWindow(dpy, root);

      /* flush changes and sleep */
      usleep (10);
The function XFlush is called to ensure that everything is draw. The function XClearWindow is used to clear the root window, that is, to blank the screeen. XClearWindow(dpy, root); clears the screen. In this program, it is called only when random()%500<1, that is, once every 500 runs of the cycle (on average).

The squares are drawn using the function XFillRectangle. The left-upper corner of each square has coordinates random()%500, random()%500: these are two random numbers between 0 and 500-1. The width of the squares is 50, and the height is 40.

Other functions for drawing are:

Draw a single point
Draw a line between two points
Draw a non-filled rectangle
Draw a filled rectangle
Draw an arc (used to draw circles and ellipses)
Draw a filled arc (circle, and ellipese)
See the man page for details.

The complete source code: simplesquares.c.

To compile, test, and install, see: testing and installing a new module

Next: getting the screen size.