-/* Copyright (c) 2003 Levi Burton <ldb@scoundrelz.net>
+/* Copyright (c) 2003 Levi Burton <donburton@sbcglobal.net>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
int color;
} square;
-void
+static void
randomize_square_colors(square *squares, int nsquares, int ncolors)
{
int i;
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, subdivisionx, subdivisiony, 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 }
-};
+static void
+popsquares_reshape (Display *dpy, Window window, void *closure,
+ unsigned int w, unsigned int h)
+{
+ struct state *st = (struct state *) closure;
+ int s = get_integer_resource(st->dpy, "subdivision", "Integer");
+ int x, y;
+ XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
+
+ if (st->xgwa.width < 100 || st->xgwa.height < 100) /* tiny window */
+ {
+ int ss = (st->xgwa.width < st->xgwa.height
+ ? st->xgwa.width : st->xgwa.height);
+ s = ss / 15;
+ if (s < 1) s = 1;
+ }
+
+ if (st->xgwa.width > st->xgwa.height * 5 || /* weird aspect ratio */
+ st->xgwa.height > st->xgwa.width * 5)
+ {
+ double r = st->xgwa.width / (double) st->xgwa.height;
+ if (r > 1)
+ {
+ st->subdivisiony = s;
+ st->subdivisionx = s * r;
+ }
+ else
+ {
+ st->subdivisionx = s;
+ st->subdivisiony = s / r;
+ }
+ }
+ else
+ {
+ st->subdivisionx = st->subdivisiony = s;
+ }
+
+ st->sw = st->xgwa.width / st->subdivisionx;
+ st->sh = st->xgwa.height / st->subdivisiony;
+ st->gw = st->sw ? st->xgwa.width / st->sw : 0;
+ st->gh = st->sh ? st->xgwa.height / st->sh : 0;
+ st->nsquares = st->gw * st->gh;
+ free (st->squares);
+ if (st->nsquares < 1) st->nsquares = 1;
+ st->squares = (square *) calloc (st->nsquares, sizeof(square));
+
+ for (y = 0; y < st->gh; y++)
+ for (x = 0; x < st->gw; x++)
+ {
+ 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;
+ }
-void
-screenhack (Display *dpy, Window window)
+ randomize_square_colors(st->squares, st->nsquares, st->ncolors);
+
+ if (st->dbuf) {
+ XFreePixmap (dpy, st->ba);
+ XFreePixmap (dpy, st->bb);
+ 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;
+ }
+}
+
+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;
- fg.pixel = get_pixel_resource ("foreground", "Foreground", dpy, xgwa.colormap);
- bg.pixel = get_pixel_resource ("background", "Background", dpy, xgwa.colormap);
+ st->delay = get_integer_resource (st->dpy, "delay", "Integer");
+ st->subdivisionx = get_integer_resource(st->dpy, "subdivision", "Integer");
+ st->subdivisiony = st->subdivisionx;
+ 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");
- XQueryColor (dpy, xgwa.colormap, &fg);
- XQueryColor (dpy, xgwa.colormap, &bg);
+# ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */
+ st->dbuf = False;
+# endif
- sw = xgwa.width / subdivision;
- sh = xgwa.height / subdivision;
- gw = xgwa.width / sw;
- gh = xgwa.height / sh;
- nsquares = gw * gh;
+ XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
- gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
+ fg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "foreground", "Foreground");
+ bg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "background", "Background");
- colors = (XColor *) calloc (ncolors, sizeof(XColor));
- squares = (square *) calloc (nsquares, sizeof(square));
+ XQueryColor (st->dpy, st->xgwa.colormap, &fg);
+ XQueryColor (st->dpy, st->xgwa.colormap, &bg);
+
+ st->sw = st->xgwa.width / st->subdivisionx;
+ st->sh = st->xgwa.height / st->subdivisiony;
+ st->gw = st->sw ? st->xgwa.width / st->sw : 0;
+ st->gh = st->sh ? st->xgwa.height / st->sh : 0;
+ st->nsquares = st->gw * st->gh;
+ if (st->nsquares < 1) st->nsquares = 1;
+ if (st->ncolors < 1) st->ncolors = 1;
+
+ 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->xgwa.screen, st->xgwa.visual, 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++)
+ popsquares_reshape (dpy, window, st, st->xgwa.width, st->xgwa.height);
+
+ 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 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 */
+#ifdef HAVE_MOBILE
+ "*ignoreRotation: True",
+#endif
+ 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)