1 /* xscreensaver, Copyright (c) 1997, 1998 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"
13 #include <X11/Xutil.h>
15 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
17 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
20 static XColor *colors = 0;
21 static int fg_pixel, bg_pixel;
22 static Pixmap p0 = 0, p1 = 0, p2 = 0, p3 = 0;
23 static GC copy_gc = 0, erase_gc = 0, window_gc = 0;
24 static int width, height, size;
25 static int x1, x2, y1, y2, x3, y3;
26 static int dx1, dx2, dx3, dy1, dy2, dy3;
27 static int othickness, thickness;
29 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
30 XdbeBackBuffer back_buf = 0;
31 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
34 init_moire2 (Display *dpy, Window window)
36 XWindowAttributes xgwa;
37 XGetWindowAttributes (dpy, window, &xgwa);
39 othickness = get_integer_resource("thickness", "Thickness");
44 ncolors = get_integer_resource ("colors", "Colors");
45 if (ncolors < 2) ncolors = 2;
46 if (ncolors <= 2) mono_p = True;
51 colors = (XColor *) malloc(sizeof(*colors) * (ncolors+1));
56 make_smooth_colormap (dpy, xgwa.visual, xgwa.colormap, colors, &ncolors,
59 bg_pixel = get_pixel_resource("background", "Background", dpy,
61 fg_pixel = get_pixel_resource("foreground", "Foreground", dpy,
64 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
65 back_buf = xdbe_get_backbuffer (dpy, window, XdbeUndefined);
66 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
71 reset_moire2 (Display *dpy, Window window)
74 XWindowAttributes xgwa;
77 XGetWindowAttributes (dpy, window, &xgwa);
79 do_three = (0 == (random() % 3));
83 size = width > height ? width : height;
85 if (p0) XFreePixmap(dpy, p0);
86 if (p1) XFreePixmap(dpy, p1);
87 if (p2) XFreePixmap(dpy, p2);
88 if (p3) XFreePixmap(dpy, p3);
90 p0 = XCreatePixmap(dpy, window, width, height, 1);
91 p1 = XCreatePixmap(dpy, window, width*2, height*2, 1);
92 p2 = XCreatePixmap(dpy, window, width*2, height*2, 1);
94 p3 = XCreatePixmap(dpy, window, width*2, height*2, 1);
98 thickness = (othickness > 0 ? othickness : (1 + (random() % 4)));
101 gcv.line_width = (thickness == 1 ? 0 : thickness);
102 gc = XCreateGC (dpy, p1, GCForeground|GCLineWidth, &gcv);
104 XFillRectangle(dpy, p1, gc, 0, 0, width*2, height*2);
105 XFillRectangle(dpy, p2, gc, 0, 0, width*2, height*2);
107 XFillRectangle(dpy, p3, gc, 0, 0, width*2, height*2);
109 XSetForeground(dpy, gc, 1);
111 xor = (do_three || (thickness == 1) || (random() & 1));
114 int i, ii, maxx, maxy;
116 #define FROB(P) do { \
119 if (0 == (random() % 5)) { \
120 float f = 1.0 + frand(0.05); \
121 if (random() & 1) maxx *= f; \
124 ii = (thickness + 1 + (xor ? 0 : 1) + (random() % (4 * thickness))); \
125 for (i = 0; i < (size*2); i += ii) \
126 XDrawArc(dpy, (P), gc, i-size, i-size, maxx-i-i, maxy-i-i, 0, 360*64); \
127 if (0 == (random() % 5)) \
129 XSetFunction(dpy, gc, GXxor); \
130 XFillRectangle(dpy, (P), gc, 0, 0, width*2, height*2); \
131 XSetFunction(dpy, gc, GXcopy); \
144 if (copy_gc) XFreeGC(dpy, copy_gc);
145 gcv.function = (xor ? GXxor : GXor);
149 copy_gc = XCreateGC (dpy, p0, GCFunction|GCForeground|GCBackground, &gcv);
152 if (erase_gc) XFreeGC(dpy, erase_gc);
153 erase_gc = XCreateGC (dpy, p0, GCForeground, &gcv);
155 gcv.foreground = fg_pixel;
156 gcv.background = bg_pixel;
157 if (window_gc) XFreeGC(dpy, window_gc);
158 window_gc = XCreateGC (dpy, window, GCForeground|GCBackground, &gcv);
160 #define FROB(N,DN,MAX) \
161 N = (MAX/2) + (random() % MAX); \
162 DN = ((1 + (random() % (7*thickness))) * ((random() & 1) ? 1 : -1))
176 moire2 (Display *dpy, Window window)
178 #define FROB(N,DN,MAX) \
180 if (N <= 0) N = 0, DN = -DN; \
181 else if (N >= MAX) N = MAX, DN = -DN; \
182 else if (0 == (random() % 100)) DN = -DN; \
183 else if (0 == (random() % 50)) \
184 DN += (DN <= -20 ? 1 : (DN >= 20 ? -1 : ((random() & 1) ? 1 : -1)))
194 XFillRectangle(dpy, p0, erase_gc, 0, 0, width, height);
195 XCopyArea(dpy, p1, p0, copy_gc, x1, y1, width, height, 0, 0);
196 XCopyArea(dpy, p2, p0, copy_gc, x2, y2, width, height, 0, 0);
198 XCopyArea(dpy, p3, p0, copy_gc, x3, y3, width, height, 0, 0);
200 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
203 XdbeSwapInfo info[1];
204 info[0].swap_window = window;
205 info[0].swap_action = XdbeUndefined;
206 XCopyPlane (dpy, p0, back_buf, window_gc, 0, 0, width, height, 0, 0, 1L);
207 XdbeSwapBuffers (dpy, info, 1);
210 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
211 XCopyPlane (dpy, p0, window, window_gc, 0, 0, width, height, 0, 0, 1L);
216 XCopyPlane(dpy, p1, window, window_gc, (width*2)/3, (height*2)/3,
219 XCopyPlane(dpy, p2, window, window_gc, (width*2)/3, (height*2)/3,
221 width/2, height/2, 1L);
228 char *progclass = "Moire2";
230 char *defaults [] = {
231 ".background: black",
232 ".foreground: white",
238 #ifdef HAVE_DOUBLE_BUFFER_EXTENSION
239 /* Off by default, since it slows it down a lot, and the flicker isn't really
240 all that bad without it... Or rather, it flickers just as badly with it.
241 The XFree86 implementation of the XDBE extension totally blows! There is
242 just *no* excuse for the "swap buffers" operation to flicker like it does.
245 #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */
250 XrmOptionDescRec options [] = {
251 { "-delay", ".delay", XrmoptionSepArg, 0 },
252 { "-ncolors", ".colors", XrmoptionSepArg, 0 },
253 { "-thickness", ".thickness", XrmoptionSepArg, 0 },
258 screenhack (Display *dpy, Window window)
260 int delay = get_integer_resource ("delay", "Integer");
261 int color_shift = get_integer_resource ("colorShift", "Integer");
265 if (color_shift <= 0) color_shift = 1;
266 init_moire2 (dpy, window);
269 int iterations = 30 + (random() % 70) + (random() % 70);
270 reset_moire2 (dpy, window);
272 flip_a = mono_p ? False : (random() & 1);
273 flip_b = mono_p ? False : (random() & 1);
277 XSetForeground(dpy, window_gc, bg_pixel);
278 XSetBackground(dpy, window_gc, fg_pixel);
282 XSetForeground(dpy, window_gc, fg_pixel);
283 XSetBackground(dpy, window_gc, bg_pixel);
286 while (--iterations > 0)
296 XSetBackground(dpy, window_gc, colors[pix].pixel);
298 XSetForeground(dpy, window_gc, colors[pix].pixel);
301 for (i = 0; i < color_shift; i++)
303 moire2 (dpy, window);
304 screenhack_handle_events (dpy);