1 /* Copyright (c) 2003 Levi Burton <donburton@sbcglobal.net>
3 * Permission to use, copy, modify, distribute, and sell this software and its
4 * documentation for any purpose is hereby granted without fee, provided that
5 * the above copyright notice appear in all copies and that both that
6 * copyright notice and this permission notice appear in supporting
7 * documentation. No representations are made about the suitability of this
8 * software for any purpose. It is provided "as is" without express or
12 #include "screenhack.h"
15 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
17 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
19 typedef struct _square {
25 randomize_square_colors(square *squares, int nsquares, int ncolors)
29 for (i = 0; i < nsquares; i++)
30 s[i].color = random() % ncolors;
38 int delay, subdivisionx, subdivisiony, border, ncolors, twitch, dbuf;
39 XWindowAttributes xgwa;
42 int sw, sh, gw, gh, nsquares;
45 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
47 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
51 popsquares_reshape (Display *dpy, Window window, void *closure,
52 unsigned int w, unsigned int h)
54 struct state *st = (struct state *) closure;
55 int s = get_integer_resource(st->dpy, "subdivision", "Integer");
57 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
59 if (st->xgwa.width < 100 || st->xgwa.height < 100) /* tiny window */
61 int ss = (st->xgwa.width < st->xgwa.height
62 ? st->xgwa.width : st->xgwa.height);
67 if (st->xgwa.width > st->xgwa.height * 5 || /* weird aspect ratio */
68 st->xgwa.height > st->xgwa.width * 5)
70 double r = st->xgwa.width / (double) st->xgwa.height;
74 st->subdivisionx = s * r;
79 st->subdivisiony = s / r;
84 st->subdivisionx = st->subdivisiony = s;
87 st->sw = st->xgwa.width / st->subdivisionx;
88 st->sh = st->xgwa.height / st->subdivisiony;
89 st->gw = st->sw ? st->xgwa.width / st->sw : 0;
90 st->gh = st->sh ? st->xgwa.height / st->sh : 0;
91 st->nsquares = st->gw * st->gh;
93 if (st->nsquares < 1) st->nsquares = 1;
94 st->squares = (square *) calloc (st->nsquares, sizeof(square));
96 for (y = 0; y < st->gh; y++)
97 for (x = 0; x < st->gw; x++)
99 square *s = (square *) &st->squares[st->gw * y + x];
106 randomize_square_colors(st->squares, st->nsquares, st->ncolors);
109 XFreePixmap (dpy, st->ba);
110 XFreePixmap (dpy, st->bb);
111 st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
112 st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
118 popsquares_init (Display *dpy, Window window)
120 struct state *st = (struct state *) calloc (1, sizeof(*st));
122 double s1, v1, s2, v2 = 0;
124 /* Not sure how to use DBEClear */
125 /* Bool dbeclear_p = get_boolean_resource(dpy, "useDBEClear", "Boolean"); */
132 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
133 st->subdivisionx = get_integer_resource(st->dpy, "subdivision", "Integer");
134 st->subdivisiony = st->subdivisionx;
135 st->border = get_integer_resource(st->dpy, "border", "Integer");
136 st->ncolors = get_integer_resource(st->dpy, "ncolors", "Integer");
137 st->twitch = get_boolean_resource(st->dpy, "twitch", "Boolean");
138 st->dbuf = get_boolean_resource(st->dpy, "doubleBuffer", "Boolean");
140 # ifdef HAVE_JWXYZ /* Don't second-guess Quartz's double-buffering */
144 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
146 fg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "foreground", "Foreground");
147 bg.pixel = get_pixel_resource (st->dpy, st->xgwa.colormap, "background", "Background");
149 XQueryColor (st->dpy, st->xgwa.colormap, &fg);
150 XQueryColor (st->dpy, st->xgwa.colormap, &bg);
152 st->sw = st->xgwa.width / st->subdivisionx;
153 st->sh = st->xgwa.height / st->subdivisiony;
154 st->gw = st->sw ? st->xgwa.width / st->sw : 0;
155 st->gh = st->sh ? st->xgwa.height / st->sh : 0;
156 st->nsquares = st->gw * st->gh;
157 if (st->nsquares < 1) st->nsquares = 1;
158 if (st->ncolors < 1) st->ncolors = 1;
160 gcv.foreground = fg.pixel;
161 gcv.background = bg.pixel;
162 st->gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
164 st->colors = (XColor *) calloc (st->ncolors, sizeof(XColor));
165 st->squares = (square *) calloc (st->nsquares, sizeof(square));
167 rgb_to_hsv (fg.red, fg.green, fg.blue, &h1, &s1, &v1);
168 rgb_to_hsv (bg.red, bg.green, bg.blue, &h2, &s2, &v2);
169 make_color_ramp (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
172 st->colors, &st->ncolors, /* would this be considered a value-result argument? */
176 fprintf (stderr, "%s: insufficient colors!\n", progname);
180 for (y = 0; y < st->gh; y++)
181 for (x = 0; x < st->gw; x++)
183 square *s = (square *) &st->squares[st->gw * y + x];
190 randomize_square_colors(st->squares, st->nsquares, st->ncolors);
194 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
195 st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
197 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
200 st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
201 st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height, st->xgwa.depth);
210 popsquares_reshape (dpy, window, st, st->xgwa.width, st->xgwa.height);
216 popsquares_draw (Display *dpy, Window window, void *closure)
218 struct state *st = (struct state *) closure;
220 for (y = 0; y < st->gh; y++)
221 for (x = 0; x < st->gw; x++)
223 square *s = (square *) &st->squares[st->gw * y + x];
224 XSetForeground (st->dpy, st->gc, st->colors[s->color].pixel);
225 XFillRectangle (st->dpy, st->b, st->gc, s->x, s->y,
226 st->border ? s->w - st->border : s->w,
227 st->border ? s->h - st->border : s->h);
229 if (s->color == st->ncolors)
231 if (st->twitch && ((random() % 4) == 0))
232 randomize_square_colors (st->squares, st->nsquares, st->ncolors);
234 s->color = random() % st->ncolors;
237 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
240 XdbeSwapInfo info[1];
241 info[0].swap_window = st->window;
242 info[0].swap_action = XdbeUndefined;
243 XdbeSwapBuffers (st->dpy, info, 1);
246 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
249 XCopyArea (st->dpy, st->b, st->window, st->gc, 0, 0,
250 st->xgwa.width, st->xgwa.height, 0, 0);
251 st->b = (st->b == st->ba ? st->bb : st->ba);
259 popsquares_event (Display *dpy, Window window, void *closure, XEvent *event)
265 popsquares_free (Display *dpy, Window window, void *closure)
267 struct state *st = (struct state *) closure;
272 static const char *popsquares_defaults [] = {
273 ".background: #0000FF",
274 ".foreground: #00008B",
280 "*doubleBuffer: False",
281 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
283 "*useDBEClear: True",
284 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
286 "*ignoreRotation: True",
291 static XrmOptionDescRec popsquares_options [] = {
292 { "-fg", ".foreground", XrmoptionSepArg, 0},
293 { "-bg", ".background", XrmoptionSepArg, 0},
294 { "-delay", ".delay", XrmoptionSepArg, 0 },
295 { "-subdivision", ".subdivision", XrmoptionSepArg, 0 },
296 { "-border", ".border", XrmoptionSepArg, 0},
297 { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
298 { "-twitch", ".twitch", XrmoptionNoArg, "True" },
299 { "-no-twitch", ".twitch", XrmoptionNoArg, "False" },
300 { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
301 { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
306 XSCREENSAVER_MODULE ("PopSquares", popsquares)