ftp://ftp.krokus.ru/pub/OpenBSD/distfiles/xscreensaver-5.01.tar.gz
[xscreensaver] / hacks / slidescreen.c
index dde3a21a5936da401ef191753ed345557d72d877..42d3fefca029a6b10a03d81b640f7f334f942f90 100644 (file)
@@ -1,5 +1,4 @@
-/* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997, 1998, 2001, 2003 
- * Jamie Zawinski <jwz@jwz.org>
+/* xscreensaver, Copyright (c) 1992-2006 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
 
 #include "screenhack.h"
 
-static int grid_size;
-static int pix_inc;
-static int hole_x, hole_y;
-static int bitmap_w, bitmap_h;
-static int xoff, yoff;
-static int grid_w, grid_h;
-static int delay, delay2;
-static GC gc;
-static int max_width, max_height;
+enum { DOWN = 0, LEFT, UP, RIGHT };
+enum { VERTICAL, HORIZONTAL };
+
+struct state {
+  Display *dpy;
+  Window window;
+
+  int grid_size;
+  int pix_inc;
+  int hole_x, hole_y;
+  int bitmap_w, bitmap_h;
+  int xoff, yoff;
+  int grid_w, grid_h;
+  int delay, delay2;
+  GC gc;
+  unsigned long fg, bg;
+  int max_width, max_height;
+  int early_i;
 
-static void
-init_slide (Display *dpy, Window window)
+  int draw_rnd, draw_i;
+  int draw_x, draw_y, draw_ix, draw_iy, draw_dx, draw_dy;
+  int draw_dir, draw_w, draw_h, draw_size, draw_inc;
+  int draw_last;
+  int draw_initted;
+
+  async_load_state *img_loader;
+};
+
+
+static void *
+slidescreen_init (Display *dpy, Window window)
 {
-  int i;
-  XGCValues gcv;
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
   XWindowAttributes xgwa;
-  long gcflags;
-  int border;
-  unsigned long fg, bg;
-  Drawable d;
-  Colormap cmap;
   Visual *visual;
+  XGCValues gcv;
+  long gcflags;
+
+  st->dpy = dpy;
+  st->window = window;
+  XGetWindowAttributes (st->dpy, st->window, &xgwa);
+  st->img_loader = load_image_async_simple (0, xgwa.screen, st->window,
+                                            st->window, 0, 0);
 
-  XGetWindowAttributes (dpy, window, &xgwa);
-  load_random_image (xgwa.screen, window, window);
-  cmap = xgwa.colormap;
   visual = xgwa.visual;
-  max_width = xgwa.width;
-  max_height = xgwa.height;
+  st->max_width = xgwa.width;
+  st->max_height = xgwa.height;
 
-  delay = get_integer_resource ("delay", "Integer");
-  delay2 = get_integer_resource ("delay2", "Integer");
-  grid_size = get_integer_resource ("gridSize", "Integer");
-  pix_inc = get_integer_resource ("pixelIncrement", "Integer");
-  border = get_integer_resource ("internalBorderWidth", "InternalBorderWidth");
+  st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+  st->delay2 = get_integer_resource (st->dpy, "delay2", "Integer");
+  st->grid_size = get_integer_resource (st->dpy, "gridSize", "Integer");
+  st->pix_inc = get_integer_resource (st->dpy, "pixelIncrement", "Integer");
+
+  /* Don't let the grid be smaller than 5x5 */
+  while (st->grid_size > xgwa.width / 5)
+    st->grid_size /= 2;
+  while (st->grid_size > xgwa.height / 5)
+    st->grid_size /= 2;
+
+  if (st->delay < 0) st->delay = 0;
+  if (st->delay2 < 0) st->delay2 = 0;
+  if (st->pix_inc < 1) st->pix_inc = 1;
+  if (st->grid_size < 1) st->grid_size = 1;
 
