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"
15 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
17 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
19 #define countof(x) (sizeof(x)/sizeof(*(x)))
20 #define ABS(x) ((x)<0?-(x):(x))
30 void (*draw) (Display *, Drawable, struct throbber *);
34 draw_star (Display *dpy, Drawable w, struct throbber *t)
39 int s = t->size / 0.383; /* trial and error, I forget how to derive this */
44 points[0].x = x + s * cos(o + 0.0*c); points[0].y = y + s * sin(o + 0.0*c);
45 points[1].x = x + s2 * cos(o + 0.1*c); points[1].y = y + s2 * sin(o + 0.1*c);
46 points[2].x = x + s * cos(o + 0.2*c); points[2].y = y + s * sin(o + 0.2*c);
47 points[3].x = x + s2 * cos(o + 0.3*c); points[3].y = y + s2 * sin(o + 0.3*c);
48 points[4].x = x + s * cos(o + 0.4*c); points[4].y = y + s * sin(o + 0.4*c);
49 points[5].x = x + s2 * cos(o + 0.5*c); points[5].y = y + s2 * sin(o + 0.5*c);
50 points[6].x = x + s * cos(o + 0.6*c); points[6].y = y + s * sin(o + 0.6*c);
51 points[7].x = x + s2 * cos(o + 0.7*c); points[7].y = y + s2 * sin(o + 0.7*c);
52 points[8].x = x + s * cos(o + 0.8*c); points[8].y = y + s * sin(o + 0.8*c);
53 points[9].x = x + s2 * cos(o + 0.9*c); points[9].y = y + s2 * sin(o + 0.9*c);
54 points[10] = points[0];
56 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
60 draw_circle (Display *dpy, Drawable w, struct throbber *t)
62 XDrawArc (dpy, w, t->gc,
70 draw_hlines (Display *dpy, Drawable w, struct throbber *t)
72 XDrawLine (dpy, w, t->gc, 0,
73 t->y - t->size, t->max_size,
75 XDrawLine (dpy, w, t->gc, 0,
76 t->y + t->size, t->max_size,
81 draw_vlines (Display *dpy, Drawable w, struct throbber *t)
83 XDrawLine (dpy, w, t->gc,
85 t->x - t->size, t->max_size);
86 XDrawLine (dpy, w, t->gc,
88 t->x + t->size, t->max_size);
92 draw_corners (Display *dpy, Drawable w, struct throbber *t)
94 int s = (t->size + t->thickness) / 2;
97 points[0].x = 0; points[0].y = t->y - s;
98 points[1].x = t->x - s; points[1].y = t->y - s;
99 points[2].x = t->x - s; points[2].y = 0;
100 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
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 = t->max_size;
105 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
107 points[0].x = t->x + s; points[0].y = 0;
108 points[1].x = t->x + s; points[1].y = t->y - s;
109 points[2].x = t->max_size; points[2].y = t->y - s;
110 XDrawLines (dpy, w, t->gc, points, countof(points), CoordModeOrigin);
112 points[0].x = t->x + s; points[0].y = t->max_size;
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);
119 static struct throbber *
120 make_throbber (Display *dpy, Drawable d, int w, int h, unsigned long pixel)
123 struct throbber *t = (struct throbber *) malloc (sizeof (*t));
127 t->speed = get_integer_resource ("speed", "Speed");
128 t->fuse = 1 + (random() % 4);
129 t->thickness = get_integer_resource ("thickness", "Thickness");
131 if (t->speed < 0) t->speed = -t->speed;
132 t->speed += (((random() % t->speed) / 2) - (t->speed / 2));
133 if (t->speed > 0) t->speed = -t->speed;
136 t->size = t->max_size;
138 t->size = t->thickness, t->speed = -t->speed;
140 gcv.foreground = pixel;
141 gcv.line_width = t->thickness;
142 gcv.line_style = LineSolid;
143 gcv.cap_style = CapProjecting;
144 gcv.join_style = JoinMiter;
145 t->gc = XCreateGC (dpy, d,
146 (GCForeground|GCLineWidth|GCLineStyle|
147 GCCapStyle|GCJoinStyle),
150 switch (random() % 11) {
151 case 0: case 1: case 2: case 3: t->draw = draw_star; break;
152 case 4: case 5: case 6: case 7: t->draw = draw_circle; break;
153 case 8: t->draw = draw_hlines; break;
154 case 9: t->draw = draw_vlines; break;
155 case 10: t->draw = draw_corners; break;
156 default: abort(); break;
163 throb (Display *dpy, Drawable window, struct throbber *t)
166 if (t->size <= (t->thickness / 2))
168 t->speed = -t->speed;
169 t->size += (t->speed * 2);
171 else if (t->size > t->max_size)
173 t->speed = -t->speed;
174 t->size += (t->speed * 2);
180 XFreeGC (dpy, t->gc);
181 memset (t, 0, sizeof(*t));
187 t->draw (dpy, window, t);
194 char *progclass = "Deluxe";
196 char *defaults [] = {
197 ".background: black",
198 ".foreground: white",
204 "*doubleBuffer: True",
205 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
207 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
211 XrmOptionDescRec options [] = {
212 { "-delay", ".delay", XrmoptionSepArg, 0 },
213 { "-thickness", ".thickness", XrmoptionSepArg, 0 },
214 { "-count", ".count", XrmoptionSepArg, 0 },
215 { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
216 { "-speed", ".speed", XrmoptionSepArg, 0 },
217 { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
218 { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
223 screenhack (Display *dpy, Window window)
225 int count = get_integer_resource ("count", "Integer");
226 int delay = get_integer_resource ("delay", "Integer");
227 int ncolors = get_integer_resource ("ncolors", "Integer");
228 Bool dbuf = get_boolean_resource ("doubleBuffer", "Boolean");
233 struct throbber **throbbers;
234 XWindowAttributes xgwa;
235 Pixmap b=0, ba=0, bb=0; /* double-buffer to reduce flicker */
236 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
237 XdbeBackBuffer backb = 0;
238 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
240 XGetWindowAttributes (dpy, window, &xgwa);
242 if (get_boolean_resource("mono", "Boolean"))
246 colors[0].pixel = get_pixel_resource("foreground", "Foreground",
251 make_random_colormap (dpy, xgwa.visual, xgwa.colormap,
252 colors, &ncolors, True, True, 0, True);
259 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
260 b = backb = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
261 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
265 ba = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
266 bb = XCreatePixmap (dpy, window, xgwa.width, xgwa.height,xgwa.depth);
275 throbbers = (struct throbber **) calloc (count, sizeof(struct throbber *));
276 for (i = 0; i < count; i++)
277 throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height,
278 colors[random() % ncolors].pixel);
280 gcv.foreground = get_pixel_resource ("background", "Background",
282 erase_gc = XCreateGC (dpy, b, GCForeground, &gcv);
284 if (ba) XFillRectangle (dpy, ba, erase_gc, 0, 0, xgwa.width, xgwa.height);
285 if (bb) XFillRectangle (dpy, bb, erase_gc, 0, 0, xgwa.width, xgwa.height);
289 XFillRectangle (dpy, b, erase_gc, 0, 0, xgwa.width, xgwa.height);
291 for (i = 0; i < count; i++)
292 if (throb (dpy, b, throbbers[i]) < 0)
293 throbbers[i] = make_throbber (dpy, b, xgwa.width, xgwa.height,
294 colors[random() % ncolors].pixel);
296 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
299 XdbeSwapInfo info[1];
300 info[0].swap_window = window;
301 info[0].swap_action = XdbeUndefined;
302 XdbeSwapBuffers (dpy, info, 1);
305 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
308 XCopyArea (dpy, b, window, erase_gc, 0, 0,
309 xgwa.width, xgwa.height, 0, 0);
310 b = (b == ba ? bb : ba);
314 screenhack_handle_events (dpy);