From http://www.jwz.org/xscreensaver/xscreensaver-5.22.tar.gz
[xscreensaver] / hacks / halo.c
index b8270ee8960bdbe0b1895e554b6d3501edac2ac8..40a55402a95b5491908cc6bdea686781dba9c4b5 100644 (file)
@@ -1,4 +1,4 @@
-/* xscreensaver, Copyright (c) 1993 Jamie Zawinski <jwz@mcom.com>
+/* xscreensaver, Copyright (c) 1993-2013 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
@@ -19,6 +19,7 @@
  */
 
 #include "screenhack.h"
+#include <stdio.h>
 
 struct circle {
   int x, y, radius;
@@ -26,320 +27,414 @@ struct circle {
   int dx, dy;
 };
 
-static struct circle *circles;
-static int count, global_count;
-static Pixmap pixmap, buffer;
-static int width, height, global_inc;
-static int delay;
-static unsigned long fg_pixel, bg_pixel;
-static XColor fgc, bgc;
-static Bool xor_p;
-static GC draw_gc, erase_gc, copy_gc, merge_gc;
-static Bool anim_p;
-static Colormap cmap;
+static enum color_mode {
+  seuss_mode, ramp_mode, random_mode
+} cmode;
+
+
+struct state {
+  Display *dpy;
+  Window window;
+
+  struct circle *circles;
+  int count, global_count;
+  Pixmap pixmap, buffer;
+  int width, height, global_inc;
+  int delay, delay2;
+  unsigned long fg_pixel, bg_pixel;
+  GC draw_gc, erase_gc, copy_gc, merge_gc;
+  Bool anim_p;
+  Colormap cmap;
+
+  int ncolors;
+  XColor *colors;
+  int fg_index;
+  int bg_index;
+
+  int iterations;
+  Bool done_once;
+  Bool done_once_no_really;
+  int clear_tick;
+  struct timeval then;
+};
 
 #define min(x,y) ((x)<(y)?(x):(y))
 #define max(x,y) ((x)>(y)?(x):(y))
 
 static void
-init_circles_1 (dpy, window)
-     Display *dpy;
-     Window window;
+init_circles_1 (struct state *st)
 {
   int i;
-  count = (global_count ? global_count
-          : (3 + (random () % max (1, (min (width, height) / 50)))
-               + (random () % max (1, (min (width, height) / 50)))));
-  circles = (struct circle *) malloc (count * sizeof (struct circle));
-  for (i = 0; i < count; i++)
+  st->count = (st->global_count ? st->global_count
+          : (3 + (random () % max (1, (min (st->width, st->height) / 50)))
+               + (random () % max (1, (min (st->width, st->height) / 50)))));
+  st->circles = (struct circle *) malloc (st->count * sizeof (struct circle));
+  for (i = 0; i < st->count; i++)
     {
-      circles [i].x = 10 + random () % (width - 20);
-      circles [i].y = 10 + random () % (height - 20);
-      if (global_inc)
-      circles [i].increment = global_inc;
+      st->circles [i].x = 10 + random () % (st->width - 20);
+      st->circles [i].y = 10 + random () % (st->height - 20);
+      if (st->global_inc)
+      st->circles [i].increment = st->global_inc;
       else
        { /* prefer smaller increments to larger ones */
          int j = 8;
          int inc = ((random()%j) + (random()%j) + (random()%j)) - ((j*3)/2);
          if (inc < 0) inc = -inc + 3;
-         circles [i].increment = inc + 3;
+         st->circles [i].increment = inc + 3;
        }
-      circles [i].radius = random () % circles [i].increment;
-      circles [i].dx = ((random () % 3) - 1) * (1 + random () % 5);
-      circles [i].dy = ((random () % 3) - 1) * (1 + random () % 5);
+      st->circles [i].radius = random () % st->circles [i].increment;
+      st->circles [i].dx = ((random () % 3) - 1) * (1 + random () % 5);
+      st->circles [i].dy = ((random () % 3) - 1) * (1 + random () % 5);
     }
 }
 
-static void
-init_circles (dpy, window)
-     Display *dpy;
-     Window window;
+static void *
+halo_init (Display *dpy, Window window)
 {
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
   XGCValues gcv;
   XWindowAttributes xgwa;
-  XGetWindowAttributes (dpy, window, &xgwa);
-  cmap = xgwa.colormap;
-  global_count = get_integer_resource ("count", "Integer");
-  if (global_count < 0) global_count = 0;
-  global_inc = get_integer_resource ("increment", "Integer");
-  if (global_inc < 0) global_inc = 0;
-  xor_p = get_boolean_resource ("xor", "Boolean");
-/*  if (mono_p) */ xor_p = True;
-  anim_p = get_boolean_resource ("animate", "Boolean");
-  delay = get_integer_resource ("delay", "Integer");
+  char *mode_str = 0;
+  st->dpy = dpy;
+  st->window = window;
+  XGetWindowAttributes (st->dpy, st->window, &xgwa);
+  st->cmap = xgwa.colormap;
+  st->global_count = get_integer_resource (st->dpy, "count", "Integer");
+  if (st->global_count < 0) st->global_count = 0;
+  st->global_inc = get_integer_resource (st->dpy, "increment", "Integer");
+  if (st->global_inc < 0) st->global_inc = 0;
+  st->anim_p = get_boolean_resource (st->dpy, "animate", "Boolean");
+  st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+  st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer") * 1000000;
+  mode_str = get_string_resource (st->dpy, "colorMode", "ColorMode");
+  if (! mode_str) cmode = random_mode;
+  else if (!strcmp (mode_str, "seuss"))  cmode = seuss_mode;
+  else if (!strcmp (mode_str, "ramp"))   cmode = ramp_mode;
+  else if (!strcmp (mode_str, "random")) cmode = random_mode;
+  else {
+    fprintf (stderr,
+            "%s: colorMode must be seuss, ramp, or random, not \"%s\"\n",
+            progname, mode_str);
+    exit (1);
+  }
+
+  if (mono_p) cmode = seuss_mode;
+  if (cmode == random_mode)
+    cmode = ((random()&3) == 1) ? ramp_mode : seuss_mode;
+
+  if (cmode == ramp_mode)
+    st->anim_p = False;    /* This combo doesn't work right... */
+
+  st->ncolors = get_integer_resource (st->dpy, "colors", "Colors");
+  if (st->ncolors < 2) st->ncolors = 2;
+  if (st->ncolors <= 2) mono_p = True;
+
+  if (mono_p)
+    st->colors  = 0;
+  else
+    st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1));
+
+
+  if (mono_p)
+    ;
+  else if (random() % (cmode == seuss_mode ? 2 : 10))
+    make_uniform_colormap (xgwa.screen, xgwa.visual, st->cmap,
+                           st->colors, &st->ncolors,
+                          True, 0, True);
+  else
+    make_smooth_colormap (xgwa.screen, xgwa.visual, st->cmap,
+                          st->colors, &st->ncolors,
+                         True, 0, True);
+
+  if (st->ncolors <= 2) mono_p = True;
+  if (mono_p) cmode = seuss_mode;
+
   if (mono_p)
     {
-      fg_pixel = get_pixel_resource ("foreground","Foreground", dpy, cmap);
-      bg_pixel = get_pixel_resource ("background","Background", dpy, cmap);
+      st->fg_pixel = get_pixel_resource (st->dpy, st->cmap, "foreground", "Foreground");
+      st->bg_pixel = get_pixel_resource (st->dpy, st->cmap, "background", "Background");
     }
   else
     {
-      hsv_to_rgb (0,   0.5, 1.0, &fgc.red, &fgc.green, &fgc.blue);
-      hsv_to_rgb (180, 1.0, 0.7, &bgc.red, &bgc.green, &bgc.blue);
-      XAllocColor (dpy, cmap, &fgc);
-      XAllocColor (dpy, cmap, &bgc);
-      fg_pixel = fgc.pixel;
-      bg_pixel = bgc.pixel;
+      st->fg_index = 0;
+      st->bg_index = st->ncolors / 4;
+      if (st->fg_index == st->bg_index) st->bg_index++;
+      st->fg_pixel = st->colors[st->fg_index].pixel;
+      st->bg_pixel = st->colors[st->bg_index].pixel;
     }
 