-  /* Don't let the grid be smaller than 3x3 */
-  if (grid_size > xgwa.width / 3)
-    grid_size = xgwa.width / 3;
-  if (grid_size > xgwa.height / 3)
-    grid_size = xgwa.height / 3;
 
   {
     XColor fgc, bgc;
-    char *fgs = get_string_resource("background", "Background");
-    char *bgs = get_string_resource("foreground", "Foreground");
+    char *fgs = get_string_resource(st->dpy, "background", "Background");
+    char *bgs = get_string_resource(st->dpy, "foreground", "Foreground");
     Bool fg_ok, bg_ok;
-    if (!XParseColor (dpy, cmap, fgs, &fgc))
-      XParseColor (dpy, cmap, "black", &bgc);
-    if (!XParseColor (dpy, cmap, bgs, &bgc))
-      XParseColor (dpy, cmap, "gray", &fgc);
+    if (!XParseColor (st->dpy, xgwa.colormap, fgs, &fgc))
+      XParseColor (st->dpy, xgwa.colormap, "black", &bgc);
+    if (!XParseColor (st->dpy, xgwa.colormap, bgs, &bgc))
+      XParseColor (st->dpy, xgwa.colormap, "gray", &fgc);
 
-    fg_ok = XAllocColor (dpy, cmap, &fgc);
-    bg_ok = XAllocColor (dpy, cmap, &bgc);
+    fg_ok = XAllocColor (st->dpy, xgwa.colormap, &fgc);
+    bg_ok = XAllocColor (st->dpy, xgwa.colormap, &bgc);
 
     /* If we weren't able to allocate the two colors we want from the
        colormap (which is likely if the screen has been grabbed on an
@@ -74,31 +96,33 @@ init_slide (Display *dpy, Window window)
        pixels without actually allocating them.
      */
     if (fg_ok)
-      fg = fgc.pixel;
+      st->fg = fgc.pixel;
     else
-      fg = 0;
+      st->fg = 0;
 
     if (bg_ok)
-      bg = bgc.pixel;
+      st->bg = bgc.pixel;
     else
-      bg = 1;
+      st->bg = 1;
 
+#ifndef HAVE_COCOA
     if (!fg_ok || bg_ok)
       {
+        int i;
        unsigned long fgd = ~0;
        unsigned long bgd = ~0;
-       int max = visual_cells (xgwa.screen, visual);
+       int max = visual_cells (xgwa.screen, xgwa.visual);
        XColor *all = (XColor *) calloc(sizeof (*all), max);
        for (i = 0; i < max; i++)
          {
            all[i].flags = DoRed|DoGreen|DoBlue;
            all[i].pixel = i;
          }
-       XQueryColors (dpy, cmap, all, max);
+       XQueryColors (st->dpy, xgwa.colormap, all, max);
        for(i = 0; i < max; i++)
          {
            long rd, gd, bd;
-           unsigned long d;
+           unsigned long dd;
            if (!fg_ok)
              {
                rd = (all[i].red   >> 8) - (fgc.red   >> 8);
@@ -107,12 +131,12 @@ init_slide (Display *dpy, Window window)
                if (rd < 0) rd = -rd;
                if (gd < 0) gd = -gd;
                if (bd < 0) bd = -bd;
-               d = (rd << 1) + (gd << 2) + bd;
-               if (d < fgd)
+               dd = (rd << 1) + (gd << 2) + bd;
+               if (dd < fgd)
                  {
-                   fgd = d;
-                   fg = all[i].pixel;
-                   if (d == 0)
+                   fgd = dd;
+                   st->fg = all[i].pixel;
+                   if (dd == 0)
                      fg_ok = True;
                  }
              }
@@ -125,12 +149,12 @@ init_slide (Display *dpy, Window window)
                if (rd < 0) rd = -rd;
                if (gd < 0) gd = -gd;
                if (bd < 0) bd = -bd;
-               d = (rd << 1) + (gd << 2) + bd;
-               if (d < bgd)
+               dd = (rd << 1) + (gd << 2) + bd;
+               if (dd < bgd)
                  {
-                   bgd = d;
-                   bg = all[i].pixel;
-                   if (d == 0)
+                   bgd = dd;
+                   st->bg = all[i].pixel;
+                   if (dd == 0)
                      bg_ok = True;
                  }
              }
@@ -140,195 +164,270 @@ init_slide (Display *dpy, Window window)
          }
        XFree(all);
       }
+#endif /* !HAVE_COCOA */
   }
 
-
-  if (delay < 0) delay = 0;
-  if (delay2 < 0) delay2 = 0;
-  if (pix_inc < 1) pix_inc = 1;
-  if (grid_size < 1) grid_size = 1;
-
-  gcv.foreground = fg;
+  gcv.foreground = st->fg;
   gcv.function = GXcopy;
   gcv.subwindow_mode = IncludeInferiors;
   gcflags = GCForeground |GCFunction;
