1 /* xscreensaver, Copyright (c) 1997-2013 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
12 #include "screenhack.h"
14 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
16 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
24 int fg_pixel, bg_pixel;
25 Pixmap p0, p1, p2, p3;
26 GC copy_gc, erase_gc, window_gc;
27 int width, height, size;
28 int x1, x2, y1, y2, x3, y3;
29 int dx1, dx2, dx3, dy1, dy2, dy3;
30 int othickness, thickness;
32 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
33 XdbeBackBuffer back_buf;
34 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
38 int delay, color_shift;
41 int iterations, iteration;
45 moire2_init_1 (struct state *st)
47 XWindowAttributes xgwa;
48 XGetWindowAttributes (st->dpy, st->window, &xgwa);
50 st->othickness = get_integer_resource(st->dpy, "thickness", "Thickness");
55 st->ncolors = get_integer_resource (st->dpy, "colors", "Colors");
56 if (st->ncolors < 2) st->ncolors = 2;
57 if (st->ncolors <= 2) mono_p = True;
62 st->colors = (XColor *) malloc(sizeof(*st->colors) * (st->ncolors+1));
67 make_smooth_colormap (xgwa.screen, xgwa.visual, xgwa.colormap,
68 st->colors, &st->ncolors,
71 st->bg_pixel = get_pixel_resource(st->dpy,
72 xgwa.colormap, "background", "Background");
73 st->fg_pixel = get_pixel_resource(st->dpy,
74 xgwa.colormap, "foreground", "Foreground");
76 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
77 st->back_buf = xdbe_get_backbuffer (st->dpy, st->window, XdbeUndefined);
78 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
83 reset_moire2 (struct state *st)
86 XWindowAttributes xgwa;
89 XGetWindowAttributes (st->dpy, st->window, &xgwa);
91 st->do_three = (0 == (random() % 3));
93 st->width = xgwa.width;
94 st->height = xgwa.height;
95 st->size = st->width > st->height ? st->width : st->height;
97 if (st->p0) XFreePixmap(st->dpy, st->p0);
98 if (st->p1) XFreePixmap(st->dpy, st->p1);
99 if (st->p2) XFreePixmap(st->dpy, st->p2);
100 if (st->p3) XFreePixmap(st->dpy, st->p3);
102 st->p0 = XCreatePixmap(st->dpy, st->window, st->width, st->height, 1);
103 st->p1 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1);
104 st->p2 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1);
106 st->p3 = XCreatePixmap(st->dpy, st->window, st->width*2, st->height*2, 1);
110 st->thickness = (st->othickness > 0 ? st->othickness : (1 + (random() % 4)));
113 gcv.line_width = (st->thickness == 1 ? 0 : st->thickness);
114 gc = XCreateGC (st->dpy, st->p1, GCForeground|GCLineWidth, &gcv);
116 XFillRectangle(st->dpy, st->p1, gc, 0, 0, st->width*2, st->height*2);
117 XFillRectangle(st->dpy, st->p2, gc, 0, 0, st->width*2, st->height*2);
119 XFillRectangle(st->dpy, st->p3, gc, 0, 0, st->width*2, st->height*2);
121 XSetForeground(st->dpy, gc, 1);
123 xor = (st->do_three || (st->thickness == 1) || (random() & 1));
126 int i, ii, maxx, maxy;
128 #define FROB(P) do { \
129 maxx = (st->size*4); \
130 maxy = (st->size*4); \
131 if (0 == (random() % 5)) { \
132 float f = 1.0 + frand(0.05); \
133 if (random() & 1) maxx *= f; \
136 ii = (st->thickness + 1 + (xor ? 0 : 1) + (random() % (4 * st->thickness))); \
137 for (i = 0; i < (st->size*2); i += ii) \
138 XDrawArc(st->dpy, (P), gc, i-st->size, i-st->size, maxx-i-i, maxy-i-i, 0, 360*64); \
139 if (0 == (random() % 5)) \
141 XSetFunction(st->dpy, gc, GXxor); \
142 XFillRectangle(st->dpy, (P), gc, 0, 0, st->width*2, st->height*2); \
143 XSetFunction(st->dpy, gc, GXcopy); \
154 XFreeGC(st->dpy, gc);
156 if (st->copy_gc) XFreeGC(st->dpy, st->copy_gc);
157 gcv.function = (xor ? GXxor : GXor);
161 st->copy_gc = XCreateGC (st->dpy, st->p0, GCFunction|GCForeground|GCBackground, &gcv);
164 if (st->erase_gc) XFreeGC(st->dpy, st->erase_gc);
165 st->erase_gc = XCreateGC (st->dpy, st->p0, GCForeground, &gcv);
167 gcv.foreground = st->fg_pixel;
168 gcv.background = st->bg_pixel;
169 if (st->window_gc) XFreeGC(st->dpy, st->window_gc);
170 st->window_gc = XCreateGC (st->dpy, st->window, GCForeground|GCBackground, &gcv);
172 #define FROB(N,DN,MAX) \
173 N = (MAX/2) + (random() % MAX); \
174 DN = ((1 + (random() % (7*st->thickness))) * ((random() & 1) ? 1 : -1))
176 FROB(st->x1,st->dx1,st->width);
177 FROB(st->x2,st->dx2,st->width);
178 FROB(st->x3,st->dx3,st->width);
179 FROB(st->y1,st->dy1,st->height);
180 FROB(st->y2,st->dy2,st->height);
181 FROB(st->y3,st->dy3,st->height);
188 moire2 (struct state *st)
190 #define FROB(N,DN,MAX) \
192 if (N <= 0) N = 0, DN = -DN; \
193 else if (N >= MAX) N = MAX, DN = -DN; \
194 else if (0 == (random() % 100)) DN = -DN; \
195 else if (0 == (random() % 50)) \
196 DN += (DN <= -20 ? 1 : (DN >= 20 ? -1 : ((random() & 1) ? 1 : -1)))
198 FROB(st->x1,st->dx1,st->width);
199 FROB(st->x2,st->dx2,st->width);
200 FROB(st->x3,st->dx3,st->width);
201 FROB(st->y1,st->dy1,st->height);
202 FROB(st->y2,st->dy2,st->height);
203 FROB(st->y3,st->dy3,st->height);
206 XFillRectangle(st->dpy, st->p0, st->erase_gc, 0, 0, st->width, st->height);
207 XCopyArea(st->dpy, st->p1, st->p0, st->copy_gc, st->x1, st->y1, st->width, st->height, 0, 0);
208 XCopyArea(st->dpy, st->p2, st->p0, st->copy_gc, st->x2, st->y2, st->width, st->height, 0, 0);
210 XCopyArea(st->dpy, st->p3, st->p0, st->copy_gc, st->x3, st->y3, st->width, st->height, 0, 0);
212 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
215 XdbeSwapInfo info[1];
216 info[0].swap_window = st->window;
217 info[0].swap_action = XdbeUndefined;
218 XCopyPlane (st->dpy, st->p0, st->back_buf, st->window_gc, 0, 0, st->width, st->height, 0, 0, 1L);
219 XdbeSwapBuffers (st->dpy, info, 1);
222 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
223 XCopyPlane (st->dpy, st->p0, st->window, st->window_gc, 0, 0, st->width, st->height, 0, 0, 1L);
226 XCopyPlane(st->dpy, st->p1, st->window, st->window_gc, (st->width*2)/3, (st->height*2)/3,
227 st->width/2, st->height/2,
228 0, st->height/2, 1L);
229 XCopyPlane(st->dpy, st->p2, st->window, st->window_gc, (st->width*2)/3, (st->height*2)/3,
230 st->width/2, st->height/2,
231 st->width/2, st->height/2, 1L);
238 moire2_init (Display *dpy, Window window)
240 struct state *st = (struct state *) calloc (1, sizeof(*st));
245 st->delay = get_integer_resource (st->dpy, "delay", "Integer");
246 st->color_shift = get_integer_resource (st->dpy, "colorShift", "Integer");
248 if (st->color_shift <= 0) st->color_shift = 1;
254 moire2_draw (Display *dpy, Window window, void *closure)
256 struct state *st = (struct state *) closure;
263 st->iterations = 30 + (random() % 70) + (random() % 70);
266 st->flip_a = mono_p ? False : (random() & 1);
267 st->flip_b = mono_p ? False : (random() & 1);
271 XSetForeground(st->dpy, st->window_gc, st->bg_pixel);
272 XSetBackground(st->dpy, st->window_gc, st->fg_pixel);
276 XSetForeground(st->dpy, st->window_gc, st->fg_pixel);
277 XSetBackground(st->dpy, st->window_gc, st->bg_pixel);
284 st->pix = st->pix % st->ncolors;
287 XSetBackground(st->dpy, st->window_gc, st->colors[st->pix].pixel);
289 XSetForeground(st->dpy, st->window_gc, st->colors[st->pix].pixel);
295 if (st->iteration >= st->color_shift)
299 if (st->iterations <= 0)
307 moire2_reshape (Display *dpy, Window window, void *closure,
308 unsigned int w, unsigned int h)
310 struct state *st = (struct state *) closure;
315 moire2_event (Display *dpy, Window window, void *closure, XEvent *event)
321 moire2_free (Display *dpy, Window window, void *closure)
325 static const char *moire2_defaults [] = {
326 ".background: black",
327 ".foreground: white",
333 "*ignoreRotation: True",
336 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
337 /* Off by default, since it slows it down a lot, and the flicker isn't really
338 all that bad without it... Or rather, it flickers just as badly with it.
339 The XFree86 implementation of the XDBE extension totally blows! There is
340 just *no* excuse for the "swap buffers" operation to flicker like it does.
343 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
348 static XrmOptionDescRec moire2_options [] = {
349 { "-delay", ".delay", XrmoptionSepArg, 0 },
350 { "-ncolors", ".colors", XrmoptionSepArg, 0 },
351 { "-thickness", ".thickness", XrmoptionSepArg, 0 },
355 XSCREENSAVER_MODULE ("Moire2", moire2)