Posted on Fri 09 March 2012

A fairly minimal xscreensaver

Today, I wanted to write my own screensaver, so I started looking for frameworks. Quickly, I found [cached]xscreensaver, the de facto standard (?) for screensavers on X11.

The readme does mention two example screensavers developers should use to start out, but they still contain some superfluous stuff (GOTOs !). To get a better understanding of the framework, I set out to reduce them as much as possible. Without further ado, here's the result of my work. Stay tuned for my finished screensaver.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
/* xscreensaver, Copyright (c) 1992-2008 Jamie Zawinski <jwz@jwz.org>
 *
 * Permission to use, copy, modify, distribute, and sell this software and its
 * documentation for any purpose is hereby granted without fee, provided that
 * the above copyright notice appear in all copies and that both that
 * copyright notice and this permission notice appear in supporting
 * documentation.  No representations are made about the suitability of this
 * software for any purpose.  It is provided "as is" without express or 
 * implied warranty.
 */

#include "screenhack.h"

struct state {
  Display *dpy;
  Window window;

  GC gc;
  int delay;
  unsigned long fg, bg, pixels [512];
  int npixels;
  int xlim, ylim;
  Colormap cmap;
};


static void *
minimal_init (Display *dpy, Window window)
{
  struct state *st = (struct state *) calloc (1, sizeof(*st));
  int i = 0;

  XGCValues gcv;
  XWindowAttributes xgwa;
  st->dpy = dpy;
  st->window = window;

  XGetWindowAttributes (st->dpy, st->window, &xgwa);
  st->xlim = xgwa.width;
  st->ylim = xgwa.height;
  st->cmap = xgwa.colormap;
  gcv.foreground= st->fg= get_pixel_resource(st->dpy, st->cmap, "foreground","Foreground");
  gcv.background= st->bg= get_pixel_resource(st->dpy, st->cmap, "background","Background");

  st->delay = get_integer_resource (st->dpy, "delay", "Integer");
  if (st->delay < 0) st->delay = 0;

  st->gc = XCreateGC (st->dpy, st->window, GCForeground, &gcv);

  for(st->npixels = 0; st->npixels < 512; st->npixels++)
  {
    XColor fgc;

    fgc.flags = DoRed|DoGreen|DoBlue;
    fgc.red = random ();
    fgc.green = random ();
    fgc.blue = random ();
    XAllocColor (st->dpy, st->cmap, &fgc);
    st->pixels[st->npixels] = fgc.pixel;
  }

  return st;
}

static unsigned long
minimal_draw (Display *dpy, Window window, void *closure)
{
  struct state *st = (struct state *) closure;
  int x, y, w=50, h=50, i;
  XGCValues gcv;

  x = random () % (st->xlim - w);
  y = random () % (st->ylim - h);

  gcv.foreground = st->pixels [random () % st->npixels];

  XChangeGC (st->dpy, st->gc, GCForeground, &gcv);
  XFillRectangle (st->dpy, st->window, st->gc, x, y, w, h);
  return st->delay;
}

static const char *minimal_defaults [] = {
  ".background: black",
  ".foreground: white",
  "*fpsSolid: true",
  "*delay:  10000",
  0
};

static XrmOptionDescRec minimal_options [] = {
  { "-delay",   ".delay", XrmoptionSepArg, 0 },
  { 0, 0, 0, 0 }
};

static void
minimal_reshape (Display *dpy, Window window, void *closure, 
                 unsigned int w, unsigned int h)
{
  struct state *st = (struct state *) closure;
  st->xlim = w;
  st->ylim = h;
}

static Bool
minimal_event (Display *dpy, Window window, void *closure, XEvent *event)
{
  return False;
}

static void
minimal_free (Display *dpy, Window window, void *closure)
{
}

XSCREENSAVER_MODULE ("Minimal", minimal)

Usage

Download the [cached]xscreensaver source and unpack it somewhere. To add your own screensaver (eg this minimal example), either replace the code in one of the existing files (for a quick try) or add your own file. Normal screensavers are in hacks, if you want to use OpenGL look in hacks/glx. If you add your own .c file, you also have to edit the Makefile - just do it like the already existing screensavers.

To actually build the project, run

1
2
./configure
make

The completed executable will be in hacks.

Tags: programming, graphics

© Julian Schrittwieser. Built using Pelican. Theme by Giulio Fidente on github. .