-  if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
+  if (use_subwindow_mode_p(xgwa.screen, st->window)) /* see grabscreen.c */
     gcflags |= GCSubwindowMode;
-  gc = XCreateGC (dpy, window, gcflags, &gcv);
+  st->gc = XCreateGC (st->dpy, st->window, gcflags, &gcv);
+
+  return st;
+}
+
+static void
+draw_grid (struct state *st)
+{
+  int i;
+  Drawable d;
+  int border;
+  XWindowAttributes xgwa;
+
+  XGetWindowAttributes (st->dpy, st->window, &xgwa);
+
+  border = get_integer_resource (st->dpy, "internalBorderWidth",
+                                 "InternalBorderWidth");
 
-  XGetWindowAttributes (dpy, window, &xgwa);
-  bitmap_w = xgwa.width;
-  bitmap_h = xgwa.height;
+  XGetWindowAttributes (st->dpy, st->window, &xgwa);
+  st->bitmap_w = xgwa.width;
+  st->bitmap_h = xgwa.height;
 
-  grid_w = bitmap_w / grid_size;
-  grid_h = bitmap_h / grid_size;
-  hole_x = random () % grid_w;
-  hole_y = random () % grid_h;
-  xoff = (bitmap_w - (grid_w * grid_size)) / 2;
-  yoff = (bitmap_h - (grid_h * grid_size)) / 2;
+  st->grid_w = st->bitmap_w / st->grid_size;
+  st->grid_h = st->bitmap_h / st->grid_size;
+  st->hole_x = random () % st->grid_w;
+  st->hole_y = random () % st->grid_h;
+  st->xoff = (st->bitmap_w - (st->grid_w * st->grid_size)) / 2;
+  st->yoff = (st->bitmap_h - (st->grid_h * st->grid_size)) / 2;
 
-  d = window;
+  d = st->window;
+
+  st->early_i = -10;
+  st->draw_last = -1;
 
   if (border)
     {
       int half = border/2;
       int half2 = (border & 1 ? half+1 : half);
-      XSetForeground(dpy, gc, bg);
-      for (i = 0; i < bitmap_w; i += grid_size)
+      XSetForeground(st->dpy, st->gc, st->bg);
+      for (i = 0; i < st->bitmap_w; i += st->grid_size)
        {
          int j;
-         for (j = 0; j < bitmap_h; j += grid_size)
-           XDrawRectangle (dpy, d, gc,
-                           xoff+i+half2, yoff+j+half2,
-                           grid_size-border-1, grid_size-border-1);
+         for (j = 0; j < st->bitmap_h; j += st->grid_size)
+           XDrawRectangle (st->dpy, d, st->gc,
+                           st->xoff+i+half2, st->yoff+j+half2,
+                           st->grid_size-border-1, st->grid_size-border-1);
        }
 
-      XSetForeground(dpy, gc, fg);
-      for (i = 0; i <= bitmap_w; i += grid_size)
-       XFillRectangle (dpy, d, gc, xoff+i-half, yoff, border, bitmap_h);
-      for (i = 0; i <= bitmap_h; i += grid_size)
-       XFillRectangle (dpy, d, gc, xoff, yoff+i-half, bitmap_w, border);
+      XSetForeground(st->dpy, st->gc, st->fg);
+      for (i = 0; i <= st->bitmap_w; i += st->grid_size)
+       XFillRectangle (st->dpy, d, st->gc, st->xoff+i-half, st->yoff, border, st->bitmap_h);
+      for (i = 0; i <= st->bitmap_h; i += st->grid_size)
+       XFillRectangle (st->dpy, d, st->gc, st->xoff, st->yoff+i-half, st->bitmap_w, border);
     }
 
-  if (xoff)
+  if (st->xoff)
+    {
+      XFillRectangle (st->dpy, d, st->gc, 0, 0, st->xoff, st->bitmap_h);
+      XFillRectangle (st->dpy, d, st->gc, st->bitmap_w - st->xoff, 0, st->xoff, st->bitmap_h);
+    }
+  if (st->yoff)
     {
-      XFillRectangle (dpy, d, gc, 0, 0, xoff, bitmap_h);
-      XFillRectangle (dpy, d, gc, bitmap_w - xoff, 0, xoff, bitmap_h);
+      XFillRectangle (st->dpy, d, st->gc, 0, 0, st->bitmap_w, st->yoff);
+      XFillRectangle (st->dpy, d, st->gc, 0, st->bitmap_h - st->yoff, st->bitmap_w, st->yoff);
     }
-  if (yoff)
+}
+
+
+static int
+slidescreen_draw_early (struct state *st)
+{
+  while (st->early_i < 0)
     {
-      XFillRectangle (dpy, d, gc, 0, 0, bitmap_w, yoff);
-      XFillRectangle (dpy, d, gc, 0, bitmap_h - yoff, bitmap_w, yoff);
+      st->early_i++;
+      return 1;
     }
 
-  XSync (dpy, False);
-  if (delay2) usleep (delay2 * 2);
- for (i = 0; i < grid_size; i += pix_inc)
+  /* for (early_i = 0; early_i < grid_size; early_i += pix_inc) */
    {
      XPoint points [3];
-     points[0].x = xoff + grid_size * hole_x;
-     points[0].y = yoff + grid_size * hole_y;
-     points[1].x = points[0].x + grid_size;
+     points[0].x = st->xoff + st->grid_size * st->hole_x;
+     points[0].y = st->yoff + st->grid_size * st->hole_y;
+     points[1].x = points[0].x + st->grid_size;
      points[1].y = points[0].y;
      points[2].x = points[0].x;
-     points[2].y = points[0].y + i;
-     XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+     points[2].y = points[0].y + st->early_i;
+     XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin);
 
      points[1].x = points[0].x;
-     points[1].y = points[0].y + grid_size;
-     points[2].x = points[0].x + i;
-     points[2].y = points[0].y + grid_size;
-     XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+     points[1].y = points[0].y + st->grid_size;
+     points[2].x = points[0].x + st->early_i;
+     points[2].y = points[0].y + st->grid_size;
+     XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin);
 
