1 /* xscreensaver, Copyright (c) 1992-1997 Jamie Zawinski <jwz@netscape.com>
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
14 #include <sys/time.h> /* for gettimeofday() */
17 # include "vms-gtod.h"
26 copy_colormap (Screen *screen, Visual *visual,
27 Colormap cmap, Colormap into_cmap)
30 Display *dpy = DisplayOfScreen (screen);
31 Window window = RootWindowOfScreen (screen);
32 int ncolors = CellsOfScreen (screen);
35 /* If this is a colormap on a mono visual, or one with insanely many
36 color cells, bug out. */
37 if (ncolors <= 2 || ncolors > 4096)
39 /* If this is a non-writable visual, bug out. */
40 if (!has_writable_cells (screen, visual))
44 into_cmap = XCreateColormap (dpy, window, visual, AllocAll);
46 cmap = DefaultColormapOfScreen (screen);
48 colors = (XColor *) calloc(sizeof(XColor), ncolors);
49 for (i = 0; i < ncolors; i++)
51 XQueryColors (dpy, cmap, colors, ncolors);
52 XStoreColors (dpy, into_cmap, colors, ncolors);
59 blacken_colormap (Screen *screen, Colormap cmap)
61 Display *dpy = DisplayOfScreen (screen);
62 int ncolors = CellsOfScreen (screen);
67 colors = (XColor *) calloc(sizeof(XColor), ncolors);
68 for (i = 0; i < ncolors; i++)
70 XStoreColors (dpy, cmap, colors, ncolors);
75 /* The business with `cmaps_per_screen' is to fake out the SGI 8-bit video
76 hardware, which is capable of installing multiple (4) colormaps
77 simultaniously. We have to install multiple copies of the same set of
78 colors in order to fill up all the available slots in the hardware color
79 lookup table, so we install an extra N colormaps per screen to make sure
80 that all screens really go black. */
83 fade_screens (Display *dpy, Colormap *cmaps,
84 int seconds, int ticks,
88 int steps = seconds * ticks;
89 long usecs_per_step = (long)(seconds * 1000000) / (long)steps;
91 int cmaps_per_screen = 5;
92 int nscreens = ScreenCount(dpy);
93 int ncmaps = nscreens * cmaps_per_screen;
94 static Colormap *fade_cmaps = 0;
95 Bool installed = False;
97 XColor *orig_colors, *current_colors, *screen_colors, *orig_screen_colors;
98 struct timeval then, now;
99 #ifdef GETTIMEOFDAY_TWO_ARGS
104 for (i = 0; i < nscreens; i++)
105 total_ncolors += CellsOfScreen (ScreenOfDisplay(dpy, i));
107 orig_colors = (XColor *) calloc(sizeof(XColor), total_ncolors);
108 current_colors = (XColor *) calloc(sizeof(XColor), total_ncolors);
110 /* Get the contents of the colormap we are fading from or to. */
111 screen_colors = orig_colors;
112 for (i = 0; i < nscreens; i++)
114 int ncolors = CellsOfScreen (ScreenOfDisplay (dpy, i));
115 Colormap cmap = (cmaps ? cmaps[i] : 0);
116 if (!cmap) cmap = DefaultColormap(dpy, i);
118 for (j = 0; j < ncolors; j++)
119 screen_colors[j].pixel = j;
120 XQueryColors (dpy, cmap, screen_colors, ncolors);
122 screen_colors += ncolors;
125 memcpy (current_colors, orig_colors, total_ncolors * sizeof (XColor));
128 /* Make the writable colormaps (we keep these around and reuse them.) */
131 fade_cmaps = (Colormap *) calloc(sizeof(Colormap), ncmaps);
132 for (i = 0; i < nscreens; i++)
134 Visual *v = DefaultVisual(dpy, i);
135 Screen *s = ScreenOfDisplay(dpy, i);
136 if (has_writable_cells (s, v))
137 for (j = 0; j < cmaps_per_screen; j++)
138 fade_cmaps[(i * cmaps_per_screen) + j] =
139 XCreateColormap (dpy, RootWindowOfScreen (s), v, AllocAll);
143 #ifdef GETTIMEOFDAY_TWO_ARGS
144 gettimeofday(&then, &tzp);
149 /* Iterate by steps of the animation... */
150 for (i = (out_p ? steps : 0);
151 (out_p ? i > 0 : i < steps);
155 /* For each screen, compute the current value of each color...
157 orig_screen_colors = orig_colors;
158 screen_colors = current_colors;
159 for (j = 0; j < nscreens; j++)
161 int ncolors = CellsOfScreen (ScreenOfDisplay (dpy, j));
162 for (k = 0; k < ncolors; k++)
164 /* This doesn't take into account the relative luminance of the
165 RGB components (0.299, 0.587, and 0.114 at gamma 2.2) but
166 the difference is imperceptible for this application... */
167 screen_colors[k].red = orig_screen_colors[k].red * i / steps;
168 screen_colors[k].green = orig_screen_colors[k].green * i / steps;
169 screen_colors[k].blue = orig_screen_colors[k].blue * i / steps;
171 screen_colors += ncolors;
172 orig_screen_colors += ncolors;
175 /* Put the colors into the maps...
177 screen_colors = current_colors;
178 for (j = 0; j < nscreens; j++)
180 int ncolors = CellsOfScreen (ScreenOfDisplay (dpy, j));
181 for (k = 0; k < cmaps_per_screen; k++)
183 Colormap c = fade_cmaps[j * cmaps_per_screen + k];
185 XStoreColors (dpy, c, screen_colors, ncolors);
187 screen_colors += ncolors;
190 /* Put the maps on the screens...
191 (only need to do this the first time through the loop.)
195 for (j = 0; j < ncmaps; j++)
197 XInstallColormap (dpy, fade_cmaps[j]);
203 /* If there is user activity, bug out. (Bug out on keypresses or
204 mouse presses, but not motion, and not release events. Bugging
205 out on motion made the unfade hack be totally useless, I think.)
207 We put the event back so that the calling code can notice it too.
208 It would be better to not remove it at all, but that's harder
209 because Xlib has such a non-design for this kind of crap, and
210 in this application it doesn't matter if the events end up out
211 of order, so in the grand unix tradition we say "fuck it" and
212 do something that mostly works for the time being.
214 if (XCheckMaskEvent (dpy, (KeyPressMask|ButtonPressMask), &dummy_event))
216 XPutBackEvent (dpy, &dummy_event);
220 #ifdef GETTIMEOFDAY_TWO_ARGS
221 gettimeofday(&now, &tzp);
226 /* If we haven't already used up our alotted time, sleep to avoid
227 changing the colormap too fast. */
229 long diff = (((now.tv_sec - then.tv_sec) * 1000000) +
230 now.tv_usec - then.tv_usec);
231 then.tv_sec = now.tv_sec;
232 then.tv_usec = now.tv_usec;
233 if (usecs_per_step > diff)
234 usleep (usecs_per_step - diff);
240 if (orig_colors) free (orig_colors);
241 if (current_colors) free (current_colors);
243 /* Now put the original maps back, if we want to end up with them.
247 for (i = 0; i < nscreens; i++)
249 Colormap cmap = (cmaps ? cmaps[i] : 0);
250 if (!cmap) cmap = DefaultColormap(dpy, i);
251 XInstallColormap (dpy, cmap);
254 /* We've faded to the default cmaps, so we don't need the black maps
255 on stage any more. (We can't uninstall these maps yet if we've
256 faded to black, because that would lead to flicker between when
257 we uninstalled them and when the caller raised its black window.)
259 for (i = 0; i < ncmaps; i++)
262 XFreeColormap(dpy, fade_cmaps[i]);
272 #include "screenhack.h"
274 char *progclass = "foo";
275 char *defaults [] = {
279 XrmOptionDescRec options [] = {0};
280 int options_size = 0;
295 fprintf(stderr,"out..."); fflush(stderr);
296 fade_screens (dpy, 0, seconds, ticks, True);
297 fprintf(stderr, "done.\n"); fflush(stderr);
299 if (delay) sleep (delay);
301 fprintf(stderr,"in..."); fflush(stderr);
302 fade_screens (dpy, 0, seconds, ticks, False);
303 fprintf(stderr, "done.\n"); fflush(stderr);
305 if (delay) sleep (delay);