ftp://ftp.uni-heidelberg.de/pub/X11/contrib/applications/xscreensaver-1.27.tar.Z
[xscreensaver] / utils / fade.c
1 /* xscreensaver, Copyright (c) 1992-1996 Jamie Zawinski <jwz@netscape.com>
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 #if __STDC__
13 # include <stdlib.h>
14 #endif
15
16 #include <stdio.h>
17 #include <X11/Xlib.h>
18 #include <X11/Xos.h>
19
20 #if __STDC__
21 # define P(x)x
22 #else
23 # define P(x)()
24 #endif
25
26 extern int get_visual_class P((Display *, Visual *));
27 extern void screenhack_usleep P((unsigned long));
28 #define usleep screenhack_usleep
29
30 #define MAX_COLORS 4096
31 static XColor orig_colors [MAX_COLORS];
32 static XColor current_colors [MAX_COLORS];
33 static int ncolors;
34
35 Colormap
36 copy_colormap (dpy, cmap, into_cmap)
37      Display *dpy;
38      Colormap cmap, into_cmap;
39 {
40   int i;
41   Screen *screen = DefaultScreenOfDisplay (dpy);
42   Visual *visual = DefaultVisualOfScreen (screen);
43   Window window = RootWindowOfScreen (screen);
44   int vclass = get_visual_class (dpy, visual);
45
46   ncolors = CellsOfScreen (screen);
47
48   /* If this is a colormap on a mono visual, or one with insanely many
49      color cells, bug out. */
50   if (ncolors <= 2 || ncolors > MAX_COLORS)
51     return 0;
52   /* If this is a non-writable visual, bug out. */
53   if (vclass == StaticGray || vclass == StaticColor || vclass == TrueColor)
54     return 0;
55
56   if (! into_cmap)
57     into_cmap = XCreateColormap (dpy, window, visual, AllocAll);
58   if (! cmap)
59     cmap = DefaultColormap (dpy, DefaultScreen (dpy));
60   for (i = 0; i < ncolors; i++)
61     orig_colors [i].pixel = i;
62   XQueryColors (dpy, cmap, orig_colors, ncolors);
63   XStoreColors (dpy, into_cmap, orig_colors, ncolors);
64   return into_cmap;
65 }
66
67 void
68 blacken_colormap (dpy, cmap)
69      Display *dpy;
70      Colormap cmap;
71 {
72   int i;
73   for (i = 0; i < ncolors; i++)
74     {
75       current_colors [i].pixel = i;
76       current_colors [i].red = current_colors [i].green =
77         current_colors [i].blue = 0;
78     }
79   XStoreColors (dpy, cmap, current_colors, ncolors);
80 }
81
82
83 /* The business with `install_p' and `extra_cmaps' is to fake out the SGI
84    8-bit video hardware, which is capable of installing multiple (4) colormaps
85    simultaniously.  We have to install multiple copies of the same set of
86    colors in order to fill up all the available slots in the hardware color
87    lookup table.
88  */
89
90 void
91 fade_colormap (dpy, cmap, cmap2, seconds, ticks, out_p, install_p)
92      Display *dpy;
93      Colormap cmap, cmap2;
94      int seconds, ticks;
95      Bool out_p;
96      Bool install_p;
97 {
98   int i;
99   int steps = seconds * ticks;
100   XEvent dummy_event;
101
102   Screen *screen = DefaultScreenOfDisplay (dpy);
103   Visual *visual = DefaultVisualOfScreen (screen);
104   Window window = RootWindowOfScreen (screen);
105   static Colormap extra_cmaps[4] = { 0, };
106   int n_extra_cmaps = sizeof(extra_cmaps)/sizeof(*extra_cmaps);
107
108   if (! cmap2)
109     return;
110
111   for (i = 0; i < ncolors; i++)
112     orig_colors [i].pixel = i;
113   XQueryColors (dpy, cmap, orig_colors, ncolors);
114   memcpy (current_colors, orig_colors, ncolors * sizeof (XColor));
115
116   if (install_p)
117     for (i=0; i < n_extra_cmaps; i++)
118       if (!extra_cmaps[i])
119         extra_cmaps[i] = XCreateColormap (dpy, window, visual, AllocAll);
120
121   for (i = (out_p ? steps : 0);
122        (out_p ? i > 0 : i < steps);
123        (out_p ? i-- : i++))
124     {
125       int j;
126       for (j = 0; j < ncolors; j++)
127         {
128           current_colors[j].red   = orig_colors[j].red   * i / steps;
129           current_colors[j].green = orig_colors[j].green * i / steps;
130           current_colors[j].blue  = orig_colors[j].blue  * i / steps;
131         }
132       XStoreColors (dpy, cmap2, current_colors, ncolors);
133
134       if (install_p)
135         {
136           for (j=0; j < n_extra_cmaps; j++)
137             if (extra_cmaps[j])
138               XStoreColors (dpy, extra_cmaps[j], current_colors, ncolors);
139
140           for (j=0; j < n_extra_cmaps; j++)
141             if (extra_cmaps[j])
142               XInstallColormap (dpy, extra_cmaps[j]);
143           XInstallColormap (dpy, cmap2);
144         }
145
146       XSync (dpy, False);
147
148       /* If there is user activity, bug out.
149          We put the event back so that the calling code can notice it too.
150          It would be better to not remove it at all, but that's harder
151          because Xlib has such a non-design for this kind of crap, and
152          in this application it doesn't matter if the events end up out
153          of order, so in the grand unix tradition we say "fuck it" and
154          do something that mostly works for the time being.
155        */
156       if (XCheckMaskEvent (dpy, (KeyPressMask | KeyReleaseMask |
157                                  ButtonPressMask | ButtonReleaseMask |
158                                  PointerMotionMask),
159                            &dummy_event))
160         {
161           XPutBackEvent (dpy, &dummy_event);
162           goto DONE;
163         }
164
165       usleep (1000000 / (ticks * 2)); /* the 2 is a hack... */
166     }
167
168 DONE:
169
170   if (install_p)
171     {
172       XInstallColormap (dpy, cmap2);
173 /*      for (i=0; i < n_extra_cmaps; i++)
174         if (extra_cmaps[i])
175           XFreeColormap (dpy, extra_cmaps[i]);
176  */
177     }
178 }
179
180 \f
181 #if 0
182 #include "../hacks/screenhack.h"
183 char *progclass = "foo";
184 char *defaults [] = {
185   0
186 };
187
188 XrmOptionDescRec options [] = {0};
189 int options_size = 0;
190
191 void
192 screenhack (dpy, w)
193      Display *dpy;
194      Window w;
195 {
196   Colormap cmap = DefaultColormap (dpy, DefaultScreen (dpy));
197   Colormap cmap2 = copy_colormap (dpy, cmap, 0);
198
199   int seconds = 1;
200   int ticks = 30 * seconds;
201   int delay = 1;
202
203   XSynchronize (dpy, True);
204
205   while (1)
206     {
207       XSync (dpy, False);
208 /*      XGrabServer (dpy); */
209       fprintf(stderr,"out..."); fflush(stderr);
210       XInstallColormap (dpy, cmap2);
211       fade_colormap (dpy, cmap, cmap2, seconds, ticks, True, True);
212       fprintf(stderr, "done.\n"); fflush(stderr);
213       if (delay) sleep (delay);
214       fprintf(stderr,"in..."); fflush(stderr);
215       fade_colormap (dpy, cmap, cmap2, seconds, ticks, False, True);
216       XInstallColormap (dpy, cmap);
217       fprintf(stderr, "done.\n"); fflush(stderr);
218       XUngrabServer (dpy);
219       XSync (dpy, False);
220       if (delay) sleep (delay);
221     }
222 }
223
224 #endif