-     points[0].x = points[1].x + grid_size;
+     points[0].x = points[1].x + st->grid_size;
      points[0].y = points[1].y;
      points[2].x = points[0].x;
-     points[2].y = points[0].y - i;
-     XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
+     points[2].y = points[0].y - st->early_i;
+     XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin);
 
      points[1].x = points[0].x;
-     points[1].y = points[0].y - grid_size;
-     points[2].x = points[1].x - i;
+     points[1].y = points[0].y - st->grid_size;
+     points[2].x = points[1].x - st->early_i;
      points[2].y = points[1].y;
-     XFillPolygon (dpy, window, gc, points, 3, Convex, CoordModeOrigin);
-
-     XSync (dpy, False);
-     if (delay) usleep (delay);
+     XFillPolygon (st->dpy, st->window, st->gc, points, 3, Convex, CoordModeOrigin);
    }
 
-  XFillRectangle (dpy, window, gc,
-                 xoff + grid_size * hole_x,
-                 yoff + grid_size * hole_y,
-                 grid_size, grid_size);
+   st->early_i += st->pix_inc;
+   if (st->early_i < st->grid_size)
+     return 1;
+
+   XFillRectangle (st->dpy, st->window, st->gc,
+                   st->xoff + st->grid_size * st->hole_x,
+                   st->yoff + st->grid_size * st->hole_y,
+                   st->grid_size, st->grid_size);
+   return 0;
 }
 
