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;
62 init_decay (Display *dpy, Window window)
65 XWindowAttributes xgwa;
69 char *s = get_string_resource("mode", "Mode");
70 if (s && !strcmp(s, "shuffle")) mode = SHUFFLE;
71 else if (s && !strcmp(s, "up")) mode = UP;
72 else if (s && !strcmp(s, "left")) mode = LEFT;
73 else if (s && !strcmp(s, "right")) mode = RIGHT;
74 else if (s && !strcmp(s, "down")) mode = DOWN;
75 else if (s && !strcmp(s, "upleft")) mode = UPLEFT;
76 else if (s && !strcmp(s, "downleft")) mode = DOWNLEFT;
77 else if (s && !strcmp(s, "upright")) mode = UPRIGHT;
78 else if (s && !strcmp(s, "downright")) mode = DOWNRIGHT;
79 else if (s && !strcmp(s, "in")) mode = IN;
80 else if (s && !strcmp(s, "out")) mode = OUT;
81 else if (s && !strcmp(s, "melt")) mode = MELT;
82 else if (s && !strcmp(s, "stretch")) mode = STRETCH;
84 if (s && *s && !!strcmp(s, "random"))
85 fprintf(stderr, "%s: unknown mode %s\n", progname, s);
86 mode = random() % (STRETCH+1);
89 delay = get_integer_resource ("delay", "Integer");
91 if (delay < 0) delay = 0;
93 XGetWindowAttributes (dpy, window, &xgwa);
95 gcv.function = GXcopy;
96 gcv.subwindow_mode = IncludeInferiors;
98 if (mode == MELT || mode == STRETCH) {
99 bg = get_pixel_resource ("background", "Background", dpy, xgwa.colormap);
103 gcflags = GCForeground |GCFunction;
104 if (use_subwindow_mode_p(xgwa.screen, window)) /* see grabscreen.c */
105 gcflags |= GCSubwindowMode;
106 gc = XCreateGC (dpy, window, gcflags, &gcv);
111 grab_screen_image (xgwa.screen, window);
113 if (mode == MELT || mode == STRETCH) {
114 /* make sure screen eventually turns background color */
115 XDrawLine(dpy, window, gc, 0, 0, sizex, 0);
117 /* slow down for smoother melting*/
125 * perform one iteration of decay
128 decay1 (Display *dpy, Window window)
130 int left, top, width, height, toleft, totop;
136 static int no_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, D,D,D,D };
137 static int up_bias[] = { L,L,L,L, R,R,R,R, U,U,U,U, U,U,D,D };
138 static int down_bias[] = { L,L,L,L, R,R,R,R, U,U,D,D, D,D,D,D };
139 static int left_bias[] = { L,L,L,L, L,L,R,R, U,U,U,U, D,D,D,D };
140 static int right_bias[] = { L,L,R,R, R,R,R,R, U,U,U,U, D,D,D,D };
142 static int upleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,U, U,D,D,D };
143 static int downleft_bias[] = { L,L,L,L, L,R,R,R, U,U,U,D, D,D,D,D };
144 static int upright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,U, U,D,D,D };
145 static int downright_bias[] = { L,L,L,R, R,R,R,R, U,U,U,D, D,D,D,D };
149 case SHUFFLE: bias = no_bias; break;
150 case UP: bias = up_bias; break;
151 case LEFT: bias = left_bias; break;
152 case RIGHT: bias = right_bias; break;
153 case DOWN: bias = down_bias; break;
154 case UPLEFT: bias = upleft_bias; break;
155 case DOWNLEFT: bias = downleft_bias; break;
156 case UPRIGHT: bias = upright_bias; break;
157 case DOWNRIGHT: bias = downright_bias; break;
158 case IN: bias = no_bias; break;
159 case OUT: bias = no_bias; break;
160 case MELT: bias = no_bias; break;
161 case STRETCH: bias = no_bias; break;
165 #define nrnd(x) (random() % (x))
167 if (mode == MELT || mode == STRETCH) {
168 left = nrnd(sizex/2);
170 width = nrnd( sizex/2 ) + sizex/2 - left;
171 height = nrnd(sizey - top);
177 left = nrnd(sizex - 1);
179 width = nrnd(sizex - left);
180 height = nrnd(sizey - top);
184 if (mode == IN || mode == OUT) {
185 int x = left+(width/2);
186 int y = top+(height/2);
190 if (x > cx && y > cy) bias = upleft_bias;
191 else if (x < cx && y > cy) bias = upright_bias;
192 else if (x < cx && y < cy) bias = downright_bias;
193 else /* (x > cx && y < cy)*/ bias = downleft_bias;
195 if (x > cx && y > cy) bias = downright_bias;
196 else if (x < cx && y > cy) bias = downleft_bias;
197 else if (x < cx && y < cy) bias = upleft_bias;
198 else /* (x > cx && y < cy)*/ bias = upright_bias;
202 switch (bias[random() % (sizeof(no_bias)/sizeof(*no_bias))]) {
203 case L: toleft = left-1; break;
204 case R: toleft = left+1; break;
205 case U: totop = top-1; break;
206 case D: totop = top+1; break;
207 default: abort(); break;
211 if (mode == STRETCH) {
212 XCopyArea (dpy, window, window, gc, 0, sizey-top-2, sizex, top+1,
215 XCopyArea (dpy, window, window, gc, left, top, width, height,
223 char *progclass = "DecayScreen";
225 char *defaults [] = {
226 "*dontClearRoot: True",
228 #ifdef __sgi /* really, HAVE_READ_DISPLAY_EXTENSION */
237 XrmOptionDescRec options [] = {
238 { "-delay", ".delay", XrmoptionSepArg, 0 },
239 { "-mode", ".mode", XrmoptionSepArg, 0 },
244 screenhack (Display *dpy, Window window)
246 init_decay (dpy, window);
249 for (i = 0; i < iterations; i++)
250 decay1 (dpy, window);
252 screenhack_handle_events (dpy);
253 if (delay) usleep (delay);