-  width = max (50, xgwa.width);
-  height = max (50, xgwa.height);
+  st->width = max (50, xgwa.width);
+  st->height = max (50, xgwa.height);
 
 #ifdef DEBUG
-  width/=2; height/=2;
+  st->width/=2; st->height/=2;
 #endif
 
-  pixmap = XCreatePixmap (dpy, window, width, height, 1);
-  if (xor_p)
-    buffer = XCreatePixmap (dpy, window, width, height, 1);
+  st->pixmap = XCreatePixmap (st->dpy, st->window, st->width, st->height, 1);
+  if (cmode == seuss_mode)
+    st->buffer = XCreatePixmap (st->dpy, st->window, st->width, st->height, 1);
   else
-    buffer = 0;
+    st->buffer = 0;
 
   gcv.foreground = 1;
   gcv.background = 0;
-  draw_gc = XCreateGC (dpy, pixmap, GCForeground | GCBackground, &gcv);
+  st->draw_gc = XCreateGC (st->dpy, st->pixmap, GCForeground | GCBackground, &gcv);
   gcv.foreground = 0;
-  erase_gc = XCreateGC (dpy, pixmap, GCForeground, &gcv);
-  gcv.foreground = fg_pixel;
-  gcv.background = bg_pixel;
-  copy_gc = XCreateGC (dpy, window, GCForeground | GCBackground, &gcv);
+  st->erase_gc = XCreateGC (st->dpy, st->pixmap, GCForeground, &gcv);
+  gcv.foreground = st->fg_pixel;
+  gcv.background = st->bg_pixel;
+  st->copy_gc = XCreateGC (st->dpy, st->window, GCForeground | GCBackground, &gcv);
 
