http://slackware.bholcomb.com/slackware/slackware-11.0/source/xap/xscreensaver/xscree...
[xscreensaver] / hacks / popsquares.c
index 8c5a767c018f6ac21de5dae3a065ecc7bca59df0..6c26165f6dc4cc6fdad76194c421b8d4e225c9fa 100644 (file)
@@ -21,7 +21,7 @@ typedef struct _square {
   int color;
 } square;
 
-void
+static void
 randomize_square_colors(square *squares, int nsquares, int ncolors)
 {
   int i;
@@ -30,166 +30,208 @@ randomize_square_colors(square *squares, int nsquares, int ncolors)
     s[i].color = random() % ncolors;
 }
 
-\f
-char *progclass = "popsquares";
 
-char *defaults [] = {
-  ".background: blue",
-  ".foreground: blue4",
-  "*delay: 25000",
-  "*subdivision:  5",
-  "*border: 1",
-  "*ncolors: 128",
-  "*twitch: False",
-  "*doubleBuffer: False",
+struct state {
+  Display *dpy;
+  Window window;
+
+   int delay, subdivision, border, ncolors, twitch, dbuf;
+    XWindowAttributes xgwa;
+    GC gc; 
+    XColor *colors;
+    int sw, sh, gw, gh, nsquares;
+    square *squares;
+    Pixmap b, ba, bb;
 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
-  "*useDBE: True",
-  "*useDBEClear: True",
+    XdbeBackBuffer backb;
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
-  0
-};
-
-XrmOptionDescRec options [] = {
-  { "-fg", ".foreground", XrmoptionSepArg, 0},
-  { "-bg", ".background", XrmoptionSepArg, 0},
-  { "-delay",     ".delay", XrmoptionSepArg, 0 },
-  { "-subdivision", ".subdivision", XrmoptionSepArg, 0 },
-  { "-border", ".border", XrmoptionSepArg, 0},
-  { "-ncolors",   ".ncolors", XrmoptionSepArg, 0 },
-  { "-twitch",    ".twitch", XrmoptionNoArg, "True" },
-  { "-no-twitch", ".twitch", XrmoptionNoArg, "False" },
-  { "-db",        ".doubleBuffer", XrmoptionNoArg, "True" },
-  { "-no-db",     ".doubleBuffer", XrmoptionNoArg, "False" },
-  { 0, 0, 0, 0 }
 };
 
-void 
-screenhack (Display *dpy, Window window)
+static void *
+popsquares_init (Display *dpy, Window window)
 {
-  int delay = get_integer_resource ("delay", "Integer");
-  int subdivision = get_integer_resource("subdivision", "Integer");
-  int border = get_integer_resource("border", "Integer");
-  int ncolors = get_integer_resource("ncolors", "Integer");
-  Bool twitch = get_boolean_resource("twitch", "Boolean");
-  Bool dbuf = get_boolean_resource("doubleBuffer", "Boolean");
+  struct state *st = (struct state *) calloc (1, sizeof(*st));
   int x, y;
-  int sw, sh, gw, gh, nsquares = 0;
   double s1, v1, s2, v2 = 0;
   int h1, h2 = 0;
   /* Not sure how to use DBEClear */
-  /* Bool dbeclear_p = get_boolean_resource("useDBEClear", "Boolean"); */
-  XColor *colors = 0;
+  /* Bool dbeclear_p = get_boolean_resource(dpy, "useDBEClear", "Boolean"); */
   XColor fg, bg;
   XGCValues gcv;
-  GC gc; 
-  square *squares;
-  XWindowAttributes xgwa;
-  Pixmap b=0, ba=0, bb=0;
-#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
-  XdbeBackBuffer backb = 0;
-#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
   
-  XGetWindowAttributes (dpy, window, &xgwa);
+  st->dpy = dpy;
+  st->window = window;
+
+  st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+  st->subdivision = get_integer_resource(st->dpy, "subdivision", "Integer");
+  st->border = get_integer_resource(st->dpy, "border", "Integer");
+  st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer");
+  st->twitch = get_boolean_resource(st->dpy, "twitch", "Boolean");
+  st->dbuf = get_boolean_resource(st->dpy, "doubleBuffer", "Boolean");
+
+# ifdef HAVE_COCOA     /* Don't second-guess Quartz's double-buffering */
+  st->dbuf = False;
+# endif
 
-  fg.pixel = get_pixel_resource ("foreground", "Foreground", dpy, xgwa.colormap);
-  bg.pixel = get_pixel_resource ("background", "Background", dpy, xgwa.colormap);
+  XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
 
-  XQueryColor (dpy, xgwa.colormap, &fg);
-  XQueryColor (dpy, xgwa.colormap, &bg);
+  fg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "foreground", "Foreground");
+  bg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "background", "Background");
 
