1 /* xscreensaver, Copyright (c) 1999-2006 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))
29 unsigned long base_pixel, *plane_masks;
37 struct throbber **throbbers;
38 XWindowAttributes xgwa;
39 Pixmap b, ba, bb; /* double-buffer to reduce flicker */
41 # ifdef HAVE_DOUBLE_BUFFER_EXTENSION
44 # endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
55 void (*draw) (struct state *, Drawable, struct throbber *);
60 draw_star (struct state *st, Drawable w, struct throbber *t)
65 int s = t->size / 0.383; /* trial and error, I forget how to derive this */
70 points[0].x = x + s * cos(o + 0.0*c); points[0].y = y + s * sin(o + 0.0*c);
71 points[1].x = x + s2 * cos(o + 0.1*c); points[1].y = y + s2 * sin(o + 0.1*c);
72 points[2].x = x + s * cos(o + 0.2*c); points[2].y = y + s * sin(o + 0.2*c);
73 points[3].x = x + s2 * cos(o + 0.3*c); points[3].y = y + s2 * sin(o + 0.3*c);
74 points[4].x = x + s * cos(o + 0.4*c); points[4].y = y + s * sin(o + 0.4*c);
75 points[5].x = x + s2 * cos(o + 0.5*c); points[5].y = y + s2 * sin(o + 0.5*c);
76 points[6].x = x + s * cos(o + 0.6*c); points[6].y = y + s * sin(o + 0.6*c);
77 points[7].x = x + s2 * cos(o + 0.7*c); points[7].y = y + s2 * sin(o + 0.7*c);
78 points[8].x = x + s * cos(o + 0.8*c); points[8].y = y + s * sin(o + 0.8*c);
79 points[9].x = x + s2 * cos(o + 0.9*c); points[9].y = y + s2 * sin(o + 0.9*c);
80 points[10] = points[0];
82 XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin);
86 draw_circle (struct state *st, Drawable w, struct throbber *t)
88 XDrawArc (st->dpy, w, t->gc,
96 draw_hlines (struct state *st, Drawable w, struct throbber *t)
98 XDrawLine (st->dpy, w, t->gc, 0,
99 t->y - t->size, t->max_size,
101 XDrawLine (st->dpy, w, t->gc, 0,
102 t->y + t->size, t->max_size,
107 draw_vlines (struct state *st, Drawable w, struct throbber *t)
109 XDrawLine (st->dpy, w, t->gc,
111 t->x - t->size, t->max_size);
112 XDrawLine (st->dpy, w, t->gc,
114 t->x + t->size, t->max_size);
118 draw_corners (struct state *st, Drawable w, struct throbber *t)
120 int s = (t->size + t->thickness) / 2;
123 points[0].x = 0; points[0].y = t->y - s;
124 points[1].x = t->x - s; points[1].y = t->y - s;
125 points[2].x = t->x - s; points[2].y = 0;
126 XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin);
128 points[0].x = 0; points[0].y = t->y + s;
129 points[1].x = t->x - s; points[1].y = t->y + s;
130 points[2].x = t->x - s; points[2].y = t->max_size;
131 XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin);
133 points[0].x = t->x + s; points[0].y = 0;
134 points[1].x = t->x + s; points[1].y = t->y - s;
135 points[2].x = t->max_size; points[2].y = t->y - s;
136 XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin);
138 points[0].x = t->x + s; points[0].y = t->max_size;
139 points[1].x = t->x + s; points[1].y = t->y + s;
140 points[2].x = t->max_size; points[2].y = t->y + s;
141 XDrawLines (st->dpy, w, t->gc, points, countof(points), CoordModeOrigin);
145 static struct throbber *
146 make_throbber (struct state *st, Drawable d, int w, int h, unsigned long pixel)
150 struct throbber *t = (struct throbber *) malloc (sizeof (*t));
154 t->speed = get_integer_resource (st->dpy, "speed", "Speed");
155 t->fuse = 1 + (random() % 4);
156 t->thickness = get_integer_resource (st->dpy, "thickness", "Thickness");
158 if (t->speed < 0) t->speed = -t->speed;
159 t->speed += (((random() % t->speed) / 2) - (t->speed / 2));
160 if (t->speed > 0) t->speed = -t->speed;
163 t->size = t->max_size;
165 t->size = t->thickness, t->speed = -t->speed;
167 flags = GCForeground;
169 if (st->transparent_p)
171 gcv.foreground = ~0L;
172 gcv.plane_mask = st->base_pixel | st->plane_masks[random() % st->nplanes];
173 flags |= GCPlaneMask;
176 # endif /* !HAVE_COCOA */
178 gcv.foreground = pixel;
181 gcv.line_width = t->thickness;
182 gcv.cap_style = CapProjecting;
183 gcv.join_style = JoinMiter;
185 flags |= (GCLineWidth | GCCapStyle | GCJoinStyle);
186 t->gc = XCreateGC (st->dpy, d, flags, &gcv);
189 if (st->transparent_p)
191 /* give a non-opaque alpha to the color */
192 unsigned long pixel = gcv.foreground;
193 unsigned long amask = BlackPixelOfScreen (st->xgwa.screen);
194 unsigned long a = (0xCCCCCCCC & amask);
195 pixel = (pixel & (~amask)) | a;
197 jwxyz_XSetAlphaAllowed (st->dpy, t->gc, True);
198 XSetForeground (st->dpy, t->gc, pixel);
200 # endif /* HAVE_COCOA */
202 switch (random() % 11) {
203 case 0: case 1: case 2: case 3: t->draw = draw_star; break;
204 case 4: case 5: case 6: case 7: t->draw = draw_circle; break;
205 case 8: t->draw = draw_hlines; break;
206 case 9: t->draw = draw_vlines; break;
207 case 10: t->draw = draw_corners; break;
208 default: abort(); break;
215 throb (struct state *st, Drawable window, struct throbber *t)
218 if (t->size <= (t->thickness / 2))
220 t->speed = -t->speed;
221 t->size += (t->speed * 2);
223 else if (t->size > t->max_size)
225 t->speed = -t->speed;
226 t->size += (t->speed * 2);
232 XFreeGC (st->dpy, t->gc);
233 memset (t, 0, sizeof(*t));
239 t->draw (st, window, t);
246 deluxe_init (Display *dpy, Window window)
248 struct state *st = (struct state *) calloc (1, sizeof(*st));
253 st->count = get_integer_resource (st->dpy, "count", "Integer");
254 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
255 st->ncolors = get_integer_resource (st->dpy, "ncolors", "Integer");
256 st->dbuf = get_boolean_resource (st->dpy, "doubleBuffer", "Boolean");
258 # ifdef HAVE_DOUBLE_BUFFER_EXTENSION
259 st->dbeclear_p = get_boolean_resource (st->dpy, "useDBEClear", "Boolean");
262 # ifdef HAVE_COCOA /* Don't second-guess Quartz's double-buffering */
266 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
268 st->transparent_p = get_boolean_resource(st->dpy, "transparent", "Transparent");
270 st->colors = (XColor *) calloc (sizeof(*st->colors), st->ncolors);
272 if (get_boolean_resource(st->dpy, "mono", "Boolean"))
276 st->colors[0].pixel = get_pixel_resource(st->dpy, st->xgwa.colormap,
277 "foreground", "Foreground");
280 else if (st->transparent_p)
282 st->nplanes = get_integer_resource (st->dpy, "planes", "Planes");
283 if (st->nplanes <= 0)
284 st->nplanes = (random() % (st->xgwa.depth-2)) + 2;
286 allocate_alpha_colors (st->xgwa.screen, st->xgwa.visual, st->xgwa.colormap,
287 &st->nplanes, True, &st->plane_masks,
289 if (st->nplanes <= 1)
293 "%s: couldn't allocate any color planes; turning transparency off.\n",
296 st->transparent_p = False;
300 #endif /* !HAVE_COCOA */
306 make_random_colormap (st->dpy, st->xgwa.visual, st->xgwa.colormap,
307 st->colors, &st->ncolors, True, True, 0, True);
314 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
316 st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeBackground);
318 st->b = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
320 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
324 st->ba = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth);
325 st->bb = XCreatePixmap (st->dpy, st->window, st->xgwa.width, st->xgwa.height,st->xgwa.depth);
334 st->throbbers = (struct throbber **) calloc (st->count, sizeof(struct throbber *));
335 for (i = 0; i < st->count; i++)
336 st->throbbers[i] = make_throbber (st, st->b, st->xgwa.width, st->xgwa.height,
337 st->colors[random() % st->ncolors].pixel);
339 gcv.foreground = get_pixel_resource (st->dpy, st->xgwa.colormap,
340 "background", "Background");
341 st->erase_gc = XCreateGC (st->dpy, st->b, GCForeground, &gcv);
343 if (st->ba) XFillRectangle (st->dpy, st->ba, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);
344 if (st->bb) XFillRectangle (st->dpy, st->bb, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);
350 deluxe_draw (Display *dpy, Window window, void *closure)
352 struct state *st = (struct state *) closure;
354 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
355 if (!st->dbeclear_p || !st->backb)
356 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
357 XFillRectangle (st->dpy, st->b, st->erase_gc, 0, 0, st->xgwa.width, st->xgwa.height);
359 for (i = 0; i < st->count; i++)
360 if (throb (st, st->b, st->throbbers[i]) < 0)
361 st->throbbers[i] = make_throbber (st, st->b, st->xgwa.width, st->xgwa.height,
362 st->colors[random() % st->ncolors].pixel);
364 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
367 XdbeSwapInfo info[1];
368 info[0].swap_window = st->window;
369 info[0].swap_action = (st->dbeclear_p ? XdbeBackground : XdbeUndefined);
370 XdbeSwapBuffers (st->dpy, info, 1);
373 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
376 XCopyArea (st->dpy, st->b, st->window, st->erase_gc, 0, 0,
377 st->xgwa.width, st->xgwa.height, 0, 0);
378 st->b = (st->b == st->ba ? st->bb : st->ba);
385 deluxe_reshape (Display *dpy, Window window, void *closure,
386 unsigned int w, unsigned int h)
388 struct state *st = (struct state *) closure;
389 if (! st->dbuf) { /* #### more complicated if we have a back buffer... */
391 XGetWindowAttributes (st->dpy, st->window, &st->xgwa);
392 XClearWindow (dpy, window);
393 for (i = 0; i < st->count; i++)
394 if (st->throbbers[i])
395 st->throbbers[i]->fuse = 0;
400 deluxe_event (Display *dpy, Window window, void *closure, XEvent *event)
406 deluxe_free (Display *dpy, Window window, void *closure)
411 static const char *deluxe_defaults [] = {
412 ".background: black",
413 ".foreground: white",
419 "*transparent: True",
420 "*doubleBuffer: True",
421 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
423 "*useDBEClear: True",
424 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
428 static XrmOptionDescRec deluxe_options [] = {
429 { "-delay", ".delay", XrmoptionSepArg, 0 },
430 { "-thickness", ".thickness", XrmoptionSepArg, 0 },
431 { "-count", ".count", XrmoptionSepArg, 0 },
432 { "-ncolors", ".ncolors", XrmoptionSepArg, 0 },
433 { "-speed", ".speed", XrmoptionSepArg, 0 },
434 { "-transparent", ".transparent", XrmoptionNoArg, "True" },
435 { "-no-transparent", ".transparent", XrmoptionNoArg, "False" },
436 { "-opaque", ".transparent", XrmoptionNoArg, "False" },
437 { "-no-opaque", ".transparent", XrmoptionNoArg, "True" },
438 { "-db", ".doubleBuffer", XrmoptionNoArg, "True" },
439 { "-no-db", ".doubleBuffer", XrmoptionNoArg, "False" },
444 XSCREENSAVER_MODULE ("Deluxe", deluxe)