-  if (xor_p)
+#ifdef HAVE_COCOA
+  jwxyz_XSetAntiAliasing (dpy, st->draw_gc,  False);
+  jwxyz_XSetAntiAliasing (dpy, st->erase_gc, False);
+  jwxyz_XSetAntiAliasing (dpy, st->copy_gc,  False);
+#endif
+
+  if (cmode == seuss_mode)
     {
       gcv.foreground = 1;
       gcv.background = 0;
       gcv.function = GXxor;
-      merge_gc = XCreateGC (dpy, pixmap,
+      st->merge_gc = XCreateGC (st->dpy, st->pixmap,
                            GCForeground | GCBackground | GCFunction, &gcv);
     }
   else
     {
-      gcv.foreground = fg_pixel;
-      gcv.background = bg_pixel;
+      gcv.foreground = st->fg_pixel;
+      gcv.background = st->bg_pixel;
       gcv.function = GXcopy;
-      merge_gc = XCreateGC (dpy, window,
+      st->merge_gc = XCreateGC (st->dpy, st->window,
                            GCForeground | GCBackground | GCFunction, &gcv);
     }
 
-  init_circles_1 (dpy, window);
-  XClearWindow (dpy, window);
-  if (buffer) XFillRectangle (dpy, buffer, erase_gc, 0, 0, width, height);
+  init_circles_1 (st);
+  XClearWindow (st->dpy, st->window);
+  if (st->buffer) XFillRectangle (st->dpy, st->buffer, st->erase_gc, 0, 0, st->width, st->height);
+  return st;
 }
 
-static void
-run_circles (dpy, window)
-     Display *dpy;
-     Window window;
+static unsigned long
+halo_draw (Display *dpy, Window window, void *closure)
 {
+  struct state *st = (struct state *) closure;
   int i;
-  static int iterations = 0;
-  static int oiterations = 0;
-  static Bool first_time_p = True;
   Bool done = False;
   Bool inhibit_sleep = False;
-  XFillRectangle (dpy, pixmap, erase_gc, 0, 0, width, height);
-  for (i = 0; i < count; i++)
+  int this_delay = st->delay;
+
+  XFillRectangle (st->dpy, st->pixmap, st->erase_gc, 0, 0, st->width, st->height);
+  for (i = 0; i < st->count; i++)
     {
-      int radius = circles [i].radius;
-      int inc = circles [i].increment;
-      if (! (iterations & 1))
+      int radius = st->circles [i].radius;
+      int inc = st->circles [i].increment;
+
+      if (! (st->iterations & 1))  /* never stop on an odd number of iterations */
        ;
-      else if (radius == 0)
+      else if (radius == 0)    /* eschew inf */
        ;
-      else if (radius < 0)
+      else if (radius < 0)     /* stop when the circles are points */
        done = True;
-      else
+      else                     /* stop when the circles fill the st->window */
        {
          /* Probably there's a simpler way to ask the musical question,
             "is this square completely enclosed by this circle," but I've
             forgotten too much trig to know it...  (That's not really the
             right question anyway, but the right question is too hard.) */
-         double x1 = ((double) (-circles [i].x)) / ((double) radius);
-         double y1 = ((double) (-circles [i].y)) / ((double) radius);
-         double x2 = ((double) (width - circles [i].x)) / ((double) radius);
-         double y2 = ((double) (height - circles [i].y)) / ((double) radius);
+         double x1 = ((double) (-st->circles [i].x)) / ((double) radius);
+         double y1 = ((double) (-st->circles [i].y)) / ((double) radius);
+         double x2 = ((double) (st->width - st->circles [i].x)) / ((double) radius);
+         double y2 = ((double) (st->height - st->circles [i].y)) / ((double) radius);
          x1 *= x1; x2 *= x2; y1 *= y1; y2 *= y2;
          if ((x1 + y1) < 1 && (x2 + y2) < 1 && (x1 + y2) < 1 && (x2 + y1) < 1)
            done = True;
        }
+
       if (radius > 0 &&
-         (xor_p || circles [0].increment < 0))
-       XFillArc (dpy,
-                 (xor_p ? pixmap : window),
-                 (xor_p ? draw_gc : merge_gc),
-                 circles [i].x - radius, circles [i].y - radius,
-                 radius * 2, radius * 2, 0, 360*64);
-      circles [i].radius += inc;
+         (cmode == seuss_mode ||       /* drawing all circles, or */
+          st->circles [0].increment < 0))      /* on the way back in */
+       {
+         XFillArc (st->dpy,
+                   (cmode == seuss_mode ? st->pixmap : st->window),
+                   (cmode == seuss_mode ? st->draw_gc : st->merge_gc),
+                   st->circles [i].x - radius, st->circles [i].y - radius,
+                   radius * 2, radius * 2, 0, 360*64);
+       }
+      st->circles [i].radius += inc;
     }
 
-  if (anim_p && !first_time_p)
+  if (st->anim_p && !st->done_once)
     inhibit_sleep = !done;
 
   if (done)
     {
-      if (anim_p)
+      if (st->anim_p)
        {
-         first_time_p = False;
-         for (i = 0; i < count; i++)
+         st->done_once = True;
+         for (i = 0; i < st->count; i++)
            {
-             circles [i].x += circles [i].dx;
-             circles [i].y += circles [i].dy;
-             circles [i].radius %= circles [i].increment;
-             if (circles [i].x < 0 || circles [i].x >= width)
+             st->circles [i].x += st->circles [i].dx;
+             st->circles [i].y += st->circles [i].dy;
+             st->circles [i].radius %= st->circles [i].increment;
+             if (st->circles [i].x < 0 || st->circles [i].x >= st->width)
                {
-                 circles [i].dx = -circles [i].dx;
-                 circles [i].x += (2 * circles [i].dx);
+                 st->circles [i].dx = -st->circles [i].dx;
+                 st->circles [i].x += (2 * st->circles [i].dx);
                }
-             if (circles [i].y < 0 || circles [i].y >= height)
+             if (st->circles [i].y < 0 || st->circles [i].y >= st->height)
                {
-                 circles [i].dy = -circles [i].dy;
-                 circles [i].y += (2 * circles [i].dy);
+                 st->circles [i].dy = -st->circles [i].dy;
+                 st->circles [i].y += (2 * st->circles [i].dy);
                }
            }
        }
-      else if (circles [0].increment < 0)
+      else if (st->circles [0].increment < 0)
        {
-         free (circles);
-         init_circles_1 (dpy, window);
+         /* We've zoomed out and the screen is blank -- re-pick the
+            center points, and shift the st->colors.
+          */
+         free (st->circles);
+         init_circles_1 (st);
          if (! mono_p)
            {
-             cycle_hue (&fgc, 10);
-             cycle_hue (&bgc, 10);
-             XFreeColors (dpy, cmap, &fgc.pixel, 1, 0);
-             XFreeColors (dpy, cmap, &bgc.pixel, 1, 0);
-             XAllocColor (dpy, cmap, &fgc);
-             XAllocColor (dpy, cmap, &bgc);
-             XSetForeground (dpy, copy_gc, fgc.pixel);
-             XSetBackground (dpy, copy_gc, bgc.pixel);
+             st->fg_index = (st->fg_index + 1) % st->ncolors;
+             st->bg_index = (st->fg_index + (st->ncolors/2)) % st->ncolors;
+             XSetForeground (st->dpy, st->copy_gc, st->colors [st->fg_index].pixel);
+             XSetBackground (st->dpy, st->copy_gc, st->colors [st->bg_index].pixel);
            }
        }
-#if 0
-      else if ((random () % 2) == 0)
+      /* Sometimes go out from the inside instead of the outside */
+      else if (st->clear_tick == 0 && ((random () % 3) == 0))
        {
-         iterations = 0; /* ick */
-         for (i = 0; i < count; i++)
-           circles [i].radius %= circles [i].increment;
+         st->iterations = 0; /* ick */
+         for (i = 0; i < st->count; i++)
+           st->circles [i].radius %= st->circles [i].increment;
+
+          st->clear_tick = ((random() % 8) + 4) | 1;   /* must be odd */
        }
-#endif
       else
        {
-         oiterations = iterations;
-         for (i = 0; i < count; i++)
+         for (i = 0; i < st->count; i++)
            {
-             circles [i].increment = -circles [i].increment;
-             circles [i].radius += (2 * circles [i].increment);
+             st->circles [i].increment = -st->circles [i].increment;
+             st->circles [i].radius += (2 * st->circles [i].increment);
            }
        }
     }
 
-  if (buffer)
-    XCopyPlane (dpy, pixmap, buffer, merge_gc, 0, 0, width, height, 0, 0, 1);
-  else if (!xor_p)
+  if (st->buffer)
+    XCopyPlane (st->dpy, st->pixmap, st->buffer, st->merge_gc, 0, 0, st->width, st->height, 0, 0, 1);
+  else if (cmode != seuss_mode)
     {
-      static int ncolors = 0;
-      static XColor *colors = 0;
-      if (circles [0].increment >= 0)
-       inhibit_sleep = True;
-      else if (done)
-       {
-         int fgh, bgh;
-         double fgs, fgv, bgs, bgv;
-         if (colors)
-           for (i = 0; i < ncolors; i++)
-             XFreeColors (dpy, cmap, &colors [i].pixel, 1, 0);
-
-         rgb_to_hsv (fgc.red, fgc.green, fgc.blue, &fgh, &fgs, &fgv);
-         rgb_to_hsv (bgc.red, bgc.green, bgc.blue, &bgh, &bgs, &bgv);
-         ncolors = oiterations;
-         colors = ((XColor *)
-                   (colors
-                    ? realloc (colors, sizeof (XColor) * ncolors)
-                    : malloc (sizeof (XColor) * ncolors)));
-         
-         make_color_ramp (bgh, bgs, bgv, fgh, fgs, fgv, colors, ncolors);
-         for (i = 0; i < ncolors; i++)
-           XAllocColor (dpy, cmap, &colors [i]);
-         XSetForeground (dpy, merge_gc, colors [0].pixel);
-       }
-      else
+
+      if (!mono_p)
        {
-         XSetForeground (dpy, merge_gc, colors [iterations].pixel);
+         st->fg_index++;
+         st->bg_index++;
+         if (st->fg_index >= st->ncolors) st->fg_index = 0;
+         if (st->bg_index >= st->ncolors) st->bg_index = 0;
+         XSetForeground (st->dpy, st->merge_gc, st->colors [st->fg_index].pixel);
        }
+
+      if (st->circles [0].increment >= 0)
+       inhibit_sleep = True;
+      else if (done && cmode == seuss_mode)
+       XFillRectangle (st->dpy, st->window, st->merge_gc, 0, 0, st->width, st->height);
     }
   else
-    XCopyPlane (dpy, pixmap, window, merge_gc, 0, 0, width, height, 0, 0, 1);
+    XCopyPlane (st->dpy, st->pixmap, st->window, st->merge_gc, 0, 0, st->width, st->height, 0, 0, 1);
 
-  if (buffer && (anim_p
-                ? (done || (first_time_p && (iterations & 1)))
-                : (iterations & 1)))
+  /* st->buffer is only used in seuss-mode or anim-mode */
+  if (st->buffer && (st->anim_p
+                ? (done || (!st->done_once && (st->iterations & 1)))
+                : (st->iterations & 1)))
     {
-      XCopyPlane (dpy, buffer, window, copy_gc, 0, 0, width, height, 0, 0, 1);
-      XSync (dpy, True);
-      if (anim_p && done)
-       XFillRectangle (dpy, buffer, erase_gc, 0, 0, width, height);
+      XCopyPlane (st->dpy, st->buffer, st->window, st->copy_gc, 0, 0, st->width, st->height, 0, 0, 1);
+      if (st->anim_p && done)
+       XFillRectangle (st->dpy, st->buffer, st->erase_gc, 0, 0, st->width, st->height);
     }
+
 #ifdef DEBUG
-  XCopyPlane (dpy, pixmap, window, copy_gc, 0,0,width,height,width,height, 1);
-  if (buffer)
-    XCopyPlane (dpy, buffer, window, copy_gc, 0,0,width,height,0,height, 1);
-  XSync (dpy, True);
+  XCopyPlane (st->dpy, st->pixmap, st->window, st->copy_gc, 0,0,st->width,st->height,st->width,st->height, 1);
+  if (st->buffer)
+    XCopyPlane (st->dpy, st->buffer, st->window, st->copy_gc, 0,0,st->width,st->height,0,st->height, 1);
 #endif
 
   if (done)
-    iterations = 0;
+    st->iterations = 0;
   else
-    iterations++;
+    st->iterations++;
 
-  if (delay && !inhibit_sleep) usleep (delay);
+  if (st->delay && !inhibit_sleep)
+    {
+      int d = st->delay;
+
+      if (cmode == seuss_mode && st->anim_p)
+        this_delay = d/100;
+      else
+        this_delay = d;
+
+      if (done)
+       st->done_once_no_really = True;
+    }
+
+  if (done && st->clear_tick > 0)
+    {
+      st->clear_tick--;
+      if (!st->clear_tick)
+        {
+          XClearWindow (st->dpy, st->window);
+          if (st->buffer) XFillRectangle (st->dpy, st->buffer, st->erase_gc, 0,0,st->width,st->height);
+        }
+    }
+
+  if (inhibit_sleep) this_delay = 0;
+
+  return this_delay;
 }
 
 \f