-static void
-slide1 (Display *dpy, Window window)
+
+static unsigned long
+slidescreen_draw (Display *dpy, Window window, void *closure)
 {
+  struct state *st = (struct state *) closure;
+  int this_delay = st->delay;
+
   /* this code is a total kludge, but who cares, it works... */
- int i, x, y, ix, iy, dx, dy, dir, w, h, size, inc;
- static int last = -1;
- do {
-   dir = random () % 4;
-   switch (dir)
-     {
-     case 0: dx = 0,  dy = 1;  break;
-     case 1: dx = -1, dy = 0;  break;
-     case 2: dx = 0,  dy = -1; break;
-     case 3: dx = 1,  dy = 0;  break;
-     default: abort ();
-     }
- } while (dir == last ||
-         hole_x + dx < 0 || hole_x + dx >= grid_w ||
-         hole_y + dy < 0 || hole_y + dy >= grid_h);
- if (grid_w > 1 && grid_h > 1)
-   last = (dir == 0 ? 2 : dir == 2 ? 0 : dir == 1 ? 3 : 1);
 
- switch (dir)
+  if (st->img_loader)   /* still loading */
+    {
+      st->img_loader = load_image_async_simple (st->img_loader, 0, 0, 0, 0, 0);
+      if (! st->img_loader)  /* just finished */
+        draw_grid (st);
+      return st->delay;
+    }
+
+  if (! st->draw_initted)
+    {
+      if (!slidescreen_draw_early (st))
+        {
+          st->draw_initted = 1;
+          return st->delay2;
+        }
+      else
+        return st->delay;
+    }
+
+ if (st->draw_i == 0)
    {
-   case 0: size = 1 + (random()%(grid_h - hole_y - 1)); h = size; w = 1; break;
-   case 1: size = 1 + (random()%hole_x);               w = size; h = 1; break;
-   case 2: size = 1 + (random()%hole_y);               h = size; w = 1; break;
-   case 3: size = 1 + (random()%(grid_w - hole_x - 1)); w = size; h = 1; break;
-   default: abort ();
-   }
+     if (st->draw_last == -1) st->draw_last = random () % 2;
+
+     /* alternate between horizontal and vertical slides */
+     /* note that draw_dir specifies the direction the _hole_ moves, not the tiles */
+     if (st->draw_last == VERTICAL) {
+       if (((st->grid_w > 1) ? st->draw_rnd = random () % (st->grid_w - 1) : 0)
+          < st->hole_x) {
+         st->draw_dx = -1; st->draw_dir = LEFT;  st->hole_x -= st->draw_rnd;
+       } else {
+         st->draw_dx =  1; st->draw_dir = RIGHT; st->draw_rnd -= st->hole_x;
+       }
+       st->draw_dy = 0; st->draw_w = st->draw_size = st->draw_rnd + 1; st->draw_h = 1;
+       st->draw_last = HORIZONTAL;
+     } else {
+       if (((st->grid_h > 1) ? st->draw_rnd = random () % (st->grid_h - 1) : 0)
+          < st->hole_y) {
+         st->draw_dy = -1; st->draw_dir = UP;    st->hole_y -= st->draw_rnd;
+       } else {
+         st->draw_dy =  1; st->draw_dir = DOWN;  st->draw_rnd -= st->hole_y;
+       }
+       st->draw_dx = 0; st->draw_h = st->draw_size = st->draw_rnd + 1; st->draw_w = 1;
+       st->draw_last = VERTICAL;
+     }
+     st->draw_ix = st->draw_x = st->xoff + (st->hole_x + st->draw_dx) * st->grid_size;
+     st->draw_iy = st->draw_y = st->yoff + (st->hole_y + st->draw_dy) * st->grid_size;
+     st->draw_inc = st->pix_inc;
 
- if (dx == -1) hole_x -= (size - 1);
- else if (dy == -1) hole_y -= (size - 1);
+   }
 
