1 /* xscreensaver, Copyright (c) 1992, 1993, 1994, 1996, 1997
2 * Jamie Zawinski <jwz@jwz.org>
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation. No representations are made about the suitability of this
9 * software for any purpose. It is provided "as is" without express or
15 * Based on slidescreen program from the xscreensaver application and the
16 * decay program for Sun framebuffers. This is the comment from the decay.c
20 * find the screen bitmap for the console and make it "decay" by
21 * randomly shifting random rectangles by one pixelwidth at a time.
24 * rewritten by Natuerlich!
25 * based on a similar "utility" on the Apollo ring at Yale.
29 * Vivek Khera <khera@cs.duke.edu>
32 * Hacked by jwz, 28-Nov-97 (sped up and added new motion directions)
35 * Added "melt" & "stretch" modes 28-Mar-1999
39 #include "screenhack.h"
41 static int sizex, sizey;
45 static int iterations=100;
63 init_decay (Display *dpy, Window window)
66 XWindowAttributes xgwa;
70 char *s = get_string_resource("mode", "Mode");
71 if (s && !strcmp(s, "shuffle")) mode = SHUFFLE;
72 else if (s && !strcmp(s, "up")) mode = UP;
73 else if (s && !strcmp(s, "left")) mode = LEFT;
74 else if (s && !strcmp(s, "right")) mode = RIGHT;
75 else if (s && !strcmp(s, "down")) mode = DOWN;
76 else if (s && !strcmp(s, "upleft")) mode = UPLEFT;
77 else if (s && !strcmp(s, "downleft")) mode = DOWNLEFT;
78 else if (s && !strcmp(s, "upright")) mode = UPRIGHT;
79 else if (s && !strcmp(s, "downright")) mode = DOWNRIGHT;
80 else if (s && !strcmp(s, "in")) mode = IN;
81 else if (s && !strcmp(s, "out")) mode = OUT;
82 else if (s && !strcmp(s, "melt")) mode = MELT;
83 else if (s && !strcmp(s, "stretch")) mode = STRETCH;
84 else if (s && !strcmp(s, "fuzz")) mode = FUZZ;
86 if (s && *s && !!strcmp(s, "random"))
87 fprintf(stderr, "%s: unknown mode %s\n", progname, s);
88 mode = random() % (FUZZ+1);
91 delay = get_integer_resource ("delay", "Integer");
93 if (delay < 0) delay = 0;
95 XGetWindowAttributes (dpy, window, &xgwa);
97 gcv.function = GXcopy;
98 gcv.subwindow_mode = IncludeInferiors;
100 if (mode == MELT || mode == STRETCH) {
101 bg = get_pixel_resource ("background", "Background", dpy, xgwa.colormap);
105 gcflags = GCForeground |GCFunction;
106 if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
107 gcflags |= GCSubwindowMode;
108 gc = XCreateGC (dpy, window, gcflags, &gcv);
113 grab_screen_image (xgwa.screen, window);
115 if (mode == MELT || mode == STRETCH) {
116 /* make sure screen eventually turns background color */
117 XDrawLine(dpy, window, gc, 0, 0, sizex, 0);
119 /* slow down for smoother melting*/
127 * perform one iteration of decay
130 decay1 (Display *dpy, Window window)
132 int left, top, width, height, toleft, totop;
138 static int no_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D };
139 static int up_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D };
140 static int down_bias[] = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D };
141 static int left_bias[] = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D };
142 static int right_bias[] = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D };
144 static int upleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D };
145 static int downleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D };
146 static int upright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D };
147 static int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D };
151 case SHUFFLE: bias = no_bias; break;
152 case UP: bias = up_bias; break;
153 case LEFT: bias = left_bias; break;
154 case RIGHT: bias = right_bias; break;
155 case DOWN: bias = down_bias; break;
156 case UPLEFT: bias = upleft_bias; break;
157 case DOWNLEFT: bias = downleft_bias; break;
158 case UPRIGHT: bias = upright_bias; break;
159 case DOWNRIGHT: bias = downright_bias; break;
160 case IN: bias = no_bias; break;
161 case OUT: bias = no_bias; break;
162 case MELT: bias = no_bias; break;
163 case STRETCH: bias = no_bias; break;
164 case FUZZ: bias = no_bias; break;
168 #define nrnd(x) (random() % (x))
170 if (mode == MELT || mode == STRETCH) {
171 left = nrnd(sizex/2);
173 width = nrnd( sizex/2 ) + sizex/2 - left;
174 height = nrnd(sizey - top);
178 } else if (mode == FUZZ) { /* By Vince Levey <vincel@vincel.org>;
179 inspired by the "melt" mode of the
180 "scrhack" IrisGL program by Paul Haeberli
182 static int toggle = 0;
184 left = nrnd(sizex - 1);
185 top = nrnd(sizey - 1);
191 toleft = nrnd(sizex - 1);
209 totop = nrnd(sizey - 1);
226 left = nrnd(sizex - 1);
228 width = nrnd(sizex - left);
229 height = nrnd(sizey - top);
233 if (mode == IN || mode == OUT) {
234 int x = left+(width/2);
235 int y = top+(height/2);
239 if (x > cx && y > cy) bias = upleft_bias;
240 else if (x < cx && y > cy) bias = upright_bias;
241 else if (x < cx && y < cy) bias = downright_bias;
242 else /* (x > cx && y < cy)*/ bias = downleft_bias;
244 if (x > cx && y > cy) bias = downright_bias;
245 else if (x < cx && y > cy) bias = downleft_bias;
246 else if (x < cx && y < cy) bias = upleft_bias;
247 else /* (x > cx && y < cy)*/ bias = upright_bias;
251 switch (bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) {
252 case L: toleft = left-1; break;
253 case R: toleft = left+1; break;
254 case U: totop = top-1; break;
255 case D: totop = top+1; break;
256 default: abort(); break;
260 if (mode == STRETCH) {
261 XCopyArea (dpy, window, window, gc, 0, sizey-top-2, sizex, top+1,
264 XCopyArea (dpy, window, window, gc, left, top, width, height,
272 char *progclass = "DecayScreen";
274 char *defaults [] = {
275 "*dontClearRoot: True",
277 #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
286 XrmOptionDescRec options [] = {
287 { "-delay", ".delay", XrmoptionSepArg, 0 },
288 { "-mode", ".mode", XrmoptionSepArg, 0 },
293 screenhack (Display *dpy, Window window)
295 init_decay (dpy, window);
298 for (i = 0; i < iterations; i++)
299 decay1 (dpy, window);
301 screenhack_handle_events (dpy);
302 if (delay) usleep (delay);