1 | /* xscreensaver, Copyright (c) 1997, 1998 Jamie Zawinski <jwz@jwz.org> |
---|
2 | * |
---|
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 |
---|
9 | * implied warranty. |
---|
10 | */ |
---|
11 | |
---|
12 | #include "screenhack.h" |
---|
13 | #include <X11/Xutil.h> |
---|
14 | |
---|
15 | #ifdef HAVE_DOUBLE_BUFFER_EXTENSION |
---|
16 | # include "xdbe.h" |
---|
17 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
18 | |
---|
19 | static int ncolors; |
---|
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; |
---|
28 | static Bool do_three; |
---|
29 | #ifdef HAVE_DOUBLE_BUFFER_EXTENSION |
---|
30 | XdbeBackBuffer back_buf = 0; |
---|
31 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
32 | |
---|
33 | static void |
---|
34 | init_moire2 (Display *dpy, Window window) |
---|
35 | { |
---|
36 | XWindowAttributes xgwa; |
---|
37 | XGetWindowAttributes (dpy, window, &xgwa); |
---|
38 | |
---|
39 | othickness = get_integer_resource("thickness", "Thickness"); |
---|
40 | |
---|
41 | if (mono_p) |
---|
42 | ncolors = 2; |
---|
43 | else |
---|
44 | ncolors = get_integer_resource ("colors", "Colors"); |
---|
45 | if (ncolors < 2) ncolors = 2; |
---|
46 | if (ncolors <= 2) mono_p = True; |
---|
47 | |
---|
48 | if (mono_p) |
---|
49 | colors = 0; |
---|
50 | else |
---|
51 | colors = (XColor *) malloc(sizeof(*colors) * (ncolors+1)); |
---|
52 | |
---|
53 | if (mono_p) |
---|
54 | ; |
---|
55 | else |
---|
56 | make_smooth_colormap (dpy, xgwa.visual, xgwa.colormap, colors, &ncolors, |
---|
57 | True, 0, True); |
---|
58 | |
---|
59 | bg_pixel = get_pixel_resource("background", "Background", dpy, |
---|
60 | xgwa.colormap); |
---|
61 | fg_pixel = get_pixel_resource("foreground", "Foreground", dpy, |
---|
62 | xgwa.colormap); |
---|
63 | |
---|
64 | #ifdef HAVE_DOUBLE_BUFFER_EXTENSION |
---|
65 | back_buf = xdbe_get_backbuffer (dpy, window, XdbeUndefined); |
---|
66 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
67 | } |
---|
68 | |
---|
69 | |
---|
70 | static void |
---|
71 | reset_moire2 (Display *dpy, Window window) |
---|
72 | { |
---|
73 | GC gc; |
---|
74 | XWindowAttributes xgwa; |
---|
75 | XGCValues gcv; |
---|
76 | Bool xor; |
---|
77 | XGetWindowAttributes (dpy, window, &xgwa); |
---|
78 | |
---|
79 | do_three = (0 == (random() % 3)); |
---|
80 | |
---|
81 | width = xgwa.width; |
---|
82 | height = xgwa.height; |
---|
83 | size = width > height ? width : height; |
---|
84 | |
---|
85 | if (p0) XFreePixmap(dpy, p0); |
---|
86 | if (p1) XFreePixmap(dpy, p1); |
---|
87 | if (p2) XFreePixmap(dpy, p2); |
---|
88 | if (p3) XFreePixmap(dpy, p3); |
---|
89 | |
---|
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); |
---|
93 | if (do_three) |
---|
94 | p3 = XCreatePixmap(dpy, window, width*2, height*2, 1); |
---|
95 | else |
---|
96 | p3 = 0; |
---|
97 | |
---|
98 | thickness = (othickness > 0 ? othickness : (1 + (random() % 4))); |
---|
99 | |
---|
100 | gcv.foreground = 0; |
---|
101 | gcv.line_width = (thickness == 1 ? 0 : thickness); |
---|
102 | gc = XCreateGC (dpy, p1, GCForeground|GCLineWidth, &gcv); |
---|
103 | |
---|
104 | XFillRectangle(dpy, p1, gc, 0, 0, width*2, height*2); |
---|
105 | XFillRectangle(dpy, p2, gc, 0, 0, width*2, height*2); |
---|
106 | if (do_three) |
---|
107 | XFillRectangle(dpy, p3, gc, 0, 0, width*2, height*2); |
---|
108 | |
---|
109 | XSetForeground(dpy, gc, 1); |
---|
110 | |
---|
111 | xor = (do_three || (thickness == 1) || (random() & 1)); |
---|
112 | |
---|
113 | { |
---|
114 | int i, ii, maxx, maxy; |
---|
115 | |
---|
116 | #define FROB(P) do { \ |
---|
117 | maxx = (size*4); \ |
---|
118 | maxy = (size*4); \ |
---|
119 | if (0 == (random() % 5)) { \ |
---|
120 | float f = 1.0 + frand(0.05); \ |
---|
121 | if (random() & 1) maxx *= f; \ |
---|
122 | else maxy *= f; \ |
---|
123 | } \ |
---|
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)) \ |
---|
128 | { \ |
---|
129 | XSetFunction(dpy, gc, GXxor); \ |
---|
130 | XFillRectangle(dpy, (P), gc, 0, 0, width*2, height*2); \ |
---|
131 | XSetFunction(dpy, gc, GXcopy); \ |
---|
132 | } \ |
---|
133 | } while(0) |
---|
134 | |
---|
135 | FROB(p1); |
---|
136 | FROB(p2); |
---|
137 | if (do_three) |
---|
138 | FROB(p3); |
---|
139 | #undef FROB |
---|
140 | } |
---|
141 | |
---|
142 | XFreeGC(dpy, gc); |
---|
143 | |
---|
144 | if (copy_gc) XFreeGC(dpy, copy_gc); |
---|
145 | gcv.function = (xor ? GXxor : GXor); |
---|
146 | gcv.foreground = 1; |
---|
147 | gcv.background = 0; |
---|
148 | |
---|
149 | copy_gc = XCreateGC (dpy, p0, GCFunction|GCForeground|GCBackground, &gcv); |
---|
150 | |
---|
151 | gcv.foreground = 0; |
---|
152 | if (erase_gc) XFreeGC(dpy, erase_gc); |
---|
153 | erase_gc = XCreateGC (dpy, p0, GCForeground, &gcv); |
---|
154 | |
---|
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); |
---|
159 | |
---|
160 | #define FROB(N,DN,MAX) \ |
---|
161 | N = (MAX/2) + (random() % MAX); \ |
---|
162 | DN = ((1 + (random() % (7*thickness))) * ((random() & 1) ? 1 : -1)) |
---|
163 | |
---|
164 | FROB(x1,dx1,width); |
---|
165 | FROB(x2,dx2,width); |
---|
166 | FROB(x3,dx3,width); |
---|
167 | FROB(y1,dy1,height); |
---|
168 | FROB(y2,dy2,height); |
---|
169 | FROB(y3,dy3,height); |
---|
170 | #undef FROB |
---|
171 | } |
---|
172 | |
---|
173 | |
---|
174 | |
---|
175 | static void |
---|
176 | moire2 (Display *dpy, Window window) |
---|
177 | { |
---|
178 | #define FROB(N,DN,MAX) \ |
---|
179 | N += DN; \ |
---|
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))) |
---|
185 | |
---|
186 | FROB(x1,dx1,width); |
---|
187 | FROB(x2,dx2,width); |
---|
188 | FROB(x3,dx3,width); |
---|
189 | FROB(y1,dy1,height); |
---|
190 | FROB(y2,dy2,height); |
---|
191 | FROB(y3,dy3,height); |
---|
192 | #undef FROB |
---|
193 | |
---|
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); |
---|
197 | if (do_three) |
---|
198 | XCopyArea(dpy, p3, p0, copy_gc, x3, y3, width, height, 0, 0); |
---|
199 | |
---|
200 | #ifdef HAVE_DOUBLE_BUFFER_EXTENSION |
---|
201 | if (back_buf) |
---|
202 | { |
---|
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); |
---|
208 | } |
---|
209 | else |
---|
210 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
211 | XCopyPlane (dpy, p0, window, window_gc, 0, 0, width, height, 0, 0, 1L); |
---|
212 | |
---|
213 | XSync(dpy, False); |
---|
214 | |
---|
215 | #if 0 |
---|
216 | XCopyPlane(dpy, p1, window, window_gc, (width*2)/3, (height*2)/3, |
---|
217 | width/2, height/2, |
---|
218 | 0, height/2, 1L); |
---|
219 | XCopyPlane(dpy, p2, window, window_gc, (width*2)/3, (height*2)/3, |
---|
220 | width/2, height/2, |
---|
221 | width/2, height/2, 1L); |
---|
222 | #endif |
---|
223 | } |
---|
224 | |
---|
225 | |
---|
226 | |
---|
227 | |
---|
228 | char *progclass = "Moire2"; |
---|
229 | |
---|
230 | char *defaults [] = { |
---|
231 | ".background: black", |
---|
232 | ".foreground: white", |
---|
233 | "*delay: 50000", |
---|
234 | "*thickness: 0", |
---|
235 | "*colors: 150", |
---|
236 | "*colorShift: 5", |
---|
237 | |
---|
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. |
---|
243 | */ |
---|
244 | "*useDBE: False", |
---|
245 | #endif /* HAVE_DOUBLE_BUFFER_EXTENSION */ |
---|
246 | |
---|
247 | 0 |
---|
248 | }; |
---|
249 | |
---|
250 | XrmOptionDescRec options [] = { |
---|
251 | { "-delay", ".delay", XrmoptionSepArg, 0 }, |
---|
252 | { "-ncolors", ".colors", XrmoptionSepArg, 0 }, |
---|
253 | { "-thickness", ".thickness", XrmoptionSepArg, 0 }, |
---|
254 | { 0, 0, 0, 0 } |
---|
255 | }; |
---|
256 | |
---|
257 | void |
---|
258 | screenhack (Display *dpy, Window window) |
---|
259 | { |
---|
260 | int delay = get_integer_resource ("delay", "Integer"); |
---|
261 | int color_shift = get_integer_resource ("colorShift", "Integer"); |
---|
262 | int pix = 0; |
---|
263 | Bool flip_a, flip_b; |
---|
264 | |
---|
265 | if (color_shift <= 0) color_shift = 1; |
---|
266 | init_moire2 (dpy, window); |
---|
267 | while (1) |
---|
268 | { |
---|
269 | int iterations = 30 + (random() % 70) + (random() % 70); |
---|
270 | reset_moire2 (dpy, window); |
---|
271 | |
---|
272 | flip_a = mono_p ? False : (random() & 1); |
---|
273 | flip_b = mono_p ? False : (random() & 1); |
---|
274 | |
---|
275 | if (flip_b) |
---|
276 | { |
---|
277 | XSetForeground(dpy, window_gc, bg_pixel); |
---|
278 | XSetBackground(dpy, window_gc, fg_pixel); |
---|
279 | } |
---|
280 | else |
---|
281 | { |
---|
282 | XSetForeground(dpy, window_gc, fg_pixel); |
---|
283 | XSetBackground(dpy, window_gc, bg_pixel); |
---|
284 | } |
---|
285 | |
---|
286 | while (--iterations > 0) |
---|
287 | { |
---|
288 | int i; |
---|
289 | |
---|
290 | if (!mono_p) |
---|
291 | { |
---|
292 | pix++; |
---|
293 | pix = pix % ncolors; |
---|
294 | |
---|
295 | if (flip_a) |
---|
296 | XSetBackground(dpy, window_gc, colors[pix].pixel); |
---|
297 | else |
---|
298 | XSetForeground(dpy, window_gc, colors[pix].pixel); |
---|
299 | } |
---|
300 | |
---|
301 | for (i = 0; i < color_shift; i++) |
---|
302 | { |
---|
303 | moire2 (dpy, window); |
---|
304 | screenhack_handle_events (dpy); |
---|
305 | if (delay) |
---|
306 | usleep(delay); |
---|
307 | } |
---|
308 | } |
---|
309 | } |
---|
310 | } |
---|