-  sw = xgwa.width / subdivision;
-  sh = xgwa.height / subdivision;
-  gw = xgwa.width / sw;
-  gh = xgwa.height / sh;
-  nsquares = gw * gh;
+  XQueryColor (st->dpy, st->xgwa.colormap, &fg);
+  XQueryColor (st->dpy, st->xgwa.colormap, &bg);
 
-  gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+  st->sw = st->xgwa.width / st->subdivision;
+  st->sh = st->xgwa.height / st->subdivision;
+  st->gw = st->xgwa.width / st->sw;
+  st->gh = st->xgwa.height / st->sh;
+  st->nsquares = st->gw * st->gh;
 
-  colors = (XColor *) calloc (ncolors, sizeof(XColor));
-  squares = (square *) calloc (nsquares, sizeof(square));
+  gcv.foreground = fg.pixel;
+  gcv.background = bg.pixel;
+  st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
+
+  st->colors = (XColor *) calloc (st->ncolors, sizeof(XColor));
+  st->squares = (square *) calloc (st->nsquares, sizeof(square));
 
   rgb_to_hsv (fg.red, fg.green, fg.blue, &h1, &s1, &v1);
   rgb_to_hsv (bg.red, bg.green, bg.blue, &h2, &s2, &v2);
-  make_color_ramp (dpy, xgwa.colormap,
+  make_color_ramp (st->dpy, st->xgwa.colormap,
                    h1, s1, v1,
                    h2, s2, v2,
-                   colors, &ncolors,  /* would this be considered a value-result argument? */
+                   st->colors, &st->ncolors,  /* would this be considered a value-result argument? */
                    True, True, False);
-  if (ncolors < 2)
+  if (st->ncolors < 2)
     {
       fprintf (stderr, "%s: insufficient colors!\n", progname);
       exit (1);
     }
 
-  for (y = 0; y < gh; y++)
-    for (x = 0; x < gw; x++) 
+  for (y = 0; y < st->gh; y++)
+    for (x = 0; x < st->gw; x++) 
       {
-        square *s = (square *) &squares[gw * y + x];
-        s->w = sw;
-        s->h = sh;
-        s->x = x * sw;
-        s->y = y * sh;
+        square *s = (square *) &st->squares[st->gw * y + x];
+        s->w = st->sw;
+        s->h = st->sh;
+        s->x = x * st->sw;
+        s->y = y * st->sh;
       }
 
-  randomize_square_colors(squares, nsquares, ncolors);
+  randomize_square_colors(st->squares, st->nsquares, st->ncolors);
 
-  if (dbuf)
+  if (st->dbuf)
     {
 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
-      b = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
-      backb = b;
+      st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
+      st->backb = st->b;
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
-      if (!b)                      
+      if (!st->b)                      
         {
-          ba = XCreatePixmap (dpy, window, xgwa.width, xgwa.height, xgwa.depth);
-          bb = XCreatePixmap (dpy, window, xgwa.width, xgwa.height, xgwa.depth);
-          b = ba;
+          st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+          st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
+          st->b = st->ba;
         }
     }
   else 
     {
-      b = window;
+      st->b = st->window;
     }
 
-  while (1) 
-    {
-      for (y = 0; y < gh; y++)
-        for (x = 0; x < gw; x++) 
+  return st;
+}
+
+static unsigned long
+popsquares_draw (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  int x, y;
+  for (y = 0; y < st->gh; y++)
+    for (x = 0; x < st->gw; x++) 
+      {
+        square *s = (square *) &st->squares[st->gw * y + x];
+        XSetForeground (st->dpy, st->gc, st->colors[s->color].pixel);
+        XFillRectangle (st->dpy, st->b, st->gc, s->x, s->y, 
+                        st->border ? s->w - st->border : s->w, 
+                        st->border ? s->h - st->border : s->h);
+        s->color++;
+        if (s->color == st->ncolors)
           {
-            square *s = (square *) &squares[gw * y + x];
-            XSetForeground (dpy, gc, colors[s->color].pixel);
-            XFillRectangle (dpy, b, gc, s->x, s->y, 
-                            border ? s->w - border : s->w, 
-                            border ? s->h - border : s->h);
-            s->color++;
-            if (s->color == ncolors)
-              {
-                if (twitch && ((random() % 4) == 0))
-                  randomize_square_colors (squares, nsquares, ncolors);
-                else
-                  s->color = random() % ncolors;
-              }
+            if (st->twitch && ((random() % 4) == 0))
+              randomize_square_colors (st->squares, st->nsquares, st->ncolors);
+            else
+              s->color = random() % st->ncolors;
           }
+      }
 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
-      if (backb) 
-        {
-          XdbeSwapInfo info[1];
-          info[0].swap_window = window;
-          info[0].swap_action = XdbeUndefined;
-          XdbeSwapBuffers (dpy, info, 1);
-        }
-      else
+  if (st->backb) 
+    {
+      XdbeSwapInfo info[1];
+      info[0].swap_window = st->window;
+      info[0].swap_action = XdbeUndefined;
+      XdbeSwapBuffers (st->dpy, info, 1);
+    }
+  else
 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
-        if (dbuf)
-          {
-            XCopyArea (dpy, b, window, gc, 0, 0, 
-                       xgwa.width, xgwa.height, 0, 0);
-            b = (b == ba ? bb : ba);
-          }
+    if (st->dbuf)
+      {
+        XCopyArea (st->dpy, st->b, st->window, st->gc, 0, 0, 
+                   st->xgwa.width, st->xgwa.height, 0, 0);
+        st->b = (st->b == st->ba ? st->bb : st->ba);
+      }
 
-      XSync (dpy, False);
-      screenhack_handle_events (dpy);
-      if (delay) 
-        usleep (delay);
-    }
+  return st->delay;
+}
+
+
+static void
+popsquares_reshape (Display *dpy, Window window, void *closure, 
+                 unsigned int w, unsigned int h)
+{
 }