-char *progclass = "Halo";
-
-char *defaults [] = {
-  "Halo.background:    black",         /* to placate SGI */
-  "Halo.foreground:    white",
-/*  "*xor:     false", */
-  "*count:     0",
-  "*delay:     100000",
+
+static const char *halo_defaults [] = {
+  ".background:                black",
+  ".foreground:                white",
+  "*colorMode:         random",
+  "*colors:            100",
+  "*count:             0",
+  "*delay:             100000",
+  "*delay2:            20",
+  "*increment:         0",
+  "*animate:           False",
+#ifdef USE_IPHONE
+  "*ignoreRotation:     True",
+#endif
   0
 };
 
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec halo_options [] = {
   { "-count",          ".count",       XrmoptionSepArg, 0 },
   { "-delay",          ".delay",       XrmoptionSepArg, 0 },
-  { "-animate",                ".animate",     XrmoptionNoArg, "True" } /* ,
-  { "-xor",            ".xor",         XrmoptionNoArg, "True" },
-  { "-no-xor",         ".xor",         XrmoptionNoArg, "False" } */
+  { "-animate",                ".animate",     XrmoptionNoArg, "True" },
+  { "-mode",           ".colorMode",   XrmoptionSepArg, 0 },
+  { "-colors",         ".colors",      XrmoptionSepArg, 0 },
+  { 0, 0, 0, 0 }
 };
-int options_size = (sizeof (options) / sizeof (options[0]));
 
-void
-screenhack (dpy, window)
-     Display *dpy;
-     Window window;
+static void
+halo_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+}
+
+static Bool
+halo_event (Display *dpy, Window window, void *closure, XEvent *event)
 {
-  init_circles (dpy, window);
-  while (1)
-    run_circles (dpy, window);
+  return False;
 }
+
+static void
+halo_free (Display *dpy, Window window, void *closure)
+{
+}
+
+XSCREENSAVER_MODULE ("Halo", halo)