1 /* xscreensaver, Copyright (c) 1999 Jamie Zawinski <jwz@jwz.org>
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
13 #include "screenhack.h"
16 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
18 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
20 #define countof(x) (sizeof(x)/sizeof(*(x)))
21 #define ABS(x) ((x)<0?-(x):(x))
23 static Bool transparent_p;
25 static unsigned long base_pixel, *plane_masks;
35 void (*draw) (Display *, Drawable, struct throbber *);
39 draw_star (Display *dpy, Drawable w, struct throbber *t)
44 int s = t->size / 0.383; /* trial and error, I forget how to derive this */
49 points[0].x = x + s * cos(o + 0.0*c); points[0].y = y + s * sin(o + 0.0*c);
50 points[1].x = x + s2 * cos(o + 0.1*c); points[1].y = y + s2 * sin(o + 0.1*c);
51 points[2].x = x + s * cos(o + 0.2*c); points[2].y = y + s * sin(o + 0.2*c);
52 points[3].x = x + s2 * cos(o + 0.3*c); points[3].y = y + s2 * sin(o + 0.3*c);
53 points[4].x = x + s * cos(o + 0.4*c); points[4].y = y + s * sin(o + 0.4*c);
54 points[5].x = x + s2 * cos(o + 0.5*c); points[5].y = y + s2 * sin(o + 0.5*c);
55 points[6].x = x + s * cos(o + 0.6*c); points[6].y = y + s * sin(o + 0.6*c);
56 points[7].x = x + s2 * cos(o + 0.7*c); points[7].y = y + s2 * sin(o + 0.7*c);
57 points[8].x = x + s * cos(o + 0.8*c); points[8].y = y + s * sin(o + 0.8*c);
58 points[9].x = x + s2 * cos(o + 0.9*c); points[9].y = y + s2 * sin(o + 0.9*c);
59 points[10] = points[0];
61 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
65 draw_circle (Display *dpy, Drawable w, struct throbber *t)
67 XDrawArc (dpy, w, t->gc,
75 draw_hlines (Display *dpy, Drawable w, struct throbber *t)
77 XDrawLine (dpy, w, t->gc, 0,
78 t->y - t->size, t->max_size,
80 XDrawLine (dpy, w, t->gc, 0,
81 t->y + t->size, t->max_size,
86 draw_vlines (Display *dpy, Drawable w, struct throbber *t)
88 XDrawLine (dpy, w, t->gc,
90 t->x - t->size, t->max_size);
91 XDrawLine (dpy, w, t->gc,
93 t->x + t->size, t->max_size);
97 draw_corners (Display *dpy, Drawable w, struct throbber *t)
99 int s = (t->size + t->thickness) / 2;
102 points[0].x = 0; points[0].y = t->y - s;
103 points[1].x = t->x - s; points[1].y = t->y - s;
104 points[2].x = t->x - s; points[2].y = 0;
105 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
107 points[0].x = 0; points[0].y = t->y + s;
108 points[1].x = t->x - s; points[1].y = t->y + s;
109 points[2].x = t->x - s; points[2].y = t->max_size;
110 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
112 points[0].x = t->x + s; points[0].y = 0;
113 points[1].x = t->x + s; points[1].y = t->y - s;
114 points[2].x = t->max_size; points[2].y = t->y - s;
115 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
117 points[0].x = t->x + s; points[0].y = t->max_size;
118 points[1].x = t->x + s; points[1].y = t->y + s;
119 points[2].x = t->max_size; points[2].y = t->y + s;
120 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
124 static struct throbber *
125 make_throbber (Display *dpy, Drawable d, int w, int h, unsigned long pixel)
129 struct throbber *t = (struct throbber *) malloc (sizeof (*t));
133 t->speed = get_integer_resource ("speed", "Speed");
134 t->fuse = 1 + (random() % 4);
135 t->thickness = get_integer_resource ("thickness", "Thickness");
137 if (t->speed < 0) t->speed = -t->speed;
138 t->speed += (((random() % t->speed) / 2) - (t->speed / 2));
139 if (t->speed > 0) t->speed = -t->speed;
142 t->size = t->max_size;
144 t->size = t->thickness, t->speed = -t->speed;
146 flags = GCForeground;
149 gcv.foreground = ~0L;
150 gcv.plane_mask = base_pixel | plane_masks[random() % nplanes];
151 flags |= GCPlaneMask;
155 gcv.foreground = pixel;
158 gcv.line_width = t->thickness;
159 gcv.line_style = LineSolid;
160 gcv.cap_style = CapProjecting;
161 gcv.join_style = JoinMiter;
163 flags |= (GCLineWidth | GCLineStyle | GCCapStyle | GCJoinStyle);
164 t->gc = XCreateGC (dpy, d, flags, &gcv);
166 switch (random() % 11) {
167 case 0: case 1: case 2: case 3: t->draw = draw_star; break;
168 case 4: case 5: case 6: case 7: t->draw = draw_circle; break;
169 case 8: t->draw = draw_hlines; break;
170 case 9: t->draw = draw_vlines; break;
171 case 10: t->draw = draw_corners; break;
172 default: abort(); break;
179 throb (Display *dpy, Drawable window, struct throbber *t)
182 if (t->size <= (t->thickness / 2))
184 t->speed = -t->speed;
185 t->size += (t->speed * 2);
187 else if (t->size > t->max_size)
189 t->speed = -t->speed;
190 t->size += (t->speed * 2);
196 XFreeGC (dpy, t->gc);
197 memset (t, 0, sizeof(*t));
203 t->draw (dpy, window, t);
210 char *progclass = "Deluxe";
212 char *defaults [] = {
213 ".background: black",
214 ".foreground: white",
221 "*transparent: False",
222 "*doubleBuffer: True",
223 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
225 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
229 XrmOptionDescRec options [] = {
230 { "-delay", ".delay", XrmoptionSepArg, 0 },
231 { "-thickness", ".thickness", XrmoptionSepArg, 0 },
232 { "-count", ".count", XrmoptionSepArg, 0 },
233 { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
234 { "-speed", ".speed", XrmoptionSepArg, 0 },
235 { "-transparent", ".transparent", XrmoptionNoArg, "True" },
236 { "-opaque", ".transparent", XrmoptionNoArg, "False" },
237 { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
238 { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
243 screenhack (Display *dpy, Window window)
245 int count = get_integer_resource ("count", "Integer");
246 int delay = get_integer_resource ("delay", "Integer");
247 int ncolors = get_integer_resource ("ncolors", "Integer");
248 Bool dbuf = get_boolean_resource ("doubleBuffer", "Boolean");
253 struct throbber **throbbers;
254 XWindowAttributes xgwa;
255 Pixmap b=0, ba=0, bb=0; /* double-buffer to reduce flicker */
256 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
257 XdbeBackBuffer backb = 0;
258 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
260 XGetWindowAttributes (dpy, window, &xgwa);
262 transparent_p = get_boolean_resource("transparent", "Transparent");
264 colors = (XColor *) calloc (sizeof(*colors), ncolors);
266 if (get_boolean_resource("mono", "Boolean"))
270 colors[0].pixel = get_pixel_resource("foreground", "Foreground",
273 else if (transparent_p)
275 nplanes = get_integer_resource ("planes", "Planes");
277 nplanes = (random() % (xgwa.depth-2)) + 2;
279 allocate_alpha_colors (xgwa.screen, xgwa.visual, xgwa.colormap,
280 &nplanes, True, &plane_masks,
285 "%s: couldn't allocate any color planes; turning transparency off.\n",
287 transparent_p = False;
294 make_random_colormap (dpy, xgwa.visual, xgwa.colormap,
295 colors, &ncolors, True, True, 0, True);
302 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
303 b = backb = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
304 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
308 ba = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
309 bb = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
318 throbbers = (struct throbber **) calloc (count, sizeof(struct throbber *));
319 for (i = 0; i < count; i++)
320 throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height,
321 colors[random() % ncolors].pixel);
323 gcv.foreground = get_pixel_resource ("background", "Background",
325 erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
327 if (ba) XFillRectangle (dpy, ba, erase_gc, 0, 0, xgwa.width, xgwa.height);
328 if (bb) XFillRectangle (dpy, bb, erase_gc, 0, 0, xgwa.width, xgwa.height);
332 XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height);
334 for (i = 0; i < count; i++)
335 if (throb (dpy, b, throbbers[i]) < 0)
336 throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height,
337 colors[random() % ncolors].pixel);
339 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
342 XdbeSwapInfo info[1];
343 info[0].swap_window = window;
344 info[0].swap_action = XdbeUndefined;
345 XdbeSwapBuffers (dpy, info, 1);
348 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
351 XCopyArea (dpy, b, window, erase_gc, 0, 0,
352 xgwa.width, xgwa.height, 0, 0);
353 b = (b == ba ? bb : ba);
357 screenhack_handle_events (dpy);