- ix = x = xoff + (hole_x + dx) * grid_size;
- iy = y = yoff + (hole_y + dy) * grid_size;
- inc = pix_inc;
- for (i = 0; i < grid_size; i += inc)
+ /* for (draw_i = 0; draw_i < grid_size; draw_i += draw_inc) */
    {
      int fx, fy, tox, toy;
-     if (inc + i > grid_size)
-       inc = grid_size - i;
-     tox = x - dx * inc;
-     toy = y - dy * inc;
+     if (st->draw_inc + st->draw_i > st->grid_size)
+       st->draw_inc = st->grid_size - st->draw_i;
+     tox = st->draw_x - st->draw_dx * st->draw_inc;
+     toy = st->draw_y - st->draw_dy * st->draw_inc;
 
-     fx = (x < 0 ? 0 : x > max_width  ? max_width  : x);
-     fy = (y < 0 ? 0 : y > max_height ? max_height : y);
-     tox = (tox < 0 ? 0 : tox > max_width  ? max_width  : tox);
-     toy = (toy < 0 ? 0 : toy > max_height ? max_height : toy);
+     fx = (st->draw_x < 0 ? 0 : st->draw_x > st->max_width  ? st->max_width  : st->draw_x);
+     fy = (st->draw_y < 0 ? 0 : st->draw_y > st->max_height ? st->max_height : st->draw_y);
+     tox = (tox < 0 ? 0 : tox > st->max_width  ? st->max_width  : tox);
+     toy = (toy < 0 ? 0 : toy > st->max_height ? st->max_height : toy);
 
-     XCopyArea (dpy, window, window, gc,
+     XCopyArea (st->dpy, st->window, st->window, st->gc,
                fx, fy,
-               grid_size * w, grid_size * h,
+               st->grid_size * st->draw_w, st->grid_size * st->draw_h,
                tox, toy);
 
-     x -= dx * inc;
-     y -= dy * inc;
-     switch (dir)
+     st->draw_x -= st->draw_dx * st->draw_inc;
+     st->draw_y -= st->draw_dy * st->draw_inc;
+     switch (st->draw_dir)
        {
-       case 0: XFillRectangle (dpy, window, gc,
-                              ix, y + grid_size * h, grid_size * w, iy - y);
+       case DOWN: XFillRectangle (st->dpy, st->window, st->gc,
+                              st->draw_ix, st->draw_y + st->grid_size * st->draw_h, st->grid_size * st->draw_w, st->draw_iy - st->draw_y);
         break;
-       case 1: XFillRectangle (dpy, window, gc, ix, iy, x - ix, grid_size * h);
+       case LEFT: XFillRectangle (st->dpy, st->window, st->gc, st->draw_ix, st->draw_iy, st->draw_x - st->draw_ix, st->grid_size * st->draw_h);
         break;
-       case 2: XFillRectangle (dpy, window, gc, ix, iy, grid_size * w, y - iy);
+       case UP: XFillRectangle (st->dpy, st->window, st->gc, st->draw_ix, st->draw_iy, st->grid_size * st->draw_w, st->draw_y - st->draw_iy);
         break;
-       case 3: XFillRectangle (dpy, window, gc,
-                              x + grid_size * w, iy, ix - x, grid_size * h);
+       case RIGHT: XFillRectangle (st->dpy, st->window, st->gc,
+                              st->draw_x + st->grid_size * st->draw_w, st->draw_iy, st->draw_ix - st->draw_x, st->grid_size * st->draw_h);
         break;
        }
-
-     XSync (dpy, False);
-     if (delay) usleep (delay);
-   }
- switch (dir)
-   {
-   case 0: hole_y += size; break;
-   case 1: hole_x--; break;
-   case 2: hole_y--; break;
-   case 3: hole_x += size; break;
    }
+
+   st->draw_i += st->draw_inc;
+   if (st->draw_i >= st->grid_size)
+     {
+       st->draw_i = 0;
+
+       switch (st->draw_dir)
+         {
+         case DOWN: st->hole_y += st->draw_size; break;
+         case LEFT: st->hole_x--; break;
+         case UP: st->hole_y--; break;
+         case RIGHT: st->hole_x += st->draw_size; break;
+         }
+
+       this_delay = st->delay2;
+     }
+
+   return this_delay;
+}
+
+static void
+slidescreen_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
+}
+
+static Bool
+slidescreen_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  return False;
+}
+
+static void
+slidescreen_free (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  XFreeGC (dpy, st->gc);
+  free (st);
 }
 
 \f
-char *progclass = "SlidePuzzle";
 
-char *defaults [] = {
+static const char *slidescreen_defaults [] = {
   "*dontClearRoot:             True",
 
 #ifdef __sgi   /* really, HAVE_READ_DISPLAY_EXTENSION */
@@ -336,7 +435,7 @@ char *defaults [] = {
 #endif
 
   ".background:                        Black",
-  ".foreground:                        Gray",
+  ".foreground:                        #BEBEBE",
   "*gridSize:                  70",
   "*pixelIncrement:            10",
   "*internalBorderWidth:       4",
@@ -345,7 +444,7 @@ char *defaults [] = {
   0
 };
 
-XrmOptionDescRec options [] = {
+static XrmOptionDescRec slidescreen_options [] = {
   { "-grid-size",      ".gridSize",            XrmoptionSepArg, 0 },
   { "-ibw",            ".internalBorderWidth", XrmoptionSepArg, 0 },
   { "-increment",      ".pixelIncrement",      XrmoptionSepArg, 0 },
@@ -354,14 +453,4 @@ XrmOptionDescRec options [] = {
   { 0, 0, 0, 0 }
 };
 
-void
-screenhack (Display *dpy, Window window)
-{
-  init_slide (dpy, window);
-  while (1)
-    {
-      slide1 (dpy, window);
-      screenhack_handle_events (dpy);
-      if (delay2) usleep (delay2);
-    }
-}
+XSCREENSAVER_MODULE ("Slidescreen", slidescreen)