+
+static Bool
+popsquares_event (Display *dpy, Window window, void *closure, XEvent *event)
+{
+  return False;
+}
+
+static void
+popsquares_free (Display *dpy, Window window, void *closure)
+{
+  struct state *st = (struct state *) closure;
+  free (st);
+}
+
+
+static const char *popsquares_defaults [] = {
+  ".background: #0000FF",
+  ".foreground: #00008B",
+  "*delay: 25000",
+  "*subdivision:  5",
+  "*border: 1",
+  "*ncolors: 128",
+  "*twitch: False",
+  "*doubleBuffer: False",
+#ifdef HAVE_DOUBLE_BUFFER_EXTENSION
+  "*useDBE: True",
+  "*useDBEClear: True",
+#endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
+  0
+};
+
+static XrmOptionDescRec popsquares_options [] = {
+  { "-fg", ".foreground", XrmoptionSepArg, 0},
+  { "-bg", ".background", XrmoptionSepArg, 0},
+  { "-delay",     ".delay", XrmoptionSepArg, 0 },
+  { "-subdivision", ".subdivision", XrmoptionSepArg, 0 },
+  { "-border", ".border", XrmoptionSepArg, 0},
+  { "-ncolors",   ".ncolors", XrmoptionSepArg, 0 },
+  { "-twitch",    ".twitch", XrmoptionNoArg, "True" },
+  { "-no-twitch", ".twitch", XrmoptionNoArg, "False" },
+  { "-db",        ".doubleBuffer", XrmoptionNoArg, "True" },
+  { "-no-db",     ".doubleBuffer", XrmoptionNoArg, "False" },
+  { 0, 0, 0, 0 }
+};
+
+
+XSCREENSAVER_MODULE ("PopSquares", popsquares)